1
0

egif_lib.c 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154
  1. /******************************************************************************
  2. egif_lib.c - GIF encoding
  3. The functions here and in dgif_lib.c are partitioned carefully so that
  4. if you only require one of read and write capability, only one of these
  5. two modules will be linked. Preserve this property!
  6. *****************************************************************************/
  7. //#include <unistd.h>
  8. #include <stdint.h>
  9. #include <stdlib.h>
  10. #include <stdio.h>
  11. #include <string.h>
  12. #include <fcntl.h>
  13. #ifdef _WIN32
  14. #include <io.h>
  15. #else
  16. #include <sys/types.h>
  17. #endif /* _WIN32 */
  18. #include <sys/stat.h>
  19. #include "gif_lib.h"
  20. #include "gif_lib_private.h"
  21. /* Masks given codes to BitsPerPixel, to make sure all codes are in range: */
  22. /*@+charint@*/
  23. static const GifPixelType CodeMask[] = {
  24. 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff
  25. };
  26. /*@-charint@*/
  27. static int EGifPutWord(int Word, GifFileType * GifFile);
  28. static int EGifSetupCompress(GifFileType * GifFile);
  29. static int EGifCompressLine(GifFileType * GifFile, GifPixelType * Line,
  30. int LineLen);
  31. static int EGifCompressOutput(GifFileType * GifFile, int Code);
  32. static int EGifBufferedOutput(GifFileType * GifFile, GifByteType * Buf,
  33. int c);
  34. /* extract bytes from an unsigned word */
  35. #define LOBYTE(x) ((x) & 0xff)
  36. #define HIBYTE(x) (((x) >> 8) & 0xff)
  37. /******************************************************************************
  38. Open a new GIF file for write, specified by name. If TestExistance then
  39. if the file exists this routines fails (returns NULL).
  40. Returns a dynamically allocated GifFileType pointer which serves as the GIF
  41. info record. The Error member is cleared if successful.
  42. ******************************************************************************/
  43. GifFileType *
  44. EGifOpenFileName(const char *FileName, const bool TestExistence, int *Error)
  45. {
  46. int FileHandle;
  47. GifFileType *GifFile;
  48. if (TestExistence)
  49. FileHandle = open(FileName, O_WRONLY | O_CREAT | O_EXCL,
  50. S_IREAD | S_IWRITE);
  51. else
  52. FileHandle = open(FileName, O_WRONLY | O_CREAT | O_TRUNC,
  53. S_IREAD | S_IWRITE);
  54. if (FileHandle == -1) {
  55. if (Error != NULL)
  56. *Error = E_GIF_ERR_OPEN_FAILED;
  57. return NULL;
  58. }
  59. GifFile = EGifOpenFileHandle(FileHandle, Error);
  60. if (GifFile == (GifFileType *) NULL)
  61. (void)close(FileHandle);
  62. return GifFile;
  63. }
  64. /******************************************************************************
  65. Update a new GIF file, given its file handle, which must be opened for
  66. write in binary mode.
  67. Returns dynamically allocated a GifFileType pointer which serves as the GIF
  68. info record.
  69. Only fails on a memory allocation error.
  70. ******************************************************************************/
  71. GifFileType *
  72. EGifOpenFileHandle(const int FileHandle, int *Error)
  73. {
  74. GifFileType *GifFile;
  75. GifFilePrivateType *Private;
  76. FILE *f;
  77. GifFile = (GifFileType *) malloc(sizeof(GifFileType));
  78. if (GifFile == NULL) {
  79. return NULL;
  80. }
  81. memset(GifFile, '\0', sizeof(GifFileType));
  82. Private = (GifFilePrivateType *)malloc(sizeof(GifFilePrivateType));
  83. if (Private == NULL) {
  84. free(GifFile);
  85. if (Error != NULL)
  86. *Error = E_GIF_ERR_NOT_ENOUGH_MEM;
  87. return NULL;
  88. }
  89. /*@i1@*/memset(Private, '\0', sizeof(GifFilePrivateType));
  90. if ((Private->HashTable = _InitHashTable()) == NULL) {
  91. free(GifFile);
  92. free(Private);
  93. if (Error != NULL)
  94. *Error = E_GIF_ERR_NOT_ENOUGH_MEM;
  95. return NULL;
  96. }
  97. #ifdef _WIN32
  98. _setmode(FileHandle, O_BINARY); /* Make sure it is in binary mode. */
  99. #endif /* _WIN32 */
  100. f = fdopen(FileHandle, "wb"); /* Make it into a stream: */
  101. GifFile->Private = (void *)Private;
  102. Private->FileHandle = FileHandle;
  103. Private->File = f;
  104. Private->FileState = FILE_STATE_WRITE;
  105. Private->gif89 = false;
  106. Private->Write = (OutputFunc) 0; /* No user write routine (MRB) */
  107. GifFile->UserData = (void *)NULL; /* No user write handle (MRB) */
  108. GifFile->Error = 0;
  109. return GifFile;
  110. }
  111. /******************************************************************************
  112. Output constructor that takes user supplied output function.
  113. Basically just a copy of EGifOpenFileHandle. (MRB)
  114. ******************************************************************************/
  115. GifFileType *
  116. EGifOpen(void *userData, OutputFunc writeFunc, int *Error)
  117. {
  118. GifFileType *GifFile;
  119. GifFilePrivateType *Private;
  120. GifFile = (GifFileType *)malloc(sizeof(GifFileType));
  121. if (GifFile == NULL) {
  122. if (Error != NULL)
  123. *Error = E_GIF_ERR_NOT_ENOUGH_MEM;
  124. return NULL;
  125. }
  126. memset(GifFile, '\0', sizeof(GifFileType));
  127. Private = (GifFilePrivateType *)malloc(sizeof(GifFilePrivateType));
  128. if (Private == NULL) {
  129. free(GifFile);
  130. if (Error != NULL)
  131. *Error = E_GIF_ERR_NOT_ENOUGH_MEM;
  132. return NULL;
  133. }
  134. memset(Private, '\0', sizeof(GifFilePrivateType));
  135. Private->HashTable = _InitHashTable();
  136. if (Private->HashTable == NULL) {
  137. free (GifFile);
  138. free (Private);
  139. if (Error != NULL)
  140. *Error = E_GIF_ERR_NOT_ENOUGH_MEM;
  141. return NULL;
  142. }
  143. GifFile->Private = (void *)Private;
  144. Private->FileHandle = 0;
  145. Private->File = (FILE *) 0;
  146. Private->FileState = FILE_STATE_WRITE;
  147. Private->Write = writeFunc; /* User write routine (MRB) */
  148. GifFile->UserData = userData; /* User write handle (MRB) */
  149. Private->gif89 = false; /* initially, write GIF87 */
  150. GifFile->Error = 0;
  151. return GifFile;
  152. }
  153. /******************************************************************************
  154. Routine to compute the GIF version that will be written on output.
  155. ******************************************************************************/
  156. const char *
  157. EGifGetGifVersion(GifFileType *GifFile)
  158. {
  159. GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
  160. int i, j;
  161. /*
  162. * Bulletproofing - always write GIF89 if we need to.
  163. * Note, we don't clear the gif89 flag here because
  164. * users of the sequential API might have called EGifSetGifVersion()
  165. * in order to set that flag.
  166. */
  167. for (i = 0; i < GifFile->ImageCount; i++) {
  168. for (j = 0; j < GifFile->SavedImages[i].ExtensionBlockCount; j++) {
  169. int function =
  170. GifFile->SavedImages[i].ExtensionBlocks[j].Function;
  171. if (function == COMMENT_EXT_FUNC_CODE
  172. || function == GRAPHICS_EXT_FUNC_CODE
  173. || function == PLAINTEXT_EXT_FUNC_CODE
  174. || function == APPLICATION_EXT_FUNC_CODE)
  175. Private->gif89 = true;
  176. }
  177. }
  178. for (i = 0; i < GifFile->ExtensionBlockCount; i++) {
  179. int function = GifFile->ExtensionBlocks[i].Function;
  180. if (function == COMMENT_EXT_FUNC_CODE
  181. || function == GRAPHICS_EXT_FUNC_CODE
  182. || function == PLAINTEXT_EXT_FUNC_CODE
  183. || function == APPLICATION_EXT_FUNC_CODE)
  184. Private->gif89 = true;
  185. }
  186. if (Private->gif89)
  187. return GIF89_STAMP;
  188. else
  189. return GIF87_STAMP;
  190. }
  191. /******************************************************************************
  192. Set the GIF version. In the extremely unlikely event that there is ever
  193. another version, replace the bool argument with an enum in which the
  194. GIF87 value is 0 (numerically the same as bool false) and the GIF89 value
  195. is 1 (numerically the same as bool true). That way we'll even preserve
  196. object-file compatibility!
  197. ******************************************************************************/
  198. void EGifSetGifVersion(GifFileType *GifFile, const bool gif89)
  199. {
  200. GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
  201. Private->gif89 = gif89;
  202. }
  203. /******************************************************************************
  204. All writes to the GIF should go through this.
  205. ******************************************************************************/
  206. static int InternalWrite(GifFileType *GifFileOut,
  207. const unsigned char *buf, size_t len)
  208. {
  209. GifFilePrivateType *Private = (GifFilePrivateType*)GifFileOut->Private;
  210. if (Private->Write)
  211. return Private->Write(GifFileOut,buf,len);
  212. else
  213. return fwrite(buf, 1, len, Private->File);
  214. }
  215. /******************************************************************************
  216. This routine should be called before any other EGif calls, immediately
  217. following the GIF file opening.
  218. ******************************************************************************/
  219. int
  220. EGifPutScreenDesc(GifFileType *GifFile,
  221. const int Width,
  222. const int Height,
  223. const int ColorRes,
  224. const int BackGround,
  225. const ColorMapObject *ColorMap)
  226. {
  227. GifByteType Buf[3];
  228. GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
  229. const char *write_version;
  230. if (Private->FileState & FILE_STATE_SCREEN) {
  231. /* If already has screen descriptor - something is wrong! */
  232. GifFile->Error = E_GIF_ERR_HAS_SCRN_DSCR;
  233. return GIF_ERROR;
  234. }
  235. if (!IS_WRITEABLE(Private)) {
  236. /* This file was NOT open for writing: */
  237. GifFile->Error = E_GIF_ERR_NOT_WRITEABLE;
  238. return GIF_ERROR;
  239. }
  240. write_version = EGifGetGifVersion(GifFile);
  241. /* First write the version prefix into the file. */
  242. if (InternalWrite(GifFile, (unsigned char *)write_version,
  243. strlen(write_version)) != strlen(write_version)) {
  244. GifFile->Error = E_GIF_ERR_WRITE_FAILED;
  245. return GIF_ERROR;
  246. }
  247. GifFile->SWidth = Width;
  248. GifFile->SHeight = Height;
  249. GifFile->SColorResolution = ColorRes;
  250. GifFile->SBackGroundColor = BackGround;
  251. if (ColorMap) {
  252. GifFile->SColorMap = GifMakeMapObject(ColorMap->ColorCount,
  253. ColorMap->Colors);
  254. if (GifFile->SColorMap == NULL) {
  255. GifFile->Error = E_GIF_ERR_NOT_ENOUGH_MEM;
  256. return GIF_ERROR;
  257. }
  258. } else
  259. GifFile->SColorMap = NULL;
  260. /*
  261. * Put the logical screen descriptor into the file:
  262. */
  263. /* Logical Screen Descriptor: Dimensions */
  264. (void)EGifPutWord(Width, GifFile);
  265. (void)EGifPutWord(Height, GifFile);
  266. /* Logical Screen Descriptor: Packed Fields */
  267. /* Note: We have actual size of the color table default to the largest
  268. * possible size (7+1 == 8 bits) because the decoder can use it to decide
  269. * how to display the files.
  270. */
  271. Buf[0] = (ColorMap ? 0x80 : 0x00) | /* Yes/no global colormap */
  272. ((ColorRes - 1) << 4) | /* Bits allocated to each primary color */
  273. (ColorMap ? ColorMap->BitsPerPixel - 1 : 0x07 ); /* Actual size of the
  274. color table. */
  275. if (ColorMap != NULL && ColorMap->SortFlag)
  276. Buf[0] |= 0x08;
  277. Buf[1] = BackGround; /* Index into the ColorTable for background color */
  278. Buf[2] = GifFile->AspectByte; /* Pixel Aspect Ratio */
  279. InternalWrite(GifFile, Buf, 3);
  280. /* If we have Global color map - dump it also: */
  281. if (ColorMap != NULL) {
  282. int i;
  283. for (i = 0; i < ColorMap->ColorCount; i++) {
  284. /* Put the ColorMap out also: */
  285. Buf[0] = ColorMap->Colors[i].Red;
  286. Buf[1] = ColorMap->Colors[i].Green;
  287. Buf[2] = ColorMap->Colors[i].Blue;
  288. if (InternalWrite(GifFile, Buf, 3) != 3) {
  289. GifFile->Error = E_GIF_ERR_WRITE_FAILED;
  290. return GIF_ERROR;
  291. }
  292. }
  293. }
  294. /* Mark this file as has screen descriptor, and no pixel written yet: */
  295. Private->FileState |= FILE_STATE_SCREEN;
  296. return GIF_OK;
  297. }
  298. /******************************************************************************
  299. This routine should be called before any attempt to dump an image - any
  300. call to any of the pixel dump routines.
  301. ******************************************************************************/
  302. int
  303. EGifPutImageDesc(GifFileType *GifFile,
  304. const int Left,
  305. const int Top,
  306. const int Width,
  307. const int Height,
  308. const bool Interlace,
  309. const ColorMapObject *ColorMap)
  310. {
  311. GifByteType Buf[3];
  312. GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
  313. if (Private->FileState & FILE_STATE_IMAGE &&
  314. Private->PixelCount > 0xffff0000UL) {
  315. /* If already has active image descriptor - something is wrong! */
  316. GifFile->Error = E_GIF_ERR_HAS_IMAG_DSCR;
  317. return GIF_ERROR;
  318. }
  319. if (!IS_WRITEABLE(Private)) {
  320. /* This file was NOT open for writing: */
  321. GifFile->Error = E_GIF_ERR_NOT_WRITEABLE;
  322. return GIF_ERROR;
  323. }
  324. GifFile->Image.Left = Left;
  325. GifFile->Image.Top = Top;
  326. GifFile->Image.Width = Width;
  327. GifFile->Image.Height = Height;
  328. GifFile->Image.Interlace = Interlace;
  329. if (ColorMap) {
  330. if (GifFile->Image.ColorMap != NULL) {
  331. GifFreeMapObject(GifFile->Image.ColorMap);
  332. GifFile->Image.ColorMap = NULL;
  333. }
  334. GifFile->Image.ColorMap = GifMakeMapObject(ColorMap->ColorCount,
  335. ColorMap->Colors);
  336. if (GifFile->Image.ColorMap == NULL) {
  337. GifFile->Error = E_GIF_ERR_NOT_ENOUGH_MEM;
  338. return GIF_ERROR;
  339. }
  340. } else {
  341. GifFile->Image.ColorMap = NULL;
  342. }
  343. /* Put the image descriptor into the file: */
  344. Buf[0] = DESCRIPTOR_INTRODUCER; /* Image separator character. */
  345. InternalWrite(GifFile, Buf, 1);
  346. (void)EGifPutWord(Left, GifFile);
  347. (void)EGifPutWord(Top, GifFile);
  348. (void)EGifPutWord(Width, GifFile);
  349. (void)EGifPutWord(Height, GifFile);
  350. Buf[0] = (ColorMap ? 0x80 : 0x00) |
  351. (Interlace ? 0x40 : 0x00) |
  352. (ColorMap ? ColorMap->BitsPerPixel - 1 : 0);
  353. InternalWrite(GifFile, Buf, 1);
  354. /* If we have Global color map - dump it also: */
  355. if (ColorMap != NULL) {
  356. int i;
  357. for (i = 0; i < ColorMap->ColorCount; i++) {
  358. /* Put the ColorMap out also: */
  359. Buf[0] = ColorMap->Colors[i].Red;
  360. Buf[1] = ColorMap->Colors[i].Green;
  361. Buf[2] = ColorMap->Colors[i].Blue;
  362. if (InternalWrite(GifFile, Buf, 3) != 3) {
  363. GifFile->Error = E_GIF_ERR_WRITE_FAILED;
  364. return GIF_ERROR;
  365. }
  366. }
  367. }
  368. if (GifFile->SColorMap == NULL && GifFile->Image.ColorMap == NULL) {
  369. GifFile->Error = E_GIF_ERR_NO_COLOR_MAP;
  370. return GIF_ERROR;
  371. }
  372. /* Mark this file as has screen descriptor: */
  373. Private->FileState |= FILE_STATE_IMAGE;
  374. Private->PixelCount = (long)Width *(long)Height;
  375. /* Reset compress algorithm parameters. */
  376. (void)EGifSetupCompress(GifFile);
  377. return GIF_OK;
  378. }
  379. /******************************************************************************
  380. Put one full scanned line (Line) of length LineLen into GIF file.
  381. ******************************************************************************/
  382. int
  383. EGifPutLine(GifFileType * GifFile, GifPixelType *Line, int LineLen)
  384. {
  385. int i;
  386. GifPixelType Mask;
  387. GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
  388. if (!IS_WRITEABLE(Private)) {
  389. /* This file was NOT open for writing: */
  390. GifFile->Error = E_GIF_ERR_NOT_WRITEABLE;
  391. return GIF_ERROR;
  392. }
  393. if (!LineLen)
  394. LineLen = GifFile->Image.Width;
  395. if (Private->PixelCount < (unsigned)LineLen) {
  396. GifFile->Error = E_GIF_ERR_DATA_TOO_BIG;
  397. return GIF_ERROR;
  398. }
  399. Private->PixelCount -= LineLen;
  400. /* Make sure the codes are not out of bit range, as we might generate
  401. * wrong code (because of overflow when we combine them) in this case: */
  402. Mask = CodeMask[Private->BitsPerPixel];
  403. for (i = 0; i < LineLen; i++)
  404. Line[i] &= Mask;
  405. return EGifCompressLine(GifFile, Line, LineLen);
  406. }
  407. /******************************************************************************
  408. Put one pixel (Pixel) into GIF file.
  409. ******************************************************************************/
  410. int
  411. EGifPutPixel(GifFileType *GifFile, GifPixelType Pixel)
  412. {
  413. GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
  414. if (!IS_WRITEABLE(Private)) {
  415. /* This file was NOT open for writing: */
  416. GifFile->Error = E_GIF_ERR_NOT_WRITEABLE;
  417. return GIF_ERROR;
  418. }
  419. if (Private->PixelCount == 0) {
  420. GifFile->Error = E_GIF_ERR_DATA_TOO_BIG;
  421. return GIF_ERROR;
  422. }
  423. --Private->PixelCount;
  424. /* Make sure the code is not out of bit range, as we might generate
  425. * wrong code (because of overflow when we combine them) in this case: */
  426. Pixel &= CodeMask[Private->BitsPerPixel];
  427. return EGifCompressLine(GifFile, &Pixel, 1);
  428. }
  429. /******************************************************************************
  430. Put a comment into GIF file using the GIF89 comment extension block.
  431. ******************************************************************************/
  432. int
  433. EGifPutComment(GifFileType *GifFile, const char *Comment)
  434. {
  435. unsigned int length;
  436. char *buf;
  437. length = strlen(Comment);
  438. if (length <= 255) {
  439. return EGifPutExtension(GifFile, COMMENT_EXT_FUNC_CODE,
  440. length, Comment);
  441. } else {
  442. buf = (char *)Comment;
  443. if (EGifPutExtensionLeader(GifFile, COMMENT_EXT_FUNC_CODE)
  444. == GIF_ERROR) {
  445. return GIF_ERROR;
  446. }
  447. /* Break the comment into 255 byte sub blocks */
  448. while (length > 255) {
  449. if (EGifPutExtensionBlock(GifFile, 255, buf) == GIF_ERROR) {
  450. return GIF_ERROR;
  451. }
  452. buf = buf + 255;
  453. length -= 255;
  454. }
  455. /* Output any partial block and the clear code. */
  456. if (length > 0) {
  457. if (EGifPutExtensionBlock(GifFile, length, buf) == GIF_ERROR) {
  458. return GIF_ERROR;
  459. }
  460. }
  461. if (EGifPutExtensionTrailer(GifFile) == GIF_ERROR) {
  462. return GIF_ERROR;
  463. }
  464. }
  465. return GIF_OK;
  466. }
  467. /******************************************************************************
  468. Begin an extension block (see GIF manual). More
  469. extensions can be dumped using EGifPutExtensionBlock until
  470. EGifPutExtensionTrailer is invoked.
  471. ******************************************************************************/
  472. int
  473. EGifPutExtensionLeader(GifFileType *GifFile, const int ExtCode)
  474. {
  475. GifByteType Buf[3];
  476. GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
  477. if (!IS_WRITEABLE(Private)) {
  478. /* This file was NOT open for writing: */
  479. GifFile->Error = E_GIF_ERR_NOT_WRITEABLE;
  480. return GIF_ERROR;
  481. }
  482. Buf[0] = EXTENSION_INTRODUCER;
  483. Buf[1] = ExtCode;
  484. InternalWrite(GifFile, Buf, 2);
  485. return GIF_OK;
  486. }
  487. /******************************************************************************
  488. Put extension block data (see GIF manual) into a GIF file.
  489. ******************************************************************************/
  490. int
  491. EGifPutExtensionBlock(GifFileType *GifFile,
  492. const int ExtLen,
  493. const void *Extension)
  494. {
  495. GifByteType Buf;
  496. GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
  497. if (!IS_WRITEABLE(Private)) {
  498. /* This file was NOT open for writing: */
  499. GifFile->Error = E_GIF_ERR_NOT_WRITEABLE;
  500. return GIF_ERROR;
  501. }
  502. Buf = ExtLen;
  503. InternalWrite(GifFile, &Buf, 1);
  504. InternalWrite(GifFile, Extension, ExtLen);
  505. return GIF_OK;
  506. }
  507. /******************************************************************************
  508. Put a terminating block (see GIF manual) into a GIF file.
  509. ******************************************************************************/
  510. int
  511. EGifPutExtensionTrailer(GifFileType *GifFile) {
  512. GifByteType Buf;
  513. GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
  514. if (!IS_WRITEABLE(Private)) {
  515. /* This file was NOT open for writing: */
  516. GifFile->Error = E_GIF_ERR_NOT_WRITEABLE;
  517. return GIF_ERROR;
  518. }
  519. /* Write the block terminator */
  520. Buf = 0;
  521. InternalWrite(GifFile, &Buf, 1);
  522. return GIF_OK;
  523. }
  524. /******************************************************************************
  525. Put an extension block (see GIF manual) into a GIF file.
  526. Warning: This function is only useful for Extension blocks that have at
  527. most one subblock. Extensions with more than one subblock need to use the
  528. EGifPutExtension{Leader,Block,Trailer} functions instead.
  529. ******************************************************************************/
  530. int
  531. EGifPutExtension(GifFileType *GifFile,
  532. const int ExtCode,
  533. const int ExtLen,
  534. const void *Extension) {
  535. GifByteType Buf[3];
  536. GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
  537. if (!IS_WRITEABLE(Private)) {
  538. /* This file was NOT open for writing: */
  539. GifFile->Error = E_GIF_ERR_NOT_WRITEABLE;
  540. return GIF_ERROR;
  541. }
  542. if (ExtCode == 0)
  543. InternalWrite(GifFile, (GifByteType *)&ExtLen, 1);
  544. else {
  545. Buf[0] = EXTENSION_INTRODUCER;
  546. Buf[1] = ExtCode; /* Extension Label */
  547. Buf[2] = ExtLen; /* Extension length */
  548. InternalWrite(GifFile, Buf, 3);
  549. }
  550. InternalWrite(GifFile, Extension, ExtLen);
  551. Buf[0] = 0;
  552. InternalWrite(GifFile, Buf, 1);
  553. return GIF_OK;
  554. }
  555. /******************************************************************************
  556. Render a Graphics Control Block as raw extension data
  557. ******************************************************************************/
  558. size_t EGifGCBToExtension(const GraphicsControlBlock *GCB,
  559. GifByteType *GifExtension)
  560. {
  561. GifExtension[0] = 0;
  562. GifExtension[0] |= (GCB->TransparentColor == NO_TRANSPARENT_COLOR) ? 0x00 : 0x01;
  563. GifExtension[0] |= GCB->UserInputFlag ? 0x02 : 0x00;
  564. GifExtension[0] |= ((GCB->DisposalMode & 0x07) << 2);
  565. GifExtension[1] = LOBYTE(GCB->DelayTime);
  566. GifExtension[2] = HIBYTE(GCB->DelayTime);
  567. GifExtension[3] = (char)GCB->TransparentColor;
  568. return 4;
  569. }
  570. /******************************************************************************
  571. Replace the Graphics Control Block for a saved image, if it exists.
  572. ******************************************************************************/
  573. int EGifGCBToSavedExtension(const GraphicsControlBlock *GCB,
  574. GifFileType *GifFile, int ImageIndex)
  575. {
  576. int i;
  577. size_t Len;
  578. GifByteType buf[sizeof(GraphicsControlBlock)]; /* a bit dodgy... */
  579. if (ImageIndex < 0 || ImageIndex > GifFile->ImageCount - 1)
  580. return GIF_ERROR;
  581. for (i = 0; i < GifFile->SavedImages[ImageIndex].ExtensionBlockCount; i++) {
  582. ExtensionBlock *ep = &GifFile->SavedImages[ImageIndex].ExtensionBlocks[i];
  583. if (ep->Function == GRAPHICS_EXT_FUNC_CODE) {
  584. EGifGCBToExtension(GCB, ep->Bytes);
  585. return GIF_OK;
  586. }
  587. }
  588. Len = EGifGCBToExtension(GCB, (GifByteType *)buf);
  589. if (GifAddExtensionBlock(&GifFile->SavedImages[ImageIndex].ExtensionBlockCount,
  590. &GifFile->SavedImages[ImageIndex].ExtensionBlocks,
  591. GRAPHICS_EXT_FUNC_CODE,
  592. Len,
  593. (unsigned char *)buf) == GIF_ERROR)
  594. return (GIF_ERROR);
  595. return (GIF_OK);
  596. }
  597. /******************************************************************************
  598. Put the image code in compressed form. This routine can be called if the
  599. information needed to be piped out as is. Obviously this is much faster
  600. than decoding and encoding again. This routine should be followed by calls
  601. to EGifPutCodeNext, until NULL block is given.
  602. The block should NOT be freed by the user (not dynamically allocated).
  603. ******************************************************************************/
  604. int
  605. EGifPutCode(GifFileType *GifFile, int CodeSize, const GifByteType *CodeBlock)
  606. {
  607. GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
  608. if (!IS_WRITEABLE(Private)) {
  609. /* This file was NOT open for writing: */
  610. GifFile->Error = E_GIF_ERR_NOT_WRITEABLE;
  611. return GIF_ERROR;
  612. }
  613. /* No need to dump code size as Compression set up does any for us: */
  614. /*
  615. * Buf = CodeSize;
  616. * if (InternalWrite(GifFile, &Buf, 1) != 1) {
  617. * GifFile->Error = E_GIF_ERR_WRITE_FAILED;
  618. * return GIF_ERROR;
  619. * }
  620. */
  621. return EGifPutCodeNext(GifFile, CodeBlock);
  622. }
  623. /******************************************************************************
  624. Continue to put the image code in compressed form. This routine should be
  625. called with blocks of code as read via DGifGetCode/DGifGetCodeNext. If
  626. given buffer pointer is NULL, empty block is written to mark end of code.
  627. ******************************************************************************/
  628. int
  629. EGifPutCodeNext(GifFileType *GifFile, const GifByteType *CodeBlock)
  630. {
  631. GifByteType Buf;
  632. GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
  633. if (CodeBlock != NULL) {
  634. if (InternalWrite(GifFile, CodeBlock, CodeBlock[0] + 1)
  635. != (unsigned)(CodeBlock[0] + 1)) {
  636. GifFile->Error = E_GIF_ERR_WRITE_FAILED;
  637. return GIF_ERROR;
  638. }
  639. } else {
  640. Buf = 0;
  641. if (InternalWrite(GifFile, &Buf, 1) != 1) {
  642. GifFile->Error = E_GIF_ERR_WRITE_FAILED;
  643. return GIF_ERROR;
  644. }
  645. Private->PixelCount = 0; /* And local info. indicate image read. */
  646. }
  647. return GIF_OK;
  648. }
  649. /******************************************************************************
  650. This routine should be called last, to close the GIF file.
  651. ******************************************************************************/
  652. int
  653. EGifCloseFile(GifFileType *GifFile, int *ErrorCode)
  654. {
  655. GifByteType Buf;
  656. GifFilePrivateType *Private;
  657. FILE *File;
  658. if (GifFile == NULL)
  659. return GIF_ERROR;
  660. Private = (GifFilePrivateType *) GifFile->Private;
  661. if (Private == NULL)
  662. return GIF_ERROR;
  663. if (!IS_WRITEABLE(Private)) {
  664. /* This file was NOT open for writing: */
  665. if (ErrorCode != NULL)
  666. *ErrorCode = E_GIF_ERR_NOT_WRITEABLE;
  667. free(GifFile);
  668. return GIF_ERROR;
  669. }
  670. File = Private->File;
  671. Buf = TERMINATOR_INTRODUCER;
  672. InternalWrite(GifFile, &Buf, 1);
  673. if (GifFile->Image.ColorMap) {
  674. GifFreeMapObject(GifFile->Image.ColorMap);
  675. GifFile->Image.ColorMap = NULL;
  676. }
  677. if (GifFile->SColorMap) {
  678. GifFreeMapObject(GifFile->SColorMap);
  679. GifFile->SColorMap = NULL;
  680. }
  681. if (Private) {
  682. if (Private->HashTable) {
  683. free((char *) Private->HashTable);
  684. }
  685. free((char *) Private);
  686. }
  687. if (File && fclose(File) != 0) {
  688. if (ErrorCode != NULL)
  689. *ErrorCode = E_GIF_ERR_CLOSE_FAILED;
  690. free(GifFile);
  691. return GIF_ERROR;
  692. }
  693. free(GifFile);
  694. if (ErrorCode != NULL)
  695. *ErrorCode = E_GIF_SUCCEEDED;
  696. return GIF_OK;
  697. }
  698. /******************************************************************************
  699. Put 2 bytes (a word) into the given file in little-endian order:
  700. ******************************************************************************/
  701. static int
  702. EGifPutWord(int Word, GifFileType *GifFile)
  703. {
  704. unsigned char c[2];
  705. c[0] = LOBYTE(Word);
  706. c[1] = HIBYTE(Word);
  707. if (InternalWrite(GifFile, c, 2) == 2)
  708. return GIF_OK;
  709. else
  710. return GIF_ERROR;
  711. }
  712. /******************************************************************************
  713. Setup the LZ compression for this image:
  714. ******************************************************************************/
  715. static int
  716. EGifSetupCompress(GifFileType *GifFile)
  717. {
  718. int BitsPerPixel;
  719. GifByteType Buf;
  720. GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
  721. /* Test and see what color map to use, and from it # bits per pixel: */
  722. if (GifFile->Image.ColorMap)
  723. BitsPerPixel = GifFile->Image.ColorMap->BitsPerPixel;
  724. else if (GifFile->SColorMap)
  725. BitsPerPixel = GifFile->SColorMap->BitsPerPixel;
  726. else {
  727. GifFile->Error = E_GIF_ERR_NO_COLOR_MAP;
  728. return GIF_ERROR;
  729. }
  730. Buf = BitsPerPixel = (BitsPerPixel < 2 ? 2 : BitsPerPixel);
  731. InternalWrite(GifFile, &Buf, 1); /* Write the Code size to file. */
  732. Private->Buf[0] = 0; /* Nothing was output yet. */
  733. Private->BitsPerPixel = BitsPerPixel;
  734. Private->ClearCode = (1 << BitsPerPixel);
  735. Private->EOFCode = Private->ClearCode + 1;
  736. Private->RunningCode = Private->EOFCode + 1;
  737. Private->RunningBits = BitsPerPixel + 1; /* Number of bits per code. */
  738. Private->MaxCode1 = 1 << Private->RunningBits; /* Max. code + 1. */
  739. Private->CrntCode = FIRST_CODE; /* Signal that this is first one! */
  740. Private->CrntShiftState = 0; /* No information in CrntShiftDWord. */
  741. Private->CrntShiftDWord = 0;
  742. /* Clear hash table and send Clear to make sure the decoder do the same. */
  743. _ClearHashTable(Private->HashTable);
  744. if (EGifCompressOutput(GifFile, Private->ClearCode) == GIF_ERROR) {
  745. GifFile->Error = E_GIF_ERR_DISK_IS_FULL;
  746. return GIF_ERROR;
  747. }
  748. return GIF_OK;
  749. }
  750. /******************************************************************************
  751. The LZ compression routine:
  752. This version compresses the given buffer Line of length LineLen.
  753. This routine can be called a few times (one per scan line, for example), in
  754. order to complete the whole image.
  755. ******************************************************************************/
  756. static int
  757. EGifCompressLine(GifFileType *GifFile,
  758. GifPixelType *Line,
  759. const int LineLen)
  760. {
  761. int i = 0, CrntCode, NewCode;
  762. unsigned long NewKey;
  763. GifPixelType Pixel;
  764. GifHashTableType *HashTable;
  765. GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
  766. HashTable = Private->HashTable;
  767. if (Private->CrntCode == FIRST_CODE) /* Its first time! */
  768. CrntCode = Line[i++];
  769. else
  770. CrntCode = Private->CrntCode; /* Get last code in compression. */
  771. while (i < LineLen) { /* Decode LineLen items. */
  772. Pixel = Line[i++]; /* Get next pixel from stream. */
  773. /* Form a new unique key to search hash table for the code combines
  774. * CrntCode as Prefix string with Pixel as postfix char.
  775. */
  776. NewKey = (((uint32_t) CrntCode) << 8) + Pixel;
  777. if ((NewCode = _ExistsHashTable(HashTable, NewKey)) >= 0) {
  778. /* This Key is already there, or the string is old one, so
  779. * simple take new code as our CrntCode:
  780. */
  781. CrntCode = NewCode;
  782. } else {
  783. /* Put it in hash table, output the prefix code, and make our
  784. * CrntCode equal to Pixel.
  785. */
  786. if (EGifCompressOutput(GifFile, CrntCode) == GIF_ERROR) {
  787. GifFile->Error = E_GIF_ERR_DISK_IS_FULL;
  788. return GIF_ERROR;
  789. }
  790. CrntCode = Pixel;
  791. /* If however the HashTable if full, we send a clear first and
  792. * Clear the hash table.
  793. */
  794. if (Private->RunningCode >= LZ_MAX_CODE) {
  795. /* Time to do some clearance: */
  796. if (EGifCompressOutput(GifFile, Private->ClearCode)
  797. == GIF_ERROR) {
  798. GifFile->Error = E_GIF_ERR_DISK_IS_FULL;
  799. return GIF_ERROR;
  800. }
  801. Private->RunningCode = Private->EOFCode + 1;
  802. Private->RunningBits = Private->BitsPerPixel + 1;
  803. Private->MaxCode1 = 1 << Private->RunningBits;
  804. _ClearHashTable(HashTable);
  805. } else {
  806. /* Put this unique key with its relative Code in hash table: */
  807. _InsertHashTable(HashTable, NewKey, Private->RunningCode++);
  808. }
  809. }
  810. }
  811. /* Preserve the current state of the compression algorithm: */
  812. Private->CrntCode = CrntCode;
  813. if (Private->PixelCount == 0) {
  814. /* We are done - output last Code and flush output buffers: */
  815. if (EGifCompressOutput(GifFile, CrntCode) == GIF_ERROR) {
  816. GifFile->Error = E_GIF_ERR_DISK_IS_FULL;
  817. return GIF_ERROR;
  818. }
  819. if (EGifCompressOutput(GifFile, Private->EOFCode) == GIF_ERROR) {
  820. GifFile->Error = E_GIF_ERR_DISK_IS_FULL;
  821. return GIF_ERROR;
  822. }
  823. if (EGifCompressOutput(GifFile, FLUSH_OUTPUT) == GIF_ERROR) {
  824. GifFile->Error = E_GIF_ERR_DISK_IS_FULL;
  825. return GIF_ERROR;
  826. }
  827. }
  828. return GIF_OK;
  829. }
  830. /******************************************************************************
  831. The LZ compression output routine:
  832. This routine is responsible for the compression of the bit stream into
  833. 8 bits (bytes) packets.
  834. Returns GIF_OK if written successfully.
  835. ******************************************************************************/
  836. static int
  837. EGifCompressOutput(GifFileType *GifFile,
  838. const int Code)
  839. {
  840. GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
  841. int retval = GIF_OK;
  842. if (Code == FLUSH_OUTPUT) {
  843. while (Private->CrntShiftState > 0) {
  844. /* Get Rid of what is left in DWord, and flush it. */
  845. if (EGifBufferedOutput(GifFile, Private->Buf,
  846. Private->CrntShiftDWord & 0xff) == GIF_ERROR)
  847. retval = GIF_ERROR;
  848. Private->CrntShiftDWord >>= 8;
  849. Private->CrntShiftState -= 8;
  850. }
  851. Private->CrntShiftState = 0; /* For next time. */
  852. if (EGifBufferedOutput(GifFile, Private->Buf,
  853. FLUSH_OUTPUT) == GIF_ERROR)
  854. retval = GIF_ERROR;
  855. } else {
  856. Private->CrntShiftDWord |= ((long)Code) << Private->CrntShiftState;
  857. Private->CrntShiftState += Private->RunningBits;
  858. while (Private->CrntShiftState >= 8) {
  859. /* Dump out full bytes: */
  860. if (EGifBufferedOutput(GifFile, Private->Buf,
  861. Private->CrntShiftDWord & 0xff) == GIF_ERROR)
  862. retval = GIF_ERROR;
  863. Private->CrntShiftDWord >>= 8;
  864. Private->CrntShiftState -= 8;
  865. }
  866. }
  867. /* If code cannt fit into RunningBits bits, must raise its size. Note */
  868. /* however that codes above 4095 are used for special signaling. */
  869. if (Private->RunningCode >= Private->MaxCode1 && Code <= 4095) {
  870. Private->MaxCode1 = 1 << ++Private->RunningBits;
  871. }
  872. return retval;
  873. }
  874. /******************************************************************************
  875. This routines buffers the given characters until 255 characters are ready
  876. to be output. If Code is equal to -1 the buffer is flushed (EOF).
  877. The buffer is Dumped with first byte as its size, as GIF format requires.
  878. Returns GIF_OK if written successfully.
  879. ******************************************************************************/
  880. static int
  881. EGifBufferedOutput(GifFileType *GifFile,
  882. GifByteType *Buf,
  883. int c)
  884. {
  885. if (c == FLUSH_OUTPUT) {
  886. /* Flush everything out. */
  887. if (Buf[0] != 0
  888. && InternalWrite(GifFile, Buf, Buf[0] + 1) != (unsigned)(Buf[0] + 1)) {
  889. GifFile->Error = E_GIF_ERR_WRITE_FAILED;
  890. return GIF_ERROR;
  891. }
  892. /* Mark end of compressed data, by an empty block (see GIF doc): */
  893. Buf[0] = 0;
  894. if (InternalWrite(GifFile, Buf, 1) != 1) {
  895. GifFile->Error = E_GIF_ERR_WRITE_FAILED;
  896. return GIF_ERROR;
  897. }
  898. } else {
  899. if (Buf[0] == 255) {
  900. /* Dump out this buffer - it is full: */
  901. if (InternalWrite(GifFile, Buf, Buf[0] + 1) != (unsigned)(Buf[0] + 1)) {
  902. GifFile->Error = E_GIF_ERR_WRITE_FAILED;
  903. return GIF_ERROR;
  904. }
  905. Buf[0] = 0;
  906. }
  907. Buf[++Buf[0]] = c;
  908. }
  909. return GIF_OK;
  910. }
  911. /******************************************************************************
  912. This routine writes to disk an in-core representation of a GIF previously
  913. created by DGifSlurp().
  914. ******************************************************************************/
  915. static int
  916. EGifWriteExtensions(GifFileType *GifFileOut,
  917. ExtensionBlock *ExtensionBlocks,
  918. int ExtensionBlockCount)
  919. {
  920. if (ExtensionBlocks) {
  921. ExtensionBlock *ep;
  922. int j;
  923. for (j = 0; j < ExtensionBlockCount; j++) {
  924. ep = &ExtensionBlocks[j];
  925. if (ep->Function != CONTINUE_EXT_FUNC_CODE)
  926. if (EGifPutExtensionLeader(GifFileOut, ep->Function) == GIF_ERROR)
  927. return (GIF_ERROR);
  928. if (EGifPutExtensionBlock(GifFileOut, ep->ByteCount, ep->Bytes) == GIF_ERROR)
  929. return (GIF_ERROR);
  930. if (j == ExtensionBlockCount - 1 || (ep+1)->Function != CONTINUE_EXT_FUNC_CODE)
  931. if (EGifPutExtensionTrailer(GifFileOut) == GIF_ERROR)
  932. return (GIF_ERROR);
  933. }
  934. }
  935. return (GIF_OK);
  936. }
  937. int
  938. EGifSpew(GifFileType *GifFileOut)
  939. {
  940. int i, j;
  941. if (EGifPutScreenDesc(GifFileOut,
  942. GifFileOut->SWidth,
  943. GifFileOut->SHeight,
  944. GifFileOut->SColorResolution,
  945. GifFileOut->SBackGroundColor,
  946. GifFileOut->SColorMap) == GIF_ERROR) {
  947. return (GIF_ERROR);
  948. }
  949. for (i = 0; i < GifFileOut->ImageCount; i++) {
  950. SavedImage *sp = &GifFileOut->SavedImages[i];
  951. int SavedHeight = sp->ImageDesc.Height;
  952. int SavedWidth = sp->ImageDesc.Width;
  953. /* this allows us to delete images by nuking their rasters */
  954. if (sp->RasterBits == NULL)
  955. continue;
  956. if (EGifWriteExtensions(GifFileOut,
  957. sp->ExtensionBlocks,
  958. sp->ExtensionBlockCount) == GIF_ERROR)
  959. return (GIF_ERROR);
  960. if (EGifPutImageDesc(GifFileOut,
  961. sp->ImageDesc.Left,
  962. sp->ImageDesc.Top,
  963. SavedWidth,
  964. SavedHeight,
  965. sp->ImageDesc.Interlace,
  966. sp->ImageDesc.ColorMap) == GIF_ERROR)
  967. return (GIF_ERROR);
  968. if (sp->ImageDesc.Interlace) {
  969. /*
  970. * The way an interlaced image should be written -
  971. * offsets and jumps...
  972. */
  973. int InterlacedOffset[] = { 0, 4, 2, 1 };
  974. int InterlacedJumps[] = { 8, 8, 4, 2 };
  975. int k;
  976. /* Need to perform 4 passes on the images: */
  977. for (k = 0; k < 4; k++)
  978. for (j = InterlacedOffset[k];
  979. j < SavedHeight;
  980. j += InterlacedJumps[k]) {
  981. if (EGifPutLine(GifFileOut,
  982. sp->RasterBits + j * SavedWidth,
  983. SavedWidth) == GIF_ERROR)
  984. return (GIF_ERROR);
  985. }
  986. } else {
  987. for (j = 0; j < SavedHeight; j++) {
  988. if (EGifPutLine(GifFileOut,
  989. sp->RasterBits + j * SavedWidth,
  990. SavedWidth) == GIF_ERROR)
  991. return (GIF_ERROR);
  992. }
  993. }
  994. }
  995. if (EGifWriteExtensions(GifFileOut,
  996. GifFileOut->ExtensionBlocks,
  997. GifFileOut->ExtensionBlockCount) == GIF_ERROR)
  998. return (GIF_ERROR);
  999. if (EGifCloseFile(GifFileOut, NULL) == GIF_ERROR)
  1000. return (GIF_ERROR);
  1001. return (GIF_OK);
  1002. }
  1003. /* end */