00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef NO_DEBUG_OUTPUT
00023 #define DEBUG_TIFF
00024 #endif
00025
00026 #undef LOCAL_DEBUG
00027 #undef DO_CLOCKING
00028 #undef DEBUG_TRANSP_GIF
00029
00030 #ifdef _WIN32
00031 #include "win32/config.h"
00032 #else
00033 #include "config.h"
00034 #endif
00035
00036 #ifdef HAVE_PNG
00037
00038 # ifdef HAVE_BUILTIN_PNG
00039 # include "libpng/png.h"
00040 # else
00041 # include <png.h>
00042 # endif
00043 #else
00044 # include <setjmp.h>
00045 # ifdef HAVE_JPEG
00046 # ifdef HAVE_UNISTD_H
00047 # include <unistd.h>
00048 # endif
00049 # include <stdio.h>
00050 # endif
00051 #endif
00052 #ifdef HAVE_JPEG
00053
00054 # undef HAVE_STDLIB_H
00055 # ifndef X_DISPLAY_MISSING
00056 # include <X11/Xmd.h>
00057 # endif
00058 # ifdef HAVE_BUILTIN_JPEG
00059 # include "libjpeg/jpeglib.h"
00060 # else
00061 # include <jpeglib.h>
00062 # endif
00063 #endif
00064
00065 #if TIME_WITH_SYS_TIME
00066 # include <sys/time.h>
00067 # include <time.h>
00068 #else
00069 # if HAVE_SYS_TIME_H
00070 # include <sys/time.h>
00071 # else
00072 # include <time.h>
00073 # endif
00074 #endif
00075 #ifdef HAVE_UNISTD_H
00076 #include <unistd.h>
00077 #endif
00078 #include <stdlib.h>
00079 #ifdef HAVE_STDARG_H
00080 #include <stdarg.h>
00081 #endif
00082 #include <string.h>
00083 #include <ctype.h>
00084
00085
00086 #ifdef const
00087 #undef const
00088 #endif
00089 #ifdef _WIN32
00090 # include "win32/afterbase.h"
00091 #else
00092 # include "afterbase.h"
00093 #endif
00094 #ifdef HAVE_GIF
00095 # ifdef HAVE_BUILTIN_UNGIF
00096 # include "libungif/gif_lib.h"
00097 # else
00098 # include <gif_lib.h>
00099 # endif
00100 #endif
00101 #ifdef HAVE_TIFF
00102 #include <tiff.h>
00103 #include <tiffio.h>
00104 #endif
00105 #ifdef HAVE_SVG
00106 #include <librsvg/rsvg.h>
00107 #endif
00108 #ifdef HAVE_LIBXPM
00109 #ifdef HAVE_LIBXPM_X11
00110 #include <X11/xpm.h>
00111 #else
00112 #include <xpm.h>
00113 #endif
00114 #endif
00115
00116 #include "asimage.h"
00117 #include "imencdec.h"
00118 #include "bmp.h"
00119 #include "scanline.h"
00120 #include "ximage.h"
00121 #include "xcf.h"
00122 #include "xpm.h"
00123 #include "ungif.h"
00124 #include "import.h"
00125 #include "asimagexml.h"
00126 #include "transform.h"
00127
00128 #ifdef jmpbuf
00129 #undef jmpbuf
00130 #endif
00131
00132
00133
00134
00135 static char *locate_image_file( const char *file, char **paths );
00136 static ASImageFileTypes check_image_type( const char *realfilename );
00137
00138 as_image_loader_func as_image_file_loaders[ASIT_Unknown] =
00139 {
00140 xpm2ASImage ,
00141 xpm2ASImage ,
00142 xpm2ASImage ,
00143 png2ASImage ,
00144 jpeg2ASImage,
00145 xcf2ASImage ,
00146 ppm2ASImage ,
00147 ppm2ASImage ,
00148 bmp2ASImage ,
00149 ico2ASImage ,
00150 ico2ASImage ,
00151 gif2ASImage ,
00152 tiff2ASImage,
00153 xml2ASImage ,
00154 svg2ASImage ,
00155 NULL,
00156 tga2ASImage,
00157 NULL,
00158 NULL,
00159 NULL
00160 };
00161
00162 const char *as_image_file_type_names[ASIT_Unknown+1] =
00163 {
00164 "XPM" ,
00165 "Z-compressed XPM" ,
00166 "GZ-compressed XPM" ,
00167 "PNG" ,
00168 "JPEG",
00169 "GIMP Xcf" ,
00170 "PPM" ,
00171 "PNM" ,
00172 "MS Windows Bitmap" ,
00173 "MS Windows Icon" ,
00174 "MS Windows Cursor" ,
00175 "GIF" ,
00176 "TIFF",
00177 "AfterStep XML" ,
00178 "Scalable Vector Graphics (SVG)" ,
00179 "XBM",
00180 "Targa",
00181 "PCX",
00182 "HTML",
00183 "XML",
00184 "Unknown"
00185 };
00186
00187 char *locate_image_file_in_path( const char *file, ASImageImportParams *iparams )
00188 {
00189 int filename_len ;
00190 char *realfilename = NULL, *tmp = NULL ;
00191 register int i;
00192 ASImageImportParams dummy_iparams = {0};
00193
00194 if( iparams == NULL )
00195 iparams = &dummy_iparams ;
00196
00197 if( file )
00198 {
00199 filename_len = strlen(file);
00200 #ifdef _WIN32
00201 for( i = 0 ; iparams->search_path[i] != NULL ; ++i )
00202 unix_path2dos_path( iparams->search_path[i] );
00203 #endif
00204
00205
00206 if( (realfilename = locate_image_file(file, iparams->search_path)) == NULL )
00207 {
00208 tmp = safemalloc( filename_len+3+1);
00209 strcpy(tmp, file);
00210 }
00211 if( realfilename == NULL )
00212 {
00213 strcpy(&(tmp[filename_len]), ".gz");
00214 realfilename = locate_image_file(tmp,iparams->search_path);
00215 }
00216 if( realfilename == NULL )
00217 {
00218 strcpy(&(tmp[filename_len]), ".Z");
00219 realfilename = locate_image_file(tmp,iparams->search_path);
00220 }
00221 if( realfilename == NULL )
00222 {
00223 for( i = filename_len-1 ; i > 0; i-- )
00224 if( !isdigit( (int)tmp[i] ) )
00225 break;
00226 if( i < filename_len-1 && i > 0 )
00227 if( tmp[i] == '.' )
00228 {
00229 iparams->subimage = atoi( &tmp[i+1] );
00230 tmp[i] = '\0';
00231 filename_len = i ;
00232 realfilename = locate_image_file(tmp,iparams->search_path);
00233 if( realfilename == NULL )
00234 {
00235 strcpy(&(tmp[filename_len]), ".gz");
00236 realfilename = locate_image_file(tmp,iparams->search_path);
00237 }
00238 if( realfilename == NULL )
00239 {
00240 strcpy(&(tmp[filename_len]), ".Z");
00241 realfilename = locate_image_file(tmp,iparams->search_path);
00242 }
00243 }
00244 }
00245 if( tmp != realfilename && tmp != NULL )
00246 free( tmp );
00247 }
00248 if( realfilename == file )
00249 realfilename = mystrdup(file);
00250 return realfilename ;
00251 }
00252 ASImage *
00253 file2ASImage_extra( const char *file, ASImageImportParams *iparams )
00254 {
00255 char *realfilename ;
00256 ASImage *im = NULL;
00257 ASImageImportParams dummy_iparams = {0};
00258
00259 if( iparams == NULL )
00260 iparams = &dummy_iparams ;
00261
00262 realfilename = locate_image_file_in_path( file, iparams );
00263
00264 if( realfilename != NULL )
00265 {
00266 ASImageFileTypes file_type = check_image_type( realfilename );
00267
00268 if( file_type == ASIT_Unknown )
00269 show_error( "Hmm, I don't seem to know anything about format of the image file \"%s\"\n.\tPlease check the manual", realfilename );
00270 else if( as_image_file_loaders[file_type] )
00271 {
00272 char *g_var = getenv( "SCREEN_GAMMA" );
00273 if( g_var != NULL )
00274 iparams->gamma = atof(g_var);
00275 im = as_image_file_loaders[file_type](realfilename, iparams);
00276 }else
00277 show_error( "Support for the format of image file \"%s\" has not been implemented yet.", realfilename );
00278
00279 if( im != NULL && im->imageman != NULL )
00280 {
00281 if( im->ref_count == 1 )
00282 {
00283 forget_asimage( im );
00284 }else
00285 {
00286 ASImage *tmp = clone_asimage( im , 0xFFFFFFFF);
00287 if( tmp )
00288 {
00289 release_asimage( im );
00290 im = tmp ;
00291 }
00292 }
00293 }
00294
00295 #ifndef NO_DEBUG_OUTPUT
00296 if( im != NULL )
00297 show_progress( "image loaded from \"%s\"", realfilename );
00298 #endif
00299 free( realfilename );
00300 }else
00301 show_error( "I'm terribly sorry, but image file \"%s\" is nowhere to be found.", file );
00302
00303 return im;
00304 }
00305
00306 void init_asimage_import_params( ASImageImportParams *iparams )
00307 {
00308 if( iparams )
00309 {
00310 iparams->flags = 0 ;
00311 iparams->width = 0 ;
00312 iparams->height = 0 ;
00313 iparams->filter = SCL_DO_ALL ;
00314 iparams->gamma = 0. ;
00315 iparams->gamma_table = NULL ;
00316 iparams->compression = 100 ;
00317 iparams->format = ASA_ASImage ;
00318 iparams->search_path = NULL;
00319 iparams->subimage = 0 ;
00320 }
00321 }
00322
00323 ASImage *
00324 file2ASImage( const char *file, ASFlagType what, double gamma, unsigned int compression, ... )
00325 {
00326 int i ;
00327 char *paths[MAX_SEARCH_PATHS+1] ;
00328 ASImageImportParams iparams ;
00329 va_list ap;
00330
00331 init_asimage_import_params( &iparams );
00332 iparams.gamma = gamma ;
00333 iparams.compression = compression ;
00334 iparams.search_path = &(paths[0]);
00335 #if 0
00336 iparams.width = 1024 ;
00337 iparams.height = -1 ;
00338 iparams.flags |= AS_IMPORT_SCALED_H|AS_IMPORT_SCALED_V ;
00339 #endif
00340 va_start (ap, compression);
00341 for( i = 0 ; i < MAX_SEARCH_PATHS ; i++ )
00342 {
00343 if( (paths[i] = va_arg(ap,char*)) == NULL )
00344 break;
00345 }
00346 paths[MAX_SEARCH_PATHS] = NULL ;
00347 va_end (ap);
00348
00349 return file2ASImage_extra( file, &iparams );
00350
00351 }
00352
00353 Pixmap
00354 file2pixmap(ASVisual *asv, Window root, const char *realfilename, Pixmap *mask_out)
00355 {
00356 Pixmap trg = None;
00357 #ifndef X_DISPLAY_MISSING
00358 Pixmap mask = None ;
00359 if( asv && realfilename )
00360 {
00361 double gamma = SCREEN_GAMMA;
00362 char *gamma_str;
00363 ASImage *im = NULL;
00364
00365 if ((gamma_str = getenv ("SCREEN_GAMMA")) != NULL)
00366 {
00367 gamma = atof (gamma_str);
00368 if (gamma == 0.0)
00369 gamma = SCREEN_GAMMA;
00370 }
00371
00372 im = file2ASImage( realfilename, 0xFFFFFFFF, gamma, 0, NULL );
00373
00374 if( im != NULL )
00375 {
00376 trg = asimage2pixmap( asv, root, im, NULL, False );
00377 if( mask_out )
00378 if( get_flags( get_asimage_chanmask(im), SCL_DO_ALPHA ) )
00379 mask = asimage2mask( asv, root, im, NULL, False );
00380 destroy_asimage( &im );
00381 }
00382 }
00383 if( mask_out )
00384 {
00385 if( *mask_out && asv )
00386 XFreePixmap( asv->dpy, *mask_out );
00387 *mask_out = mask ;
00388 }
00389 #endif
00390 return trg ;
00391 }
00392
00393 static ASImage *
00394 load_image_from_path( const char *file, char **path, double gamma)
00395 {
00396 ASImageImportParams iparams ;
00397
00398 init_asimage_import_params( &iparams );
00399 iparams.gamma = gamma ;
00400 iparams.search_path = path;
00401
00402 return file2ASImage_extra( file, &iparams );
00403 }
00404
00405 ASImageFileTypes
00406 get_asimage_file_type( ASImageManager* imageman, const char *file )
00407 {
00408 ASImageFileTypes file_type = ASIT_Unknown ;
00409 if( file )
00410 {
00411 ASImageImportParams iparams ;
00412 char *realfilename ;
00413
00414 init_asimage_import_params( &iparams );
00415 iparams.search_path = imageman?&(imageman->search_path[0]):NULL;
00416 realfilename = locate_image_file_in_path( file, &iparams );
00417
00418 if( realfilename != NULL )
00419 {
00420 file_type = check_image_type( realfilename );
00421 free( realfilename );
00422 }
00423 }
00424 return file_type;
00425 }
00426
00427
00428 ASImage *
00429 get_asimage( ASImageManager* imageman, const char *file, ASFlagType what, unsigned int compression )
00430 {
00431 ASImage *im = NULL ;
00432 if( imageman && file )
00433 if( (im = fetch_asimage(imageman, file )) == NULL )
00434 {
00435 im = load_image_from_path( file, &(imageman->search_path[0]), imageman->gamma);
00436 if( im )
00437 {
00438 store_asimage( imageman, im, file );
00439 set_flags( im->flags, ASIM_NAME_IS_FILENAME );
00440 }
00441
00442 }
00443 return im;
00444 }
00445
00446 void
00447 calculate_proportions( int src_w, int src_h, int *pdst_w, int *pdst_h )
00448 {
00449 int dst_w = pdst_w?*pdst_w:0 ;
00450 int dst_h = pdst_h?*pdst_h:0 ;
00451
00452 if( src_w > 0 && src_w >= src_h && (dst_w > 0 || dst_h <= 0))
00453 dst_h = (src_h*dst_w)/src_w ;
00454 else if( src_h > 0 )
00455 dst_w = (src_w*dst_h)/src_h ;
00456
00457 if( pdst_w ) *pdst_w = dst_w ;
00458 if( pdst_h ) *pdst_h = dst_h ;
00459 }
00460
00461 void print_asimage_func (ASHashableValue value);
00462 ASImage *
00463 get_thumbnail_asimage( ASImageManager* imageman, const char *file, int thumb_width, int thumb_height, ASFlagType flags )
00464 {
00465 ASImage *im = NULL ;
00466
00467 if( imageman && file )
00468 {
00469 #define AS_THUMBNAIL_NAME_FORMAT "%s_scaled_to_%dx%d"
00470 char *thumbnail_name = safemalloc( strlen(file)+sizeof(AS_THUMBNAIL_NAME_FORMAT)+32 );
00471 ASImage *original_im = query_asimage(imageman, file );
00472
00473 if( thumb_width <= 0 && thumb_height <= 0 )
00474 {
00475 thumb_width = 48 ;
00476 thumb_height = 48 ;
00477 }
00478
00479 if( get_flags(flags, AS_THUMBNAIL_PROPORTIONAL ) )
00480 {
00481 if( original_im != NULL )
00482 calculate_proportions( original_im->width, original_im->height, &thumb_width, &thumb_height );
00483 }else
00484 {
00485 if( thumb_width == 0 )
00486 thumb_width = thumb_height ;
00487 if( thumb_height == 0 )
00488 thumb_height = thumb_width ;
00489 }
00490
00491 if( thumb_width > 0 && thumb_height > 0 )
00492 {
00493 sprintf( thumbnail_name, AS_THUMBNAIL_NAME_FORMAT, file, thumb_width, thumb_height ) ;
00494 im = fetch_asimage(imageman, thumbnail_name );
00495 if( im == NULL )
00496 {
00497 if( original_im != NULL )
00498 {
00499 if( (( (int)original_im->width > thumb_width || (int)original_im->height > thumb_height ) && !get_flags( flags, AS_THUMBNAIL_DONT_REDUCE ) ) ||
00500 (( (int)original_im->width < thumb_width || (int)original_im->height < thumb_height ) && !get_flags( flags, AS_THUMBNAIL_DONT_ENLARGE ) ) )
00501 {
00502 im = scale_asimage( NULL, original_im, thumb_width, thumb_height, ASA_ASImage, 100, ASIMAGE_QUALITY_FAST );
00503 if( im != NULL )
00504 store_asimage( imageman, im, thumbnail_name );
00505 }else
00506 im = dup_asimage( original_im );
00507 }
00508 }
00509 }
00510
00511 if( im == NULL )
00512 {
00513 ASImage *tmp ;
00514 ASImageImportParams iparams ;
00515
00516 init_asimage_import_params( &iparams );
00517 iparams.gamma = imageman->gamma ;
00518 iparams.search_path = &(imageman->search_path[0]);
00519
00520 iparams.width = thumb_width ;
00521 iparams.height = thumb_height ;
00522 if( !get_flags( flags, AS_THUMBNAIL_DONT_ENLARGE|AS_THUMBNAIL_DONT_REDUCE ) )
00523 iparams.flags |= AS_IMPORT_RESIZED|AS_IMPORT_SCALED_BOTH ;
00524
00525 if( get_flags( flags, AS_THUMBNAIL_DONT_ENLARGE ) )
00526 iparams.flags |= AS_IMPORT_FAST ;
00527
00528 tmp = file2ASImage_extra( file, &iparams );
00529 if( tmp )
00530 {
00531 im = tmp ;
00532 if( (int)tmp->width != thumb_width || (int)tmp->height != thumb_height )
00533 {
00534 if( get_flags(flags, AS_THUMBNAIL_PROPORTIONAL ) )
00535 {
00536 calculate_proportions( tmp->width, tmp->height, &thumb_width, &thumb_height );
00537 sprintf( thumbnail_name, AS_THUMBNAIL_NAME_FORMAT, file, thumb_width, thumb_height );
00538 if( (im = query_asimage( imageman, thumbnail_name )) == NULL )
00539 im = tmp ;
00540 }
00541 if( im == tmp )
00542 {
00543 if( (( (int)tmp->width > thumb_width || (int)tmp->height > thumb_height ) && !get_flags( flags, AS_THUMBNAIL_DONT_REDUCE ) ) ||
00544 (( (int)tmp->width < thumb_width || (int)tmp->height < thumb_height ) && !get_flags( flags, AS_THUMBNAIL_DONT_ENLARGE ) ) )
00545 {
00546 im = scale_asimage( NULL, tmp, thumb_width, thumb_height, ASA_ASImage, 100, ASIMAGE_QUALITY_FAST );
00547 if( im == NULL )
00548 im = tmp ;
00549 }
00550 }
00551 }
00552
00553 if( im != NULL )
00554 {
00555 if( im->imageman == NULL )
00556 store_asimage( imageman, im, thumbnail_name );
00557 else
00558 dup_asimage( im );
00559 }
00560
00561 if( im != tmp )
00562 destroy_asimage( &tmp );
00563 }
00564
00565 }
00566
00567 if( thumbnail_name )
00568 free( thumbnail_name );
00569 }
00570 return im;
00571 }
00572
00573
00574 Bool
00575 reload_asimage_manager( ASImageManager *imman )
00576 {
00577 #if (HAVE_AFTERBASE_FLAG==1)
00578 if( imman != NULL )
00579 {
00580 ASHashIterator iter ;
00581 if( start_hash_iteration (imman->image_hash, &iter) )
00582 {
00583 do
00584 {
00585 ASImage *im = curr_hash_data( &iter );
00586
00587 if( get_flags( im->flags, ASIM_NAME_IS_FILENAME ) )
00588 {
00589
00590 ASImage *reloaded_im = load_image_from_path( im->name, &(imman->search_path[0]), imman->gamma);
00591
00592 if( reloaded_im )
00593 {
00594 if( asimage_replace (im, reloaded_im) )
00595 free( reloaded_im );
00596 else
00597 destroy_asimage( &reloaded_im );
00598 }
00599 }
00600 }while( next_hash_item( &iter ) );
00601 return True;
00602 }
00603 }
00604 #endif
00605 return False;
00606 }
00607
00608
00609 ASImageListEntry *
00610 ref_asimage_list_entry( ASImageListEntry *entry )
00611 {
00612 if( entry )
00613 {
00614 if( IS_ASIMAGE_LIST_ENTRY(entry) )
00615 ++(entry->ref_count);
00616 else
00617 entry = NULL ;
00618 }
00619 return entry;
00620 }
00621
00622 ASImageListEntry *
00623 unref_asimage_list_entry( ASImageListEntry *entry )
00624 {
00625 if( entry )
00626 {
00627 if( IS_ASIMAGE_LIST_ENTRY(entry) )
00628 {
00629 --(entry->ref_count);
00630 if( entry->ref_count <= 0 )
00631 {
00632 ASImageListEntry *prev = entry->prev ;
00633 ASImageListEntry *next = entry->next ;
00634 if( !IS_ASIMAGE_LIST_ENTRY(prev) )
00635 prev = NULL ;
00636 if( !IS_ASIMAGE_LIST_ENTRY(next) )
00637 next = NULL ;
00638 if( prev )
00639 prev->next = next ;
00640 if( next )
00641 next->prev = prev ;
00642
00643 if( entry->preview )
00644 safe_asimage_destroy( entry->preview );
00645 if( entry->name )
00646 free( entry->name );
00647 if( entry->fullfilename )
00648 free( entry->fullfilename );
00649 if( entry->buffer )
00650 destroy_asimage_list_entry_buffer( &(entry->buffer) );
00651 memset( entry, 0x00, sizeof(ASImageListEntry));
00652 free( entry );
00653 entry = NULL ;
00654 }
00655 }else
00656 entry = NULL ;
00657 }
00658 return entry;
00659 }
00660
00661 ASImageListEntry *
00662 create_asimage_list_entry()
00663 {
00664 ASImageListEntry *entry = safecalloc( 1, sizeof(ASImageListEntry));
00665 entry->ref_count = 1 ;
00666 entry->magic = MAGIC_ASIMAGE_LIST_ENTRY ;
00667 return entry;
00668 }
00669
00670 void
00671 destroy_asimage_list( ASImageListEntry **plist )
00672 {
00673 if( plist )
00674 {
00675 ASImageListEntry *curr = *plist ;
00676 while( IS_ASIMAGE_LIST_ENTRY(curr) )
00677 {
00678 ASImageListEntry *to_delete = curr ;
00679 curr = curr->next ;
00680 unref_asimage_list_entry( to_delete );
00681 }
00682 *plist = NULL ;
00683 }
00684 }
00685
00686 void destroy_asimage_list_entry_buffer( ASImageListEntryBuffer **pbuffer )
00687 {
00688 if( pbuffer && *pbuffer )
00689 {
00690 if( (*pbuffer)->data )
00691 free( (*pbuffer)->data ) ;
00692 free( *pbuffer );
00693 *pbuffer = NULL ;
00694 }
00695 }
00696
00697 struct ASImageListAuxData
00698 {
00699 ASImageListEntry **pcurr;
00700 ASImageListEntry *last ;
00701 ASFlagType preview_type ;
00702 unsigned int preview_width ;
00703 unsigned int preview_height ;
00704 unsigned int preview_compression ;
00705 ASVisual *asv;
00706 };
00707
00708 #ifndef _WIN32
00709 Bool
00710 direntry2ASImageListEntry( const char *fname, const char *fullname,
00711 struct stat *stat_info, void *aux_data)
00712 {
00713 struct ASImageListAuxData *data = (struct ASImageListAuxData*)aux_data;
00714 ASImageFileTypes file_type ;
00715 ASImageListEntry *curr ;
00716
00717 if (S_ISDIR (stat_info->st_mode))
00718 return False;
00719
00720 file_type = check_image_type( fullname );
00721 if( file_type != ASIT_Unknown && as_image_file_loaders[file_type] == NULL )
00722 file_type = ASIT_Unknown ;
00723
00724 curr = create_asimage_list_entry();
00725 *(data->pcurr) = curr ;
00726 if( data->last )
00727 data->last->next = curr ;
00728 curr->prev = data->last ;
00729 data->last = curr ;
00730 data->pcurr = &(data->last->next);
00731
00732 curr->name = mystrdup( fname );
00733 curr->fullfilename = mystrdup(fullname);
00734 curr->type = file_type ;
00735 curr->d_mode = stat_info->st_mode;
00736 curr->d_mtime = stat_info->st_mtime;
00737 curr->d_size = stat_info->st_size;
00738
00739 if( curr->type != ASIT_Unknown && data->preview_type != 0 )
00740 {
00741 ASImageImportParams iparams = {0} ;
00742 ASImage *im = as_image_file_loaders[file_type](fullname, &iparams);
00743 if( im )
00744 {
00745 int scale_width = im->width ;
00746 int scale_height = im->height ;
00747 int tile_width = im->width ;
00748 int tile_height = im->height ;
00749
00750 if( data->preview_width > 0 )
00751 {
00752 if( get_flags( data->preview_type, SCALE_PREVIEW_H ) )
00753 scale_width = data->preview_width ;
00754 else
00755 tile_width = data->preview_width ;
00756 }
00757 if( data->preview_height > 0 )
00758 {
00759 if( get_flags( data->preview_type, SCALE_PREVIEW_V ) )
00760 scale_height = data->preview_height ;
00761 else
00762 tile_height = data->preview_height ;
00763 }
00764 if( scale_width != im->width || scale_height != im->height )
00765 {
00766 ASImage *tmp = scale_asimage( data->asv, im, scale_width, scale_height, ASA_ASImage, data->preview_compression, ASIMAGE_QUALITY_DEFAULT );
00767 if( tmp != NULL )
00768 {
00769 destroy_asimage( &im );
00770 im = tmp ;
00771 }
00772 }
00773 if( tile_width != im->width || tile_height != im->height )
00774 {
00775 ASImage *tmp = tile_asimage( data->asv, im, 0, 0, tile_width, tile_height, TINT_NONE, ASA_ASImage, data->preview_compression, ASIMAGE_QUALITY_DEFAULT );
00776 if( tmp != NULL )
00777 {
00778 destroy_asimage( &im );
00779 im = tmp ;
00780 }
00781 }
00782 }
00783
00784 curr->preview = im ;
00785 }
00786 return True;
00787 }
00788 #endif
00789
00790 ASImageListEntry *
00791 get_asimage_list( ASVisual *asv, const char *dir,
00792 ASFlagType preview_type, double gamma,
00793 unsigned int preview_width, unsigned int preview_height,
00794 unsigned int preview_compression,
00795 unsigned int *count_ret,
00796 int (*select) (const char *) )
00797 {
00798 ASImageListEntry *im_list = NULL ;
00799 #ifndef _WIN32
00800 struct ASImageListAuxData aux_data ;
00801 int count ;
00802
00803 aux_data.pcurr = &im_list;
00804 aux_data.last = NULL;
00805 aux_data.preview_type = preview_type;
00806 aux_data.preview_width = preview_width;
00807 aux_data.preview_height = preview_height;
00808 aux_data.preview_compression = preview_compression;
00809 aux_data.asv = asv ;
00810
00811
00812 if( asv == NULL || dir == NULL )
00813 return NULL ;
00814
00815 count = my_scandir_ext ((char*)dir, select, direntry2ASImageListEntry, &aux_data);
00816
00817 if( count_ret )
00818 *count_ret = count ;
00819 #endif
00820 return im_list;
00821 }
00822
00823 char *format_asimage_list_entry_details( ASImageListEntry *entry, Bool vertical )
00824 {
00825 char *details_text ;
00826
00827 if( entry )
00828 {
00829 int type = (entry->type>ASIT_Unknown)?ASIT_Unknown:entry->type ;
00830 details_text = safemalloc(128);
00831 if( entry->preview )
00832 sprintf( details_text, vertical?"File type: %s\nSize %dx%d":"File type: %s; Size %dx%d", as_image_file_type_names[type], entry->preview->width, entry->preview->height );
00833 else
00834 sprintf( details_text, "File type: %s", as_image_file_type_names[type]);
00835 }else
00836 details_text = mystrdup("");
00837 return details_text;
00838 }
00839
00840 Bool
00841 load_asimage_list_entry_data( ASImageListEntry *entry, size_t max_bytes )
00842 {
00843 char * new_buffer ;
00844 size_t new_buffer_size ;
00845 FILE *fp;
00846 Bool binary = False ;
00847 if( entry == NULL )
00848 return False;
00849 if( entry->buffer == NULL )
00850 entry->buffer = safecalloc( 1, sizeof(ASImageListEntryBuffer) );
00851 if( (int)entry->buffer->size == entry->d_size || entry->buffer->size >= max_bytes )
00852 return True;
00853 new_buffer_size = min( max_bytes, (size_t)entry->d_size );
00854 new_buffer = malloc( new_buffer_size );
00855 if( new_buffer == NULL )
00856 return False ;
00857 if( entry->buffer->size > 0 )
00858 {
00859 memcpy( new_buffer, entry->buffer->data, entry->buffer->size ) ;
00860 free( entry->buffer->data );
00861 }
00862 entry->buffer->data = new_buffer ;
00863
00864 fp = fopen(entry->fullfilename, "rb");
00865 if ( fp != NULL )
00866 {
00867 int len = new_buffer_size - entry->buffer->size ;
00868 if( entry->buffer->size > 0 )
00869 fseek( fp, entry->buffer->size, SEEK_SET );
00870 len = fread(entry->buffer->data, 1, len, fp);
00871 if( len > 0 )
00872 entry->buffer->size += len ;
00873 fclose(fp);
00874 }
00875
00876 if( entry->type == ASIT_Unknown )
00877 {
00878 int i = entry->buffer->size ;
00879 register char *ptr = entry->buffer->data ;
00880 while ( --i >= 0 )
00881 if( !isprint(ptr[i]) && ptr[i] != '\n'&& ptr[i] != '\r'&& ptr[i] != '\t' )
00882 break;
00883 binary = (i >= 0);
00884 }else
00885 binary = (entry->type != ASIT_Xpm && entry->type != ASIT_XMLScript &&
00886 entry->type != ASIT_HTML && entry->type != ASIT_XML );
00887 if( binary )
00888 set_flags( entry->buffer->flags, ASILEB_Binary );
00889 else
00890 clear_flags( entry->buffer->flags, ASILEB_Binary );
00891
00892
00893
00894 return True;
00895 }
00896
00897
00898
00899
00900 static char *
00901 locate_image_file( const char *file, char **paths )
00902 {
00903 char *realfilename = NULL;
00904 if( file != NULL )
00905 {
00906 realfilename = mystrdup( file );
00907 #ifdef _WIN32
00908 unix_path2dos_path( realfilename );
00909 #endif
00910
00911 if( CheckFile( realfilename ) != 0 )
00912 {
00913 free( realfilename ) ;
00914 realfilename = NULL ;
00915 if( paths != NULL )
00916 {
00917 register int i = 0;
00918 do
00919 {
00920 if( i > 0 )
00921 {
00922 show_progress( "looking for image \"%s\" in path [%s]", file, paths[i] );
00923 }
00924 realfilename = find_file( file, paths[i], R_OK );
00925 }while( realfilename == NULL && paths[i++] != NULL );
00926 }
00927 }
00928 }
00929 return realfilename;
00930 }
00931
00932 static FILE*
00933 open_image_file( const char *path )
00934 {
00935 FILE *fp = NULL;
00936 if ( path )
00937 {
00938 if ((fp = fopen (path, "rb")) == NULL)
00939 show_error("cannot open image file \"%s\" for reading. Please check permissions.", path);
00940 }else
00941 fp = stdin ;
00942 return fp ;
00943 }
00944
00945 static ASImageFileTypes
00946 check_image_type( const char *realfilename )
00947 {
00948 ASImageFileTypes type = ASIT_Unknown ;
00949 int filename_len = strlen( realfilename );
00950 FILE *fp ;
00951 #define FILE_HEADER_SIZE 512
00952
00953
00954 if( filename_len > 5 && (mystrncasecmp( realfilename+filename_len-5, ".html", 5 ) == 0 ||
00955 mystrncasecmp( realfilename+filename_len-4, ".htm", 4 ) == 0 ))
00956 type = ASIT_HTML;
00957 else if( filename_len > 7 && mystrncasecmp( realfilename+filename_len-7, ".xpm.gz", 7 ) == 0 )
00958 type = ASIT_GZCompressedXpm;
00959 else if( filename_len > 6 && mystrncasecmp( realfilename+filename_len-6, ".xpm.Z", 6 ) == 0 )
00960 type = ASIT_ZCompressedXpm ;
00961 else if( (fp = open_image_file( realfilename )) != NULL )
00962 {
00963 char head[FILE_HEADER_SIZE+1] ;
00964 int bytes_in = 0 ;
00965 memset(&head[0], 0x00, sizeof(head));
00966 bytes_in = fread( &(head[0]), sizeof(char), FILE_HEADER_SIZE, fp );
00967 DEBUG_OUT("%s: head[0]=0x%2.2X(%d),head[2]=0x%2.2X(%d)\n", realfilename+filename_len-4, head[0], head[0], head[2], head[2] );
00968
00969
00970
00971 if( bytes_in > 3 )
00972 {
00973 if( (CARD8)head[0] == 0xff && (CARD8)head[1] == 0xd8 && (CARD8)head[2] == 0xff)
00974 type = ASIT_Jpeg;
00975 else if (strstr ((char *)&(head[0]), "XPM") != NULL)
00976 type = ASIT_Xpm;
00977 else if (head[1] == 'P' && head[2] == 'N' && head[3] == 'G')
00978 type = ASIT_Png;
00979 else if (head[0] == 'G' && head[1] == 'I' && head[2] == 'F')
00980 type = ASIT_Gif;
00981 else if (head[0] == head[1] && (head[0] == 'I' || head[0] == 'M'))
00982 type = ASIT_Tiff;
00983 else if (head[0] == 'P' && isdigit(head[1]))
00984 type = (head[1]!='5' && head[1]!='6')?ASIT_Pnm:ASIT_Ppm;
00985 else if (head[0] == 0xa && head[1] <= 5 && head[2] == 1)
00986 type = ASIT_Pcx;
00987 else if (head[0] == 'B' && head[1] == 'M')
00988 type = ASIT_Bmp;
00989 else if (head[0] == 0 && head[2] == 1 && mystrncasecmp(realfilename+filename_len-4, ".ICO", 4)==0 )
00990 type = ASIT_Ico;
00991 else if (head[0] == 0 && head[2] == 2 &&
00992 (mystrncasecmp(realfilename+filename_len-4, ".CUR", 4)==0 ||
00993 mystrncasecmp(realfilename+filename_len-4, ".ICO", 4)==0) )
00994 type = ASIT_Cur;
00995 }
00996 if( type == ASIT_Unknown && bytes_in > 6 )
00997 {
00998 if( mystrncasecmp( head, "<HTML>", 6 ) == 0 )
00999 type = ASIT_HTML;
01000 }
01001 if( type == ASIT_Unknown && bytes_in > 8 )
01002 {
01003 if( strncmp(&(head[0]), XCF_SIGNATURE, (size_t) XCF_SIGNATURE_LEN) == 0)
01004 type = ASIT_Xcf;
01005 else if (head[0] == 0 && head[1] == 0 &&
01006 head[2] == 2 && head[3] == 0 && head[4] == 0 && head[5] == 0 && head[6] == 0 && head[7] == 0)
01007 type = ASIT_Targa;
01008 else if (strncmp (&(head[0]), "#define", (size_t) 7) == 0)
01009 type = ASIT_Xbm;
01010 else if( mystrncasecmp(realfilename+filename_len-4, ".SVG", 4)==0 )
01011 type = ASIT_SVG ;
01012 else
01013 {
01014 int i ;
01015
01016 type = ASIT_XMLScript ;
01017 for( i = 0 ; i < bytes_in ; ++i ) if( !isspace(head[i]) ) break;
01018 while( bytes_in > 0 && type == ASIT_XMLScript )
01019 {
01020 if( i >= bytes_in )
01021 {
01022 bytes_in = fread( &(head[0]), sizeof(CARD8), FILE_HEADER_SIZE, fp );
01023 for( i = 0 ; i < bytes_in ; ++i ) if( !isspace(head[i]) ) break;
01024 }
01025 else if( head[i] != '<' )
01026 type = ASIT_Unknown ;
01027 else if( mystrncasecmp( &(head[i]), "<svg", 4 ) == 0 )
01028 {
01029 type = ASIT_SVG ;
01030 }else if( mystrncasecmp( &(head[i]), "<!DOCTYPE ", 10 ) == 0 )
01031 {
01032 type = ASIT_XML ;
01033 for( i += 9 ; i < bytes_in ; ++i ) if( !isspace(head[i]) ) break;
01034 if( i < bytes_in )
01035 {
01036 if( mystrncasecmp( &(head[i]), "afterstep-image-xml", 19 ) == 0 )
01037 {
01038 i += 19 ;
01039 type = ASIT_XMLScript ;
01040 }
01041 }
01042 }else
01043 {
01044 while( bytes_in > 0 && type == ASIT_XMLScript )
01045 {
01046 while( ++i < bytes_in )
01047 if( !isspace(head[i]) )
01048 {
01049 if( !isprint(head[i]) )
01050 {
01051 type = ASIT_Unknown ;
01052 break ;
01053 }else if( head[i] == '>' )
01054 break ;
01055 }
01056
01057 if( i >= bytes_in )
01058 {
01059 bytes_in = fread( &(head[0]), sizeof(CARD8), FILE_HEADER_SIZE, fp );
01060 i = 0 ;
01061 }else
01062 break ;
01063 }
01064 break;
01065 }
01066 }
01067 }
01068 }
01069 fclose( fp );
01070 }
01071 return type;
01072 }
01073
01074
01075 ASImageFileTypes
01076 check_asimage_file_type( const char *realfilename )
01077 {
01078 if( realfilename == NULL )
01079 return ASIT_Unknown;
01080 return check_image_type( realfilename );
01081 }
01082
01083
01084 #ifdef HAVE_XPM
01085
01086 #ifdef LOCAL_DEBUG
01087 Bool print_component( CARD32*, int, unsigned int );
01088 #endif
01089
01090 static ASImage *
01091 xpm_file2ASImage( ASXpmFile *xpm_file, unsigned int compression )
01092 {
01093 ASImage *im = NULL ;
01094 int line = 0;
01095
01096 LOCAL_DEBUG_OUT( "do_alpha is %d. im->height = %d, im->width = %d", xpm_file->do_alpha, xpm_file->height, xpm_file->width );
01097 if( build_xpm_colormap( xpm_file ) )
01098 if( (im = create_xpm_image( xpm_file, compression )) != NULL )
01099 {
01100 int bytes_count = im->width*4 ;
01101 ASFlagType rgb_flags = ASStorage_RLEDiffCompress|ASStorage_32Bit ;
01102 ASFlagType alpha_flags = ASStorage_RLEDiffCompress|ASStorage_32Bit ;
01103 int old_storage_block_size = set_asstorage_block_size( NULL, xpm_file->width*xpm_file->height*3/2 );
01104
01105 if( !xpm_file->full_alpha )
01106 alpha_flags |= ASStorage_Bitmap ;
01107 for( line = 0 ; line < xpm_file->height ; ++line )
01108 {
01109 if( !convert_xpm_scanline( xpm_file, line ) )
01110 break;
01111 im->channels[IC_RED][line] = store_data( NULL, (CARD8*)xpm_file->scl.red, bytes_count, rgb_flags, 0);
01112 im->channels[IC_GREEN][line] = store_data( NULL, (CARD8*)xpm_file->scl.green, bytes_count, rgb_flags, 0);
01113 im->channels[IC_BLUE][line] = store_data( NULL, (CARD8*)xpm_file->scl.blue, bytes_count, rgb_flags, 0);
01114 if( xpm_file->do_alpha )
01115 im->channels[IC_ALPHA][line] = store_data( NULL, (CARD8*)xpm_file->scl.alpha, bytes_count, alpha_flags, 0);
01116 #ifdef LOCAL_DEBUG
01117 printf( "%d: \"%s\"\n", line, xpm_file->str_buf );
01118 print_component( xpm_file->scl.red, 0, xpm_file->width );
01119 print_component( xpm_file->scl.green, 0, xpm_file->width );
01120 print_component( xpm_file->scl.blue, 0, xpm_file->width );
01121 #endif
01122 }
01123 set_asstorage_block_size( NULL, old_storage_block_size);
01124 }
01125 return im ;
01126 }
01127
01128 ASImage *
01129 xpm2ASImage( const char * path, ASImageImportParams *params )
01130 {
01131 ASXpmFile *xpm_file = NULL;
01132 ASImage *im = NULL ;
01133 START_TIME(started);
01134
01135 LOCAL_DEBUG_CALLER_OUT ("(\"%s\", 0x%lX)", path, params->flags);
01136 if( (xpm_file=open_xpm_file(path)) == NULL )
01137 {
01138 show_error("cannot open image file \"%s\" for reading. Please check permissions.", path);
01139 return NULL;
01140 }
01141
01142 im = xpm_file2ASImage( xpm_file, params->compression );
01143 close_xpm_file( &xpm_file );
01144
01145 SHOW_TIME("image loading",started);
01146 return im;
01147 }
01148
01149 ASXpmFile *open_xpm_data(const char **data);
01150 ASXpmFile *open_xpm_raw_data(const char *data);
01151
01152 ASImage *
01153 xpm_data2ASImage( const char **data, ASImageImportParams *params )
01154 {
01155 ASXpmFile *xpm_file = NULL;
01156 ASImage *im = NULL ;
01157 START_TIME(started);
01158
01159 LOCAL_DEBUG_CALLER_OUT ("(\"%s\", 0x%lX)", (char*)data, params->flags);
01160 if( (xpm_file=open_xpm_data(data)) == NULL )
01161 {
01162 show_error("cannot read XPM data.");
01163 return NULL;
01164 }
01165
01166 im = xpm_file2ASImage( xpm_file, params->compression );
01167 close_xpm_file( &xpm_file );
01168
01169 SHOW_TIME("image loading",started);
01170 return im;
01171 }
01172
01173 ASImage *
01174 xpmRawBuff2ASImage( const char *data, ASImageImportParams *params )
01175 {
01176 ASXpmFile *xpm_file = NULL;
01177 ASImage *im = NULL ;
01178 START_TIME(started);
01179
01180 LOCAL_DEBUG_CALLER_OUT ("(\"%s\", 0x%lX)", (char*)data, params->flags);
01181 if( (xpm_file=open_xpm_raw_data(data)) == NULL )
01182 {
01183 show_error("cannot read XPM data.");
01184 return NULL;
01185 }
01186
01187 im = xpm_file2ASImage( xpm_file, params->compression );
01188 close_xpm_file( &xpm_file );
01189
01190 SHOW_TIME("image loading",started);
01191 return im;
01192 }
01193
01194 #else
01195
01196 ASImage *
01197 xpm2ASImage( const char * path, ASImageImportParams *params )
01198 {
01199 show_error( "unable to load file \"%s\" - XPM image format is not supported.\n", path );
01200 return NULL ;
01201 }
01202
01203 #endif
01204
01205
01206 static inline void
01207 apply_gamma( register CARD8* raw, register CARD8 *gamma_table, unsigned int width )
01208 {
01209 if( gamma_table )
01210 {
01211 register unsigned int i ;
01212 for( i = 0 ; i < width ; ++i )
01213 raw[i] = gamma_table[raw[i]] ;
01214 }
01215 }
01216
01217
01218 #ifdef HAVE_PNG
01219 ASImage *
01220 png2ASImage_int( void *data, png_rw_ptr read_fn, ASImageImportParams *params )
01221 {
01222
01223 double image_gamma = DEFAULT_PNG_IMAGE_GAMMA;
01224 png_structp png_ptr;
01225 png_infop info_ptr;
01226 png_uint_32 width, height;
01227 int bit_depth, color_type, interlace_type;
01228 int intent;
01229 ASScanline buf;
01230 CARD8 *upscaled_gray = NULL;
01231 Bool do_alpha = False, grayscale = False ;
01232 png_bytep *row_pointers, row;
01233 unsigned int y;
01234 size_t row_bytes, offset ;
01235 static ASImage *im = NULL ;
01236 int old_storage_block_size;
01237 START_TIME(started);
01238
01239
01240
01241
01242
01243
01244
01245 if((png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)) != NULL )
01246 {
01247
01248 if( (info_ptr = png_create_info_struct (png_ptr)) != NULL )
01249 {
01250
01251
01252
01253
01254 if ( !setjmp (png_ptr->jmpbuf))
01255 {
01256 ASFlagType rgb_flags = ASStorage_RLEDiffCompress|ASStorage_32Bit ;
01257
01258 if(read_fn == NULL )
01259 {
01260 png_init_io(png_ptr, (FILE*)data);
01261 }else
01262 {
01263 png_set_read_fn(png_ptr, (void*)data, (png_rw_ptr) read_fn);
01264 }
01265
01266 png_read_info (png_ptr, info_ptr);
01267 png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL);
01268
01269
01270
01271
01272 if (bit_depth < 8)
01273 {
01274
01275
01276 if( bit_depth == 1 )
01277 {
01278 set_flags( rgb_flags, ASStorage_Bitmap );
01279 png_set_packing (png_ptr);
01280 }else
01281 {
01282
01283
01284
01285
01286 upscaled_gray = safemalloc(width+8);
01287 }
01288 }else if (bit_depth == 16)
01289 {
01290 png_set_strip_16 (png_ptr);
01291 }
01292
01293
01294 if (color_type == PNG_COLOR_TYPE_PALETTE)
01295 {
01296 png_set_expand (png_ptr);
01297 color_type = PNG_COLOR_TYPE_RGB;
01298 }
01299
01300
01301
01302
01303 if( color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_GRAY )
01304 {
01305 if( png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
01306 {
01307 png_set_expand(png_ptr);
01308 color_type |= PNG_COLOR_MASK_ALPHA;
01309 }
01310 }else
01311 {
01312 png_set_filler( png_ptr, 0xFF, PNG_FILLER_AFTER );
01313 color_type |= PNG_COLOR_MASK_ALPHA;
01314 }
01315
01316
01317
01318
01319
01320
01321 if (png_get_sRGB (png_ptr, info_ptr, &intent))
01322 {
01323 png_set_gamma (png_ptr, params->gamma, DEFAULT_PNG_IMAGE_GAMMA);
01324 }else if (png_get_gAMA (png_ptr, info_ptr, &image_gamma) && bit_depth >= 8)
01325 {
01326 png_set_gamma (png_ptr, params->gamma, image_gamma);
01327 }else
01328 {
01329 png_set_gamma (png_ptr, params->gamma, DEFAULT_PNG_IMAGE_GAMMA);
01330 }
01331
01332
01333
01334
01335
01336
01337 png_read_update_info (png_ptr, info_ptr);
01338
01339 png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL);
01340
01341 im = create_asimage( width, height, params->compression );
01342 do_alpha = ((color_type & PNG_COLOR_MASK_ALPHA) != 0 );
01343 grayscale = ( color_type == PNG_COLOR_TYPE_GRAY_ALPHA ||
01344 color_type == PNG_COLOR_TYPE_GRAY) ;
01345
01346
01347
01348
01349 if( !do_alpha && grayscale )
01350 clear_flags( rgb_flags, ASStorage_32Bit );
01351 else
01352 prepare_scanline( im->width, 0, &buf, False );
01353
01354 row_bytes = png_get_rowbytes (png_ptr, info_ptr);
01355
01356
01357 row_pointers = safemalloc( height * sizeof( png_bytep ) + row_bytes * height );
01358 row = (png_bytep)(row_pointers + height) ;
01359 for (offset = 0, y = 0; y < height; y++, offset += row_bytes)
01360 row_pointers[y] = row + offset;
01361
01362
01363 png_read_image (png_ptr, row_pointers);
01364
01365 old_storage_block_size = set_asstorage_block_size( NULL, width*height*3/2 );
01366 for (y = 0; y < height; y++)
01367 {
01368 if( do_alpha || !grayscale )
01369 {
01370 raw2scanline( row_pointers[y], &buf, NULL, buf.width, grayscale, do_alpha );
01371 im->channels[IC_RED][y] = store_data( NULL, (CARD8*)buf.red, buf.width*4, rgb_flags, 0);
01372 }else
01373 {
01374 if ( bit_depth == 2 )
01375 {
01376 int i, pixel_i = -1;
01377 static CARD8 gray2bit_translation[4] = {0,85,170,255};
01378 for ( i = 0 ; i < row_bytes ; ++i )
01379 {
01380 CARD8 b = row_pointers[y][i];
01381 upscaled_gray[++pixel_i] = gray2bit_translation[b&0x03];
01382 upscaled_gray[++pixel_i] = gray2bit_translation[(b&0xC)>>2];
01383 upscaled_gray[++pixel_i] = gray2bit_translation[(b&0x30)>>4];
01384 upscaled_gray[++pixel_i] = gray2bit_translation[(b&0xC0)>>6];
01385 }
01386 im->channels[IC_RED][y] = store_data( NULL, upscaled_gray, width, rgb_flags, 0);
01387 }else if ( bit_depth == 4 )
01388 {
01389 int i, pixel_i = -1;
01390 static CARD8 gray4bit_translation[16] = {0,17,34,51, 68,85,102,119, 136,153,170,187, 204,221,238,255};
01391 for ( i = 0 ; i < row_bytes ; ++i )
01392 {
01393 CARD8 b = row_pointers[y][i];
01394 upscaled_gray[++pixel_i] = gray4bit_translation[b&0x0F];
01395 upscaled_gray[++pixel_i] = gray4bit_translation[(b&0xF0)>>4];
01396 }
01397 im->channels[IC_RED][y] = store_data( NULL, upscaled_gray, width, rgb_flags, 0);
01398 }else
01399 im->channels[IC_RED][y] = store_data( NULL, row_pointers[y], row_bytes, rgb_flags, 1);
01400 }
01401
01402 if( grayscale )
01403 {
01404 im->channels[IC_GREEN][y] = dup_data( NULL, im->channels[IC_RED][y] );
01405 im->channels[IC_BLUE][y] = dup_data( NULL, im->channels[IC_RED][y] );
01406 }else
01407 {
01408 im->channels[IC_GREEN][y] = store_data( NULL, (CARD8*)buf.green, buf.width*4, rgb_flags, 0);
01409 im->channels[IC_BLUE][y] = store_data( NULL, (CARD8*)buf.blue, buf.width*4, rgb_flags, 0);
01410 }
01411
01412 if( do_alpha )
01413 {
01414 int has_zero = False, has_nozero = False ;
01415 register unsigned int i;
01416 for ( i = 0 ; i < buf.width ; ++i)
01417 {
01418 if( buf.alpha[i] != 0x00FF )
01419 {
01420 if( buf.alpha[i] == 0 )
01421 has_zero = True ;
01422 else
01423 {
01424 has_nozero = True ;
01425 break;
01426 }
01427 }
01428 }
01429 if( has_zero || has_nozero )
01430 {
01431 ASFlagType alpha_flags = ASStorage_32Bit|ASStorage_RLEDiffCompress ;
01432 if( !has_nozero )
01433 set_flags( alpha_flags, ASStorage_Bitmap );
01434 im->channels[IC_ALPHA][y] = store_data( NULL, (CARD8*)buf.alpha, buf.width*4, alpha_flags, 0);
01435 }
01436 }
01437 }
01438 set_asstorage_block_size( NULL, old_storage_block_size );
01439 if (upscaled_gray)
01440 free(upscaled_gray);
01441 free (row_pointers);
01442 if( do_alpha || !grayscale )
01443 free_scanline(&buf, True);
01444
01445 png_read_end (png_ptr, info_ptr);
01446 }
01447 }
01448
01449 png_destroy_read_struct (&png_ptr, &info_ptr, (png_infopp) NULL);
01450 if (info_ptr)
01451 free (info_ptr);
01452 }
01453
01454 #if defined(LOCAL_DEBUG) && !defined(NO_DEBUG_OUTPUT)
01455 print_asimage( im, ASFLAGS_EVERYTHING, __FUNCTION__, __LINE__ );
01456 #endif
01457 SHOW_TIME("image loading",started);
01458 return im ;
01459 }
01460
01461
01462
01463 typedef struct ASImPNGReadBuffer
01464 {
01465 CARD8 *buffer ;
01466
01467 } ASImPNGReadBuffer;
01468
01469 static void asim_png_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
01470 {
01471 ASImPNGReadBuffer *buf = (ASImPNGReadBuffer *)png_ptr->io_ptr;
01472 memcpy(data, buf->buffer, length);
01473 buf->buffer += length;
01474 }
01475
01476 ASImage *
01477 PNGBuff2ASimage(CARD8 *buffer, ASImageImportParams *params)
01478 {
01479 static ASImage *im = NULL;
01480 ASImPNGReadBuffer buf;
01481 buf.buffer = buffer;
01482 im = png2ASImage_int((void*)&buf,(png_rw_ptr)asim_png_read_data, params);
01483 return im;
01484 }
01485
01486
01487 ASImage *
01488 png2ASImage( const char * path, ASImageImportParams *params )
01489 {
01490 FILE *fp ;
01491 static ASImage *im = NULL ;
01492
01493 if ((fp = open_image_file(path)) == NULL)
01494 return NULL;
01495
01496 im = png2ASImage_int((void*)fp, NULL, params);
01497
01498 fclose(fp);
01499 return im;
01500 }
01501 #else
01502 ASImage *
01503 png2ASImage( const char * path, ASImageImportParams *params )
01504 {
01505 show_error( "unable to load file \"%s\" - PNG image format is not supported.\n", path );
01506 return NULL ;
01507 }
01508
01509 ASImage *
01510 PNGBuff2ASimage(CARD8 *buffer, ASImageImportParams *params)
01511 {
01512 return NULL;
01513 }
01514
01515 #endif
01516
01517
01518
01519
01520 #ifdef HAVE_JPEG
01521 struct my_error_mgr
01522 {
01523 struct jpeg_error_mgr pub;
01524 jmp_buf setjmp_buffer;
01525 };
01526 typedef struct my_error_mgr *my_error_ptr;
01527
01528 METHODDEF (void)
01529 my_error_exit (j_common_ptr cinfo)
01530 {
01531
01532 my_error_ptr myerr = (my_error_ptr) cinfo->err;
01533
01534
01535 (*cinfo->err->output_message) (cinfo);
01536
01537 longjmp (myerr->setjmp_buffer, 1);
01538 }
01539
01540 ASImage *
01541 jpeg2ASImage( const char * path, ASImageImportParams *params )
01542 {
01543 ASImage *im ;
01544 int old_storage_block_size ;
01545
01546
01547
01548 struct jpeg_decompress_struct cinfo;
01549 void *temp_cinfo = NULL;
01550
01551
01552
01553
01554 struct my_error_mgr jerr;
01555
01556 FILE *infile;
01557 JSAMPARRAY buffer;
01558 ASScanline buf;
01559 int y;
01560 START_TIME(started);
01561
01562
01563
01564
01565
01566
01567
01568
01569 if ((infile = open_image_file(path)) == NULL)
01570 return NULL;
01571
01572
01573
01574 cinfo.err = jpeg_std_error (&jerr.pub);
01575 jerr.pub.error_exit = my_error_exit;
01576
01577 if (setjmp (jerr.setjmp_buffer))
01578 {
01579
01580
01581
01582 jpeg_destroy_decompress (&cinfo);
01583 fclose (infile);
01584 return NULL;
01585 }
01586
01587 jpeg_create_decompress (&cinfo);
01588
01589 jpeg_stdio_src (&cinfo, infile);
01590
01591 (void)jpeg_read_header (&cinfo, TRUE);
01592
01593
01594
01595
01596
01597
01598
01599
01600 cinfo.quantize_colors = FALSE;
01601 cinfo.output_gamma = params->gamma;
01602
01603 if( get_flags( params->flags, AS_IMPORT_SCALED_BOTH ) == AS_IMPORT_SCALED_BOTH )
01604 {
01605 int w = params->width ;
01606 int h = params->height ;
01607 int ratio ;
01608
01609 if( w == 0 )
01610 {
01611 if( h == 0 )
01612 {
01613 w = cinfo.image_width ;
01614 h = cinfo.image_height ;
01615 }else
01616 w = (cinfo.image_width * h)/cinfo.image_height ;
01617 }else if( h == 0 )
01618 h = (cinfo.image_height * w)/cinfo.image_width ;
01619
01620 ratio = cinfo.image_height/h ;
01621 if( ratio > (int)cinfo.image_width/w )
01622 ratio = cinfo.image_width/w ;
01623
01624 cinfo.scale_num = 1 ;
01625
01626 cinfo.scale_denom = 1 ;
01627 if( ratio >= 2 )
01628 {
01629 if( ratio >= 4 )
01630 {
01631 if( ratio >= 8 )
01632 cinfo.scale_denom = 8 ;
01633 else
01634 cinfo.scale_denom = 4 ;
01635 }else
01636 cinfo.scale_denom = 2 ;
01637 }
01638 }
01639
01640 if( get_flags( params->flags, AS_IMPORT_FAST ) )
01641 {
01642 cinfo.do_fancy_upsampling = FALSE ;
01643 cinfo.do_block_smoothing = FALSE ;
01644 cinfo.dct_method = JDCT_IFAST ;
01645 }
01646
01647
01648 (void)jpeg_start_decompress (&cinfo);
01649 LOCAL_DEBUG_OUT("stored image size %dx%d", cinfo.output_width, cinfo.output_height);
01650
01651 im = create_asimage( cinfo.output_width, cinfo.output_height, params->compression );
01652
01653 if( cinfo.output_components != 1 )
01654 prepare_scanline( im->width, 0, &buf, False );
01655
01656
01657 temp_cinfo = &cinfo;
01658 buffer = cinfo.mem->alloc_sarray((j_common_ptr) temp_cinfo, JPOOL_IMAGE,
01659 cinfo.output_width * cinfo.output_components, 1);
01660
01661
01662 SHOW_TIME("loading initialization",started);
01663 y = -1 ;
01664
01665
01666
01667
01668 old_storage_block_size = set_asstorage_block_size( NULL, im->width*im->height*3/2 );
01669
01670 while ( ++y < (int)cinfo.output_height )
01671 {
01672
01673
01674
01675
01676 (void)jpeg_read_scanlines (&cinfo, buffer, 1);
01677 if( cinfo.output_components==1 )
01678 {
01679 apply_gamma( (CARD8*)buffer[0], params->gamma_table, im->width );
01680 im->channels[IC_RED][y] = store_data( NULL, (CARD8*)buffer[0], im->width, ASStorage_RLEDiffCompress, 0);
01681 im->channels[IC_GREEN][y] = dup_data( NULL, im->channels[IC_RED][y] );
01682 im->channels[IC_BLUE][y] = dup_data( NULL, im->channels[IC_RED][y] );
01683 }else
01684 {
01685 raw2scanline( (CARD8*)buffer[0], &buf, params->gamma_table, im->width, (cinfo.output_components==1), False);
01686 im->channels[IC_RED][y] = store_data( NULL, (CARD8*)buf.red, buf.width*4, ASStorage_32BitRLE, 0);
01687 im->channels[IC_GREEN][y] = store_data( NULL, (CARD8*)buf.green, buf.width*4, ASStorage_32BitRLE, 0);
01688 im->channels[IC_BLUE][y] = store_data( NULL, (CARD8*)buf.blue, buf.width*4, ASStorage_32BitRLE, 0);
01689 }
01690
01691
01692
01693
01694
01695
01696
01697
01698 }
01699 set_asstorage_block_size( NULL, old_storage_block_size );
01700 if( cinfo.output_components != 1 )
01701 free_scanline(&buf, True);
01702 SHOW_TIME("read",started);
01703
01704
01705
01706 if (cinfo.output_scanline < cinfo.output_height)
01707 jpeg_abort_decompress (&cinfo);
01708 else
01709 (void)jpeg_finish_decompress (&cinfo);
01710
01711
01712
01713
01714
01715 jpeg_destroy_decompress (&cinfo);
01716
01717
01718
01719
01720
01721 fclose (infile);
01722
01723
01724
01725 SHOW_TIME("image loading",started);
01726 LOCAL_DEBUG_OUT("done loading JPEG image \"%s\"", path);
01727 return im ;
01728 }
01729 #else
01730 ASImage *
01731 jpeg2ASImage( const char * path, ASImageImportParams *params )
01732 {
01733 show_error( "unable to load file \"%s\" - JPEG image format is not supported.\n", path );
01734 return NULL ;
01735 }
01736
01737 #endif
01738
01739
01740
01741
01742
01743 ASImage *
01744 xcf2ASImage( const char * path, ASImageImportParams *params )
01745 {
01746 ASImage *im = NULL ;
01747
01748 FILE *infile;
01749 XcfImage *xcf_im;
01750 START_TIME(started);
01751
01752
01753
01754
01755
01756
01757 if ((infile = open_image_file(path)) == NULL)
01758 return NULL;
01759
01760 xcf_im = read_xcf_image( infile );
01761 fclose( infile );
01762
01763 if( xcf_im == NULL )
01764 return NULL;
01765
01766 LOCAL_DEBUG_OUT("stored image size %ldx%ld", xcf_im->width, xcf_im->height);
01767 #ifdef LOCAL_DEBUG
01768 print_xcf_image( xcf_im );
01769 #endif
01770 {
01771 XcfLayer *layer = xcf_im->layers ;
01772 while ( layer )
01773 {
01774 if( layer->hierarchy )
01775 if( layer->hierarchy->image )
01776 if( layer->hierarchy->width == xcf_im->width &&
01777 layer->hierarchy->height == xcf_im->height )
01778 {
01779 im = layer->hierarchy->image ;
01780 layer->hierarchy->image = NULL ;
01781 }
01782 layer = layer->next ;
01783 }
01784 }
01785 free_xcf_image(xcf_im);
01786
01787 SHOW_TIME("image loading",started);
01788 return im ;
01789 }
01790
01791
01792
01793 ASImage *
01794 ppm2ASImage( const char * path, ASImageImportParams *params )
01795 {
01796 ASImage *im = NULL ;
01797
01798 FILE *infile;
01799 ASScanline buf;
01800 int y;
01801 unsigned int type = 0, width = 0, height = 0, colors = 0;
01802 #define PPM_BUFFER_SIZE 71
01803 char buffer[PPM_BUFFER_SIZE];
01804 START_TIME(started);
01805
01806 if ((infile = open_image_file(path)) == NULL)
01807 return NULL;
01808
01809 if( fgets( &(buffer[0]), PPM_BUFFER_SIZE, infile ) )
01810 {
01811 if( buffer[0] == 'P' )
01812 switch( buffer[1] )
01813 {
01814 case '5' : type= 5 ; break ;
01815 case '6' : type= 6 ; break ;
01816 case '8' : type= 8 ; break ;
01817 default:
01818 show_error( "invalid or unsupported PPM/PNM file format in image file \"%s\"", path );
01819 }
01820 if( type > 0 )
01821 {
01822 while ( fgets( &(buffer[0]), PPM_BUFFER_SIZE, infile ) )
01823 {
01824 if( buffer[0] != '#' )
01825 {
01826 register int i = 0;
01827 if( width > 0 )
01828 {
01829 colors = atoi(&(buffer[i]));
01830 break;
01831 }
01832 width = atoi( &(buffer[i]) );
01833 while ( buffer[i] != '\0' && !isspace((int)buffer[i]) ) ++i;
01834 while ( isspace((int)buffer[i]) ) ++i;
01835 if( buffer[i] != '\0')
01836 height = atoi(&(buffer[i]));
01837 }
01838 }
01839 }
01840 }
01841
01842 if( type > 0 && colors <= 255 &&
01843 width > 0 && width < MAX_IMPORT_IMAGE_SIZE &&
01844 height > 0 && height < MAX_IMPORT_IMAGE_SIZE )
01845 {
01846 CARD8 *data ;
01847 size_t row_size = width * ((type==6)?3:((type==8)?4:1));
01848
01849 data = safemalloc( row_size );
01850
01851 LOCAL_DEBUG_OUT("stored image size %dx%d", width, height);
01852 im = create_asimage( width, height, params->compression );
01853 prepare_scanline( im->width, 0, &buf, False );
01854 y = -1 ;
01855
01856 while ( ++y < (int)height )
01857 {
01858 if( fread( data, sizeof (char), row_size, infile ) < row_size )
01859 break;
01860
01861 raw2scanline( data, &buf, params->gamma_table, im->width, (type==5), (type==8));
01862
01863 asimage_add_line (im, IC_RED, buf.red , y);
01864 asimage_add_line (im, IC_GREEN, buf.green, y);
01865 asimage_add_line (im, IC_BLUE, buf.blue , y);
01866 if( type == 8 )
01867 asimage_add_line (im, IC_ALPHA, buf.alpha , y);
01868 }
01869 free_scanline(&buf, True);
01870 free( data );
01871 }
01872 fclose( infile );
01873 SHOW_TIME("image loading",started);
01874 return im ;
01875 }
01876
01877
01878
01879 static size_t
01880 bmp_read32 (FILE *fp, CARD32 *data, int count)
01881 {
01882 size_t total = count;
01883 if( count > 0 )
01884 {
01885 #ifdef WORDS_BIGENDIAN
01886 CARD8 *raw = (CARD8*)data ;
01887 #endif
01888 total = fread((char*) data, sizeof (CARD8), count<<2, fp)>>2;
01889 count = 0 ;
01890 #ifdef WORDS_BIGENDIAN
01891 while( count < total )
01892 {
01893 data[count] = (raw[0]<<24)|(raw[1]<<16)|(raw[2]<<8)|raw[3];
01894 ++count ;
01895 raw += 4 ;
01896 }
01897 #endif
01898 }
01899 return total;
01900 }
01901
01902 static size_t
01903 bmp_read16 (FILE *fp, CARD16 *data, int count)
01904 {
01905 size_t total = count;
01906 if( count > 0 )
01907 {
01908 #ifdef WORDS_BIGENDIAN
01909 CARD8 *raw = (CARD8*)data ;
01910 #endif
01911 total = fread((char*) data, sizeof (CARD8), count<<1, fp)>>1;
01912 count = 0 ;
01913 #ifdef WORDS_BIGENDIAN
01914 while( count < total )
01915 {
01916 data[count] = (raw[0]<<16)|raw[1];
01917 ++count ;
01918 raw += 2 ;
01919 }
01920 #endif
01921 }
01922 return total;
01923 }
01924
01925
01926 ASImage *
01927 read_bmp_image( FILE *infile, size_t data_offset, BITMAPINFOHEADER *bmp_info,
01928 ASScanline *buf, CARD8 *gamma_table,
01929 unsigned int width, unsigned int height,
01930 Bool add_colormap, unsigned int compression )
01931 {
01932 Bool success = False ;
01933 CARD8 *cmap = NULL ;
01934 int cmap_entries = 0, cmap_entry_size = 4, row_size ;
01935 int y;
01936 ASImage *im = NULL ;
01937 CARD8 *data ;
01938 int direction = -1 ;
01939
01940 if( bmp_read32( infile, &bmp_info->biSize, 1 ) )
01941 {
01942 if( bmp_info->biSize == 40 )
01943 {
01944 bmp_read32( infile, (CARD32*)&bmp_info->biWidth, 2 );
01945 bmp_read16( infile, &bmp_info->biPlanes, 2 );
01946 bmp_info->biCompression = 1 ;
01947 success = (bmp_read32( infile, &bmp_info->biCompression, 6 )==6);
01948 }else
01949 {
01950 CARD16 dumm[2] ;
01951 bmp_read16( infile, &dumm[0], 2 );
01952 bmp_info->biWidth = dumm[0] ;
01953 bmp_info->biHeight = dumm[1] ;
01954 success = ( bmp_read16( infile, &bmp_info->biPlanes, 2 ) == 2 );
01955 bmp_info->biCompression = 0 ;
01956 }
01957 }
01958 #ifdef LOCAL_DEBUG
01959 fprintf( stderr, "bmp.info.biSize = %ld(0x%lX)\n", bmp_info->biSize, bmp_info->biSize );
01960 fprintf( stderr, "bmp.info.biWidth = %ld\nbmp.info.biHeight = %ld\n", bmp_info->biWidth, bmp_info->biHeight );
01961 fprintf( stderr, "bmp.info.biPlanes = %d\nbmp.info.biBitCount = %d\n", bmp_info->biPlanes, bmp_info->biBitCount );
01962 fprintf( stderr, "bmp.info.biCompression = %ld\n", bmp_info->biCompression );
01963 fprintf( stderr, "bmp.info.biSizeImage = %ld\n", bmp_info->biSizeImage );
01964 #endif
01965 if( ((int)(bmp_info->biHeight)) < 0 )
01966 direction = 1 ;
01967 if( height == 0 )
01968 height = direction == 1 ? -((long)(bmp_info->biHeight)):bmp_info->biHeight ;
01969 if( width == 0 )
01970 width = bmp_info->biWidth ;
01971
01972 if( !success || bmp_info->biCompression != 0 ||
01973 width > MAX_IMPORT_IMAGE_SIZE ||
01974 height > MAX_IMPORT_IMAGE_SIZE )
01975 {
01976 return NULL;
01977 }
01978 if( bmp_info->biBitCount < 16 )
01979 cmap_entries = 0x01<<bmp_info->biBitCount ;
01980
01981 if( bmp_info->biSize != 40 )
01982 cmap_entry_size = 3;
01983 if( cmap_entries )
01984 {
01985 cmap = safemalloc( cmap_entries * cmap_entry_size );
01986 if (fread(cmap, sizeof (CARD8), cmap_entries * cmap_entry_size, infile)){;};
01987 }
01988
01989 if( add_colormap )
01990 data_offset += cmap_entries*cmap_entry_size ;
01991
01992 fseek( infile, data_offset, SEEK_SET );
01993 row_size = (width*bmp_info->biBitCount)>>3 ;
01994 if( row_size == 0 )
01995 row_size = 1 ;
01996 else
01997 row_size = (row_size+3)/4 ;
01998 row_size *= 4 ;
01999 data = safemalloc( row_size );
02000
02001 im = create_asimage( width, height, compression );
02002
02003 prepare_scanline( im->width, 0, buf, True );
02004
02005 y =( direction == 1 )?0:height-1 ;
02006 while( y >= 0 && y < (int)height)
02007 {
02008 if( fread( data, sizeof (char), row_size, infile ) < (unsigned int)row_size )
02009 break;
02010 dib_data_to_scanline(buf, bmp_info, gamma_table, data, cmap, cmap_entry_size);
02011 asimage_add_line (im, IC_RED, buf->red , y);
02012 asimage_add_line (im, IC_GREEN, buf->green, y);
02013 asimage_add_line (im, IC_BLUE, buf->blue , y);
02014 y += direction ;
02015 }
02016 free( data );
02017 if( cmap )
02018 free( cmap );
02019 return im ;
02020 }
02021
02022 ASImage *
02023 bmp2ASImage( const char * path, ASImageImportParams *params )
02024 {
02025 ASImage *im = NULL ;
02026
02027 FILE *infile;
02028 ASScanline buf;
02029 BITMAPFILEHEADER bmp_header ;
02030 BITMAPINFOHEADER bmp_info;
02031 START_TIME(started);
02032
02033
02034 if ((infile = open_image_file(path)) == NULL)
02035 return NULL;
02036
02037 bmp_header.bfType = 0 ;
02038 if( bmp_read16( infile, &bmp_header.bfType, 1 ) )
02039 if( bmp_header.bfType == BMP_SIGNATURE )
02040 if( bmp_read32( infile, &bmp_header.bfSize, 3 ) == 3 )
02041 im = read_bmp_image( infile, bmp_header.bfOffBits, &bmp_info, &buf, params->gamma_table, 0, 0, False, params->compression );
02042 #ifdef LOCAL_DEBUG
02043 fprintf( stderr, "bmp.header.bfType = 0x%X\nbmp.header.bfSize = %ld\nbmp.header.bfOffBits = %ld(0x%lX)\n",
02044 bmp_header.bfType, bmp_header.bfSize, bmp_header.bfOffBits, bmp_header.bfOffBits );
02045 #endif
02046 if( im != NULL )
02047 free_scanline( &buf, True );
02048 else
02049 show_error( "invalid or unsupported BMP format in image file \"%s\"", path );
02050
02051 fclose( infile );
02052 SHOW_TIME("image loading",started);
02053 return im ;
02054 }
02055
02056
02057
02058
02059 ASImage *
02060 ico2ASImage( const char * path, ASImageImportParams *params )
02061 {
02062 ASImage *im = NULL ;
02063
02064 FILE *infile;
02065 ASScanline buf;
02066 int y, mask_bytes;
02067 CARD8 *and_mask;
02068 START_TIME(started);
02069 struct IconDirectoryEntry {
02070 CARD8 bWidth;
02071 CARD8 bHeight;
02072 CARD8 bColorCount;
02073 CARD8 bReserved;
02074 CARD16 wPlanes;
02075 CARD16 wBitCount;
02076 CARD32 dwBytesInRes;
02077 CARD32 dwImageOffset;
02078 };
02079 struct ICONDIR {
02080 CARD16 idReserved;
02081 CARD16 idType;
02082 CARD16 idCount;
02083 } icon_dir;
02084 struct IconDirectoryEntry icon;
02085 BITMAPINFOHEADER bmp_info;
02086
02087 if ((infile = open_image_file(path)) == NULL)
02088 return NULL;
02089
02090 icon_dir.idType = 0 ;
02091 if( bmp_read16( infile, &icon_dir.idReserved, 3 ) == 3)
02092 if( icon_dir.idType == 1 || icon_dir.idType == 2)
02093 {
02094 if (fread( &(icon.bWidth), sizeof(CARD8),4,infile )){;};
02095 bmp_read16( infile, &(icon.wPlanes), 2 );
02096 if( bmp_read32( infile, &(icon.dwBytesInRes), 2 ) == 2 )
02097 {
02098 fseek( infile, icon.dwImageOffset, SEEK_SET );
02099 im = read_bmp_image( infile, icon.dwImageOffset+40+(icon.bColorCount*4), &bmp_info, &buf, params->gamma_table,
02100 icon.bWidth, icon.bHeight, (icon.bColorCount==0), params->compression );
02101 }
02102 }
02103 #ifdef LOCAL_DEBUG
02104 fprintf( stderr, "icon.dir.idType = 0x%X\nicon.dir.idCount = %d\n", icon_dir.idType, icon_dir.idCount );
02105 fprintf( stderr, "icon[1].bWidth = %d(0x%X)\n", icon.bWidth, icon.bWidth );
02106 fprintf( stderr, "icon[1].bHeight = %d(0x%X)\n", icon.bHeight, icon.bHeight );
02107 fprintf( stderr, "icon[1].bColorCount = %d\n", icon.bColorCount );
02108 fprintf( stderr, "icon[1].dwImageOffset = %ld(0x%lX)\n", icon.dwImageOffset, icon.dwImageOffset );
02109 fprintf( stderr, "icon[1].bmp_size = %ld\n", icon.dwBytesInRes );
02110 fprintf( stderr, "icon[1].dwBytesInRes = %ld\n", icon.dwBytesInRes );
02111 #endif
02112 if( im != NULL )
02113 {
02114 mask_bytes = ((icon.bWidth>>3)+3)/4 ;
02115 mask_bytes *= 4 ;
02116 and_mask = safemalloc( mask_bytes );
02117 for( y = icon.bHeight-1 ; y >= 0 ; y-- )
02118 {
02119 int x ;
02120 if( fread( and_mask, sizeof (CARD8), mask_bytes, infile ) < (unsigned int)mask_bytes )
02121 break;
02122 for( x = 0 ; x < icon.bWidth ; ++x )
02123 {
02124 buf.alpha[x] = (and_mask[x>>3]&(0x80>>(x&0x7)))? 0x0000 : 0x00FF ;
02125 }
02126 im->channels[IC_ALPHA][y] = store_data( NULL, (CARD8*)buf.alpha, im->width*4,
02127 ASStorage_32BitRLE|ASStorage_Bitmap, 0);
02128 }
02129 free( and_mask );
02130 free_scanline( &buf, True );
02131 }else
02132 show_error( "invalid or unsupported ICO format in image file \"%s\"", path );
02133
02134 fclose( infile );
02135 SHOW_TIME("image loading",started);
02136 return im ;
02137 }
02138
02139
02140 #ifdef HAVE_GIF
02141
02142 int
02143 gif_interlaced2y(int line , int height)
02144 {
02145 int passed_lines = 0;
02146 int lines_in_current_pass;
02147
02148 lines_in_current_pass = height / 8 + (height%8?1:0);
02149 if (line < lines_in_current_pass)
02150 return line * 8;
02151
02152 passed_lines = lines_in_current_pass;
02153
02154 if (height > 4)
02155 {
02156 lines_in_current_pass = (height - 4) / 8 + ((height - 4)%8 ? 1 : 0);
02157 if (line < lines_in_current_pass + passed_lines)
02158 return 4 + 8*(line - passed_lines);
02159 passed_lines += lines_in_current_pass;
02160 }
02161
02162 if (height > 2)
02163 {
02164 lines_in_current_pass = (height - 2) / 4 + ((height - 2)%4 ? 1 : 0);
02165 if (line < lines_in_current_pass + passed_lines)
02166 return 2 + 4*(line - passed_lines);
02167 passed_lines += lines_in_current_pass;
02168 }
02169 return 1 + 2*(line - passed_lines);
02170 }
02171
02172
02173 ASImage *
02174 gif2ASImage( const char * path, ASImageImportParams *params )
02175 {
02176 FILE *fp ;
02177 int status = GIF_ERROR;
02178 GifFileType *gif;
02179 ASImage *im = NULL ;
02180 int transparent = -1 ;
02181 unsigned int y;
02182 unsigned int width = 0, height = 0;
02183 ColorMapObject *cmap = NULL ;
02184
02185 START_TIME(started);
02186
02187 params->return_animation_delay = 0 ;
02188
02189 if ((fp = open_image_file(path)) == NULL)
02190 return NULL;
02191 if( (gif = open_gif_read(fp)) != NULL )
02192 {
02193 SavedImage *sp = NULL ;
02194 int count = 0 ;
02195
02196 status = get_gif_saved_images(gif, params->subimage, &sp, &count );
02197 if( status == GIF_OK && sp != NULL && count > 0 )
02198 {
02199 GifPixelType *row_pointer ;
02200 #ifdef DEBUG_TRANSP_GIF
02201 fprintf( stderr, "Ext block = %p, count = %d\n", sp->ExtensionBlocks, sp->ExtensionBlockCount );
02202 #endif
02203 if( sp->ExtensionBlocks )
02204 for ( y = 0; y < (unsigned int)sp->ExtensionBlockCount; y++)
02205 {
02206 #ifdef DEBUG_TRANSP_GIF
02207 fprintf( stderr, "%d: func = %X, bytes[0] = 0x%X\n", y, sp->ExtensionBlocks[y].Function, sp->ExtensionBlocks[y].Bytes[0]);
02208 #endif
02209 if( sp->ExtensionBlocks[y].Function == GRAPHICS_EXT_FUNC_CODE )
02210 {
02211 if( sp->ExtensionBlocks[y].Bytes[0]&0x01 )
02212 {
02213 transparent = ((unsigned int) sp->ExtensionBlocks[y].Bytes[GIF_GCE_TRANSPARENCY_BYTE])&0x00FF;
02214 #ifdef DEBUG_TRANSP_GIF
02215 fprintf( stderr, "transp = %u\n", transparent );
02216 #endif
02217 }
02218 params->return_animation_delay = (((unsigned int) sp->ExtensionBlocks[y].Bytes[GIF_GCE_DELAY_BYTE_LOW])&0x00FF) +
02219 ((((unsigned int) sp->ExtensionBlocks[y].Bytes[GIF_GCE_DELAY_BYTE_HIGH])<<8)&0x00FF00);
02220 }else if( sp->ExtensionBlocks[y].Function == APPLICATION_EXT_FUNC_CODE && sp->ExtensionBlocks[y].ByteCount == 11 )
02221 {
02222 if( strncmp(&(sp->ExtensionBlocks[y].Bytes[0]), "NETSCAPE2.0", 11 ) == 0 )
02223 {
02224 ++y ;
02225 if( y < (unsigned int)sp->ExtensionBlockCount && sp->ExtensionBlocks[y].ByteCount == 3 )
02226 {
02227 params->return_animation_repeats = (((unsigned int) sp->ExtensionBlocks[y].Bytes[GIF_NETSCAPE_REPEAT_BYTE_LOW])&0x00FF) +
02228 ((((unsigned int) sp->ExtensionBlocks[y].Bytes[GIF_NETSCAPE_REPEAT_BYTE_HIGH])<<8)&0x00FF00);
02229
02230 #ifdef DEBUG_TRANSP_GIF
02231 fprintf( stderr, "animation_repeats = %d\n", params->return_animation_repeats );
02232 #endif
02233 }
02234 }
02235 }
02236 }
02237 cmap = gif->SColorMap ;
02238
02239 cmap = (sp->ImageDesc.ColorMap == NULL)?gif->SColorMap:sp->ImageDesc.ColorMap;
02240 width = sp->ImageDesc.Width;
02241 height = sp->ImageDesc.Height;
02242
02243 if( cmap != NULL && (row_pointer = (unsigned char*)sp->RasterBits) != NULL &&
02244 width < MAX_IMPORT_IMAGE_SIZE && height < MAX_IMPORT_IMAGE_SIZE )
02245 {
02246 int bg_color = gif->SBackGroundColor ;
02247 int interlaced = sp->ImageDesc.Interlace;
02248 int image_y;
02249 CARD8 *r = NULL, *g = NULL, *b = NULL, *a = NULL ;
02250 int old_storage_block_size ;
02251 r = safemalloc( width );
02252 g = safemalloc( width );
02253 b = safemalloc( width );
02254 a = safemalloc( width );
02255
02256 im = create_asimage( width, height, params->compression );
02257 old_storage_block_size = set_asstorage_block_size( NULL, im->width*im->height*3/2 );
02258
02259 for (y = 0; y < height; ++y)
02260 {
02261 unsigned int x ;
02262 Bool do_alpha = False ;
02263 image_y = interlaced ? gif_interlaced2y(y, height):y;
02264 for (x = 0; x < width; ++x)
02265 {
02266 int c = row_pointer[x];
02267 if ( c == transparent)
02268 {
02269 c = bg_color ;
02270 do_alpha = True ;
02271 a[x] = 0 ;
02272 }else
02273 a[x] = 0x00FF ;
02274
02275 r[x] = cmap->Colors[c].Red;
02276 g[x] = cmap->Colors[c].Green;
02277 b[x] = cmap->Colors[c].Blue;
02278 }
02279 row_pointer += x ;
02280 im->channels[IC_RED][image_y] = store_data( NULL, r, width, ASStorage_RLEDiffCompress, 0);
02281 im->channels[IC_GREEN][image_y] = store_data( NULL, g, width, ASStorage_RLEDiffCompress, 0);
02282 im->channels[IC_BLUE][image_y] = store_data( NULL, b, width, ASStorage_RLEDiffCompress, 0);
02283 if( do_alpha )
02284 im->channels[IC_ALPHA][image_y] = store_data( NULL, a, im->width, ASStorage_RLEDiffCompress|ASStorage_Bitmap, 0);
02285 }
02286 set_asstorage_block_size( NULL, old_storage_block_size );
02287 free(a);
02288 free(b);
02289 free(g);
02290 free(r);
02291 }
02292 free_gif_saved_images( sp, count );
02293 }else if( status != GIF_OK )
02294 ASIM_PrintGifError();
02295 else if( params->subimage == -1 )
02296 show_error( "Image file \"%s\" does not have any valid image information.", path );
02297 else
02298 show_error( "Image file \"%s\" does not have subimage %d.", path, params->subimage );
02299
02300 DGifCloseFile(gif);
02301 fclose( fp );
02302 }
02303 SHOW_TIME("image loading",started);
02304 return im ;
02305 }
02306 #else
02307 ASImage *
02308 gif2ASImage( const char * path, ASImageImportParams *params )
02309 {
02310 show_error( "unable to load file \"%s\" - missing GIF image format libraries.\n", path );
02311 return NULL ;
02312 }
02313 #endif
02314
02315 #ifdef HAVE_TIFF
02316
02317
02318 ASImage *
02319 tiff2ASImage( const char * path, ASImageImportParams *params )
02320 {
02321 TIFF *tif ;
02322
02323 static ASImage *im = NULL ;
02324 CARD32 *data;
02325 int data_size;
02326 CARD32 width = 1, height = 1;
02327 CARD16 depth = 4 ;
02328 CARD16 bits = 0 ;
02329 CARD32 rows_per_strip =0 ;
02330 CARD32 tile_width = 0, tile_length = 0 ;
02331 CARD32 planar_config = 0 ;
02332 CARD16 photo = 0;
02333 START_TIME(started);
02334
02335 if ((tif = TIFFOpen(path,"r")) == NULL)
02336 {
02337 show_error("cannot open image file \"%s\" for reading. Please check permissions.", path);
02338 return NULL;
02339 }
02340
02341 #ifdef DEBUG_TIFF
02342 {;}
02343 #endif
02344 if( params->subimage > 0 )
02345 if( !TIFFSetDirectory(tif, params->subimage))
02346 {
02347 TIFFClose(tif);
02348 show_error("Image file \"%s\" does not contain subimage %d.", path, params->subimage);
02349 return NULL ;
02350 }
02351
02352 TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width);
02353 TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height);
02354 if( !TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &depth) )
02355 depth = 3 ;
02356 if( !TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bits) )
02357 bits = 8 ;
02358 if( !TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &rows_per_strip ) )
02359 rows_per_strip = height ;
02360 if( !TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photo) )
02361 photo = 0 ;
02362
02363 #ifndef PHOTOMETRIC_CFA
02364 #define PHOTOMETRIC_CFA 32803
02365 #endif
02366
02367 TIFFGetField(tif, TIFFTAG_PLANARCONFIG, &planar_config);
02368
02369 if( TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tile_width) ||
02370 TIFFGetField(tif, TIFFTAG_TILELENGTH, &tile_length) )
02371 {
02372 show_error( "Tiled TIFF image format is not supported yet." );
02373 TIFFClose(tif);
02374 return NULL;
02375 }
02376
02377
02378 if( rows_per_strip == 0 || rows_per_strip > height )
02379 rows_per_strip = height ;
02380 if( depth <= 0 )
02381 depth = 4 ;
02382 if( depth <= 2 && get_flags( photo, PHOTOMETRIC_RGB) )
02383 depth += 2 ;
02384 LOCAL_DEBUG_OUT ("size = %ldx%ld, depth = %d, bits = %d, rps = %ld, photo = %d, tile_size = %dx%d, config = %d",
02385 width, height, depth, bits, rows_per_strip, photo, tile_width, tile_length, planar_config);
02386 if( width < MAX_IMPORT_IMAGE_SIZE && height < MAX_IMPORT_IMAGE_SIZE )
02387 {
02388 data_size = width*rows_per_strip*sizeof(CARD32);
02389 data = (CARD32*) _TIFFmalloc(data_size);
02390 if (data != NULL)
02391 {
02392 CARD8 *r = NULL, *g = NULL, *b = NULL, *a = NULL ;
02393 ASFlagType store_flags = ASStorage_RLEDiffCompress ;
02394 int first_row = 0 ;
02395 int old_storage_block_size;
02396 if( bits == 1 )
02397 set_flags( store_flags, ASStorage_Bitmap );
02398
02399 im = create_asimage( width, height, params->compression );
02400 old_storage_block_size = set_asstorage_block_size( NULL, im->width*im->height*3/2 );
02401
02402 if( depth == 2 || depth == 4 )
02403 a = safemalloc( width );
02404 r = safemalloc( width );
02405 if( depth > 2 )
02406 {
02407 g = safemalloc( width );
02408 b = safemalloc( width );
02409 }
02410 if (photo == PHOTOMETRIC_CFA)
02411 {
02412 Bool success = False;
02413
02414 ASIMStrip *strip = create_asim_strip(10, im->width, 8, True);
02415 ASImageOutput *imout = start_image_output( NULL, im, ASA_ASImage, 8, ASIMAGE_QUALITY_DEFAULT);
02416
02417 LOCAL_DEBUG_OUT( "custom CFA TIFF reading...");
02418
02419 if (strip && imout)
02420 {
02421 int cfa_type = 0;
02422 ASIMStripLoader line_loaders[2][2] =
02423 { {decode_RG_12_be, decode_GB_12_be},
02424 {decode_BG_12_be, decode_GR_12_be}
02425 };
02426 int line_loaders_num[2] = {2, 2};
02427
02428 int bytes_per_row = (bits * width + 7)/8;
02429 int loaded_data_size = 0;
02430
02431 if ( 1)
02432 {
02433 int strip_no;
02434 uint32* bc;
02435 TIFFGetField(tif, TIFFTAG_STRIPBYTECOUNTS, &bc);
02436 int all_strip_size = 0;
02437 for (strip_no = 0; strip_no < TIFFNumberOfStrips(tif); ++strip_no)
02438 all_strip_size += bc[strip_no];
02439
02440 if (data_size < all_strip_size)
02441 {
02442 data_size = all_strip_size;
02443 _TIFFfree(data);
02444 data = _TIFFmalloc(data_size);
02445 }
02446
02447 if (planar_config == PLANARCONFIG_CONTIG)
02448 {
02449 for (strip_no = 0; strip_no < TIFFNumberOfStrips(tif); strip_no++)
02450 {
02451 int bytes_in;
02452 if (bits == 12)
02453 {
02454
02455
02456
02457 bytes_in = TIFFReadRawStrip(tif, strip_no, data+loaded_data_size, data_size-loaded_data_size);
02458 }else
02459 bytes_in = TIFFReadEncodedStrip(tif, strip_no, data+loaded_data_size, data_size-loaded_data_size);
02460
02461 LOCAL_DEBUG_OUT( "strip size = %d, bytes_in = %d, bytes_per_row = %d", bc[strip_no], bytes_in, bytes_per_row);
02462 if (bytes_in >= 0)
02463 loaded_data_size += bytes_in;
02464 else
02465 {
02466 LOCAL_DEBUG_OUT( "failed reading strip %d", strip_no);
02467 }
02468 }
02469 } else if (planar_config == PLANARCONFIG_SEPARATE)
02470 {
02471
02472 }
02473 }else
02474 {
02475
02476 }
02477
02478 if (loaded_data_size > 0)
02479 {
02480 int offset;
02481 int data_row = 0;
02482 do
02483 {
02484 offset = data_row * bytes_per_row;
02485 int loaded_rows = load_asim_strip (strip, (CARD8*)data + offset, loaded_data_size-offset,
02486 data_row, bytes_per_row,
02487 line_loaders[cfa_type], line_loaders_num[cfa_type]);
02488
02489 if (loaded_rows == 0)
02490 {
02491 interpolate_asim_strip_custom_rggb2 (strip, SCL_DO_RED|SCL_DO_GREEN|SCL_DO_BLUE, False);
02492 #if 0
02493 if (!get_flags (strip->lines[0]->flags, SCL_DO_RED))
02494 {
02495 int x;
02496 for (x = 0; x < width; ++x)
02497 {
02498 strip->lines[0]->red[x] = strip->lines[1]->red[x];
02499 strip->lines[1]->blue[x] = strip->lines[0]->blue[x];
02500 }
02501 set_flags (strip->lines[0]->flags, SCL_DO_RED);
02502 set_flags (strip->lines[1]->flags, SCL_DO_BLUE);
02503 }
02504 #endif
02505
02506 imout->output_image_scanline( imout, strip->lines[0], 1);
02507
02508 advance_asim_strip (strip);
02509
02510 }
02511 data_row += loaded_rows;
02512 }while (offset < loaded_data_size);
02513 success = True;
02514 }
02515 }
02516 destroy_asim_strip (&strip);
02517 stop_image_output( &imout );
02518
02519 if (!success)
02520 destroy_asimage (&im);
02521 }else
02522 {
02523 TIFFReadRGBAStrip(tif, first_row, (void*)data);
02524 do
02525 {
02526 register CARD32 *row = data ;
02527 int y = first_row + rows_per_strip ;
02528 if( y > height )
02529 y = height ;
02530 while( --y >= first_row )
02531 {
02532 int x ;
02533 for( x = 0 ; x < width ; ++x )
02534 {
02535 CARD32 c = row[x] ;
02536 if( depth == 4 || depth == 2 )
02537 a[x] = TIFFGetA(c);
02538 r[x] = TIFFGetR(c);
02539 if( depth > 2 )
02540 {
02541 g[x] = TIFFGetG(c);
02542 b[x] = TIFFGetB(c);
02543 }
02544 }
02545 im->channels[IC_RED][y] = store_data( NULL, r, width, store_flags, 0);
02546 if( depth > 2 )
02547 {
02548 im->channels[IC_GREEN][y] = store_data( NULL, g, width, store_flags, 0);
02549 im->channels[IC_BLUE][y] = store_data( NULL, b, width, store_flags, 0);
02550 }else
02551 {
02552 im->channels[IC_GREEN][y] = dup_data( NULL, im->channels[IC_RED][y]);
02553 im->channels[IC_BLUE][y] = dup_data( NULL, im->channels[IC_RED][y]);
02554 }
02555
02556 if( depth == 4 || depth == 2 )
02557 im->channels[IC_ALPHA][y] = store_data( NULL, a, width, store_flags, 0);
02558 row += width ;
02559 }
02560
02561 do
02562 {
02563 first_row += rows_per_strip ;
02564 }while (first_row < height && !TIFFReadRGBAStrip(tif, first_row, (void*)data));
02565
02566 }while (first_row < height);
02567 }
02568 set_asstorage_block_size( NULL, old_storage_block_size );
02569
02570 if( b ) free( b );
02571 if( g ) free( g );
02572 if( r ) free( r );
02573 if( a ) free( a );
02574 _TIFFfree(data);
02575 }
02576 }
02577
02578 TIFFClose(tif);
02579 SHOW_TIME("image loading",started);
02580
02581 return im ;
02582 }
02583 #else
02584
02585 ASImage *
02586 tiff2ASImage( const char * path, ASImageImportParams *params )
02587 {
02588 show_error( "unable to load file \"%s\" - missing TIFF image format libraries.\n", path );
02589 return NULL ;
02590 }
02591 #endif
02592
02593
02594 static ASImage *
02595 load_xml2ASImage( ASImageManager *imman, const char *path, unsigned int compression, int width, int height )
02596 {
02597 ASVisual fake_asv ;
02598 char *slash, *curr_path = NULL ;
02599 char *doc_str = NULL ;
02600 ASImage *im = NULL ;
02601
02602 memset( &fake_asv, 0x00, sizeof(ASVisual) );
02603 if( (slash = strrchr( path, '/' )) != NULL )
02604 curr_path = mystrndup( path, slash-path );
02605
02606 if((doc_str = load_file(path)) == NULL )
02607 show_error( "unable to load file \"%s\" file is either too big or is not readable.\n", path );
02608 else
02609 {
02610 im = compose_asimage_xml_at_size(&fake_asv, imman, NULL, doc_str, 0, 0, None, curr_path, width, height);
02611 free( doc_str );
02612 }
02613
02614 if( curr_path )
02615 free( curr_path );
02616 return im ;
02617 }
02618
02619
02620 ASImage *
02621 xml2ASImage( const char *path, ASImageImportParams *params )
02622 {
02623 int width = -1, height = -1 ;
02624 static ASImage *im = NULL ;
02625 START_TIME(started);
02626
02627 if( get_flags( params->flags, AS_IMPORT_SCALED_H ) )
02628 width = (params->width <= 0)?((params->height<=0)?-1:params->height):params->width ;
02629
02630 if( get_flags( params->flags, AS_IMPORT_SCALED_V ) )
02631 height = (params->height <= 0)?((params->width <= 0)?-1:params->width):params->height ;
02632
02633 im = load_xml2ASImage( NULL, path, params->compression, width, height );
02634
02635 SHOW_TIME("image loading",started);
02636 return im ;
02637 }
02638
02639 #ifdef HAVE_SVG
02640 ASImage *
02641 svg2ASImage( const char * path, ASImageImportParams *params )
02642 {
02643 static int gType_inited = 0;
02644
02645 ASImage *im = NULL;
02646 GdkPixbuf *pixbuf;
02647 int channels ;
02648 Bool do_alpha ;
02649 int width = -1, height = -1 ;
02650
02651 START_TIME(started);
02652 #if 1
02653
02654
02655 if (gType_inited == 0)
02656 {
02657 g_type_init();
02658 gType_inited = 1;
02659 }
02660
02661 if( get_flags( params->flags, AS_IMPORT_SCALED_H ) )
02662 width = (params->width <= 0)?((params->height<=0)?-1:params->height):params->width ;
02663
02664 if( get_flags( params->flags, AS_IMPORT_SCALED_V ) )
02665 height = (params->height <= 0)?((params->width <= 0)?-1:params->width):params->height ;
02666
02667 if( (pixbuf = rsvg_pixbuf_from_file_at_size( path, width, height, NULL)) == NULL )
02668 return NULL ;
02669
02670 channels = gdk_pixbuf_get_n_channels(pixbuf) ;
02671 do_alpha = gdk_pixbuf_get_has_alpha(pixbuf) ;
02672 if ( ((channels == 4 && do_alpha) ||(channels == 3 && !do_alpha)) &&
02673 gdk_pixbuf_get_bits_per_sample(pixbuf) == 8 )
02674 {
02675 int width, height;
02676 register CARD8 *row = gdk_pixbuf_get_pixels(pixbuf);
02677 int y;
02678 CARD8 *r = NULL, *g = NULL, *b = NULL, *a = NULL ;
02679 int old_storage_block_size;
02680
02681 width = gdk_pixbuf_get_width(pixbuf);
02682 height = gdk_pixbuf_get_height(pixbuf);
02683
02684 r = safemalloc( width );
02685 g = safemalloc( width );
02686 b = safemalloc( width );
02687 if( do_alpha )
02688 a = safemalloc( width );
02689
02690
02691 im = create_asimage(width, height, params->compression );
02692 old_storage_block_size = set_asstorage_block_size( NULL, im->width*im->height*3/2 );
02693 for (y = 0; y < height; ++y)
02694 {
02695 int x, i = 0 ;
02696 for( x = 0 ; x < width ; ++x )
02697 {
02698 r[x] = row[i++];
02699 g[x] = row[i++];
02700 b[x] = row[i++];
02701 if( do_alpha )
02702 a[x] = row[i++];
02703 }
02704 im->channels[IC_RED][y] = store_data( NULL, r, width, ASStorage_RLEDiffCompress, 0);
02705 im->channels[IC_GREEN][y] = store_data( NULL, g, width, ASStorage_RLEDiffCompress, 0);
02706 im->channels[IC_BLUE][y] = store_data( NULL, b, width, ASStorage_RLEDiffCompress, 0);
02707
02708 if( do_alpha )
02709 for( x = 0 ; x < width ; ++x )
02710 if( a[x] != 0x00FF )
02711 {
02712 im->channels[IC_ALPHA][y] = store_data( NULL, a, width, ASStorage_RLEDiffCompress, 0);
02713 break;
02714 }
02715 row += channels*width ;
02716 }
02717 set_asstorage_block_size( NULL, old_storage_block_size );
02718 free(r);
02719 free(g);
02720 free(b);
02721 if( a )
02722 free(a);
02723 }
02724
02725 if (pixbuf)
02726 gdk_pixbuf_unref(pixbuf);
02727 #endif
02728 SHOW_TIME("image loading",started);
02729
02730 return im ;
02731 }
02732 #else
02733
02734 ASImage *
02735 svg2ASImage( const char * path, ASImageImportParams *params )
02736 {
02737 show_error( "unable to load file \"%s\" - missing SVG image format libraries.\n", path );
02738 return NULL ;
02739 }
02740 #endif
02741
02742
02743
02744
02745
02746 typedef struct ASTGAHeader
02747 {
02748 CARD8 IDLength ;
02749 CARD8 ColorMapType;
02750 #define TGA_NoImageData 0
02751 #define TGA_ColormappedImage 1
02752 #define TGA_TrueColorImage 2
02753 #define TGA_BWImage 3
02754 #define TGA_RLEColormappedImage 9
02755 #define TGA_RLETrueColorImage 10
02756 #define TGA_RLEBWImage 11
02757 CARD8 ImageType;
02758 struct
02759 {
02760 CARD16 FirstEntryIndex ;
02761 CARD16 ColorMapLength ;
02762 CARD8 ColorMapEntrySize ;
02763 }ColormapSpec;
02764 struct
02765 {
02766 CARD16 XOrigin;
02767 CARD16 YOrigin;
02768 CARD16 Width;
02769 CARD16 Height;
02770 CARD8 Depth;
02771 #define TGA_LeftToRight (0x01<<4)
02772 #define TGA_TopToBottom (0x01<<5)
02773 CARD8 Descriptor;
02774 }ImageSpec;
02775
02776 }ASTGAHeader;
02777
02778 typedef struct ASTGAColorMap
02779 {
02780 int bytes_per_entry;
02781 int bytes_total ;
02782 CARD8 *data ;
02783 }ASTGAColorMap;
02784
02785 typedef struct ASTGAImageData
02786 {
02787 int bytes_per_pixel;
02788 int image_size;
02789 int bytes_total ;
02790 CARD8 *data ;
02791 }ASTGAImageData;
02792
02793 static Bool load_tga_colormapped(FILE *infile, ASTGAHeader *tga, ASTGAColorMap *cmap, ASScanline *buf, CARD8 *read_buf, CARD8 *gamma_table )
02794 {
02795
02796 return True;
02797 }
02798
02799 static Bool load_tga_truecolor(FILE *infile, ASTGAHeader *tga, ASTGAColorMap *cmap, ASScanline *buf, CARD8 *read_buf, CARD8 *gamma_table )
02800 {
02801 CARD32 *a = buf->alpha ;
02802 CARD32 *r = buf->red ;
02803 CARD32 *g = buf->green ;
02804 CARD32 *b = buf->blue ;
02805 int bpp = (tga->ImageSpec.Depth+7)/8;
02806 int bpl = buf->width*bpp;
02807 if( fread( read_buf, 1, bpl, infile ) != (unsigned int)bpl )
02808 return False;
02809 if( bpp == 3 )
02810 {
02811 unsigned int i;
02812 if( gamma_table )
02813 for( i = 0 ; i < buf->width ; ++i )
02814 {
02815 b[i] = gamma_table[*(read_buf++)];
02816 g[i] = gamma_table[*(read_buf++)];
02817 r[i] = gamma_table[*(read_buf++)];
02818 }
02819 else
02820 for( i = 0 ; i < buf->width ; ++i )
02821 {
02822 b[i] = *(read_buf++);
02823 g[i] = *(read_buf++);
02824 r[i] = *(read_buf++);
02825 }
02826 set_flags( buf->flags, SCL_DO_RED|SCL_DO_GREEN|SCL_DO_BLUE );
02827 }else if( bpp == 4 )
02828 {
02829 unsigned int i;
02830 for( i = 0 ; i < buf->width ; ++i )
02831 {
02832 b[i] = *(read_buf++);
02833 g[i] = *(read_buf++);
02834 r[i] = *(read_buf++);
02835 a[i] = *(read_buf++);
02836 }
02837 set_flags( buf->flags, SCL_DO_RED|SCL_DO_GREEN|SCL_DO_BLUE|SCL_DO_ALPHA );
02838 }
02839
02840 return True;
02841 }
02842
02843 static Bool load_tga_bw(FILE *infile, ASTGAHeader *tga, ASTGAColorMap *cmap, ASScanline *buf, CARD8 *read_buf, CARD8 *gamma_table )
02844 {
02845
02846 return True;
02847 }
02848
02849 static Bool load_tga_rle_colormapped(FILE *infile, ASTGAHeader *tga, ASTGAColorMap *cmap, ASScanline *buf, CARD8 *read_buf, CARD8 *gamma_table )
02850 {
02851
02852 return True;
02853 }
02854
02855 static Bool load_tga_rle_truecolor(FILE *infile, ASTGAHeader *tga, ASTGAColorMap *cmap, ASScanline *buf, CARD8 *read_buf, CARD8 *gamma_table )
02856 {
02857
02858 return True;
02859 }
02860
02861 static Bool load_tga_rle_bw(FILE *infile, ASTGAHeader *tga, ASTGAColorMap *cmap, ASScanline *buf, CARD8 *read_buf, CARD8 *gamma_table )
02862 {
02863
02864 return True;
02865 }
02866
02867
02868
02869 ASImage *
02870 tga2ASImage( const char * path, ASImageImportParams *params )
02871 {
02872 ASImage *im = NULL ;
02873
02874 FILE *infile;
02875 ASTGAHeader tga;
02876 ASTGAColorMap *cmap = NULL ;
02877 int width = 1, height = 1;
02878 START_TIME(started);
02879
02880
02881 if ((infile = open_image_file(path)) == NULL)
02882 return NULL;
02883 if( fread( &tga, 1, 3, infile ) == 3 )
02884 if( fread( &tga.ColormapSpec, 1, 5, infile ) == 5 )
02885 if( fread( &tga.ImageSpec, 1, 10, infile ) == 10 )
02886 {
02887 Bool success = True ;
02888 Bool (*load_row_func)(FILE *infile, ASTGAHeader *tga, ASTGAColorMap *cmap, ASScanline *buf, CARD8 *read_buf, CARD8 *gamma_table );
02889
02890 if( tga.IDLength > 0 )
02891 success = (fseek( infile, tga.IDLength, SEEK_CUR )==0);
02892 if( success && tga.ColorMapType != 0 )
02893 {
02894 cmap = safecalloc( 1, sizeof(ASTGAColorMap));
02895 cmap->bytes_per_entry = (tga.ColormapSpec.ColorMapEntrySize+7)/8;
02896 cmap->bytes_total = cmap->bytes_per_entry*tga.ColormapSpec.ColorMapLength;
02897 cmap->data = safemalloc( cmap->bytes_total);
02898 success = ( fread( cmap->data, 1, cmap->bytes_total, infile ) == (unsigned int)cmap->bytes_total );
02899 }else if( tga.ImageSpec.Depth != 24 && tga.ImageSpec.Depth != 32 )
02900 success = False ;
02901
02902 if( success )
02903 {
02904 success = False;
02905 if( tga.ImageType != TGA_NoImageData )
02906 {
02907 width = tga.ImageSpec.Width ;
02908 height = tga.ImageSpec.Height ;
02909 if( width < MAX_IMPORT_IMAGE_SIZE && height < MAX_IMPORT_IMAGE_SIZE )
02910 success = True;
02911 }
02912 }
02913 switch( tga.ImageType )
02914 {
02915 case TGA_ColormappedImage :load_row_func = load_tga_colormapped ; break ;
02916 case TGA_TrueColorImage :load_row_func = load_tga_truecolor ; break ;
02917 case TGA_BWImage :load_row_func = load_tga_bw ; break ;
02918 case TGA_RLEColormappedImage:load_row_func = load_tga_rle_colormapped ; break ;
02919 case TGA_RLETrueColorImage :load_row_func = load_tga_rle_truecolor ; break ;
02920 case TGA_RLEBWImage :load_row_func = load_tga_rle_bw ; break ;
02921 default:
02922 load_row_func = NULL ;
02923 }
02924
02925 if( success && load_row_func != NULL )
02926 {
02927 ASImageOutput *imout ;
02928 int old_storage_block_size;
02929 im = create_asimage( width, height, params->compression );
02930 old_storage_block_size = set_asstorage_block_size( NULL, im->width*im->height*3/2 );
02931
02932 if((imout = start_image_output( NULL, im, ASA_ASImage, 0, ASIMAGE_QUALITY_DEFAULT)) == NULL )
02933 {
02934 destroy_asimage( &im );
02935 success = False;
02936 }else
02937 {
02938 ASScanline buf;
02939 int y ;
02940 CARD8 *read_buf = safemalloc( width*4*2 );
02941 prepare_scanline( im->width, 0, &buf, True );
02942 if( !get_flags( tga.ImageSpec.Descriptor, TGA_TopToBottom ) )
02943 toggle_image_output_direction( imout );
02944 for( y = 0 ; y < height ; ++y )
02945 {
02946 if( !load_row_func( infile, &tga, cmap, &buf, read_buf, params->gamma_table ) )
02947 break;
02948 imout->output_image_scanline( imout, &buf, 1);
02949 }
02950 stop_image_output( &imout );
02951 free_scanline( &buf, True );
02952 free( read_buf );
02953 }
02954 set_asstorage_block_size( NULL, old_storage_block_size );
02955
02956 }
02957 }
02958 if( im == NULL )
02959 show_error( "invalid or unsupported TGA format in image file \"%s\"", path );
02960
02961 if (cmap) free (cmap);
02962 fclose( infile );
02963 SHOW_TIME("image loading",started);
02964 return im ;
02965 }
02966
02967
02968
02969 ASImage *
02970 convert_argb2ASImage( ASVisual *asv, int width, int height, ARGB32 *argb, CARD8 *gamma_table )
02971 {
02972 ASImage *im = NULL ;
02973 ASImageOutput *imout ;
02974 im = create_asimage( width, height, 100 );
02975 if((imout = start_image_output( NULL, im, ASA_ASImage, 0, ASIMAGE_QUALITY_DEFAULT)) == NULL )
02976 {
02977 destroy_asimage( &im );
02978 return NULL;
02979 }else
02980 {
02981 ASScanline buf;
02982 int y ;
02983 int old_storage_block_size = set_asstorage_block_size( NULL, im->width*im->height*3 );
02984
02985 prepare_scanline( im->width, 0, &buf, True );
02986 for( y = 0 ; y < height ; ++y )
02987 {
02988 int x ;
02989 for( x = 0 ; x < width ; ++x )
02990 {
02991 ARGB32 c = argb[x];
02992 buf.alpha[x] = ARGB32_ALPHA8(c);
02993 buf.red[x] = ARGB32_RED8(c);
02994 buf.green[x] = ARGB32_GREEN8(c);
02995 buf.blue[x] = ARGB32_BLUE8(c);
02996 }
02997 argb += width ;
02998 set_flags( buf.flags, SCL_DO_RED|SCL_DO_GREEN|SCL_DO_BLUE|SCL_DO_ALPHA );
02999 imout->output_image_scanline( imout, &buf, 1);
03000 }
03001 set_asstorage_block_size( NULL, old_storage_block_size );
03002 stop_image_output( &imout );
03003 free_scanline( &buf, True );
03004 }
03005
03006 return im ;
03007 }
03008
03009
03010 ASImage *
03011 argb2ASImage( const char *path, ASImageImportParams *params )
03012 {
03013 ASVisual fake_asv ;
03014 long argb_data_len = -1;
03015 char *argb_data = NULL ;
03016 ASImage *im = NULL ;
03017
03018 memset( &fake_asv, 0x00, sizeof(ASVisual) );
03019
03020 argb_data = load_binary_file(path, &argb_data_len);
03021 if(argb_data == NULL || argb_data_len < 8 )
03022 show_error( "unable to load file \"%s\" file is either too big or is not readable.\n", path );
03023 else
03024 {
03025 int width = ((CARD32*)argb_data)[0] ;
03026 int height = ((CARD32*)argb_data)[1] ;
03027 if( 2 + width*height > (int)(argb_data_len/sizeof(CARD32)))
03028 {
03029 show_error( "file \"%s\" is too small for specified image size of %dx%d.\n", path, width, height );
03030 }else
03031 im = convert_argb2ASImage( &fake_asv, width, height, (ARGB32*)argb_data+2, params->gamma_table );
03032 }
03033 if( argb_data )
03034 free( argb_data );
03035
03036 return im ;
03037 }
03038