blender.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2000,2001 Sasha Vasko <sasha at aftercode.net>
00003  *
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Lesser General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 2.1 of the License, or (at your option) any later version.
00008  *
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Lesser General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Lesser General Public
00015  * License along with this library; if not, write to the Free Software
00016  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017  */
00018 
00019 #ifdef _WIN32
00020 #include "win32/config.h"
00021 #else
00022 #include "config.h"
00023 #endif
00024 
00025 /*#define LOCAL_DEBUG*/
00026 /*#define DO_CLOCKING*/
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 /* colorspace conversion functions :                                                                                     */
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 /* Traditionally Hue is represented by 360 degree circle.
00072   For our needs we use 255 degree circle instead.
00073 
00074   Now the circle is separated into 6 segments :
00075   Trad:         Us:                             Color range:    Red:    Green:  Blue:
00076   0-60          0    -42.5              red-yellow      FF-7F   0 -7F   0 -0
00077   60-120    42.5 -85            yellow-green    7F-0    7F-FF   0 -0
00078   120-180   85   -127.5         green-cyan      0 -0    FF-7F   0 -7F
00079   180-240   127.5-170           cyan-blue       0 -0    7F-0    7F-FF
00080   240-300   170  -212.5     blue-magenta    0-7F    0 -0        FF-7F
00081   300-360   212.5-255       magenta-red     7F-FF   0 -0    7F-0
00082 
00083   As seen from above in each segment at least one of the RGB values is 0.
00084   To achieve that we find minimum of R, G and b and substract it from all,
00085   and then multiply values by ratio to bring it into range :
00086 
00087   new_val = ((val - min_val)*0xFEFF)/(max_val-min_val)
00088   (note that we use 16bit values, instead of 8 bit as above)
00089 
00090   WE store hue in 16 bits, so instead of above value of 42.5 per segment
00091   we should use 85<<7 == 0x00002A80 per segment.
00092 
00093   When all the RGB values are the same - then hue is invalid and  = 0;
00094   To distinguish between hue == 0 when color is Red and invalid hue, we
00095   make all valid hues to fit in range 0x0001-0xFF00, with 0x0001 being RED.
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) ){ /* 300 to 60 degrees segment */ \
00114                         if( (blue) <= (green) ){  /* 0-60 degrees segment*/    \
00115                                 (hue) = HUE16_RED    + (((green) - (blue)) * (HUE16_RANGE)) / (delta) ;\
00116                                 if( (hue) == 0 ) (hue) = MIN_HUE16 ; \
00117                         }else {                /* 300-0 degrees segment*/ \
00118                                 (hue) = HUE16_MAGENTA+ (((red)   - (blue)) * (HUE16_RANGE)) / (delta) ; \
00119                                 if( (hue) == 0 ) (hue) = MAX_HUE16 ;                                 \
00120                         }                                                                   \
00121                 }else if( (green) == (max_val) ){ /* 60 to 180 degrees segment */           \
00122                         if( (blue) >= (red) )    /* 120-180 degrees segment*/                   \
00123                                 (hue) = HUE16_GREEN  + (((blue)-(red) ) * (HUE16_RANGE)) / (delta) ;    \
00124                         else                 /* 60-120 degrees segment */                   \
00125                                 (hue) = HUE16_YELLOW + (((green)-(red)) * (HUE16_RANGE)) / (delta) ;    \
00126                 }else if( (red) >= (green) )     /* 240 to 300 degrees segment */           \
00127                         (hue)     = HUE16_BLUE   + (((red) -(green))* (HUE16_RANGE)) / (delta) ;    \
00128                 else                        /* 180 to 240 degrees segment */            \
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 :    /* red was max, then green  */ \
00137                                 (red)   = (max_val); (green)=mid_val+(min_val); (blue) = (min_val); break; \
00138                         case HUE_YELLOW_TO_GREEN :  /* green was max, then red */                      \
00139                                 (green) = (max_val); (red) =(max_val)-mid_val;  (blue) = (min_val); break; \
00140                         case HUE_GREEN_TO_CYAN :    /* green was max, then blue*/                      \
00141                                 (green) = (max_val); (blue)= mid_val+(min_val); (red)  = (min_val); break; \
00142                         case HUE_CYAN_TO_BLUE :     /* blue was max, then green  */                    \
00143                                 (blue)  = (max_val); (green)=(max_val)-mid_val; (red)  = (min_val); break; \
00144                         case HUE_BLUE_TO_MAGENTA :  /* blue was max, then red   */                     \
00145                                 (blue)  = (max_val); (red)  = mid_val+(min_val);(green)= (min_val); break; \
00146                         case HUE_MAGENTA_TO_RED :   /* red was max, then blue */                       \
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                                         /* returns luminance */
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                                         /* returns hue */
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 /* scanline blending                                                                                                     */
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 /*fprintf( stderr, "%4.4x%4.4x%4.4x%4.4x+%4.4x%4.4x%4.4x%4.4x ", ba[i], br[i], bg[i], bb[i], ta[i], tr[i], tg[i], tb[i] );*/
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 /*ndef HAVE_MMX*/
00401 /* MMX implementaion of alpha-blending below turns out to be 
00402    30% slower then the original integer math implementation under it 
00403    I'm probably stupid or something.  
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                         /* b=(b*ca + t*a)>>8 */
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 /*      fputc( '\n', stderr );*/
00432 }
00433 
00434 void    /* this one was first implemented on XImages by allanon :) - mode 131  */
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    /* addition with saturation : */
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    /* substruction with saturation : */
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    /* absolute pixel value difference : */
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    /* darkest of the two makes it in : */
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    /* lightest of the two makes it in : */
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    /* guess what this one does - I could not :) */
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    /* somehow overlays bottom with top : */
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         /* add some randomization here  if (rand < alpha) - combine */
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 /* The end !!!!                                                                                                                                  */
00728 /*********************************************************************************/
00729 

Generated on Tue Jul 5 14:13:27 2011 for ROOT_528-00b_version by  doxygen 1.5.1