00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifdef _WIN32
00022 #include "win32/config.h"
00023 #else
00024 #include "config.h"
00025 #endif
00026
00027
00028
00029
00030 #ifdef HAVE_STDLIB_H
00031 #include <stdlib.h>
00032 #endif
00033 #include <string.h>
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
00045 #ifdef _WIN32
00046 # include "win32/afterbase.h"
00047 #else
00048 # include "afterbase.h"
00049 #endif
00050 #include "asimage.h"
00051 #include "xcf.h"
00052
00053 static XcfProperty *read_xcf_props( FILE *fp );
00054 static XcfListElem *read_xcf_list_offsets( FILE *fp, size_t elem_size );
00055 static void read_xcf_layers( XcfImage *xcf_im, FILE *fp, XcfLayer *head );
00056 static void read_xcf_channels( XcfImage *xcf_im, FILE *fp, XcfChannel *head );
00057 static XcfHierarchy*read_xcf_hierarchy( XcfImage *xcf_im, FILE *fp, CARD8 opacity, ARGB32 colormask );
00058 static void read_xcf_levels( XcfImage *xcf_im, FILE *fp, XcfLevel *head );
00059 static void read_xcf_tiles( XcfImage *xcf_im, FILE *fp, XcfTile *head );
00060 static void read_xcf_tiles_rle( XcfImage *xcf_im, FILE *fp, XcfTile *head );
00061
00062 static size_t
00063 xcf_read8 (FILE *fp, CARD8 *data, int count)
00064 {
00065 size_t total = count;
00066
00067 while (count > 0)
00068 {
00069 int bytes = fread ((char*) data, sizeof (char), count, fp);
00070 if( bytes <= 0 )
00071 break;
00072 count -= bytes;
00073 data += bytes;
00074 }
00075 return total;
00076 }
00077
00078 static size_t
00079 xcf_read32 (FILE *fp, CARD32 *data, int count)
00080 {
00081 size_t total = count;
00082 if( count > 0 )
00083 {
00084 CARD8 *raw = (CARD8*)data ;
00085 total = xcf_read8( fp, raw, count<<2 )>>2;
00086 count = 0 ;
00087 #ifndef WORDS_BIGENDIAN
00088 while( count < (int)total )
00089 {
00090 data[count] = (raw[0]<<24)|(raw[1]<<16)|(raw[2]<<8)|raw[3];
00091 ++count ;
00092 raw += 4 ;
00093 }
00094 #endif
00095 }
00096 return total;
00097 }
00098
00099 static void
00100 xcf_skip_string (FILE *fp)
00101 {
00102 CARD32 size = 0;
00103 if( xcf_read32 (fp, &size, 1)< 1 )
00104 return;
00105 if( size > 0 )
00106 {
00107 fseek(fp, size, SEEK_CUR );
00108 }
00109 }
00110 void print_xcf_layers( char* prompt, XcfLayer *head );
00111
00112 XcfImage *
00113 read_xcf_image( FILE *fp )
00114 {
00115 XcfImage *xcf_im = NULL ;
00116 XcfProperty *prop ;
00117
00118 if( fp )
00119 {
00120 int i ;
00121 char sig[XCF_SIGNATURE_FULL_LEN+1] ;
00122 if( xcf_read8( fp, (unsigned char*)&(sig[0]),XCF_SIGNATURE_FULL_LEN ) >= XCF_SIGNATURE_FULL_LEN )
00123 {
00124 if( mystrncasecmp( sig, XCF_SIGNATURE, XCF_SIGNATURE_LEN) == 0 )
00125 {
00126 xcf_im = safecalloc( 1, sizeof(XcfImage));
00127 if( mystrncasecmp( &(sig[XCF_SIGNATURE_LEN+1]), "file", 4 ) == 0 )
00128 xcf_im->version = 0 ;
00129 else
00130 xcf_im->version = atoi(&(sig[XCF_SIGNATURE_LEN+1]));
00131 if( xcf_read32( fp, &(xcf_im->width), 3 ) < 3 )
00132 {
00133 free( xcf_im );
00134 xcf_im = NULL ;
00135 }
00136 }
00137 }
00138 if( xcf_im == NULL )
00139 {
00140 show_error( "invalid .xcf file format - not enough data to read" );
00141 return NULL ;
00142 }
00143
00144 xcf_im->properties = read_xcf_props( fp );
00145 for( prop = xcf_im->properties ; prop != NULL ; prop = prop->next )
00146 {
00147 if( prop->id == XCF_PROP_COLORMAP )
00148 {
00149 register int i ;
00150 CARD32 n = *((CARD32*)(prop->data)) ;
00151 n = as_ntohl(n);
00152 xcf_im->num_cols = n ;
00153 xcf_im->colormap = safemalloc( MAX(n*3,(CARD32)XCF_COLORMAP_SIZE));
00154 if( xcf_im->version == 0 )
00155 {
00156 for( i = 0 ; i < (int)n ; i++ )
00157 {
00158 xcf_im->colormap[i*3] = i ;
00159 xcf_im->colormap[i*3+1] = i ;
00160 xcf_im->colormap[i*3+2] = i ;
00161 }
00162 }else
00163 memcpy( xcf_im->colormap, prop->data+4, MIN(prop->len-4,n));
00164 }else if( prop->id == XCF_PROP_COMPRESSION )
00165 xcf_im->compression = *(prop->data);
00166 }
00167 xcf_im->layers = (XcfLayer*) read_xcf_list_offsets( fp, sizeof(XcfLayer) );
00168 xcf_im->channels = (XcfChannel*)read_xcf_list_offsets( fp, sizeof(XcfChannel));
00169 for( i = 0 ; i < XCF_TILE_HEIGHT ; i++ )
00170 prepare_scanline(xcf_im->width,0,&(xcf_im->scanline_buf[i]), False );
00171
00172 if( xcf_im->layers )
00173 read_xcf_layers( xcf_im, fp, xcf_im->layers );
00174 if( xcf_im->channels )
00175 read_xcf_channels( xcf_im, fp, xcf_im->channels );
00176 }
00177 return xcf_im;
00178 }
00179
00180
00181
00182 void
00183 print_xcf_properties( char* prompt, XcfProperty *prop )
00184 {
00185 register int i = 0 ;
00186 while( prop )
00187 {
00188 fprintf( stderr, "%s.properties[%d] = %p\n", prompt, i, prop );
00189 fprintf( stderr, "%s.properties[%d].id = %ld\n", prompt, i, (long)prop->id );
00190 fprintf( stderr, "%s.properties[%d].size = %ld\n", prompt, i, (long)prop->len );
00191 if( prop->len > 0 )
00192 {
00193 register unsigned int k ;
00194 fprintf( stderr, "%s.properties[%d].data = ", prompt, i );
00195 for( k = 0 ; k < prop->len ; k++ )
00196 fprintf( stderr, "%2.2X ", prop->data[k] );
00197 fprintf( stderr, "\n" );
00198 }
00199 prop = prop->next ;
00200 ++i ;
00201 }
00202 }
00203
00204 void
00205 print_xcf_hierarchy( char* prompt, XcfHierarchy *h )
00206 {
00207 if( h )
00208 {
00209 XcfLevel *level = h->levels ;
00210 int i = 0 ;
00211
00212 fprintf( stderr, "%s.hierarchy.width = %ld\n", prompt, (long)h->width );
00213 fprintf( stderr, "%s.hierarchy.height = %ld\n", prompt,(long) h->height );
00214 fprintf( stderr, "%s.hierarchy.bpp = %ld\n", prompt, (long)h->bpp );
00215 while( level )
00216 {
00217 XcfTile *tile = level->tiles ;
00218 int k = 0 ;
00219 fprintf( stderr, "%s.hierarchy.level[%d].offset = %ld\n", prompt, i, (long)level->offset );
00220 fprintf( stderr, "%s.hierarchy.level[%d].width = %ld\n", prompt, i, (long)level->width );
00221 fprintf( stderr, "%s.hierarchy.level[%d].height = %ld\n", prompt, i, (long)level->height );
00222 while ( tile )
00223 {
00224 fprintf( stderr, "%s.hierarchy.level[%d].tile[%d].offset = %ld\n", prompt, i, k, (long)tile->offset );
00225 fprintf( stderr, "%s.hierarchy.level[%d].tile[%d].estimated_size = %ld\n", prompt, i, k, (long)tile->estimated_size );
00226 tile = tile->next ;
00227 ++k ;
00228 }
00229 level = level->next ;
00230 ++i ;
00231 }
00232 }
00233 }
00234
00235 void
00236 print_xcf_channels( char* prompt, XcfChannel *head, Bool mask )
00237 {
00238 register int i = 0 ;
00239 char p[256] ;
00240 while( head )
00241 {
00242 if( mask )
00243 sprintf( p, "%s.mask", prompt );
00244 else
00245 sprintf( p, "%s.channel[%d]", prompt, i );
00246
00247 if( head->offset > 0 )
00248 fprintf( stderr, "%s.offset = %ld\n", p, (long)head->offset );
00249 fprintf( stderr, "%s.width = %ld\n" , p,(long) head->width );
00250 fprintf( stderr, "%s.height = %ld\n", p, (long)head->height );
00251 print_xcf_properties( p, head->properties );
00252 fprintf( stderr, "%s.opacity = %ld\n", p, (long)head->opacity );
00253 fprintf( stderr, "%s.visible = %d\n" , p, head->visible );
00254 fprintf( stderr, "%s.color = #%lX\n" , p, (long)head->color );
00255 fprintf( stderr, "%s.hierarchy_offset = %ld\n", p, (long)head->hierarchy_offset );
00256 print_xcf_hierarchy( p, head->hierarchy );
00257
00258 head = head->next ;
00259 ++i ;
00260 }
00261 }
00262
00263 void
00264 print_xcf_layers( char* prompt, XcfLayer *head )
00265 {
00266 register int i = 0 ;
00267 char p[256] ;
00268 while( head )
00269 {
00270 fprintf( stderr, "%s.layer[%d] = %p\n", prompt, i, head );
00271 fprintf( stderr, "%s.layer[%d].offset = %ld\n", prompt, i, (long)head->offset );
00272 fprintf( stderr, "%s.layer[%d].width = %ld\n", prompt, i, (long)head->width );
00273 fprintf( stderr, "%s.layer[%d].height = %ld\n", prompt, i, (long)head->height );
00274 fprintf( stderr, "%s.layer[%d].type = %ld\n", prompt, i, (long)head->type );
00275 sprintf( p, "%s.layer[%d]", prompt, i );
00276 print_xcf_properties( p, head->properties );
00277 fprintf( stderr, "%s.layer[%d].opacity = %ld\n", prompt, i, (long)head->opacity );
00278 fprintf( stderr, "%s.layer[%d].visible = %d\n", prompt, i, head->visible );
00279 fprintf( stderr, "%s.layer[%d].preserve_transparency = %d\n", prompt, i, head->preserve_transparency );
00280 fprintf( stderr, "%s.layer[%d].mode = %ld\n" , prompt, i, (long)head->mode );
00281 fprintf( stderr, "%s.layer[%d].offset_x = %ld\n", prompt, i, (long)head->offset_x );
00282 fprintf( stderr, "%s.layer[%d].offset_y = %ld\n", prompt, i, (long)head->offset_y );
00283
00284 fprintf( stderr, "%s.layer[%d].hierarchy_offset = %ld\n", prompt, i, (long)head->hierarchy_offset );
00285 print_xcf_hierarchy( p, head->hierarchy );
00286 fprintf( stderr, "%s.layer[%d].mask_offset = %ld\n", prompt, i, (long)head->mask_offset );
00287 print_xcf_channels( p, head->mask, True );
00288
00289 head = head->next ;
00290 ++i ;
00291 }
00292 }
00293
00294 void
00295 print_xcf_image( XcfImage *xcf_im )
00296 {
00297 if( xcf_im )
00298 {
00299 fprintf( stderr, "XcfImage.version = %d\n", xcf_im->version );
00300 fprintf( stderr, "XcfImage.width = %ld\nXcfImage.height = %ld\nXcfImage.type = %ld\n",
00301 (long)xcf_im->width, (long)xcf_im->height, (long)xcf_im->type );
00302 fprintf( stderr, "XcfImage.num_cols = %ld\n", (long)xcf_im->num_cols );
00303 fprintf( stderr, "XcfImage.compression = %d\n", xcf_im->compression );
00304 print_xcf_properties( "XcfImage", xcf_im->properties );
00305 print_xcf_layers( "XcfImage", xcf_im->layers );
00306 print_xcf_channels( "XcfImage", xcf_im->channels, False );
00307 }
00308 }
00309
00310
00311
00312
00313 void
00314 free_xcf_properties( XcfProperty *head )
00315 {
00316 while( head )
00317 {
00318 XcfProperty *next = head->next ;
00319 if( head->len > 0 && head->data && head->data != (CARD8*)&(head->buffer[0]))
00320 free( head->data );
00321 free( head );
00322 head = next ;
00323 }
00324 }
00325
00326 void
00327 free_xcf_hierarchy( XcfHierarchy *hierarchy )
00328 {
00329 if( hierarchy )
00330 {
00331 register XcfLevel *level = hierarchy->levels;
00332 while( level )
00333 {
00334 XcfLevel *next = level->next ;
00335 while( level->tiles )
00336 {
00337 XcfTile *next = level->tiles->next ;
00338 if( level->tiles->data )
00339 free( level->tiles->data );
00340 free( level->tiles );
00341 level->tiles = next ;
00342 }
00343 free( level );
00344 level = next ;
00345 }
00346 if( hierarchy->image )
00347 destroy_asimage( &hierarchy->image );
00348 free( hierarchy );
00349 }
00350 }
00351
00352 void
00353 free_xcf_channels( XcfChannel *head )
00354 {
00355 while( head )
00356 {
00357 XcfChannel *next = head->next ;
00358 if( head->properties )
00359 free_xcf_properties( head->properties );
00360 if( head->hierarchy )
00361 free_xcf_hierarchy( head->hierarchy );
00362 free( head );
00363 head = next ;
00364 }
00365 }
00366
00367 void
00368 free_xcf_layers( XcfLayer *head )
00369 {
00370 while( head )
00371 {
00372 XcfLayer *next = head->next ;
00373 if( head->properties )
00374 free_xcf_properties( head->properties );
00375 if( head->hierarchy )
00376 free_xcf_hierarchy( head->hierarchy );
00377 free_xcf_channels( head->mask );
00378 free( head );
00379 head = next ;
00380 }
00381 }
00382
00383 void
00384 free_xcf_image( XcfImage *xcf_im )
00385 {
00386 if( xcf_im )
00387 {
00388 int i ;
00389
00390 if( xcf_im->properties )
00391 free_xcf_properties( xcf_im->properties );
00392 if( xcf_im->colormap )
00393 free( xcf_im->colormap );
00394 if( xcf_im->layers )
00395 free_xcf_layers( xcf_im->layers );
00396 if( xcf_im->channels )
00397 free_xcf_channels( xcf_im->channels );
00398
00399 for( i = 0 ; i < XCF_TILE_HEIGHT ; i++ )
00400 free_scanline( &(xcf_im->scanline_buf[i]), True );
00401 }
00402 }
00403
00404
00405
00406
00407
00408 static XcfProperty *
00409 read_xcf_props( FILE *fp )
00410 {
00411 XcfProperty *head = NULL;
00412 XcfProperty **tail = &head;
00413 CARD32 prop_vals[2] ;
00414
00415 do
00416 {
00417 if( xcf_read32( fp, &(prop_vals[0]), 2 ) < 2 )
00418 break;
00419 if( prop_vals[0] != 0 )
00420 {
00421 *tail = safecalloc( 1, sizeof(XcfProperty));
00422 (*tail)->id = prop_vals[0] ;
00423 (*tail)->len = prop_vals[1] ;
00424 if( (*tail)->len > 0 )
00425 {
00426 if( (*tail)->len <= 8 )
00427 (*tail)->data = (CARD8*)&((*tail)->buffer[0]) ;
00428 else
00429 (*tail)->data = safemalloc( (*tail)->len );
00430 xcf_read8( fp, (*tail)->data, (*tail)->len );
00431 }
00432 tail = &((*tail)->next);
00433 }
00434 }while( prop_vals[0] != 0 );
00435 return head;
00436 }
00437
00438 static XcfListElem *
00439 read_xcf_list_offsets( FILE *fp, size_t elem_size )
00440 {
00441 XcfListElem *head = NULL ;
00442 XcfListElem **tail = &head ;
00443 CARD32 offset ;
00444
00445 do
00446 {
00447 if( xcf_read32( fp, &offset, 1 ) < 1 )
00448 break;
00449 if( offset != 0 )
00450 {
00451 *tail = safecalloc( 1, elem_size);
00452 (*tail)->any.offset = offset ;
00453 tail = (XcfListElem**)&((*tail)->any.next);
00454 }
00455 }while( offset != 0 );
00456 return head;
00457 }
00458
00459 static void
00460 read_xcf_layers( XcfImage *xcf_im, FILE *fp, XcfLayer *head )
00461 {
00462 XcfProperty *prop ;
00463 while( head )
00464 {
00465 fseek( fp, head->offset, SEEK_SET );
00466 if( xcf_read32( fp, &(head->width), 3 ) < 3 )
00467 {
00468 head->width = 0 ;
00469 head->height = 0 ;
00470 head->type = 0 ;
00471 continue;
00472 }
00473 xcf_skip_string(fp);
00474 head->properties = read_xcf_props( fp );
00475 for( prop = head->properties ; prop != NULL ; prop = prop->next )
00476 {
00477 CARD32 *pd = (CARD32*)(prop->data) ;
00478 if( prop->id == XCF_PROP_FLOATING_SELECTION )
00479 {
00480 xcf_im->floating_selection = head;
00481 }else if( prop->id == XCF_PROP_OPACITY && pd)
00482 {
00483 head->opacity = as_ntohl(*pd);
00484 }else if( prop->id == XCF_PROP_VISIBLE && pd)
00485 {
00486 head->visible = ( *pd !=0);
00487 }else if( prop->id == XCF_PROP_PRESERVE_TRANSPARENCY && pd)
00488 {
00489 head->preserve_transparency = (*pd!=0);
00490 }else if( prop->id == XCF_PROP_MODE && pd)
00491 {
00492 head->mode = as_ntohl(*pd);
00493 }else if( prop->id == XCF_PROP_OFFSETS && pd)
00494 {
00495 head->offset_x = as_ntohl(pd[0]);
00496 head->offset_y = as_ntohl(pd[1]);
00497 }
00498 }
00499
00500 if( xcf_im->floating_selection != head && head->visible )
00501 {
00502 if( xcf_read32( fp, &(head->hierarchy_offset), 2 ) < 2 )
00503 {
00504 head->hierarchy_offset = 0 ;
00505 head->mask_offset = 0 ;
00506 }
00507 if( head->hierarchy_offset > 0 )
00508 {
00509 fseek( fp, head->hierarchy_offset, SEEK_SET );
00510 head->hierarchy = read_xcf_hierarchy( xcf_im, fp, (CARD8)head->opacity, 0xFFFFFFFF );
00511 }
00512 if( head->mask_offset > 0 )
00513 {
00514 head->mask = safecalloc( 1, sizeof(XcfChannel) );
00515 head->mask->offset = head->mask_offset;
00516 read_xcf_channels( xcf_im, fp, head->mask );
00517 }
00518 }
00519
00520 head = head->next ;
00521 }
00522 }
00523
00524 static void
00525 read_xcf_channels( XcfImage *xcf_im, FILE *fp, XcfChannel *head )
00526 {
00527 XcfProperty *prop ;
00528 while( head )
00529 {
00530 fseek( fp, head->offset, SEEK_SET );
00531 if( xcf_read32( fp, &(head->width), 2 ) < 2 )
00532 {
00533 head->width = 0 ;
00534 head->height = 0 ;
00535 continue;
00536 }
00537 xcf_skip_string(fp);
00538 head->properties = read_xcf_props( fp );
00539 for( prop = head->properties ; prop != NULL ; prop = prop->next )
00540 {
00541 CARD32 *pd = (CARD32*)(prop->data) ;
00542 if( prop->id == XCF_PROP_OPACITY )
00543 {
00544 head->opacity = as_ntohl(*pd);
00545 }else if( prop->id == XCF_PROP_VISIBLE )
00546 {
00547 head->visible = ( *pd !=0);
00548 }else if( prop->id == XCF_PROP_COLOR )
00549 {
00550 head->color = MAKE_ARGB32(0xFF,prop->data[0],prop->data[1],prop->data[2]);
00551 }
00552 }
00553
00554 if( head->visible )
00555 {
00556 if( xcf_read32( fp, &(head->hierarchy_offset), 1 ) < 1 )
00557 head->hierarchy_offset = 0 ;
00558
00559 if( head->hierarchy_offset > 0 )
00560 {
00561 fseek( fp, head->hierarchy_offset, SEEK_SET );
00562 head->hierarchy = read_xcf_hierarchy( xcf_im, fp, (CARD8)head->opacity, head->color );
00563 }
00564 }
00565 head = head->next ;
00566 }
00567 }
00568
00569 typedef void (*decode_xcf_tile_func)( FILE *fp, XcfTile *tile, int bpp,
00570 ASScanline *buf, CARD8* tile_buf, int offset_x, int offset_y, int width, int height);
00571
00572
00573 void decode_xcf_tile( FILE *fp, XcfTile *tile, int bpp,
00574 ASScanline *buf, CARD8* tile_buf, int offset_x, int offset_y, int width, int height);
00575 void decode_xcf_tile_rle( FILE *fp, XcfTile *tile, int bpp,
00576 ASScanline *buf, CARD8* tile_buf, int offset_x, int offset_y, int width, int height);
00577 Bool fix_xcf_image_line( ASScanline *buf, int bpp, unsigned int width, CARD8 *cmap,
00578 CARD8 opacity, ARGB32 color );
00579
00580
00581 static XcfHierarchy*
00582 read_xcf_hierarchy( XcfImage *xcf_im, FILE *fp, CARD8 opacity, ARGB32 colormask )
00583 {
00584 XcfHierarchy *h = NULL ;
00585 CARD32 h_props[3] ;
00586
00587 if( xcf_read32( fp, &(h_props[0]), 3 ) < 3 )
00588 return NULL;
00589 h = safecalloc(1, sizeof(XcfHierarchy));
00590
00591 h->width = h_props[0] ;
00592 h->height = h_props[1] ;
00593 h->bpp = h_props[2] ;
00594
00595 h->levels = (XcfLevel*)read_xcf_list_offsets( fp, sizeof(XcfLevel));
00596 if( h->levels )
00597 {
00598 read_xcf_levels( xcf_im, fp, h->levels );
00599
00600
00601 if( h->levels->width == h->width && h->levels->height == h->height )
00602 {
00603
00604
00605 int height_left = h->height ;
00606 ASScanline *buf = &(xcf_im->scanline_buf[0]) ;
00607 XcfTile *tile = h->levels->tiles ;
00608 decode_xcf_tile_func decode_func = decode_xcf_tile ;
00609 CARD8 *tile_buf = &(xcf_im->tile_buf[0]);
00610 int i;
00611
00612 if( xcf_im->compression == XCF_COMPRESS_RLE )
00613 decode_func = decode_xcf_tile_rle ;
00614 else if( xcf_im->compression != XCF_COMPRESS_NONE )
00615 {
00616 show_error( "XCF image contains information compressed with usupported method." );
00617 return h;
00618 }
00619
00620 if (XCF_TILE_WIDTH < h->width)
00621 tile_buf = safemalloc (h->width*XCF_TILE_HEIGHT*6);
00622
00623 if (xcf_im->width < h->width)
00624 for( i = 0 ; i < XCF_TILE_HEIGHT ; i++ )
00625 {
00626 free_scanline (&(xcf_im->scanline_buf[i]), True);
00627 prepare_scanline (h->width,0,&(xcf_im->scanline_buf[i]), False );
00628 }
00629
00630 h->image = create_asimage( h->width, h->height, 0 );
00631 while( height_left > 0 && tile )
00632 {
00633 int width_left = h->width ;
00634 int max_i, y ;
00635
00636 while( width_left > 0 && tile )
00637 {
00638 fseek( fp, tile->offset, SEEK_SET );
00639 decode_func(fp, tile, h->bpp, buf, tile_buf,
00640 h->width-width_left, h->height-height_left,
00641 MIN(width_left,XCF_TILE_WIDTH), MIN(height_left,XCF_TILE_HEIGHT));
00642
00643 width_left -= XCF_TILE_WIDTH ;
00644 tile = tile->next ;
00645 }
00646
00647
00648 max_i = MIN(height_left,XCF_TILE_HEIGHT);
00649 y = h->height - height_left ;
00650 for( i = 0 ; i < max_i ; i++ )
00651 {
00652 Bool do_alpha = fix_xcf_image_line( &(buf[i]), h->bpp, h->width, xcf_im->colormap, opacity, colormask );
00653 if( h->bpp > 1 || xcf_im->colormap != NULL )
00654 {
00655 asimage_add_line (h->image, IC_RED, buf[i].red , y+i);
00656 asimage_add_line (h->image, IC_GREEN, buf[i].green, y+i);
00657 asimage_add_line (h->image, IC_BLUE, buf[i].blue , y+i);
00658 }
00659 if( do_alpha )
00660 asimage_add_line (h->image, IC_ALPHA, buf[i].alpha, y+i);
00661 }
00662
00663 height_left -= XCF_TILE_HEIGHT ;
00664 }
00665 if (tile_buf != &(xcf_im->tile_buf[0]))
00666 free (tile_buf);
00667 }
00668 }
00669 return h;
00670 }
00671
00672 static void
00673 read_xcf_levels( XcfImage *xcf_im, FILE *fp, XcfLevel *head )
00674 {
00675 while( head )
00676 {
00677 fseek( fp, head->offset, SEEK_SET );
00678 if( xcf_read32( fp, &(head->width), 2 ) < 2 )
00679 {
00680 head->width = 0 ;
00681 head->height = 0 ;
00682 continue;
00683 }
00684
00685 head->tiles = (XcfTile*)read_xcf_list_offsets( fp, sizeof(XcfTile));
00686 if( head->tiles )
00687 {
00688 if( xcf_im->compression == XCF_COMPRESS_NONE )
00689 read_xcf_tiles( xcf_im, fp, head->tiles );
00690 else if( xcf_im->compression == XCF_COMPRESS_RLE )
00691 read_xcf_tiles_rle( xcf_im, fp, head->tiles );
00692 }
00693 head = head->next ;
00694 }
00695 }
00696
00697 static void
00698 read_xcf_tiles( XcfImage *xcf_im, FILE *fp, XcfTile *head )
00699 {
00700 while( head )
00701 {
00702 head->estimated_size = XCF_TILE_WIDTH*XCF_TILE_HEIGHT*4 ;
00703 head = head->next ;
00704 }
00705 }
00706
00707
00708 static void
00709 read_xcf_tiles_rle( XcfImage *xcf_im, FILE *fp, XcfTile *head )
00710 {
00711 while( head )
00712 {
00713 if( head->next )
00714 head->estimated_size = head->next->offset - head->offset ;
00715 else
00716 head->estimated_size = (XCF_TILE_WIDTH*XCF_TILE_HEIGHT)*6 ;
00717 head = head->next ;
00718 }
00719 }
00720
00721
00722
00723 static inline void
00724 store_colors( CARD8 *data, ASScanline *curr_buf, int bpp, int comp, int offset_x, int width )
00725 {
00726 register int i ;
00727 CARD32 *out = NULL;
00728 if( comp+1 < bpp || bpp == 3 )
00729 {
00730 switch( comp )
00731 {
00732 case 0 : out = &(curr_buf->red[offset_x]); break ;
00733 case 1 : out = &(curr_buf->green[offset_x]); break ;
00734 case 2 : out = &(curr_buf->blue[offset_x]); break ;
00735 }
00736 }else
00737 out = &(curr_buf->alpha[offset_x]);
00738
00739 if( out )
00740 for( i = 0 ; i < width ; i++ )
00741 out[i] = data[i] ;
00742 }
00743
00744 void
00745 decode_xcf_tile( FILE *fp, XcfTile *tile, int bpp,
00746 ASScanline *buf, CARD8* tile_buf, int offset_x, int offset_y, int width, int height)
00747 {
00748 int bytes_in, available = width*height ;
00749 int y = 0;
00750 int comp = 0 ;
00751
00752 bytes_in = xcf_read8( fp, tile_buf, available*6 );
00753 while( comp < bpp && bytes_in >= 2 )
00754 {
00755 while ( y < height )
00756 {
00757 store_colors( tile_buf, &(buf[y]), bpp, comp, offset_x, MIN(width,bytes_in));
00758 tile_buf += width ;
00759 bytes_in -= width ;
00760 ++y ;
00761 }
00762 ++comp;
00763 y = 0 ;
00764 }
00765 }
00766
00767
00768 void
00769 decode_xcf_tile_rle( FILE *fp, XcfTile *tile, int bpp,
00770 ASScanline *buf, CARD8* tile_buf, int offset_x, int offset_y, int width, int height)
00771 {
00772 int bytes_in, available = width*height ;
00773 int x = 0, y = 0;
00774 CARD8 tmp[XCF_TILE_WIDTH] ;
00775 int comp = 0 ;
00776
00777 bytes_in = xcf_read8( fp, tile_buf, available*6 );
00778 while( comp < bpp && bytes_in >= 2 )
00779 {
00780 while ( y < height )
00781 {
00782 int len = *tile_buf ;
00783 register int i ;
00784 ++tile_buf;
00785 --bytes_in;
00786 if( len >= 128 )
00787 {
00788 if( len == 128 )
00789 {
00790 len = (((int)tile_buf[0])<<8)+tile_buf[1] ;
00791 tile_buf += 2 ; bytes_in -= 2 ;
00792 }else
00793 len = 255 - (len-1);
00794 if( len > bytes_in )
00795 break;
00796 for( i = 0 ; i < len ; ++i )
00797 {
00798 tmp[x] = tile_buf[i] ;
00799 if( ++x >= width )
00800 {
00801 store_colors( &(tmp[0]), &(buf[y]), bpp, comp, offset_x, width );
00802 x = 0 ;
00803 ++y ;
00804 if( y >= height )
00805 i = len ;
00806 }
00807 }
00808 tile_buf += len ;
00809 bytes_in -= len ;
00810 }else
00811 {
00812 CARD8 v ;
00813 ++len ;
00814 if( len == 128 )
00815 {
00816 len = (((int)tile_buf[0])<<8)+tile_buf[1] ;
00817 tile_buf += 2 ; bytes_in -= 2 ;
00818 }
00819 if( len >= bytes_in )
00820 len = bytes_in-1 ;
00821 v = tile_buf[0] ;
00822 for( i = 0 ; i < len ; ++i)
00823 {
00824 tmp[x] = v ;
00825 if( ++x >= width )
00826 {
00827 store_colors( &(tmp[0]), &(buf[y]), bpp, comp, offset_x, width );
00828 x = 0 ;
00829 ++y ;
00830 if( y >= height )
00831 i = len ;
00832 }
00833 }
00834 ++tile_buf;
00835 --bytes_in;
00836 }
00837 }
00838 ++comp;
00839 x = 0 ;
00840 y = 0 ;
00841 }
00842 }
00843
00844 Bool
00845 fix_xcf_image_line( ASScanline *buf, int bpp, unsigned int width, CARD8 *cmap,
00846 CARD8 opacity, ARGB32 color )
00847 {
00848 register unsigned int i ;
00849 Bool do_alpha = False ;
00850 if( bpp == 1 )
00851 {
00852 if( cmap )
00853 {
00854 for( i = 0 ; i < width ; i++ )
00855 {
00856 int cmap_idx = ((int)(buf->alpha[i]))*3 ;
00857 buf->red[i] = cmap[cmap_idx];
00858 buf->blue[i] = cmap[cmap_idx+1];
00859 buf->green[i] = cmap[cmap_idx+2];
00860 buf->alpha[i] = opacity;
00861 }
00862 }if ( (color&0x00FFFFFF) == 0x00FFFFFF )
00863 for( i = 0 ; i < width ; i++ )
00864 {
00865 buf->red[i] = buf->alpha[i];
00866 buf->blue[i] = buf->alpha[i];
00867 buf->green[i] = buf->alpha[i];
00868 buf->alpha[i] = opacity;
00869 }
00870 else
00871 for( i = 0 ; i < width ; i++ )
00872 buf->alpha[i] = ((int)(buf->alpha[i])*opacity)>>8;
00873 }if( bpp == 2 )
00874 {
00875 for( i = 0 ; i < width ; i++ )
00876 {
00877 if( cmap )
00878 {
00879 int cmap_idx = ((int)(buf->red[i]))*3 ;
00880 buf->red[i] = cmap[cmap_idx];
00881 buf->blue[i] = cmap[cmap_idx+1];
00882 buf->green[i] = cmap[cmap_idx+2];
00883 }else
00884 buf->blue[i] = buf->green[i] = buf->red[i] ;
00885
00886 buf->alpha[i] = ((int)(buf->alpha[i])*opacity)>>8;
00887 if( (buf->alpha[i]&0x00FF) != 0x00FF )
00888 do_alpha = True ;
00889 }
00890 }else
00891 {
00892 for( i = 0 ; i < width ; i++ )
00893 {
00894 buf->alpha[i] = ((int)(buf->alpha[i])*opacity)>>8;
00895 if( (buf->alpha[i]&0x00FF) != 0x00FF )
00896 do_alpha = True ;
00897 }
00898 }
00899 return do_alpha;
00900 }