00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifdef _WIN32
00023 #include "win32/config.h"
00024 #else
00025 #include "config.h"
00026 #endif
00027
00028
00029
00030
00031 #if TIME_WITH_SYS_TIME
00032 # include <sys/time.h>
00033 # include <time.h>
00034 #else
00035 # if HAVE_SYS_TIME_H
00036 # include <sys/time.h>
00037 # else
00038 # include <time.h>
00039 # endif
00040 #endif
00041 #ifdef HAVE_UNISTD_H
00042 #include <unistd.h>
00043 #endif
00044 #ifdef HAVE_STDLIB_H
00045 #include <stdlib.h>
00046 #endif
00047 #ifdef HAVE_STDARG_H
00048 #include <stdarg.h>
00049 #endif
00050 #include <string.h>
00051 #include <ctype.h>
00052
00053 #ifdef _WIN32
00054 # include "win32/afterbase.h"
00055 #else
00056 # include "afterbase.h"
00057 #endif
00058 #ifdef HAVE_GIF
00059 # ifdef HAVE_BUILTIN_UNGIF
00060 # include "libungif/gif_lib.h"
00061 # else
00062 # include <gif_lib.h>
00063 # endif
00064 #endif
00065
00066 #include "asimage.h"
00067 #include "ascmap.h"
00068 #include "ungif.h"
00069
00070 #ifdef HAVE_GIF
00071
00072 void
00073 free_gif_saved_image( SavedImage *sp, Bool reusable )
00074 {
00075 if( sp )
00076 {
00077 if (sp->ImageDesc.ColorMap)
00078 FreeMapObject(sp->ImageDesc.ColorMap);
00079
00080 if (sp->RasterBits)
00081 free((char *)sp->RasterBits);
00082
00083 if (sp->ExtensionBlocks)
00084 FreeExtension(sp);
00085
00086 if( !reusable )
00087 free( sp );
00088 }
00089 }
00090
00091 void
00092 free_gif_saved_images( SavedImage *images, int count )
00093 {
00094 if( images )
00095 {
00096 while ( --count >= 0 )
00097 free_gif_saved_image( &(images[count]), True );
00098 free( images );
00099 }
00100 }
00101
00102 static void
00103 append_gif_saved_image( SavedImage *src, SavedImage **ret, int *ret_images )
00104 {
00105 *ret = realloc( *ret, sizeof( SavedImage )*((*ret_images)+1));
00106 memcpy( &((*ret)[*ret_images]), src, sizeof(SavedImage) );
00107 memset( src, 0x00, sizeof( SavedImage ) );
00108 ++(*ret_images) ;
00109 }
00110
00111
00112
00113
00114
00115
00116 int fread_gif( GifFileType *gif, GifByteType* buf, int len )
00117 {
00118 int ret = fread( buf, 1, len, gif->UserData );
00119 return ret;
00120 }
00121
00122 GifFileType*
00123 open_gif_read( FILE *in_stream )
00124 {
00125 return DGifOpen(in_stream, fread_gif);
00126 }
00127
00128 int
00129 get_gif_image_desc( GifFileType *gif, SavedImage *im )
00130 {
00131 long start_pos, end_pos ;
00132 int status;
00133
00134 start_pos = ftell(gif->UserData);
00135 status = DGifGetImageDesc( gif );
00136 end_pos = ftell(gif->UserData);
00137 if( status == GIF_OK )
00138 {
00139 int ext_count = im->ExtensionBlockCount ;
00140 ExtensionBlock *ext_ptr = im->ExtensionBlocks ;
00141
00142 im->ExtensionBlocks = NULL ;
00143 im->ExtensionBlockCount = 0 ;
00144
00145 free_gif_saved_image( im, True );
00146 memset( im, 0x00, sizeof(SavedImage));
00147
00148 im->ExtensionBlocks = ext_ptr ;
00149 im->ExtensionBlockCount = ext_count ;
00150
00151 memcpy( &(im->ImageDesc), &(gif->Image), sizeof(GifImageDesc));
00152 if( gif->Image.ColorMap )
00153 {
00154 im->ImageDesc.ColorMap = MakeMapObject(gif->Image.ColorMap->ColorCount, NULL);
00155 fseek( gif->UserData, start_pos+9, SEEK_SET );
00156 if(fread( im->ImageDesc.ColorMap->Colors, 1, gif->Image.ColorMap->ColorCount*3, gif->UserData)){;};
00157 fseek( gif->UserData, end_pos, SEEK_SET );
00158 gif->Image.ColorMap = NULL ;
00159 }
00160 }
00161 return status;
00162 }
00163
00164 int
00165 get_gif_saved_images( GifFileType *gif, int subimage, SavedImage **ret, int *ret_images )
00166 {
00167 GifRecordType RecordType;
00168 GifByteType *ExtData;
00169 SavedImage temp_save;
00170 int curr_image = 0, ret_count = *ret_images ;
00171 int status = GIF_OK;
00172
00173 memset( &temp_save, 0x00, sizeof( temp_save ) );
00174 do
00175 {
00176 if ( (status = DGifGetRecordType(gif, &RecordType)) == GIF_ERROR)
00177 {
00178 break;
00179 }
00180 switch (RecordType)
00181 {
00182 case IMAGE_DESC_RECORD_TYPE:
00183 if ((status = get_gif_image_desc(gif, &temp_save)) == GIF_OK)
00184 {
00185 int size = temp_save.ImageDesc.Width*temp_save.ImageDesc.Height ;
00186 temp_save.RasterBits = realloc( temp_save.RasterBits, size );
00187 status = DGifGetLine(gif, (unsigned char*)temp_save.RasterBits, size);
00188 if (status == GIF_OK)
00189 {
00190 if( curr_image == subimage || subimage < 0 )
00191 {
00192 append_gif_saved_image( &temp_save, ret, &(ret_count));
00193 }
00194 }
00195 ++curr_image ;
00196 }
00197 break;
00198
00199 case EXTENSION_RECORD_TYPE:
00200 status = DGifGetExtension(gif,&temp_save.Function,&ExtData);
00201 while (ExtData != NULL && status == GIF_OK )
00202 {
00203
00204 if ((status = AddExtensionBlock(&temp_save, ExtData[0], (char*)&(ExtData[1]))) == GIF_OK)
00205 status = DGifGetExtensionNext(gif, &ExtData);
00206 temp_save.Function = 0;
00207 }
00208 break;
00209
00210 case TERMINATE_RECORD_TYPE:
00211 break;
00212
00213 default:
00214 break;
00215 }
00216 }while( status == GIF_OK && RecordType != TERMINATE_RECORD_TYPE);
00217
00218
00219
00220
00221
00222 free_gif_saved_image( &temp_save, True );
00223
00224 *ret_images = ret_count ;
00225 return status;
00226 }
00227
00228 int
00229 write_gif_saved_images( GifFileType *gif, SavedImage *images, unsigned int count )
00230 {
00231 int status = GIF_OK;
00232 unsigned int i ;
00233
00234 for( i = 0 ; i < count && status == GIF_OK; ++i )
00235 {
00236 register SavedImage *sp = &images[i];
00237 int SavedHeight = sp->ImageDesc.Height;
00238 int SavedWidth = sp->ImageDesc.Width;
00239 ExtensionBlock *ep;
00240 int y ;
00241
00242 #if 1
00243 if (sp->ExtensionBlocks)
00244 for ( y = 0; y < sp->ExtensionBlockCount && status == GIF_OK; y++)
00245 {
00246 ep = &sp->ExtensionBlocks[y];
00247 status = EGifPutExtension(gif, (ep->Function != 0) ? ep->Function : '\0',
00248 ep->ByteCount, ep->Bytes);
00249 }
00250 #endif
00251 if( status == GIF_OK )
00252 {
00253 status = EGifPutImageDesc(gif, sp->ImageDesc.Left, sp->ImageDesc.Top,
00254 SavedWidth, SavedHeight, sp->ImageDesc.Interlace,
00255 sp->ImageDesc.ColorMap );
00256 for (y = 0; y < SavedHeight && status == GIF_OK ; y++)
00257 status = EGifPutLine(gif, (unsigned char*)sp->RasterBits + y * SavedWidth, SavedWidth);
00258 }
00259 }
00260 return status;
00261 }
00262
00263 #endif
00264