1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-03-09 15:50:02 +00:00
cde/cde/lib/DtHelp/il/ildecomplzw.c
2018-06-27 21:58:04 -06:00

467 lines
17 KiB
C

/*
* CDE - Common Desktop Environment
*
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
*
* These libraries and programs are free software; you can
* redistribute them and/or modify them under the terms of the GNU
* Lesser General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* These libraries and programs are distributed in the hope that
* they will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with these libraries and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
/* $XConsortium: ildecomplzw.c /main/5 1996/06/19 12:23:35 ageorge $ */
/**---------------------------------------------------------------------
***
*** (c)Copyright 1991 Hewlett-Packard Co.
***
*** RESTRICTED RIGHTS LEGEND
*** Use, duplication, or disclosure by the U.S. Government is subject to
*** restrictions as set forth in sub-paragraph (c)(1)(ii) of the Rights in
*** Technical Data and Computer Software clause in DFARS 252.227-7013.
*** Hewlett-Packard Company
*** 3000 Hanover Street
*** Palo Alto, CA 94304 U.S.A.
*** Rights for non-DOD U.S. Government Departments and Agencies are as set
*** forth in FAR 52.227-19(c)(1,2).
***
***-------------------------------------------------------------------*/
#include <stdlib.h>
#include "ilint.h"
#include "ilpipelem.h"
#include "ildecomp.h"
#include "ilerrors.h"
/* ========================================================================
Local definitions
======================================================================== */
#define CLEAR_CODE 256
#define END_OF_INFORMATION 257
#define MAX_NODES 0x1000
#define OKAY 1
/* ========================================================================
Decompression private data type declaration
======================================================================== */
typedef struct { /* decode node structure */
unsigned short value; /* byte value of node */
short previous; /* previous string node index */
} ilDenodeRec, *ilDenodePtr;
typedef struct { /* private image information */
ilDenodePtr denodes; /* table/tree for decode nodes */
ilPtr pString; /* ptr to string table */
unsigned long length; /* number of bytes read */
unsigned int nextNode; /* next node to be used */
unsigned long nDstLineBytes; /* width of dst in bytes */
} ilDecompPrivRec, *ilDecompPrivPtr;
/* ========================================================================
-------------------- ilDecompLZWInit/Cleanup -------------------
Allocate / deallocate buffers for LZW decompression.
======================================================================== */
static ilError ilDecompLZWInit(
ilDecompPrivPtr pPriv,
ilImageInfo *pSrcImage,
ilImageInfo *pDstImage
)
{
pPriv->denodes = (ilDenodePtr)NULL;
pPriv->pString = (ilPtr)IL_MALLOC (MAX_NODES);
if (!pPriv->pString)
return IL_ERROR_MALLOC;
pPriv->denodes = (ilDenodePtr)IL_MALLOC (sizeof(ilDenodeRec) * MAX_NODES);
if (!pPriv->denodes) {
IL_FREE (pPriv->pString);
pPriv->pString = (ilPtr)NULL;
return IL_ERROR_MALLOC;
}
return IL_OK;
}
static ilError ilDecompLZWCleanup (
ilDecompPrivPtr pPriv,
ilBool aborting
)
{
if (pPriv->pString)
IL_FREE (pPriv->pString);
if (pPriv->denodes)
IL_FREE ((ilPtr)pPriv->denodes);
return IL_OK;
}
/* ========================================================================
-------------------- ilCurrentBitsRead( ) -------------------
Returns the number of bits per code word for the next node in the tree.
======================================================================== */
static int ilCurrentBitsRead (
ilDecompPrivPtr pPriv
)
{
int retval;
int node;
node = pPriv->nextNode + 2;
if (node <= (512 - 2)) retval = 9;
else {
if (node <= (1024 - 2)) retval = 10;
else {
if (node <= (2048 - 2)) retval = 11;
else retval = 12;
}
}
return retval;
}
/* End ilCurrentBitsRead() */
/* ========================================================================
-------------------- ilStringFromCode --------------------
Using the code as the starting node in the decode tree this routine
builds the string by traversing backwards up the tree.
======================================================================== */
static void ilStringFromCode(
ilDecompPrivPtr pPriv,
unsigned int code, /* Code to look for string with. */
ilPtr pString, /* Pointer to value for the length of the string */
unsigned int *pcount /* Pointer to location to place string at in memory */
)
{
unsigned int index;
int node;
ilDenodePtr denodes = pPriv->denodes;
if (code > 255) node = code - 2; /* remove for extra codes */
else node = code;
index = 0; /* start at end of string */
while (node != -1) { /* build string backwards */
pString[index++] = denodes[node].value;
node = denodes[node].previous;
}
*pcount = index;
}
/* ========================================================================
-------------------- ilAddStringToTable --------------------
Adds a new node to the decode table and links it back to the last code
for the current string.
======================================================================== */
static void ilAddStringToTable (
ilDecompPrivPtr pPriv,
unsigned int code, /* Code for previous entry in table */
unsigned char khar /* Value for new node */
)
{
ilDenodePtr denodes = pPriv->denodes;
denodes[pPriv->nextNode].value = khar;
if (code < 256) denodes[pPriv->nextNode].previous = code;
else denodes[pPriv->nextNode].previous = code - 2;
pPriv->nextNode++;
}
/* ========================================================================
--------------------ilInitializeDecodeTable --------------------
Allocates the decode table. Initializes the table with the first
256 entries.
======================================================================== */
static ilError ilInitializeDecodeTable (
ilDecompPrivPtr pPriv
)
{
unsigned int i;
for (i = 0;i < 256;i++) {
pPriv->denodes[i].value = i;
pPriv->denodes[i].previous = -1;
}
pPriv->nextNode = 256;
for (i = 256;i < MAX_NODES;i++) {
pPriv->denodes[i].value = 0;
pPriv->denodes[i].previous = -1;
}
return IL_OK;
}
/* ========================================================================
-------------------- ilDecompLZWExecute() -------------------
Routine defined in ilDecompLZW for executing LZW
decompression when the pipe gets executed.
======================================================================== */
static ilError ilDecompLZWExecute(
ilExecuteData *pData,
unsigned long dstLine,
unsigned long *pNLines
)
{
/* ========================================================================
ilDecompLZWExecute() definitions
======================================================================== */
/* Macro which returns whether a clear code exists at *_pByte: a clear code
is 9 bits, = 256, or 0x80 in first byte and a zero in the upper bit of the next.
Each strip must begin with a clear code; at end of strip, a search-ahead
is done for the next clear code.
*/
#define IS_CLEAR_CODE(_pByte) ( (*(_pByte) == 0x80) && ((*(_pByte+1) & 0x80) == 0) )
/* My defines */
unsigned long dstNBytes; /* Number of destination image bytes per row */
long nLines; /* Number of lines per source image strip */
long nBytesToGo; /* Number of source image bytes left to unpack for current strip */
long nDstLineBytesToGo; /* Number of bytes left to write to this line of destination */
ilPtr pSrcByte; /* Pointer to source image data */
ilPtr pDstByte; /* Pointer to destination image data first byte */
ilPtr pSrcStart; /* Pointer to initial src (comp) byte */
ilPtr pDstLine; /* Pointer to destination image data first byte of each scanline */
ilDecompPrivPtr pPriv; /* Pointer to private image data */
ilImagePlaneInfo *pPlane;
/* Greeley defines */
unsigned int bitCount;
unsigned int numBits;
/* compatibility problem with long and unsigned long data fields */
CARD32 bits;
long k;
unsigned int code;
unsigned int oldCode;
unsigned int stringCount = 0;
ilError status = IL_OK;
ilPtr pString;
/* ========================================================================
ilDecompLZWExecute() set up for decompression algorithm code
======================================================================== */
pPriv = (ilDecompPrivPtr)pData->pPrivate;
nLines = *pNLines;
if (nLines <= 0)
return IL_OK;
nBytesToGo = pData->compressed.nBytesToRead;
if (nBytesToGo <= 0)
return IL_OK;
pPlane = &pData->pSrcImage->plane[0];
if (!pPlane->pPixels) return IL_ERROR_NULL_COMPRESSED_IMAGE;
pSrcStart = pPlane->pPixels + pData->compressed.srcOffset;
pSrcByte = pSrcStart;
pPlane = &pData->pDstImage->plane[0];
dstNBytes = pPlane->nBytesPerRow;
pDstLine = pPlane->pPixels + dstLine * dstNBytes;
/* ========================================================================
ilDecompLZWExecute() decompression algorithm code
======================================================================== */
/* get ptr to 4k string buffer */
pString = pPriv->pString;
/* decode each line of compressed data into the destination image */
pPriv->length = 0;
pPriv->nextNode = 256; /* set to keep ref in ReadCode() call to CurrentBits2() from bombing */
bits = 0;
bitCount = 0;
/* Each strip must begin with a clear code; error if not. */
if (!IS_CLEAR_CODE (pSrcByte))
return IL_ERROR_COMPRESSED_DATA;
while (nLines-- > 0) {
pDstByte = pDstLine;
pDstLine += dstNBytes;
nDstLineBytesToGo = pPriv->nDstLineBytes;
while (nDstLineBytesToGo > 0) {
if (stringCount == 0) { /* get another string */
/* BEGIN ReadCode */
if (bitCount < 16) { /* Get next byte(s) of encoded source image data */
if (--nBytesToGo < 0)
return IL_ERROR_COMPRESSED_DATA;
if (--nBytesToGo < 0) {
bits |= (*pSrcByte++ << (24 - bitCount));
bitCount += 8;
}
else {
bits |= (*pSrcByte++ << (24 - bitCount));
bits |= (*pSrcByte++ << (16 - bitCount));
bitCount += 16;
}
}
numBits = ilCurrentBitsRead (pPriv);
code = (unsigned short)(bits >> (32 - numBits));
bits <<= numBits;
bitCount -= numBits;
/* END ReadCode */
if (code == END_OF_INFORMATION)
goto xit; /* done, EXIT */
if (code == CLEAR_CODE) {
if ((status = ilInitializeDecodeTable (pPriv)) != IL_OK) goto xit;
/* BEGIN ReadCode */
if (bitCount < 16) { /* Get next byte(s) of encoded source image data */
if (--nBytesToGo < 0)
return IL_ERROR_COMPRESSED_DATA;
if (--nBytesToGo < 0) {
bits |= (*pSrcByte++ << (24 - bitCount));
bitCount += 8;
}
else {
bits |= (*pSrcByte++ << (24 - bitCount));
bits |= (*pSrcByte++ << (16 - bitCount));
bitCount += 16;
}
}
numBits = ilCurrentBitsRead (pPriv);
code = (bits >> (32 - numBits));
bits <<= numBits;
bitCount -= numBits;
/* END ReadCode */
if (code == END_OF_INFORMATION) goto xit;
ilStringFromCode (pPriv, code, pString, &stringCount);
oldCode = code;
}
else {
if ((code < 256) || ((code - 2) < pPriv->nextNode)) { /* code is in table */
ilStringFromCode (pPriv, code, pString, &stringCount);
ilAddStringToTable (pPriv, oldCode, pString[stringCount - 1]);
oldCode = code;
}
else {
ilStringFromCode (pPriv, oldCode, pString, &stringCount);
for (k = stringCount - 1; k >= 0; k--) pString[k + 1] = pString[k];
pString[0] = pString[stringCount];
stringCount++;
ilAddStringToTable (pPriv, oldCode, pString[0]);
oldCode = code;
}
}
}
/* Store one byte, subtract line byte count */
*pDstByte++ = pString[--stringCount];
nDstLineBytesToGo--;
}
}
xit:
return status;
}
/* ========================================================================
-------------------- ilDecompLZW() --------------------
Code entry point for LZW decompression. This includes image descriptor
parameter error checking and function calls for: strip handler
initialization, adding the filter element to the pipe, pipe
initialization, execution and destruction, decompression algorithm.....
======================================================================== */
IL_PRIVATE ilBool _ilDecompLZW (
ilPipe pipe,
ilPipeInfo *pinfo,
ilImageDes *pimdes,
ilImageFormat *pimformat
)
{
ilDstElementData dstdata;
ilDecompPrivPtr pPriv;
ilImageDes des;
ilImageFormat format;
long bytesPerRow [IL_MAX_SAMPLES];
dstdata.producerObject = (ilObject) NULL;
des = *pimdes;
des.compression = IL_UNCOMPRESSED;
dstdata.pDes = &des;
format = *pimformat;
format.rowBitAlign = (format.nBitsPerSample[0] == 1) ? 32 : 8;
dstdata.pFormat = &format;
dstdata.width = pinfo->width;
dstdata.height = pinfo->height;
dstdata.pPalette = pinfo->pPalette;
dstdata.stripHeight = pinfo->stripHeight;
dstdata.constantStrip = pinfo->constantStrip;
pPriv = (ilDecompPrivPtr) ilAddPipeElement(pipe, IL_FILTER, sizeof(ilDecompPrivRec), 0,
(ilSrcElementData *)NULL, &dstdata,
ilDecompLZWInit, ilDecompLZWCleanup, IL_NPF, ilDecompLZWExecute, NULL, 0);
if (!pPriv) return FALSE;
/* Store info in *pPriv. For nDstLineBytes, need minimum # of bytes uncompressed
dst data would take - get bytes/row using rowBitAlign of 8 (packed).
*/
format.rowBitAlign = 8;
ilGetBytesPerRow (pimdes, &format, pinfo->width, bytesPerRow);
pPriv->nDstLineBytes = bytesPerRow[0];
return TRUE;
}