tif_packbits.c
上传用户:looem2003
上传日期:2014-07-20
资源大小:13733k
文件大小:8k
源码类别:

打印编程

开发平台:

Visual C++

  1. /* $Id: tif_packbits.c,v 1.13 2006/02/07 11:03:29 dron 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, tsample_t s)
  35. {
  36. (void) s;
  37.         if (!(tif->tif_data = (tidata_t)_TIFFmalloc(sizeof(tsize_t))))
  38. return (0);
  39. /*
  40.  * Calculate the scanline/tile-width size in bytes.
  41.  */
  42. if (isTiled(tif))
  43. *(tsize_t*)tif->tif_data = TIFFTileRowSize(tif);
  44. else
  45. *(tsize_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.  * NB: tidata is the type representing *(tidata_t);
  57.  *     if tidata_t is made signed then this type must
  58.  *     be adjusted accordingly.
  59.  */
  60. typedef unsigned char tidata;
  61. /*
  62.  * Encode a run of pixels.
  63.  */
  64. static int
  65. PackBitsEncode(TIFF* tif, tidata_t buf, tsize_t cc, tsample_t s)
  66. {
  67. unsigned char* bp = (unsigned char*) buf;
  68. tidata_t op, ep, lastliteral;
  69. long n, slop;
  70. int b;
  71. enum { BASE, LITERAL, RUN, LITERAL_RUN } state;
  72. (void) s;
  73. op = tif->tif_rawcp;
  74. ep = tif->tif_rawdata + tif->tif_rawdatasize;
  75. state = BASE;
  76. lastliteral = 0;
  77. while (cc > 0) {
  78. /*
  79.  * Find the longest string of identical bytes.
  80.  */
  81. b = *bp++, cc--, n = 1;
  82. for (; cc > 0 && b == *bp; cc--, bp++)
  83. n++;
  84. again:
  85. if (op + 2 >= ep) { /* insure space for new data */
  86. /*
  87.  * Be careful about writing the last
  88.  * literal.  Must write up to that point
  89.  * and then copy the remainder to the
  90.  * front of the buffer.
  91.  */
  92. if (state == LITERAL || state == LITERAL_RUN) {
  93. slop = op - lastliteral;
  94. tif->tif_rawcc += lastliteral - tif->tif_rawcp;
  95. if (!TIFFFlushData1(tif))
  96. return (-1);
  97. op = tif->tif_rawcp;
  98. while (slop-- > 0)
  99. *op++ = *lastliteral++;
  100. lastliteral = tif->tif_rawcp;
  101. } else {
  102. tif->tif_rawcc += op - tif->tif_rawcp;
  103. if (!TIFFFlushData1(tif))
  104. return (-1);
  105. op = tif->tif_rawcp;
  106. }
  107. }
  108. switch (state) {
  109. case BASE: /* initial state, set run/literal */
  110. if (n > 1) {
  111. state = RUN;
  112. if (n > 128) {
  113. *op++ = (tidata) -127;
  114. *op++ = (tidataval_t) b;
  115. n -= 128;
  116. goto again;
  117. }
  118. *op++ = (tidataval_t)(-(n-1));
  119. *op++ = (tidataval_t) b;
  120. } else {
  121. lastliteral = op;
  122. *op++ = 0;
  123. *op++ = (tidataval_t) b;
  124. state = LITERAL;
  125. }
  126. break;
  127. case LITERAL: /* last object was literal string */
  128. if (n > 1) {
  129. state = LITERAL_RUN;
  130. if (n > 128) {
  131. *op++ = (tidata) -127;
  132. *op++ = (tidataval_t) b;
  133. n -= 128;
  134. goto again;
  135. }
  136. *op++ = (tidataval_t)(-(n-1)); /* encode run */
  137. *op++ = (tidataval_t) b;
  138. } else { /* extend literal */
  139. if (++(*lastliteral) == 127)
  140. state = BASE;
  141. *op++ = (tidataval_t) b;
  142. }
  143. break;
  144. case RUN: /* last object was run */
  145. if (n > 1) {
  146. if (n > 128) {
  147. *op++ = (tidata) -127;
  148. *op++ = (tidataval_t) b;
  149. n -= 128;
  150. goto again;
  151. }
  152. *op++ = (tidataval_t)(-(n-1));
  153. *op++ = (tidataval_t) b;
  154. } else {
  155. lastliteral = op;
  156. *op++ = 0;
  157. *op++ = (tidataval_t) b;
  158. state = LITERAL;
  159. }
  160. break;
  161. case LITERAL_RUN: /* literal followed by a run */
  162. /*
  163.  * Check to see if previous run should
  164.  * be converted to a literal, in which
  165.  * case we convert literal-run-literal
  166.  * to a single literal.
  167.  */
  168. if (n == 1 && op[-2] == (tidata) -1 &&
  169.     *lastliteral < 126) {
  170. state = (((*lastliteral) += 2) == 127 ?
  171.     BASE : LITERAL);
  172. op[-2] = op[-1]; /* replicate */
  173. } else
  174. state = RUN;
  175. goto again;
  176. }
  177. }
  178. tif->tif_rawcc += op - tif->tif_rawcp;
  179. tif->tif_rawcp = op;
  180. return (1);
  181. }
  182. /*
  183.  * Encode a rectangular chunk of pixels.  We break it up
  184.  * into row-sized pieces to insure that encoded runs do
  185.  * not span rows.  Otherwise, there can be problems with
  186.  * the decoder if data is read, for example, by scanlines
  187.  * when it was encoded by strips.
  188.  */
  189. static int
  190. PackBitsEncodeChunk(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
  191. {
  192. tsize_t rowsize = *(tsize_t*)tif->tif_data;
  193. while ((long)cc > 0) {
  194. int chunk = rowsize;
  195. if( cc < chunk )
  196.     chunk = cc;
  197. if (PackBitsEncode(tif, bp, chunk, s) < 0)
  198.     return (-1);
  199. bp += chunk;
  200. cc -= chunk;
  201. }
  202. return (1);
  203. }
  204. static int
  205. PackBitsDecode(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s)
  206. {
  207. char *bp;
  208. tsize_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 && (long)occ > 0) {
  215. n = (long) *bp++, 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 < n )
  227.                         {
  228. TIFFWarningExt(tif->tif_clientdata, tif->tif_name,
  229.                                         "PackBitsDecode: discarding %d bytes "
  230.                                         "to avoid buffer overrun",
  231.                                         n - occ);
  232.                             n = occ;
  233.                         }
  234. occ -= n;
  235. b = *bp++, cc--;
  236. while (n-- > 0)
  237. *op++ = (tidataval_t) b;
  238. } else { /* copy next n+1 bytes literally */
  239. if (occ < n + 1)
  240.                         {
  241.                             TIFFWarningExt(tif->tif_clientdata, tif->tif_name,
  242.                                         "PackBitsDecode: discarding %d bytes "
  243.                                         "to avoid buffer overrun",
  244.                                         n - occ + 1);
  245.                             n = occ - 1;
  246.                         }
  247.                         _TIFFmemcpy(op, bp, ++n);
  248. op += n; occ -= n;
  249. bp += n; cc -= n;
  250. }
  251. }
  252. tif->tif_rawcp = (tidata_t) bp;
  253. tif->tif_rawcc = cc;
  254. if (occ > 0) {
  255. TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
  256.     "PackBitsDecode: Not enough data for scanline %ld",
  257.     (long) tif->tif_row);
  258. return (0);
  259. }
  260. return (1);
  261. }
  262. int
  263. TIFFInitPackBits(TIFF* tif, int scheme)
  264. {
  265. (void) scheme;
  266. tif->tif_decoderow = PackBitsDecode;
  267. tif->tif_decodestrip = PackBitsDecode;
  268. tif->tif_decodetile = PackBitsDecode;
  269. tif->tif_preencode = PackBitsPreEncode;
  270.         tif->tif_postencode = PackBitsPostEncode;
  271. tif->tif_encoderow = PackBitsEncode;
  272. tif->tif_encodestrip = PackBitsEncodeChunk;
  273. tif->tif_encodetile = PackBitsEncodeChunk;
  274. return (1);
  275. }
  276. #endif /* PACKBITS_SUPPORT */
  277. /* vim: set ts=8 sts=8 sw=8 noet: */