00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #undef USE_STUPID_GIMP_WAY_DESTROYING_COLORS
00020 #undef LOCAL_DEBUG
00021 #undef DO_CLOCKING
00022 #undef DEBUG_HSV_ADJUSTMENT
00023 #define USE_64BIT_FPU
00024 #undef NEED_RBITSHIFT_FUNCS
00025
00026 #ifdef _WIN32
00027 #include "win32/config.h"
00028 #else
00029 #include "config.h"
00030 #endif
00031
00032
00033 #ifdef DO_CLOCKING
00034 #if TIME_WITH_SYS_TIME
00035 # include <sys/time.h>
00036 # include <time.h>
00037 #else
00038 # if HAVE_SYS_TIME_H
00039 # include <sys/time.h>
00040 # else
00041 # include <time.h>
00042 # endif
00043 #endif
00044 #endif
00045 #ifdef HAVE_UNISTD_H
00046 #include <unistd.h>
00047 #endif
00048 #ifdef HAVE_STDLIB_H
00049 #include <stdlib.h>
00050 #endif
00051 #ifdef HAVE_STDARG_H
00052 #include <stdarg.h>
00053 #endif
00054 #include <math.h>
00055 #include <string.h>
00056
00057 #ifdef HAVE_MMX
00058 #include <mmintrin.h>
00059 #endif
00060
00061 #ifdef _WIN32
00062 # include "win32/afterbase.h"
00063 #else
00064 # include "afterbase.h"
00065 #endif
00066 #include "asvisual.h"
00067 #include "blender.h"
00068 #include "asimage.h"
00069 #include "imencdec.h"
00070 #include "transform.h"
00071
00072 ASVisual __transform_fake_asv = {0};
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085 #define INTERPOLATE_COLOR1(c) ((c)<<QUANT_ERR_BITS)
00086 #define INTERPOLATE_COLOR2(c1,c2,c3,c4) ((((c2)<<2)+(c2)+((c3)<<2)+(c3)-(c1)-(c4))<<(QUANT_ERR_BITS-3))
00087 #define INTERPOLATE_COLOR2_V(c1,c2,c3,c4) ((((c2)<<2)+(c2)+((c3)<<2)+(c3)-(c1)-(c4))>>3)
00088
00089
00090
00091
00092
00093
00094 #define INTERPOLATE_A_COLOR3(c1,c2,c3,c4) (((((c2)<<2)+(c2)+((c3)<<1)+(c3)-(c1)-(c4))<<QUANT_ERR_BITS)/6)
00095 #define INTERPOLATE_B_COLOR3(c1,c2,c3,c4) (((((c2)<<1)+(c2)+((c3)<<2)+(c3)-(c1)-(c4))<<QUANT_ERR_BITS)/6)
00096 #define INTERPOLATE_A_COLOR3_V(c1,c2,c3,c4) ((((c2)<<2)+(c2)+((c3)<<1)+(c3)-(c1)-(c4))/6)
00097 #define INTERPOLATE_B_COLOR3_V(c1,c2,c3,c4) ((((c2)<<1)+(c2)+((c3)<<2)+(c3)-(c1)-(c4))/6)
00098
00099
00100
00101
00102
00103 #define INTERPOLATION_Cs(c) ((c)<<1)
00104
00105 #define INTERPOLATION_TOTAL_START(c1,c2,c3,c4,S) ((((S)<<1)+1)*(c2)+(c3)-(c1)-(c4))
00106 #define INTERPOLATION_TOTAL_STEP(c2,c3) ((c3<<1)-(c2<<1))
00107 #define INTERPOLATE_N_COLOR(T,S) (((T)<<(QUANT_ERR_BITS-1))/(S))
00108
00109 #define AVERAGE_COLOR1(c) ((c)<<QUANT_ERR_BITS)
00110 #define AVERAGE_COLOR2(c1,c2) (((c1)+(c2))<<(QUANT_ERR_BITS-1))
00111 #define AVERAGE_COLORN(T,N) (((T)<<QUANT_ERR_BITS)/N)
00112
00113 static inline void
00114 enlarge_component12( register CARD32 *src, register CARD32 *dst, int *scales, int len )
00115 {
00116 register int i = 0, k = 0;
00117 register int c1 = src[0], c4;
00118 --len; --len ;
00119 while( i < len )
00120 {
00121 c4 = src[i+2];
00122
00123 dst[k] = INTERPOLATE_COLOR1(src[i]) ;
00124 if( scales[i] == 2 )
00125 {
00126 register int c2 = src[i], c3 = src[i+1] ;
00127 c3 = INTERPOLATE_COLOR2(c1,c2,c3,c4);
00128 dst[++k] = (c3&0xFF000000 )?0:c3;
00129 }
00130 c1 = src[i];
00131 ++k;
00132 ++i;
00133 }
00134
00135
00136 if( scales[i] == 1 )
00137 dst[k] = INTERPOLATE_COLOR1(src[i]);
00138 else
00139 {
00140 register int c2 = src[i], c3 = src[i+1] ;
00141 c2 = INTERPOLATE_COLOR2(c1,c2,c3,c3);
00142 dst[k] = (c2&0xFF000000 )?0:c2;
00143 }
00144 dst[k+1] = INTERPOLATE_COLOR1(src[i+1]);
00145 }
00146
00147 static inline void
00148 enlarge_component23( register CARD32 *src, register CARD32 *dst, int *scales, int len )
00149 {
00150 register int i = 0, k = 0;
00151 register int c1 = src[0], c4 = src[1];
00152 if( scales[0] == 1 )
00153 {
00154 dst[k] = INTERPOLATE_COLOR1(src[0]) ;
00155 ++k;
00156 ++i;
00157 }
00158 --len; --len ;
00159 while( i < len )
00160 {
00161 register int c2 = src[i], c3 = src[i+1] ;
00162 c4 = src[i+2];
00163 dst[k] = INTERPOLATE_COLOR1(c2) ;
00164 if( scales[i] == 2 )
00165 {
00166 c3 = INTERPOLATE_COLOR2(c1,c2,c3,c3);
00167 dst[++k] = (c3&0x7F000000 )?0:c3;
00168 }else
00169 {
00170 dst[++k] = INTERPOLATE_A_COLOR3(c1,c2,c3,c4);
00171 if( dst[k]&0x7F000000 )
00172 dst[k] = 0 ;
00173 c3 = INTERPOLATE_B_COLOR3(c1,c2,c3,c3);
00174 dst[++k] = (c3&0x7F000000 )?0:c3;
00175 }
00176 c1 = c2 ;
00177 ++k;
00178 ++i;
00179 }
00180
00181 {
00182 register int c2 = src[i], c3 = src[i+1] ;
00183 dst[k] = INTERPOLATE_COLOR1(c2) ;
00184 if( scales[i] == 2 )
00185 {
00186 c2 = INTERPOLATE_COLOR2(c1,c2,c3,c3);
00187 dst[k+1] = (c2&0x7F000000 )?0:c2;
00188 }else
00189 {
00190 if( scales[i] == 1 )
00191 --k;
00192 else
00193 {
00194 dst[++k] = INTERPOLATE_A_COLOR3(c1,c2,c3,c3);
00195 if( dst[k]&0x7F000000 )
00196 dst[k] = 0 ;
00197 c2 = INTERPOLATE_B_COLOR3(c1,c2,c3,c3);
00198 dst[k+1] = (c2&0x7F000000 )?0:c2;
00199 }
00200 }
00201 }
00202 dst[k+2] = INTERPOLATE_COLOR1(src[i+1]) ;
00203 }
00204
00205
00206
00207
00208 static inline void
00209 enlarge_component( register CARD32 *src, register CARD32 *dst, int *scales, int len )
00210 {
00211
00212 int i = 0;
00213 int c1 = src[0];
00214 register int T ;
00215 --len ;
00216 if( len < 1 )
00217 {
00218 CARD32 c = INTERPOLATE_COLOR1(c1) ;
00219 for( i = 0 ; i < scales[0] ; ++i )
00220 dst[i] = c;
00221 return;
00222 }
00223 do
00224 {
00225 register short S = scales[i];
00226 register int step = INTERPOLATION_TOTAL_STEP(src[i],src[i+1]);
00227
00228 if( i+1 == len )
00229 T = INTERPOLATION_TOTAL_START(c1,src[i],src[i+1],src[i+1],S);
00230 else
00231 T = INTERPOLATION_TOTAL_START(c1,src[i],src[i+1],src[i+2],S);
00232
00233
00234 if( step )
00235 {
00236 register int n = 0 ;
00237 do
00238 {
00239 dst[n] = (T&0x7F000000)?0:INTERPOLATE_N_COLOR(T,S);
00240 if( ++n >= S ) break;
00241 T = (int)T + (int)step;
00242 }while(1);
00243 dst += n ;
00244 }else
00245 {
00246 register CARD32 c = (T&0x7F000000)?0:INTERPOLATE_N_COLOR(T,S);
00247 while(--S >= 0){ dst[S] = c; }
00248 dst += scales[i] ;
00249 }
00250 c1 = src[i];
00251 }while(++i < len );
00252 *dst = INTERPOLATE_COLOR1(src[i]) ;
00253
00254 }
00255
00256 static inline void
00257 enlarge_component_dumb( register CARD32 *src, register CARD32 *dst, int *scales, int len )
00258 {
00259
00260 int i = 0, k = 0;
00261 do
00262 {
00263 register CARD32 c = INTERPOLATE_COLOR1(src[i]);
00264 int max_k = k+scales[i];
00265 do
00266 {
00267 dst[k] = c ;
00268 }while( ++k < max_k );
00269 }while( ++i < len );
00270 }
00271
00272
00273 static inline void
00274 shrink_component( register CARD32 *src, register CARD32 *dst, int *scales, int len )
00275 {
00276
00277 register int i = -1, k = -1;
00278 while( ++k < len )
00279 {
00280 register int reps = scales[k] ;
00281 register int c1 = src[++i];
00282
00283 if( reps == 1 )
00284 dst[k] = AVERAGE_COLOR1(c1);
00285 else if( reps == 2 )
00286 {
00287 ++i;
00288 dst[k] = AVERAGE_COLOR2(c1,src[i]);
00289 }else
00290 {
00291 reps += i-1;
00292 while( reps > i )
00293 {
00294 ++i ;
00295 c1 += src[i];
00296 }
00297 {
00298 register short S = scales[k];
00299 dst[k] = AVERAGE_COLORN(c1,S);
00300 }
00301 }
00302 }
00303 }
00304 static inline void
00305 shrink_component11( register CARD32 *src, register CARD32 *dst, int *scales, int len )
00306 {
00307 register int i ;
00308 for( i = 0 ; i < len ; ++i )
00309 dst[i] = AVERAGE_COLOR1(src[i]);
00310 }
00311
00312
00313 static inline void
00314 reverse_component( register CARD32 *src, register CARD32 *dst, int *unused, int len )
00315 {
00316 register int i = 0;
00317 src += len-1 ;
00318 do
00319 {
00320 dst[i] = src[-i];
00321 }while(++i < len );
00322 }
00323
00324 static inline void
00325 add_component( CARD32 *src, CARD32 *incr, int *scales, int len )
00326 {
00327 len += len&0x01;
00328 #ifdef HAVE_MMX
00329 #if 1
00330 if( asimage_use_mmx )
00331 {
00332 int i = 0;
00333 __m64 *vdst = (__m64*)&(src[0]);
00334 __m64 *vinc = (__m64*)&(incr[0]);
00335 len = len>>1;
00336 do{
00337 vdst[i] = _mm_add_pi32(vdst[i],vinc[i]);
00338 }while( ++i < len );
00339 _mm_empty();
00340 }else
00341 #else
00342 if( asimage_use_mmx )
00343 {
00344 double *ddst = (double*)&(src[0]);
00345 double *dinc = (double*)&(incr[0]);
00346 len = len>>1;
00347 do{
00348 asm volatile
00349 (
00350 "movq %0, %%mm0 \n\t"
00351 "paddd %1, %%mm0 \n\t"
00352 "movq %%mm0, %0 \n\t"
00353 : "=m" (ddst[i])
00354 : "m" (dinc[i])
00355 );
00356 }while( ++i < len );
00357 }else
00358 #endif
00359 #endif
00360 {
00361 register int c1, c2;
00362 int i = 0;
00363 do{
00364 c1 = (int)src[i] + (int)incr[i] ;
00365 c2 = (int)src[i+1] + (int)incr[i+1] ;
00366 src[i] = c1;
00367 src[i+1] = c2;
00368 i += 2 ;
00369 }while( i < len );
00370 }
00371 }
00372
00373 #ifdef NEED_RBITSHIFT_FUNCS
00374 static inline void
00375 rbitshift_component( register CARD32 *src, register CARD32 *dst, int shift, int len )
00376 {
00377 register int i ;
00378 for( i = 0 ; i < len ; ++i )
00379 dst[i] = src[i]>>shift;
00380 }
00381 #endif
00382
00383 static inline void
00384 start_component_interpolation( CARD32 *c1, CARD32 *c2, CARD32 *c3, CARD32 *c4, register CARD32 *T, register CARD32 *step, int S, int len)
00385 {
00386 register int i;
00387 for( i = 0 ; i < len ; i++ )
00388 {
00389 register int rc2 = c2[i], rc3 = c3[i] ;
00390 T[i] = INTERPOLATION_TOTAL_START(c1[i],rc2,rc3,c4[i],S)/(S<<1);
00391 step[i] = INTERPOLATION_TOTAL_STEP(rc2,rc3)/(S<<1);
00392 }
00393 }
00394
00395 static inline void
00396 component_interpolation_hardcoded( CARD32 *c1, CARD32 *c2, CARD32 *c3, CARD32 *c4, register CARD32 *T, CARD32 *unused, CARD16 kind, int len)
00397 {
00398 register int i;
00399 if( kind == 1 )
00400 {
00401 for( i = 0 ; i < len ; i++ )
00402 {
00403 #if 1
00404
00405
00406 T[i] = (c2[i]+c3[i])>>1 ;
00407 #else
00408 register int minus = c1[i]+c4[i] ;
00409 register int plus = (c2[i]<<1)+c2[i]+(c3[i]<<1)+c3[i];
00410
00411 T[i] = ( (plus>>1) < minus )?(c2[i]+c3[i])>>1 :
00412 (plus-minus)>>2;
00413 #endif
00414 }
00415 }else if( kind == 2 )
00416 {
00417 for( i = 0 ; i < len ; i++ )
00418 {
00419 register int rc1 = c1[i], rc2 = c2[i], rc3 = c3[i] ;
00420 T[i] = INTERPOLATE_A_COLOR3_V(rc1,rc2,rc3,c4[i]);
00421 }
00422 }else
00423 for( i = 0 ; i < len ; i++ )
00424 {
00425 register int rc1 = c1[i], rc2 = c2[i], rc3 = c3[i] ;
00426 T[i] = INTERPOLATE_B_COLOR3_V(rc1,rc2,rc3,c4[i]);
00427 }
00428 }
00429
00430 #ifdef NEED_RBITSHIFT_FUNCS
00431 static inline void
00432 divide_component_mod( register CARD32 *data, CARD16 ratio, int len )
00433 {
00434 register int i ;
00435 for( i = 0 ; i < len ; ++i )
00436 data[i] /= ratio;
00437 }
00438
00439 static inline void
00440 rbitshift_component_mod( register CARD32 *data, int bits, int len )
00441 {
00442 register int i ;
00443 for( i = 0 ; i < len ; ++i )
00444 data[i] = data[i]>>bits;
00445 }
00446 #endif
00447 void
00448 print_component( register CARD32 *data, int nonsense, int len )
00449 {
00450 register int i ;
00451 for( i = 0 ; i < len ; ++i )
00452 fprintf( stderr, " %8.8lX", (long)data[i] );
00453 fprintf( stderr, "\n");
00454 }
00455
00456 static inline void
00457 tint_component_mod( register CARD32 *data, CARD16 ratio, int len )
00458 {
00459 register int i ;
00460 if( ratio == 255 )
00461 for( i = 0 ; i < len ; ++i )
00462 data[i] = data[i]<<8;
00463 else if( ratio == 128 )
00464 for( i = 0 ; i < len ; ++i )
00465 data[i] = data[i]<<7;
00466 else if( ratio == 0 )
00467 for( i = 0 ; i < len ; ++i )
00468 data[i] = 0;
00469 else
00470 for( i = 0 ; i < len ; ++i )
00471 data[i] = data[i]*ratio;
00472 }
00473
00474 static inline void
00475 make_component_gradient16( register CARD32 *data, CARD16 from, CARD16 to, CARD8 seed, int len )
00476 {
00477 register int i ;
00478 long incr = (((long)to<<8)-((long)from<<8))/len ;
00479
00480 if( incr == 0 )
00481 for( i = 0 ; i < len ; ++i )
00482 data[i] = from;
00483 else
00484 {
00485 long curr = from<<8;
00486 curr += ((long)(((CARD32)seed)<<8) > incr)?incr:((CARD32)seed)<<8 ;
00487 for( i = 0 ; i < len ; ++i )
00488 {
00489
00490 data[i] = curr>>8;
00491 curr += ((curr&0x00FF)>>1)+incr ;
00492 }
00493 }
00494 }
00495
00496
00497 static inline void
00498 copytintpad_scanline( ASScanline *src, ASScanline *dst, int offset, ARGB32 tint )
00499 {
00500 register int i ;
00501 CARD32 chan_tint[4], chan_fill[4] ;
00502 int color ;
00503 int copy_width = src->width, dst_offset = 0, src_offset = 0;
00504
00505 if( offset+(int)src->width < 0 || offset > (int)dst->width )
00506 return;
00507 chan_tint[IC_RED] = ARGB32_RED8 (tint)<<1;
00508 chan_tint[IC_GREEN] = ARGB32_GREEN8(tint)<<1;
00509 chan_tint[IC_BLUE] = ARGB32_BLUE8 (tint)<<1;
00510 chan_tint[IC_ALPHA] = ARGB32_ALPHA8(tint)<<1;
00511 chan_fill[IC_RED] = ARGB32_RED8 (dst->back_color)<<dst->shift;
00512 chan_fill[IC_GREEN] = ARGB32_GREEN8(dst->back_color)<<dst->shift;
00513 chan_fill[IC_BLUE] = ARGB32_BLUE8 (dst->back_color)<<dst->shift;
00514 chan_fill[IC_ALPHA] = ARGB32_ALPHA8(dst->back_color)<<dst->shift;
00515 if( offset < 0 )
00516 src_offset = -offset ;
00517 else
00518 dst_offset = offset ;
00519 copy_width = MIN( src->width-src_offset, dst->width-dst_offset );
00520
00521 dst->flags = src->flags ;
00522 for( color = 0 ; color < IC_NUM_CHANNELS ; ++color )
00523 {
00524 register CARD32 *psrc = src->channels[color]+src_offset;
00525 register CARD32 *pdst = dst->channels[color];
00526 int ratio = chan_tint[color];
00527
00528
00529 {
00530
00531 for( i = 0 ; i < dst_offset ; ++i )
00532 pdst[i] = 0;
00533 pdst += dst_offset ;
00534 }
00535
00536 if( get_flags(src->flags, 0x01<<color) )
00537 {
00538 if( ratio >= 254 )
00539 for( i = 0 ; i < copy_width ; ++i )
00540 pdst[i] = psrc[i]<<8;
00541 else if( ratio == 128 )
00542 for( i = 0 ; i < copy_width ; ++i )
00543 pdst[i] = psrc[i]<<7;
00544 else if( ratio == 0 )
00545 for( i = 0 ; i < copy_width ; ++i )
00546 pdst[i] = 0;
00547 else
00548 for( i = 0 ; i < copy_width ; ++i )
00549 pdst[i] = psrc[i]*ratio;
00550 }else
00551 {
00552 ratio = ratio*chan_fill[color];
00553 for( i = 0 ; i < copy_width ; ++i )
00554 pdst[i] = ratio;
00555 set_flags( dst->flags, (0x01<<color));
00556 }
00557 {
00558
00559 for( ; i < (int)dst->width-dst_offset ; ++i )
00560 pdst[i] = 0;
00561
00562 }
00563 }
00564 }
00565
00566
00567
00568
00569 void
00570 make_gradient_scanline( ASScanline *scl, ASGradient *grad, ASFlagType filter, ARGB32 seed )
00571 {
00572 if( scl && grad && filter != 0 )
00573 {
00574 int offset = 0, step, i, max_i = grad->npoints - 1 ;
00575 ARGB32 last_color = ARGB32_Black ;
00576 int last_idx = 0;
00577 double last_offset = 0., *offsets = grad->offset ;
00578 int *used = safecalloc(max_i+1, sizeof(int));
00579
00580 for( i = 0 ; i <= max_i ; ++i )
00581 if( offsets[i] <= 0. )
00582 {
00583 last_color = grad->color[i] ;
00584 last_idx = i ;
00585 used[i] = 1 ;
00586 break;
00587 }
00588
00589 for( i = 0 ; i <= max_i ; i++ )
00590 {
00591 register int k ;
00592 int new_idx = -1 ;
00593
00594 for( k = 0 ; k <= max_i ; ++k )
00595 {
00596 if( used[k]==0 && offsets[k] >= last_offset )
00597 {
00598 if( new_idx < 0 )
00599 new_idx = k ;
00600 else if( offsets[new_idx] > offsets[k] )
00601 new_idx = k ;
00602 else
00603 {
00604 register int d1 = new_idx-last_idx ;
00605 register int d2 = k - last_idx ;
00606 if( d1*d1 > d2*d2 )
00607 new_idx = k ;
00608 }
00609 }
00610 }
00611 if( new_idx < 0 )
00612 break;
00613 used[new_idx] = 1 ;
00614 step = (int)((grad->offset[new_idx] * (double)scl->width) - (double)offset) ;
00615
00616 if( step > (int)scl->width-offset )
00617 step = (int)scl->width-offset ;
00618 if( step > 0 )
00619 {
00620 int color ;
00621 for( color = 0 ; color < IC_NUM_CHANNELS ; ++color )
00622 if( get_flags( filter, 0x01<<color ) )
00623 {
00624 LOCAL_DEBUG_OUT("channel %d from #%4.4lX to #%4.4lX, ofset = %d, step = %d",
00625 color, ARGB32_CHAN8(last_color,color)<<8, ARGB32_CHAN8(grad->color[new_idx],color)<<8, offset, step );
00626 make_component_gradient16( scl->channels[color]+offset,
00627 (CARD16)(ARGB32_CHAN8(last_color,color)<<8),
00628 (CARD16)(ARGB32_CHAN8(grad->color[new_idx],color)<<8),
00629 (CARD8)ARGB32_CHAN8(seed,color),
00630 step);
00631 }
00632 offset += step ;
00633 }
00634 last_offset = offsets[new_idx];
00635 last_color = grad->color[new_idx];
00636 last_idx = new_idx ;
00637 }
00638 scl->flags = filter ;
00639 free( used );
00640 }
00641 }
00642
00643
00644
00645
00646 Bool
00647 check_scale_parameters( ASImage *src, int src_width, int src_height, int *to_width, int *to_height )
00648 {
00649 if( src == NULL )
00650 return False;
00651
00652 if( *to_width == 0 )
00653 *to_width = src_width ;
00654 else if( *to_width < 2 )
00655 *to_width = 2 ;
00656 if( *to_height == 0 )
00657 *to_height = src_height ;
00658 else if( *to_height < 2 )
00659 *to_height = 2 ;
00660 return True;
00661 }
00662
00663 int *
00664 make_scales( int from_size, int to_size, int tail )
00665 {
00666 int *scales ;
00667 int smaller = MIN(from_size,to_size);
00668 int bigger = MAX(from_size,to_size);
00669 register int i = 0, k = 0;
00670 int eps;
00671 LOCAL_DEBUG_OUT( "from %d to %d tail %d", from_size, to_size, tail );
00672 scales = safecalloc( smaller+tail, sizeof(int));
00673 if( smaller <= 1 )
00674 {
00675 scales[0] = bigger ;
00676 return scales;
00677 }
00678 #if 1
00679 else if( smaller == bigger )
00680 {
00681 for ( i = 0 ; i < smaller ; i++ )
00682 scales[i] = 1 ;
00683 return scales;
00684 }
00685 #endif
00686 if( from_size >= to_size )
00687 tail = 0 ;
00688 if( tail != 0 )
00689 {
00690 bigger-=tail ;
00691 if( (smaller-=tail) == 1 )
00692 {
00693 scales[0] = bigger ;
00694 return scales;
00695 }
00696 }else if( smaller == 2 )
00697 {
00698 scales[1] = bigger/2 ;
00699 scales[0] = bigger - scales[1] ;
00700 return scales ;
00701 }
00702
00703 eps = -bigger/2;
00704 LOCAL_DEBUG_OUT( "smaller %d, bigger %d, eps %d", smaller, bigger, eps );
00705
00706
00707
00708 for ( i = 0 ; i < bigger ; i++ )
00709 {
00710 ++scales[k];
00711 eps += smaller;
00712 LOCAL_DEBUG_OUT( "scales[%d] = %d, i = %d, k = %d, eps %d", k, scales[k], i, k, eps );
00713 if( eps+eps >= bigger )
00714 {
00715 ++k ;
00716 eps -= bigger ;
00717 }
00718 }
00719
00720 return scales;
00721 }
00722
00723
00724 void
00725 scale_image_down( ASImageDecoder *imdec, ASImageOutput *imout, int h_ratio, int *scales_h, int* scales_v)
00726 {
00727 ASScanline dst_line, total ;
00728 int k = -1;
00729 int max_k = imout->im->height,
00730 line_len = MIN(imout->im->width, imdec->out_width);
00731
00732 prepare_scanline( imout->im->width, QUANT_ERR_BITS, &dst_line, imout->asv->BGR_mode );
00733 prepare_scanline( imout->im->width, QUANT_ERR_BITS, &total, imout->asv->BGR_mode );
00734 while( ++k < max_k )
00735 {
00736 int reps = scales_v[k] ;
00737 imdec->decode_image_scanline( imdec );
00738 total.flags = imdec->buffer.flags ;
00739 CHOOSE_SCANLINE_FUNC(h_ratio,imdec->buffer,total,scales_h,line_len);
00740
00741 while( --reps > 0 )
00742 {
00743 imdec->decode_image_scanline( imdec );
00744 total.flags = imdec->buffer.flags ;
00745 CHOOSE_SCANLINE_FUNC(h_ratio,imdec->buffer,dst_line,scales_h,line_len);
00746 SCANLINE_FUNC(add_component,total,dst_line,NULL,total.width);
00747 }
00748
00749 imout->output_image_scanline( imout, &total, scales_v[k] );
00750 }
00751 free_scanline(&dst_line, True);
00752 free_scanline(&total, True);
00753 }
00754
00755 void
00756 scale_image_up( ASImageDecoder *imdec, ASImageOutput *imout, int h_ratio, int *scales_h, int* scales_v)
00757 {
00758 ASScanline src_lines[4], *c1, *c2, *c3, *c4 = NULL;
00759 int i = 0, max_i,
00760 line_len = MIN(imout->im->width, imdec->out_width),
00761 out_width = imout->im->width;
00762 ASScanline step ;
00763
00764 prepare_scanline( out_width, 0, &(src_lines[0]), imout->asv->BGR_mode);
00765 prepare_scanline( out_width, 0, &(src_lines[1]), imout->asv->BGR_mode);
00766 prepare_scanline( out_width, 0, &(src_lines[2]), imout->asv->BGR_mode);
00767 prepare_scanline( out_width, 0, &(src_lines[3]), imout->asv->BGR_mode);
00768 prepare_scanline( out_width, QUANT_ERR_BITS, &step, imout->asv->BGR_mode );
00769
00770
00771 imdec->decode_image_scanline( imdec );
00772 src_lines[1].flags = imdec->buffer.flags ;
00773 CHOOSE_SCANLINE_FUNC(h_ratio,imdec->buffer,src_lines[1],scales_h,line_len);
00774
00775 step.flags = src_lines[0].flags = src_lines[1].flags ;
00776
00777 SCANLINE_FUNC(copy_component,src_lines[1],src_lines[0],0,out_width);
00778
00779 imdec->decode_image_scanline( imdec );
00780 src_lines[2].flags = imdec->buffer.flags ;
00781 CHOOSE_SCANLINE_FUNC(h_ratio,imdec->buffer,src_lines[2],scales_h,line_len);
00782
00783 i = 0 ;
00784 max_i = imdec->out_height-1 ;
00785 LOCAL_DEBUG_OUT( "i = %d, max_i = %d", i, max_i );
00786 do
00787 {
00788 int S = scales_v[i] ;
00789 c1 = &(src_lines[i&0x03]);
00790 c2 = &(src_lines[(i+1)&0x03]);
00791 c3 = &(src_lines[(i+2)&0x03]);
00792 c4 = &(src_lines[(i+3)&0x03]);
00793
00794 if( i+1 < max_i )
00795 {
00796 imdec->decode_image_scanline( imdec );
00797 c4->flags = imdec->buffer.flags ;
00798 CHOOSE_SCANLINE_FUNC(h_ratio,imdec->buffer,*c4,scales_h,line_len);
00799 }
00800
00801 if( S > 0 )
00802 {
00803 imout->output_image_scanline( imout, c2, 1);
00804 if( S > 1 )
00805 {
00806 if( S == 2 )
00807 {
00808 SCANLINE_COMBINE(component_interpolation_hardcoded,*c1,*c2,*c3,*c4,*c1,*c1,1,out_width);
00809 imout->output_image_scanline( imout, c1, 1);
00810 }else if( S == 3 )
00811 {
00812 SCANLINE_COMBINE(component_interpolation_hardcoded,*c1,*c2,*c3,*c4,*c1,*c1,2,out_width);
00813 imout->output_image_scanline( imout, c1, 1);
00814 SCANLINE_COMBINE(component_interpolation_hardcoded,*c1,*c2,*c3,*c4,*c1,*c1,3,out_width);
00815 imout->output_image_scanline( imout, c1, 1);
00816 }else
00817 {
00818 SCANLINE_COMBINE(start_component_interpolation,*c1,*c2,*c3,*c4,*c1,step,S,out_width);
00819 do
00820 {
00821 imout->output_image_scanline( imout, c1, 1);
00822 if((--S)<=1)
00823 break;
00824 SCANLINE_FUNC(add_component,*c1,step,NULL,out_width );
00825 }while(1);
00826 }
00827 }
00828 }
00829 }while( ++i < max_i );
00830 imout->output_image_scanline( imout, c3, 1);
00831 free_scanline(&step, True);
00832 free_scanline(&(src_lines[3]), True);
00833 free_scanline(&(src_lines[2]), True);
00834 free_scanline(&(src_lines[1]), True);
00835 free_scanline(&(src_lines[0]), True);
00836 }
00837
00838 void
00839 scale_image_up_dumb( ASImageDecoder *imdec, ASImageOutput *imout, int h_ratio, int *scales_h, int* scales_v)
00840 {
00841 ASScanline src_line;
00842 int line_len = MIN(imout->im->width, imdec->out_width);
00843 int out_width = imout->im->width;
00844 int y = 0 ;
00845
00846 prepare_scanline( out_width, QUANT_ERR_BITS, &src_line, imout->asv->BGR_mode );
00847
00848 imout->tiling_step = 1 ;
00849 LOCAL_DEBUG_OUT( "imdec->next_line = %d, imdec->out_height = %d", imdec->next_line, imdec->out_height );
00850 while( y < (int)imdec->out_height )
00851 {
00852 imdec->decode_image_scanline( imdec );
00853 src_line.flags = imdec->buffer.flags ;
00854 CHOOSE_SCANLINE_FUNC(h_ratio,imdec->buffer,src_line,scales_h,line_len);
00855 imout->tiling_range = scales_v[y];
00856 LOCAL_DEBUG_OUT( "y = %d, tiling_range = %d", y, imout->tiling_range );
00857 imout->output_image_scanline( imout, &src_line, 1);
00858 imout->next_line += scales_v[y]-1;
00859 ++y;
00860 }
00861 free_scanline(&src_line, True);
00862 }
00863
00864
00865 static inline ASImage *
00866 create_destination_image( unsigned int width, unsigned int height, ASAltImFormats format,
00867 unsigned int compression, ARGB32 back_color )
00868 {
00869 ASImage *dst = create_asimage(width, height, compression);
00870 if( dst )
00871 {
00872 if( format != ASA_ASImage )
00873 set_flags( dst->flags, ASIM_DATA_NOT_USEFUL );
00874
00875 dst->back_color = back_color ;
00876 }
00877 return dst ;
00878 }
00879
00880
00881
00882
00883
00884 ASImage *
00885 scale_asimage( ASVisual *asv, ASImage *src, int to_width, int to_height,
00886 ASAltImFormats out_format, unsigned int compression_out, int quality )
00887 {
00888 ASImage *dst = NULL ;
00889 ASImageOutput *imout ;
00890 ASImageDecoder *imdec;
00891 int h_ratio ;
00892 int *scales_h = NULL, *scales_v = NULL;
00893 START_TIME(started);
00894
00895 if( asv == NULL ) asv = &__transform_fake_asv ;
00896
00897 if( !check_scale_parameters(src,src->width, src->height,&to_width,&to_height) )
00898 return NULL;
00899 if( (imdec = start_image_decoding(asv, src, SCL_DO_ALL, 0, 0, 0, 0, NULL)) == NULL )
00900 return NULL;
00901
00902 dst = create_destination_image( to_width, to_height, out_format, compression_out, src->back_color );
00903
00904 if( to_width == src->width )
00905 h_ratio = 0;
00906 else if( to_width < src->width )
00907 h_ratio = 1;
00908 else
00909 {
00910 if ( quality == ASIMAGE_QUALITY_POOR )
00911 h_ratio = 1 ;
00912 else if( src->width > 1 )
00913 {
00914 h_ratio = (to_width/(src->width-1))+1;
00915 if( h_ratio*(src->width-1) < to_width )
00916 ++h_ratio ;
00917 }else
00918 h_ratio = to_width ;
00919 ++h_ratio ;
00920 }
00921 scales_h = make_scales( src->width, to_width, ( quality == ASIMAGE_QUALITY_POOR )?0:1 );
00922 scales_v = make_scales( src->height, to_height, ( quality == ASIMAGE_QUALITY_POOR || src->height <= 3)?0:1 );
00923 #if defined(LOCAL_DEBUG) && !defined(NO_DEBUG_OUTPUT)
00924 {
00925 register int i ;
00926 for( i = 0 ; i < MIN(src->width, to_width) ; i++ )
00927 fprintf( stderr, " %d", scales_h[i] );
00928 fprintf( stderr, "\n" );
00929 for( i = 0 ; i < MIN(src->height, to_height) ; i++ )
00930 fprintf( stderr, " %d", scales_v[i] );
00931 fprintf( stderr, "\n" );
00932 }
00933 #endif
00934 if((imout = start_image_output( asv, dst, out_format, QUANT_ERR_BITS, quality )) == NULL )
00935 {
00936 destroy_asimage( &dst );
00937 }else
00938 {
00939 if( to_height <= src->height )
00940 scale_image_down( imdec, imout, h_ratio, scales_h, scales_v );
00941 else if( quality == ASIMAGE_QUALITY_POOR || src->height <= 3 )
00942 scale_image_up_dumb( imdec, imout, h_ratio, scales_h, scales_v );
00943 else
00944 scale_image_up( imdec, imout, h_ratio, scales_h, scales_v );
00945 stop_image_output( &imout );
00946 }
00947 free( scales_h );
00948 free( scales_v );
00949 stop_image_decoding( &imdec );
00950 SHOW_TIME("", started);
00951 return dst;
00952 }
00953
00954 ASImage *
00955 scale_asimage2( ASVisual *asv, ASImage *src,
00956 int clip_x, int clip_y,
00957 int clip_width, int clip_height,
00958 int to_width, int to_height,
00959 ASAltImFormats out_format, unsigned int compression_out, int quality )
00960 {
00961 ASImage *dst = NULL ;
00962 ASImageOutput *imout ;
00963 ASImageDecoder *imdec;
00964 int h_ratio ;
00965 int *scales_h = NULL, *scales_v = NULL;
00966 START_TIME(started);
00967
00968 if( src == NULL )
00969 return NULL;
00970
00971 if( asv == NULL ) asv = &__transform_fake_asv ;
00972
00973 if( clip_width == 0 )
00974 clip_width = src->width ;
00975 if( clip_height == 0 )
00976 clip_height = src->height ;
00977 if( !check_scale_parameters(src, clip_width, clip_height, &to_width, &to_height) )
00978 return NULL;
00979 if( (imdec = start_image_decoding(asv, src, SCL_DO_ALL, clip_x, clip_y, clip_width, clip_height, NULL)) == NULL )
00980 return NULL;
00981
00982 dst = create_destination_image( to_width, to_height, out_format, compression_out, src->back_color );
00983
00984 if( to_width == clip_width )
00985 h_ratio = 0;
00986 else if( to_width < clip_width )
00987 h_ratio = 1;
00988 else
00989 {
00990 if ( quality == ASIMAGE_QUALITY_POOR )
00991 h_ratio = 1 ;
00992 else if( clip_width > 1 )
00993 {
00994 h_ratio = (to_width/(clip_width-1))+1;
00995 if( h_ratio*(clip_width-1) < to_width )
00996 ++h_ratio ;
00997 }else
00998 h_ratio = to_width ;
00999 ++h_ratio ;
01000 }
01001 scales_h = make_scales( clip_width, to_width, ( quality == ASIMAGE_QUALITY_POOR )?0:1 );
01002 scales_v = make_scales( clip_height, to_height, ( quality == ASIMAGE_QUALITY_POOR || clip_height <= 3)?0:1 );
01003 #if defined(LOCAL_DEBUG) && !defined(NO_DEBUG_OUTPUT)
01004 {
01005 register int i ;
01006 for( i = 0 ; i < MIN(clip_width, to_width) ; i++ )
01007 fprintf( stderr, " %d", scales_h[i] );
01008 fprintf( stderr, "\n" );
01009 for( i = 0 ; i < MIN(clip_height, to_height) ; i++ )
01010 fprintf( stderr, " %d", scales_v[i] );
01011 fprintf( stderr, "\n" );
01012 }
01013 #endif
01014 if((imout = start_image_output( asv, dst, out_format, QUANT_ERR_BITS, quality )) == NULL )
01015 {
01016 destroy_asimage( &dst );
01017 }else
01018 {
01019 if( to_height <= clip_height )
01020 scale_image_down( imdec, imout, h_ratio, scales_h, scales_v );
01021 else if( quality == ASIMAGE_QUALITY_POOR || clip_height <= 3 )
01022 scale_image_up_dumb( imdec, imout, h_ratio, scales_h, scales_v );
01023 else
01024 scale_image_up( imdec, imout, h_ratio, scales_h, scales_v );
01025 stop_image_output( &imout );
01026 }
01027 free( scales_h );
01028 free( scales_v );
01029 stop_image_decoding( &imdec );
01030 SHOW_TIME("", started);
01031 return dst;
01032 }
01033
01034 ASImage *
01035 tile_asimage( ASVisual *asv, ASImage *src,
01036 int offset_x, int offset_y,
01037 int to_width,
01038 int to_height,
01039 ARGB32 tint,
01040 ASAltImFormats out_format, unsigned int compression_out, int quality )
01041 {
01042 ASImage *dst = NULL ;
01043 ASImageDecoder *imdec ;
01044 ASImageOutput *imout ;
01045 START_TIME(started);
01046
01047 if( asv == NULL ) asv = &__transform_fake_asv ;
01048
01049 LOCAL_DEBUG_CALLER_OUT( "src = %p, offset_x = %d, offset_y = %d, to_width = %d, to_height = %d, tint = #%8.8lX", src, offset_x, offset_y, to_width, to_height, tint );
01050 if( src== NULL || (imdec = start_image_decoding(asv, src, SCL_DO_ALL, offset_x, offset_y, to_width, 0, NULL)) == NULL )
01051 {
01052 LOCAL_DEBUG_OUT( "failed to start image decoding%s", "");
01053 return NULL;
01054 }
01055
01056 dst = create_destination_image( to_width, to_height, out_format, compression_out, src->back_color );
01057
01058 if((imout = start_image_output( asv, dst, out_format, (tint!=0)?8:0, quality)) == NULL )
01059 {
01060 LOCAL_DEBUG_OUT( "failed to start image output%s", "");
01061 destroy_asimage( &dst );
01062 }else
01063 {
01064 int y, max_y = to_height;
01065 LOCAL_DEBUG_OUT("tiling actually...%s", "");
01066 if( to_height > src->height )
01067 {
01068 imout->tiling_step = src->height ;
01069 max_y = src->height ;
01070 }
01071 if( tint != 0 )
01072 {
01073 for( y = 0 ; y < max_y ; y++ )
01074 {
01075 imdec->decode_image_scanline( imdec );
01076 tint_component_mod( imdec->buffer.red, (CARD16)(ARGB32_RED8(tint)<<1), to_width );
01077 tint_component_mod( imdec->buffer.green, (CARD16)(ARGB32_GREEN8(tint)<<1), to_width );
01078 tint_component_mod( imdec->buffer.blue, (CARD16)(ARGB32_BLUE8(tint)<<1), to_width );
01079 tint_component_mod( imdec->buffer.alpha, (CARD16)(ARGB32_ALPHA8(tint)<<1), to_width );
01080 imout->output_image_scanline( imout, &(imdec->buffer), 1);
01081 }
01082 }else
01083 for( y = 0 ; y < max_y ; y++ )
01084 {
01085 imdec->decode_image_scanline( imdec );
01086 imout->output_image_scanline( imout, &(imdec->buffer), 1);
01087 }
01088 stop_image_output( &imout );
01089 }
01090 stop_image_decoding( &imdec );
01091
01092 SHOW_TIME("", started);
01093 return dst;
01094 }
01095
01096 ASImage *
01097 merge_layers( ASVisual *asv,
01098 ASImageLayer *layers, int count,
01099 int dst_width,
01100 int dst_height,
01101 ASAltImFormats out_format, unsigned int compression_out, int quality )
01102 {
01103 ASImage *dst = NULL ;
01104 ASImageDecoder **imdecs ;
01105 ASImageOutput *imout ;
01106 ASImageLayer *pcurr = layers;
01107 int i ;
01108 ASScanline dst_line ;
01109 START_TIME(started);
01110
01111 LOCAL_DEBUG_CALLER_OUT( "dst_width = %d, dst_height = %d", dst_width, dst_height );
01112
01113 dst = create_destination_image( dst_width, dst_height, out_format, compression_out, ARGB32_DEFAULT_BACK_COLOR );
01114 if( dst == NULL )
01115 return NULL;
01116
01117 if( asv == NULL ) asv = &__transform_fake_asv ;
01118
01119 prepare_scanline( dst_width, QUANT_ERR_BITS, &dst_line, asv->BGR_mode );
01120 dst_line.flags = SCL_DO_ALL ;
01121
01122 imdecs = safecalloc( count+20, sizeof(ASImageDecoder*));
01123
01124 for( i = 0 ; i < count ; i++ )
01125 {
01126
01127 if( (pcurr->im != NULL || pcurr->solid_color != 0 || i == 0) &&
01128 pcurr->dst_x < (int)dst_width && pcurr->dst_x+(int)pcurr->clip_width > 0 )
01129 {
01130 imdecs[i] = start_image_decoding(asv, pcurr->im, SCL_DO_ALL,
01131 pcurr->clip_x, pcurr->clip_y,
01132 pcurr->clip_width, pcurr->clip_height,
01133 pcurr->bevel);
01134 if( pcurr->bevel_width != 0 && pcurr->bevel_height != 0 )
01135 set_decoder_bevel_geom( imdecs[i],
01136 pcurr->bevel_x, pcurr->bevel_y,
01137 pcurr->bevel_width, pcurr->bevel_height );
01138 if( pcurr->tint == 0 && i != 0 )
01139 set_decoder_shift( imdecs[i], 8 );
01140 if( pcurr->im == NULL )
01141 set_decoder_back_color( imdecs[i], pcurr->solid_color );
01142 }
01143 if( pcurr->next == pcurr )
01144 break;
01145 else
01146 pcurr = (pcurr->next!=NULL)?pcurr->next:pcurr+1 ;
01147 }
01148 if( i < count )
01149 count = i+1 ;
01150
01151 if(imdecs[0] == NULL || (imout = start_image_output( asv, dst, out_format, QUANT_ERR_BITS, quality)) == NULL )
01152 {
01153 for( i = 0 ; i < count ; i++ )
01154 if( imdecs[i] )
01155 stop_image_decoding( &(imdecs[i]) );
01156
01157 destroy_asimage( &dst );
01158 free_scanline( &dst_line, True );
01159 }else
01160 {
01161 int y, max_y = 0;
01162 int min_y = dst_height;
01163 int bg_tint = (layers[0].tint==0)?0x7F7F7F7F:layers[0].tint ;
01164 int bg_bottom = layers[0].dst_y+layers[0].clip_height+imdecs[0]->bevel_v_addon ;
01165 LOCAL_DEBUG_OUT("blending actually...%s", "");
01166 pcurr = layers ;
01167 for( i = 0 ; i < count ; i++ )
01168 {
01169 if( imdecs[i] )
01170 {
01171 int layer_bottom = pcurr->dst_y+pcurr->clip_height ;
01172 if( pcurr->dst_y < min_y )
01173 min_y = pcurr->dst_y;
01174 layer_bottom += imdecs[i]->bevel_v_addon ;
01175 if( (int)layer_bottom > max_y )
01176 max_y = layer_bottom;
01177 }
01178 pcurr = (pcurr->next!=NULL)?pcurr->next:pcurr+1 ;
01179 }
01180 if( min_y < 0 )
01181 min_y = 0 ;
01182 else if( min_y >= (int)dst_height )
01183 min_y = dst_height ;
01184
01185 if( max_y >= (int)dst_height )
01186 max_y = dst_height ;
01187 else
01188 imout->tiling_step = max_y ;
01189
01190 LOCAL_DEBUG_OUT( "min_y = %d, max_y = %d", min_y, max_y );
01191 dst_line.back_color = imdecs[0]->back_color ;
01192 dst_line.flags = 0 ;
01193 for( y = 0 ; y < min_y ; ++y )
01194 imout->output_image_scanline( imout, &dst_line, 1);
01195 dst_line.flags = SCL_DO_ALL ;
01196 pcurr = layers ;
01197 for( i = 0 ; i < count ; ++i )
01198 {
01199 if( imdecs[i] && pcurr->dst_y < min_y )
01200 imdecs[i]->next_line = min_y - pcurr->dst_y ;
01201 pcurr = (pcurr->next!=NULL)?pcurr->next:pcurr+1 ;
01202 }
01203 for( ; y < max_y ; ++y )
01204 {
01205 if( layers[0].dst_y <= y && bg_bottom > y )
01206 imdecs[0]->decode_image_scanline( imdecs[0] );
01207 else
01208 {
01209 imdecs[0]->buffer.back_color = imdecs[0]->back_color ;
01210 imdecs[0]->buffer.flags = 0 ;
01211 }
01212 copytintpad_scanline( &(imdecs[0]->buffer), &dst_line, layers[0].dst_x, bg_tint );
01213 pcurr = layers[0].next?layers[0].next:&(layers[1]) ;
01214 for( i = 1 ; i < count ; i++ )
01215 {
01216 if( imdecs[i] && pcurr->dst_y <= y &&
01217 pcurr->dst_y+(int)pcurr->clip_height+(int)imdecs[i]->bevel_v_addon > y )
01218 {
01219 register ASScanline *b = &(imdecs[i]->buffer);
01220 CARD32 tint = pcurr->tint ;
01221 imdecs[i]->decode_image_scanline( imdecs[i] );
01222 if( tint != 0 )
01223 {
01224 tint_component_mod( b->red, (CARD16)(ARGB32_RED8(tint)<<1), b->width );
01225 tint_component_mod( b->green, (CARD16)(ARGB32_GREEN8(tint)<<1), b->width );
01226 tint_component_mod( b->blue, (CARD16)(ARGB32_BLUE8(tint)<<1), b->width );
01227 tint_component_mod( b->alpha, (CARD16)(ARGB32_ALPHA8(tint)<<1), b->width );
01228 }
01229 pcurr->merge_scanlines( &dst_line, b, pcurr->dst_x );
01230 }
01231 pcurr = (pcurr->next!=NULL)?pcurr->next:pcurr+1 ;
01232 }
01233 imout->output_image_scanline( imout, &dst_line, 1);
01234 }
01235 dst_line.back_color = imdecs[0]->back_color ;
01236 dst_line.flags = 0 ;
01237 for( ; y < (int)dst_height ; y++ )
01238 imout->output_image_scanline( imout, &dst_line, 1);
01239 stop_image_output( &imout );
01240 }
01241 for( i = 0 ; i < count ; i++ )
01242 if( imdecs[i] != NULL )
01243 {
01244 stop_image_decoding( &(imdecs[i]) );
01245 }
01246 free( imdecs );
01247 free_scanline( &dst_line, True );
01248 SHOW_TIME("", started);
01249 return dst;
01250 }
01251
01252
01253
01254
01255 static void
01256 make_gradient_left2right( ASImageOutput *imout, ASScanline *dither_lines, int dither_lines_num, ASFlagType filter )
01257 {
01258 int line ;
01259
01260 imout->tiling_step = dither_lines_num;
01261 for( line = 0 ; line < dither_lines_num ; line++ )
01262 imout->output_image_scanline( imout, &(dither_lines[line]), 1);
01263 }
01264
01265 static void
01266 make_gradient_top2bottom( ASImageOutput *imout, ASScanline *dither_lines, int dither_lines_num, ASFlagType filter )
01267 {
01268 int y, height = imout->im->height, width = imout->im->width ;
01269 int line ;
01270 ASScanline result;
01271 CARD32 chan_data[MAX_GRADIENT_DITHER_LINES] = {0,0,0,0};
01272 LOCAL_DEBUG_CALLER_OUT( "width = %d, height = %d, filetr = 0x%lX, dither_count = %d\n", width, height, filter, dither_lines_num );
01273 prepare_scanline( width, QUANT_ERR_BITS, &result, imout->asv->BGR_mode );
01274 for( y = 0 ; y < height ; y++ )
01275 {
01276 int color ;
01277
01278 result.flags = 0 ;
01279 result.back_color = ARGB32_DEFAULT_BACK_COLOR ;
01280 LOCAL_DEBUG_OUT( "line: %d", y );
01281 for( color = 0 ; color < IC_NUM_CHANNELS ; color++ )
01282 if( get_flags( filter, 0x01<<color ) )
01283 {
01284 Bool dithered = False ;
01285 for( line = 0 ; line < dither_lines_num ; line++ )
01286 {
01287
01288
01289 CARD32 c = dither_lines[line].channels[color][y] ;
01290 if( y+1 < height )
01291 {
01292 c += ((dither_lines[line].channels[color][y+1]&0xFF)>>1);
01293 if( (c&0xFFFF0000) != 0 )
01294 c = ( c&0x7F000000 )?0:0x0000FF00;
01295 }
01296 chan_data[line] = c ;
01297
01298 if( chan_data[line] != chan_data[0] )
01299 dithered = True;
01300 }
01301 LOCAL_DEBUG_OUT( "channel: %d. Dithered ? %d", color, dithered );
01302
01303 if( !dithered )
01304 {
01305 result.back_color = (result.back_color&(~MAKE_ARGB32_CHAN8(0xFF,color)))|
01306 MAKE_ARGB32_CHAN16(chan_data[0],color);
01307 LOCAL_DEBUG_OUT( "back_color = %8.8lX", result.back_color);
01308 }else
01309 {
01310 register CARD32 *dst = result.channels[color] ;
01311 for( line = 0 ; line < dither_lines_num ; line++ )
01312 {
01313 register int x ;
01314 register CARD32 d = chan_data[line] ;
01315 for( x = line ; x < width ; x+=dither_lines_num )
01316 {
01317 dst[x] = d ;
01318 }
01319 }
01320 set_flags(result.flags, 0x01<<color);
01321 }
01322 }
01323 imout->output_image_scanline( imout, &result, 1);
01324 }
01325 free_scanline( &result, True );
01326 }
01327
01328 static void
01329 make_gradient_diag_width( ASImageOutput *imout, ASScanline *dither_lines, int dither_lines_num, ASFlagType filter, Bool from_bottom )
01330 {
01331 int line = 0;
01332
01333 short smaller = imout->im->height;
01334 short bigger = imout->im->width;
01335 register int i = 0;
01336 int eps;
01337 LOCAL_DEBUG_CALLER_OUT( "width = %d, height = %d, filetr = 0x%lX, dither_count = %d, dither width = %d\n", bigger, smaller, filter, dither_lines_num, dither_lines[0].width );
01338
01339 if( from_bottom )
01340 toggle_image_output_direction( imout );
01341 eps = -(bigger>>1);
01342 for ( i = 0 ; i < bigger ; i++ )
01343 {
01344 eps += smaller;
01345 if( (eps << 1) >= bigger )
01346 {
01347
01348 dither_lines[line].offset_x = i ;
01349 imout->output_image_scanline( imout, &(dither_lines[line]), 1);
01350 if( ++line >= dither_lines_num )
01351 line = 0;
01352 eps -= bigger ;
01353 }
01354 }
01355 }
01356
01357 static void
01358 make_gradient_diag_height( ASImageOutput *imout, ASScanline *dither_lines, int dither_lines_num, ASFlagType filter, Bool from_bottom )
01359 {
01360 int line = 0;
01361 unsigned short width = imout->im->width, height = imout->im->height ;
01362
01363 unsigned short smaller = width;
01364 unsigned short bigger = height;
01365 register int i = 0, k =0;
01366 int eps;
01367 ASScanline result;
01368 int *offsets ;
01369
01370 prepare_scanline( width, QUANT_ERR_BITS, &result, imout->asv->BGR_mode );
01371 offsets = safemalloc( sizeof(int)*width );
01372 offsets[0] = 0 ;
01373
01374 eps = -(bigger>>1);
01375 for ( i = 0 ; i < bigger ; i++ )
01376 {
01377 ++offsets[k];
01378 eps += smaller;
01379 if( (eps << 1) >= bigger )
01380 {
01381 if( ++k >= width )
01382 break;
01383 offsets[k] = offsets[k-1] ;
01384 eps -= bigger ;
01385 }
01386 }
01387
01388 if( from_bottom )
01389 toggle_image_output_direction( imout );
01390
01391 result.flags = (filter&SCL_DO_ALL);
01392 if( (filter&SCL_DO_ALL) == SCL_DO_ALL )
01393 {
01394 for( i = 0 ; i < height ; i++ )
01395 {
01396 for( k = 0 ; k < width ; k++ )
01397 {
01398 int offset = i+offsets[k] ;
01399 CARD32 **src_chan = &(dither_lines[line].channels[0]) ;
01400 result.alpha[k] = src_chan[IC_ALPHA][offset] ;
01401 result.red [k] = src_chan[IC_RED] [offset] ;
01402 result.green[k] = src_chan[IC_GREEN][offset] ;
01403 result.blue [k] = src_chan[IC_BLUE] [offset] ;
01404 if( ++line >= dither_lines_num )
01405 line = 0 ;
01406 }
01407 imout->output_image_scanline( imout, &result, 1);
01408 }
01409 }else
01410 {
01411 for( i = 0 ; i < height ; i++ )
01412 {
01413 for( k = 0 ; k < width ; k++ )
01414 {
01415 int offset = i+offsets[k] ;
01416 CARD32 **src_chan = &(dither_lines[line].channels[0]) ;
01417 if( get_flags(filter, SCL_DO_ALPHA) )
01418 result.alpha[k] = src_chan[IC_ALPHA][offset] ;
01419 if( get_flags(filter, SCL_DO_RED) )
01420 result.red[k] = src_chan[IC_RED] [offset] ;
01421 if( get_flags(filter, SCL_DO_GREEN) )
01422 result.green[k] = src_chan[IC_GREEN][offset] ;
01423 if( get_flags(filter, SCL_DO_BLUE) )
01424 result.blue[k] = src_chan[IC_BLUE] [offset] ;
01425 if( ++line >= dither_lines_num )
01426 line = 0 ;
01427 }
01428 imout->output_image_scanline( imout, &result, 1);
01429 }
01430 }
01431
01432 free( offsets );
01433 free_scanline( &result, True );
01434 }
01435
01436 static ARGB32
01437 get_best_grad_back_color( ASGradient *grad )
01438 {
01439 ARGB32 back_color = 0 ;
01440 int chan ;
01441 for( chan = 0 ; chan < IC_NUM_CHANNELS ; ++chan )
01442 {
01443 CARD8 best = 0;
01444 unsigned int best_size = 0;
01445 register int i = grad->npoints;
01446 while( --i > 0 )
01447 {
01448 CARD8 c = ARGB32_CHAN8(grad->color[i], chan );
01449 unsigned int span = grad->color[i]*20000;
01450 if( c == ARGB32_CHAN8(grad->color[i-1], chan ) )
01451 {
01452 span -= grad->color[i-1]*2000;
01453 if( c == best )
01454 best_size += span ;
01455 else if( span > best_size )
01456 {
01457 best_size = span ;
01458 best = c ;
01459 }
01460 }
01461 }
01462 back_color |= MAKE_ARGB32_CHAN8(best,chan);
01463 }
01464 return back_color;
01465 }
01466
01467 ASImage*
01468 make_gradient( ASVisual *asv, ASGradient *grad,
01469 int width, int height, ASFlagType filter,
01470 ASAltImFormats out_format, unsigned int compression_out, int quality )
01471 {
01472 ASImage *im = NULL ;
01473 ASImageOutput *imout;
01474 int line_len = width;
01475 START_TIME(started);
01476 LOCAL_DEBUG_CALLER_OUT( "type = 0x%X, width=%d, height = %d, filter = 0x%lX", grad->type, width, height, filter );
01477 if( grad == NULL )
01478 return NULL;
01479
01480 if( asv == NULL ) asv = &__transform_fake_asv ;
01481
01482 if( width == 0 )
01483 width = 2;
01484 if( height == 0 )
01485 height = 2;
01486
01487 im = create_destination_image( width, height, out_format, compression_out, get_best_grad_back_color( grad ) );
01488
01489 if( get_flags(grad->type,GRADIENT_TYPE_ORIENTATION) )
01490 line_len = height ;
01491 if( get_flags(grad->type,GRADIENT_TYPE_DIAG) )
01492 line_len = MAX(width,height)<<1 ;
01493 if((imout = start_image_output( asv, im, out_format, QUANT_ERR_BITS, quality)) == NULL )
01494 {
01495 destroy_asimage( &im );
01496 }else
01497 {
01498 int dither_lines = MIN(imout->quality+1, MAX_GRADIENT_DITHER_LINES) ;
01499 ASScanline *lines;
01500 int line;
01501 static ARGB32 dither_seeds[MAX_GRADIENT_DITHER_LINES] = { 0, 0xFFFFFFFF, 0x7F0F7F0F, 0x0F7F0F7F };
01502
01503 if( dither_lines > (int)im->height || dither_lines > (int)im->width )
01504 dither_lines = MIN(im->height, im->width) ;
01505
01506 lines = safecalloc( dither_lines, sizeof(ASScanline));
01507 for( line = 0 ; line < dither_lines ; line++ )
01508 {
01509 prepare_scanline( line_len, QUANT_ERR_BITS, &(lines[line]), asv->BGR_mode );
01510 make_gradient_scanline( &(lines[line]), grad, filter, dither_seeds[line] );
01511 }
01512 switch( get_flags(grad->type,GRADIENT_TYPE_MASK) )
01513 {
01514 case GRADIENT_Left2Right :
01515 make_gradient_left2right( imout, lines, dither_lines, filter );
01516 break ;
01517 case GRADIENT_Top2Bottom :
01518 make_gradient_top2bottom( imout, lines, dither_lines, filter );
01519 break ;
01520 case GRADIENT_TopLeft2BottomRight :
01521 case GRADIENT_BottomLeft2TopRight :
01522 if( width >= height )
01523 make_gradient_diag_width( imout, lines, dither_lines, filter,
01524 (grad->type==GRADIENT_BottomLeft2TopRight));
01525 else
01526 make_gradient_diag_height( imout, lines, dither_lines, filter,
01527 (grad->type==GRADIENT_BottomLeft2TopRight));
01528 break ;
01529 default:
01530 break;
01531 }
01532 stop_image_output( &imout );
01533 for( line = 0 ; line < dither_lines ; line++ )
01534 free_scanline( &(lines[line]), True );
01535 free( lines );
01536 }
01537 SHOW_TIME("", started);
01538 return im;
01539 }
01540
01541
01542
01543
01544 ASImage *
01545 flip_asimage( ASVisual *asv, ASImage *src,
01546 int offset_x, int offset_y,
01547 int to_width,
01548 int to_height,
01549 int flip,
01550 ASAltImFormats out_format, unsigned int compression_out, int quality )
01551 {
01552 ASImage *dst = NULL ;
01553 ASImageOutput *imout ;
01554 ASFlagType filter = SCL_DO_ALL;
01555 START_TIME(started);
01556
01557 LOCAL_DEBUG_CALLER_OUT( "offset_x = %d, offset_y = %d, to_width = %d, to_height = %d", offset_x, offset_y, to_width, to_height );
01558 if( src == NULL )
01559 return NULL ;
01560
01561 filter = get_asimage_chanmask(src);
01562 dst = create_destination_image( to_width, to_height, out_format, compression_out, src->back_color);
01563
01564 if( asv == NULL ) asv = &__transform_fake_asv ;
01565
01566 if((imout = start_image_output( asv, dst, out_format, 0, quality)) == NULL )
01567 {
01568 destroy_asimage( &dst );
01569 }else
01570 {
01571 ASImageDecoder *imdec ;
01572 ASScanline result ;
01573 int y;
01574 LOCAL_DEBUG_OUT("flip-flopping actually...%s", "");
01575 prepare_scanline( to_width, 0, &result, asv->BGR_mode );
01576 if( (imdec = start_image_decoding(asv, src, filter, offset_x, offset_y,
01577 get_flags( flip, FLIP_VERTICAL )?to_height:to_width,
01578 get_flags( flip, FLIP_VERTICAL )?to_width:to_height, NULL)) != NULL )
01579 {
01580 if( get_flags( flip, FLIP_VERTICAL ) )
01581 {
01582 CARD32 *chan_data ;
01583 size_t pos = 0;
01584 int x ;
01585 CARD32 *a = imdec->buffer.alpha ;
01586 CARD32 *r = imdec->buffer.red ;
01587 CARD32 *g = imdec->buffer.green ;
01588 CARD32 *b = imdec->buffer.blue;
01589
01590 chan_data = safemalloc( to_width*to_height*sizeof(CARD32));
01591 result.back_color = src->back_color;
01592 result.flags = filter ;
01593
01594
01595
01596
01597 for( y = 0 ; y < (int)to_width ; y++ )
01598 {
01599 imdec->decode_image_scanline( imdec );
01600 for( x = 0; x < (int)to_height ; x++ )
01601 {
01602 chan_data[pos++] = MAKE_ARGB32( a[x],r[x],g[x],b[x] );
01603 }
01604 }
01605
01606 if( get_flags( flip, FLIP_UPSIDEDOWN ) )
01607 {
01608 for( y = 0 ; y < (int)to_height ; ++y )
01609 {
01610 pos = y + (int)(to_width-1)*(to_height) ;
01611 for( x = 0 ; x < (int)to_width ; ++x )
01612 {
01613 result.alpha[x] = ARGB32_ALPHA8(chan_data[pos]);
01614 result.red [x] = ARGB32_RED8(chan_data[pos]);
01615 result.green[x] = ARGB32_GREEN8(chan_data[pos]);
01616 result.blue [x] = ARGB32_BLUE8(chan_data[pos]);
01617 pos -= to_height ;
01618 }
01619 imout->output_image_scanline( imout, &result, 1);
01620 }
01621 }else
01622 {
01623 for( y = to_height-1 ; y >= 0 ; --y )
01624 {
01625 pos = y ;
01626 for( x = 0 ; x < (int)to_width ; ++x )
01627 {
01628 result.alpha[x] = ARGB32_ALPHA8(chan_data[pos]);
01629 result.red [x] = ARGB32_RED8(chan_data[pos]);
01630 result.green[x] = ARGB32_GREEN8(chan_data[pos]);
01631 result.blue [x] = ARGB32_BLUE8(chan_data[pos]);
01632 pos += to_height ;
01633 }
01634 imout->output_image_scanline( imout, &result, 1);
01635 }
01636 }
01637 free( chan_data );
01638 }else
01639 {
01640 toggle_image_output_direction( imout );
01641
01642 for( y = 0 ; y < (int)to_height ; y++ )
01643 {
01644 imdec->decode_image_scanline( imdec );
01645 result.flags = imdec->buffer.flags = imdec->buffer.flags & filter ;
01646 result.back_color = imdec->buffer.back_color ;
01647 SCANLINE_FUNC_FILTERED(reverse_component,imdec->buffer,result,0,to_width);
01648 imout->output_image_scanline( imout, &result, 1);
01649 }
01650 }
01651 stop_image_decoding( &imdec );
01652 }
01653 free_scanline( &result, True );
01654 stop_image_output( &imout );
01655 }
01656 SHOW_TIME("", started);
01657 return dst;
01658 }
01659
01660 ASImage *
01661 mirror_asimage( ASVisual *asv, ASImage *src,
01662 int offset_x, int offset_y,
01663 int to_width,
01664 int to_height,
01665 Bool vertical, ASAltImFormats out_format,
01666 unsigned int compression_out, int quality )
01667 {
01668 ASImage *dst = NULL ;
01669 ASImageOutput *imout ;
01670 START_TIME(started);
01671
01672 LOCAL_DEBUG_CALLER_OUT( "offset_x = %d, offset_y = %d, to_width = %d, to_height = %d", offset_x, offset_y, to_width, to_height );
01673 dst = create_destination_image( to_width, to_height, out_format, compression_out, src->back_color);
01674
01675 if( asv == NULL ) asv = &__transform_fake_asv ;
01676
01677 if((imout = start_image_output( asv, dst, out_format, 0, quality)) == NULL )
01678 {
01679 destroy_asimage( &dst );
01680 }else
01681 {
01682 ASImageDecoder *imdec ;
01683 ASScanline result ;
01684 int y;
01685 if( !vertical )
01686 prepare_scanline( to_width, 0, &result, asv->BGR_mode );
01687 LOCAL_DEBUG_OUT("miroring actually...%s", "");
01688 if( (imdec = start_image_decoding(asv, src, SCL_DO_ALL, offset_x, offset_y,
01689 to_width, to_height, NULL)) != NULL )
01690 {
01691 if( vertical )
01692 {
01693 toggle_image_output_direction( imout );
01694 for( y = 0 ; y < (int)to_height ; y++ )
01695 {
01696 imdec->decode_image_scanline( imdec );
01697 imout->output_image_scanline( imout, &(imdec->buffer), 1);
01698 }
01699 }else
01700 {
01701 for( y = 0 ; y < (int)to_height ; y++ )
01702 {
01703 imdec->decode_image_scanline( imdec );
01704 result.flags = imdec->buffer.flags ;
01705 result.back_color = imdec->buffer.back_color ;
01706 SCANLINE_FUNC(reverse_component,imdec->buffer,result,0,to_width);
01707 imout->output_image_scanline( imout, &result, 1);
01708 }
01709 }
01710 stop_image_decoding( &imdec );
01711 }
01712 if( !vertical )
01713 free_scanline( &result, True );
01714 stop_image_output( &imout );
01715 }
01716 SHOW_TIME("", started);
01717 return dst;
01718 }
01719
01720 ASImage *
01721 pad_asimage( ASVisual *asv, ASImage *src,
01722 int dst_x, int dst_y,
01723 int to_width,
01724 int to_height,
01725 ARGB32 color,
01726 ASAltImFormats out_format,
01727 unsigned int compression_out, int quality )
01728 {
01729 ASImage *dst = NULL ;
01730 ASImageOutput *imout ;
01731 int clip_width, clip_height ;
01732 START_TIME(started);
01733
01734 LOCAL_DEBUG_CALLER_OUT( "dst_x = %d, dst_y = %d, to_width = %d, to_height = %d", dst_x, dst_y, to_width, to_height );
01735 if( src == NULL )
01736 return NULL ;
01737
01738 if( to_width == src->width && to_height == src->height && dst_x == 0 && dst_y == 0 )
01739 return clone_asimage( src, SCL_DO_ALL );
01740
01741 if( asv == NULL ) asv = &__transform_fake_asv ;
01742
01743 dst = create_destination_image( to_width, to_height, out_format, compression_out, src->back_color);
01744
01745 clip_width = src->width ;
01746 clip_height = src->height ;
01747 if( dst_x < 0 )
01748 clip_width = MIN( (int)to_width, dst_x+clip_width );
01749 else
01750 clip_width = MIN( (int)to_width-dst_x, clip_width );
01751 if( dst_y < 0 )
01752 clip_height = MIN( (int)to_height, dst_y+clip_height);
01753 else
01754 clip_height = MIN( (int)to_height-dst_y, clip_height);
01755 if( (clip_width <= 0 || clip_height <= 0) )
01756 {
01757 dst->back_color = color ;
01758 return dst ;
01759 }
01760
01761 if((imout = start_image_output( asv, dst, out_format, 0, quality)) == NULL )
01762 {
01763 destroy_asimage( &dst );
01764 }else
01765 {
01766 ASImageDecoder *imdec = NULL;
01767 ASScanline result ;
01768 int y;
01769 int start_x = (dst_x < 0)? 0: dst_x;
01770 int start_y = (dst_y < 0)? 0: dst_y;
01771
01772 if( (int)to_width != clip_width || clip_width != (int)src->width )
01773 {
01774 prepare_scanline( to_width, 0, &result, asv->BGR_mode );
01775 imdec = start_image_decoding( asv, src, SCL_DO_ALL,
01776 (dst_x<0)? -dst_x:0,
01777 (dst_y<0)? -dst_y:0,
01778 clip_width, clip_height, NULL);
01779 }
01780
01781 result.back_color = color ;
01782 result.flags = 0 ;
01783 LOCAL_DEBUG_OUT( "filling %d lines with %8.8lX", start_y, color );
01784 for( y = 0 ; y < start_y ; y++ )
01785 imout->output_image_scanline( imout, &result, 1);
01786
01787 if( imdec )
01788 result.back_color = imdec->buffer.back_color ;
01789 if( (int)to_width == clip_width )
01790 {
01791 if( imdec == NULL )
01792 {
01793 LOCAL_DEBUG_OUT( "copiing %d lines", clip_height );
01794 copy_asimage_lines( dst, start_y, src, (dst_y < 0 )? -dst_y: 0, clip_height, SCL_DO_ALL );
01795 imout->next_line += clip_height ;
01796 }else
01797 for( y = 0 ; y < clip_height ; y++ )
01798 {
01799 imdec->decode_image_scanline( imdec );
01800 imout->output_image_scanline( imout, &(imdec->buffer), 1);
01801 }
01802 }else if( imdec )
01803 {
01804 for( y = 0 ; y < clip_height ; y++ )
01805 {
01806 int chan ;
01807
01808 imdec->decode_image_scanline( imdec );
01809 result.flags = imdec->buffer.flags ;
01810 for( chan = 0 ; chan < IC_NUM_CHANNELS ; ++chan )
01811 {
01812 register CARD32 *chan_data = result.channels[chan] ;
01813 register CARD32 *src_chan_data = imdec->buffer.channels[chan]+((dst_x<0)? -dst_x : 0) ;
01814 CARD32 chan_val = ARGB32_CHAN8(color, chan);
01815 register int k = -1;
01816 for( k = 0 ; k < start_x ; ++k )
01817 chan_data[k] = chan_val ;
01818 chan_data += k ;
01819 for( k = 0 ; k < clip_width ; ++k )
01820 chan_data[k] = src_chan_data[k];
01821 chan_data += k ;
01822 k = to_width-(start_x+clip_width) ;
01823 while( --k >= 0 )
01824 chan_data[k] = chan_val ;
01825 }
01826 imout->output_image_scanline( imout, &result, 1);
01827 }
01828 }
01829 result.back_color = color ;
01830 result.flags = 0 ;
01831 LOCAL_DEBUG_OUT( "filling %d lines with %8.8lX at the end", to_height-(start_y+clip_height), color );
01832 for( y = start_y+clip_height ; y < (int)to_height ; y++ )
01833 imout->output_image_scanline( imout, &result, 1);
01834
01835 if( imdec )
01836 {
01837 stop_image_decoding( &imdec );
01838 free_scanline( &result, True );
01839 }
01840 stop_image_output( &imout );
01841 }
01842 SHOW_TIME("", started);
01843 return dst;
01844 }
01845
01846
01847
01848
01849 Bool fill_asimage( ASVisual *asv, ASImage *im,
01850 int x, int y, int width, int height,
01851 ARGB32 color )
01852 {
01853 ASImageOutput *imout;
01854 ASImageDecoder *imdec;
01855 START_TIME(started);
01856
01857 if( asv == NULL ) asv = &__transform_fake_asv ;
01858
01859 if( im == NULL )
01860 return False;
01861 if( x < 0 )
01862 { width += x ; x = 0 ; }
01863 if( y < 0 )
01864 { height += y ; y = 0 ; }
01865
01866 if( width <= 0 || height <= 0 || x >= (int)im->width || y >= (int)im->height )
01867 return False;
01868 if( x+width > (int)im->width )
01869 width = (int)im->width-x ;
01870 if( y+height > (int)im->height )
01871 height = (int)im->height-y ;
01872
01873 if((imout = start_image_output( asv, im, ASA_ASImage, 0, ASIMAGE_QUALITY_DEFAULT)) == NULL )
01874 return False ;
01875 else
01876 {
01877 int i ;
01878 imout->next_line = y ;
01879 if( x == 0 && width == (int)im->width )
01880 {
01881 ASScanline result ;
01882 result.flags = 0 ;
01883 result.back_color = color ;
01884 for( i = 0 ; i < height ; i++ )
01885 imout->output_image_scanline( imout, &result, 1);
01886 }else if ((imdec = start_image_decoding(asv, im, SCL_DO_ALL, 0, y, im->width, height, NULL)) != NULL )
01887 {
01888 CARD32 alpha = ARGB32_ALPHA8(color), red = ARGB32_RED8(color),
01889 green = ARGB32_GREEN8(color), blue = ARGB32_BLUE8(color);
01890 CARD32 *a = imdec->buffer.alpha + x ;
01891 CARD32 *r = imdec->buffer.red + x ;
01892 CARD32 *g = imdec->buffer.green + x ;
01893 CARD32 *b = imdec->buffer.blue + x ;
01894 for( i = 0 ; i < height ; i++ )
01895 {
01896 register int k ;
01897 imdec->decode_image_scanline( imdec );
01898 for( k = 0 ; k < width ; ++k )
01899 {
01900 a[k] = alpha ;
01901 r[k] = red ;
01902 g[k] = green ;
01903 b[k] = blue ;
01904 }
01905 imout->output_image_scanline( imout, &(imdec->buffer), 1);
01906 }
01907 stop_image_decoding( &imdec );
01908 }
01909 }
01910 stop_image_output( &imout );
01911 SHOW_TIME("", started);
01912 return True;
01913 }
01914
01915
01916
01917
01918 Bool
01919 colorize_asimage_vector( ASVisual *asv, ASImage *im,
01920 ASVectorPalette *palette,
01921 ASAltImFormats out_format,
01922 int quality )
01923 {
01924 ASImageOutput *imout = NULL ;
01925 ASScanline buf ;
01926 int x, y, curr_point, last_point ;
01927 register double *vector ;
01928 double *points ;
01929 double *multipliers[IC_NUM_CHANNELS] ;
01930 START_TIME(started);
01931
01932 if( im == NULL || palette == NULL || out_format == ASA_Vector )
01933 return False;
01934
01935 if( im->alt.vector == NULL )
01936 return False;
01937 vector = im->alt.vector ;
01938
01939 if( asv == NULL ) asv = &__transform_fake_asv ;
01940
01941 if((imout = start_image_output( asv, im, out_format, QUANT_ERR_BITS, quality)) == NULL )
01942 return False;
01943
01944
01945 if( !get_flags( im->flags, ASIM_VECTOR_TOP2BOTTOM) )
01946 toggle_image_output_direction(imout);
01947
01948 prepare_scanline( im->width, QUANT_ERR_BITS, &buf, asv->BGR_mode );
01949 curr_point = palette->npoints/2 ;
01950 points = palette->points ;
01951 last_point = palette->npoints-1 ;
01952 buf.flags = 0 ;
01953 for( y = 0 ; y < IC_NUM_CHANNELS ; ++y )
01954 {
01955 if( palette->channels[y] )
01956 {
01957 multipliers[y] = safemalloc( last_point*sizeof(double));
01958 for( x = 0 ; x < last_point ; ++x )
01959 {
01960 if (points[x+1] == points[x])
01961 multipliers[y][x] = 1;
01962 else
01963 multipliers[y][x] = (double)(palette->channels[y][x+1] - palette->channels[y][x])/
01964 (points[x+1]-points[x]);
01965
01966
01967
01968 }
01969
01970 set_flags(buf.flags, (0x01<<y));
01971 }else
01972 multipliers[y] = NULL ;
01973 }
01974 for( y = 0 ; y < (int)im->height ; ++y )
01975 {
01976 for( x = 0 ; x < (int)im->width ;)
01977 {
01978 register int i = IC_NUM_CHANNELS ;
01979 double d ;
01980
01981 if( points[curr_point] > vector[x] )
01982 {
01983 while( --curr_point >= 0 )
01984 if( points[curr_point] < vector[x] )
01985 break;
01986 if( curr_point < 0 )
01987 ++curr_point ;
01988 }else
01989 {
01990 while( points[curr_point+1] < vector[x] )
01991 if( ++curr_point >= last_point )
01992 {
01993 curr_point = last_point-1 ;
01994 break;
01995 }
01996 }
01997 d = vector[x]-points[curr_point];
01998
01999 while( --i >= 0 )
02000 if( multipliers[i] )
02001 {
02002 buf.channels[i][x] = (int)(d*multipliers[i][curr_point])+palette->channels[i][curr_point] ;
02003
02004 }
02005
02006 #if 1
02007 while( ++x < (int)im->width )
02008 if( vector[x] == vector[x-1] )
02009 {
02010 buf.red[x] = buf.red[x-1] ;
02011 buf.green[x] = buf.green[x-1] ;
02012 buf.blue[x] = buf.blue[x-1] ;
02013 buf.alpha[x] = buf.alpha[x-1] ;
02014 }else
02015 break;
02016 #else
02017 ++x ;
02018 #endif
02019 }
02020
02021 imout->output_image_scanline( imout, &buf, 1);
02022 vector += im->width ;
02023 }
02024 for( y = 0 ; y < IC_NUM_CHANNELS ; ++y )
02025 if( multipliers[y] )
02026 free(multipliers[y]);
02027
02028 stop_image_output( &imout );
02029 free_scanline( &buf, True );
02030 SHOW_TIME("", started);
02031 return True;
02032 }
02033
02034 ASImage *
02035 create_asimage_from_vector( ASVisual *asv, double *vector,
02036 int width, int height,
02037 ASVectorPalette *palette,
02038 ASAltImFormats out_format,
02039 unsigned int compression, int quality )
02040 {
02041 ASImage *im = NULL;
02042
02043 if( asv == NULL ) asv = &__transform_fake_asv ;
02044
02045 if( vector != NULL )
02046 {
02047 im = create_destination_image( width, height, out_format, compression, ARGB32_DEFAULT_BACK_COLOR);
02048
02049 if( im != NULL )
02050 {
02051 if( set_asimage_vector( im, vector ) )
02052 if( palette )
02053 colorize_asimage_vector( asv, im, palette, out_format, quality );
02054 }
02055 }
02056 return im ;
02057 }
02058
02059
02060
02061
02062
02063
02064 #undef PI
02065 #define PI 3.141592526
02066
02067 #if 0
02068 static inline void
02069 gauss_component(CARD32 *src, CARD32 *dst, int radius, double* gauss, int len)
02070 {
02071 int x, j, r = radius - 1;
02072 for (x = 0 ; x < len ; x++) {
02073 register double v = 0.0;
02074 for (j = x - r ; j <= 0 ; j++) v += src[0] * gauss[x - j];
02075 for ( ; j < x ; j++) v += src[j] * gauss[x - j];
02076 v += src[x] * gauss[0];
02077 for (j = x + r ; j >= len ; j--) v += src[len - 1] * gauss[j - x];
02078 for ( ; j > x ; j--) v += src[j] * gauss[j - x];
02079 dst[x] = (CARD32)v;
02080 }
02081 }
02082 #endif
02083
02084 #define GAUSS_COEFF_TYPE int
02085
02086 static void calc_gauss_int(int radius, GAUSS_COEFF_TYPE* gauss, GAUSS_COEFF_TYPE* gauss_sums);
02087
02088 #define gauss_data_t CARD32
02089 #define gauss_var_t int
02090
02091 static inline void
02092 gauss_component_int(gauss_data_t *s1, gauss_data_t *d1, int radius, GAUSS_COEFF_TYPE* gauss, GAUSS_COEFF_TYPE* gauss_sums, int len)
02093 {
02094 #define DEFINE_GAUS_TMP_VAR CARD32 *xs1 = &s1[x]; CARD32 v1 = xs1[0]*gauss[0]
02095 if( len < radius + radius )
02096 {
02097 int x = 0, j;
02098 while( x < len )
02099 {
02100 int tail = len - 1 - x;
02101 int gauss_sum = gauss[0];
02102 DEFINE_GAUS_TMP_VAR;
02103 for (j = 1 ; j <= x ; ++j)
02104 {
02105 v1 += xs1[-j]*gauss[j];
02106 gauss_sum += gauss[j];
02107 }
02108 for (j = 1 ; j <= tail ; ++j)
02109 {
02110 v1 += xs1[j]*gauss[j];
02111 gauss_sum += gauss[j];
02112 }
02113 d1[x] = (v1<<10)/gauss_sum;
02114 ++x;
02115 }
02116 return;
02117 }
02118
02119 #define MIDDLE_STRETCH_GAUSS(j_check) \
02120 do{ for( j = 1 ; j j_check ; ++j ) v1 += (xs1[-j]*gauss[j]+xs1[j]*gauss[j]); }while(0)
02121
02122
02123 {
02124 int x = 0 ;
02125 for( ; x < radius-1 ; ++x )
02126 {
02127 int j ;
02128 gauss_data_t *xs1 = &s1[x];
02129 gauss_var_t v1 = xs1[0]*gauss[0];
02130 for( j = 1 ; j <= x ; ++j )
02131 v1 += (xs1[-j]*gauss[j]+xs1[j]*gauss[j]);
02132
02133 for( ; j < radius ; ++j )
02134 v1 += xs1[j]*gauss[j];
02135 d1[x] = (v1<<10)/gauss_sums[x];
02136 }
02137 }
02138
02139
02140 if (radius-1 == len - radius)
02141 {
02142 gauss_data_t *xs1 = &s1[radius-1];
02143 gauss_var_t v1 = xs1[0]*gauss[0];
02144 int j = 1;
02145 for( ; j < radius ; ++j )
02146 v1 += (xs1[-j]*gauss[j]+xs1[j]*gauss[j]);
02147 d1[radius] = v1 ;
02148 }else
02149 {
02150 int x = radius;
02151 for(; x <= len - radius + 1; x+=3)
02152 {
02153 gauss_data_t *xs1 = &s1[x];
02154 gauss_var_t v1 = xs1[-1]*gauss[0];
02155 gauss_var_t v2 = xs1[0]*gauss[0];
02156 gauss_var_t v3 = xs1[1]*gauss[0];
02157 int j = 1;
02158 for( ; j < radius ; ++j )
02159 {
02160 int g = gauss[j];
02161 v1 += xs1[-j-1]*g+xs1[j-1]*g;
02162 v2 += xs1[-j]*g+xs1[j]*g;
02163 v3 += xs1[-j+1]*g+xs1[j+1]*g;
02164 }
02165 d1[x-1] = v1 ;
02166 d1[x] = v2 ;
02167 d1[x+1] = v3 ;
02168 }
02169 }
02170 {
02171 int x = 0;
02172 gauss_data_t *td1 = &d1[len-1];
02173 for( ; x < radius-1; ++x )
02174 {
02175 int j;
02176 gauss_data_t *xs1 = &s1[len-1-x];
02177 gauss_var_t v1 = xs1[0]*gauss[0];
02178 for( j = 1 ; j <= x ; ++j )
02179 v1 += (xs1[-j]*gauss[j]+xs1[j]*gauss[j]);
02180
02181 for( ; j <radius ; ++j )
02182 v1 += xs1[-j]*gauss[j];
02183 td1[-x] = (v1<<10)/gauss_sums[x];
02184 }
02185 }
02186 #undef MIDDLE_STRETCH_GAUSS
02187 #undef DEFINE_GAUS_TMP_VAR
02188 }
02189
02190
02191
02192 #ifdef USE_PARALLEL_OPTIMIZATION
02193
02194
02195
02196 static inline void
02197 gauss_component_int2(CARD32 *s1, CARD32 *d1, CARD32 *s2, CARD32 *d2, int radius, GAUSS_COEFF_TYPE* gauss, GAUSS_COEFF_TYPE* gauss_sums, int len)
02198 {
02199 #define MIDDLE_STRETCH_GAUSS do{GAUSS_COEFF_TYPE g = gauss[j]; \
02200 v1 += (xs1[-j]+xs1[j])*g; \
02201 v2 += (xs2[-j]+xs2[j])*g; }while(0)
02202
02203 int x, j;
02204 int tail = radius;
02205 GAUSS_COEFF_TYPE g0 = gauss[0];
02206 for( x = 0 ; x < radius ; ++x )
02207 {
02208 register CARD32 *xs1 = &s1[x];
02209 register CARD32 *xs2 = &s2[x];
02210 register CARD32 v1 = s1[x]*g0;
02211 register CARD32 v2 = s2[x]*g0;
02212 for( j = 1 ; j <= x ; ++j )
02213 MIDDLE_STRETCH_GAUSS;
02214 for( ; j < radius ; ++j )
02215 {
02216 GAUSS_COEFF_TYPE g = gauss[j];
02217 CARD32 m1 = xs1[j]*g;
02218 CARD32 m2 = xs2[j]*g;
02219 v1 += m1;
02220 v2 += m2;
02221 }
02222 v1 = v1<<10;
02223 v2 = v2<<10;
02224 {
02225 GAUSS_COEFF_TYPE gs = gauss_sums[x];
02226 d1[x] = v1/gs;
02227 d2[x] = v2/gs;
02228 }
02229 }
02230 while( x <= len-radius )
02231 {
02232 register CARD32 *xs1 = &s1[x];
02233 register CARD32 *xs2 = &s2[x];
02234 register CARD32 v1 = s1[x]*g0;
02235 register CARD32 v2 = s2[x]*g0;
02236 for( j = 1 ; j < radius ; ++j )
02237 MIDDLE_STRETCH_GAUSS;
02238 d1[x] = v1 ;
02239 d2[x] = v2 ;
02240 ++x;
02241 }
02242 while( --tail > 0 )
02243 {
02244 register CARD32 *xs1 = &s1[x];
02245 register CARD32 *xs2 = &s2[x];
02246 register CARD32 v1 = xs1[0]*g0;
02247 register CARD32 v2 = xs2[0]*g0;
02248 for( j = 1 ; j < tail ; ++j )
02249 MIDDLE_STRETCH_GAUSS;
02250 for( ; j <radius ; ++j )
02251 {
02252 GAUSS_COEFF_TYPE g = gauss[j];
02253 CARD32 m1 = xs1[-j]*g;
02254 CARD32 m2 = xs2[-j]*g;
02255 v1 += m1;
02256 v2 += m2;
02257 }
02258 v1 = v1<<10;
02259 v2 = v2<<10;
02260 {
02261 GAUSS_COEFF_TYPE gs = gauss_sums[tail];
02262 d1[x] = v1/gs;
02263 d2[x] = v2/gs;
02264 }
02265 ++x;
02266 }
02267 #undef MIDDLE_STRETCH_GAUSS
02268 }
02269 #endif
02270
02271 static inline void
02272 load_gauss_scanline(ASScanline *result, ASImageDecoder *imdec, int horz, GAUSS_COEFF_TYPE *sgauss, GAUSS_COEFF_TYPE *sgauss_sums, ASFlagType filter )
02273 {
02274 ASFlagType lf;
02275 int x, chan;
02276 #ifdef USE_PARALLEL_OPTIMIZATION
02277 int todo_count = 0;
02278 int todo[IC_NUM_CHANNELS] = {-1,-1,-1,-1};
02279 #endif
02280 imdec->decode_image_scanline(imdec);
02281 lf = imdec->buffer.flags&filter ;
02282 result->flags = imdec->buffer.flags;
02283 result->back_color = imdec->buffer.back_color;
02284
02285 for( chan = 0 ; chan < IC_NUM_CHANNELS ; ++chan )
02286 {
02287 CARD32 *res_chan = result->channels[chan];
02288 CARD32 *src_chan = imdec->buffer.channels[chan];
02289 if( get_flags(lf, 0x01<<chan) )
02290 {
02291 if( horz == 1 )
02292 {
02293 for( x = 0 ; x < result->width ; ++x )
02294 res_chan[x] = src_chan[x]<<10 ;
02295 }else
02296 {
02297 #ifdef USE_PARALLEL_OPTIMIZATION
02298 todo[todo_count++] = chan;
02299 #else
02300 gauss_component_int(src_chan, res_chan, horz, sgauss, sgauss_sums, result->width);
02301 #endif
02302 }
02303 }else if( get_flags( result->flags, 0x01<<chan ) )
02304 copy_component( src_chan, res_chan, 0, result->width);
02305 else if( get_flags( filter, 0x01<<chan ) )
02306 {
02307 CARD32 fill = (CARD32)ARGB32_RED8(imdec->buffer.back_color)<<10;
02308 for( x = 0 ; x < result->width ; ++x ) res_chan[x] = fill ;
02309 }
02310 }
02311
02312 #ifdef USE_PARALLEL_OPTIMIZATION
02313 switch( 4 - todo_count )
02314 {
02315 case 0 :
02316 gauss_component_int2(imdec->buffer.channels[todo[2]], result->channels[todo[2]],
02317 imdec->buffer.channels[todo[3]], result->channels[todo[3]],
02318 horz, sgauss, sgauss_sums, result->width);
02319 case 2 :
02320 gauss_component_int2(imdec->buffer.channels[todo[0]], result->channels[todo[0]],
02321 imdec->buffer.channels[todo[1]], result->channels[todo[1]],
02322 horz, sgauss, sgauss_sums, result->width); break ;
02323 case 1 :
02324 gauss_component_int2(imdec->buffer.channels[todo[1]], result->channels[todo[1]],
02325 imdec->buffer.channels[todo[2]], result->channels[todo[2]],
02326 horz, sgauss, sgauss_sums, result->width);
02327 case 3 :
02328 gauss_component_int( imdec->buffer.channels[todo[0]],
02329 result->channels[todo[0]],
02330 horz, sgauss, sgauss_sums, result->width); break ;
02331 }
02332 #endif
02333 }
02334
02335
02336 ASImage* blur_asimage_gauss(ASVisual* asv, ASImage* src, double dhorz, double dvert,
02337 ASFlagType filter,
02338 ASAltImFormats out_format, unsigned int compression_out, int quality)
02339 {
02340 ASImage *dst = NULL;
02341 ASImageOutput *imout;
02342 ASImageDecoder *imdec;
02343 int y, x, chan;
02344 int horz = (int)dhorz;
02345 int vert = (int)dvert;
02346 int width, height ;
02347 #if 0
02348 struct timeval stv;
02349 gettimeofday (&stv,NULL);
02350 #define PRINT_BACKGROUND_OP_TIME do{ struct timeval tv;gettimeofday (&tv,NULL); tv.tv_sec-= stv.tv_sec;\
02351 fprintf (stderr,__FILE__ "%d: elapsed %ld usec\n",__LINE__,\
02352 tv.tv_sec*1000000+tv.tv_usec-stv.tv_usec );}while(0)
02353 #else
02354 #define PRINT_BACKGROUND_OP_TIME do{}while(0)
02355 #endif
02356
02357 if (!src) return NULL;
02358
02359 if( asv == NULL ) asv = &__transform_fake_asv ;
02360
02361 width = src->width ;
02362 height = src->height ;
02363 dst = create_destination_image( width, height, out_format, compression_out, src->back_color);
02364
02365 imout = start_image_output(asv, dst, out_format, 0, quality);
02366 if (!imout)
02367 {
02368 destroy_asimage( &dst );
02369 return NULL;
02370 }
02371
02372 imdec = start_image_decoding(asv, src, SCL_DO_ALL, 0, 0, src->width, src->height, NULL);
02373 if (!imdec)
02374 {
02375 stop_image_output(&imout);
02376 destroy_asimage( &dst );
02377 return NULL;
02378 }
02379
02380 if( horz > (width-1)/2 ) horz = (width==1 )?1:(width-1)/2 ;
02381 if( vert > (height-1)/2 ) vert = (height==1)?1:(height-1)/2 ;
02382 if (horz > 128)
02383 horz = 128;
02384 else if (horz < 1)
02385 horz = 1;
02386 if( vert > 128 )
02387 vert = 128 ;
02388 else if( vert < 1 )
02389 vert = 1 ;
02390
02391 if( vert == 1 && horz == 1 )
02392 {
02393 for (y = 0 ; y < dst->height ; y++)
02394 {
02395 imdec->decode_image_scanline(imdec);
02396 imout->output_image_scanline(imout, &(imdec->buffer), 1);
02397 }
02398 }else
02399 {
02400 ASScanline result;
02401 GAUSS_COEFF_TYPE *horz_gauss = NULL;
02402 GAUSS_COEFF_TYPE *horz_gauss_sums = NULL;
02403
02404 if( horz > 1 )
02405 {
02406 PRINT_BACKGROUND_OP_TIME;
02407 horz_gauss = safecalloc(horz+1, sizeof(GAUSS_COEFF_TYPE));
02408 horz_gauss_sums = safecalloc(horz+1, sizeof(GAUSS_COEFF_TYPE));
02409 calc_gauss_int(horz, horz_gauss, horz_gauss_sums);
02410 PRINT_BACKGROUND_OP_TIME;
02411 }
02412 prepare_scanline(width, 0, &result, asv->BGR_mode);
02413 if( vert == 1 )
02414 {
02415 for (y = 0 ; y < height ; y++)
02416 {
02417 load_gauss_scanline(&result, imdec, horz, horz_gauss, horz_gauss_sums, filter );
02418 for( chan = 0 ; chan < IC_NUM_CHANNELS ; ++chan )
02419 if( get_flags( filter, 0x01<<chan ) )
02420 {
02421 CARD32 *res_chan = result.channels[chan];
02422 for( x = 0 ; x < width ; ++x )
02423 res_chan[x] = (res_chan[x]&0x03Fc0000)?255:res_chan[x]>>10;
02424 }
02425 imout->output_image_scanline(imout, &result, 1);
02426 }
02427 }else
02428 {
02429 GAUSS_COEFF_TYPE *vert_gauss = safecalloc(vert+1, sizeof(GAUSS_COEFF_TYPE));
02430 GAUSS_COEFF_TYPE *vert_gauss_sums = safecalloc(vert+1, sizeof(GAUSS_COEFF_TYPE));
02431 int lines_count = vert*2-1;
02432 int first_line = 0, last_line = lines_count-1;
02433 ASScanline *lines_mem = safecalloc( lines_count, sizeof(ASScanline));
02434 ASScanline **lines = safecalloc( dst->height+1, sizeof(ASScanline*));
02435
02436
02437 calc_gauss_int(vert, vert_gauss, vert_gauss_sums);
02438 PRINT_BACKGROUND_OP_TIME;
02439
02440 for( y = 0 ; y < lines_count ; ++y )
02441 {
02442 lines[y] = &lines_mem[y] ;
02443 prepare_scanline(width, 0, lines[y], asv->BGR_mode);
02444 load_gauss_scanline(lines[y], imdec, horz, horz_gauss, horz_gauss_sums, filter );
02445 }
02446
02447 PRINT_BACKGROUND_OP_TIME;
02448 result.flags = 0xFFFFFFFF;
02449
02450 for (y = 0 ; y < vert-1 ; y++)
02451 {
02452 for( chan = 0 ; chan < IC_NUM_CHANNELS ; ++chan )
02453 {
02454 CARD32 *res_chan = result.channels[chan];
02455 if( !get_flags(filter, 0x01<<chan) )
02456 copy_component( lines[y]->channels[chan], res_chan, 0, width);
02457 else
02458 {
02459 register ASScanline **ysrc = &lines[y];
02460 int j = 0;
02461 GAUSS_COEFF_TYPE g = vert_gauss[0];
02462 CARD32 *src_chan1 = ysrc[0]->channels[chan];
02463 for( x = 0 ; x < width ; ++x )
02464 res_chan[x] = src_chan1[x]*g;
02465 while( ++j <= y )
02466 {
02467 CARD32 *src_chan2 = ysrc[j]->channels[chan];
02468 g = vert_gauss[j];
02469 src_chan1 = ysrc[-j]->channels[chan];
02470 for( x = 0 ; x < width ; ++x )
02471 res_chan[x] += (src_chan1[x]+src_chan2[x])*g;
02472 }
02473 for( ; j < vert ; ++j )
02474 {
02475 g = vert_gauss[j];
02476 src_chan1 = ysrc[j]->channels[chan];
02477 for( x = 0 ; x < width ; ++x )
02478 res_chan[x] += src_chan1[x]*g;
02479 }
02480 g = vert_gauss_sums[y];
02481 for( x = 0 ; x < width ; ++x )
02482 {
02483 gauss_var_t v = res_chan[x]/g;
02484 res_chan[x] = (v&0x03Fc0000)?255:v>>10;
02485 }
02486 }
02487 }
02488 imout->output_image_scanline(imout, &result, 1);
02489 }
02490 PRINT_BACKGROUND_OP_TIME;
02491
02492 for( ; y <= height - vert; ++y)
02493 {
02494 for( chan = 0 ; chan < IC_NUM_CHANNELS ; ++chan )
02495 {
02496 CARD32 *res_chan = result.channels[chan];
02497 if( !get_flags(filter, 0x01<<chan) )
02498 copy_component( lines[y]->channels[chan], res_chan, 0, result.width);
02499 else
02500 {
02501 register ASScanline **ysrc = &lines[y];
02502
02503 int j = 0;
02504 CARD32 *src_chan1 = ysrc[0]->channels[chan];
02505 memset( res_chan, 0x00, width*4 );
02506
02507
02508
02509 while( ++j < vert )
02510 {
02511 CARD32 *src_chan2 = ysrc[j]->channels[chan];
02512 GAUSS_COEFF_TYPE g = vert_gauss[j];
02513 src_chan1 = ysrc[-j]->channels[chan];
02514 switch( g )
02515 {
02516 case 1 :
02517 for( x = 0 ; x < width ; ++x )
02518 res_chan[x] += src_chan1[x]+src_chan2[x];
02519 break;
02520 case 2 :
02521 for( x = 0 ; x < width ; ++x )
02522 res_chan[x] += (src_chan1[x]+src_chan2[x])<<1;
02523 break;
02524 #if 1
02525 case 4 :
02526 for( x = 0 ; x < width ; ++x )
02527 res_chan[x] += (src_chan1[x]+src_chan2[x])<<2;
02528 break;
02529 case 8 :
02530 for( x = 0 ; x < width ; ++x )
02531 res_chan[x] += (src_chan1[x]+src_chan2[x])<<3;
02532 break;
02533 case 16 :
02534 for( x = 0 ; x < width ; ++x )
02535 res_chan[x] += (src_chan1[x]+src_chan2[x])<<4;
02536 break;
02537 case 32 :
02538 for( x = 0 ; x < width ; ++x )
02539 res_chan[x] += (src_chan1[x]+src_chan2[x])<<5;
02540 break;
02541 #endif
02542 default :
02543 for( x = 0 ; x < width ; ++x )
02544 res_chan[x] += (src_chan1[x]+src_chan2[x])*g;
02545 }
02546 }
02547 src_chan1 = ysrc[0]->channels[chan];
02548 for( x = 0 ; x < width ; ++x )
02549 {
02550 gauss_var_t v = src_chan1[x]*vert_gauss[0] + res_chan[x];
02551 res_chan[x] = (v&0xF0000000)?255:v>>20;
02552 }
02553 }
02554 }
02555
02556 imout->output_image_scanline(imout, &result, 1);
02557 ++last_line;
02558
02559 lines[last_line] = lines[first_line] ;
02560 ++first_line;
02561 load_gauss_scanline(lines[last_line], imdec, horz, horz_gauss, horz_gauss_sums, filter );
02562 }
02563 PRINT_BACKGROUND_OP_TIME;
02564
02565 for( ; y < height; ++y)
02566 {
02567 int tail = height - y ;
02568 for( chan = 0 ; chan < IC_NUM_CHANNELS ; ++chan )
02569 {
02570 CARD32 *res_chan = result.channels[chan];
02571 if( !get_flags(filter, 0x01<<chan) )
02572 copy_component( lines[y]->channels[chan], res_chan, 0, result.width);
02573 else
02574 {
02575 register ASScanline **ysrc = &lines[y];
02576 int j = 0;
02577 GAUSS_COEFF_TYPE g ;
02578 CARD32 *src_chan1 = ysrc[0]->channels[chan];
02579 for( x = 0 ; x < width ; ++x )
02580 res_chan[x] = src_chan1[x]*vert_gauss[0];
02581 for( j = 1 ; j < tail ; ++j )
02582 {
02583 CARD32 *src_chan2 = ysrc[j]->channels[chan];
02584 g = vert_gauss[j];
02585 src_chan1 = ysrc[-j]->channels[chan];
02586 for( x = 0 ; x < width ; ++x )
02587 res_chan[x] += (src_chan1[x]+src_chan2[x])*g;
02588 }
02589 for( ; j < vert ; ++j )
02590 {
02591 g = vert_gauss[j];
02592 src_chan1 = ysrc[-j]->channels[chan];
02593 for( x = 0 ; x < width ; ++x )
02594 res_chan[x] += src_chan1[x]*g;
02595 }
02596 g = vert_gauss_sums[tail];
02597 for( x = 0 ; x < width ; ++x )
02598 {
02599 gauss_var_t v = res_chan[x]/g;
02600 res_chan[x] = (v&0x03Fc0000)?255:v>>10;
02601 }
02602 }
02603 }
02604
02605 imout->output_image_scanline(imout, &result, 1);
02606 }
02607
02608 for( y = 0 ; y < lines_count ; ++y )
02609 free_scanline(&lines_mem[y], True);
02610 free( lines_mem );
02611 free( lines );
02612 free(vert_gauss_sums);
02613 free(vert_gauss);
02614
02615 }
02616 free_scanline(&result, True);
02617 if( horz_gauss_sums )
02618 free(horz_gauss_sums);
02619 if( horz_gauss )
02620 free(horz_gauss);
02621 }
02622 PRINT_BACKGROUND_OP_TIME;
02623
02624 stop_image_decoding(&imdec);
02625 stop_image_output(&imout);
02626
02627 return dst;
02628 }
02629
02630 #if 0
02631 static void calc_gauss_double(double radius, double* gauss)
02632 {
02633 int i, mult;
02634 double std_dev, sum = 0.0;
02635 double g0, g_last;
02636 double n, nn, nPI, nnPI;
02637 if (radius <= 1.0)
02638 {
02639 gauss[0] = 1.0;
02640 return;
02641 }
02642
02643
02644 if (radius > 128.0) radius = 128.0;
02645 std_dev = (radius - 1) * 0.3003866304;
02646 do
02647 {
02648 sum = 0 ;
02649 n = std_dev * std_dev;
02650 nn = 2*n ;
02651 nPI = n*PI;
02652 nnPI = nn*PI;
02653 sum = g0 = 1.0 / nnPI ;
02654 for (i = 1 ; i < radius-1 ; i++)
02655 sum += exp((double)-i * (double)i / nn)/nPI;
02656 g_last = exp((double)-i * (double)i / nn)/nnPI;
02657 sum += g_last*2.0 ;
02658
02659 mult = (int)((1024.0+radius*0.94)/sum);
02660 std_dev += 0.1 ;
02661 }while( g_last*mult < 1. );
02662
02663 gauss[0] = g0/sum ;
02664 gauss[(int)radius-1] = g_last/sum;
02665
02666 sum *= nnPI;
02667 for (i = 1 ; i < radius-1 ; i++)
02668 gauss[i] = exp((double)-i * (double)i / nn)/sum;
02669 }
02670 #endif
02671
02672
02673 static const double standard_deviations[128] =
02674 {
02675 0.0, 0.300387, 0.600773, 0.901160, 1.201547, 1.501933, 1.852320, 2.202706, 2.553093, 2.903480, 3.253866, 3.604253, 3.954640, 4.355026, 4.705413, 5.105799,
02676 5.456186, 5.856573, 6.256959, 6.657346, 7.057733, 7.458119, 7.858506, 8.258892, 8.659279, 9.059666, 9.510052, 9.910439, 10.360826, 10.761212, 11.211599, 11.611986,
02677 12.062372, 12.512759, 12.963145, 13.413532, 13.863919, 14.314305, 14.764692, 15.215079, 15.665465, 16.115852, 16.566238, 17.066625, 17.517012, 18.017398, 18.467785, 18.968172,
02678 19.418558, 19.918945, 20.419332, 20.869718, 21.370105, 21.870491, 22.370878, 22.871265, 23.371651, 23.872038, 24.372425, 24.872811, 25.373198, 25.923584, 26.423971, 26.924358,
02679 27.474744, 27.975131, 28.525518, 29.025904, 29.576291, 30.126677, 30.627064, 31.177451, 31.727837, 32.278224, 32.828611, 33.378997, 33.929384, 34.479771, 35.030157, 35.580544,
02680 36.130930, 36.731317, 37.281704, 37.832090, 38.432477, 38.982864, 39.583250, 40.133637, 40.734023, 41.334410, 41.884797, 42.485183, 43.085570, 43.685957, 44.286343, 44.886730,
02681 45.487117, 46.087503, 46.687890, 47.288276, 47.938663, 48.539050, 49.139436, 49.789823, 50.390210, 50.990596, 51.640983, 52.291369, 52.891756, 53.542143, 54.192529, 54.842916,
02682 55.443303, 56.093689, 56.744076, 57.394462, 58.044849, 58.745236, 59.395622, 60.046009, 60.696396, 61.396782, 62.047169, 62.747556, 63.397942, 64.098329, 64.748715, 65.449102
02683
02684 };
02685
02686 static const double descr_approxim_mult[128] =
02687 {
02688 0.0, 576.033927, 1539.585724, 2313.193545, 3084.478025, 3855.885078, 4756.332754, 5657.242476, 6558.536133, 7460.139309, 8361.990613, 9264.041672, 10166.254856, 11199.615571, 12102.233350, 13136.515398,
02689 14039.393687, 15074.393173, 16109.866931, 17145.763345, 18182.036948, 19218.647831, 20255.561010, 21292.745815, 22330.175327, 23367.825876, 24540.507339, 25578.741286, 26752.587529, 27791.291872, 28966.144174, 30005.229117,
02690 31180.955186, 32357.252344, 33534.082488, 34711.410459, 35889.203827, 37067.432679, 38246.069415, 39425.088562, 40604.466591, 41784.181759, 42964.213952, 44284.538859, 45465.382595, 46787.130142, 47968.686878, 49291.724522,
02691 50473.909042, 51798.119528, 53123.060725, 54306.137507, 55632.091099, 56958.688068, 58285.899344, 59613.697438, 60942.056354, 62270.951500, 63600.359608, 64930.258655, 66260.627789, 67737.102560, 69068.620203, 70400.544942,
02692 71879.460632, 73212.395873, 74692.932606, 76026.792904, 77508.839552, 78991.791376, 80327.002820, 81811.308203, 83296.434414, 84782.353155, 86269.037314, 87756.460905, 89244.599028, 90733.427810, 92222.924365, 93713.066749,
02693 95203.833910, 96847.414084, 98339.659244, 99832.465294, 101479.012792, 102973.158567, 104621.682880, 106117.081106, 107767.473327, 109418.953577, 110916.202212, 112569.394820, 114223.592283, 115878.766626, 117534.890826, 119191.938777,
02694 120849.885258, 122508.705901, 124168.377156, 125828.876263, 127648.916790, 129311.319925, 130974.481906, 132798.169283, 134463.087846, 136128.703019, 137955.784611, 139784.215161, 141452.370894, 143283.009733, 145114.908442, 146948.037106,
02695 148619.357599, 150454.489089, 152290.771330, 154128.177628, 155966.682058, 157971.069246, 159812.039780, 161654.030102, 163497.017214, 165507.250512, 167352.489586, 169365.683736, 171213.071546, 173229.105499, 175078.544507, 177097.303447
02696
02697 };
02698
02699 static void calc_gauss_int(int radius, GAUSS_COEFF_TYPE* gauss, GAUSS_COEFF_TYPE* gauss_sums)
02700 {
02701 int i = radius;
02702 double dmult;
02703 double std_dev;
02704 if (i <= 1)
02705 {
02706 gauss[0] = 1024;
02707 gauss_sums[0] = 1024;
02708 return;
02709 }
02710
02711
02712 if (i > 128) i = 128;
02713 #if 1
02714 {
02715 double nn;
02716 GAUSS_COEFF_TYPE sum = 1024 ;
02717 std_dev = standard_deviations[i-1];
02718 dmult = descr_approxim_mult[i-1];
02719 nn = 2*std_dev * std_dev ;
02720 dmult /=nn*PI;
02721 gauss[0] = (GAUSS_COEFF_TYPE)(dmult + 0.5);
02722 while( i >= 1 )
02723 {
02724 gauss[i] = (GAUSS_COEFF_TYPE)(exp((double)-i * (double)i / nn)*dmult + 0.5);
02725 gauss_sums[i] = sum;
02726 sum -= gauss[i];
02727 --i;
02728 }
02729 gauss_sums[0] = sum;
02730 }
02731 #else
02732 double g0, g_last, sum = 0.;
02733 double n, nn, nPI, nnPI;
02734 std_dev = (radius - 1) * 0.3003866304;
02735 do
02736 {
02737 sum = 0 ;
02738 n = std_dev * std_dev;
02739 nn = 2*n ;
02740 nPI = n*PI;
02741 nnPI = nn*PI;
02742 sum = g0 = 1.0 / nnPI ;
02743 for (i = 1 ; i < radius-1 ; i++)
02744 sum += exp((double)-i * (double)i / nn)/nPI;
02745 g_last = exp((double)-i * (double)i / nn)/nnPI;
02746 sum += g_last*2.0 ;
02747
02748 dmult = 1024.0/sum;
02749 std_dev += 0.05 ;
02750 }while( g_last*dmult < 1. );
02751 gauss[0] = g0 * dmult + 0.5;
02752 gauss[(int)radius-1] = g_last * dmult + 0.5;
02753 dmult /=nnPI;
02754 for (i = 1 ; i < radius-1 ; i++)
02755 gauss[i] = exp((double)-i * (double)i / nn)*dmult + 0.5;
02756
02757 #endif
02758
02759 #if 0
02760 {
02761 static int count = 0 ;
02762 if( ++count == 16 )
02763 {
02764 fprintf( stderr, "\n " );
02765 count = 0 ;
02766 }
02767
02768 fprintf(stderr, "%lf, ", dmult*nnPI );
02769 }
02770 #endif
02771 #if 0
02772 {
02773 int sum_da = 0 ;
02774 fprintf(stderr, "sum = %f, dmult = %f\n", sum, dmult );
02775 for (i = 0 ; i < radius ; i++)
02776 {
02777
02778 sum_da += gauss[i]*2 ;
02779 fprintf(stderr, "discr_approx(%d) = %d\n", i, gauss[i]);
02780 }
02781 sum_da -= gauss[0];
02782
02783 fprintf(stderr, "sum_da = %d\n", sum_da );
02784 }
02785 #endif
02786 }
02787
02788
02789
02790
02791
02792 ASImage*
02793 adjust_asimage_hsv( ASVisual *asv, ASImage *src,
02794 int offset_x, int offset_y,
02795 int to_width, int to_height,
02796 int affected_hue, int affected_radius,
02797 int hue_offset, int saturation_offset, int value_offset,
02798 ASAltImFormats out_format,
02799 unsigned int compression_out, int quality )
02800 {
02801 ASImage *dst = NULL ;
02802 ASImageDecoder *imdec ;
02803 ASImageOutput *imout ;
02804 START_TIME(started);
02805
02806 if( asv == NULL ) asv = &__transform_fake_asv ;
02807
02808 LOCAL_DEBUG_CALLER_OUT( "offset_x = %d, offset_y = %d, to_width = %d, to_height = %d, hue = %u", offset_x, offset_y, to_width, to_height, affected_hue );
02809 if( src == NULL )
02810 return NULL;
02811 if( (imdec = start_image_decoding(asv, src, SCL_DO_ALL, offset_x, offset_y, to_width, 0, NULL)) == NULL )
02812 return NULL;
02813
02814 dst = create_destination_image( to_width, to_height, out_format, compression_out, src->back_color);
02815 set_decoder_shift(imdec,8);
02816 if((imout = start_image_output( asv, dst, out_format, 8, quality)) == NULL )
02817 {
02818 destroy_asimage( &dst );
02819 }else
02820 {
02821 CARD32 from_hue1 = 0, from_hue2 = 0, to_hue1 = 0, to_hue2 = 0 ;
02822 int y, max_y = to_height;
02823 Bool do_greyscale = False ;
02824
02825 affected_hue = normalize_degrees_val( affected_hue );
02826 affected_radius = normalize_degrees_val( affected_radius );
02827 if( value_offset != 0 )
02828 do_greyscale = (affected_hue+affected_radius >= 360 || affected_hue-affected_radius <= 0 );
02829 if( affected_hue > affected_radius )
02830 {
02831 from_hue1 = degrees2hue16(affected_hue-affected_radius);
02832 if( affected_hue+affected_radius >= 360 )
02833 {
02834 to_hue1 = MAX_HUE16 ;
02835 from_hue2 = MIN_HUE16 ;
02836 to_hue2 = degrees2hue16(affected_hue+affected_radius-360);
02837 }else
02838 to_hue1 = degrees2hue16(affected_hue+affected_radius);
02839 }else
02840 {
02841 from_hue1 = degrees2hue16(affected_hue+360-affected_radius);
02842 to_hue1 = MAX_HUE16 ;
02843 from_hue2 = MIN_HUE16 ;
02844 to_hue2 = degrees2hue16(affected_hue+affected_radius);
02845 }
02846 hue_offset = degrees2hue16(hue_offset);
02847 saturation_offset = (saturation_offset<<16) / 100;
02848 value_offset = (value_offset<<16)/100 ;
02849 LOCAL_DEBUG_OUT("adjusting actually...%s", "");
02850 if( to_height > src->height )
02851 {
02852 imout->tiling_step = src->height ;
02853 max_y = src->height ;
02854 }
02855 for( y = 0 ; y < max_y ; y++ )
02856 {
02857 register int x = imdec->buffer.width;
02858 CARD32 *r = imdec->buffer.red;
02859 CARD32 *g = imdec->buffer.green;
02860 CARD32 *b = imdec->buffer.blue ;
02861 long h, s, v ;
02862 imdec->decode_image_scanline( imdec );
02863 while( --x >= 0 )
02864 {
02865 if( (h = rgb2hue( r[x], g[x], b[x] )) != 0 )
02866 {
02867 #ifdef DEBUG_HSV_ADJUSTMENT
02868 fprintf( stderr, "IN %d: rgb = #%4.4lX.%4.4lX.%4.4lX hue = %ld(%d) range is (%ld - %ld, %ld - %ld), dh = %d\n", __LINE__, r[x], g[x], b[x], h, ((h>>8)*360)>>8, from_hue1, to_hue1, from_hue2, to_hue2, hue_offset );
02869 #endif
02870
02871 if( affected_radius >= 180 ||
02872 (h >= (int)from_hue1 && h <= (int)to_hue1 ) ||
02873 (h >= (int)from_hue2 && h <= (int)to_hue2 ) )
02874
02875 {
02876 s = rgb2saturation( r[x], g[x], b[x] ) + saturation_offset;
02877 v = rgb2value( r[x], g[x], b[x] )+value_offset;
02878 h += hue_offset ;
02879 if( h > MAX_HUE16 )
02880 h -= MAX_HUE16 ;
02881 else if( h == 0 )
02882 h = MIN_HUE16 ;
02883 else if( h < 0 )
02884 h += MAX_HUE16 ;
02885 if( v < 0 ) v = 0 ;
02886 else if( v > 0x00FFFF ) v = 0x00FFFF ;
02887
02888 if( s < 0 ) s = 0 ;
02889 else if( s > 0x00FFFF ) s = 0x00FFFF ;
02890
02891 hsv2rgb ( (CARD32)h, (CARD32)s, (CARD32)v, &r[x], &g[x], &b[x]);
02892
02893 #ifdef DEBUG_HSV_ADJUSTMENT
02894 fprintf( stderr, "OUT %d: rgb = #%4.4lX.%4.4lX.%4.4lX hue = %ld(%ld) sat = %ld val = %ld\n", __LINE__, r[x], g[x], b[x], h, ((h>>8)*360)>>8, s, v );
02895 #endif
02896 }
02897 }else if( do_greyscale )
02898 {
02899 int tmp = (int)r[x] + value_offset ;
02900 g[x] = b[x] = r[x] = (tmp < 0)?0:((tmp>0x00FFFF)?0x00FFff:tmp);
02901 }
02902 }
02903 imdec->buffer.flags = 0xFFFFFFFF ;
02904 imout->output_image_scanline( imout, &(imdec->buffer), 1);
02905 }
02906 stop_image_output( &imout );
02907 }
02908 stop_image_decoding( &imdec );
02909
02910 SHOW_TIME("", started);
02911 return dst;
02912 }
02913
02914 static void
02915 slice_scanline( ASScanline *dst, ASScanline *src, int start_x, int end_x, ASScanline *middle )
02916 {
02917 CARD32 *sa = src->alpha, *da = dst->alpha ;
02918 CARD32 *sr = src->red, *dr = dst->red ;
02919 CARD32 *sg = src->green, *dg = dst->green ;
02920 CARD32 *sb = src->blue, *db = dst->blue ;
02921 int max_x = min( start_x, (int)dst->width);
02922 int tail = (int)src->width - end_x ;
02923 int tiling_step = end_x - start_x ;
02924 int x1, x2, max_x2 ;
02925
02926 LOCAL_DEBUG_OUT( "start_x = %d, end_x = %d, tail = %d, tiling_step = %d, max_x = %d", start_x, end_x, tail, tiling_step, max_x );
02927 for( x1 = 0 ; x1 < max_x ; ++x1 )
02928 {
02929 da[x1] = sa[x1] ;
02930 dr[x1] = sr[x1] ;
02931 dg[x1] = sg[x1] ;
02932 db[x1] = sb[x1] ;
02933 }
02934 if( x1 >= dst->width )
02935 return;
02936
02937 max_x2 = (int) dst->width - tail ;
02938 max_x = min(end_x, max_x2);
02939 if( middle )
02940 {
02941 CARD32 *ma = middle->alpha-x1 ;
02942 CARD32 *mr = middle->red-x1 ;
02943 CARD32 *mg = middle->green-x1 ;
02944 CARD32 *mb = middle->blue-x1 ;
02945 LOCAL_DEBUG_OUT( "middle->width = %d", middle->width );
02946
02947 for( ; x1 < max_x2 ; ++x1 )
02948 {
02949 da[x1] = ma[x1] ;
02950 dr[x1] = mr[x1] ;
02951 dg[x1] = mg[x1] ;
02952 db[x1] = mb[x1] ;
02953 }
02954 LOCAL_DEBUG_OUT( "%d: %8.8lX %8.8lX %8.8lX %8.8lX", x1-1, ma[x1-1], mr[x1-1], mg[x1-1], mb[x1-1] );
02955 }else
02956 {
02957 for( ; x1 < max_x ; ++x1 )
02958 {
02959 x2 = x1 ;
02960 for( x2 = x1 ; x2 < max_x2 ; x2 += tiling_step )
02961 {
02962 da[x2] = sa[x1] ;
02963 dr[x2] = sr[x1] ;
02964 dg[x2] = sg[x1] ;
02965 db[x2] = sb[x1] ;
02966 }
02967 }
02968 }
02969
02970 x1 = src->width - tail ;
02971 x2 = max(max_x2,start_x) ;
02972 max_x = src->width ;
02973 max_x2 = dst->width ;
02974 for( ; x1 < max_x && x2 < max_x2; ++x1, ++x2 )
02975 {
02976 da[x2] = sa[x1] ;
02977 dr[x2] = sr[x1] ;
02978 dg[x2] = sg[x1] ;
02979 db[x2] = sb[x1] ;
02980 }
02981 }
02982
02983
02984 ASImage*
02985 slice_asimage2( ASVisual *asv, ASImage *src,
02986 int slice_x_start, int slice_x_end,
02987 int slice_y_start, int slice_y_end,
02988 int to_width,
02989 int to_height,
02990 Bool scale,
02991 ASAltImFormats out_format,
02992 unsigned int compression_out, int quality )
02993 {
02994 ASImage *dst = NULL ;
02995 ASImageDecoder *imdec = NULL ;
02996 ASImageOutput *imout = NULL ;
02997 START_TIME(started);
02998
02999 if( asv == NULL ) asv = &__transform_fake_asv ;
03000
03001 LOCAL_DEBUG_CALLER_OUT( "scale = %d, sx1 = %d, sx2 = %d, sy1 = %d, sy2 = %d, to_width = %d, to_height = %d", scale, slice_x_start, slice_x_end, slice_y_start, slice_y_end, to_width, to_height );
03002 if( src == NULL )
03003 return NULL;
03004 if( (imdec = start_image_decoding(asv, src, SCL_DO_ALL, 0, 0, src->width, 0, NULL)) == NULL )
03005 return NULL;
03006 if( slice_x_end == 0 && slice_x_start > 0 )
03007 slice_x_end = slice_x_start + 1 ;
03008 if( slice_y_end == 0 && slice_y_start > 0 )
03009 slice_y_end = slice_y_start + 1 ;
03010 if( slice_x_end > src->width )
03011 slice_x_end = src->width ;
03012 if( slice_y_end > src->height )
03013 slice_y_end = src->height ;
03014 if( slice_x_start > slice_x_end )
03015 slice_x_start = (slice_x_end > 0 ) ? slice_x_end-1 : 0 ;
03016 if( slice_y_start > slice_y_end )
03017 slice_y_start = (slice_y_end > 0 ) ? slice_y_end-1 : 0 ;
03018
03019 LOCAL_DEBUG_OUT( "sx1 = %d, sx2 = %d, sy1 = %d, sy2 = %d, to_width = %d, to_height = %d", slice_x_start, slice_x_end, slice_y_start, slice_y_end, to_width, to_height );
03020 dst = create_destination_image( to_width, to_height, out_format, compression_out, src->back_color);
03021 if((imout = start_image_output( asv, dst, out_format, 0, quality)) == NULL )
03022 {
03023 destroy_asimage( &dst );
03024 }else
03025 {
03026 int y1, y2 ;
03027 int max_y = min( slice_y_start, (int)dst->height);
03028 int tail = (int)src->height - slice_y_end ;
03029 int max_y2 = (int) dst->height - tail ;
03030 ASScanline *out_buf = prepare_scanline( to_width, 0, NULL, asv->BGR_mode );
03031
03032 out_buf->flags = 0xFFFFFFFF ;
03033
03034 if( scale )
03035 {
03036 ASImageDecoder *imdec_scaled ;
03037 ASImage *tmp ;
03038 int x_middle = to_width - slice_x_start ;
03039 int x_right = src->width - (slice_x_end+1) ;
03040 int y_middle = to_height - slice_y_start ;
03041 int y_bottom = src->height - (slice_y_end+1) ;
03042 x_middle = ( x_middle <= x_right )? 0 : x_middle-x_right ;
03043 y_middle = ( y_middle <= y_bottom )? 0 : y_middle-y_bottom ;
03044
03045 if( x_middle > 0 )
03046 {
03047 tmp = scale_asimage2( asv, src, slice_x_start, 0,
03048 slice_x_end-slice_x_start, max_y,
03049 x_middle, max_y, ASA_ASImage, 0, quality );
03050 imdec_scaled = start_image_decoding(asv, tmp, SCL_DO_ALL, 0, 0, 0, 0, NULL) ;
03051 for( y1 = 0 ; y1 < max_y ; ++y1 )
03052 {
03053 imdec->decode_image_scanline( imdec );
03054 imdec_scaled->decode_image_scanline( imdec_scaled );
03055 slice_scanline( out_buf, &(imdec->buffer), slice_x_start, slice_x_end, &(imdec_scaled->buffer) );
03056 imout->output_image_scanline( imout, out_buf, 1);
03057 }
03058 stop_image_decoding( &imdec_scaled );
03059 destroy_asimage( &tmp );
03060 }else
03061 {
03062 for( y1 = 0 ; y1 < max_y ; ++y1 )
03063 {
03064 imdec->decode_image_scanline( imdec );
03065 imout->output_image_scanline( imout, &(imdec->buffer), 1);
03066 }
03067 }
03068
03069
03070 if( y_middle > 0 )
03071 {
03072 ASImage *sides ;
03073 ASImageDecoder *imdec_sides ;
03074 sides = scale_asimage2( asv, src, 0, slice_y_start,
03075 src->width, slice_y_end-slice_y_start,
03076 src->width, y_middle, ASA_ASImage, 0, quality );
03077 imdec_sides = start_image_decoding(asv, sides, SCL_DO_ALL, 0, 0, 0, 0, NULL) ;
03078
03079 if( x_middle > 0 )
03080 {
03081 tmp = scale_asimage2( asv, sides, slice_x_start, 0,
03082 slice_x_end-slice_x_start, y_middle,
03083 x_middle, y_middle, ASA_ASImage, 0, quality );
03084
03085
03086 imdec_scaled = start_image_decoding(asv, tmp, SCL_DO_ALL, 0, 0, 0, 0, NULL) ;
03087 for( y1 = 0 ; y1 < y_middle ; ++y1 )
03088 {
03089 imdec_sides->decode_image_scanline( imdec_sides );
03090 imdec_scaled->decode_image_scanline( imdec_scaled );
03091 slice_scanline( out_buf, &(imdec_sides->buffer), slice_x_start, slice_x_end, &(imdec_scaled->buffer) );
03092 imout->output_image_scanline( imout, out_buf, 1);
03093 }
03094 stop_image_decoding( &imdec_scaled );
03095 destroy_asimage( &tmp );
03096
03097 }else
03098 {
03099 for( y1 = 0 ; y1 < y_middle ; ++y1 )
03100 {
03101 imdec_sides->decode_image_scanline( imdec_sides );
03102 imout->output_image_scanline( imout, &(imdec->buffer), 1);
03103 }
03104 }
03105 stop_image_decoding( &imdec_sides );
03106 destroy_asimage( &sides );
03107 }
03108
03109
03110
03111 y2 = max(max_y2,(int)slice_y_start) ;
03112 y1 = src->height - tail ;
03113 imout->next_line = y2 ;
03114 imdec->next_line = y1 ;
03115 max_y = src->height ;
03116 if( y2 + max_y - y1 > dst->height )
03117 max_y = dst->height + y1 - y2 ;
03118 LOCAL_DEBUG_OUT( "y1 = %d, max_y = %d", y1, max_y );
03119 if( x_middle > 0 )
03120 {
03121 tmp = scale_asimage2( asv, src, slice_x_start, y1,
03122 slice_x_end-slice_x_start, src->height-y1,
03123 x_middle, src->height-y1, ASA_ASImage, 0, quality );
03124 imdec_scaled = start_image_decoding(asv, tmp, SCL_DO_ALL, 0, 0, 0, 0, NULL) ;
03125 for( ; y1 < max_y ; ++y1 )
03126 {
03127 imdec->decode_image_scanline( imdec );
03128 imdec_scaled->decode_image_scanline( imdec_scaled );
03129 slice_scanline( out_buf, &(imdec->buffer), slice_x_start, slice_x_end, &(imdec_scaled->buffer) );
03130 imout->output_image_scanline( imout, out_buf, 1);
03131 }
03132 stop_image_decoding( &imdec_scaled );
03133 destroy_asimage( &tmp );
03134 }else
03135 {
03136 for( ; y1 < max_y ; ++y1 )
03137 {
03138 imdec->decode_image_scanline( imdec );
03139 imout->output_image_scanline( imout, &(imdec->buffer), 1);
03140 }
03141 }
03142
03143 }else
03144 {
03145 imout->tiling_step = 0;
03146 LOCAL_DEBUG_OUT( "max_y = %d", max_y );
03147 for( y1 = 0 ; y1 < max_y ; ++y1 )
03148 {
03149 imdec->decode_image_scanline( imdec );
03150 slice_scanline( out_buf, &(imdec->buffer), slice_x_start, slice_x_end, NULL );
03151 imout->output_image_scanline( imout, out_buf, 1);
03152 }
03153
03154 imout->tiling_step = (int)slice_y_end - (int)slice_y_start;
03155 max_y = min(slice_y_end, max_y2);
03156 LOCAL_DEBUG_OUT( "y1 = %d, max_y = %d, tiling_step = %d", y1, max_y, imout->tiling_step );
03157 for( ; y1 < max_y ; ++y1 )
03158 {
03159 imdec->decode_image_scanline( imdec );
03160 slice_scanline( out_buf, &(imdec->buffer), slice_x_start, slice_x_end, NULL );
03161 imout->output_image_scanline( imout, out_buf, 1);
03162 }
03163
03164
03165 imout->tiling_step = 0;
03166 imout->next_line = y2 = max(max_y2,(int)slice_y_start) ;
03167 imdec->next_line = y1 = src->height - tail ;
03168 max_y = src->height ;
03169 if( y2 + max_y - y1 > dst->height )
03170 max_y = dst->height + y1 - y2 ;
03171 LOCAL_DEBUG_OUT( "y1 = %d, max_y = %d", y1, max_y );
03172 for( ; y1 < max_y ; ++y1 )
03173 {
03174 imdec->decode_image_scanline( imdec );
03175 slice_scanline( out_buf, &(imdec->buffer), slice_x_start, slice_x_end, NULL );
03176 imout->output_image_scanline( imout, out_buf, 1);
03177 }
03178 }
03179 free_scanline( out_buf, False );
03180 stop_image_output( &imout );
03181 }
03182 stop_image_decoding( &imdec );
03183
03184 SHOW_TIME("", started);
03185 return dst;
03186 }
03187
03188 ASImage*
03189 slice_asimage( ASVisual *asv, ASImage *src,
03190 int slice_x_start, int slice_x_end,
03191 int slice_y_start, int slice_y_end,
03192 int to_width, int to_height,
03193 ASAltImFormats out_format,
03194 unsigned int compression_out, int quality )
03195 {
03196
03197 return slice_asimage2( asv, src, slice_x_start, slice_x_end,
03198 slice_y_start, slice_y_end, to_width, to_height,
03199 False, out_format, compression_out, quality );
03200 }
03201
03202
03203 ASImage *
03204 pixelize_asimage( ASVisual *asv, ASImage *src,
03205 int clip_x, int clip_y, int clip_width, int clip_height,
03206 int pixel_width, int pixel_height,
03207 ASAltImFormats out_format, unsigned int compression_out, int quality )
03208 {
03209 ASImage *dst = NULL ;
03210 ASImageDecoder *imdec ;
03211 ASImageOutput *imout ;
03212 START_TIME(started);
03213
03214 if( asv == NULL ) asv = &__transform_fake_asv ;
03215
03216 if (src== NULL)
03217 return NULL;
03218
03219 if (clip_width <= 0)
03220 clip_width = src->width;
03221 if (clip_height <= 0)
03222 clip_height = src->height;
03223
03224 if (pixel_width <= 0)
03225 pixel_width = 1;
03226 else if (pixel_width > clip_width)
03227 pixel_width = clip_width;
03228
03229 if (pixel_height <= 0)
03230 pixel_height = 1;
03231 else if (pixel_height > clip_height)
03232 pixel_height = clip_height;
03233
03234 LOCAL_DEBUG_CALLER_OUT( "src = %p, offset_x = %d, offset_y = %d, to_width = %d, to_height = %d, pixel_width = %d, pixel_height = %d", src, clip_x, clip_y, clip_width, clip_height, pixel_width, pixel_height );
03235 if( (imdec = start_image_decoding(asv, src, SCL_DO_ALL, clip_x, clip_y, clip_width, 0, NULL)) == NULL )
03236 {
03237 LOCAL_DEBUG_OUT( "failed to start image decoding%s", "");
03238 return NULL;
03239 }
03240
03241 dst = create_destination_image( clip_width, clip_height, out_format, compression_out, src->back_color );
03242
03243 if((imout = start_image_output( asv, dst, out_format, 0, quality)) == NULL )
03244 {
03245 LOCAL_DEBUG_OUT( "failed to start image output%s", "");
03246 destroy_asimage( &dst );
03247 }else
03248 {
03249 int y, max_y = clip_height;
03250 LOCAL_DEBUG_OUT("pixelizing actually...%s", "");
03251
03252 if( pixel_width > 1 || pixel_height > 1 )
03253 {
03254 int pixel_h_count = (clip_width+pixel_width-1)/pixel_width;
03255 ASScanline *pixels = prepare_scanline( pixel_h_count, 0, NULL, asv->BGR_mode );
03256 ASScanline *out_buf = prepare_scanline( clip_width, 0, NULL, asv->BGR_mode );
03257 int lines_count = 0;
03258
03259 out_buf->flags = SCL_DO_ALL;
03260
03261 for( y = 0 ; y < max_y ; y++ )
03262 {
03263 int pixel_x = 0, x ;
03264 imdec->decode_image_scanline( imdec );
03265 for (x = 0; x < clip_width; x += pixel_width)
03266 {
03267 int xx = x+pixel_width;
03268 ASScanline *srcsl = &(imdec->buffer);
03269
03270 if (xx > clip_width)
03271 xx = clip_width;
03272
03273 while ( --xx >= x)
03274 {
03275 pixels->red[pixel_x] += srcsl->red[xx];
03276 pixels->green[pixel_x] += srcsl->green[xx];
03277 pixels->blue[pixel_x] += srcsl->blue[xx];
03278 pixels->alpha[pixel_x] += srcsl->alpha[xx];
03279 }
03280 ++pixel_x;
03281 }
03282 if (++lines_count >= pixel_height || y == max_y-1)
03283 {
03284 pixel_x = 0;
03285
03286 for (x = 0; x < clip_width; x += pixel_width)
03287 {
03288 int xx = (x + pixel_width> clip_width) ? clip_width : x + pixel_width;
03289 int count = (xx - x) * lines_count;
03290 CARD32 r = pixels->red [pixel_x] / count;
03291 CARD32 g = pixels->green [pixel_x] / count;
03292 CARD32 b = pixels->blue [pixel_x] / count;
03293 CARD32 a = pixels->alpha [pixel_x] / count;
03294
03295 pixels->red [pixel_x] = 0;
03296 pixels->green [pixel_x] = 0;
03297 pixels->blue [pixel_x] = 0;
03298 pixels->alpha [pixel_x] = 0;
03299
03300 if (xx > clip_width)
03301 xx = clip_width;
03302
03303 while ( --xx >= x)
03304 {
03305 out_buf->red[xx] = r;
03306 out_buf->green[xx] = g;
03307 out_buf->blue[xx] = b;
03308 out_buf->alpha[xx] = a;
03309 }
03310
03311 ++pixel_x;
03312 }
03313 while (lines_count--)
03314 imout->output_image_scanline( imout, out_buf, 1);
03315 lines_count = 0;
03316 }
03317 }
03318 free_scanline( out_buf, False );
03319 free_scanline( pixels, False );
03320 }else
03321 for( y = 0 ; y < max_y ; y++ )
03322 {
03323 imdec->decode_image_scanline( imdec );
03324 imout->output_image_scanline( imout, &(imdec->buffer), 1);
03325 }
03326 stop_image_output( &imout );
03327 }
03328 stop_image_decoding( &imdec );
03329
03330 SHOW_TIME("", started);
03331 return dst;
03332 }
03333
03334 ASImage *
03335 color2alpha_asimage( ASVisual *asv, ASImage *src,
03336 int clip_x, int clip_y, int clip_width, int clip_height,
03337 ARGB32 color,
03338 ASAltImFormats out_format, unsigned int compression_out, int quality )
03339 {
03340 ASImage *dst = NULL ;
03341 ASImageDecoder *imdec ;
03342 ASImageOutput *imout ;
03343 START_TIME(started);
03344
03345 if( asv == NULL ) asv = &__transform_fake_asv ;
03346
03347 if (src== NULL)
03348 return NULL;
03349
03350 if (clip_width <= 0)
03351 clip_width = src->width;
03352 if (clip_height <= 0)
03353 clip_height = src->height;
03354
03355
03356 LOCAL_DEBUG_CALLER_OUT( "src = %p, offset_x = %d, offset_y = %d, to_width = %d, to_height = %d, color = #%8.8x", src, clip_x, clip_y, clip_width, clip_height, color );
03357 if( (imdec = start_image_decoding(asv, src, SCL_DO_ALL, clip_x, clip_y, clip_width, 0, NULL)) == NULL )
03358 {
03359 LOCAL_DEBUG_OUT( "failed to start image decoding%s", "");
03360 return NULL;
03361 }
03362
03363 dst = create_destination_image( clip_width, clip_height, out_format, compression_out, src->back_color );
03364
03365 if((imout = start_image_output( asv, dst, out_format, 0, quality)) == NULL )
03366 {
03367 LOCAL_DEBUG_OUT( "failed to start image output%s", "");
03368 destroy_asimage( &dst );
03369 }else
03370 {
03371 int y, max_y = min(clip_height,(int)src->height);
03372 CARD32 cr = ARGB32_RED8(color);
03373 CARD32 cg = ARGB32_GREEN8(color);
03374 CARD32 cb = ARGB32_BLUE8(color);
03375 #if defined(LOCAL_DEBUG) && !defined(NO_DEBUG_OUTPUT)
03376 fprintf (stderr, "color2alpha():%d: color: red = 0x%8.8X green = 0x%8.8X blue = 0x%8.8X\n", __LINE__, cr, cg, cb);
03377 #endif
03378
03379 for( y = 0 ; y < max_y ; y++ )
03380 {
03381 int x ;
03382 ASScanline *srcsl = &(imdec->buffer);
03383 imdec->decode_image_scanline( imdec );
03384 for (x = 0; x < imdec->buffer.width; ++x)
03385 {
03386 CARD32 r = srcsl->red[x];
03387 CARD32 g = srcsl->green[x];
03388 CARD32 b = srcsl->blue[x];
03389 CARD32 a = srcsl->alpha[x];
03390
03391 {
03392 CARD32 aa = a, ar, ag, ab;
03393
03394 #define AS_MIN_CHAN_VAL 2
03395 #define AS_MAX_CHAN_VAL 255
03396 #define MAKE_CHAN_ALPHA_FROM_COL(chan) \
03397 ((c##chan < AS_MIN_CHAN_VAL)? (chan)<<4 : \
03398 ((chan > c##chan)? ((chan - c##chan)<<12) / (AS_MAX_CHAN_VAL - c##chan) : \
03399 ((c##chan - chan)<<12) / c##chan))
03400
03401 ar = MAKE_CHAN_ALPHA_FROM_COL(r);
03402 ag = MAKE_CHAN_ALPHA_FROM_COL(g);
03403 ab = MAKE_CHAN_ALPHA_FROM_COL(b);
03404 #undef MAKE_CHAN_ALPHA_FROM_COL
03405
03406 #if defined(LOCAL_DEBUG) && !defined(NO_DEBUG_OUTPUT)
03407 fprintf (stderr, "color2alpha():%d: src(argb): %8.8X %8.8X %8.8X %8.8X; ", __LINE__, a, r, g, b);
03408 #endif
03409 a = (ar > ag) ? max(ar, ab) : max(ag,ab);
03410 #if defined(LOCAL_DEBUG) && !defined(NO_DEBUG_OUTPUT)
03411 fprintf (stderr, "alpha: (%8.8X %8.8X %8.8X)->%8.8X; ", ar, ag, ab, a);
03412 #endif
03413
03414 if (a == 0) a = 1;
03415 #if defined(USE_STUPID_GIMP_WAY_DESTROYING_COLORS)
03416 #define APPLY_ALPHA_TO_CHAN(chan) ({int __s = chan; int __c = c##chan; __c += (( __s - __c)*4096)/(int)a;(__c<=0)?0:((__c>=255)?255:__c);})
03417 #else
03418 #define APPLY_ALPHA_TO_CHAN(chan) chan
03419 #endif
03420 srcsl->red[x] = APPLY_ALPHA_TO_CHAN(r);
03421 srcsl->green[x] = APPLY_ALPHA_TO_CHAN(g);
03422 srcsl->blue[x] = APPLY_ALPHA_TO_CHAN(b);
03423 #undef APPLY_ALPHA_TO_CHAN
03424 a = a*aa>>12;
03425 srcsl->alpha[x] = (a>255)?255:a;
03426
03427 #if defined(LOCAL_DEBUG) && !defined(NO_DEBUG_OUTPUT)
03428 fprintf (stderr, "result: %8.8X %8.8X %8.8X %8.8X.\n", src->alpha[x], src->red[x], src->green[x], src->blue[x]);
03429 #endif
03430
03431 }
03432
03433 }
03434 imout->output_image_scanline( imout, srcsl, 1);
03435 }
03436 stop_image_output( &imout );
03437 }
03438 stop_image_decoding( &imdec );
03439
03440 SHOW_TIME("", started);
03441 return dst;
03442 }
03443
03444
03445
03446
03447
03448