import.c

Go to the documentation of this file.
00001 /* This file contains code for unified image loading from many file formats */
00002 /********************************************************************/
00003 /* Copyright (c) 2001,2004 Sasha Vasko <sasha at aftercode.net>     */
00004 /* Copyright (c) 2004 Maxim Nikulin <nikulin at gorodok.net>        */
00005 /********************************************************************/
00006 /*
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020  */
00021 /*#undef NO_DEBUG_OUTPUT*/
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 /* Include file for users of png library. */
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 /* Include file for users of png library. */
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 /* <setjmp.h> is used for the optional error recovery mechanism */
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 /* High level interface :                                                                                                                  */
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                 /* first lets try to find file as it is */
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                 { /* let's try and see if appending .gz will make any difference */
00213                         strcpy(&(tmp[filename_len]), ".gz");
00214                         realfilename = locate_image_file(tmp,iparams->search_path);
00215                 }
00216                 if( realfilename == NULL )
00217                 { /* let's try and see if appending .Z will make any difference */
00218                         strcpy(&(tmp[filename_len]), ".Z");
00219                         realfilename = locate_image_file(tmp,iparams->search_path);
00220                 }
00221                 if( realfilename == NULL )
00222                 { /* let's try and see if we have subimage number appended */
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] == '.' )                 /* we have possible subimage number */
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                                         { /* let's try and see if appending .gz will make any difference */
00235                                                 strcpy(&(tmp[filename_len]), ".gz");
00236                                                 realfilename = locate_image_file(tmp,iparams->search_path);
00237                                         }
00238                                         if( realfilename == NULL )
00239                                         { /* let's try and see if appending .Z will make any difference */
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                 /* returned image must not be tracked by any ImageManager yet !!! */
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 ) /* simply scale it down to a thumbnail size */
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 /*fprintf( stderr, "im = %p. flags = 0x%lX\n", im, im->flags );         */
00587                                 if( get_flags( im->flags, ASIM_NAME_IS_FILENAME ) )
00588                                 {
00589 /*fprintf( stderr, "reloading image \"%s\" ...", im->name );*/
00590                                         ASImage *reloaded_im = load_image_from_path( im->name, &(imman->search_path[0]), imman->gamma);
00591 /*fprintf( stderr, "Done. reloaded_im = %p.\n", reloaded_im );*/                                        
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         /* TODO read new_buffer_size - entry->buffer_size bytes into the end of the buffer */
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 /* Some helper functions :                                                         */
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                         {       /* now lets try and find the file in any of the optional paths :*/
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         /* lets check if we have compressed xpm file : */
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 /*              fprintf( stderr, " IMAGE FILE HEADER READS : [%s][%c%c%c%c%c%c%c%c][%s], bytes_in = %d\n", (char*)&(head[0]),
00969                                                 head[0], head[1], head[2], head[3], head[4], head[5], head[6], head[7], strstr ((char *)&(head[0]), "XPM"),bytes_in );
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                         {/* the nastiest check - for XML files : */
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      /* XPM XPM XPM XPM XPM XPM XPM XPM XPM XPM XPM XPM XPM XPM XPM 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                   /* XPM XPM XPM XPM XPM XPM XPM XPM XPM XPM XPM XPM XPM XPM XPM XPM */
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                  /* XPM XPM XPM XPM XPM XPM XPM XPM XPM XPM XPM XPM XPM XPM XPM XPM */
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         /* PNG PNG PNG PNG PNG PNG PNG PNG PNG PNG PNG PNG PNG PNG PNG 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         /* Create and initialize the png_struct with the desired error handler
01240          * functions.  If you want to use the default stderr and longjump method,
01241          * you can supply NULL for the last three parameters.  We also supply the
01242          * the compiler header file version, so that we know if the application
01243          * was compiled with a compatible version of the library.  REQUIRED
01244          */
01245         if((png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)) != NULL )
01246         {
01247                 /* Allocate/initialize the memory for image information.  REQUIRED. */
01248                 if( (info_ptr = png_create_info_struct (png_ptr)) != NULL )
01249                 {
01250                         /* Set error handling if you are using the setjmp/longjmp method (this is
01251                          * the normal method of doing things with libpng).  REQUIRED unless you
01252                          * set up your own error handlers in the png_create_read_struct() earlier.
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 /*fprintf( stderr, "bit_depth = %d, color_type = %d, width = %d, height = %d\n", 
01270          bit_depth, color_type, width, height); 
01271 */
01272                                 if (bit_depth < 8)
01273                                 {/* Extract multiple pixels with bit depths of 1, 2, and 4 from a single
01274                                   * byte into separate bytes (useful for paletted and grayscale images).
01275                                   */
01276                                         if( bit_depth == 1 ) 
01277                                         {
01278                                                 set_flags( rgb_flags, ASStorage_Bitmap );
01279                                                 png_set_packing (png_ptr);
01280                                         }else
01281                                         {
01282                                                 /* even though 2 and 4 bit values get expanded into a whole bytes the 
01283                                                    values don't get scaled accordingly !!! 
01284                                                    WE will have to take care of it ourselves :
01285                                                 */      
01286                                                 upscaled_gray = safemalloc(width+8);
01287                                         }
01288                                 }else if (bit_depth == 16)
01289                                 {/* tell libpng to strip 16 bit/color files down to 8 bits/color */
01290                                         png_set_strip_16 (png_ptr);
01291                                 }
01292 
01293                                 /* Expand paletted colors into true RGB triplets */
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                                 /* Expand paletted or RGB images with transparency to full alpha channels
01301                                  * so the data will be available as RGBA quartets.
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 /*                              if( color_type == PNG_COLOR_TYPE_RGB )
01317                                         color_type = PNG_COLOR_TYPE_RGB_ALPHA ;
01318                                 else
01319                                         color_type = PNG_COLOR_TYPE_GRAY_ALPHA ;
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                                 {/* don't gamma-correct 1, 2, 4 bpp grays as we loose data this way */
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                                 /* Optional call to gamma correct and add the background to the palette
01333                                  * and update info structure.  REQUIRED if you are expecting libpng to
01334                                  * update the palette for you (ie you selected such a transform above).
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 /* fprintf( stderr, "do_alpha = %d, grayscale = %d, bit_depth = %d, color_type = %d, width = %d, height = %d\n", 
01347          do_alpha, grayscale, bit_depth, color_type, width, height); */
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                                 /* allocating big chunk of memory at once, to enable mmap
01356                                  * that will release memory to system right after free() */
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                                 /* The easiest way to read the image: */
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                                 /* read rest of file, and get additional chunks in info_ptr - REQUIRED */
01445                                 png_read_end (png_ptr, info_ptr);
01446                         }
01447                 }
01448                 /* clean up after the read, and free any memory allocated - REQUIRED */
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 /****** VO ******/
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                   /* PNG PNG PNG PNG PNG PNG PNG PNG PNG PNG PNG PNG PNG PNG PNG PNG */
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                  /* PNG PNG PNG PNG PNG PNG PNG PNG PNG PNG PNG PNG PNG PNG PNG PNG */
01516 /***********************************************************************************/
01517 
01518 
01519 /***********************************************************************************/
01520 #ifdef HAVE_JPEG     /* JPEG JPEG JPEG JPEG JPEG JPEG JPEG JPEG JPEG JPEG JPEG JPEG JPEG */
01521 struct my_error_mgr
01522 {
01523         struct jpeg_error_mgr pub;                                 /* "public" fields */
01524         jmp_buf       setjmp_buffer;                       /* for return to caller */
01525 };
01526 typedef struct my_error_mgr *my_error_ptr;
01527 
01528 METHODDEF (void)
01529 my_error_exit (j_common_ptr cinfo)
01530 {
01531         /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
01532         my_error_ptr  myerr = (my_error_ptr) cinfo->err;
01533         /* Always display the message. */
01534         /* We could postpone this until after returning, if we chose. */
01535         (*cinfo->err->output_message) (cinfo);
01536         /* Return control to the setjmp point */
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         /* This struct contains the JPEG decompression parameters and pointers to
01546          * working space (which is allocated as needed by the JPEG library).
01547          */
01548         struct jpeg_decompress_struct cinfo;
01549         void *temp_cinfo = NULL;
01550         /* We use our private extension JPEG error handler.
01551          * Note that this struct must live as long as the main JPEG parameter
01552          * struct, to avoid dangling-pointer problems.
01553          */
01554         struct my_error_mgr jerr;
01555         /* More stuff */
01556         FILE         *infile;                                      /* source file */
01557         JSAMPARRAY    buffer;                                      /* Output row buffer */
01558         ASScanline    buf;
01559         int y;
01560         START_TIME(started);
01561  /*     register int i ;*/
01562 
01563         /* we want to open the input file before doing anything else,
01564          * so that the setjmp() error recovery below can assume the file is open.
01565          * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
01566          * requires it in order to read binary files.
01567          */
01568 
01569         if ((infile = open_image_file(path)) == NULL)
01570                 return NULL;
01571 
01572         /* Step 1: allocate and initialize JPEG decompression object */
01573         /* We set up the normal JPEG error routines, then override error_exit. */
01574         cinfo.err = jpeg_std_error (&jerr.pub);
01575         jerr.pub.error_exit = my_error_exit;
01576         /* Establish the setjmp return context for my_error_exit to use. */
01577         if (setjmp (jerr.setjmp_buffer))
01578         {
01579                 /* If we get here, the JPEG code has signaled an error.
01580                    * We need to clean up the JPEG object, close the input file, and return.
01581                  */
01582                 jpeg_destroy_decompress (&cinfo);
01583                 fclose (infile);
01584                 return NULL;
01585         }
01586         /* Now we can initialize the JPEG decompression object. */
01587         jpeg_create_decompress (&cinfo);
01588         /* Step 2: specify data source (eg, a file) */
01589         jpeg_stdio_src (&cinfo, infile);
01590         /* Step 3: read file parameters with jpeg_read_header() */
01591         (void)jpeg_read_header (&cinfo, TRUE);
01592         /* We can ignore the return value from jpeg_read_header since
01593          *   (a) suspension is not possible with the stdio data source, and
01594          *   (b) we passed TRUE to reject a tables-only JPEG file as an error.
01595          * See libjpeg.doc for more info.
01596          */
01597 
01598         /* Step 4: set parameters for decompression */
01599         /* Adjust default decompression parameters */
01600         cinfo.quantize_colors = FALSE;                 /* we don't want no stinking colormaps ! */
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                 /* only supported values are 1, 2, 4, and 8 */
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         {/* this does not really makes much of a difference */
01642                 cinfo.do_fancy_upsampling = FALSE ; 
01643                 cinfo.do_block_smoothing = FALSE ; 
01644                 cinfo.dct_method = JDCT_IFAST ; 
01645         }
01646         
01647         /* Step 5: Start decompressor */
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         /* Make a one-row-high sample array that will go away when done with image */
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         /* Step 6: while (scan lines remain to be read) */
01662         SHOW_TIME("loading initialization",started);
01663         y = -1 ;
01664         /*cinfo.output_scanline*/
01665 /*      for( i = 0 ; i < im->width ; i++ )      fprintf( stderr, "%3.3d    ", i );
01666         fprintf( stderr, "\n");
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                 /* jpeg_read_scanlines expects an array of pointers to scanlines.
01673                  * Here the array is only one element long, but you could ask for
01674                  * more than one scanline at a time if that's more convenient.
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 /*              fprintf( stderr, "src:");
01691                 for( i = 0 ; i < im->width ; i++ )
01692                         fprintf( stderr, "%2.2X%2.2X%2.2X ", buffer[0][i*3], buffer[0][i*3+1], buffer[0][i*3+2] );
01693                 fprintf( stderr, "\ndst:");
01694                 for( i = 0 ; i < im->width ; i++ )
01695                         fprintf( stderr, "%2.2X%2.2X%2.2X ", buf.red[i], buf.green[i], buf.blue[i] );
01696                 fprintf( stderr, "\n");
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         /* Step 7: Finish decompression */
01705         /* we must abort the decompress if not all lines were read */
01706         if (cinfo.output_scanline < cinfo.output_height)
01707                 jpeg_abort_decompress (&cinfo);
01708         else
01709                 (void)jpeg_finish_decompress (&cinfo);
01710         /* We can ignore the return value since suspension is not possible
01711          * with the stdio data source.
01712          */
01713         /* Step 8: Release JPEG decompression object */
01714         /* This is an important step since it will release a good deal of memory. */
01715         jpeg_destroy_decompress (&cinfo);
01716         /* After finish_decompress, we can close the input file.
01717          * Here we postpone it until after no more JPEG errors are possible,
01718          * so as to simplify the setjmp error logic above.  (Actually, I don't
01719          * think that jpeg_destroy can do an error exit, but why assume anything...)
01720          */
01721         fclose (infile);
01722         /* At this point you may want to check to see whether any corrupt-data
01723          * warnings occurred (test whether jerr.pub.num_warnings is nonzero).
01724          */
01725         SHOW_TIME("image loading",started);
01726         LOCAL_DEBUG_OUT("done loading JPEG image \"%s\"", path);
01727         return im ;
01728 }
01729 #else                   /* JPEG JPEG JPEG JPEG JPEG JPEG JPEG JPEG JPEG JPEG JPEG JPEG JPEG */
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                  /* JPEG JPEG JPEG JPEG JPEG JPEG JPEG JPEG JPEG JPEG JPEG JPEG JPEG */
01738 /***********************************************************************************/
01739 
01740 /***********************************************************************************/
01741 /* XCF - GIMP's native file format :                                                                                       */
01742 
01743 ASImage *
01744 xcf2ASImage( const char * path, ASImageImportParams *params )
01745 {
01746         ASImage *im = NULL ;
01747         /* More stuff */
01748         FILE         *infile;                                      /* source file */
01749         XcfImage  *xcf_im;
01750         START_TIME(started);
01751 
01752         /* we want to open the input file before doing anything else,
01753          * so that the setjmp() error recovery below can assume the file is open.
01754          * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
01755          * requires it in order to read binary files.
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         {/* TODO : temporary workaround untill we implement layers merging */
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 /* PPM/PNM file format :                                                                                                                           */
01793 ASImage *
01794 ppm2ASImage( const char * path, ASImageImportParams *params )
01795 {
01796         ASImage *im = NULL ;
01797         /* More stuff */
01798         FILE         *infile;                                      /* source file */
01799         ASScanline    buf;
01800         int y;
01801         unsigned int type = 0, width = 0, height = 0, colors = 0;
01802 #define PPM_BUFFER_SIZE 71                     /* Sun says that no line should be longer then this */
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                         {    /* we only support RAWBITS formats : */
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                 /*cinfo.output_scanline*/
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 /* Windows BMP file format :                                                                                                       */
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                         /* BMPs are encoded as Little Endian */
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                         /* BMPs are encoded as Little Endian */
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                         /* BMPs are encoded as Little Endian */
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                         /* BMPs are encoded as Little Endian */
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                 {/* long header */
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 ;            /* everything is aligned by 32 bits */
01998         row_size *= 4 ;                            /* in bytes  */
01999         data = safemalloc( row_size );
02000 
02001         im = create_asimage( width,  height, compression );
02002         /* Window BMP files are little endian  - we need to swap Red and Blue */
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         /* More stuff */
02027         FILE         *infile;                                      /* source file */
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 /* Windows ICO/CUR file format :                                                                                                   */
02058 
02059 ASImage *
02060 ico2ASImage( const char * path, ASImageImportParams *params )
02061 {
02062         ASImage *im = NULL ;
02063         /* More stuff */
02064         FILE         *infile;                                      /* source file */
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 ;    /* everything is aligned by 32 bits */
02115         mask_bytes *= 4 ;                      /* in bytes  */
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         /* GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF */
02141 
02142 int
02143 gif_interlaced2y(int line /* 0 -- (height - 1) */, int height)
02144 {
02145         int passed_lines = 0;
02146         int lines_in_current_pass;
02147         /* pass 1 */
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         /* pass 2 */
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         /* pass 3 */
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 ) /* application extension */
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                   /* GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF */
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                  /* GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF */
02314 
02315 #ifdef HAVE_TIFF/* TIFF TIFF TIFF TIFF TIFF TIFF TIFF TIFF TIFF TIFF TIFF TIFF 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                         {/* need alternative - more complicated method */
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/* striped image */)
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                                                 /* create one large buffer for the image data : */
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) /* can't use libTIFF's function - it can't handle 12bit data ! */
02453                                                                 {
02454                                                                         /* PENTAX cameras claim that data is compressed as runlength packbits - 
02455                                                                            it is not in fact run-length, which confuses libTIFF 
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                                                         /* TODO: do something with split channels */
02472                                                 }
02473                                         }else
02474                                         {
02475                                                 /* TODO: implement support for tiled images */
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                                                         { /* need to write out some rows to free up space */
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 //clear_flags (strip->lines[0]->flags, SCL_DO_GREEN|SCL_DO_BLUE);
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                                         /* move onto the next strip now : */
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         /* close the file */
02578         TIFFClose(tif);
02579         SHOW_TIME("image loading",started);
02580 
02581         return im ;
02582 }
02583 #else                   /* TIFF TIFF TIFF TIFF TIFF TIFF TIFF TIFF TIFF TIFF TIFF TIFF TIFF */
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                  /* TIFF TIFF TIFF TIFF TIFF TIFF TIFF TIFF TIFF TIFF TIFF TIFF TIFF */
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/* SVG SVG SVG SVG SVG SVG SVG SVG SVG SVG SVG SVG SVG SVG SVG 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         /* Damn gtk mess... must init once atleast.. can we just init
02654            several times or do we bork then? */
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                   /* SVG SVG SVG SVG SVG SVG SVG SVG SVG SVG SVG SVG SVG SVG SVG SVG */
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                  /* SVG SVG SVG SVG SVG SVG SVG SVG SVG SVG SVG SVG SVG SVG SVG SVG */
02741 
02742 
02743 /*************************************************************************/
02744 /* Targa Image format - some stuff borrowed from the GIMP.
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 ;  /* number of entries */ 
02762                 CARD8  ColorMapEntrySize ;  /* number of bits per entry */ 
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         /* More stuff */
02874         FILE         *infile;                                      /* source file */
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 /* ARGB                                                                                                                                  */
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 

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