2
0

gifalloc.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. /*****************************************************************************
  2. * "Gif-Lib" - Yet another gif library.
  3. *
  4. * Written by: Gershon Elber Ver 0.1, Jun. 1989
  5. * Extensively hacked by: Eric S. Raymond Ver 1.?, Sep 1992
  6. *****************************************************************************
  7. * GIF construction tools
  8. *****************************************************************************
  9. * History:
  10. * 15 Sep 92 - Version 1.0 by Eric Raymond.
  11. ****************************************************************************/
  12. #ifdef HAVE_CONFIG_H
  13. #include <config.h>
  14. #endif
  15. #include <stdlib.h>
  16. #include <stdio.h>
  17. #include <string.h>
  18. #include "gif_lib.h"
  19. #define MAX(x, y) (((x) > (y)) ? (x) : (y))
  20. /******************************************************************************
  21. * Miscellaneous utility functions
  22. *****************************************************************************/
  23. /* return smallest bitfield size n will fit in */
  24. int
  25. BitSize(int n) {
  26. register int i;
  27. for (i = 1; i <= 8; i++)
  28. if ((1 << i) >= n)
  29. break;
  30. return (i);
  31. }
  32. /******************************************************************************
  33. * Color map object functions
  34. *****************************************************************************/
  35. /*
  36. * Allocate a color map of given size; initialize with contents of
  37. * ColorMap if that pointer is non-NULL.
  38. */
  39. ColorMapObject *
  40. MakeMapObject(int ColorCount,
  41. const GifColorType * ColorMap) {
  42. ColorMapObject *Object;
  43. /*** FIXME: Our ColorCount has to be a power of two. Is it necessary to
  44. * make the user know that or should we automatically round up instead? */
  45. if (ColorCount != (1 << BitSize(ColorCount))) {
  46. return ((ColorMapObject *) NULL);
  47. }
  48. Object = (ColorMapObject *)malloc(sizeof(ColorMapObject));
  49. if (Object == (ColorMapObject *) NULL) {
  50. return ((ColorMapObject *) NULL);
  51. }
  52. Object->Colors = (GifColorType *)calloc(ColorCount, sizeof(GifColorType));
  53. if (Object->Colors == (GifColorType *) NULL) {
  54. return ((ColorMapObject *) NULL);
  55. }
  56. Object->ColorCount = ColorCount;
  57. Object->BitsPerPixel = BitSize(ColorCount);
  58. if (ColorMap) {
  59. memcpy((char *)Object->Colors,
  60. (char *)ColorMap, ColorCount * sizeof(GifColorType));
  61. }
  62. return (Object);
  63. }
  64. /*
  65. * Free a color map object
  66. */
  67. void
  68. FreeMapObject(ColorMapObject * Object) {
  69. if (Object != NULL) {
  70. free(Object->Colors);
  71. free(Object);
  72. /*** FIXME:
  73. * When we are willing to break API we need to make this function
  74. * FreeMapObject(ColorMapObject **Object)
  75. * and do this assignment to NULL here:
  76. * *Object = NULL;
  77. */
  78. }
  79. }
  80. #ifdef DEBUG
  81. void
  82. DumpColorMap(ColorMapObject * Object,
  83. FILE * fp) {
  84. if (Object) {
  85. int i, j, Len = Object->ColorCount;
  86. for (i = 0; i < Len; i += 4) {
  87. for (j = 0; j < 4 && j < Len; j++) {
  88. fprintf(fp, "%3d: %02x %02x %02x ", i + j,
  89. Object->Colors[i + j].Red,
  90. Object->Colors[i + j].Green,
  91. Object->Colors[i + j].Blue);
  92. }
  93. fprintf(fp, "\n");
  94. }
  95. }
  96. }
  97. #endif /* DEBUG */
  98. /*
  99. * Compute the union of two given color maps and return it. If result can't
  100. * fit into 256 colors, NULL is returned, the allocated union otherwise.
  101. * ColorIn1 is copied as is to ColorUnion, while colors from ColorIn2 are
  102. * copied iff they didn't exist before. ColorTransIn2 maps the old
  103. * ColorIn2 into ColorUnion color map table.
  104. */
  105. ColorMapObject *
  106. UnionColorMap(const ColorMapObject * ColorIn1,
  107. const ColorMapObject * ColorIn2,
  108. GifPixelType ColorTransIn2[]) {
  109. int i, j, CrntSlot, RoundUpTo, NewBitSize;
  110. ColorMapObject *ColorUnion;
  111. /*
  112. * Allocate table which will hold the result for sure.
  113. */
  114. ColorUnion = MakeMapObject(MAX(ColorIn1->ColorCount,
  115. ColorIn2->ColorCount) * 2, NULL);
  116. if (ColorUnion == NULL)
  117. return (NULL);
  118. /* Copy ColorIn1 to ColorUnionSize; */
  119. /*** FIXME: What if there are duplicate entries into the colormap to begin
  120. * with? */
  121. for (i = 0; i < ColorIn1->ColorCount; i++)
  122. ColorUnion->Colors[i] = ColorIn1->Colors[i];
  123. CrntSlot = ColorIn1->ColorCount;
  124. /*
  125. * Potentially obnoxious hack:
  126. *
  127. * Back CrntSlot down past all contiguous {0, 0, 0} slots at the end
  128. * of table 1. This is very useful if your display is limited to
  129. * 16 colors.
  130. */
  131. while (ColorIn1->Colors[CrntSlot - 1].Red == 0
  132. && ColorIn1->Colors[CrntSlot - 1].Green == 0
  133. && ColorIn1->Colors[CrntSlot - 1].Blue == 0)
  134. CrntSlot--;
  135. /* Copy ColorIn2 to ColorUnionSize (use old colors if they exist): */
  136. for (i = 0; i < ColorIn2->ColorCount && CrntSlot <= 256; i++) {
  137. /* Let's see if this color already exists: */
  138. /*** FIXME: Will it ever occur that ColorIn2 will contain duplicate
  139. * entries? So we should search from 0 to CrntSlot rather than
  140. * ColorIn1->ColorCount?
  141. */
  142. for (j = 0; j < ColorIn1->ColorCount; j++)
  143. if (memcmp (&ColorIn1->Colors[j], &ColorIn2->Colors[i],
  144. sizeof(GifColorType)) == 0)
  145. break;
  146. if (j < ColorIn1->ColorCount)
  147. ColorTransIn2[i] = j; /* color exists in Color1 */
  148. else {
  149. /* Color is new - copy it to a new slot: */
  150. ColorUnion->Colors[CrntSlot] = ColorIn2->Colors[i];
  151. ColorTransIn2[i] = CrntSlot++;
  152. }
  153. }
  154. if (CrntSlot > 256) {
  155. FreeMapObject(ColorUnion);
  156. return ((ColorMapObject *) NULL);
  157. }
  158. NewBitSize = BitSize(CrntSlot);
  159. RoundUpTo = (1 << NewBitSize);
  160. if (RoundUpTo != ColorUnion->ColorCount) {
  161. register GifColorType *Map = ColorUnion->Colors;
  162. /*
  163. * Zero out slots up to next power of 2.
  164. * We know these slots exist because of the way ColorUnion's
  165. * start dimension was computed.
  166. */
  167. for (j = CrntSlot; j < RoundUpTo; j++)
  168. Map[j].Red = Map[j].Green = Map[j].Blue = 0;
  169. /* perhaps we can shrink the map? */
  170. if (RoundUpTo < ColorUnion->ColorCount)
  171. ColorUnion->Colors = (GifColorType *)realloc(Map,
  172. sizeof(GifColorType) * RoundUpTo);
  173. }
  174. ColorUnion->ColorCount = RoundUpTo;
  175. ColorUnion->BitsPerPixel = NewBitSize;
  176. return (ColorUnion);
  177. }
  178. /*
  179. * Apply a given color translation to the raster bits of an image
  180. */
  181. void
  182. ApplyTranslation(SavedImage * Image,
  183. GifPixelType Translation[]) {
  184. register int i;
  185. register int RasterSize = Image->ImageDesc.Height * Image->ImageDesc.Width;
  186. for (i = 0; i < RasterSize; i++)
  187. Image->RasterBits[i] = Translation[Image->RasterBits[i]];
  188. }
  189. /******************************************************************************
  190. * Extension record functions
  191. *****************************************************************************/
  192. void
  193. MakeExtension(SavedImage * New,
  194. int Function) {
  195. New->Function = Function;
  196. /*** FIXME:
  197. * Someday we might have to deal with multiple extensions.
  198. * ??? Was this a note from Gershon or from me? Does the multiple
  199. * extension blocks solve this or do we need multiple Functions? Or is
  200. * this an obsolete function? (People should use AddExtensionBlock
  201. * instead?)
  202. * Looks like AddExtensionBlock needs to take the int Function argument
  203. * then it can take the place of this function. Right now people have to
  204. * use both. Fix AddExtensionBlock and add this to the deprecation list.
  205. */
  206. }
  207. int
  208. AddExtensionBlock(SavedImage * New,
  209. int Len,
  210. unsigned char ExtData[]) {
  211. ExtensionBlock *ep;
  212. if (New->ExtensionBlocks == NULL)
  213. New->ExtensionBlocks=(ExtensionBlock *)malloc(sizeof(ExtensionBlock));
  214. else
  215. New->ExtensionBlocks = (ExtensionBlock *)realloc(New->ExtensionBlocks,
  216. sizeof(ExtensionBlock) *
  217. (New->ExtensionBlockCount + 1));
  218. if (New->ExtensionBlocks == NULL)
  219. return (GIF_ERROR);
  220. ep = &New->ExtensionBlocks[New->ExtensionBlockCount++];
  221. ep->ByteCount=Len;
  222. ep->Bytes = (char *)malloc(ep->ByteCount);
  223. if (ep->Bytes == NULL)
  224. return (GIF_ERROR);
  225. if (ExtData) {
  226. memcpy(ep->Bytes, ExtData, Len);
  227. ep->Function = New->Function;
  228. }
  229. return (GIF_OK);
  230. }
  231. void
  232. FreeExtension(SavedImage * Image)
  233. {
  234. ExtensionBlock *ep;
  235. if ((Image == NULL) || (Image->ExtensionBlocks == NULL)) {
  236. return;
  237. }
  238. for (ep = Image->ExtensionBlocks;
  239. ep < (Image->ExtensionBlocks + Image->ExtensionBlockCount); ep++)
  240. (void)free((char *)ep->Bytes);
  241. free((char *)Image->ExtensionBlocks);
  242. Image->ExtensionBlocks = NULL;
  243. }
  244. /******************************************************************************
  245. * Image block allocation functions
  246. ******************************************************************************/
  247. /* Private Function:
  248. * Frees the last image in the GifFile->SavedImages array
  249. */
  250. void
  251. FreeLastSavedImage(GifFileType *GifFile) {
  252. SavedImage *sp;
  253. if ((GifFile == NULL) || (GifFile->SavedImages == NULL))
  254. return;
  255. /* Remove one SavedImage from the GifFile */
  256. GifFile->ImageCount--;
  257. sp = &GifFile->SavedImages[GifFile->ImageCount];
  258. /* Deallocate its Colormap */
  259. if (sp->ImageDesc.ColorMap) {
  260. FreeMapObject(sp->ImageDesc.ColorMap);
  261. sp->ImageDesc.ColorMap = NULL;
  262. }
  263. /* Deallocate the image data */
  264. if (sp->RasterBits)
  265. free((char *)sp->RasterBits);
  266. /* Deallocate any extensions */
  267. if (sp->ExtensionBlocks)
  268. FreeExtension(sp);
  269. /*** FIXME: We could realloc the GifFile->SavedImages structure but is
  270. * there a point to it? Saves some memory but we'd have to do it every
  271. * time. If this is used in FreeSavedImages then it would be inefficient
  272. * (The whole array is going to be deallocated.) If we just use it when
  273. * we want to free the last Image it's convenient to do it here.
  274. */
  275. }
  276. /*
  277. * Append an image block to the SavedImages array
  278. */
  279. SavedImage *
  280. MakeSavedImage(GifFileType * GifFile,
  281. const SavedImage * CopyFrom) {
  282. SavedImage *sp;
  283. if (GifFile->SavedImages == NULL)
  284. GifFile->SavedImages = (SavedImage *)malloc(sizeof(SavedImage));
  285. else
  286. GifFile->SavedImages = (SavedImage *)realloc(GifFile->SavedImages,
  287. sizeof(SavedImage) * (GifFile->ImageCount + 1));
  288. if (GifFile->SavedImages == NULL)
  289. return ((SavedImage *)NULL);
  290. else {
  291. sp = &GifFile->SavedImages[GifFile->ImageCount++];
  292. memset((char *)sp, '\0', sizeof(SavedImage));
  293. if (CopyFrom) {
  294. memcpy((char *)sp, CopyFrom, sizeof(SavedImage));
  295. /*
  296. * Make our own allocated copies of the heap fields in the
  297. * copied record. This guards against potential aliasing
  298. * problems.
  299. */
  300. /* first, the local color map */
  301. if (sp->ImageDesc.ColorMap) {
  302. sp->ImageDesc.ColorMap = MakeMapObject(
  303. CopyFrom->ImageDesc.ColorMap->ColorCount,
  304. CopyFrom->ImageDesc.ColorMap->Colors);
  305. if (sp->ImageDesc.ColorMap == NULL) {
  306. FreeLastSavedImage(GifFile);
  307. return (SavedImage *)(NULL);
  308. }
  309. }
  310. /* next, the raster */
  311. sp->RasterBits = (unsigned char *)malloc(sizeof(GifPixelType) *
  312. CopyFrom->ImageDesc.Height *
  313. CopyFrom->ImageDesc.Width);
  314. if (sp->RasterBits == NULL) {
  315. FreeLastSavedImage(GifFile);
  316. return (SavedImage *)(NULL);
  317. }
  318. memcpy(sp->RasterBits, CopyFrom->RasterBits,
  319. sizeof(GifPixelType) * CopyFrom->ImageDesc.Height *
  320. CopyFrom->ImageDesc.Width);
  321. /* finally, the extension blocks */
  322. if (sp->ExtensionBlocks) {
  323. sp->ExtensionBlocks = (ExtensionBlock *)malloc(
  324. sizeof(ExtensionBlock) *
  325. CopyFrom->ExtensionBlockCount);
  326. if (sp->ExtensionBlocks == NULL) {
  327. FreeLastSavedImage(GifFile);
  328. return (SavedImage *)(NULL);
  329. }
  330. memcpy(sp->ExtensionBlocks, CopyFrom->ExtensionBlocks,
  331. sizeof(ExtensionBlock) * CopyFrom->ExtensionBlockCount);
  332. /*
  333. * For the moment, the actual blocks can take their
  334. * chances with free(). We'll fix this later.
  335. *** FIXME: [Better check this out... Toshio]
  336. * 2004 May 27: Looks like this was an ESR note.
  337. * It means the blocks are shallow copied from InFile to
  338. * OutFile. However, I don't see that in this code....
  339. * Did ESR fix it but never remove this note (And other notes
  340. * in gifspnge?)
  341. */
  342. }
  343. }
  344. return (sp);
  345. }
  346. }
  347. void
  348. FreeSavedImages(GifFileType * GifFile) {
  349. SavedImage *sp;
  350. if ((GifFile == NULL) || (GifFile->SavedImages == NULL)) {
  351. return;
  352. }
  353. for (sp = GifFile->SavedImages;
  354. sp < GifFile->SavedImages + GifFile->ImageCount; sp++) {
  355. if (sp->ImageDesc.ColorMap) {
  356. FreeMapObject(sp->ImageDesc.ColorMap);
  357. sp->ImageDesc.ColorMap = NULL;
  358. }
  359. if (sp->RasterBits)
  360. free((char *)sp->RasterBits);
  361. if (sp->ExtensionBlocks)
  362. FreeExtension(sp);
  363. }
  364. free((char *)GifFile->SavedImages);
  365. GifFile->SavedImages=NULL;
  366. }