export.c

Go to the documentation of this file.
00001 /* This file contains code for unified image writing into many file formats */
00002 /********************************************************************/
00003 /* Copyright (c) 2001 Sasha Vasko <sasha at aftercode.net>           */
00004 /********************************************************************/
00005 /*
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  */
00020 
00021 #undef LOCAL_DEBUG
00022 #ifdef _WIN32
00023 #include "win32/config.h"
00024 #else
00025 #include "config.h"
00026 #endif
00027 
00028 #ifdef HAVE_PNG
00029 /* Include file for users of png library. */
00030 # ifdef HAVE_BUILTIN_PNG
00031 #  include "libpng/png.h"
00032 # else
00033 #  include <png.h>
00034 # endif
00035 #else
00036 #include <setjmp.h>
00037 # ifdef HAVE_JPEG
00038 #   ifdef HAVE_UNISTD_H
00039 #     include <unistd.h>
00040 #   endif
00041 #   include <stdio.h>
00042 # endif
00043 #endif
00044 #ifdef HAVE_JPEG
00045 /* Include file for users of jpg library. */
00046 # undef HAVE_STDLIB_H
00047 # ifndef X_DISPLAY_MISSING
00048 #  include <X11/Xmd.h>
00049 # endif
00050 # ifdef HAVE_BUILTIN_JPEG
00051 #  include "libjpeg/jpeglib.h"
00052 # else
00053 #  include <jpeglib.h>
00054 # endif
00055 #endif
00056 /*#define DO_CLOCKING*/
00057 
00058 #if TIME_WITH_SYS_TIME
00059 # include <sys/time.h>
00060 # include <time.h>
00061 #else
00062 # if HAVE_SYS_TIME_H
00063 #  include <sys/time.h>
00064 # else
00065 #  include <time.h>
00066 # endif
00067 #endif
00068 #ifdef HAVE_UNISTD_H
00069 #include <unistd.h>
00070 #endif
00071 #ifdef HAVE_STDLIB_H
00072 #include <stdlib.h>
00073 #endif
00074 #ifdef HAVE_STDARG_H
00075 #include <stdarg.h>
00076 #endif
00077 #include <string.h>
00078 #include <ctype.h>
00079 /* <setjmp.h> is used for the optional error recovery mechanism */
00080 
00081 #ifdef _WIN32
00082 # include "win32/afterbase.h"
00083 #else
00084 # include "afterbase.h"
00085 #endif
00086 
00087 #ifdef HAVE_GIF
00088 # ifdef HAVE_BUILTIN_UNGIF
00089 #  include "libungif/gif_lib.h"
00090 # else
00091 #  include <gif_lib.h>
00092 # endif
00093 #endif
00094 
00095 #ifdef HAVE_TIFF
00096 #include <tiff.h>
00097 #include <tiffio.h>
00098 #endif
00099 #ifdef HAVE_LIBXPM
00100 #ifdef HAVE_LIBXPM_X11
00101 #include <X11/xpm.h>
00102 #else
00103 #include <xpm.h>
00104 #endif
00105 #endif
00106 
00107 #include "asimage.h"
00108 #include "imencdec.h"
00109 #include "xcf.h"
00110 #include "xpm.h"
00111 #include "ungif.h"
00112 #include "import.h"
00113 #include "export.h"
00114 #include "ascmap.h"
00115 #include "bmp.h"
00116 
00117 #ifdef jmpbuf
00118 #undef jmpbuf
00119 #endif
00120 
00121 /***********************************************************************************/
00122 /* High level interface :                                                                                                                  */
00123 as_image_writer_func as_image_file_writers[ASIT_Unknown] =
00124 {
00125         ASImage2xpm ,
00126         ASImage2xpm ,
00127         ASImage2xpm ,
00128         ASImage2png ,
00129         ASImage2jpeg,
00130         ASImage2xcf ,
00131         ASImage2ppm ,
00132         ASImage2ppm ,
00133         ASImage2bmp ,
00134         ASImage2ico ,
00135         ASImage2ico ,
00136         ASImage2gif ,
00137         ASImage2tiff,
00138         NULL,
00139         NULL,
00140         NULL
00141 };
00142 
00143 Bool
00144 ASImage2file( ASImage *im, const char *dir, const char *file,
00145                           ASImageFileTypes type, ASImageExportParams *params )
00146 {
00147         int   filename_len, dirname_len = 0 ;
00148         char *realfilename = NULL ;
00149         Bool  res = False ;
00150 
00151         if( im == NULL ) return False;
00152 
00153         if( file )
00154         {
00155                 filename_len = strlen(file);
00156                 if( dir != NULL )
00157                         dirname_len = strlen(dir)+1;
00158                 realfilename = safemalloc( dirname_len+filename_len+1 );
00159                 if( dir != NULL )
00160                 {
00161                         strcpy( realfilename, dir );
00162                         realfilename[dirname_len-1] = '/' ;
00163                 }
00164                 strcpy( realfilename+dirname_len, file );
00165 #ifdef _WIN32
00166                 unix_path2dos_path( realfilename );
00167 #endif
00168         }
00169         if( type >= ASIT_Unknown || type < 0 )
00170                 show_error( "Hmm, I don't seem to know anything about format you trying to write file \"%s\" in\n.\tPlease check the manual", realfilename );
00171         else if( as_image_file_writers[type] )
00172                 res = as_image_file_writers[type](im, realfilename, params);
00173         else
00174                 show_error( "Support for the format of image file \"%s\" has not been implemented yet.", realfilename );
00175 
00176         free( realfilename );
00177         return res;
00178 }
00179 
00180 /* hmm do we need pixmap2file ???? */
00181 
00182 /***********************************************************************************/
00183 /* Some helper functions :                                                         */
00184 
00185 static FILE*
00186 open_writeable_image_file( const char *path )
00187 {
00188         FILE *fp = NULL;
00189         if ( path )
00190         {
00191                 if ((fp = fopen (path, "wb")) == NULL)
00192                         show_error("cannot open image file \"%s\" for writing. Please check permissions.", path);
00193         }else
00194                 fp = stdout ;
00195         return fp ;
00196 }
00197 
00198 void
00199 scanline2raw( register CARD8 *row, ASScanline *buf, CARD8 *gamma_table, unsigned int width, Bool grayscale, Bool do_alpha )
00200 {
00201         register int x = width;
00202 
00203         if( grayscale )
00204                 row += do_alpha? width<<1 : width ;
00205         else
00206                 row += width*(do_alpha?4:3) ;
00207 
00208         if( gamma_table )
00209         {
00210                 if( !grayscale )
00211                 {
00212                         while ( --x >= 0 )
00213                         {
00214                                 row -= 3 ;
00215                                 if( do_alpha )
00216                                 {
00217                                         --row;
00218                                         buf->alpha[x] = row[3];
00219                                 }
00220                                 buf->xc1[x]  = gamma_table[row[0]];
00221                                 buf->xc2[x]= gamma_table[row[1]];
00222                                 buf->xc3[x] = gamma_table[row[2]];
00223                         }
00224                 }else /* greyscale */
00225                         while ( --x >= 0 )
00226                         {
00227                                 if( do_alpha )
00228                                         buf->alpha[x] = *(--row);
00229                                 buf->xc1 [x] = buf->xc2[x] = buf->xc3[x]  = gamma_table[*(--row)];
00230                         }
00231         }else
00232         {
00233                 if( !grayscale )
00234                 {
00235                         while ( --x >= 0 )
00236                         {
00237                                 row -= 3 ;
00238                                 if( do_alpha )
00239                                 {
00240                                         --row;
00241                                         buf->alpha[x] = row[3];
00242                                 }
00243                                 buf->xc1[x]  = row[0];
00244                                 buf->xc2[x]= row[1];
00245                                 buf->xc3[x] = row[2];
00246                         }
00247                 }else /* greyscale */
00248                         while ( --x >= 0 )
00249                         {
00250                                 if( do_alpha )
00251                                         buf->alpha[x] = *(--row);
00252                                 buf->xc1 [x] = buf->xc2[x] = buf->xc3[x]  = *(--row);
00253                         }
00254         }
00255 }
00256 
00257 /***********************************************************************************/
00258 #define SHOW_PENDING_IMPLEMENTATION_NOTE(f) \
00259         show_error( "I'm sorry, but " f " image writing is pending implementation. Appreciate your patience" )
00260 #define SHOW_UNSUPPORTED_NOTE(f,path) \
00261         show_error( "unable to write file \"%s\" - " f " image format is not supported.\n", (path) )
00262 
00263 
00264 #ifdef HAVE_XPM      /* XPM XPM XPM XPM XPM XPM XPM XPM XPM XPM XPM XPM XPM XPM XPM XPM */
00265 
00266 #ifdef LOCAL_DEBUG
00267 Bool print_component( CARD32*, int, unsigned int );
00268 #endif
00269 
00270 Bool
00271 ASImage2xpm ( ASImage *im, const char *path, ASImageExportParams *params )
00272 {
00273         FILE *outfile;
00274         unsigned int y, x ;
00275         int *mapped_im, *row_pointer ;
00276         ASColormap         cmap = {0};
00277         ASXpmCharmap       xpm_cmap = {0};
00278         int transp_idx = 0;
00279         START_TIME(started);
00280         static const ASXpmExportParams defaultsXPM = { ASIT_Xpm, EXPORT_ALPHA, 4, 127, 512 };
00281         ASImageExportParams defaults;
00282         register char *ptr ;
00283 
00284         LOCAL_DEBUG_CALLER_OUT ("(\"%s\")", path);
00285 
00286         if( params == NULL ) {
00287            defaults.type = defaultsXPM.type;
00288            defaults.xpm = defaultsXPM;
00289            params = &defaults ;
00290         }
00291 
00292         if ((outfile = open_writeable_image_file( path )) == NULL)
00293                 return False;
00294 
00295     mapped_im = colormap_asimage( im, &cmap, params->xpm.max_colors, params->xpm.dither, params->xpm.opaque_threshold );
00296         if( !get_flags( params->xpm.flags, EXPORT_ALPHA) )
00297                 cmap.has_opaque = False ;
00298         else
00299                 transp_idx = cmap.count ;
00300 
00301 LOCAL_DEBUG_OUT("building charmap%s","");
00302         build_xpm_charmap( &cmap, cmap.has_opaque, &xpm_cmap );
00303         SHOW_TIME("charmap calculation",started);
00304 
00305 LOCAL_DEBUG_OUT("writing file%s","");
00306         fprintf( outfile, "/* XPM */\nstatic char *asxpm[] = {\n/* columns rows colors chars-per-pixel */\n"
00307                                           "\"%d %d %d %d\",\n", im->width, im->height, xpm_cmap.count,  xpm_cmap.cpp );
00308     ptr = &(xpm_cmap.char_code[0]);
00309         for( y = 0 ; y < cmap.count ; y++ )
00310         {
00311                 fprintf( outfile, "\"%s c #%2.2X%2.2X%2.2X\",\n", ptr, cmap.entries[y].red, cmap.entries[y].green, cmap.entries[y].blue );
00312                 ptr += xpm_cmap.cpp+1 ;
00313         }
00314         if( cmap.has_opaque && y < xpm_cmap.count )
00315                 fprintf( outfile, "\"%s c None\",\n", ptr );
00316         SHOW_TIME("image header writing",started);
00317 
00318         row_pointer = mapped_im ;
00319         for( y = 0 ; y < im->height ; y++ )
00320         {
00321                 fputc( '"', outfile );
00322                 for( x = 0; x < im->width ; x++ )
00323                 {
00324                         register int idx = (row_pointer[x] >= 0)? row_pointer[x] : transp_idx ;
00325                         register char *ptr = &(xpm_cmap.char_code[idx*(xpm_cmap.cpp+1)]) ;
00326 LOCAL_DEBUG_OUT( "(%d,%d)->%d (row_pointer %d )", x, y, idx, row_pointer[x] );
00327             if( idx > (int)cmap.count )
00328                 show_error("bad XPM color index :(%d,%d) -> %d, %d: %s", x, y, idx, row_pointer[x], ptr );
00329                         while( *ptr )
00330                                 fputc( *(ptr++), outfile );
00331                 }
00332                 row_pointer += im->width ;
00333                 fputc( '"', outfile );
00334                 if( y < im->height-1 )
00335                         fputc( ',', outfile );
00336                 fputc( '\n', outfile );
00337         }
00338         fprintf( outfile, "};\n" );
00339         if (outfile != stdout)
00340                 fclose( outfile );
00341 
00342         SHOW_TIME("image writing",started);
00343         destroy_xpm_charmap( &xpm_cmap, True );
00344         free( mapped_im );
00345         destroy_colormap( &cmap, True );
00346 
00347         SHOW_TIME("total",started);
00348         return True;
00349 }
00350 
00351 
00352 /****** VO ******/
00353 Bool
00354 ASImage2xpmRawBuff ( ASImage *im, CARD8 **buffer, int *size, ASImageExportParams *params )
00355 {
00356         unsigned int y, x ;
00357         int *mapped_im, *row_pointer ;
00358         ASColormap         cmap = {0};
00359         ASXpmCharmap       xpm_cmap = {0} ;
00360         int transp_idx = 0;
00361         START_TIME(started);
00362         static const ASXpmExportParams defaultsXPM = { ASIT_Xpm, EXPORT_ALPHA, 4, 127, 512 };
00363         ASImageExportParams defaults;
00364         register char *ptr ;
00365    char *curr;
00366 
00367    if( params == NULL ) {
00368       defaults.type = defaultsXPM.type;
00369       defaults.xpm = defaultsXPM;
00370       params = &defaults ;
00371    }
00372 
00373     mapped_im = colormap_asimage( im, &cmap, params->xpm.max_colors, params->xpm.dither, params->xpm.opaque_threshold );
00374         if (mapped_im == NULL)
00375                 return False;
00376         if( !get_flags( params->xpm.flags, EXPORT_ALPHA) )
00377                 cmap.has_opaque = False ;
00378         else
00379                 transp_idx = cmap.count ;
00380 
00381 
00382 LOCAL_DEBUG_OUT("building charmap%s","");
00383         build_xpm_charmap( &cmap, cmap.has_opaque, &xpm_cmap );
00384         SHOW_TIME("charmap calculation",started);
00385 
00386    *size = 0;
00387    *buffer = 0;
00388 
00389    /* crazy check against buffer overflow */
00390    if ((im->width > 100000) || (im->height > 1000000) || 
00391        (xpm_cmap.count > 100000) || (xpm_cmap.cpp > 100000)) {
00392                 destroy_xpm_charmap( &xpm_cmap, True );
00393                 free( mapped_im );
00394                 destroy_colormap( &cmap, True );
00395       return False;
00396    }
00397 
00398    /* estimate size*/
00399    *size =  (im->width + 4)*im->height*xpm_cmap.cpp;
00400    *size += cmap.count*(20 + xpm_cmap.cpp);
00401    *size += 200;
00402 
00403    curr = calloc(*size, 1);
00404    *buffer = (CARD8*)curr;
00405 
00406         sprintf(curr, "/* XPM */\nstatic char *asxpm[] = {\n/* columns rows colors chars-per-pixel */\n"
00407                                           "\"%d %d %d %d\",\n", im->width, im->height, xpm_cmap.count,  xpm_cmap.cpp );
00408 
00409    curr += strlen(curr);
00410 
00411     ptr = &(xpm_cmap.char_code[0]);
00412         for( y = 0 ; y < cmap.count ; y++ )
00413         {
00414                 sprintf(curr, "\"%s c #%2.2X%2.2X%2.2X\",\n", ptr, cmap.entries[y].red, cmap.entries[y].green, cmap.entries[y].blue );
00415                 ptr += xpm_cmap.cpp+1 ;
00416       curr += strlen(curr);
00417         }
00418         if( cmap.has_opaque && y < xpm_cmap.count ) {
00419                 sprintf(curr, "\"%s c None\",\n", ptr );
00420       curr += strlen(curr);
00421    }
00422         SHOW_TIME("image header writing",started);
00423 
00424         row_pointer = mapped_im ;
00425         for( y = 0 ; y < im->height ; y++ )
00426         {
00427                 *curr = '"';
00428       curr++;
00429 
00430                 for( x = 0; x < im->width ; x++ )
00431                 {
00432                         register int idx = (row_pointer[x] >= 0)? row_pointer[x] : transp_idx ;
00433                         register char *ptr = &(xpm_cmap.char_code[idx*(xpm_cmap.cpp+1)]) ;
00434          int len = strlen(ptr);
00435 
00436             if( idx > (int)cmap.count )
00437                 show_error("bad XPM color index :(%d,%d) -> %d, %d: %s", x, y, idx, row_pointer[x], ptr );
00438 
00439          memcpy(curr, ptr, len);
00440          curr += len;
00441                 }
00442                 row_pointer += im->width ;
00443                 *curr = '"';
00444       curr++;
00445                 if( y < im->height-1 ) {
00446                    *curr = ',';
00447          curr++;
00448       }
00449                 *curr = '\n';
00450       curr++;
00451         }
00452         sprintf( curr, "};\n" );
00453 
00454         destroy_xpm_charmap( &xpm_cmap, True );
00455         free( mapped_im );
00456         destroy_colormap( &cmap, True );
00457    *size = strlen((char*)*buffer);
00458 
00459         SHOW_TIME("total",started);
00460         return True;
00461 }
00462 
00463 
00464 
00465 #else                   /* XPM XPM XPM XPM XPM XPM XPM XPM XPM XPM XPM XPM XPM XPM XPM XPM */
00466 
00467 Bool
00468 ASImage2xpm ( ASImage *im, const char *path,  ASImageExportParams *params )
00469 {
00470         SHOW_UNSUPPORTED_NOTE("XPM",path);
00471         return False ;
00472 }
00473 
00474 #endif                  /* XPM XPM XPM XPM XPM XPM XPM XPM XPM XPM XPM XPM XPM XPM XPM XPM */
00475 /***********************************************************************************/
00476 
00477 /***********************************************************************************/
00478 #ifdef HAVE_PNG         /* PNG PNG PNG PNG PNG PNG PNG PNG PNG PNG PNG PNG PNG PNG PNG PNG */
00479 static Bool
00480 ASImage2png_int ( ASImage *im, void *data, png_rw_ptr write_fn, png_flush_ptr flush_fn, register ASImageExportParams *params )
00481 {
00482         png_structp png_ptr  = NULL;
00483         png_infop   info_ptr = NULL;
00484         png_byte *row_pointer;
00485         int y ;
00486         Bool has_alpha;
00487         Bool grayscale;
00488         int compression;
00489         ASImageDecoder *imdec ;
00490         CARD32 *r, *g, *b, *a ;
00491         png_color_16 back_color ;
00492 
00493         START_TIME(started);
00494         static const ASPngExportParams defaults = { ASIT_Png, EXPORT_ALPHA, -1 };
00495 
00496         png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL );
00497     if ( png_ptr != NULL )
00498         if( (info_ptr = png_create_info_struct(png_ptr)) != NULL )
00499                         if( setjmp(png_ptr->jmpbuf) )
00500                         {
00501                                 png_destroy_info_struct(png_ptr, (png_infopp) &info_ptr);
00502                                 info_ptr = NULL ;
00503                 }
00504 
00505 
00506         if( params == NULL )
00507         {
00508                 compression = defaults.compression ;
00509                 grayscale = get_flags(defaults.flags, EXPORT_GRAYSCALE );
00510                 has_alpha = get_flags(defaults.flags, EXPORT_ALPHA );
00511         }else
00512         {
00513                 compression = params->png.compression ;
00514                 grayscale = get_flags(params->png.flags, EXPORT_GRAYSCALE );
00515                 has_alpha = get_flags(params->png.flags, EXPORT_ALPHA );
00516         }
00517 
00518         /* lets see if we have alpha channel indeed : */
00519         if( has_alpha )
00520         {
00521                 if( !get_flags( get_asimage_chanmask(im), SCL_DO_ALPHA) )
00522                         has_alpha = False ;
00523         }
00524 
00525         if((imdec = start_image_decoding( NULL /* default visual */ , im,
00526                                               has_alpha?SCL_DO_ALL:(SCL_DO_GREEN|SCL_DO_BLUE|SCL_DO_RED),
00527                                                                           0, 0, im->width, 0, NULL)) == NULL )
00528         {
00529                 LOCAL_DEBUG_OUT( "failed to start image decoding%s", "");
00530                 png_destroy_write_struct(&png_ptr, &info_ptr);
00531                 return False;
00532         }
00533 
00534         if( !info_ptr)
00535         {
00536                 if( png_ptr )
00537                 png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
00538                 stop_image_decoding( &imdec );
00539         return False;
00540     }
00541 
00542         if( write_fn == NULL && flush_fn == NULL ) 
00543         {       
00544                 png_init_io(png_ptr, (FILE*)data);
00545         }else
00546         {
00547             png_set_write_fn(png_ptr,data,(png_rw_ptr) write_fn, flush_fn );    
00548         }        
00549 
00550         if( compression > 0 )
00551                 png_set_compression_level(png_ptr,MIN(compression,99)/10);
00552 
00553         png_set_IHDR(png_ptr, info_ptr, im->width, im->height, 8,
00554                          grayscale ? (has_alpha?PNG_COLOR_TYPE_GRAY_ALPHA:PNG_COLOR_TYPE_GRAY):
00555                                      (has_alpha?PNG_COLOR_TYPE_RGB_ALPHA:PNG_COLOR_TYPE_RGB),
00556                                  PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
00557                                  PNG_FILTER_TYPE_DEFAULT );
00558         /* better set background color as some web browsers can't seem to work without it ( IE in particular ) */
00559         memset( &back_color, 0x00, sizeof(png_color_16));
00560         back_color.red = ARGB32_RED16( im->back_color );
00561         back_color.green = ARGB32_GREEN16( im->back_color );
00562         back_color.blue = ARGB32_BLUE16( im->back_color );
00563         png_set_bKGD(png_ptr, info_ptr, &back_color);
00564         /* PNG treats alpha s alevel of opacity,
00565          * and so do we - there is no need to reverse it : */
00566         /*      png_set_invert_alpha(png_ptr); */
00567 
00568         /* starting writing the file : writing info first */
00569         png_write_info(png_ptr, info_ptr);
00570 
00571         r = imdec->buffer.red ;
00572         g = imdec->buffer.green ;
00573         b = imdec->buffer.blue ;
00574         a = imdec->buffer.alpha ;
00575 
00576         if( grayscale )
00577         {
00578                 row_pointer = safemalloc( im->width*(has_alpha?2:1));
00579                 for ( y = 0 ; y < (int)im->height ; y++ )
00580                 {
00581                         register int i = im->width;
00582                         CARD8   *ptr = (CARD8*)row_pointer;
00583 
00584                         imdec->decode_image_scanline( imdec );
00585                         if( has_alpha )
00586                         {
00587                                 while( --i >= 0 ) /* normalized graylevel computing :  */
00588                                 {
00589                     ptr[(i<<1)] = (57*r[i]+181*g[i]+18*b[i])/256 ;
00590                                         ptr[(i<<1)+1] = a[i] ;
00591                                 }
00592                         }else
00593                                 while( --i >= 0 ) /* normalized graylevel computing :  */
00594                     ptr[i] = (57*r[i]+181*g[i]+18*b[i])/256 ;
00595                         png_write_rows(png_ptr, &row_pointer, 1);
00596                 }
00597         }else
00598         {
00599 /*              fprintf( stderr, "saving : %s\n", path );*/
00600                 row_pointer = safecalloc( im->width * (has_alpha?4:3), 1 );
00601                 for (y = 0; y < (int)im->height; y++)
00602                 {
00603                         register int i = im->width;
00604                         CARD8   *ptr = (CARD8*)(row_pointer+(i-1)*(has_alpha?4:3)) ;
00605                         imdec->decode_image_scanline( imdec );
00606                         if( has_alpha )
00607                         {
00608                                 while( --i >= 0 )
00609                                 {
00610                                         /* 0 is red, 1 is green, 2 is blue, 3 is alpha */
00611                             ptr[0] = r[i] ;
00612                                         ptr[1] = g[i] ;
00613                                         ptr[2] = b[i] ;
00614                                         ptr[3] = a[i] ;
00615                                         ptr-=4;
00616                                         /*fprintf( stderr, "#%2.2X%2.2X%2.2X%2.2X ", imbuf.alpha[i], imbuf.red[i], imbuf.green[i], imbuf.blue[i] );*/
00617                                 }
00618                         }else
00619                                 while( --i >= 0 )
00620                                 {
00621                                         ptr[0] = r[i] ;
00622                                         ptr[1] = g[i] ;
00623                                         ptr[2] = b[i] ;
00624                                         ptr-=3;
00625                                         /*fprintf( stderr, "#%FFX%2.2X%2.2X%2.2X ", imbuf.red[i], imbuf.green[i], imbuf.blue[i] );*/
00626                                 }
00627                         /*fprintf( stderr, "\n");*/
00628                         png_write_rows(png_ptr, &row_pointer, 1);
00629                 }
00630         }
00631 
00632         png_write_end(png_ptr, info_ptr);
00633         png_destroy_write_struct(&png_ptr, &info_ptr);
00634         free( row_pointer );
00635         stop_image_decoding( &imdec );
00636 
00637         SHOW_TIME("image writing", started);
00638         return True ;
00639 }
00640 
00641 Bool
00642 ASImage2png ( ASImage *im, const char *path, register ASImageExportParams *params )
00643 {
00644         FILE *outfile;
00645         Bool res ;
00646         
00647         if( im == NULL )
00648                 return False;
00649         
00650         if ((outfile = open_writeable_image_file( path )) == NULL)
00651                 return False;
00652 
00653         res = ASImage2png_int ( im, outfile, NULL, NULL, params );
00654         
00655         if (outfile != stdout)
00656                 fclose(outfile);
00657         return res;
00658 }
00659 
00660 typedef struct ASImPNGBuffer
00661 {
00662         CARD8 *buffer ; 
00663         int used_size, allocated_size ;
00664                  
00665 }ASImPNGBuffer;
00666 
00667 void asim_png_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
00668 {
00669         ASImPNGBuffer *buff = (ASImPNGBuffer*) png_get_io_ptr(png_ptr); 
00670         if( buff && length > 0 )
00671         {
00672                 if( buff->used_size + length > (unsigned int)buff->allocated_size ) 
00673                 {                      /* allocating in 2048 byte increements : */
00674                         buff->allocated_size = (buff->used_size + length + 2048)&0xFFFFF800 ; 
00675                         buff->buffer = realloc( buff->buffer, buff->allocated_size );
00676                 }        
00677                 memcpy( &(buff->buffer[buff->used_size]), data, length );
00678                 buff->used_size += length ;
00679         }        
00680 }
00681          
00682 void asim_png_flush_data(png_structp png_ptr)
00683 {
00684         /* nothing to do really, but PNG requires it */ 
00685 }        
00686 
00687 
00688 Bool
00689 ASImage2PNGBuff( ASImage *im, CARD8 **buffer, int *size, ASImageExportParams *params )
00690 {
00691         ASImPNGBuffer int_buff  ;
00692 
00693         if( im == NULL || buffer == NULL || size == NULL ) 
00694                 return False;
00695         
00696         memset( &int_buff, 0x00, sizeof(ASImPNGBuffer) );
00697 
00698         if( ASImage2png_int ( im, &int_buff, (png_rw_ptr)asim_png_write_data, (png_flush_ptr)asim_png_flush_data, params ) )
00699         {
00700                 *buffer = int_buff.buffer ; 
00701                 *size = int_buff.used_size ;               
00702                 return True;
00703         }
00704 
00705         if( int_buff.buffer ) 
00706                 free( int_buff.buffer );
00707         
00708         *buffer = NULL ; 
00709         *size = 0 ;
00710         return False;
00711 }
00712 
00713 
00714 #else                   /* PNG PNG PNG PNG PNG PNG PNG PNG PNG PNG PNG PNG PNG PNG PNG PNG */
00715 Bool
00716 ASImage2png ( ASImage *im, const char *path,  ASImageExportParams *params )
00717 {
00718         SHOW_UNSUPPORTED_NOTE( "PNG", path );
00719         return False;
00720 }
00721 
00722 Bool
00723 ASImage2PNGBuff( ASImage *im, CARD8 **buffer, int *size, ASImageExportParams *params )
00724 {
00725         if( buffer ) 
00726                 *buffer = NULL ; 
00727         if( size ) 
00728                 *size = 0 ;
00729         return False;
00730 }
00731 
00732 
00733 #endif                  /* PNG PNG PNG PNG PNG PNG PNG PNG PNG PNG PNG PNG PNG PNG PNG PNG */
00734 /***********************************************************************************/
00735 
00736 
00737 /***********************************************************************************/
00738 #ifdef HAVE_JPEG     /* JPEG JPEG JPEG JPEG JPEG JPEG JPEG JPEG JPEG JPEG JPEG JPEG JPEG */
00739 Bool
00740 ASImage2jpeg( ASImage *im, const char *path,  ASImageExportParams *params )
00741 {
00742         /* This struct contains the JPEG decompression parameters and pointers to
00743          * working space (which is allocated as needed by the JPEG library).
00744          */
00745         struct jpeg_compress_struct cinfo;
00746         struct jpeg_error_mgr jerr;
00747         /* More stuff */
00748         FILE             *outfile;              /* target file */
00749     JSAMPROW      row_pointer[1];/* pointer to JSAMPLE row[s] */
00750         int               y;
00751         static const ASJpegExportParams defaultsJpeg = { ASIT_Jpeg, 0, -1 };
00752         ASImageExportParams defaults;
00753         Bool grayscale;
00754         ASImageDecoder *imdec ;
00755         CARD32 *r, *g, *b ;
00756         START_TIME(started);
00757 
00758         if( im == NULL )
00759                 return False;
00760 
00761         if( params == NULL ) {
00762            defaults.type = defaultsJpeg.type;
00763            defaults.jpeg = defaultsJpeg;
00764            params = &defaults ;
00765         }
00766 
00767         if ((outfile = open_writeable_image_file( path )) == NULL)
00768                 return False;
00769 
00770         if((imdec = start_image_decoding( NULL /* default visual */ , im,
00771                                               (SCL_DO_GREEN|SCL_DO_BLUE|SCL_DO_RED),
00772                                                                           0, 0, im->width, 0, NULL)) == NULL )
00773         {
00774                 LOCAL_DEBUG_OUT( "failed to start image decoding%s", "");
00775                 if (outfile != stdout)
00776                         fclose(outfile);
00777                 return False;
00778         }
00779 
00780 
00781         grayscale = get_flags(params->jpeg.flags, EXPORT_GRAYSCALE );
00782 
00783         /* Step 1: allocate and initialize JPEG compression object */
00784         /* We have to set up the error handler first, in case the initialization
00785         * step fails.  (Unlikely, but it could happen if you are out of memory.)
00786         * This routine fills in the contents of struct jerr, and returns jerr's
00787         * address which we place into the link field in cinfo.
00788         */
00789         cinfo.err = jpeg_std_error(&jerr);
00790         /* Now we can initialize the JPEG compression object. */
00791         jpeg_create_compress(&cinfo);
00792 
00793         /* Step 2: specify data destination (eg, a file) */
00794         /* Note: steps 2 and 3 can be done in either order. */
00795         /* Here we use the library-supplied code to send compressed data to a
00796         * stdio stream.  You can also write your own code to do something else.
00797         * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
00798         * requires it in order to write binary files.
00799         */
00800         jpeg_stdio_dest(&cinfo, outfile);
00801 
00802         /* Step 3: set parameters for compression */
00803         cinfo.image_width  = im->width;         /* image width and height, in pixels */
00804         cinfo.image_height = im->height;
00805         cinfo.input_components = (grayscale)?1:3;                   /* # of color components per pixel */
00806         cinfo.in_color_space   = (grayscale)?JCS_GRAYSCALE:JCS_RGB;     /* colorspace of input image */
00807         /* Now use the library's routine to set default compression parameters.
00808         * (You must set at least cinfo.in_color_space before calling this)*/
00809         jpeg_set_defaults(&cinfo);
00810         if( params->jpeg.quality > 0 )
00811                 jpeg_set_quality(&cinfo, MIN(params->jpeg.quality,100), TRUE /* limit to baseline-JPEG values */);
00812 
00813         /* Step 4: Start compressor */
00814         /* TRUE ensures that we will write a complete interchange-JPEG file.*/
00815         jpeg_start_compress(&cinfo, TRUE);
00816 
00817         /* Step 5: while (scan lines remain to be written) */
00818         /*           jpeg_write_scanlines(...); */
00819 
00820         /* Here we use the library's state variable cinfo.next_scanline as the
00821         * loop counter, so that we don't have to keep track ourselves.
00822         * To keep things simple, we pass one scanline per call; you can pass
00823         * more if you wish, though.
00824         */
00825         r = imdec->buffer.red ;
00826         g = imdec->buffer.green ;
00827         b = imdec->buffer.blue ;
00828 
00829         if( grayscale )
00830         {
00831                 row_pointer[0] = safemalloc( im->width );
00832                 for (y = 0; y < (int)im->height; y++)
00833                 {
00834                         register int i = im->width;
00835                         CARD8   *ptr = (CARD8*)row_pointer[0];
00836                         imdec->decode_image_scanline( imdec );
00837                         while( --i >= 0 ) /* normalized graylevel computing :  */
00838                                 ptr[i] = (54*r[i]+183*g[i]+19*b[i])/256 ;
00839                         (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
00840                 }
00841         }else
00842         {
00843                 row_pointer[0] = safemalloc( im->width * 3 );
00844                 for (y = 0; y < (int)im->height; y++)
00845                 {
00846                         register int i = (int)im->width;
00847                         CARD8   *ptr = (CARD8*)(row_pointer[0]+(i-1)*3) ;
00848 LOCAL_DEBUG_OUT( "decoding  row %d", y );
00849                         imdec->decode_image_scanline( imdec );
00850 LOCAL_DEBUG_OUT( "building  row %d", y );
00851                         while( --i >= 0 )
00852                         {
00853                                 ptr[0] = r[i] ;
00854                                 ptr[1] = g[i] ;
00855                                 ptr[2] = b[i] ;
00856                                 ptr-=3;
00857                         }
00858 LOCAL_DEBUG_OUT( "writing  row %d", y );
00859                         (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
00860                 }
00861         }
00862 LOCAL_DEBUG_OUT( "done writing image%s","" );
00863 /*      free(buffer); */
00864 
00865         /* Step 6: Finish compression and release JPEG compression object*/
00866         jpeg_finish_compress(&cinfo);
00867         jpeg_destroy_compress(&cinfo);
00868 
00869         free( row_pointer[0] );
00870         
00871         stop_image_decoding( &imdec );
00872         if (outfile != stdout)
00873                 fclose(outfile);
00874 
00875         SHOW_TIME("image export",started);
00876         LOCAL_DEBUG_OUT("done writing JPEG image \"%s\"", path);
00877         return True ;
00878 }
00879 #else                   /* JPEG JPEG JPEG JPEG JPEG JPEG JPEG JPEG JPEG JPEG JPEG JPEG JPEG */
00880 
00881 Bool
00882 ASImage2jpeg( ASImage *im, const char *path,  ASImageExportParams *params )
00883 {
00884         SHOW_UNSUPPORTED_NOTE( "JPEG", path );
00885         return False;
00886 }
00887 
00888 #endif                  /* JPEG JPEG JPEG JPEG JPEG JPEG JPEG JPEG JPEG JPEG JPEG JPEG JPEG */
00889 /***********************************************************************************/
00890 
00891 /***********************************************************************************/
00892 /* XCF - GIMP's native file format :                                                                                       */
00893 
00894 Bool
00895 ASImage2xcf ( ASImage *im, const char *path,  ASImageExportParams *params )
00896 {
00897         /* More stuff */
00898         XcfImage  *xcf_im = NULL;
00899         START_TIME(started);
00900 
00901         SHOW_PENDING_IMPLEMENTATION_NOTE("XCF");
00902         if( xcf_im == NULL )
00903                 return False;
00904 
00905 #ifdef LOCAL_DEBUG
00906         print_xcf_image( xcf_im );
00907 #endif
00908         /* Make a one-row-high sample array that will go away when done with image */
00909         SHOW_TIME("write initialization",started);
00910 
00911         free_xcf_image(xcf_im);
00912         SHOW_TIME("image export",started);
00913         return False ;
00914 }
00915 
00916 /***********************************************************************************/
00917 /* PPM/PNM file format :                                                                                                                           */
00918 Bool
00919 ASImage2ppm ( ASImage *im, const char *path,  ASImageExportParams *params )
00920 {
00921         START_TIME(started);
00922         SHOW_PENDING_IMPLEMENTATION_NOTE("PPM");
00923         SHOW_TIME("image export",started);
00924         return False;
00925 }
00926 
00927 /***********************************************************************************/
00928 /* Windows BMP file format :                                                                                                       */
00929 static size_t
00930 bmp_write32 (FILE *fp, CARD32 *data, int count)
00931 {
00932         size_t total = count;
00933         if( count > 0 )
00934         {
00935 #ifdef WORDS_BIGENDIAN                         /* BMPs are encoded as Little Endian */
00936                 CARD8 *raw = (CARD8*)data ;
00937 #endif
00938                 count = 0 ;
00939 #ifdef WORDS_BIGENDIAN                         /* BMPs are encoded as Little Endian */
00940                 while( count < total )
00941                 {
00942                         data[count] = (raw[0]<<24)|(raw[1]<<16)|(raw[2]<<8)|raw[3];
00943                         ++count ;
00944                         raw += 4 ;
00945                 }
00946 #endif
00947                 total = fwrite((char*) data, sizeof (CARD8), total<<2, fp)>>2;
00948         }
00949         return total;
00950 }
00951 
00952 static size_t
00953 bmp_write16 (FILE *fp, CARD16 *data, int count)
00954 {
00955         size_t total = count;
00956         if( count > 0 )
00957         {
00958 #ifdef WORDS_BIGENDIAN                         /* BMPs are encoded as Little Endian */
00959                 CARD8 *raw = (CARD8*)data ;
00960 #endif
00961                 count = 0 ;
00962 #ifdef WORDS_BIGENDIAN                         /* BMPs are encoded as Little Endian */
00963                 while( count < total )
00964                 {
00965                         data[count] = (raw[0]<<16)|raw[1];
00966                         ++count ;
00967                         raw += 2 ;
00968                 }
00969 #endif
00970                 total = fwrite((char*) data, sizeof (CARD8), total<<1, fp)>>1;
00971         }
00972         return total;
00973 }
00974 
00975 Bool
00976 ASImage2bmp ( ASImage *im, const char *path,  ASImageExportParams *params )
00977 {
00978         Bool success = False;
00979         FILE *outfile = NULL ;
00980         START_TIME(started);
00981 
00982         if ((outfile = open_writeable_image_file( path )) != NULL)
00983         {
00984                 void *bmbits ;
00985                 BITMAPINFO *bmi = ASImage2DBI( get_default_asvisual(), im, 0, 0, im->width, im->height, &bmbits, 0 );
00986                 if( bmi != NULL && bmbits != NULL ) 
00987                 {
00988                         BITMAPFILEHEADER bmh ;
00989                         int bits_size = (((bmi->bmiHeader.biWidth*3+3)/4)*4)*bmi->bmiHeader.biHeight;          /* DWORD aligned */
00990 
00991                         bmh.bfType = BMP_SIGNATURE;
00992                     bmh.bfSize = 14+bmi->bmiHeader.biSize+bits_size; /* Specifies the size, in bytes, of the bitmap file */
00993                     bmh.bfReserved1 = 0;
00994                         bmh.bfReserved2 = 0;
00995                     bmh.bfOffBits = 14+bmi->bmiHeader.biSize; /* Specifies the offset, in bytes, 
00996                                                            * from the BITMAPFILEHEADER structure to the bitmap bits */
00997                         /* writing off the header */
00998                         bmp_write16( outfile, &bmh.bfType, 1 );
00999                         bmp_write32( outfile, &bmh.bfSize, 3 );
01000                         /* writing off the bitmapinfo : */
01001                         bmp_write32( outfile, &bmi->bmiHeader.biSize, 1 );
01002                         bmp_write32( outfile, (CARD32*)&bmi->bmiHeader.biWidth, 2 );
01003                         bmp_write16( outfile, &bmi->bmiHeader.biPlanes, 2 );
01004                         /* bmi->bmiHeader.biCompression = 0 ; */
01005                         bmp_write32( outfile, &bmi->bmiHeader.biCompression, 6 );
01006 
01007                         /* writing off the bitmapbits */
01008                         if (fwrite( bmbits, sizeof(CARD8), bits_size, outfile ) == bits_size)
01009                                 success = True;
01010                                 
01011                         free( bmbits );
01012                         free( bmi );
01013                         
01014                 }
01015                 if (outfile != stdout)
01016                         fclose(outfile);
01017         }
01018         SHOW_TIME("image export",started);
01019         return success;
01020 }
01021 
01022 /***********************************************************************************/
01023 /* Windows ICO/CUR file format :                                                                                                   */
01024 Bool
01025 ASImage2ico ( ASImage *im, const char *path,  ASImageExportParams *params )
01026 {
01027         START_TIME(started);
01028         SHOW_PENDING_IMPLEMENTATION_NOTE("ICO");
01029         SHOW_TIME("image export",started);
01030         return False;
01031 }
01032 
01033 /***********************************************************************************/
01034 #ifdef HAVE_GIF         /* GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF */
01035 
01036 Bool ASImage2gif( ASImage *im, const char *path,  ASImageExportParams *params )
01037 {
01038         FILE *outfile = NULL, *infile = NULL;
01039         GifFileType *gif = NULL ;
01040         ColorMapObject *gif_cmap ;
01041         Bool dont_save_cmap = False ;
01042         static const ASGifExportParams defaultsGif = { ASIT_Gif,EXPORT_ALPHA|EXPORT_APPEND, 3, 127, 10 };
01043         ASImageExportParams defaults;
01044         ASColormap         cmap;
01045         int *mapped_im ;
01046         int y ;
01047         GifPixelType *row_pointer ;
01048         Bool new_image = True ;
01049         START_TIME(started);
01050         int cmap_size = 1;
01051 #define GIF_NETSCAPE_EXT_BYTES 3
01052         unsigned char netscape_ext_bytes[GIF_NETSCAPE_EXT_BYTES] = { 0x1, 0x0, 0x0};
01053 #define GIF_GCE_BYTES 4 
01054         unsigned char gce_bytes[GIF_GCE_BYTES] = {0x01, 0x0, 0x0, 0x0 }; /* Graphic Control Extension bytes :
01055                                                                                 * first byte - flags (0x01 for transparency )
01056                                                                                                                                         * second and third bytes - animation delay
01057                                                                                                                                         * forth byte - transoparent pixel value.
01058                                                                                                                                         */
01059         LOCAL_DEBUG_CALLER_OUT ("(\"%s\")", path);
01060 
01061         if( params == NULL ) {
01062            defaults.type = defaultsGif.type;
01063            defaults.gif = defaultsGif;
01064            params = &defaults ;
01065         }
01066 
01067         mapped_im = colormap_asimage( im, &cmap, 255, params->gif.dither, params->gif.opaque_threshold );
01068 
01069         if( get_flags( params->gif.flags, EXPORT_ALPHA) &&
01070                 get_flags( get_asimage_chanmask(im), SCL_DO_ALPHA) )
01071                 gce_bytes[GIF_GCE_TRANSPARENCY_BYTE] = cmap.count ;
01072         else
01073                 gce_bytes[0] = 0 ;
01074 #ifdef DEBUG_TRANSP_GIF
01075         fprintf( stderr, "***> cmap.count = %d, transp_byte = %X, flags = %d, chanmask = %d\n", cmap.count, gce_bytes[GIF_GCE_TRANSPARENCY_BYTE],
01076                      get_flags( params->gif.flags, EXPORT_ALPHA), get_flags( get_asimage_chanmask(im), SCL_DO_ALPHA) );
01077 #endif
01078         gce_bytes[GIF_GCE_DELAY_BYTE_HIGH] = (params->gif.animate_delay>>8)&0x00FF;
01079         gce_bytes[GIF_GCE_DELAY_BYTE_LOW] =  params->gif.animate_delay&0x00FF;
01080 
01081         if( get_flags( params->gif.flags, EXPORT_ANIMATION_REPEATS ) )
01082         {
01083                 netscape_ext_bytes[GIF_NETSCAPE_REPEAT_BYTE_HIGH] = (params->gif.animate_repeats>>8)&0x00FF;
01084                 netscape_ext_bytes[GIF_NETSCAPE_REPEAT_BYTE_LOW] = params->gif.animate_repeats&0x00FF;
01085         }               
01086 
01087         while( cmap_size < 256 && cmap_size < (int)cmap.count+(gce_bytes[0]&0x01) )
01088                 cmap_size = cmap_size<<1 ;
01089         if( (gif_cmap = MakeMapObject(cmap_size, NULL )) == NULL )
01090         {
01091                 free( mapped_im );
01092                 ASIM_PrintGifError();
01093                 return False;
01094         }
01095         memcpy( &(gif_cmap->Colors[0]), &(cmap.entries[0]), MIN(cmap.count,(unsigned int)cmap_size)*3 );
01096 
01097         if( get_flags(params->gif.flags, EXPORT_APPEND) && path != NULL)
01098                 infile = fopen( path, "rb" );
01099         if( infile != NULL )
01100         {
01101                 SavedImage *images = NULL ;
01102                 int count = 0 ;
01103                 /* TODO: do something about multiimage files !!! */
01104                 gif = open_gif_read(infile);
01105                 if( gif == NULL || get_gif_saved_images(gif, -1, &images, &count) == GIF_ERROR)
01106                 {
01107                         ASIM_PrintGifError();
01108                         if( gif )
01109                         {
01110                                 DGifCloseFile(gif);
01111                                 gif = NULL ;
01112                         }
01113                         if (infile)
01114                         {
01115                                 fclose( infile );
01116                                 infile = NULL;
01117                         }
01118                 }else
01119                 {
01120                         GifFileType gif_src ;
01121 
01122                         new_image = False ;
01123                         gif_src = *gif ;
01124                         gif->SColorMap = NULL ;
01125                         gif->Image.ColorMap = NULL ;
01126                         DGifCloseFile(gif);
01127                         gif = NULL;
01128                         fclose (infile);
01129                         infile = NULL;
01130                         outfile = open_writeable_image_file( path );
01131 
01132                         if (outfile)
01133                                 gif = EGifOpenFileHandle(fileno(outfile));
01134                                 
01135                         if (gif)
01136                         {
01137                                 int status;
01138                                 if( ( status = EGifPutScreenDesc(gif, gif_src.SWidth, gif_src.SHeight,
01139                                                        gif_src.SColorResolution,
01140                                                                            gif_src.SBackGroundColor,
01141                                                                            gif_src.SColorMap )) == GIF_OK )
01142                                         status = write_gif_saved_images( gif, images, count );
01143                                 if( status != GIF_OK )
01144                                         ASIM_PrintGifError();
01145                         }
01146                         if (gif_src.SColorMap)
01147                         {  /* we only want to save private colormap if it is any different from
01148                             * screen colormap ( saves us  768 bytes per image ) */
01149                                 if( gif_cmap->ColorCount == gif_src.SColorMap->ColorCount )
01150                                         dont_save_cmap = ( memcmp( gif_cmap->Colors, gif_src.SColorMap->Colors, gif_cmap->ColorCount*sizeof(GifColorType)) == 0 );
01151                                 FreeMapObject(gif_src.SColorMap);
01152                         }
01153                         if (gif)
01154                         {
01155                                 EGifPutExtension(gif, GRAPHICS_EXT_FUNC_CODE, GIF_GCE_BYTES, &(gce_bytes[0]));
01156                                 if( get_flags( params->gif.flags, EXPORT_ANIMATION_REPEATS ) )
01157                                 {
01158                                         EGifPutExtensionFirst(gif, APPLICATION_EXT_FUNC_CODE, 11, "NETSCAPE2.0");
01159                                         EGifPutExtensionLast(gif, 0, GIF_NETSCAPE_EXT_BYTES, &(netscape_ext_bytes[0]));
01160                                 }
01161                                 
01162                                 if( EGifPutImageDesc(gif, 0, 0, im->width, im->height, FALSE, (dont_save_cmap)?NULL:gif_cmap ) == GIF_ERROR )
01163                                         ASIM_PrintGifError();
01164                         }
01165                 }
01166                 free_gif_saved_images( images, count );
01167         }
01168 
01169         if (gif == NULL)
01170         {
01171                 if (outfile == NULL)
01172                         outfile = open_writeable_image_file(path);
01173                         
01174                 if (outfile)
01175                         if ((gif = EGifOpenFileHandle(fileno(outfile))) == NULL)
01176                                 ASIM_PrintGifError();
01177         }
01178 
01179         if( new_image && gif )
01180         {
01181                 if( EGifPutScreenDesc(gif, im->width, im->height, cmap_size, 0, gif_cmap ) == GIF_ERROR )
01182                         ASIM_PrintGifError();
01183         
01184                 EGifPutExtension(gif, 0xf9, GIF_GCE_BYTES, &(gce_bytes[0]));
01185         
01186                 if( EGifPutImageDesc(gif, 0, 0, im->width, im->height, FALSE, NULL ) == GIF_ERROR )
01187                         ASIM_PrintGifError();
01188         }
01189 
01190         if( gif_cmap )
01191         {
01192                 FreeMapObject(gif_cmap);
01193                 gif_cmap = NULL ;
01194         }
01195         if( gif )
01196         {
01197                 row_pointer = safemalloc( im->width*sizeof(GifPixelType));
01198 
01199                 /* it appears to be much faster to write image out in line by line fashion */
01200                 for( y = 0 ; y < (int)im->height ; y++ )
01201                 {
01202                         register int x = im->width ;
01203                         register int *src = mapped_im + x*y;
01204                     while( --x >= 0 )
01205                                 row_pointer[x] = src[x] ;
01206                         if( EGifPutLine(gif, row_pointer, im->width)  == GIF_ERROR)
01207                                 ASIM_PrintGifError();
01208                 }
01209                 free( row_pointer );
01210                 if (EGifCloseFile(gif) == GIF_ERROR)
01211                         ASIM_PrintGifError();
01212                 gif = NULL;
01213         }
01214         free( mapped_im );
01215         destroy_colormap( &cmap, True );
01216         
01217         if (outfile 
01218 #ifdef NO_DOUBLE_FCLOSE_AFTER_FDOPEN
01219                 && gif  /* can't do double fclose in MS CRT after VC2005 */
01220 #endif
01221                 && outfile != stdout)
01222         {
01223                 fclose (outfile);
01224         }
01225 
01226         SHOW_TIME("image export",started);
01227         return True ;
01228 }
01229 #else                   /* GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF */
01230 Bool
01231 ASImage2gif( ASImage *im, const char *path, ASImageExportParams *params )
01232 {
01233         SHOW_UNSUPPORTED_NOTE("GIF",path);
01234         return False ;
01235 }
01236 #endif                  /* GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF */
01237 
01238 #ifdef HAVE_TIFF/* TIFF TIFF TIFF TIFF TIFF TIFF TIFF TIFF TIFF TIFF TIFF TIFF TIFF */
01239 Bool
01240 ASImage2tiff( ASImage *im, const char *path, ASImageExportParams *params)
01241 {
01242         TIFF *out;
01243         static const ASTiffExportParams defaultsTiff = { ASIT_Tiff, 0, (CARD32)-1, TIFF_COMPRESSION_NONE, 100, 0 };
01244         ASImageExportParams defaults;
01245         uint16 photometric = PHOTOMETRIC_RGB;
01246         tsize_t linebytes, scanline;
01247         ASImageDecoder *imdec ;
01248         CARD32 *r, *g, *b, *a ;
01249         unsigned char* buf;
01250         CARD32  row ;
01251         Bool has_alpha ;
01252         int nsamples = 3 ;
01253         START_TIME(started);
01254 
01255         if( params == NULL ) {
01256            defaults.type = defaultsTiff.type;
01257            defaults.tiff = defaultsTiff;
01258            params = &defaults ;
01259         }
01260 
01261         if( path == NULL )
01262         {
01263                 SHOW_UNSUPPORTED_NOTE("TIFF streamed into stdout",path);
01264                 return False ;
01265         }
01266         out = TIFFOpen(path, "w");
01267         if (out == NULL)
01268                 return False;
01269         /* I don't really know why by grayscale images in Tiff does not work :(
01270          * still here is the code :*/
01271         if( get_flags( params->tiff.flags, EXPORT_GRAYSCALE ) )
01272                 nsamples = 1 ;
01273         has_alpha = get_flags( params->tiff.flags, EXPORT_ALPHA );
01274         if( has_alpha )
01275         {
01276                 if( !get_flags( get_asimage_chanmask(im), SCL_DO_ALPHA) )
01277                         has_alpha = False ;
01278                 else
01279                         ++nsamples ;
01280         }
01281 
01282         if((imdec = start_image_decoding( NULL /* default visual */ , im,
01283                                               has_alpha?SCL_DO_ALL:(SCL_DO_GREEN|SCL_DO_BLUE|SCL_DO_RED),
01284                                                                           0, 0, im->width, 0, NULL)) == NULL )
01285         {
01286                 LOCAL_DEBUG_OUT( "failed to start image decoding%s", "");
01287                 TIFFClose(out);
01288                 return False;
01289         }
01290 
01291         TIFFSetField(out, TIFFTAG_IMAGEWIDTH, (uint32) im->width);
01292         TIFFSetField(out, TIFFTAG_IMAGELENGTH, (uint32) im->height);
01293         TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
01294         TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, nsamples);
01295         if (has_alpha)
01296         {
01297             uint16 v[1];
01298             v[0] = EXTRASAMPLE_UNASSALPHA;
01299             TIFFSetField(out, TIFFTAG_EXTRASAMPLES, 1, v);
01300         }
01301 
01302         TIFFSetField(out, TIFFTAG_BITSPERSAMPLE,   8);
01303         TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
01304         if( params->tiff.compression_type == -1  )
01305                 params->tiff.compression_type = defaultsTiff.compression_type ;
01306         TIFFSetField(out, TIFFTAG_COMPRESSION,  params->tiff.compression_type);
01307         switch (params->tiff.compression_type )
01308         {
01309                 case COMPRESSION_JPEG:
01310                         photometric = PHOTOMETRIC_YCBCR;
01311                         if( params->tiff.jpeg_quality > 0 )
01312                                 TIFFSetField(out, TIFFTAG_JPEGQUALITY, params->tiff.jpeg_quality );
01313                         TIFFSetField( out, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB );
01314                         break;
01315         }
01316         TIFFSetField(out, TIFFTAG_PHOTOMETRIC, photometric);
01317 
01318         linebytes = im->width*nsamples;
01319         scanline = TIFFScanlineSize(out);
01320         if (scanline > linebytes)
01321         {
01322                 buf = (unsigned char *)_TIFFmalloc(scanline);
01323                 _TIFFmemset(buf+linebytes, 0, scanline-linebytes);
01324         } else
01325                 buf = (unsigned char *)_TIFFmalloc(linebytes);
01326         TIFFSetField(out, TIFFTAG_ROWSPERSTRIP,
01327                                  TIFFDefaultStripSize(out, params->tiff.rows_per_strip));
01328 
01329         r = imdec->buffer.red ;
01330         g = imdec->buffer.green ;
01331         b = imdec->buffer.blue ;
01332         a = imdec->buffer.alpha ;
01333 
01334         for (row = 0; row < im->height; ++row)
01335         {
01336                 register int i = im->width, k = (im->width-1)*nsamples ;
01337                 imdec->decode_image_scanline( imdec );
01338 
01339                 if( has_alpha )
01340                 {
01341                         if( nsamples == 2 )
01342                                 while ( --i >= 0 )
01343                                 {
01344                                         buf[k+1] = a[i] ;
01345                                         buf[k] = (54*r[i]+183*g[i]+19*b[i])/256 ;
01346                                         k-= 2;
01347                                 }
01348                         else
01349                                 while ( --i >= 0 )
01350                                 {
01351                                         buf[k+3] = a[i] ;
01352                                         buf[k+2] = b[i] ;
01353                                         buf[k+1] = g[i] ;
01354                                         buf[k] = r[i] ;
01355                                         k-= 4;
01356                                 }
01357                 }else if( nsamples == 1 )
01358                         while ( --i >= 0 )
01359                                 buf[k--] = (54*r[i]+183*g[i]+19*b[i])/256 ;
01360                 else
01361                         while ( --i >= 0 )
01362                         {
01363                                 buf[k+2] = b[i] ;
01364                                 buf[k+1] = g[i] ;
01365                                 buf[k] = r[i] ;
01366                                 k-= 3;
01367                         }
01368 
01369                 if (TIFFWriteScanline(out, buf, row, 0) < 0)
01370                         break;
01371         }
01372         stop_image_decoding( &imdec );
01373         TIFFClose(out);
01374         SHOW_TIME("image export",started);
01375         return True;
01376 }
01377 #else                   /* TIFF TIFF TIFF TIFF TIFF TIFF TIFF TIFF TIFF TIFF TIFF TIFF TIFF */
01378 
01379 Bool
01380 ASImage2tiff( ASImage *im, const char *path, ASImageExportParams *params )
01381 {
01382         SHOW_UNSUPPORTED_NOTE("TIFF",path);
01383         return False ;
01384 }
01385 #endif                  /* TIFF TIFF TIFF TIFF TIFF TIFF TIFF TIFF TIFF TIFF TIFF TIFF TIFF */

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