ilcomppackbits.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  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: ilcomppackbits.c /main/3 1995/10/23 15:42:43 rswiston $ */
  24. /**---------------------------------------------------------------------
  25. ***
  26. *** (c)Copyright 1991 Hewlett-Packard Co.
  27. ***
  28. *** RESTRICTED RIGHTS LEGEND
  29. *** Use, duplication, or disclosure by the U.S. Government is subject to
  30. *** restrictions as set forth in sub-paragraph (c)(1)(ii) of the Rights in
  31. *** Technical Data and Computer Software clause in DFARS 252.227-7013.
  32. *** Hewlett-Packard Company
  33. *** 3000 Hanover Street
  34. *** Palo Alto, CA 94304 U.S.A.
  35. *** Rights for non-DOD U.S. Government Departments and Agencies are as set
  36. *** forth in FAR 52.227-19(c)(1,2).
  37. ***
  38. ***-------------------------------------------------------------------*/
  39. #include "ilint.h"
  40. #include "ilpipelem.h"
  41. #include "ilcompress.h"
  42. #include "ilerrors.h"
  43. /* ========================================================================
  44. Compression private data structure definition
  45. ======================================================================== */
  46. typedef struct {
  47. int stripHeight;
  48. int height;
  49. int width;
  50. int widthbytes;
  51. int beingRecalled;
  52. ilBool firstStrip;
  53. } ilCompPBPrivRec, *ilCompPBPrivPtr;
  54. /* ========================================================================
  55. -------------------- ilComppackbitsInit -------------------
  56. ======================================================================== */
  57. static ilError ilComppackbitsInit(
  58. ilCompPBPrivPtr pPrivate,
  59. ilImageInfo *pSrcImage,
  60. ilImageInfo *pDstImage
  61. )
  62. {
  63. pPrivate->firstStrip = TRUE;
  64. return IL_OK;
  65. }
  66. /* End ilComppackbitsInit() */
  67. /* ========================================================================
  68. -------------------- ilComppackbitsExecute() -------------------
  69. ======================================================================== */
  70. static ilError ilComppackbitsExecute(
  71. ilExecuteData *pData,
  72. unsigned long dstLine,
  73. unsigned long *pNLines
  74. )
  75. {
  76. #define PB_MAX_BUFFER_WRITE 140 /* max bytes written after check for room in compressed buffer */
  77. unsigned long nBytes = 0; /* Number of source image bytes to unpack for current strip */
  78. unsigned long nLines; /* Number of lines per source image strip */
  79. ilPtr pSrcByte; /* Pointer to source image data first byte */
  80. ilPtr pSrcLine; /* Pointer to source image data first byte of line */
  81. ilPtr pDstByte; /* Pointer to destination image data */
  82. ilPtr pDstBufferEnd; /* Ptr to byte "PB_MAX_BUFFER_WRITE" from end of compressed buffer */
  83. unsigned long srcNBytes; /* Number of source image bytes per row */
  84. ilCompPBPrivPtr pPriv; /* Pointer to private image data */
  85. ilImagePlaneInfo *pSrcPlane, *pDstPlane;
  86. long offset; /* difference between current dst image address pointer and the
  87. start address of the dst image buffer */
  88. long length; /* number of bytes written to dst image */
  89. int count; /* run count value */
  90. int start, j; /* indices into source data */
  91. int nBytesM1; /* bytes per row of data minus one */
  92. /* ========================================================================
  93. Set up for execution of compression algorithm code
  94. ======================================================================== */
  95. pPriv = (ilCompPBPrivPtr) pData->pPrivate;
  96. nLines = *pNLines;
  97. if (nLines <= 0) return IL_OK;
  98. pSrcPlane = &pData->pSrcImage->plane[0];
  99. srcNBytes = pSrcPlane->nBytesPerRow;
  100. pSrcLine = pSrcPlane->pPixels + pData->srcLine * srcNBytes;
  101. /* allocate destination buffer space */
  102. if (pPriv->firstStrip) {
  103. if (!_ilReallocCompressedBuffer (pData->pDstImage, 0, PB_MAX_BUFFER_WRITE))
  104. return IL_ERROR_MALLOC;
  105. pPriv->firstStrip = FALSE;
  106. }
  107. pDstPlane = &pData->pDstImage->plane[0];
  108. pDstBufferEnd = pDstPlane->pPixels + (pDstPlane->bufferSize - PB_MAX_BUFFER_WRITE);
  109. /* exit. Pointer pPixels must not be NULL */
  110. if (!pDstPlane->pPixels) return IL_ERROR_NULL_COMPRESSED_IMAGE;
  111. pDstByte = pDstPlane->pPixels + *pData->compressed.pDstOffset;
  112. /* write out image, one strip at a time */
  113. nBytesM1 = pPriv->widthbytes - 1;
  114. while ( nLines-- > 0 ) {
  115. pSrcByte = pSrcLine;
  116. start = 0;
  117. j = 0;
  118. while (j <= nBytesM1) {
  119. start = j;
  120. if ( pSrcByte[j] == pSrcByte[j+1] ) { /* repeat run */
  121. while ((pSrcByte[j] == pSrcByte[j+1]) && (j < nBytesM1) && ((j-start) < 127) ) j++;
  122. /* output buffer size handling code */
  123. if (pDstByte >= pDstBufferEnd) {
  124. offset = pDstByte - pDstPlane->pPixels;
  125. if (!_ilReallocCompressedBuffer (pData->pDstImage, 0, offset + PB_MAX_BUFFER_WRITE))
  126. return IL_ERROR_MALLOC;
  127. pDstByte = pDstPlane->pPixels + offset;
  128. pDstBufferEnd = pDstPlane->pPixels + (pDstPlane->bufferSize - PB_MAX_BUFFER_WRITE);
  129. }
  130. j++;
  131. count = 1 - (j-start);
  132. *pDstByte++ = count;
  133. *pDstByte++ = pSrcByte[j-1];
  134. }
  135. else { /* literal run */
  136. while ( (pSrcByte[j] != pSrcByte[j+1]) && (j <= nBytesM1) && ((j-start) < 128) ) j++;
  137. /* output buffer size handling code */
  138. if (pDstByte >= pDstBufferEnd) {
  139. offset = pDstByte - pDstPlane->pPixels;
  140. if (!_ilReallocCompressedBuffer (pData->pDstImage, 0, offset + PB_MAX_BUFFER_WRITE))
  141. return IL_ERROR_MALLOC;
  142. pDstByte = pDstPlane->pPixels + offset;
  143. pDstBufferEnd = pDstPlane->pPixels + (pDstPlane->bufferSize - PB_MAX_BUFFER_WRITE);
  144. }
  145. count = j-start - 1;
  146. *pDstByte++ = count;
  147. do {
  148. *pDstByte++ = pSrcByte[start++];
  149. } while (--count >= 0);
  150. }
  151. } /* end row loop */
  152. pSrcLine += srcNBytes;
  153. } /* end while */
  154. /* Return the number of bytes written, = dst ptr - beginning of dst buffer */
  155. *pData->compressed.pNBytesWritten = pDstByte - (pDstPlane->pPixels + *pData->compressed.pDstOffset);
  156. return IL_OK;
  157. }
  158. /* ========================================================================
  159. -------------------- ilCompressPackbits --------------------
  160. ======================================================================== */
  161. IL_PRIVATE ilBool _ilCompressPackbits (
  162. ilPipe pipe,
  163. ilPipeInfo *pinfo,
  164. ilImageDes *pimdes,
  165. ilImageFormat *pimformat,
  166. ilSrcElementData *pSrcData
  167. )
  168. {
  169. ilDstElementData dstdata;
  170. ilCompPBPrivPtr pPriv;
  171. ilImageDes des;
  172. ilBool bitPerPixel;
  173. /* Validate that image is bit/pixel, or if not bit, convert to byte if fits. */
  174. if (pimdes->nSamplesPerPixel != 1)
  175. return ilDeclarePipeInvalid (pipe, IL_ERROR_IMAGE_TYPE);
  176. if (pimformat->nBitsPerSample[0] == 1)
  177. bitPerPixel = TRUE;
  178. else {
  179. bitPerPixel = FALSE;
  180. if (pimformat->nBitsPerSample[0] != 8)
  181. if (!ilConvert (pipe, (ilImageDes *)NULL, IL_FORMAT_BYTE, 0, (ilPtr)NULL))
  182. return FALSE;
  183. }
  184. /* dstdata describes strips being output to next pipe element */
  185. dstdata.producerObject = (ilObject) NULL;
  186. des = *pimdes;
  187. des.compression = IL_PACKBITS;
  188. dstdata.pDes = &des;
  189. dstdata.pFormat = (bitPerPixel) ? IL_FORMAT_BIT : IL_FORMAT_BYTE;
  190. dstdata.width = pinfo->width;
  191. dstdata.height = pinfo->height;
  192. dstdata.stripHeight = pSrcData->stripHeight;
  193. dstdata.constantStrip = pSrcData->constantStrip;
  194. dstdata.pPalette = pinfo->pPalette;
  195. dstdata.pCompData = (ilPtr)NULL;
  196. /* ========================================================================
  197. Add the filter to the pipeline
  198. ======================================================================== */
  199. pPriv = (ilCompPBPrivPtr) ilAddPipeElement(pipe, IL_FILTER, sizeof(ilCompPBPrivRec), 0, pSrcData, &dstdata,
  200. ilComppackbitsInit, IL_NPF, IL_NPF, ilComppackbitsExecute, 0);
  201. if (!pPriv) return FALSE; /* EXIT */
  202. /* save private date */
  203. pPriv->stripHeight = dstdata.stripHeight;
  204. pPriv->height = pinfo->height;
  205. pPriv->width = pinfo->width;
  206. pPriv->widthbytes = (bitPerPixel) ? (pPriv->width + 7) / 8 : pPriv->width;
  207. pPriv->beingRecalled = FALSE;
  208. return TRUE;
  209. }