tif_packbits.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. /*
  2. * Copyright (c) 1988-1997 Sam Leffler
  3. * Copyright (c) 1991-1997 Silicon Graphics, Inc.
  4. *
  5. * Permission to use, copy, modify, distribute, and sell this software and
  6. * its documentation for any purpose is hereby granted without fee, provided
  7. * that (i) the above copyright notices and this permission notice appear in
  8. * all copies of the software and related documentation, and (ii) the names of
  9. * Sam Leffler and Silicon Graphics may not be used in any advertising or
  10. * publicity relating to the software without the specific, prior written
  11. * permission of Sam Leffler and Silicon Graphics.
  12. *
  13. * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
  14. * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
  15. * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
  16. *
  17. * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
  18. * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
  19. * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  20. * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
  21. * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  22. * OF THIS SOFTWARE.
  23. */
  24. #include "tiffiop.h"
  25. #ifdef PACKBITS_SUPPORT
  26. /*
  27. * TIFF Library.
  28. *
  29. * PackBits Compression Algorithm Support
  30. */
  31. #include <stdio.h>
  32. static int
  33. PackBitsPreEncode(TIFF* tif, uint16_t s)
  34. {
  35. (void) s;
  36. tif->tif_data = (uint8_t*)_TIFFmalloc(sizeof(tmsize_t));
  37. if (tif->tif_data == NULL)
  38. return (0);
  39. /*
  40. * Calculate the scanline/tile-width size in bytes.
  41. */
  42. if (isTiled(tif))
  43. *(tmsize_t*)tif->tif_data = TIFFTileRowSize(tif);
  44. else
  45. *(tmsize_t*)tif->tif_data = TIFFScanlineSize(tif);
  46. return (1);
  47. }
  48. static int
  49. PackBitsPostEncode(TIFF* tif)
  50. {
  51. if (tif->tif_data)
  52. _TIFFfree(tif->tif_data);
  53. return (1);
  54. }
  55. /*
  56. * Encode a run of pixels.
  57. */
  58. static int
  59. PackBitsEncode(TIFF* tif, uint8_t* buf, tmsize_t cc, uint16_t s)
  60. {
  61. unsigned char* bp = (unsigned char*) buf;
  62. uint8_t* op;
  63. uint8_t* ep;
  64. uint8_t* lastliteral;
  65. long n, slop;
  66. int b;
  67. enum { BASE, LITERAL, RUN, LITERAL_RUN } state;
  68. (void) s;
  69. op = tif->tif_rawcp;
  70. ep = tif->tif_rawdata + tif->tif_rawdatasize;
  71. state = BASE;
  72. lastliteral = 0;
  73. while (cc > 0) {
  74. /*
  75. * Find the longest string of identical bytes.
  76. */
  77. b = *bp++;
  78. cc--;
  79. n = 1;
  80. for (; cc > 0 && b == *bp; cc--, bp++)
  81. n++;
  82. again:
  83. if (op + 2 >= ep) { /* insure space for new data */
  84. /*
  85. * Be careful about writing the last
  86. * literal. Must write up to that point
  87. * and then copy the remainder to the
  88. * front of the buffer.
  89. */
  90. if (state == LITERAL || state == LITERAL_RUN) {
  91. slop = (long)(op - lastliteral);
  92. tif->tif_rawcc += (tmsize_t)(lastliteral - tif->tif_rawcp);
  93. if (!TIFFFlushData1(tif))
  94. return (0);
  95. op = tif->tif_rawcp;
  96. while (slop-- > 0)
  97. *op++ = *lastliteral++;
  98. lastliteral = tif->tif_rawcp;
  99. } else {
  100. tif->tif_rawcc += (tmsize_t)(op - tif->tif_rawcp);
  101. if (!TIFFFlushData1(tif))
  102. return (0);
  103. op = tif->tif_rawcp;
  104. }
  105. }
  106. switch (state) {
  107. case BASE: /* initial state, set run/literal */
  108. if (n > 1) {
  109. state = RUN;
  110. if (n > 128) {
  111. *op++ = (uint8_t) -127;
  112. *op++ = (uint8_t) b;
  113. n -= 128;
  114. goto again;
  115. }
  116. *op++ = (uint8_t)(-(n - 1));
  117. *op++ = (uint8_t) b;
  118. } else {
  119. lastliteral = op;
  120. *op++ = 0;
  121. *op++ = (uint8_t) b;
  122. state = LITERAL;
  123. }
  124. break;
  125. case LITERAL: /* last object was literal string */
  126. if (n > 1) {
  127. state = LITERAL_RUN;
  128. if (n > 128) {
  129. *op++ = (uint8_t) -127;
  130. *op++ = (uint8_t) b;
  131. n -= 128;
  132. goto again;
  133. }
  134. *op++ = (uint8_t)(-(n - 1)); /* encode run */
  135. *op++ = (uint8_t) b;
  136. } else { /* extend literal */
  137. if (++(*lastliteral) == 127)
  138. state = BASE;
  139. *op++ = (uint8_t) b;
  140. }
  141. break;
  142. case RUN: /* last object was run */
  143. if (n > 1) {
  144. if (n > 128) {
  145. *op++ = (uint8_t) -127;
  146. *op++ = (uint8_t) b;
  147. n -= 128;
  148. goto again;
  149. }
  150. *op++ = (uint8_t)(-(n - 1));
  151. *op++ = (uint8_t) b;
  152. } else {
  153. lastliteral = op;
  154. *op++ = 0;
  155. *op++ = (uint8_t) b;
  156. state = LITERAL;
  157. }
  158. break;
  159. case LITERAL_RUN: /* literal followed by a run */
  160. /*
  161. * Check to see if previous run should
  162. * be converted to a literal, in which
  163. * case we convert literal-run-literal
  164. * to a single literal.
  165. */
  166. if (n == 1 && op[-2] == (uint8_t) -1 &&
  167. *lastliteral < 126) {
  168. state = (((*lastliteral) += 2) == 127 ?
  169. BASE : LITERAL);
  170. op[-2] = op[-1]; /* replicate */
  171. } else
  172. state = RUN;
  173. goto again;
  174. }
  175. }
  176. tif->tif_rawcc += (tmsize_t)(op - tif->tif_rawcp);
  177. tif->tif_rawcp = op;
  178. return (1);
  179. }
  180. /*
  181. * Encode a rectangular chunk of pixels. We break it up
  182. * into row-sized pieces to insure that encoded runs do
  183. * not span rows. Otherwise, there can be problems with
  184. * the decoder if data is read, for example, by scanlines
  185. * when it was encoded by strips.
  186. */
  187. static int
  188. PackBitsEncodeChunk(TIFF* tif, uint8_t* bp, tmsize_t cc, uint16_t s)
  189. {
  190. tmsize_t rowsize = *(tmsize_t*)tif->tif_data;
  191. while (cc > 0) {
  192. tmsize_t chunk = rowsize;
  193. if( cc < chunk )
  194. chunk = cc;
  195. if (PackBitsEncode(tif, bp, chunk, s) < 0)
  196. return (-1);
  197. bp += chunk;
  198. cc -= chunk;
  199. }
  200. return (1);
  201. }
  202. static int
  203. PackBitsDecode(TIFF* tif, uint8_t* op, tmsize_t occ, uint16_t s)
  204. {
  205. static const char module[] = "PackBitsDecode";
  206. char *bp;
  207. tmsize_t cc;
  208. long n;
  209. int b;
  210. (void) s;
  211. bp = (char*) tif->tif_rawcp;
  212. cc = tif->tif_rawcc;
  213. while (cc > 0 && occ > 0) {
  214. n = (long) *bp++;
  215. cc--;
  216. /*
  217. * Watch out for compilers that
  218. * don't sign extend chars...
  219. */
  220. if (n >= 128)
  221. n -= 256;
  222. if (n < 0) { /* replicate next byte -n+1 times */
  223. if (n == -128) /* nop */
  224. continue;
  225. n = -n + 1;
  226. if( occ < (tmsize_t)n )
  227. {
  228. TIFFWarningExt(tif->tif_clientdata, module,
  229. "Discarding %"TIFF_SSIZE_FORMAT" bytes to avoid buffer overrun",
  230. (tmsize_t)n - occ);
  231. n = (long)occ;
  232. }
  233. if( cc == 0 )
  234. {
  235. TIFFWarningExt(tif->tif_clientdata, module,
  236. "Terminating PackBitsDecode due to lack of data.");
  237. break;
  238. }
  239. occ -= n;
  240. b = *bp++;
  241. cc--;
  242. while (n-- > 0)
  243. *op++ = (uint8_t) b;
  244. } else { /* copy next n+1 bytes literally */
  245. if (occ < (tmsize_t)(n + 1))
  246. {
  247. TIFFWarningExt(tif->tif_clientdata, module,
  248. "Discarding %"TIFF_SSIZE_FORMAT" bytes to avoid buffer overrun",
  249. (tmsize_t)n - occ + 1);
  250. n = (long)occ - 1;
  251. }
  252. if (cc < (tmsize_t) (n+1))
  253. {
  254. TIFFWarningExt(tif->tif_clientdata, module,
  255. "Terminating PackBitsDecode due to lack of data.");
  256. break;
  257. }
  258. _TIFFmemcpy(op, bp, ++n);
  259. op += n; occ -= n;
  260. bp += n; cc -= n;
  261. }
  262. }
  263. tif->tif_rawcp = (uint8_t*) bp;
  264. tif->tif_rawcc = cc;
  265. if (occ > 0) {
  266. TIFFErrorExt(tif->tif_clientdata, module,
  267. "Not enough data for scanline %"PRIu32,
  268. tif->tif_row);
  269. return (0);
  270. }
  271. return (1);
  272. }
  273. int
  274. TIFFInitPackBits(TIFF* tif, int scheme)
  275. {
  276. (void) scheme;
  277. tif->tif_decoderow = PackBitsDecode;
  278. tif->tif_decodestrip = PackBitsDecode;
  279. tif->tif_decodetile = PackBitsDecode;
  280. tif->tif_preencode = PackBitsPreEncode;
  281. tif->tif_postencode = PackBitsPostEncode;
  282. tif->tif_encoderow = PackBitsEncode;
  283. tif->tif_encodestrip = PackBitsEncodeChunk;
  284. tif->tif_encodetile = PackBitsEncodeChunk;
  285. return (1);
  286. }
  287. #endif /* PACKBITS_SUPPORT */
  288. /* vim: set ts=8 sts=8 sw=8 noet: */
  289. /*
  290. * Local Variables:
  291. * mode: c
  292. * c-basic-offset: 8
  293. * fill-column: 78
  294. * End:
  295. */