00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
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
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
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
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
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
00181
00182
00183
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
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
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
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
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
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
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
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
00475
00476
00477
00478 #ifdef HAVE_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
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 , 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
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
00565
00566
00567
00568
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 )
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 )
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
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
00611 ptr[0] = r[i] ;
00612 ptr[1] = g[i] ;
00613 ptr[2] = b[i] ;
00614 ptr[3] = a[i] ;
00615 ptr-=4;
00616
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
00626 }
00627
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 {
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
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
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
00734
00735
00736
00737
00738 #ifdef HAVE_JPEG
00739 Bool
00740 ASImage2jpeg( ASImage *im, const char *path, ASImageExportParams *params )
00741 {
00742
00743
00744
00745 struct jpeg_compress_struct cinfo;
00746 struct jpeg_error_mgr jerr;
00747
00748 FILE *outfile;
00749 JSAMPROW row_pointer[1];
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 , 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
00784
00785
00786
00787
00788
00789 cinfo.err = jpeg_std_error(&jerr);
00790
00791 jpeg_create_compress(&cinfo);
00792
00793
00794
00795
00796
00797
00798
00799
00800 jpeg_stdio_dest(&cinfo, outfile);
00801
00802
00803 cinfo.image_width = im->width;
00804 cinfo.image_height = im->height;
00805 cinfo.input_components = (grayscale)?1:3;
00806 cinfo.in_color_space = (grayscale)?JCS_GRAYSCALE:JCS_RGB;
00807
00808
00809 jpeg_set_defaults(&cinfo);
00810 if( params->jpeg.quality > 0 )
00811 jpeg_set_quality(&cinfo, MIN(params->jpeg.quality,100), TRUE );
00812
00813
00814
00815 jpeg_start_compress(&cinfo, TRUE);
00816
00817
00818
00819
00820
00821
00822
00823
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 )
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
00864
00865
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
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
00889
00890
00891
00892
00893
00894 Bool
00895 ASImage2xcf ( ASImage *im, const char *path, ASImageExportParams *params )
00896 {
00897
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
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
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
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
00936 CARD8 *raw = (CARD8*)data ;
00937 #endif
00938 count = 0 ;
00939 #ifdef WORDS_BIGENDIAN
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
00959 CARD8 *raw = (CARD8*)data ;
00960 #endif
00961 count = 0 ;
00962 #ifdef WORDS_BIGENDIAN
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;
00990
00991 bmh.bfType = BMP_SIGNATURE;
00992 bmh.bfSize = 14+bmi->bmiHeader.biSize+bits_size;
00993 bmh.bfReserved1 = 0;
00994 bmh.bfReserved2 = 0;
00995 bmh.bfOffBits = 14+bmi->bmiHeader.biSize;
00996
00997
00998 bmp_write16( outfile, &bmh.bfType, 1 );
00999 bmp_write32( outfile, &bmh.bfSize, 3 );
01000
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
01005 bmp_write32( outfile, &bmi->bmiHeader.biCompression, 6 );
01006
01007
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
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
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 };
01055
01056
01057
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
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 {
01148
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
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
01220 #endif
01221 && outfile != stdout)
01222 {
01223 fclose (outfile);
01224 }
01225
01226 SHOW_TIME("image export",started);
01227 return True ;
01228 }
01229 #else
01230 Bool
01231 ASImage2gif( ASImage *im, const char *path, ASImageExportParams *params )
01232 {
01233 SHOW_UNSUPPORTED_NOTE("GIF",path);
01234 return False ;
01235 }
01236 #endif
01237
01238 #ifdef HAVE_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
01270
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 , 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
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