00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifdef _WIN32
00020 #include "win32/config.h"
00021 #else
00022 #include "config.h"
00023 #endif
00024
00025
00026
00027
00028 #ifdef HAVE_MMX
00029 #include <mmintrin.h>
00030 #endif
00031
00032 #include <ctype.h>
00033 #ifdef _WIN32
00034 # include "win32/afterbase.h"
00035 #else
00036 # include "afterbase.h"
00037 #endif
00038 #include "asvisual.h"
00039 #include "scanline.h"
00040 #include "blender.h"
00041
00042
00043
00044
00045
00046 CARD32
00047 rgb2value( CARD32 red, CARD32 green, CARD32 blue )
00048 {
00049 if( red > green )
00050 return MAX(red,blue);
00051 return MAX(green, blue);
00052 }
00053
00054 CARD32
00055 rgb2saturation( CARD32 red, CARD32 green, CARD32 blue )
00056 {
00057 register int max_val, min_val ;
00058 if( red > green )
00059 {
00060 max_val = MAX(red,blue);
00061 min_val = MIN(green,blue);
00062 }else
00063 {
00064 max_val = MAX(green, blue) ;
00065 min_val = MIN(red,blue) ;
00066 }
00067 return max_val > 1 ? ((max_val - min_val)<<15)/(max_val>>1) : 0;
00068 }
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098 #define HUE_RED_TO_YELLOW 0
00099 #define HUE_YELLOW_TO_GREEN 1
00100 #define HUE_GREEN_TO_CYAN 2
00101 #define HUE_CYAN_TO_BLUE 3
00102 #define HUE_BLUE_TO_MAGENTA 4
00103 #define HUE_MAGENTA_TO_RED 5
00104
00105 #define HUE16_RED (HUE16_RANGE*HUE_RED_TO_YELLOW)
00106 #define HUE16_YELLOW (HUE16_RANGE*HUE_YELLOW_TO_GREEN)
00107 #define HUE16_GREEN (HUE16_RANGE*HUE_GREEN_TO_CYAN)
00108 #define HUE16_CYAN (HUE16_RANGE*HUE_CYAN_TO_BLUE)
00109 #define HUE16_BLUE (HUE16_RANGE*HUE_BLUE_TO_MAGENTA)
00110 #define HUE16_MAGENTA (HUE16_RANGE*HUE_MAGENTA_TO_RED)
00111
00112 #define MAKE_HUE16(hue,red,green,blue,min_val,max_val,delta) \
00113 do{ if( (red) == (max_val) ){ \
00114 if( (blue) <= (green) ){ \
00115 (hue) = HUE16_RED + (((green) - (blue)) * (HUE16_RANGE)) / (delta) ;\
00116 if( (hue) == 0 ) (hue) = MIN_HUE16 ; \
00117 }else { \
00118 (hue) = HUE16_MAGENTA+ (((red) - (blue)) * (HUE16_RANGE)) / (delta) ; \
00119 if( (hue) == 0 ) (hue) = MAX_HUE16 ; \
00120 } \
00121 }else if( (green) == (max_val) ){ \
00122 if( (blue) >= (red) ) \
00123 (hue) = HUE16_GREEN + (((blue)-(red) ) * (HUE16_RANGE)) / (delta) ; \
00124 else \
00125 (hue) = HUE16_YELLOW + (((green)-(red)) * (HUE16_RANGE)) / (delta) ; \
00126 }else if( (red) >= (green) ) \
00127 (hue) = HUE16_BLUE + (((red) -(green))* (HUE16_RANGE)) / (delta) ; \
00128 else \
00129 (hue) = HUE16_CYAN + (((blue)-(green))* (HUE16_RANGE)) / (delta) ; \
00130 }while(0)
00131 #define INTERPRET_HUE16(hue,delta,max_val,red,green,blue) \
00132 do{ int range = (hue)/HUE16_RANGE ; \
00133 int min_val = (max_val) - (delta); \
00134 int mid_val = ((hue) - HUE16_RANGE*range)*(delta) / HUE16_RANGE ; \
00135 switch( range ) { \
00136 case HUE_RED_TO_YELLOW : \
00137 (red) = (max_val); (green)=mid_val+(min_val); (blue) = (min_val); break; \
00138 case HUE_YELLOW_TO_GREEN : \
00139 (green) = (max_val); (red) =(max_val)-mid_val; (blue) = (min_val); break; \
00140 case HUE_GREEN_TO_CYAN : \
00141 (green) = (max_val); (blue)= mid_val+(min_val); (red) = (min_val); break; \
00142 case HUE_CYAN_TO_BLUE : \
00143 (blue) = (max_val); (green)=(max_val)-mid_val; (red) = (min_val); break; \
00144 case HUE_BLUE_TO_MAGENTA : \
00145 (blue) = (max_val); (red) = mid_val+(min_val);(green)= (min_val); break; \
00146 case HUE_MAGENTA_TO_RED : \
00147 (red) = (max_val); (blue) = (max_val)-mid_val;(green)= (min_val); break; \
00148 } \
00149 }while(0)
00150
00151
00152 int normalize_degrees_val( int degrees )
00153 {
00154 while ( degrees < 0 ) degrees += 360 ;
00155 while ( degrees >= 360 ) degrees -= 360 ;
00156 return degrees;
00157 }
00158
00159 CARD32
00160 degrees2hue16( int degrees )
00161 {
00162 CARD32 hue = 0 ;
00163
00164 while ( degrees < 0 ) degrees += 360 ;
00165 while ( degrees >= 360 ) degrees -= 360 ;
00166
00167 hue = degrees * HUE16_RANGE / 60 ;
00168 return (hue==0)?MIN_HUE16:hue ;
00169 }
00170
00171 int
00172 hue162degrees( CARD32 hue )
00173 {
00174 if( hue < MIN_HUE16 || hue > MAX_HUE16 )
00175 return -1 ;
00176
00177 return (hue*60)/HUE16_RANGE ;
00178 }
00179
00180 CARD32
00181 rgb2hue( CARD32 red, CARD32 green, CARD32 blue )
00182 {
00183 int max_val, min_val, hue = 0 ;
00184 if( red > green )
00185 {
00186 max_val = MAX(red,blue);
00187 min_val = MIN(green,blue);
00188 }else
00189 {
00190 max_val = MAX(green,blue);
00191 min_val = MIN(red,blue);
00192 }
00193 if( max_val != min_val)
00194 {
00195 int delta = max_val-min_val ;
00196 MAKE_HUE16(hue,(int)red,(int)green,(int)blue,min_val,max_val,delta);
00197 }
00198 return hue;
00199 }
00200
00201 CARD32
00202 rgb2hsv( CARD32 red, CARD32 green, CARD32 blue, CARD32 *saturation, CARD32 *value )
00203 {
00204 int max_val, min_val, hue = 0 ;
00205 if( red > green )
00206 {
00207 max_val = MAX(red,blue);
00208 min_val = MIN(green,blue);
00209 }else
00210 {
00211 max_val = MAX(green,blue);
00212 min_val = MIN(red,blue);
00213 }
00214 *value = max_val ;
00215 if( max_val != min_val)
00216 {
00217 int delta = max_val-min_val ;
00218 *saturation = (max_val>1)?(delta<<15)/(max_val>>1): 0;
00219 MAKE_HUE16(hue,(int)red,(int)green,(int)blue,min_val,max_val,delta);
00220 }else
00221 *saturation = 0 ;
00222 return hue;
00223 }
00224
00225 void
00226 hsv2rgb (CARD32 hue, CARD32 saturation, CARD32 value, CARD32 *red, CARD32 *green, CARD32 *blue)
00227 {
00228 if (saturation == 0 || hue == 0 )
00229 {
00230 *blue = *green = *red = value;
00231 }else
00232 {
00233 int delta = ((saturation*(value>>1))>>15) ;
00234 INTERPRET_HUE16(hue,delta,value,*red,*green,*blue);
00235 }
00236 }
00237
00238 CARD32
00239 rgb2luminance (CARD32 red, CARD32 green, CARD32 blue )
00240 {
00241 int max_val, min_val;
00242 if( red > green )
00243 {
00244 max_val = MAX(red,blue);
00245 min_val = MIN(green,blue);
00246 }else
00247 {
00248 max_val = MAX(green,blue);
00249 min_val = MIN(red,blue);
00250 }
00251 return (max_val+min_val)>>1;
00252 }
00253
00254 CARD32
00255 rgb2hls (CARD32 red, CARD32 green, CARD32 blue, CARD32 *luminance, CARD32 *saturation )
00256 {
00257 int max_val, min_val, hue = 0 ;
00258 if( red > green )
00259 {
00260 max_val = MAX(red,blue);
00261 min_val = MIN(green,blue);
00262 }else
00263 {
00264 max_val = MAX(green,blue);
00265 min_val = MIN(red,blue);
00266 }
00267 *luminance = (max_val+min_val)>>1;
00268
00269 if( max_val != min_val )
00270 {
00271 int delta = max_val-min_val ;
00272 if( *luminance == 0 ) ++(*luminance);
00273 else if( *luminance == 0x0000FFFF ) --(*luminance);
00274 *saturation = (*luminance < 0x00008000 )?
00275 (delta<<15)/ *luminance :
00276 (delta<<15)/ (0x0000FFFF - *luminance);
00277 MAKE_HUE16(hue,(int)red,(int)green,(int)blue,min_val,max_val,delta);
00278 }else
00279 *saturation = 0 ;
00280 return hue;
00281 }
00282
00283 void
00284 hls2rgb (CARD32 hue, CARD32 luminance, CARD32 saturation, CARD32 *red, CARD32 *green, CARD32 *blue)
00285 {
00286 if (saturation == 0)
00287 {
00288 *blue = *green = *red = luminance;
00289 }else
00290 {
00291 int delta = ( luminance < 0x00008000 )?
00292 (saturation*luminance)>>15 :
00293 (saturation*(0x0000FFFF-luminance))>>15 ;
00294 int max_val = delta+(((luminance<<1)-delta)>>1) ;
00295
00296 INTERPRET_HUE16(hue,delta,max_val,*red,*green,*blue);
00297 }
00298 }
00299
00300
00301
00302
00303
00304 typedef struct merge_scanlines_func_desc {
00305 char *name ;
00306 int name_len ;
00307 merge_scanlines_func func;
00308 char *short_desc;
00309 }merge_scanlines_func_desc;
00310
00311 merge_scanlines_func_desc std_merge_scanlines_func_list[] =
00312 {
00313 { "add", 3, add_scanlines, "color addition with saturation" },
00314 { "alphablend", 10, alphablend_scanlines, "alpha-blending" },
00315 { "allanon", 7, allanon_scanlines, "color values averaging" },
00316 { "colorize", 8, colorize_scanlines, "hue and saturate bottom image same as top image" },
00317 { "darken", 6, darken_scanlines, "use lowest color value from both images" },
00318 { "diff", 4, diff_scanlines, "use absolute value of the color difference between two images" },
00319 { "dissipate", 9, dissipate_scanlines, "randomly alpha-blend images"},
00320 { "hue", 3, hue_scanlines, "hue bottom image same as top image" },
00321 { "lighten", 7, lighten_scanlines, "use highest color value from both images" },
00322 { "overlay", 7, overlay_scanlines, "some wierd image overlaying(see GIMP)" },
00323 { "saturate", 8, saturate_scanlines, "saturate bottom image same as top image"},
00324 { "screen", 6, screen_scanlines, "another wierd image overlaying(see GIMP)" },
00325 { "sub", 3, sub_scanlines, "color substraction with saturation" },
00326 { "tint", 4, tint_scanlines, "tinting image with image" },
00327 { "value", 5, value_scanlines, "value bottom image same as top image" },
00328 { NULL, 0, NULL }
00329 };
00330
00331 merge_scanlines_func
00332 blend_scanlines_name2func( const char *name )
00333 {
00334 register int i = 0;
00335
00336 if( name == NULL )
00337 return NULL ;
00338 while( isspace((int)*name) ) ++name;
00339 do
00340 {
00341 if( name[0] == std_merge_scanlines_func_list[i].name[0] )
00342 if( mystrncasecmp( name, std_merge_scanlines_func_list[i].name,
00343 std_merge_scanlines_func_list[i].name_len ) == 0 )
00344 return std_merge_scanlines_func_list[i].func ;
00345
00346 }while( std_merge_scanlines_func_list[++i].name != NULL );
00347
00348 return NULL ;
00349
00350 }
00351
00352 void
00353 list_scanline_merging(FILE* stream, const char *format)
00354 {
00355 int i = 0 ;
00356 do
00357 {
00358 fprintf( stream, format,
00359 std_merge_scanlines_func_list[i].name,
00360 std_merge_scanlines_func_list[i].short_desc );
00361 }while( std_merge_scanlines_func_list[++i].name != NULL );
00362 }
00363
00364 #define BLEND_SCANLINES_HEADER \
00365 register int i = -1, max_i = bottom->width ; \
00366 register CARD32 *ta = top->alpha, *tr = top->red, *tg = top->green, *tb = top->blue; \
00367 register CARD32 *ba = bottom->alpha, *br = bottom->red, *bg = bottom->green, *bb = bottom->blue; \
00368 if( offset < 0 ){ \
00369 offset = -offset ; \
00370 ta += offset ; tr += offset ; tg += offset ; tb += offset ; \
00371 if( (int)top->width-offset < max_i ) max_i = (int)(top->width)-offset ; \
00372 }else{ \
00373 if( offset > 0 ){ \
00374 ba += offset ; br += offset ; bg += offset ; bb += offset ; \
00375 max_i -= offset ; } \
00376 if( (int)(top->width) < max_i ) max_i = top->width ; \
00377 }
00378
00379
00380
00381 void
00382 alphablend_scanlines( ASScanline *bottom, ASScanline *top, int offset )
00383 {
00384 BLEND_SCANLINES_HEADER
00385 while( ++i < max_i )
00386 {
00387 int a = ta[i] ;
00388 int ca ;
00389
00390 if( a >= 0x0000FF00 )
00391 {
00392 br[i] = tr[i] ;
00393 bg[i] = tg[i] ;
00394 bb[i] = tb[i] ;
00395 ba[i] = 0x0000FF00;
00396 }else if( a > 0x000000FF )
00397 {
00398 a = (a>>8) ;
00399 ca = 255-a;
00400 #if 0
00401
00402
00403
00404
00405 __m64 va = _mm_set_pi16 (ca, a, ca, a);
00406 __m64 vd = _mm_set_pi16 (br[i],tr[i],ba[i],ta[i]);
00407
00408
00409 vd = _mm_srli_pi16( vd, 8 );
00410 vd = _mm_madd_pi16( va, vd );
00411 ba[i] = _mm_cvtsi64_si32( vd );
00412 vd = _mm_srli_si64( vd, 32 );
00413 br[i] = _mm_cvtsi64_si32( vd );
00414
00415 vd = _mm_set_pi16 (bb[i],tb[i],bg[i],tg[i]);
00416 vd = _mm_srli_pi16( vd, 8 );
00417 vd = _mm_madd_pi16( va, vd );
00418 bg[i] = _mm_cvtsi64_si32( vd );
00419 vd = _mm_srli_si64( vd, 32 );
00420 bb[i] = _mm_cvtsi64_si32( vd );
00421 _mm_empty();
00422 #else
00423 ba[i] = ((ba[i]*ca)>>8)+ta[i] ;
00424 br[i] = (br[i]*ca+tr[i]*a)>>8 ;
00425 bg[i] = (bg[i]*ca+tg[i]*a)>>8 ;
00426 bb[i] = (bb[i]*ca+tb[i]*a)>>8 ;
00427 #endif
00428 }
00429 }
00430
00431
00432 }
00433
00434 void
00435 allanon_scanlines( ASScanline *bottom, ASScanline *top, int offset )
00436 {
00437 BLEND_SCANLINES_HEADER
00438 while( ++i < max_i )
00439 {
00440 if( ta[i] != 0 )
00441 {
00442 br[i] = (br[i]+tr[i])>>1 ;
00443 bg[i] = (bg[i]+tg[i])>>1 ;
00444 bb[i] = (bb[i]+tb[i])>>1 ;
00445 ba[i] = (ba[i]+ta[i])>>1 ;
00446 }
00447 }
00448 }
00449
00450 void
00451 tint_scanlines( ASScanline *bottom, ASScanline *top, int offset )
00452 {
00453 BLEND_SCANLINES_HEADER
00454 while( ++i < max_i )
00455 {
00456 if( ta[i] != 0 )
00457 {
00458 br[i] = (br[i]*(tr[i]>>1))>>15 ;
00459 bg[i] = (bg[i]*(tg[i]>>1))>>15 ;
00460 bb[i] = (bb[i]*(tb[i]>>1))>>15 ;
00461 }
00462 }
00463 }
00464
00465 void
00466 add_scanlines( ASScanline *bottom, ASScanline *top, int offset )
00467 {
00468 BLEND_SCANLINES_HEADER
00469 while( ++i < max_i )
00470 if( ta[i] )
00471 {
00472 if( ta[i] > ba[i] )
00473 ba[i] = ta[i] ;
00474 br[i] = (br[i]+tr[i]) ;
00475 if( br[i] > 0x0000FFFF )
00476 br[i] = 0x0000FFFF ;
00477 bg[i] = (bg[i]+tg[i]) ;
00478 if( bg[i] > 0x0000FFFF )
00479 bg[i] = 0x0000FFFF ;
00480 bb[i] = (bb[i]+tb[i]) ;
00481 if( bb[i] > 0x0000FFFF )
00482 bb[i] = 0x0000FFFF ;
00483 ba[i] = (ba[i]+ta[i]) ;
00484 if( ba[i] > 0x0000FFFF )
00485 ba[i] = 0x0000FFFF ;
00486 }
00487 }
00488
00489 void
00490 sub_scanlines( ASScanline *bottom, ASScanline *top, int offset )
00491 {
00492 BLEND_SCANLINES_HEADER
00493 while( ++i < max_i )
00494 if( ta[i] )
00495 {
00496 int res ;
00497 if( ta[i] > ba[i] )
00498 ba[i] = ta[i] ;
00499 res = (int)br[i] - (int)tr[i] ;
00500 br[i] = res < 0 ? 0: res ;
00501 res = (int)bg[i] - (int)tg[i] ;
00502 bg[i] = res < 0 ? 0: res ;
00503 res = (int)bb[i] - (int)tb[i] ;
00504 bb[i] = res < 0 ? 0: res ;
00505 }
00506 }
00507
00508 void
00509 diff_scanlines( ASScanline *bottom, ASScanline *top, int offset )
00510 {
00511 BLEND_SCANLINES_HEADER
00512 while( ++i < max_i )
00513 {
00514 if( ta[i] )
00515 {
00516 int res = (int)br[i] - (int)tr[i] ;
00517 br[i] = res < 0 ? -res: res ;
00518 res = (int)bg[i] - (int)tg[i] ;
00519 bg[i] = res < 0 ? -res: res ;
00520 res = (int)bb[i] - (int)tb[i] ;
00521 bb[i] = res < 0 ? -res: res ;
00522
00523 if( ta[i] > ba[i] )
00524 ba[i] = ta[i] ;
00525 }
00526 }
00527 }
00528
00529 void
00530 darken_scanlines( ASScanline *bottom, ASScanline *top, int offset )
00531 {
00532 BLEND_SCANLINES_HEADER
00533 while( ++i < max_i )
00534 if( ta[i] )
00535 {
00536 if( ta[i] < ba[i] )
00537 ba[i] = ta[i] ;
00538 if( tr[i] < br[i] )
00539 br[i] = tr[i];
00540 if( tg[i] < bg[i] )
00541 bg[i] = tg[i];
00542 if( tb[i] < bb[i] )
00543 bb[i] = tb[i];
00544 }
00545 }
00546
00547 void
00548 lighten_scanlines( ASScanline *bottom, ASScanline *top, int offset )
00549 {
00550 BLEND_SCANLINES_HEADER
00551 while( ++i < max_i )
00552 if( ta[i] )
00553 {
00554 if( ta[i] > ba[i] )
00555 ba[i] = ta[i] ;
00556 if( tr[i] > br[i] )
00557 br[i] = tr[i];
00558 if( tg[i] > bg[i] )
00559 bg[i] = tg[i];
00560 if( tb[i] > bb[i] )
00561 bb[i] = tb[i];
00562 }
00563 }
00564
00565 void
00566 screen_scanlines( ASScanline *bottom, ASScanline *top, int offset )
00567 {
00568 BLEND_SCANLINES_HEADER
00569 #define DO_SCREEN_VALUE(b,t) \
00570 res1 = 0x0000FFFF - (int)b[i] ; res2 = 0x0000FFFF - (int)t[i] ;\
00571 res1 = 0x0000FFFF - ((res1*res2)>>16); b[i] = res1 < 0 ? 0 : res1
00572
00573 while( ++i < max_i )
00574 if( ta[i] )
00575 {
00576 int res1 ;
00577 int res2 ;
00578
00579 DO_SCREEN_VALUE(br,tr);
00580 DO_SCREEN_VALUE(bg,tg);
00581 DO_SCREEN_VALUE(bb,tb);
00582
00583 if( ta[i] > ba[i] )
00584 ba[i] = ta[i] ;
00585 }
00586 }
00587
00588 void
00589 overlay_scanlines( ASScanline *bottom, ASScanline *top, int offset )
00590 {
00591 BLEND_SCANLINES_HEADER
00592 #define DO_OVERLAY_VALUE(b,t) \
00593 tmp_screen = 0x0000FFFF - (((0x0000FFFF - (int)b[i]) * (0x0000FFFF - (int)t[i])) >> 16); \
00594 tmp_mult = (b[i] * t[i]) >> 16; \
00595 res = (b[i] * tmp_screen + (0x0000FFFF - (int)b[i]) * tmp_mult) >> 16; \
00596 b[i] = res < 0 ? 0 : res
00597
00598 while( ++i < max_i )
00599 if( ta[i] )
00600 {
00601 int tmp_screen, tmp_mult, res ;
00602 DO_OVERLAY_VALUE(br,tr);
00603 DO_OVERLAY_VALUE(bg,tg);
00604 DO_OVERLAY_VALUE(bb,tb);
00605 if( ta[i] > ba[i] )
00606 ba[i] = ta[i] ;
00607 }
00608 }
00609
00610 void
00611 hue_scanlines( ASScanline *bottom, ASScanline *top, int offset )
00612 {
00613 BLEND_SCANLINES_HEADER
00614 while( ++i < max_i )
00615 if( ta[i] )
00616 {
00617 CARD32 hue = rgb2hue( tr[i], tg[i], tb[i]);
00618 if( hue > 0 )
00619 {
00620 CARD32 saturation = rgb2saturation( br[i], bg[i], bb[i]);
00621 CARD32 value = rgb2value( br[i], bg[i], bb[i]);;
00622
00623 hsv2rgb(hue, saturation, value, &br[i], &bg[i], &bb[i]);
00624 }
00625 if( ta[i] < ba[i] )
00626 ba[i] = ta[i] ;
00627 }
00628 }
00629
00630 void
00631 saturate_scanlines( ASScanline *bottom, ASScanline *top, int offset )
00632 {
00633 BLEND_SCANLINES_HEADER
00634 while( ++i < max_i )
00635 if( ta[i] )
00636 {
00637 CARD32 saturation, value;
00638 CARD32 hue = rgb2hsv( br[i], bg[i], bb[i], &saturation, &value);
00639
00640 saturation = rgb2saturation( tr[i], tg[i], tb[i]);
00641 hsv2rgb(hue, saturation, value, &br[i], &bg[i], &bb[i]);
00642 if( ta[i] < ba[i] )
00643 ba[i] = ta[i] ;
00644 }
00645 }
00646
00647 void
00648 value_scanlines( ASScanline *bottom, ASScanline *top, int offset )
00649 {
00650 BLEND_SCANLINES_HEADER
00651 while( ++i < max_i )
00652 if( ta[i] )
00653 {
00654 CARD32 saturation, value;
00655 CARD32 hue = rgb2hsv( br[i], bg[i], bb[i], &saturation, &value);
00656
00657 value = rgb2value( tr[i], tg[i], tb[i]);
00658 hsv2rgb(hue, saturation, value, &br[i], &bg[i], &bb[i]);
00659
00660 if( ta[i] < ba[i] )
00661 ba[i] = ta[i] ;
00662 }
00663 }
00664
00665 void
00666 colorize_scanlines( ASScanline *bottom, ASScanline *top, int offset )
00667 {
00668 BLEND_SCANLINES_HEADER
00669
00670 while( ++i < max_i )
00671 if( ta[i] )
00672 {
00673 #if 1
00674 CARD32 luminance, saturation ;
00675 CARD32 hue = rgb2hls( tr[i], tg[i], tb[i], &luminance, &saturation );
00676
00677 luminance = rgb2luminance( br[i], bg[i], bb[i]);
00678 hls2rgb(hue, luminance, saturation, &br[i], &bg[i], &bb[i]);
00679 #else
00680 CARD32 h, l, s, r, g, b;
00681 h = rgb2hls( br[i], bg[i], bb[i], &l, &s );
00682 hls2rgb( h, l, s, &r, &g, &b );
00683 if( r > br[i]+10 || r < br[i] - 10 )
00684 {
00685 fprintf( stderr, "%X.%X.%X -> %X.%X.%X -> %X.%X.%X\n", br[i], bg[i], bb[i], h, l, s, r, g, b );
00686 fprintf( stderr, "%d.%d.%d -> %d.%d.%d -> %d.%d.%d\n", br[i], bg[i], bb[i], h, l, s, r, g, b );
00687 }
00688 #endif
00689 if( ta[i] < ba[i] )
00690 ba[i] = ta[i] ;
00691 }
00692 }
00693
00694 void
00695 dissipate_scanlines( ASScanline *bottom, ASScanline *top, int offset )
00696 {
00697 static CARD32 rnd32_seed = 345824357;
00698 BLEND_SCANLINES_HEADER
00699
00700 #define MAX_MY_RND32 0x00ffffffff
00701 #ifdef WORD64
00702 #define MY_RND32() \
00703 (rnd32_seed = ((1664525L*rnd32_seed)&MAX_MY_RND32)+1013904223L)
00704 #else
00705 #define MY_RND32() \
00706 (rnd32_seed = (1664525L*rnd32_seed)+1013904223L)
00707 #endif
00708
00709
00710 while( ++i < max_i )
00711 {
00712 int a = ta[i] ;
00713 if( a > 0 && (int)MY_RND32() < (a<<15) )
00714 {
00715 ba[i] += a ;
00716 if( ba[i] > 0x0000FFFF )
00717 ba[i] = 0x0000FFFF ;
00718 a = (a>>8) ;
00719 br[i] = (br[i]*(255-a)+tr[i]*a)>>8 ;
00720 bg[i] = (bg[i]*(255-a)+tg[i]*a)>>8 ;
00721 bb[i] = (bb[i]*(255-a)+tb[i]*a)>>8 ;
00722 }
00723 }
00724 }
00725
00726
00727
00728
00729