1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * 4 * This code is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 only, as 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 }