6 * published by the Free Software Foundation. Oracle designates this 7 * particular file as subject to the "Classpath" exception as provided 8 * by Oracle in the LICENSE file that accompanied this code. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 */ 24 25 /***************************************************************************** 26 * "Gif-Lib" - Yet another gif library. 27 * 28 * Written by: Gershon Elber Ver 0.1, Jun. 1989 29 * Extensively hacked by: Eric S. Raymond Ver 1.?, Sep 1992 30 ***************************************************************************** 31 * GIF construction tools 32 ***************************************************************************** 33 * History: 34 * 15 Sep 92 - Version 1.0 by Eric Raymond. 35 ****************************************************************************/ 36 37 #ifdef HAVE_CONFIG_H 38 #include <config.h> 39 #endif 40 41 #include <stdlib.h> 42 #include <stdio.h> 43 #include <string.h> 44 #include "gif_lib.h" 45 46 #define MAX(x, y) (((x) > (y)) ? (x) : (y)) 47 48 /****************************************************************************** 49 * Miscellaneous utility functions 50 *****************************************************************************/ 51 52 /* return smallest bitfield size n will fit in */ 53 int 54 BitSize(int n) { 55 56 register int i; 57 58 for (i = 1; i <= 8; i++) 59 if ((1 << i) >= n) 60 break; 61 return (i); 62 } 63 64 /****************************************************************************** 65 * Color map object functions 66 *****************************************************************************/ 67 68 /* 69 * Allocate a color map of given size; initialize with contents of 70 * ColorMap if that pointer is non-NULL. 71 */ 72 ColorMapObject * 73 MakeMapObject(int ColorCount, 74 const GifColorType * ColorMap) { 75 76 ColorMapObject *Object; 77 78 /*** FIXME: Our ColorCount has to be a power of two. Is it necessary to 79 * make the user know that or should we automatically round up instead? */ 80 if (ColorCount != (1 << BitSize(ColorCount))) { 81 return ((ColorMapObject *) NULL); 82 } 83 84 Object = (ColorMapObject *)malloc(sizeof(ColorMapObject)); 85 if (Object == (ColorMapObject *) NULL) { 86 return ((ColorMapObject *) NULL); 87 } 88 89 Object->Colors = (GifColorType *)calloc(ColorCount, sizeof(GifColorType)); 90 if (Object->Colors == (GifColorType *) NULL) { 91 free(Object); 92 return ((ColorMapObject *) NULL); 93 } 94 95 Object->ColorCount = ColorCount; 96 Object->BitsPerPixel = BitSize(ColorCount); 97 98 if (ColorMap) { 99 memcpy((char *)Object->Colors, 100 (char *)ColorMap, ColorCount * sizeof(GifColorType)); 101 } 102 103 return (Object); 104 } 105 106 /* 107 * Free a color map object 108 */ 109 void 110 FreeMapObject(ColorMapObject * Object) { 111 112 if (Object != NULL) { 113 free(Object->Colors); 114 free(Object); 115 Object = NULL; 116 } 117 } 118 119 #ifdef DEBUG 120 void 121 DumpColorMap(ColorMapObject * Object, 122 FILE * fp) { 123 124 if (Object) { 125 int i, j, Len = Object->ColorCount; 126 127 for (i = 0; i < Len; i += 4) { 128 for (j = 0; j < 4 && j < Len; j++) { 129 fprintf(fp, "%3d: %02x %02x %02x ", i + j, 130 Object->Colors[i + j].Red, 131 Object->Colors[i + j].Green, 132 Object->Colors[i + j].Blue); 133 } 134 fprintf(fp, "\n"); 135 } 136 } 137 } 138 #endif /* DEBUG */ 139 140 /****************************************************************************** 141 * Extension record functions 142 *****************************************************************************/ 143 144 void 145 MakeExtension(SavedImage * New, 146 int Function) { 147 148 New->Function = Function; 149 /*** FIXME: 150 * Someday we might have to deal with multiple extensions. 151 * ??? Was this a note from Gershon or from me? Does the multiple 152 * extension blocks solve this or do we need multiple Functions? Or is 153 * this an obsolete function? (People should use AddExtensionBlock 154 * instead?) 155 * Looks like AddExtensionBlock needs to take the int Function argument 156 * then it can take the place of this function. Right now people have to 157 * use both. Fix AddExtensionBlock and add this to the deprecation list. 158 */ 159 } 160 161 int 162 AddExtensionBlock(SavedImage * New, 163 int Len, 164 unsigned char ExtData[]) { 165 166 ExtensionBlock *ep; 167 168 if (New->ExtensionBlocks == NULL) 169 New->ExtensionBlocks=(ExtensionBlock *)malloc(sizeof(ExtensionBlock)); 170 else 171 New->ExtensionBlocks = (ExtensionBlock *)realloc(New->ExtensionBlocks, 172 sizeof(ExtensionBlock) * 173 (New->ExtensionBlockCount + 1)); 174 175 if (New->ExtensionBlocks == NULL) 176 return (GIF_ERROR); 177 178 ep = &New->ExtensionBlocks[New->ExtensionBlockCount++]; 179 180 ep->ByteCount=Len; 181 ep->Bytes = (char *)malloc(ep->ByteCount); 182 if (ep->Bytes == NULL) 183 return (GIF_ERROR); 184 185 if (ExtData) { 186 memcpy(ep->Bytes, ExtData, Len); 187 ep->Function = New->Function; 188 } 189 190 return (GIF_OK); 191 } 192 193 void 194 FreeExtension(SavedImage * Image) 195 { 196 ExtensionBlock *ep; 197 198 if ((Image == NULL) || (Image->ExtensionBlocks == NULL)) { 199 return; 200 } 201 for (ep = Image->ExtensionBlocks; 202 ep < (Image->ExtensionBlocks + Image->ExtensionBlockCount); ep++) 203 (void)free((char *)ep->Bytes); 204 free((char *)Image->ExtensionBlocks); 205 Image->ExtensionBlocks = NULL; 206 } 207 208 /****************************************************************************** 209 * Image block allocation functions 210 ******************************************************************************/ 211 212 /* Private Function: 213 * Frees the last image in the GifFile->SavedImages array 214 */ 215 void 216 FreeLastSavedImage(GifFileType *GifFile) { 217 218 SavedImage *sp; 219 220 if ((GifFile == NULL) || (GifFile->SavedImages == NULL)) 221 return; 222 223 /* Remove one SavedImage from the GifFile */ 224 GifFile->ImageCount--; 225 sp = &GifFile->SavedImages[GifFile->ImageCount]; 226 227 /* Deallocate its Colormap */ 228 if (sp->ImageDesc.ColorMap) 229 FreeMapObject(sp->ImageDesc.ColorMap); 230 231 /* Deallocate the image data */ 232 if (sp->RasterBits) 233 free((char *)sp->RasterBits); 234 235 /* Deallocate any extensions */ 236 if (sp->ExtensionBlocks) 237 FreeExtension(sp); 238 239 /*** FIXME: We could realloc the GifFile->SavedImages structure but is 240 * there a point to it? Saves some memory but we'd have to do it every 241 * time. If this is used in FreeSavedImages then it would be inefficient 242 * (The whole array is going to be deallocated.) If we just use it when 243 * we want to free the last Image it's convenient to do it here. 244 */ 245 } 246 247 /* 248 * Append an image block to the SavedImages array 249 */ 250 SavedImage * 251 MakeSavedImage(GifFileType * GifFile, 252 const SavedImage * CopyFrom) { 253 254 SavedImage *sp; 255 256 if (GifFile->SavedImages == NULL) 257 GifFile->SavedImages = (SavedImage *)malloc(sizeof(SavedImage)); 258 else 259 GifFile->SavedImages = (SavedImage *)realloc(GifFile->SavedImages, 260 sizeof(SavedImage) * (GifFile->ImageCount + 1)); 261 262 if (GifFile->SavedImages == NULL) 263 return ((SavedImage *)NULL); 264 else { 265 sp = &GifFile->SavedImages[GifFile->ImageCount++]; 266 memset((char *)sp, '\0', sizeof(SavedImage)); 267 268 if (CopyFrom) { 269 memcpy((char *)sp, CopyFrom, sizeof(SavedImage)); 270 271 /* 272 * Make our own allocated copies of the heap fields in the 273 * copied record. This guards against potential aliasing 274 * problems. 275 */ 276 277 /* first, the local color map */ 278 if (sp->ImageDesc.ColorMap) { 279 sp->ImageDesc.ColorMap = MakeMapObject( 280 CopyFrom->ImageDesc.ColorMap->ColorCount, 281 CopyFrom->ImageDesc.ColorMap->Colors); 282 if (sp->ImageDesc.ColorMap == NULL) { 283 FreeLastSavedImage(GifFile); 284 return (SavedImage *)(NULL); 285 } 286 } 287 288 /* next, the raster */ 289 sp->RasterBits = (unsigned char *)malloc(sizeof(GifPixelType) * 290 CopyFrom->ImageDesc.Height * 291 CopyFrom->ImageDesc.Width); 292 if (sp->RasterBits == NULL) { 293 FreeLastSavedImage(GifFile); 294 return (SavedImage *)(NULL); 295 } 296 memcpy(sp->RasterBits, CopyFrom->RasterBits, 297 sizeof(GifPixelType) * CopyFrom->ImageDesc.Height * 298 CopyFrom->ImageDesc.Width); 299 300 /* finally, the extension blocks */ 301 if (sp->ExtensionBlocks) { 302 sp->ExtensionBlocks = (ExtensionBlock *)malloc( 303 sizeof(ExtensionBlock) * 304 CopyFrom->ExtensionBlockCount); 305 if (sp->ExtensionBlocks == NULL) { 306 FreeLastSavedImage(GifFile); 307 return (SavedImage *)(NULL); 308 } 309 memcpy(sp->ExtensionBlocks, CopyFrom->ExtensionBlocks, 310 sizeof(ExtensionBlock) * CopyFrom->ExtensionBlockCount); 311 312 /* 313 * For the moment, the actual blocks can take their 314 * chances with free(). We'll fix this later. 315 *** FIXME: [Better check this out... Toshio] 316 * 2004 May 27: Looks like this was an ESR note. 317 * It means the blocks are shallow copied from InFile to 318 * OutFile. However, I don't see that in this code.... 319 * Did ESR fix it but never remove this note (And other notes 320 * in gifspnge?) 321 */ 322 } 323 } 324 325 return (sp); 326 } 327 } 328 329 void 330 FreeSavedImages(GifFileType * GifFile) { 331 332 SavedImage *sp; 333 334 if ((GifFile == NULL) || (GifFile->SavedImages == NULL)) { 335 return; 336 } 337 for (sp = GifFile->SavedImages; 338 sp < GifFile->SavedImages + GifFile->ImageCount; sp++) { 339 if (sp->ImageDesc.ColorMap) 340 FreeMapObject(sp->ImageDesc.ColorMap); 341 342 if (sp->RasterBits) 343 free((char *)sp->RasterBits); 344 345 if (sp->ExtensionBlocks) 346 FreeExtension(sp); 347 } 348 free((char *)GifFile->SavedImages); 349 GifFile->SavedImages=NULL; 350 } | 6 * published by the Free Software Foundation. Oracle designates this 7 * particular file as subject to the "Classpath" exception as provided 8 * by Oracle in the LICENSE file that accompanied this code. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 */ 24 25 /***************************************************************************** 26 27 GIF construction tools 28 29 ****************************************************************************/ 30 31 #include <stdlib.h> 32 #include <stdio.h> 33 #include <string.h> 34 35 #include "gif_lib.h" 36 37 #define MAX(x, y) (((x) > (y)) ? (x) : (y)) 38 39 /****************************************************************************** 40 Miscellaneous utility functions 41 ******************************************************************************/ 42 43 /* return smallest bitfield size n will fit in */ 44 int 45 GifBitSize(int n) 46 { 47 register int i; 48 49 for (i = 1; i <= 8; i++) 50 if ((1 << i) >= n) 51 break; 52 return (i); 53 } 54 55 /****************************************************************************** 56 Color map object functions 57 ******************************************************************************/ 58 59 /* 60 * Allocate a color map of given size; initialize with contents of 61 * ColorMap if that pointer is non-NULL. 62 */ 63 ColorMapObject * 64 GifMakeMapObject(int ColorCount, const GifColorType *ColorMap) 65 { 66 ColorMapObject *Object; 67 68 /*** FIXME: Our ColorCount has to be a power of two. Is it necessary to 69 * make the user know that or should we automatically round up instead? */ 70 if (ColorCount != (1 << GifBitSize(ColorCount))) { 71 return ((ColorMapObject *) NULL); 72 } 73 74 Object = (ColorMapObject *)malloc(sizeof(ColorMapObject)); 75 if (Object == (ColorMapObject *) NULL) { 76 return ((ColorMapObject *) NULL); 77 } 78 79 Object->Colors = (GifColorType *)calloc(ColorCount, sizeof(GifColorType)); 80 if (Object->Colors == (GifColorType *) NULL) { 81 free(Object); 82 return ((ColorMapObject *) NULL); 83 } 84 85 Object->ColorCount = ColorCount; 86 Object->BitsPerPixel = GifBitSize(ColorCount); 87 Object->SortFlag = false; 88 89 if (ColorMap != NULL) { 90 memcpy((char *)Object->Colors, 91 (char *)ColorMap, ColorCount * sizeof(GifColorType)); 92 } 93 94 return (Object); 95 } 96 97 /******************************************************************************* 98 Free a color map object 99 *******************************************************************************/ 100 void 101 GifFreeMapObject(ColorMapObject *Object) 102 { 103 if (Object != NULL) { 104 (void)free(Object->Colors); 105 (void)free(Object); 106 } 107 } 108 109 #ifdef DEBUG 110 void 111 DumpColorMap(ColorMapObject *Object, 112 FILE * fp) 113 { 114 if (Object != NULL) { 115 int i, j, Len = Object->ColorCount; 116 117 for (i = 0; i < Len; i += 4) { 118 for (j = 0; j < 4 && j < Len; j++) { 119 (void)fprintf(fp, "%3d: %02x %02x %02x ", i + j, 120 Object->Colors[i + j].Red, 121 Object->Colors[i + j].Green, 122 Object->Colors[i + j].Blue); 123 } 124 (void)fprintf(fp, "\n"); 125 } 126 } 127 } 128 #endif /* DEBUG */ 129 130 /******************************************************************************* 131 Compute the union of two given color maps and return it. If result can't 132 fit into 256 colors, NULL is returned, the allocated union otherwise. 133 ColorIn1 is copied as is to ColorUnion, while colors from ColorIn2 are 134 copied iff they didn't exist before. ColorTransIn2 maps the old 135 ColorIn2 into the ColorUnion color map table./ 136 *******************************************************************************/ 137 ColorMapObject * 138 GifUnionColorMap(const ColorMapObject *ColorIn1, 139 const ColorMapObject *ColorIn2, 140 GifPixelType ColorTransIn2[]) 141 { 142 int i, j, CrntSlot, RoundUpTo, NewGifBitSize; 143 ColorMapObject *ColorUnion; 144 145 /* 146 * We don't worry about duplicates within either color map; if 147 * the caller wants to resolve those, he can perform unions 148 * with an empty color map. 149 */ 150 151 /* Allocate table which will hold the result for sure. */ 152 ColorUnion = GifMakeMapObject(MAX(ColorIn1->ColorCount, 153 ColorIn2->ColorCount) * 2, NULL); 154 155 if (ColorUnion == NULL) 156 return (NULL); 157 158 /* 159 * Copy ColorIn1 to ColorUnion. 160 */ 161 for (i = 0; i < ColorIn1->ColorCount; i++) 162 ColorUnion->Colors[i] = ColorIn1->Colors[i]; 163 CrntSlot = ColorIn1->ColorCount; 164 165 /* 166 * Potentially obnoxious hack: 167 * 168 * Back CrntSlot down past all contiguous {0, 0, 0} slots at the end 169 * of table 1. This is very useful if your display is limited to 170 * 16 colors. 171 */ 172 while (ColorIn1->Colors[CrntSlot - 1].Red == 0 173 && ColorIn1->Colors[CrntSlot - 1].Green == 0 174 && ColorIn1->Colors[CrntSlot - 1].Blue == 0) 175 CrntSlot--; 176 177 /* Copy ColorIn2 to ColorUnion (use old colors if they exist): */ 178 for (i = 0; i < ColorIn2->ColorCount && CrntSlot <= 256; i++) { 179 /* Let's see if this color already exists: */ 180 for (j = 0; j < ColorIn1->ColorCount; j++) 181 if (memcmp (&ColorIn1->Colors[j], &ColorIn2->Colors[i], 182 sizeof(GifColorType)) == 0) 183 break; 184 185 if (j < ColorIn1->ColorCount) 186 ColorTransIn2[i] = j; /* color exists in Color1 */ 187 else { 188 /* Color is new - copy it to a new slot: */ 189 ColorUnion->Colors[CrntSlot] = ColorIn2->Colors[i]; 190 ColorTransIn2[i] = CrntSlot++; 191 } 192 } 193 194 if (CrntSlot > 256) { 195 GifFreeMapObject(ColorUnion); 196 return ((ColorMapObject *) NULL); 197 } 198 199 NewGifBitSize = GifBitSize(CrntSlot); 200 RoundUpTo = (1 << NewGifBitSize); 201 202 if (RoundUpTo != ColorUnion->ColorCount) { 203 register GifColorType *Map = ColorUnion->Colors; 204 205 /* 206 * Zero out slots up to next power of 2. 207 * We know these slots exist because of the way ColorUnion's 208 * start dimension was computed. 209 */ 210 for (j = CrntSlot; j < RoundUpTo; j++) 211 Map[j].Red = Map[j].Green = Map[j].Blue = 0; 212 213 /* perhaps we can shrink the map? */ 214 if (RoundUpTo < ColorUnion->ColorCount) { 215 GifColorType *new_map = (GifColorType *)realloc(Map, 216 sizeof(GifColorType) * RoundUpTo); 217 if( new_map == NULL ) { 218 GifFreeMapObject(ColorUnion); 219 return ((ColorMapObject *) NULL); 220 } 221 ColorUnion->Colors = new_map; 222 } 223 } 224 225 ColorUnion->ColorCount = RoundUpTo; 226 ColorUnion->BitsPerPixel = NewGifBitSize; 227 228 return (ColorUnion); 229 } 230 231 /******************************************************************************* 232 Apply a given color translation to the raster bits of an image 233 *******************************************************************************/ 234 void 235 GifApplyTranslation(SavedImage *Image, GifPixelType Translation[]) 236 { 237 register int i; 238 register int RasterSize = Image->ImageDesc.Height * Image->ImageDesc.Width; 239 240 for (i = 0; i < RasterSize; i++) 241 Image->RasterBits[i] = Translation[Image->RasterBits[i]]; 242 } 243 244 /****************************************************************************** 245 Extension record functions 246 ******************************************************************************/ 247 int 248 GifAddExtensionBlock(int *ExtensionBlockCount, 249 ExtensionBlock **ExtensionBlocks, 250 int Function, 251 unsigned int Len, 252 unsigned char ExtData[]) 253 { 254 ExtensionBlock *ep; 255 256 if (*ExtensionBlocks == NULL) 257 *ExtensionBlocks=(ExtensionBlock *)malloc(sizeof(ExtensionBlock)); 258 else { 259 ExtensionBlock* ep_new = (ExtensionBlock *)realloc(*ExtensionBlocks, 260 sizeof(ExtensionBlock) * 261 (*ExtensionBlockCount + 1)); 262 if( ep_new == NULL ) 263 return (GIF_ERROR); 264 *ExtensionBlocks = ep_new; 265 } 266 267 if (*ExtensionBlocks == NULL) 268 return (GIF_ERROR); 269 270 ep = &(*ExtensionBlocks)[(*ExtensionBlockCount)++]; 271 272 ep->Function = Function; 273 ep->ByteCount=Len; 274 ep->Bytes = (GifByteType *)malloc(ep->ByteCount); 275 if (ep->Bytes == NULL) 276 return (GIF_ERROR); 277 278 if (ExtData != NULL) { 279 memcpy(ep->Bytes, ExtData, Len); 280 } 281 282 return (GIF_OK); 283 } 284 285 void 286 GifFreeExtensions(int *ExtensionBlockCount, 287 ExtensionBlock **ExtensionBlocks) 288 { 289 ExtensionBlock *ep; 290 291 if (*ExtensionBlocks == NULL) 292 return; 293 294 for (ep = *ExtensionBlocks; 295 ep < (*ExtensionBlocks + *ExtensionBlockCount); 296 ep++) 297 (void)free((char *)ep->Bytes); 298 (void)free((char *)*ExtensionBlocks); 299 *ExtensionBlocks = NULL; 300 *ExtensionBlockCount = 0; 301 } 302 303 /****************************************************************************** 304 Image block allocation functions 305 ******************************************************************************/ 306 307 /* Private Function: 308 * Frees the last image in the GifFile->SavedImages array 309 */ 310 void 311 FreeLastSavedImage(GifFileType *GifFile) 312 { 313 SavedImage *sp; 314 315 if ((GifFile == NULL) || (GifFile->SavedImages == NULL)) 316 return; 317 318 /* Remove one SavedImage from the GifFile */ 319 GifFile->ImageCount--; 320 sp = &GifFile->SavedImages[GifFile->ImageCount]; 321 322 /* Deallocate its Colormap */ 323 if (sp->ImageDesc.ColorMap != NULL) { 324 GifFreeMapObject(sp->ImageDesc.ColorMap); 325 sp->ImageDesc.ColorMap = NULL; 326 } 327 328 /* Deallocate the image data */ 329 if (sp->RasterBits != NULL) 330 free((char *)sp->RasterBits); 331 332 /* Deallocate any extensions */ 333 GifFreeExtensions(&sp->ExtensionBlockCount, &sp->ExtensionBlocks); 334 335 /*** FIXME: We could realloc the GifFile->SavedImages structure but is 336 * there a point to it? Saves some memory but we'd have to do it every 337 * time. If this is used in GifFreeSavedImages then it would be inefficient 338 * (The whole array is going to be deallocated.) If we just use it when 339 * we want to free the last Image it's convenient to do it here. 340 */ 341 } 342 343 /* 344 * Append an image block to the SavedImages array 345 */ 346 SavedImage * 347 GifMakeSavedImage(GifFileType *GifFile, const SavedImage *CopyFrom) 348 { 349 if (GifFile->SavedImages == NULL) 350 GifFile->SavedImages = (SavedImage *)malloc(sizeof(SavedImage)); 351 else 352 GifFile->SavedImages = (SavedImage *)realloc(GifFile->SavedImages, 353 sizeof(SavedImage) * (GifFile->ImageCount + 1)); 354 355 if (GifFile->SavedImages == NULL) 356 return ((SavedImage *)NULL); 357 else { 358 SavedImage *sp = &GifFile->SavedImages[GifFile->ImageCount++]; 359 memset((char *)sp, '\0', sizeof(SavedImage)); 360 361 if (CopyFrom != NULL) { 362 memcpy((char *)sp, CopyFrom, sizeof(SavedImage)); 363 364 /* 365 * Make our own allocated copies of the heap fields in the 366 * copied record. This guards against potential aliasing 367 * problems. 368 */ 369 370 /* first, the local color map */ 371 if (sp->ImageDesc.ColorMap != NULL) { 372 sp->ImageDesc.ColorMap = GifMakeMapObject( 373 CopyFrom->ImageDesc.ColorMap->ColorCount, 374 CopyFrom->ImageDesc.ColorMap->Colors); 375 if (sp->ImageDesc.ColorMap == NULL) { 376 FreeLastSavedImage(GifFile); 377 return (SavedImage *)(NULL); 378 } 379 } 380 381 /* next, the raster */ 382 sp->RasterBits = (unsigned char *)malloc(sizeof(GifPixelType) * 383 CopyFrom->ImageDesc.Height * 384 CopyFrom->ImageDesc.Width); 385 if (sp->RasterBits == NULL) { 386 FreeLastSavedImage(GifFile); 387 return (SavedImage *)(NULL); 388 } 389 memcpy(sp->RasterBits, CopyFrom->RasterBits, 390 sizeof(GifPixelType) * CopyFrom->ImageDesc.Height * 391 CopyFrom->ImageDesc.Width); 392 393 /* finally, the extension blocks */ 394 if (sp->ExtensionBlocks != NULL) { 395 sp->ExtensionBlocks = (ExtensionBlock *)malloc( 396 sizeof(ExtensionBlock) * 397 CopyFrom->ExtensionBlockCount); 398 if (sp->ExtensionBlocks == NULL) { 399 FreeLastSavedImage(GifFile); 400 return (SavedImage *)(NULL); 401 } 402 memcpy(sp->ExtensionBlocks, CopyFrom->ExtensionBlocks, 403 sizeof(ExtensionBlock) * CopyFrom->ExtensionBlockCount); 404 } 405 } 406 407 return (sp); 408 } 409 } 410 411 void 412 GifFreeSavedImages(GifFileType *GifFile) 413 { 414 SavedImage *sp; 415 416 if ((GifFile == NULL) || (GifFile->SavedImages == NULL)) { 417 return; 418 } 419 for (sp = GifFile->SavedImages; 420 sp < GifFile->SavedImages + GifFile->ImageCount; sp++) { 421 if (sp->ImageDesc.ColorMap != NULL) { 422 GifFreeMapObject(sp->ImageDesc.ColorMap); 423 sp->ImageDesc.ColorMap = NULL; 424 } 425 426 if (sp->RasterBits != NULL) 427 free((char *)sp->RasterBits); 428 429 GifFreeExtensions(&sp->ExtensionBlockCount, &sp->ExtensionBlocks); 430 } 431 free((char *)GifFile->SavedImages); 432 GifFile->SavedImages = NULL; 433 } 434 435 /* end */ |