iltiffwrite.c 56 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * Copyright (c) 1993-2012, The Open Group. All rights reserved.
  5. *
  6. * These libraries and programs are free software; you can
  7. * redistribute them and/or modify them under the terms of the GNU
  8. * Lesser General Public License as published by the Free Software
  9. * Foundation; either version 2 of the License, or (at your option)
  10. * any later version.
  11. *
  12. * These libraries and programs are distributed in the hope that
  13. * they will be useful, but WITHOUT ANY WARRANTY; without even the
  14. * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  15. * PURPOSE. See the GNU Lesser General Public License for more
  16. * details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with these libraries and programs; if not, write
  20. * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
  21. * Floor, Boston, MA 02110-1301 USA
  22. */
  23. /* $XConsortium: iltiffwrite.c /main/4 1996/01/08 12:17:15 lehors $ */
  24. /* /ilc/iltiffwrite.c : Code for ilWriteFileImage(); add a consumer to the pipe
  25. to write to a TIFF file. See also /ilc/iltiff.c and /ilc/iltiffread.c .
  26. */
  27. #include "iltiffint.h"
  28. #include "ilpipelem.h"
  29. #include "iljpgencode.h"
  30. #include "ilerrors.h"
  31. /* Tag info summary, private to ilWriteFileImage(). Encapsulates the user and std
  32. tag info. Contains ptrs to data which is created when the pipe element is added
  33. and freed when pipe emptied (Destroy() function).
  34. "pTagOffsets" points to an array of offsets, in the same order as the tags at
  35. "pTagWriteData" + 2 (bytes). For each tag, if the offset is zero (0), the tag
  36. data is in the tag, already byte-flipped. If non-zero, it is the offset of the
  37. tag data from pTagWriteData. The file offset where the data at pTagWriteData
  38. will be written must be added to this offset and inserted into the tag byte-flipped.
  39. See ilMergeWriteTags() for details.
  40. */
  41. typedef struct {
  42. ilPtr pAlloc; /* ptr to whole mess to deallocate */
  43. CARD32 *pTagOffsets; /* see above */
  44. ilPtr pTagWriteData; /* ptr to data to write to file */
  45. long tagWriteSize; /* size in bytes of data to write */
  46. ilFileOffset *pStripOffsets; /* ptr to strip offset list in memory */
  47. INT32 *pStripByteCounts; /* ptr to strip byte count list in memory */
  48. ilFileOffset *pJIF; /* (JIF only): offset in memory */
  49. long *pJIFLength; /* (JIF only): length in memory */
  50. unsigned short *pJPEGRestart; /* (JPEG only): restart interval in memory */
  51. long *pJPEGQTables; /* (JPEG only): Q tables in memory */
  52. long *pJPEGDCTables; /* (JPEG only): DC tables in memory */
  53. long *pJPEGACTables; /* (JPEG only): AC tables in memory */
  54. unsigned short *pPalette; /* ptr to pal; null if not palette image */
  55. int nPaletteColors; /* # of RGB triplets at pPalette */
  56. int tagCount; /* # of tags to write */
  57. } ilTagInfoRec, *ilTagInfoPtr;
  58. typedef struct {
  59. /* Data set into private when element added */
  60. ilFilePtr pFile; /* ptr to file being written */
  61. ilTagInfoRec tagInfo; /* see above */
  62. ilBool bigEndian; /* true if MM byte order file */
  63. unsigned int compression; /* type of compression being written */
  64. long nStrips; /* # of strips which should be written */
  65. ilFileOffset tailPtrOffset; /* "next ptr" to point to this image */
  66. ilFileImageRec fileImage; /* data for file image being added */
  67. /* Data set/inited by ilWriteFileInit() */
  68. ilFileOffset *pStripOffset; /* next in-memory strip offset to store */
  69. INT32 *pStripByteCount; /* same for byte count (# bytes written) */
  70. long nStripsSoFar; /* # of strips written so far */
  71. long nLinesSoFar; /* # of lines written so far */
  72. long nBytesSoFar; /* # of bytes written so far (JPEG only) */
  73. } ilWriteFilePrivRec, *ilWriteFilePrivPtr;
  74. /* Copy 4 bytes of a long byte-flipped based on given "bigEndian" flag, to
  75. the given ptr which must be of type ilPtr. Same for a short.
  76. */
  77. #define IL_WRITE_FLIP_LONG(_bigEndian, _long, _ptr) { \
  78. if (_bigEndian) { \
  79. *(_ptr)++ = (_long) >> 24; \
  80. *(_ptr)++ = ((_long) >> 16) & 0xff; \
  81. *(_ptr)++ = ((_long) >> 8) & 0xff; \
  82. *(_ptr)++ = (_long) & 0xff; \
  83. } \
  84. else { \
  85. *(_ptr)++ = (_long) & 0xff; \
  86. *(_ptr)++ = ((_long) >> 8) & 0xff; \
  87. *(_ptr)++ = ((_long) >> 16) & 0xff; \
  88. *(_ptr)++ = (_long) >> 24; \
  89. } \
  90. }
  91. #define IL_WRITE_FLIP_SHORT(_bigEndian, _short, _ptr) { \
  92. if (_bigEndian) { \
  93. *(_ptr)++ = ((_short) >> 8) & 0xff; \
  94. *(_ptr)++ = (_short) & 0xff; \
  95. } \
  96. else { \
  97. *(_ptr)++ = (_short) & 0xff; \
  98. *(_ptr)++ = ((_short) >> 8) & 0xff; \
  99. } \
  100. }
  101. /* --------------------- ilWriteFileInit -------------------------- */
  102. /* Init() function for ilWriteFileImage().
  103. */
  104. static ilError ilWriteFileInit (
  105. ilWriteFilePrivPtr pPriv,
  106. ilImageInfo *pSrcImage,
  107. ilImageInfo *pDstImage
  108. )
  109. {
  110. /* Point to beginning of strip offset/byte count memory buffers. */
  111. pPriv->pStripOffset = pPriv->tagInfo.pStripOffsets;
  112. pPriv->pStripByteCount = pPriv->tagInfo.pStripByteCounts;
  113. pPriv->nStripsSoFar = 0;
  114. pPriv->nLinesSoFar = 0;
  115. pPriv->nBytesSoFar = 0;
  116. return IL_OK;
  117. }
  118. /* --------------------- ilWriteFileCleanup -------------------------- */
  119. /* Cleanup() function for ilWriteFileImage().
  120. */
  121. static ilError ilWriteFileCleanup (
  122. ilWriteFilePrivPtr pPriv,
  123. ilBool aborting
  124. )
  125. {
  126. ilFilePtr pFile;
  127. ilFileOffset position;
  128. ilByte fourBytes[4], nextBytes[4];
  129. ilPtr pBytes, pTag;
  130. CARD32 *pTagOffsets, l;
  131. int i;
  132. /* If aborting pipe, just exit. The net effect is that if
  133. some image strips are written and the pipe aborted before completion,
  134. the image strips are there but not pointed to by anything.
  135. */
  136. if (aborting)
  137. return IL_OK; /* EXIT */
  138. /* Make sure the proper # of lines and strips have been written or error. */
  139. if ((pPriv->nStripsSoFar != pPriv->nStrips)
  140. || (pPriv->nLinesSoFar != pPriv->fileImage.p.height))
  141. return IL_ERROR_MALFORMED_FILE_WRITE;
  142. pFile = pPriv->pFile;
  143. /* Read "offset to next" that will be pointed to this image; set as "offset to
  144. next" for this image (IFDOffset), following tag info; see ilMergeWriteTags().
  145. */
  146. if (!IL_SEEK (pFile, pPriv->tailPtrOffset) || !IL_READ (pFile, 4, nextBytes))
  147. return IL_ERROR_FILE_IO;
  148. pBytes = pPriv->tagInfo.pTagWriteData + pPriv->tagInfo.tagCount * IL_TAG_SIZE + 2;
  149. *pBytes++ = nextBytes[0];
  150. *pBytes++ = nextBytes[1];
  151. *pBytes++ = nextBytes[2];
  152. *pBytes++ = nextBytes[3];
  153. /* Position to EOF; save file position in "position". Update tags whose values
  154. did not fit in the tag; they have a non-zero value in the array @pTagOffsets;
  155. the value is the offset from the beginning of the data to be written to the
  156. tag data.
  157. */
  158. if (fseek (pFile->stream, 0, 2)) /* seek to EOF (2); return != 0 is error */
  159. return IL_ERROR_FILE_IO;
  160. position = ftell (pFile->stream) - pFile->offset;
  161. pTagOffsets = pPriv->tagInfo.pTagOffsets;
  162. pTag = pPriv->tagInfo.pTagWriteData + 2;
  163. for (i = 0; i < pPriv->tagInfo.tagCount; i++, pTagOffsets++, pTag += IL_TAG_SIZE)
  164. if (*pTagOffsets) {
  165. l = position + *pTagOffsets;
  166. pBytes = pTag + 8; /* point to offset field of the tag */
  167. IL_WRITE_FLIP_LONG (pPriv->bigEndian, l, pBytes)
  168. }
  169. /* Write out the tag data to add the image to the file. Patch location at
  170. "tailPtrOffset" in file to point to this image to link image into list.
  171. */
  172. if (fwrite ((char *)pPriv->tagInfo.pTagWriteData, pPriv->tagInfo.tagWriteSize, 1,
  173. pFile->stream) != 1)
  174. return IL_ERROR_FILE_IO;
  175. pBytes = fourBytes;
  176. /* compatibility problem with long or unsigned long data fields */
  177. IL_WRITE_FLIP_LONG (pPriv->bigEndian, (CARD32)position, pBytes)
  178. if (!IL_SEEK (pFile, pPriv->tailPtrOffset) || !IL_WRITE (pFile, 4, fourBytes))
  179. return IL_ERROR_FILE_IO;
  180. fflush (pFile->stream); /* flush all buffers; image now in file */
  181. /* If this image is now last in file (its next offset is null), update file's
  182. offset to last image's offset to next, and copy of same in private.
  183. */
  184. if (!nextBytes[0] && !nextBytes[1] && !nextBytes[2] && !nextBytes[3]) {
  185. pFile->IFDTailPtrOffset = position + pPriv->tagInfo.tagCount * IL_TAG_SIZE + 2;
  186. pPriv->tailPtrOffset = pFile->IFDTailPtrOffset;
  187. }
  188. /* Mark file image list as invalid, so this image will show up next time. */
  189. pFile->haveImageList = FALSE;
  190. return IL_OK;
  191. }
  192. /* ------------------------ ilWriteFileDestroy ----------------------------- */
  193. /* Destroy() function for ilWriteFileImage().
  194. */
  195. static ilError ilWriteFileDestroy (
  196. ilWriteFilePrivPtr pPriv
  197. )
  198. {
  199. /* Free the tag data malloc'd by ilMergeWriteTags() when element added. */
  200. IL_FREE (pPriv->tagInfo.pAlloc);
  201. return IL_OK;
  202. }
  203. /* --------------------- ilCopyPalette -------------------------- */
  204. /* Called by Execute() function before writing first strip to copy the palette
  205. into the tag memory buffer, so it will be written out by ilWriteFileCleanup().
  206. */
  207. static void ilCopyPalette (
  208. ilWriteFilePrivPtr pPriv,
  209. unsigned short *pSrcPalette
  210. )
  211. {
  212. unsigned short *pDstPalette;
  213. ilPtr pBytes;
  214. /* Since using IL_WRITE_FLIP_SHORT, palEntry should be unsigned short */
  215. unsigned short palEntry;
  216. unsigned long greenOffset, blueOffset;
  217. int i;
  218. /* Copy palette into the in-memory tag area, byte-flipped.
  219. It will be written out along with all the tags and tag data during Cleanup().
  220. TIFF palettes are the same as IL: all the red, then green, then blue values,
  221. each a short, except in TIFF each is "2 ** nBits" entries
  222. (pPriv->nPaletteColors) in length; in the IL they are always 256 entries.
  223. */
  224. pDstPalette = pPriv->tagInfo.pPalette;
  225. if (pDstPalette) {
  226. greenOffset = pPriv->tagInfo.nPaletteColors;
  227. blueOffset = pPriv->tagInfo.nPaletteColors * 2;
  228. for (i = 0; i < pPriv->tagInfo.nPaletteColors; i++, pSrcPalette++, pDstPalette++) {
  229. palEntry = *pSrcPalette;
  230. pBytes = (ilPtr)pDstPalette;
  231. IL_WRITE_FLIP_SHORT (pPriv->bigEndian, palEntry, pBytes)
  232. palEntry = *(pSrcPalette + 256);
  233. pBytes = (ilPtr)(pDstPalette + greenOffset);
  234. IL_WRITE_FLIP_SHORT (pPriv->bigEndian, palEntry, pBytes)
  235. palEntry = *(pSrcPalette + 512);
  236. pBytes = (ilPtr)(pDstPalette + blueOffset);
  237. IL_WRITE_FLIP_SHORT (pPriv->bigEndian, palEntry, pBytes)
  238. }
  239. }
  240. }
  241. /* --------------------- ilWriteFileExecute -------------------------- */
  242. /* Execute() for ilWriteFileImage().
  243. */
  244. static ilError ilWriteFileExecute (
  245. ilExecuteData *pData,
  246. long dstLine,
  247. long *pNLines
  248. )
  249. {
  250. ilWriteFilePrivPtr pPriv;
  251. ilFilePtr pFile;
  252. unsigned long nBytes, rowBytes;
  253. ilPtr pBytes;
  254. long position;
  255. if (*pNLines <= 0)
  256. return IL_OK;
  257. pPriv = (ilWriteFilePrivPtr)pData->pPrivate;
  258. pFile = pPriv->pFile;
  259. /* If first strip and a palette image copy the palette into tag data */
  260. if ((pPriv->nStripsSoFar <= 0) && pPriv->tagInfo.pPalette)
  261. ilCopyPalette (pPriv, pData->pSrcImage->pPalette);
  262. /* Check for too many lines/strips or inconstant strips (except last). */
  263. pPriv->nLinesSoFar += *pNLines;
  264. pPriv->nStripsSoFar++;
  265. if ((pPriv->nStripsSoFar > pPriv->nStrips)
  266. || (pPriv->nLinesSoFar > pPriv->fileImage.p.height)
  267. || ((pPriv->nLinesSoFar != pPriv->fileImage.p.height) /* not last strip */
  268. && (*pNLines != pPriv->fileImage.p.stripHeight)))
  269. return IL_ERROR_MALFORMED_FILE_WRITE;
  270. /* Write one strip of data to the end of the file, after saving "position". */
  271. if (fseek (pFile->stream, 0, 2)) /* seek to EOF (2); return != 0 is error */
  272. return IL_ERROR_FILE_IO; /* EXIT */
  273. position = ftell (pFile->stream) - pFile->offset;
  274. if (pPriv->compression == IL_UNCOMPRESSED) {
  275. rowBytes = pData->pSrcImage->plane[0].nBytesPerRow;
  276. nBytes = rowBytes * *pNLines;
  277. pBytes = pData->pSrcImage->plane[0].pPixels + pData->srcLine * rowBytes;
  278. }
  279. else {
  280. nBytes = pData->compressed.nBytesToRead;
  281. pBytes = pData->pSrcImage->plane[0].pPixels + pData->compressed.srcOffset;
  282. }
  283. if (fwrite ((char *)pBytes, nBytes, 1, pFile->stream) != 1)
  284. return IL_ERROR_FILE_IO; /* EXIT */
  285. /* Store byte-flipped the offset within the file (position) and size
  286. (nBytes) of the strip just written.
  287. */
  288. pBytes = (ilPtr)pPriv->pStripOffset;
  289. pPriv->pStripOffset++;
  290. /* compatibility problem with long or unsigned long data fields */
  291. IL_WRITE_FLIP_LONG (pPriv->bigEndian, (CARD32)position, pBytes)
  292. pBytes = (ilPtr)pPriv->pStripByteCount;
  293. pPriv->pStripByteCount++;
  294. /* compatibility problem with long or unsigned long data fields */
  295. IL_WRITE_FLIP_LONG (pPriv->bigEndian, (CARD32)nBytes, pBytes)
  296. return IL_OK;
  297. }
  298. /* --------------------------- ilWriteJIFData -------------------------------- */
  299. /* Called by ilWriteJPEGExecute() when first strip encountered, to encode
  300. and write a JIF header into the TIFF file.
  301. */
  302. static ilError ilWriteJIFData (
  303. ilWriteFilePrivPtr pPriv,
  304. ilFilePtr pFile,
  305. ilImageInfo *pImage
  306. )
  307. {
  308. iljpgJIFOffsetsRec offsets;
  309. iljpgDataRec data;
  310. long JIFOffset;
  311. long position, nBytes, i, j;
  312. ilJPEGEncodeStream streamRec;
  313. ilJPEGData *pCompData;
  314. ilError error;
  315. long mcuWidth, mcuHeight;
  316. ilPtr pBytes;
  317. /* Init streamRec so output is written into malloc'd memory, and encode
  318. a JIF image into that memory. For restartInterval value: if a single strip
  319. use value from raw data (== 0 if no restart markers), otherwise calculate
  320. it from strip size. If multi-strip and non-zero restartMarker in raw data
  321. a JIF image cannot be created - see below.
  322. */
  323. pCompData = (ilJPEGData *)pImage->pCompData;
  324. _ilJPEGDataIn (pImage->pDes, pPriv->fileImage.p.width, pPriv->fileImage.p.height,
  325. &data);
  326. _ilJPEGTablesIn (pCompData, &data);
  327. if (pPriv->nStrips != 1) { /* else data.restartInterval = raw already */
  328. mcuWidth = 8 * data.maxHoriFactor;
  329. mcuHeight = 8 * data.maxVertFactor;
  330. data.restartInterval = /* # of mcus across * # down */
  331. ((pPriv->fileImage.p.width + mcuWidth - 1) / mcuWidth) *
  332. ((pPriv->fileImage.p.stripHeight + mcuHeight - 1) / mcuHeight);
  333. }
  334. streamRec.pBuffer = streamRec.pDst = streamRec.pPastEndBuffer = (ilPtr)NULL;
  335. if (error = iljpgEncodeJIF (&streamRec, &data, &offsets))
  336. return error;
  337. /* Write JIF header to end of file, at "position". */
  338. if (fseek (pFile->stream, 0, 2)) /* seek to EOF (2); != 0 is error */
  339. return IL_ERROR_FILE_IO;
  340. position = ftell (pFile->stream) - pFile->offset;
  341. nBytes = streamRec.pDst - streamRec.pBuffer;
  342. if (fwrite ((char *)streamRec.pBuffer, nBytes, 1, pFile->stream) != 1)
  343. return IL_ERROR_FILE_IO;
  344. IL_FREE (streamRec.pBuffer); /* free malloc'd buffer space */
  345. pPriv->nBytesSoFar = nBytes; /* JIF data size so far */
  346. /* Update in-memory values for tags that point to JIF data and to
  347. the Q/DC/AC tables, returned by iljpgEncodeJIF() above.
  348. Write restartInterval: if 0, no restart markers. If non-zero,
  349. then there must be only one strip in image or it cannot be encoded as
  350. as a JIF image, because restart markers need to be written between the
  351. strips and would not mesh with restart markers already in the data;
  352. so in that case write JIF pointer marker = 0 => not JIF.
  353. The resulting file will be able to be read by IL2.1 and later but not by
  354. earlier IL versions or by other software that relies on JIF.
  355. */
  356. pBytes = (ilPtr)pPriv->tagInfo.pJPEGRestart;
  357. /* type cast from int to short before FLIP */
  358. IL_WRITE_FLIP_SHORT (pPriv->bigEndian, (short)pCompData->restartInterval, pBytes)
  359. if (pCompData->restartInterval && (pPriv->nStrips != 1))
  360. JIFOffset = 0; /* not valid JIF; write 0 ptr */
  361. else JIFOffset = position;
  362. pBytes = (ilPtr)pPriv->tagInfo.pJIF;
  363. /* compatibility problem with long or unsigned long data fields */
  364. IL_WRITE_FLIP_LONG (pPriv->bigEndian, (CARD32)position, pBytes)
  365. /* Write offsets to Q tables for each component: table offset for each
  366. table, indexed by component table index, plus file to offset to JIF hdr.
  367. */
  368. pBytes = (ilPtr)pPriv->tagInfo.pJPEGQTables;
  369. for (i = 0; i < pPriv->fileImage.p.des.nSamplesPerPixel; i++) {
  370. j = offsets.QTables[data.comp[i].QTableIndex];
  371. if (!j) /* no Q table defined for that index */
  372. return IL_ERROR_COMPRESSED_DATA;
  373. j += position; /* now offset from start of "file" */
  374. /* compatibility problem with long or unsigned long data fields */
  375. IL_WRITE_FLIP_LONG (pPriv->bigEndian, (INT32)j, pBytes)
  376. }
  377. /* Same thing for DC and AC tables */
  378. pBytes = (ilPtr)pPriv->tagInfo.pJPEGDCTables;
  379. for (i = 0; i < pPriv->fileImage.p.des.nSamplesPerPixel; i++) {
  380. j = offsets.DCTables[data.comp[i].DCTableIndex];
  381. if (!j)
  382. return IL_ERROR_COMPRESSED_DATA;
  383. j += position;
  384. /* compatibility problem with long or unsigned long data fields */
  385. IL_WRITE_FLIP_LONG (pPriv->bigEndian, (INT32)j, pBytes)
  386. }
  387. pBytes = (ilPtr)pPriv->tagInfo.pJPEGACTables;
  388. for (i = 0; i < pPriv->fileImage.p.des.nSamplesPerPixel; i++) {
  389. j = offsets.ACTables[data.comp[i].ACTableIndex];
  390. if (!j)
  391. return IL_ERROR_COMPRESSED_DATA;
  392. j += position;
  393. /* compatibility problem with long or unsigned long data fields */
  394. IL_WRITE_FLIP_LONG (pPriv->bigEndian, (INT32)j, pBytes)
  395. }
  396. return IL_OK;
  397. }
  398. /* --------------------- ilWriteJPEGExecute -------------------------- */
  399. /* Execute() for ilWriteFileImage() when writing JPEG-compressed data.
  400. */
  401. static ilError ilWriteJPEGExecute (
  402. ilExecuteData *pData,
  403. long dstLine,
  404. long *pNLines
  405. )
  406. {
  407. ilWriteFilePrivPtr pPriv;
  408. ilFilePtr pFile;
  409. ilError error;
  410. long position, nBytes, i, j;
  411. ilPtr pBytes;
  412. ilByte marker[2];
  413. /* The overall approach is to write a JIF image into the file plus strips.
  414. The data written will be the JIF "header", followed by strips of JPEG
  415. data, separated by restart markers. Each strip will pointed to by
  416. the normal TIFF strip offset/byte counts. The resulting data can then
  417. be read either as a JIF image (using the JPEGInterchangeFormat/Length
  418. tags - how IL2.0 and earlier versions read it) or as a "raw" image using
  419. the other JPEG tags (how later versions read it).
  420. */
  421. pPriv = (ilWriteFilePrivPtr)pData->pPrivate;
  422. pFile = pPriv->pFile;
  423. /* Check for too many lines/strips or inconstant strips (except last). */
  424. pPriv->nLinesSoFar += *pNLines;
  425. pPriv->nStripsSoFar++;
  426. if ((pPriv->nStripsSoFar > pPriv->nStrips)
  427. || (pPriv->nLinesSoFar > pPriv->fileImage.p.height)
  428. || ((pPriv->nLinesSoFar != pPriv->fileImage.p.height) /* not last strip */
  429. && (*pNLines != pPriv->fileImage.p.stripHeight)))
  430. return IL_ERROR_MALFORMED_FILE_WRITE;
  431. /* If first strip: encode a JIF header and write it to file.
  432. Init streamRec so output is written into malloc'd memory, and encode
  433. a JIF image into that memory.
  434. */
  435. if (pPriv->nStripsSoFar <= 1) /* first strip; inc'd above */
  436. if (error = ilWriteJIFData (pPriv, pFile, pData->pSrcImage))
  437. return error;
  438. /* Write one strip of data to end of the TIFF file, after saving "position". */
  439. if (fseek (pFile->stream, 0, 2)) /* seek to EOF (2); return != 0 is error */
  440. return IL_ERROR_FILE_IO;
  441. position = ftell (pFile->stream) - pFile->offset;
  442. nBytes = pData->compressed.nBytesToRead;
  443. pBytes = pData->pSrcImage->plane[0].pPixels + pData->compressed.srcOffset;
  444. if (fwrite ((char *)pBytes, nBytes, 1, pFile->stream) != 1)
  445. return IL_ERROR_FILE_IO;
  446. pPriv->nBytesSoFar += nBytes + 2; /* # bytes in strip + 2 for marker below */
  447. /* Store byte-flipped the offset within the file (position) and size
  448. (nBytes) of the strip just written.
  449. */
  450. pBytes = (ilPtr)pPriv->pStripOffset;
  451. pPriv->pStripOffset++;
  452. /* compatibility problem with long or unsigned long data fields */
  453. IL_WRITE_FLIP_LONG (pPriv->bigEndian, (CARD32)position, pBytes)
  454. pBytes = (ilPtr)pPriv->pStripByteCount;
  455. pPriv->pStripByteCount++;
  456. /* compatibility problem with long or unsigned long data fields */
  457. IL_WRITE_FLIP_LONG (pPriv->bigEndian, (INT32)nBytes, pBytes)
  458. /* If last strip, add an EOI marker to end and store JIF length tag value;
  459. otherwise add a restart marker, with strip count modulo 8 in it.
  460. */
  461. marker[0] = 0xff;
  462. if (pPriv->nStripsSoFar >= pPriv->nStrips) {
  463. marker[1] = ILJPGM_EOI;
  464. pBytes = (ilPtr)pPriv->tagInfo.pJIFLength;
  465. /* compatibility problem with long or unsigned long data fields */
  466. IL_WRITE_FLIP_LONG (pPriv->bigEndian, (INT32)pPriv->nBytesSoFar, pBytes)
  467. }
  468. else marker[1] = ILJPGM_RST0 | ((pPriv->nStripsSoFar - 1) & 7);
  469. /* Write two byte restart or end of image (EOI) marker */
  470. if (fseek (pFile->stream, 0, 2))
  471. return IL_ERROR_FILE_IO;
  472. if (fwrite ((char *)marker, 2, 1, pFile->stream) != 1)
  473. return IL_ERROR_FILE_IO;
  474. return IL_OK;
  475. }
  476. /* --------------------- ilMergeWriteTags ----------------------------------- */
  477. /* Called by ilWriteFileImage(). Merge the user and std tag info, copy the
  478. tag data (flipped) and return into to *pInfo.
  479. */
  480. static ilError ilMergeWriteTags (
  481. ilBool bigEndian, /* byte order to be written */
  482. int nStdTags, /* # of std (IL) tags */
  483. ilFileTag *pStdTags, /* ptr to std tags */
  484. int nUserTags, /* # of user (IL) tags */
  485. ilFileTag *pUserTags, /* ptr to user tags */
  486. ilTagInfoPtr pInfo) /* returned tag info */
  487. {
  488. ilFileTag **ppTagsInit, **ppLastTag;
  489. ilFileTag **ppTag, **ppTagTemp, *pTag;
  490. ilPtr pTagData, pFileTags;
  491. long tagArraySize, tagDataSize, l;
  492. CARD32 *pTagOffsets, *pLong;
  493. int nTags, i;
  494. unsigned short tagType, *pShort;
  495. int tagNumber;
  496. /* Allocate and null an array of ptrs to tags, size = # user + std tags, + 1
  497. so that there is at least one guaranteed null tag ptr, for "end of array".
  498. */
  499. tagArraySize = nStdTags + nUserTags + 1;
  500. ppTagsInit = (ilFileTag **)IL_MALLOC (tagArraySize * sizeof (ilFileTag **));
  501. if (!ppTagsInit)
  502. return IL_ERROR_MALLOC;
  503. ppLastTag = ppTagsInit + tagArraySize - 1;
  504. for (ppTag = ppTagsInit; ppTag <= ppLastTag; ppTag++)
  505. *ppTag = (ilFileTag *)NULL;
  506. /* Fill in array with ptrs to tags, sorted in ascending numeric order (required
  507. by TIFF!), with duplicates eliminated. Do the user tags, then the std tags,
  508. so that the std tag values overwrite the user if duplicates present.
  509. Sort by insertion sort: find tag with number >= this tag's number, or end
  510. of list (null ptr). If greater, shift all values up one; then insert this tag
  511. */
  512. for (i = 0, pTag = pUserTags, nTags = nUserTags; i < 2;
  513. i++, pTag = pStdTags, nTags = nStdTags) {
  514. while (nTags-- > 0) {
  515. ppTag = ppTagsInit;
  516. while (*ppTag && ((*ppTag)->number < pTag->number))
  517. ppTag++;
  518. if (*ppTag && ((*ppTag)->number > pTag->number)) {
  519. ppTagTemp = ppLastTag;
  520. while (ppTagTemp > ppTag) {
  521. *ppTagTemp = *(ppTagTemp - 1);
  522. ppTagTemp--;
  523. }
  524. }
  525. *ppTag = pTag;
  526. pTag++;
  527. }
  528. }
  529. /* Set "nTags" to the resulting number of tags, and "tagDataSize" to the size
  530. of tag data which does not fit in the tag itself (rounded to mult of 2).
  531. */
  532. for (tagDataSize = 0, nTags = 0, ppTag = ppTagsInit; *ppTag; nTags++, ppTag++) {
  533. pTag = *ppTag;
  534. tagType = pTag->type;
  535. if ((tagType == 0) || (tagType > IL_MAX_TAG_TYPE)) {
  536. IL_FREE (ppTagsInit);
  537. return IL_ERROR_FILE_TAG_TYPE;
  538. }
  539. if (pTag->nItems > _ilTagTypeItemsThatFit [tagType])
  540. tagDataSize += (_ilTagTypeItemSizes [tagType] * pTag->nItems + 1) & ~1;
  541. }
  542. /* Alloc room on heap for: an array of offsets to tag data for each tag, or 0
  543. if tag data fits in tag; the # of tags (2 bytes); the tags themselves; the
  544. next IFD offset (4 bytes); and the tag data that does not fit in the tags.
  545. pInfo->pAlloc will point to it all:
  546. -----------------------------
  547. | offset to data for each | <- pTagOffsets (not written)
  548. | tag or 0 if data in tag | (rest is written to TIFF, and is
  549. | | "tagWriteSize" bytes in size
  550. -----------------------------
  551. | # of tags (short) | <- pTagWriteData
  552. -----------------------------
  553. | tag info for each tag | +2
  554. | (of type ilTIFFTagRec) |
  555. -----------------------------
  556. | ptr to next IFD | + # tags * IL_TAG_SIZE + 2
  557. -----------------------------
  558. | tag data external to tags | + # tags * IL_TAG_SIZE + 6
  559. -----------------------------
  560. */
  561. pInfo->tagCount = nTags;
  562. pInfo->tagWriteSize = nTags * IL_TAG_SIZE + 2 + tagDataSize + 4;
  563. pInfo->pAlloc = (ilPtr)IL_MALLOC_ZERO (nTags * sizeof(INT32) + pInfo->tagWriteSize);
  564. if (!pInfo->pAlloc) {
  565. IL_FREE (ppTagsInit);
  566. return IL_ERROR_MALLOC;
  567. }
  568. pInfo->pTagOffsets = (CARD32 *)pInfo->pAlloc;
  569. pInfo->pTagWriteData = pInfo->pAlloc + nTags * sizeof(INT32);
  570. pTagData = (ilPtr)pInfo->pTagWriteData + nTags * IL_TAG_SIZE + 6;
  571. /* Write the # of tags byte-flipped, point "pFileTags" to tag data write area.
  572. For byte/ascii data: "nItems" is length of string, including trailing null
  573. for ascii. Round up to even byte boundary (TIFF requirement).
  574. */
  575. pFileTags = (ilPtr)pInfo->pTagWriteData;
  576. IL_WRITE_FLIP_SHORT (bigEndian, (unsigned short)nTags, pFileTags)
  577. for (ppTag = ppTagsInit, pTagOffsets = pInfo->pTagOffsets; *ppTag; ppTag++) {
  578. ilPtr pWrite;
  579. pTag = *ppTag;
  580. tagType = pTag->type;
  581. IL_WRITE_FLIP_SHORT (bigEndian, pTag->number, pFileTags)
  582. IL_WRITE_FLIP_SHORT (bigEndian, tagType, pFileTags)
  583. /* compatibility problem with long or unsigned long data fields */
  584. IL_WRITE_FLIP_LONG (bigEndian, (CARD32)pTag->nItems, pFileTags)
  585. if (pTag->nItems > _ilTagTypeItemsThatFit [tagType]) {
  586. *pTagOffsets++ = pTagData - pInfo->pTagWriteData;
  587. pWrite = pTagData;
  588. pTagData += (_ilTagTypeItemSizes [tagType] * pTag->nItems + 1) & ~1UL;
  589. }
  590. else {
  591. *pTagOffsets++ = 0;
  592. pWrite = pFileTags;
  593. }
  594. pFileTags += 4; /* skip one TIFF long */
  595. /* Copy the data at "*pTag->pItems" to "pWrite", with byte-flip.
  596. pWrite points to 4 byte area in tag if items fit, else to area in pTagData.
  597. NOTE: handle strip offsets/byte counts specially: pItems is ignored.
  598. */
  599. tagNumber = pTag->number;
  600. if (tagNumber == IL_TAG_STRIP_OFFSETS)
  601. pInfo->pStripOffsets = (ilFileOffset *)pWrite;
  602. else if (tagNumber == IL_TAG_STRIP_BYTE_COUNTS)
  603. pInfo->pStripByteCounts = (INT32 *)pWrite;
  604. else if (tagNumber == IL_TAG_COLOR_MAP)
  605. pInfo->pPalette = (unsigned short *)pWrite;
  606. else if (tagNumber == IL_TAG_JPEG_INTERCHANGE_FORMAT)
  607. pInfo->pJIF = (ilFileOffset *)pWrite;
  608. else if (tagNumber == IL_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH)
  609. pInfo->pJIFLength = (long *)pWrite;
  610. else if (tagNumber == IL_TAG_JPEG_RESTART_INTERVAL)
  611. pInfo->pJPEGRestart = (unsigned short *)pWrite;
  612. else if (tagNumber == IL_TAG_JPEG_Q_TABLES)
  613. pInfo->pJPEGQTables = (long *)pWrite;
  614. else if (tagNumber == IL_TAG_JPEG_DC_TABLES)
  615. pInfo->pJPEGDCTables = (long *)pWrite;
  616. else if (tagNumber == IL_TAG_JPEG_AC_TABLES)
  617. pInfo->pJPEGACTables = (long *)pWrite;
  618. else switch (tagType) {
  619. case IL_TAG_BYTE:
  620. case IL_TAG_ASCII:
  621. bcopy ((char *)pTag->pItems, (char *)pWrite, pTag->nItems);
  622. break;
  623. case IL_TAG_SHORT:
  624. for (i = 0, pShort = (unsigned short *)pTag->pItems;
  625. i < pTag->nItems; i++, pShort++)
  626. IL_WRITE_FLIP_SHORT (bigEndian, *pShort, pWrite)
  627. break;
  628. case IL_TAG_LONG:
  629. /* compatibility problem with long or unsigned long data fields */
  630. for (i = 0, pLong = (CARD32 *)pTag->pItems;
  631. i < pTag->nItems; i++, pLong++)
  632. IL_WRITE_FLIP_LONG (bigEndian, *pLong, pWrite)
  633. break;
  634. case IL_TAG_RATIONAL:
  635. /* compatibility problem with long or unsigned long data fields */
  636. for (i = 0, pLong = (CARD32 *)pTag->pItems; i < pTag->nItems; i++) {
  637. IL_WRITE_FLIP_LONG (bigEndian, *pLong, pWrite)
  638. pLong++;
  639. IL_WRITE_FLIP_LONG (bigEndian, *pLong, pWrite)
  640. pLong++;
  641. }
  642. break;
  643. }
  644. } /* END for one tag */
  645. /* Fill in ptr to next IFD (= 0, null), free temp alloc space and exit.
  646. */
  647. /* compatibility problem with long or unsigned long data fields */
  648. IL_WRITE_FLIP_LONG (bigEndian, 0, pFileTags)
  649. IL_FREE (ppTagsInit);
  650. return IL_OK;
  651. }
  652. /* ---------------------- ilFormatPipeImage --------------------------------- */
  653. /* Reformat and compress the pipe image as necessary. On entry, pStripHeight
  654. must point to the callers requested stripHeight; on return it is the new
  655. (constant) stripHeight to use to write.
  656. On entry, pInfo/pDes/pFormat must point to the current pipe values;
  657. on return they are the new pipe values. Returns false if an error occurs.
  658. */
  659. static ilBool ilFormatPipeImage (
  660. ilPipe pipe,
  661. unsigned int compression,
  662. ilPtr pCompData,
  663. long *pStripHeight,
  664. ilPipeInfo *pInfo,
  665. ilImageDes *pDes,
  666. ilImageFormat *pFormat
  667. )
  668. {
  669. #define IL_WRITE_TIFF_STRIP_SIZE (16 * 1024) /* write 16KB strips as default */
  670. long stripHeight;
  671. long i, nLevels;
  672. ilBool mustConvert;
  673. unsigned long g3Flags, g4Flags;
  674. ilJPEGEncodeControl jpegEncode;
  675. /* If compression is "use current compression" (which makes it easier for
  676. caller to copy images), then set compression to current pipe compression,
  677. and point pCompData to compression-specific current pipe data.
  678. */
  679. if (compression == IL_WRITE_CURRENT_COMPRESSION) {
  680. compression = pDes->compression;
  681. if (compression == IL_G3) {
  682. g3Flags = pDes->compInfo.g3.flags;
  683. pCompData = (ilPtr)&g3Flags;
  684. }
  685. else if (compression == IL_G4) {
  686. g4Flags = pDes->compInfo.g4.flags;
  687. pCompData = (ilPtr)&g4Flags;
  688. }
  689. }
  690. /* Compare the levels/sample to bits/sample, and scale up if levels != 2**bits.
  691. This is because the IL separates bits and levels, but TIFF assumes # levels
  692. = 2**bits. A 16 level 8 bit gray image must be level-scaled up to 256 or
  693. else the reader will assume 256 level and display it too dark.
  694. However, bitonal must be bit/pixel, and for palette, levels is ignored.
  695. NOTE: the right thing to do is to convert the format (e.g. change 16
  696. level 8 bit gray to 4 bit gray), but ilConvert() does not handle this yet!
  697. */
  698. switch (pDes->type) {
  699. case IL_BITONAL:
  700. if (pFormat->nBitsPerSample[0] != 1) {
  701. pFormat->nBitsPerSample[0] = 1;
  702. if (!ilConvert (pipe, (ilImageDes *)NULL, pFormat, 0, NULL))
  703. return FALSE;
  704. }
  705. break;
  706. case IL_PALETTE: /* ignore nLevels for palette images */
  707. break;
  708. default: /* continuous tone: match levels to bits */
  709. for (i = 0, mustConvert = FALSE; i < pDes->nSamplesPerPixel; i++) {
  710. nLevels = 1 << pFormat->nBitsPerSample[i];
  711. if (pDes->nLevelsPerSample[i] != nLevels) {
  712. pDes->nLevelsPerSample[i] = nLevels;
  713. mustConvert = TRUE;
  714. }
  715. }
  716. if (mustConvert)
  717. if (!ilConvert (pipe, pDes, pFormat, 0, (ilPtr)NULL))
  718. return FALSE;
  719. break;
  720. }
  721. /* Convert to pixel order and reget pipe info if multi-sample and planar.
  722. However, leave planar if JPEG compression - keep YCbCr subsampled if so.
  723. */
  724. if (pDes->nSamplesPerPixel == 1)
  725. pFormat->sampleOrder = IL_SAMPLE_PIXELS;
  726. else if ((pFormat->sampleOrder != IL_SAMPLE_PIXELS) && (compression != IL_JPEG)) {
  727. pFormat->sampleOrder = IL_SAMPLE_PIXELS;
  728. if (!ilConvert (pipe, (ilImageDes *)NULL, pFormat, 0, NULL))
  729. return FALSE;
  730. ilGetPipeInfo (pipe, FALSE, pInfo, pDes, pFormat);
  731. }
  732. /* If writing uncompressed, force rowBitAlign of 8 (required by TIFF);
  733. else compress to stripHeight, using the given compression & data.
  734. If stripHeight is 0 use default TIFF write size, based on uncompressed size.
  735. */
  736. stripHeight = *pStripHeight;
  737. if (compression == IL_UNCOMPRESSED) {
  738. ilGetPipeInfo (pipe, TRUE, pInfo, pDes, pFormat); /* force decompression */
  739. if (pFormat->rowBitAlign != 8) {
  740. pFormat->rowBitAlign = 8;
  741. if (!ilConvert (pipe, (ilImageDes *)NULL, pFormat, 0, (ilPtr)NULL))
  742. return FALSE;
  743. ilGetPipeInfo (pipe, FALSE, pInfo, pDes, pFormat);
  744. }
  745. if (stripHeight <= 0) {
  746. long bytesPerRow [IL_MAX_SAMPLES];
  747. ilGetBytesPerRow (pDes, pFormat, pInfo->width, bytesPerRow);
  748. stripHeight = IL_WRITE_TIFF_STRIP_SIZE / bytesPerRow[0];
  749. }
  750. if (stripHeight <= 0)
  751. stripHeight = 1;
  752. else if (stripHeight > pInfo->height)
  753. stripHeight = pInfo->height;
  754. *pStripHeight = stripHeight; /* write with desired strip height */
  755. }
  756. else {
  757. /* If compressing JPEG, force "raw" format; get caller's Q (dflt = 0).
  758. Compress with desired strip height, unless already JPEG compressed,
  759. in which case use 0 strip height: accept current strip height.
  760. */
  761. if (compression == IL_JPEG) {
  762. jpegEncode.mustbezero = IL_JPEGM_RAW;
  763. if (pCompData)
  764. jpegEncode.Q = ((ilJPEGEncodeControl *)pCompData)->Q;
  765. else jpegEncode.Q = 0;
  766. pCompData = (ilPtr)&jpegEncode;
  767. if (pDes->compression == IL_JPEG)
  768. stripHeight = 0; /* accept current strip height */
  769. }
  770. if (!ilCompress (pipe, compression, pCompData, stripHeight, 0))
  771. return FALSE;
  772. ilGetPipeInfo (pipe, FALSE, pInfo, pDes, pFormat);
  773. *pStripHeight = pInfo->stripHeight; /* strip height determined by compression */
  774. }
  775. return TRUE;
  776. }
  777. /* ---------------------- ilWriteFileImage ---------------------------------- */
  778. /* Public function: see spec.
  779. Adds a consumer to the given pipe to write the current pipe image.
  780. */
  781. IL_EXTERN char _ilVersionString[]; /* in /ilc/ilversion.c ; written for "software" tag */
  782. ilBool ilWriteFileImage (
  783. ilPipe pipe,
  784. ilFile file,
  785. unsigned int method,
  786. ilFileImage fileImage,
  787. unsigned int compression,
  788. ilPtr pCompData,
  789. long stripHeight,
  790. long xRes,
  791. long yRes,
  792. short page,
  793. short nPages,
  794. int nUserTags,
  795. ilFileTag *pUserTags,
  796. unsigned long mustBeZero
  797. )
  798. {
  799. #define MAX_WRITE_TAGS 50 /* max # of std (non-user) tags added here */
  800. #define TW_ADD_TAG(_number, _type, _nItems, _pItems) { \
  801. pTag->number = (_number); \
  802. pTag->type = (_type); \
  803. pTag->nItems = (_nItems); \
  804. pTag->pItems = (ilPtr)(_pItems); \
  805. pTag++; \
  806. nTags++; \
  807. }
  808. long nStripsPerImage;
  809. ilFileTag tags [MAX_WRITE_TAGS];
  810. ilFileTag *pTag;
  811. int nTags, i;
  812. ilTagInfoRec tagInfo;
  813. ilFilePtr pFile;
  814. ilPipeInfo info;
  815. ilImageDes des;
  816. ilImageFormat format;
  817. ilContext context;
  818. ilError error;
  819. ilWriteFilePrivPtr pPriv;
  820. ilSrcElementData srcData;
  821. unsigned long group3Options, group4Options;
  822. ilFileImageRelation writeMethod;
  823. ilFileOffset tailPtrOffset;
  824. /* NOTE: below data types (sizes) FIXED! - tied to TIFF type (short/long) */
  825. short ditherLevels[IL_TAG_P0_DITHER_LEVELS_LENGTH];
  826. short bitsPerSample [IL_MAX_SAMPLES], TIFFcompression, photo;
  827. short nSamplesPerPixel, resolutionUnit, planarConfiguration;
  828. short pageInfo[2], predictor, fillOrder;
  829. short jpegProc, subsample[2], positioning;
  830. long width, height, newSubFileType;
  831. long xResolution[2], yResolution[2], coeff[6], refBW[12];
  832. #define VERSION_LENGTH 18 /* length includes trailing null */
  833. char versionName [VERSION_LENGTH];
  834. /* Get pipe state - must be IL_PIPE_FORMING or declare an error. */
  835. pFile = (ilFilePtr)file;
  836. context = pFile->o.p.context;
  837. if (ilGetPipeInfo (pipe, FALSE, &info, &des, &format) != IL_PIPE_FORMING) {
  838. if (!context->error)
  839. ilDeclarePipeInvalid (pipe, IL_ERROR_PIPE_STATE);
  840. return FALSE;
  841. }
  842. if (mustBeZero != 0)
  843. return ilDeclarePipeInvalid (pipe, IL_ERROR_PAR_NOT_ZERO);
  844. if (context != pipe->context)
  845. return ilDeclarePipeInvalid (pipe, IL_ERROR_CONTEXT_MISMATCH);
  846. /* Force the file image list to be formed if not already; exit on error. */
  847. ilListFileImages (file, 0);
  848. if (context->error)
  849. return ilDeclarePipeInvalid (pipe, context->error);
  850. /* Handle "method" set "writeMethod", "newSubFileType". */
  851. switch (method) {
  852. case IL_WRITE_MAIN: /* no parent, add as last image */
  853. writeMethod = mainImage;
  854. newSubFileType = 0;
  855. fileImage = (ilFileImage)NULL;
  856. break;
  857. /* Transparency mask: error if no parent, or parent already has or is a mask, or
  858. not bitonal image.
  859. */
  860. case IL_WRITE_MASK:
  861. if (!fileImage /* no parent */
  862. || (fileImage->file != file) /* not from file being written */
  863. || fileImage->pMask /* parent already has a mask */
  864. || (((ilFileImagePtr)fileImage)->imageType == maskImage)
  865. || (des.nSamplesPerPixel != 1) /* not bitonal */
  866. || (format.nBitsPerSample[0] != 1))
  867. return ilDeclarePipeInvalid (pipe, IL_ERROR_FILE_WRITE_METHOD);
  868. writeMethod = maskImage;
  869. newSubFileType = 4; /* TIFF transparency mask */
  870. break;
  871. /* Child image: must have non-mask parent fileImage with same file or error.
  872. Point to last image associated with parent: find last child (its mask if
  873. it has one), so that child images are in order written, and masks "bind"
  874. closest to image that they are a mask of.
  875. */
  876. case IL_WRITE_CHILD:
  877. writeMethod = childImage;
  878. newSubFileType = 1; /* TIFF reduced resolution image */
  879. if (!fileImage /* no parent */
  880. || (fileImage->file != file) /* not from file being written */
  881. || (((ilFileImagePtr)fileImage)->imageType == maskImage))
  882. return ilDeclarePipeInvalid (pipe, IL_ERROR_FILE_WRITE_METHOD);
  883. while (fileImage->pChild)
  884. fileImage = fileImage->pChild;
  885. if (fileImage->pMask)
  886. fileImage = fileImage->pMask; /* write after the mask image */
  887. break;
  888. default:
  889. return ilDeclarePipeInvalid (pipe, IL_ERROR_FILE_WRITE_METHOD);
  890. break;
  891. }
  892. /* Reformat and compress the pipe image as necessary. Return the stripHeight
  893. to use, and the new pipe info/des/format.
  894. */
  895. if (!ilFormatPipeImage (pipe, compression, pCompData, &stripHeight,
  896. &info, &des, &format))
  897. return FALSE;
  898. /* Form the tags to be written for this file image. */
  899. nTags = 0;
  900. pTag = tags;
  901. /* Write the 1st part of the IL version string as the "software" tag, starting 4
  902. chars into string (past '@(#)') - remember length includes trailing null!
  903. */
  904. bcopy (&_ilVersionString[4], versionName, VERSION_LENGTH - 1);
  905. versionName [VERSION_LENGTH-1] = 0;
  906. TW_ADD_TAG (IL_TAG_SOFTWARE, IL_TAG_ASCII, VERSION_LENGTH, versionName)
  907. if (page >= 0)
  908. newSubFileType |= 2; /* mark as multi-page image */
  909. TW_ADD_TAG (IL_TAG_NEW_SUBFILE_TYPE, IL_TAG_LONG, 1, &newSubFileType)
  910. width = info.width;
  911. TW_ADD_TAG (IL_TAG_IMAGE_WIDTH, IL_TAG_LONG, 1, &width)
  912. height = info.height;
  913. TW_ADD_TAG (IL_TAG_IMAGE_LENGTH, IL_TAG_LONG, 1, &height)
  914. for (i = 0; i < des.nSamplesPerPixel; i++)
  915. bitsPerSample [i] = format.nBitsPerSample [i];
  916. TW_ADD_TAG (IL_TAG_BITS_PER_SAMPLE, IL_TAG_SHORT, des.nSamplesPerPixel, bitsPerSample)
  917. /* Determine TIFF compression tag based on pipe image compression and possibly
  918. des.compInfo. Ensure pCompData null if not used.
  919. */
  920. switch (des.compression) {
  921. case IL_UNCOMPRESSED:
  922. TIFFcompression = 1;
  923. break;
  924. /* Group 3: use des.compInfo.g3.flags.
  925. If 0, write TIFF G3 (code 2), else code 3: must have EOL_MARKERS; init
  926. group3Options to be written below, and write FillOrder tag (required for
  927. Class F; not recommended for other uses in TIFF).
  928. Add group 3 options tag only if "true" (not TIFF) G3 (TIFFcompression == 3)
  929. */
  930. case IL_G3:
  931. { unsigned long userOptions;
  932. userOptions = des.compInfo.g3.flags;
  933. if (userOptions == 0)
  934. TIFFcompression = 2;
  935. else {
  936. if (userOptions & ~0x3f) /* unhandled bits set: error */
  937. return ilDeclarePipeInvalid (pipe, IL_ERROR_COMPRESSION);
  938. group3Options = 0;
  939. fillOrder = (userOptions & IL_G3M_LSB_FIRST) ? 2 : 1;
  940. TW_ADD_TAG (IL_TAG_FILL_ORDER, IL_TAG_SHORT, 1, &fillOrder)
  941. if (userOptions & IL_G3M_2D)
  942. group3Options |= 1;
  943. if (userOptions & IL_G3M_UNCOMPRESSED)
  944. group3Options |= 2;
  945. if (!(userOptions & IL_G3M_EOL_MARKERS))
  946. return ilDeclarePipeInvalid (pipe, IL_ERROR_COMPRESSION);
  947. if (!(userOptions & IL_G3M_EOL_UNALIGNED))
  948. group3Options |= 4;
  949. TW_ADD_TAG (IL_TAG_GROUP_3_OPTIONS, IL_TAG_LONG, 1, &group3Options)
  950. TIFFcompression = 3;
  951. }
  952. }
  953. break;
  954. case IL_G4:
  955. { unsigned long userOptions;
  956. userOptions = des.compInfo.g4.flags;
  957. fillOrder = (userOptions & IL_G4M_LSB_FIRST) ? 2 : 1;
  958. TW_ADD_TAG (IL_TAG_FILL_ORDER, IL_TAG_SHORT, 1, &fillOrder)
  959. }
  960. group4Options = 0;
  961. TW_ADD_TAG (IL_TAG_GROUP_4_OPTIONS, IL_TAG_LONG, 1, &group4Options)
  962. TIFFcompression = 4;
  963. break;
  964. case IL_LZW:
  965. if (pCompData)
  966. return ilDeclarePipeInvalid (pipe, IL_ERROR_COMPRESSION);
  967. TIFFcompression = 5;
  968. break;
  969. /* JPEG: write JIF with restart markers between strips.
  970. For JIF-in-TIFF: add tags for a file ptr and length of the JIF image,
  971. and the restart interval, but don't know value until JIF image received.
  972. */
  973. case IL_JPEG:
  974. jpegProc = 1; /* baseline sequential process */
  975. TW_ADD_TAG (IL_TAG_JPEG_PROC, IL_TAG_SHORT, 1, &jpegProc)
  976. TW_ADD_TAG (IL_TAG_JPEG_INTERCHANGE_FORMAT, IL_TAG_LONG, 1, NULL)
  977. TW_ADD_TAG (IL_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH, IL_TAG_LONG, 1, NULL)
  978. TW_ADD_TAG (IL_TAG_JPEG_RESTART_INTERVAL, IL_TAG_SHORT, 1, NULL)
  979. TW_ADD_TAG (IL_TAG_JPEG_Q_TABLES, IL_TAG_LONG, des.nSamplesPerPixel, NULL)
  980. TW_ADD_TAG (IL_TAG_JPEG_DC_TABLES, IL_TAG_LONG, des.nSamplesPerPixel, NULL)
  981. TW_ADD_TAG (IL_TAG_JPEG_AC_TABLES, IL_TAG_LONG, des.nSamplesPerPixel, NULL)
  982. TIFFcompression = 6;
  983. break;
  984. case IL_PACKBITS:
  985. if (pCompData)
  986. return ilDeclarePipeInvalid (pipe, IL_ERROR_COMPRESSION);
  987. TIFFcompression = 32773;
  988. break;
  989. default:
  990. return ilDeclarePipeInvalid (pipe, IL_ERROR_COMPRESSION);
  991. }
  992. TW_ADD_TAG (IL_TAG_COMPRESSION, IL_TAG_SHORT, 1, &TIFFcompression)
  993. /* Image type-specific code: set PhotometricInterpretation: to 4 (transparency
  994. mask) if a maskImage, else based on image type.
  995. */
  996. if (writeMethod == maskImage)
  997. photo = 4; /* special code for transparency mask images */
  998. else switch (des.type) {
  999. case IL_BITONAL:
  1000. case IL_GRAY: photo = (des.blackIsZero) ? 1 : 0; break;
  1001. case IL_PALETTE: photo = 3; break;
  1002. case IL_RGB: photo = 2; break;
  1003. /* YCbCr subsampling currently supported only if JPEG/JIF compressed. */
  1004. case IL_YCBCR:
  1005. /* Add the YCbCr-specific tags: coefficients as fractions of 10000 */
  1006. coeff[0] = des.typeInfo.YCbCr.lumaRed;
  1007. coeff[2] = des.typeInfo.YCbCr.lumaGreen;
  1008. coeff[4] = des.typeInfo.YCbCr.lumaBlue;
  1009. coeff[1] = coeff[3] = coeff[5] = 10000;
  1010. TW_ADD_TAG (IL_TAG_YCBCR_COEFFICIENTS, IL_TAG_RATIONAL, 3, coeff)
  1011. /* TIFF only allows subsampling as follows: Y = 1, Cr/Cb = 1,2,4 but
  1012. Cr and CB equal to each other; vert <= horiz.
  1013. */
  1014. { ilYCbCrSampleInfo *pSample = des.typeInfo.YCbCr.sample;
  1015. if ((pSample[0].subsampleHoriz != 1)
  1016. || (pSample[0].subsampleVert != 1)
  1017. || (pSample[1].subsampleHoriz != pSample[2].subsampleHoriz)
  1018. || (pSample[1].subsampleVert != pSample[2].subsampleVert)
  1019. || (pSample[1].subsampleVert > pSample[2].subsampleHoriz))
  1020. return ilDeclarePipeInvalid (pipe, IL_ERROR_YCBCR_TIFF);
  1021. subsample[0] = pSample[1].subsampleHoriz;
  1022. subsample[1] = pSample[1].subsampleVert;
  1023. TW_ADD_TAG (IL_TAG_YCBCR_SUBSAMPLING, IL_TAG_SHORT, 2, subsample)
  1024. /* Set positioning - ? is centered correct ? */
  1025. positioning = 1;
  1026. TW_ADD_TAG (IL_TAG_YCBCR_POSITIONING, IL_TAG_SHORT, 1, &positioning)
  1027. refBW[0] = pSample[0].refBlack; refBW[1] = 1;
  1028. refBW[2] = pSample[0].refWhite; refBW[3] = 1;
  1029. refBW[4] = pSample[1].refBlack; refBW[5] = 1;
  1030. refBW[6] = pSample[1].refWhite; refBW[7] = 1;
  1031. refBW[8] = pSample[2].refBlack; refBW[9] = 1;
  1032. refBW[10] = pSample[2].refWhite; refBW[11] = 1;
  1033. TW_ADD_TAG (IL_TAG_REFERENCE_BLACK_WHITE, IL_TAG_RATIONAL, 6, refBW)
  1034. }
  1035. photo = 6;
  1036. break;
  1037. default:
  1038. return ilDeclarePipeInvalid (pipe, IL_ERROR_IMAGE_TYPE);
  1039. }
  1040. TW_ADD_TAG (IL_TAG_PHOTOMETRIC_INTERPRETATION, IL_TAG_SHORT, 1, &photo)
  1041. /* Write # strips stripOffsets/ByteCounts, but supply no data - called
  1042. function handles these specially and creates blank space, filled in later.
  1043. */
  1044. nStripsPerImage = (info.height + stripHeight - 1) / stripHeight;
  1045. TW_ADD_TAG (IL_TAG_STRIP_OFFSETS, IL_TAG_LONG, nStripsPerImage, NULL)
  1046. TW_ADD_TAG (IL_TAG_STRIP_BYTE_COUNTS, IL_TAG_LONG, nStripsPerImage, NULL)
  1047. nSamplesPerPixel = des.nSamplesPerPixel;
  1048. TW_ADD_TAG (IL_TAG_SAMPLES_PER_PIXEL, IL_TAG_SHORT, 1, &nSamplesPerPixel)
  1049. TW_ADD_TAG (IL_TAG_ROWS_PER_STRIP, IL_TAG_LONG, 1, &stripHeight);
  1050. /* Write x/yRes: specified in dpi * 2; default to 300 dpi if not given. */
  1051. resolutionUnit = 2;
  1052. TW_ADD_TAG (IL_TAG_RESOLUTION_UNIT, IL_TAG_SHORT, 1, &resolutionUnit)
  1053. if (xRes <= 0) xRes = 600;
  1054. xResolution [0] = xRes;
  1055. xResolution [1] = 2;
  1056. TW_ADD_TAG (IL_TAG_X_RESOLUTION, IL_TAG_RATIONAL, 1, xResolution)
  1057. if (yRes <= 0) yRes = 600;
  1058. yResolution [0] = yRes;
  1059. yResolution [1] = 2;
  1060. TW_ADD_TAG (IL_TAG_Y_RESOLUTION, IL_TAG_RATIONAL, 1, yResolution)
  1061. /* As per TIFF spec, write planarConfiguration tag only if # samples > 1. */
  1062. if (des.nSamplesPerPixel > 1) {
  1063. planarConfiguration = (format.sampleOrder == IL_SAMPLE_PIXELS) ? 1 : 2;
  1064. TW_ADD_TAG (IL_TAG_PLANAR_CONFIGURATION, IL_TAG_SHORT, 1, &planarConfiguration)
  1065. }
  1066. if (page >= 0) { /* else no page tag written */
  1067. pageInfo[0] = page;
  1068. pageInfo[1] = nPages;
  1069. TW_ADD_TAG (IL_TAG_PAGE_NUMBER, IL_TAG_SHORT, 2, pageInfo)
  1070. }
  1071. if (des.compression == IL_LZW) {
  1072. predictor = 1;
  1073. TW_ADD_TAG (IL_TAG_PREDICTOR, IL_TAG_SHORT, 1, &predictor)
  1074. }
  1075. /* If a palette entry, add a colorMap tag; # colors = 2 ** # bits.
  1076. If dithered flags bit set, write private tag to mark it as such.
  1077. */
  1078. if (des.type == IL_PALETTE) {
  1079. tagInfo.nPaletteColors = 1 << format.nBitsPerSample [0];
  1080. TW_ADD_TAG (IL_TAG_COLOR_MAP, IL_TAG_SHORT, 3 * tagInfo.nPaletteColors, NULL)
  1081. if (des.flags & IL_DITHERED_PALETTE) {
  1082. ditherLevels[0] = IL_TAG_P0_FLAG_DITHER_LEVELS;
  1083. ditherLevels[1] = des.typeInfo.palette.levels[0];
  1084. ditherLevels[2] = des.typeInfo.palette.levels[1];
  1085. ditherLevels[3] = des.typeInfo.palette.levels[2];
  1086. TW_ADD_TAG (IL_TAG_PRIVATE_0, IL_TAG_SHORT, IL_TAG_P0_DITHER_LEVELS_LENGTH,
  1087. ditherLevels)
  1088. }
  1089. }
  1090. else tagInfo.pPalette = (unsigned short *)NULL;
  1091. /* Merge the user tags with the tags formed above, convert the data to
  1092. the proper byte order and return the allocated info to "tagInfo" or error.
  1093. */
  1094. if (error = ilMergeWriteTags (pFile->bigEndian, nTags, tags, nUserTags, pUserTags,
  1095. &tagInfo))
  1096. return ilDeclarePipeInvalid (pipe, error);
  1097. /* Add consumer pipe element, forcing constant "stripHeight" - ignored if pipe
  1098. image is compressed - stripHeight was forced above by call to ilCompress().
  1099. Use separate function for when writing JPEG.
  1100. */
  1101. srcData.consumerImage = (ilObject)NULL;
  1102. srcData.stripHeight = stripHeight;
  1103. srcData.constantStrip = TRUE;
  1104. srcData.minBufferHeight = 0;
  1105. pPriv = (ilWriteFilePrivPtr)ilAddPipeElement (pipe, IL_CONSUMER,
  1106. sizeof(ilWriteFilePrivRec), 0, &srcData, (ilDstElementData *)NULL,
  1107. ilWriteFileInit, ilWriteFileCleanup, ilWriteFileDestroy,
  1108. (des.compression == IL_JPEG) ? ilWriteJPEGExecute : ilWriteFileExecute, 0);
  1109. if (!pPriv)
  1110. return FALSE;
  1111. /* Fill in private (*pPriv), including template for file image to be added. */
  1112. pPriv->pFile = pFile;
  1113. pPriv->tagInfo = tagInfo;
  1114. pPriv->bigEndian = pFile->bigEndian;
  1115. pPriv->compression = des.compression;
  1116. pPriv->nStrips = nStripsPerImage;
  1117. /* Point pPriv->tailPtrOffset to location in file to point to this image: "ptr
  1118. to next" of last image in file (if main image) else ptr to next of parent.
  1119. */
  1120. if (fileImage) /* have parent: child or mask image */
  1121. pPriv->tailPtrOffset = ((ilFileImagePtr)fileImage)->tagOffset +
  1122. ((ilFileImagePtr)fileImage)->tagCount * IL_TAG_SIZE;
  1123. else pPriv->tailPtrOffset = pFile->IFDTailPtrOffset;
  1124. pPriv->fileImage.p.file = (ilFile)pFile;
  1125. pPriv->fileImage.p.pNext = pPriv->fileImage.p.pPrev =
  1126. pPriv->fileImage.p.pChild = pPriv->fileImage.p.pMask = (ilFileImage)NULL;
  1127. pPriv->fileImage.p.width = info.width;
  1128. pPriv->fileImage.p.height = info.height;
  1129. pPriv->fileImage.p.xRes = xRes;
  1130. pPriv->fileImage.p.yRes = yRes;
  1131. pPriv->fileImage.p.page = page;
  1132. pPriv->fileImage.p.nPages = nPages;
  1133. pPriv->fileImage.p.des = des;
  1134. pPriv->fileImage.p.format = format;
  1135. pPriv->fileImage.p.stripHeight = stripHeight;
  1136. pPriv->fileImage.context = pFile->o.p.context;
  1137. pPriv->fileImage.tagCount = tagInfo.tagCount;
  1138. pipe->context->error = IL_OK;
  1139. return TRUE;
  1140. }
  1141. /* ---------------------- ilInitFile ---------------------------------- */
  1142. /* Public function: see spec.
  1143. Writes a TIFF file header at position "offset" of file "stream" using
  1144. Motorola order (MM) if "MSBIsFirst", else Intel order (II).
  1145. */
  1146. ilBool ilInitFile (
  1147. ilContext context,
  1148. FILE *stream,
  1149. long offset,
  1150. ilBool MSBIsFirst,
  1151. unsigned long mustBeZero
  1152. )
  1153. {
  1154. ilBool bigEndian;
  1155. ilFilePtr pFile;
  1156. ilByte *pHeader;
  1157. static ilByte MSBFirstHeader[] = { 'M', 'M', 0, 42, 0, 0, 0, 0 };
  1158. static ilByte LSBFirstHeader[] = { 'I', 'I', 42, 0, 0, 0, 0, 0 };
  1159. if (fseek (stream, offset, 0)) { /* nonzero means error for fseek */
  1160. context->error = IL_ERROR_FILE_IO;
  1161. return FALSE;
  1162. }
  1163. pHeader = (MSBIsFirst) ? MSBFirstHeader : LSBFirstHeader;
  1164. if (fwrite ((char *)pHeader, sizeof (MSBFirstHeader), 1, stream) != 1) {
  1165. context->error = IL_ERROR_FILE_IO;
  1166. return FALSE;
  1167. }
  1168. fflush (stream); /* flush header out to file */
  1169. context->error = IL_OK;
  1170. return TRUE;
  1171. }