2
0

tif_packbits.c 7.4 KB

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