ungif.c

Go to the documentation of this file.
00001 /* This file contains code for unified image loading from many
00002  * uncompressed  GIFs */
00003 /********************************************************************/
00004 /* Copyright (c) 2001 Sasha Vasko <sasha at aftercode.net>           */
00005 /********************************************************************/
00006 /*
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020  */
00021 
00022 #ifdef _WIN32
00023 #include "win32/config.h"
00024 #else
00025 #include "config.h"
00026 #endif
00027 
00028 /*#define LOCAL_DEBUG */
00029 /*#define DO_CLOCKING */
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         /* GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF 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 /* It appears that nobody has bloody debugged giflib with multiimage files where
00112  * subimages have private colormaps. So it bloody fucks everything up.
00113  * So we bloody have to cludge it to get something usefull.
00114  * Oh The pain! The pain!
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                         /* Create an extension block with our data */
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:        /* Should be trapped by DGifGetRecordType */
00214                                 break;
00215                 }
00216     }while( status == GIF_OK && RecordType != TERMINATE_RECORD_TYPE);
00217 
00218 /*      if( status == GIF_OK && *ret == NULL )
00219                 append_gif_saved_image( &temp_save, ret, &(ret_count));
00220         else
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                  /* GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF GIF */
00264 

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