ildecompg3.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482
  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: ildecompg3.c /main/6 1996/06/19 12:23:58 ageorge $ */
  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 <math.h>
  40. #include <stdio.h>
  41. #include <stdlib.h>
  42. #include "ilint.h"
  43. #include "ilpipelem.h"
  44. #include "ilerrors.h"
  45. #include "ildecomp.h"
  46. #include "ildecompg4.h"
  47. /* ========================================================================
  48. -------------------- _ilDeCompressG3Init -------------------
  49. Routine defined in ilDecompG3 for initializing CCITT Group3
  50. compression when the pipe gets executed.
  51. ======================================================================== */
  52. static ilError _ilDecompG3Init(
  53. ilDecompG3G4PrivPtr pPriv,
  54. ilImageInfo *pSrcImage,
  55. ilImageInfo *pDstImage
  56. )
  57. {
  58. /* Allocate space for Reference line, needed for 2 dimensional coding */
  59. pPriv->gpRefLine = (ilPtr)IL_MALLOC(pPriv->nDstLineBytes );
  60. if (!pPriv->gpRefLine)
  61. return IL_ERROR_MALLOC;
  62. return IL_OK;
  63. }
  64. /* ========================================================================
  65. -------------------- _ilDeCompressG3Cleanup -------------------
  66. Routine defined in ilDecompG3 for Cleaning up CCITT Group3
  67. compression when the pipe gets executed.
  68. ======================================================================== */
  69. static ilError _ilDecompG3Cleanup(
  70. ilDecompG3G4PrivPtr pPriv,
  71. ilImageInfo *pSrcImage,
  72. ilImageInfo *pDstImage
  73. )
  74. {
  75. if (pPriv->gpRefLine)
  76. IL_FREE( (ilPtr)pPriv->gpRefLine);
  77. return IL_OK;
  78. }
  79. /* ======================================================================== */
  80. /* ========================================================================
  81. -------------------- _ilDecompG3Line -------------------
  82. Input : pointer to the Private data record or decompG3G4
  83. pointer to the Destination image
  84. Does : Reading the Source Image, De-Compresses One line for the destn.
  85. image by One dimensional coding.
  86. ======================================================================== */
  87. static ilError _ilDecompG3Line(
  88. ilDecompG3G4PrivPtr pPriv,
  89. ilPtr dstImageP
  90. )
  91. {
  92. int a0; /* changing elements used while decomressing */
  93. short color; /* color of the pixel */
  94. int firstRun; /* no. of consecutive pixels for M(a0a1) in Horiz mode */
  95. /* int secondRun; no. of consecutive pixels for M(a1a2) in Horiz mode */
  96. long bits ;
  97. long width;
  98. ilBool Is_Lsb_First ;
  99. ilPtr ImageP;
  100. int srcpos;
  101. ilDecompG4HuffTablePtrConst pDecodeWhite = ilArFax1DDecodeWhite;
  102. ilDecompG4HuffTablePtrConst pDecodeTemp;
  103. ilDecompG4HuffTablePtrConst pDecodeBlack = ilArFax1DDecodeBlack;
  104. ilPtr sByte;
  105. int no_of_ones;
  106. int startPixel;
  107. static const unsigned char fillmasks[] =
  108. {
  109. 0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff };
  110. /* Deccompression Procedure ....
  111. From the compressed data from Source Image .. retrieve a long bit; use this as
  112. index to determine the number of White Pixels and then the number of
  113. Black Pixels... Keep retrieving, till the end of line is reached..
  114. ( Until the value of a0 reaches the ImageWidth. )
  115. The new line would have always started with a White Pixel code.
  116. Until the value of a0 reaches the ImageWidth.
  117. See ilcompressg3.c for more infn. on G3 compression .
  118. */
  119. width = pPriv->width;
  120. a0 = 0;
  121. color = pPriv->white;
  122. Is_Lsb_First = pPriv->Is_Lsb_First;
  123. srcpos = pPriv->srcpos;
  124. ImageP = pPriv->ImageP;
  125. do { /* till a complete Image line is DeCompressed */
  126. if (color == pPriv->white) { /* white is run is expected first always... */
  127. firstRun = 0;
  128. do {
  129. if ( Is_Lsb_First )
  130. GET_VALUE_LSB(bits,ImageP, srcpos, G4M_WhiteRun)
  131. else
  132. GET_VALUE_MSB(bits,ImageP, srcpos, G4M_WhiteRun)
  133. pDecodeTemp = pDecodeWhite+bits;
  134. /* if invalid data is found .... */
  135. if ( ( pDecodeTemp->length == 0 ) && ( pDecodeTemp->value == 0 )
  136. && ( pDecodeTemp->type == 0 ) )
  137. return IL_ERROR_COMPRESSED_DATA ;
  138. srcpos += pDecodeTemp->length;
  139. firstRun += pDecodeTemp->value;
  140. } while (pDecodeTemp->type != G4K_CodetypeTerminator) ;
  141. }
  142. else { /* look for black Run */
  143. firstRun = 0;
  144. do {
  145. if ( Is_Lsb_First )
  146. GET_VALUE_LSB(bits,ImageP, srcpos, G4M_BlackRun)
  147. else
  148. GET_VALUE_MSB(bits,ImageP, srcpos, G4M_BlackRun)
  149. pDecodeTemp = pDecodeBlack+bits;
  150. /* if invalid data is found .... */
  151. if ( ( pDecodeTemp->length == 0 ) && ( pDecodeTemp->value == 0 )
  152. && ( pDecodeTemp->type == 0 ) )
  153. return IL_ERROR_COMPRESSED_DATA ;
  154. srcpos += pDecodeTemp->length;
  155. firstRun += pDecodeTemp->value;
  156. } while (pDecodeTemp->type != G4K_CodetypeTerminator) ;
  157. }
  158. if (a0 + firstRun > width)
  159. firstRun = width - a0;
  160. if ( (color) && (firstRun > 0) ) /* fill the dst image with 1's */
  161. {
  162. /* the whole block was written as a function, In-lined later
  163. to speedup performance in Hpux .. */
  164. /* fill 1's in the current Byte */
  165. sByte = dstImageP ;
  166. no_of_ones = firstRun;
  167. startPixel = a0 ;
  168. sByte += startPixel>>3;
  169. if (startPixel &= 7) { /* align to byte boundary */
  170. if (no_of_ones < 8 - startPixel) {
  171. *sByte++ |= fillmasks[no_of_ones] >> startPixel;
  172. goto putones_done;
  173. }
  174. *sByte++ |= 0xff >> startPixel;
  175. no_of_ones -= 8 - startPixel;
  176. if (!no_of_ones)
  177. goto putones_done;
  178. }
  179. /* fill 1's in the consecutive Full Bytes */
  180. memset(sByte,0xff,(no_of_ones >> 3));
  181. sByte += (no_of_ones >> 3 );
  182. no_of_ones = no_of_ones & 7 ;
  183. /* fill 1's in the last partial Byte */
  184. *sByte |= fillmasks[no_of_ones];
  185. }
  186. putones_done:
  187. a0 += firstRun;
  188. color = !color ;
  189. } while (a0 < width); /* End of Image line is reached */
  190. pPriv->srcpos = srcpos;
  191. return IL_OK ;
  192. }
  193. /* ========================================================================
  194. -------------------- ilDecompG3Execute -------------------
  195. Routine defined in ilDecompG3 for executing CCITT Group4
  196. decompression when the pipe gets executed.
  197. ======================================================================== */
  198. static ilError _ilDecompG3Execute(
  199. ilExecuteData *pData,
  200. unsigned long dstLine,
  201. unsigned long *pNLines
  202. )
  203. {
  204. /* ========================================================================
  205. ilDecompG3Execute() definitions
  206. ======================================================================== */
  207. ilImagePlaneInfo *pSrcPlane; /* Pointer to the Source Image Plane */
  208. ilImagePlaneInfo *pDstPlane; /* Pointer to the Source Image Plane */
  209. ilPtr pSrcLine; /* Pointer to the Source Image FirstLine */
  210. ilDecompG3G4PrivPtr pPriv; /* Pointer to private image data */
  211. ilPtr dstImageP; /* Pointer to the Destn. Image */
  212. ilPtr pRefLine = NULL; /* Pointer to the Reference line */
  213. ilError error; /* Returned error */
  214. int dstBytesPerRow; /* no.of byte per Row in the dest image */
  215. ilBool Is_2DCoding; /* G3 2 D coding is present, if True */
  216. ilBool Is_EOLs; /* EOL markers are set, and will have to be decoded */
  217. int bits; /* to store the current bit from the source image */
  218. int temp; /* some temp var.. */
  219. ilBool tag_bit; /* True or 1 for G3 1D coded line ,else G3 2d */
  220. long nLines; /* no. of lines in the current strip */
  221. ilDecompG4HuffTablePtrConst pDecodeWhite = ilArFax1DDecodeWhite;
  222. ilDecompG4HuffTablePtrConst pDecodeTemp;
  223. /* ========================================================================
  224. ilDecompG3Execute() set up for decompression algorithm code
  225. ======================================================================== */
  226. pPriv = (ilDecompG3G4PrivPtr) pData->pPrivate;
  227. if ( *pNLines <= 0 ) return IL_OK ;
  228. if ( pData->compressed.nBytesToRead <= 0 ) return IL_OK ;
  229. nLines = *pNLines;
  230. /* Exit if pointer to pPixels is NULL */
  231. pSrcPlane = &pData->pSrcImage->plane[0];
  232. if (!pSrcPlane->pPixels) return IL_ERROR_NULL_COMPRESSED_IMAGE;
  233. pSrcLine = pSrcPlane->pPixels + pData->compressed.srcOffset; /* image location pointer */
  234. pDstPlane = &pData->pDstImage->plane[0];
  235. /* The destination image line pointer gets updated at the beginning of each strip */
  236. dstImageP = (pDstPlane->pPixels + (dstLine * pDstPlane->nBytesPerRow));
  237. dstBytesPerRow = pDstPlane->nBytesPerRow ;
  238. /* ========================================================================
  239. Zero the output (dst) buffer. _ilPutOnes() writes only ones, and expects
  240. that the dst lines have already been zeroed.
  241. ======================================================================== */
  242. bzero ((char *)dstImageP, (pDstPlane->nBytesPerRow * *pNLines) );
  243. /* this pPriv->maxSrcPos is set to the bits that could be read, to prevent the
  244. program from reading beyond the compressed bytes; this check is done by
  245. the macro Get_value_msb & lsb */
  246. pPriv->maxSrcPos = pData->compressed.nBytesToRead * 8 ;
  247. pPriv->srcpos = 0;
  248. pPriv->ImageP = pSrcLine;
  249. pPriv->Is_Lsb_First = ( pPriv->compFlags & IL_G3M_LSB_FIRST);
  250. Is_2DCoding = ( pPriv->compFlags & IL_G3M_2D);
  251. Is_EOLs = ( pPriv->compFlags & IL_G3M_EOL_MARKERS);
  252. /* For G3 - 2D files, EOLs must be present, if not Error in the Compressed
  253. file... so check for that */
  254. if ( (Is_2DCoding) && (!(Is_EOLs)) )
  255. return IL_ERROR_COMPRESSED_DATA ;
  256. /* Allocate space for the Reference line and set to zero Or 1's */
  257. /* if G3 - 2 dimensional Coding is present */
  258. if ( Is_2DCoding ) {
  259. if (pPriv->white)
  260. memset(pPriv->gpRefLine,0xff,(pDstPlane->nBytesPerRow ));
  261. else
  262. memset(pPriv->gpRefLine,0x00,(pDstPlane->nBytesPerRow ));
  263. pRefLine = pPriv->gpRefLine;
  264. }
  265. /* till the Destination Image is filled up , call the decompress from the
  266. source line by line.. If any error in reading the compressed data, i.e
  267. invalid Code words or invalid Modes are found will retrun the error
  268. IL_ERROR_COMPRESSED_DATA .
  269. After decompressing each line, the decompressed line is set as reference
  270. line for the next line to be decompressed.
  271. Destination image size and Pointer are suitably decremented & incremented.
  272. */
  273. while ( nLines-- > 0 )
  274. {
  275. /* If EOLs are present in the compressed Image, (they will be there at the begining
  276. of Each line, not at the end contrary to the meaning of EOL !! ), they have to be
  277. skipped... ; This loop takes care of this whether the EOL's are aligned or Not.. */
  278. if ( Is_EOLs ) {
  279. do {
  280. if ( pPriv->Is_Lsb_First )
  281. GET_VALUE_LSB(bits, pPriv->ImageP, pPriv->srcpos, G4M_WhiteRun)
  282. else
  283. GET_VALUE_MSB(bits, pPriv->ImageP, pPriv->srcpos, G4M_WhiteRun)
  284. pDecodeTemp = pDecodeWhite+bits;
  285. if ( ( pDecodeTemp->length == 12 ) && ( pDecodeTemp->value == 1 )
  286. && ( pDecodeTemp->type == G4K_CodetypeEol ) )
  287. {
  288. pPriv->srcpos += 1 ;
  289. continue;
  290. }
  291. } while ( ( pDecodeTemp->length == 12 ) && ( pDecodeTemp->value == 1 )
  292. && ( pDecodeTemp->type == G4K_CodetypeEol ) ) ;
  293. pPriv->srcpos += 12 ;
  294. } /* Block Is_EOLs */
  295. /* If 2D compressed Image, then, after EOL look for the tag bit, which indicates
  296. the mode of compression for the next line;
  297. PIXEL(...), retrieves the next bit i.e tag bit, and if it is equal to 1, then
  298. next line sholud be decompressed 1 dimesionally...;
  299. so, call _ilDecompG3Line(...);
  300. else, next line sholud be decompressed 2 dimesionally...and call
  301. _ilDecompG4Line(...);
  302. If not 2D compressed Image, and if Not EOLs, then, the next row of image, will
  303. be from the start of the next byte, so check for that and skip to the next
  304. byte...
  305. */
  306. if ( Is_2DCoding ) {
  307. /* Retrieve the tag_bit, depending on the bit Order */
  308. if ( pPriv->Is_Lsb_First )
  309. tag_bit = PIXEL_LSB(pPriv->ImageP,pPriv->srcpos);
  310. else
  311. tag_bit = PIXEL(pPriv->ImageP,pPriv->srcpos);
  312. if ( tag_bit ) {
  313. pPriv->srcpos++;
  314. if ((error = _ilDecompG3Line(pPriv,dstImageP)) )
  315. return error;
  316. }
  317. else {
  318. pPriv->srcpos++;
  319. if ((error = _ilDecompG4Line(pPriv,pRefLine,dstImageP)) )
  320. return error;
  321. }
  322. } else {
  323. if ( ( !Is_EOLs) && ( ( temp = pPriv->srcpos % 8) != 0 ) )
  324. pPriv->srcpos += (8-temp) ;
  325. if ((error = _ilDecompG3Line(pPriv,dstImageP)) )
  326. return error;
  327. } /* is 2d coding */
  328. pRefLine = dstImageP;
  329. dstImageP += dstBytesPerRow;
  330. }
  331. return IL_OK;
  332. }
  333. /* End ilDecompG3Execute() */
  334. /* ========================================================================
  335. -------------------- ilDecompG3() -------------------
  336. Entry point of code for CCITT Group3 decompression. This
  337. includes image descriptor parameter error checking and function calls
  338. for: strip handler initialization, adding the filter element to the
  339. pipe, pipe initialization and execution, decompression algorithm,
  340. along with cleanup and destruction of allocated memory.....
  341. ======================================================================== */
  342. IL_PRIVATE
  343. ilBool _ilDecompG3 (
  344. ilPipe pipe,
  345. ilPipeInfo *pinfo,
  346. ilImageDes *pimdes
  347. )
  348. {
  349. ilDstElementData dstdata;
  350. ilDecompG3G4PrivPtr pPriv;
  351. ilImageDes des;
  352. /* Validate that image is bitonal */
  353. if (pimdes->type != IL_BITONAL)
  354. return ilDeclarePipeInvalid (pipe, IL_ERROR_IMAGE_TYPE);
  355. /*
  356. Check for Group3, uncompressed, or any undefined bits on. These
  357. are not supported!
  358. */
  359. if (pimdes->compInfo.g3.flags & IL_G4M_UNCOMPRESSED )
  360. return ilDeclarePipeInvalid (pipe, IL_ERROR_NOT_IMPLEMENTED);
  361. /* dstdata describes strips being output to next pipe element */
  362. dstdata.producerObject = (ilObject) NULL;
  363. des = *pimdes;
  364. des.compression = IL_UNCOMPRESSED;
  365. des.compInfo.g4.flags = 0;
  366. dstdata.pDes = &des;
  367. dstdata.pFormat = IL_FORMAT_BIT;
  368. dstdata.width = pinfo->width;
  369. dstdata.height = pinfo->height;
  370. dstdata.pPalette = (unsigned short *)NULL;
  371. /* set output strip height */
  372. dstdata.stripHeight = pinfo->stripHeight;
  373. dstdata.constantStrip = pinfo->constantStrip;
  374. dstdata.pCompData = (ilPtr)NULL;
  375. pPriv = (ilDecompG3G4PrivPtr) ilAddPipeElement(pipe, IL_FILTER, sizeof(ilDecompG3G4PrivRec), 0, (ilSrcElementData
  376. *)NULL,
  377. &dstdata, _ilDecompG3Init,_ilDecompG3Cleanup ,IL_NPF, _ilDecompG3Execute, NULL, 0);
  378. if (!pPriv) return FALSE; /* EXIT */
  379. /* save private data */
  380. pPriv->width = pinfo->width;
  381. pPriv->white = ( des.blackIsZero ? 1 : 0 );
  382. pPriv->compFlags = pimdes->compInfo.g4.flags;
  383. pPriv->nDstLineBytes = (pPriv->width + 7) / 8;
  384. return TRUE;
  385. }