1 /* libhpojip -- HP OfficeJet image-processing library. */
3 /* Copyright (C) 1995-2002 Hewlett-Packard Company
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful, but
11 * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied
12 * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and
13 * NON-INFRINGEMENT. See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
20 * In addition, as a special exception, Hewlett-Packard Company
21 * gives permission to link the code of this program with any
22 * version of the OpenSSL library which is distributed under a
23 * license identical to that listed in the included LICENSE.OpenSSL
24 * file, and distribute linked combinations including the two.
25 * You must obey the GNU General Public License in all respects
26 * for all of the code used other than OpenSSL. If you modify
27 * this file, you may extend this exception to your version of the
28 * file, but you are not obligated to do so. If you do not wish to
29 * do so, delete this exception statement from your version.
32 /* Original author: Mark Overton and others.
34 * Ported to Linux by David Paschal.
37 /******************************************************************************\
39 * xtable.c - Performs a 256-entry table lookup on all bytes
41 ******************************************************************************
43 * Name of Global Jump-Table:
47 * Items in aXformInfo array passed into setXformSpec:
49 * aXformInfo[IP_TABLE_WHICH] = contents of table to use:
50 * IP_TABLE_USER = user-supplied pointer to a 256-byte table,
51 * IP_TABLE_USER_WORD = user-supplied pointer to a 4096-word table,
52 * IP_TABLE_PASS_THRU = pass-thru table that does nothing,
53 * IP_TABLE_GAMMA = gamma function,
54 * IP_TABLE_THRESHOLD = threshold (snaps each incoming byte to 0 or 255),
55 * IP_TABLE_MIRROR = mirror-image each incoming byte,
56 * IP_TABLE_USER_THREE = three user-supplied table pointers,
57 * IP_TABLE_USER_THREE_WORD = three user-supplied table pointers for 48-bit (see format below),
58 * IP_TABLE_BW_CLIP = white/black clipper (2 thresholds below)
60 * aXformInfo[IP_TABLE_OPTION] =
61 * parameter based on type of table to use. values:
62 * - (type IP_TABLE_USER) pointer to user table,
63 * this table is copied into this xform's instance,
64 * - (type IP_TABLE_GAMMA) gamma value, in 16.16 fixed-point, a value
65 * less than 1.0 does an inverse gamma, (for
66 * type IP_TABLE_GAMMA above),
67 * - (type IP_TABLE_THRESHOLD) threshold value. if an incoming byte is >=
68 * this value, it changes to 255, else it changes
69 * to 0 (for type IP_TABLE_THRESHOLD above),
70 * - (type IP_TABLE_BW_CLIP) hi word = number of 0 entries at start,
71 * lo word = number of 255 entries at end,
73 * For option IP_TABLE_USER_THREE above (three user-supplied table pointers),
74 * these three 256-byte tables are for 3-component color data. The pointers are in
75 * aXformInfo[IP_TABLE_COLOR_1], aXformInfo[IP_TABLE_COLOR_2], and aXformInfo[IP_TABLE_COLOR_3].
77 * For option IP_TABLE_USER_THREE_WORD (three user tables for 48-bit color data),
78 * the pointers are in aXformInfo as with IP_TABLE_USER_THREE.
79 * Each table consists of 4096 words (8192 bytes) which are indexed by the high 12 bits
80 * of each color-channel. The low four bits are interpolated herein. Each table-entry
81 * contains a 16-bit pixel-value, even though it's indexed by just 12 bits.
83 * IP_TABLE_USER_WORD is like IP_TABLE_USER_THREE_WORD described above.
85 * For option IP_TABLE_BW_CLIP, the white/black clipper, the table starts with the given
86 * number of 0's, and ends with the given number of 255's, and linearly
87 * progresses between 1 and 254 in between them. This serves to snap
88 * almost-black to black, and almost-white to white. If these numbers
89 * are large, this table also boosts contrast.
91 * Capabilities and Limitations:
93 * The incoming data can be any kind of raw pixels of 1, 8, 16, 24 or 48
94 * bits/pixel. Bi-level (1 bit/pixel) data is treated as 8 pixels per byte.
95 * All table-types support all these forms of input data. For 16 bits/channel
96 * data, the tables are interpolated.
98 * For improved precision, the following define larger (12-bit index) tables:
99 * IP_TABLE_USER_WORD - 16 bits per pixel (grayscale)
100 * IP_TABLE_USER_THREE_WORD - 48 bits per pixel (color)
102 * Also, IP_TABLE_GAMMA will create a 12-bit table when the input data
103 * is 16 bits/channel.
105 * 12-bit tables work with 8-bit/channel data, and 8-bit tables work with
106 * 16-bit/channel data. Truncation or interpolation is done as needed.
108 * Default Input Traits, and Output Traits:
110 * trait default input output
111 * ------------------- --------------------- ------------------------
112 * iPixelsPerRow * passed into output same as default input
113 * iBitsPerPixel * passed into output same as default input
114 * iComponentsPerPixel passed into output same as default input
115 * lHorizDPI passed into output same as default input
116 * lVertDPI passed into output same as default input
117 * lNumRows passed into output same as default input
118 * iNumPages passed into output same as default input
119 * iPageNum passed into output same as default input
121 * Above, a "*" by an item indicates it must be valid (not negative).
123 * Apr 1998 Mark Overton -- wrote original code
125 \******************************************************************************/
129 #include "string.h" /* for memset and memcpy */
130 #include "math.h" /* for pow for generating gamma table */
137 #define PRINT(msg,arg1,arg2) \
138 _ftprintf(stderr, msg, (int)arg1, (int)arg2)
140 #define PRINT(msg,arg1,arg2)
143 #define CHECK_VALUE 0x4ba1dace
147 IP_IMAGE_TRAITS traits; /* traits of the input and output image */
148 BYTE bWhich; /* which table to generate */
149 BYTE bTables[3][256]; /* the 8-bit look-up tables */
150 WORD *pwTables[3]; /* ptrs to 12-bit-index tables (for 16-bits/pixel) */
151 BOOL bBigTable; /* are we using the 12-bit tables? */
152 int nTables; /* # of tables defined (1 or 3) */
153 DWORD dwBytesPerRow; /* # of bytes in each row */
154 DWORD dwRowsDone; /* number of rows converted so far */
155 DWORD dwInNextPos; /* file pos for subsequent input */
156 DWORD dwOutNextPos; /* file pos for subsequent output */
157 DWORD dwValidChk; /* struct validity check value */
158 } TBL_INST, *PTBL_INST;
173 static BOOL generateTable (
175 DWORD_OR_PVOID aXformInfo[])
186 g->bBigTable = FALSE;
187 pTable = g->bTables[0];
188 dwparam = aXformInfo[IP_TABLE_OPTION].dword;
189 pvparam = aXformInfo[IP_TABLE_OPTION].pvoid;
190 flparam = aXformInfo[IP_TABLE_OPTION].fl;
191 which = (IP_TABLE_TYPE)aXformInfo[IP_TABLE_WHICH].dword;
192 g->bWhich = (BYTE)which;
199 memcpy (pTable, (PBYTE)pvparam, 256);
202 case IP_TABLE_USER_WORD:
205 IP_MEM_ALLOC (4097*sizeof(WORD), pwTable); /* 4097: extra entry at end */
206 g->pwTables[0] = pwTable;
207 memcpy (pwTable, (PWORD)pvparam, 4096*sizeof(WORD));
208 pwTable[4096] = pwTable[4095]; /* extra entry to help interpolation */
212 case IP_TABLE_USER_THREE:
213 if (aXformInfo[IP_TABLE_COLOR_1].pvoid==0 ||
214 aXformInfo[IP_TABLE_COLOR_2].pvoid==0 ||
215 aXformInfo[IP_TABLE_COLOR_3].pvoid==0)
217 memcpy (g->bTables[0], (PBYTE)aXformInfo[IP_TABLE_COLOR_1].pvoid, 256);
218 memcpy (g->bTables[1], (PBYTE)aXformInfo[IP_TABLE_COLOR_2].pvoid, 256);
219 memcpy (g->bTables[2], (PBYTE)aXformInfo[IP_TABLE_COLOR_3].pvoid, 256);
223 case IP_TABLE_USER_THREE_WORD:
224 if (aXformInfo[IP_TABLE_COLOR_1].pvoid==0 ||
225 aXformInfo[IP_TABLE_COLOR_2].pvoid==0 ||
226 aXformInfo[IP_TABLE_COLOR_3].pvoid==0)
229 for (nTable=0; nTable<3; nTable++) {
230 IP_MEM_ALLOC (4097*sizeof(WORD), pwTable); /* 4097: extra entry at end */
231 g->pwTables[nTable] = pwTable;
232 memcpy (pwTable, (PWORD)aXformInfo[IP_TABLE_COLOR_1+nTable].pvoid, 4096*sizeof(WORD));
233 pwTable[4096] = pwTable[4095]; /* extra entry to help interpolation */
239 case IP_TABLE_PASS_THRU:
243 for (i=0; i<=255; i++)
255 gamma = (float)flparam / (float)(1L<<16);
256 if (gamma<=0.0f || gamma>=10.0f)
258 gamma = 1.0f / gamma;
260 if (g->traits.iBitsPerPixel==16 || g->traits.iBitsPerPixel==48) {
262 IP_MEM_ALLOC (4097*sizeof(WORD), pwTable); /* 4097: extra entry at end */
263 g->pwTables[0] = pwTable;
265 for (index=0; index<=4095u; index++) {
266 fval = (float)index / 4095.0f;
267 gamval = 65535.0f * (float)pow(fval, gamma);
268 pwTable[index] = (WORD)(gamval + 0.5f);
271 pwTable[4096] = pwTable[4095]; /* extra entry to help interpolation */
274 for (index=0; index<=255u; index++) {
275 fval = (float)index / 255.0f;
276 gamval = 255.0f * (float)pow(fval, gamma);
277 pTable[index] = (BYTE)(gamval + 0.5f);
283 case IP_TABLE_THRESHOLD:
284 if (dwparam<1 || dwparam>255)
286 memset (pTable, 0, dwparam);
287 memset (pTable+dwparam, 255, 256-dwparam);
290 case IP_TABLE_MIRROR:
294 for (index=0; index<=255; index++) {
295 for (mask=0x01u; mask<=0x80u; mask<<=1) {
304 case IP_TABLE_BW_CLIP:
306 DWORD nBlack, nWhite, nMid, slopeMid, posMid, index;
308 nBlack = dwparam >> 16;
309 nWhite = dwparam & 0xFFFFu;
311 if (nBlack+nWhite > 256)
314 for (index=0; index<nBlack; index++)
317 for (index=256-nWhite; index<=255; index++)
320 nMid = 256 - nBlack - nWhite;
321 slopeMid = (255ul<<16) / (nMid + 1);
322 posMid = 0x8000u; /* offset for rounding */
324 for (index=nBlack; index<256-nWhite; index++) {
326 pTable[index] = (BYTE)(posMid >> 16);
343 /*****************************************************************************\
345 * table_openXform - Creates a new instance of the transformer
347 *****************************************************************************
349 * This returns a handle for the new instance to be passed into
350 * all subsequent calls.
352 * Return value: IP_DONE=success; IP_FATAL_ERROR=misc error.
354 \*****************************************************************************/
356 static WORD table_openXform (
357 IP_XFORM_HANDLE *pXform) /* out: returned handle */
361 INSURE (pXform != NULL);
362 IP_MEM_ALLOC (sizeof(TBL_INST), g);
364 memset (g, 0, sizeof(TBL_INST));
365 g->dwValidChk = CHECK_VALUE;
369 return IP_FATAL_ERROR;
374 /*****************************************************************************\
376 * table_setDefaultInputTraits - Specifies default input image traits
378 *****************************************************************************
380 * The header of the file-type handled by the transform probably does
381 * not include *all* the image traits we'd like to know. Those not
382 * specified in the file-header are filled in from info provided by
385 * Return value: IP_DONE=success; IP_FATAL_ERROR=misc error.
387 \*****************************************************************************/
389 static WORD table_setDefaultInputTraits (
390 IP_XFORM_HANDLE hXform, /* in: handle for xform */
391 PIP_IMAGE_TRAITS pTraits) /* in: default image traits */
395 HANDLE_TO_PTR (hXform, g);
397 /* insure that traits we care about are known */
398 INSURE (pTraits->iPixelsPerRow>0 && pTraits->iBitsPerPixel>0);
399 g->traits = *pTraits; /* a structure copy */
400 g->dwBytesPerRow = (g->traits.iPixelsPerRow*g->traits.iBitsPerPixel + 7) / 8;
404 return IP_FATAL_ERROR;
409 /*****************************************************************************\
411 * table_setXformSpec - Provides xform-specific information
413 \*****************************************************************************/
415 static WORD table_setXformSpec (
416 IP_XFORM_HANDLE hXform, /* in: handle for xform */
417 DWORD_OR_PVOID aXformInfo[]) /* in: xform information */
421 HANDLE_TO_PTR (hXform, g);
423 if (! generateTable(g,aXformInfo))
428 return IP_FATAL_ERROR;
433 /*****************************************************************************\
435 * table_getHeaderBufSize- Returns size of input buf needed to hold header
437 \*****************************************************************************/
439 static WORD table_getHeaderBufSize (
440 IP_XFORM_HANDLE hXform, /* in: handle for xform */
441 DWORD *pdwInBufLen) /* out: buf size for parsing header */
443 /* since input is raw pixels, there is no header, so set it to zero */
450 /*****************************************************************************\
452 * table_getActualTraits - Parses header, and returns input & output traits
454 \*****************************************************************************/
456 static WORD table_getActualTraits (
457 IP_XFORM_HANDLE hXform, /* in: handle for xform */
458 DWORD dwInputAvail, /* in: # avail bytes in input buf */
459 PBYTE pbInputBuf, /* in: ptr to input buffer */
460 PDWORD pdwInputUsed, /* out: # bytes used from input buf */
461 PDWORD pdwInputNextPos,/* out: file-pos to read from next */
462 PIP_IMAGE_TRAITS pIntraits, /* out: input image traits */
463 PIP_IMAGE_TRAITS pOutTraits) /* out: output image traits */
467 HANDLE_TO_PTR (hXform, g);
469 /* Since there is no header, we'll report no usage of input */
471 *pdwInputNextPos = 0;
473 *pIntraits = g->traits; /* structure copies */
474 *pOutTraits = g->traits;
476 return IP_DONE | IP_READY_FOR_DATA;
479 return IP_FATAL_ERROR;
484 /****************************************************************************\
486 * table_getActualBufSizes - Returns buf sizes needed for remainder of job
488 \****************************************************************************/
490 static WORD table_getActualBufSizes (
491 IP_XFORM_HANDLE hXform, /* in: handle for xform */
492 PDWORD pdwMinInBufLen, /* out: min input buf size */
493 PDWORD pdwMinOutBufLen) /* out: min output buf size */
497 HANDLE_TO_PTR (hXform, g);
499 *pdwMinInBufLen = *pdwMinOutBufLen = g->dwBytesPerRow;
503 return IP_FATAL_ERROR;
508 /*****************************************************************************\
510 * table_convert - Converts one row
512 \*****************************************************************************/
514 static WORD table_convert (
515 IP_XFORM_HANDLE hXform,
516 DWORD dwInputAvail, /* in: # avail bytes in in-buf */
517 PBYTE pbInputBuf, /* in: ptr to in-buffer */
518 PDWORD pdwInputUsed, /* out: # bytes used from in-buf */
519 PDWORD pdwInputNextPos, /* out: file-pos to read from next */
520 DWORD dwOutputAvail, /* in: # avail bytes in out-buf */
521 PBYTE pbOutputBuf, /* in: ptr to out-buffer */
522 PDWORD pdwOutputUsed, /* out: # bytes written in out-buf */
523 PDWORD pdwOutputThisPos) /* out: file-pos to write the data */
527 PBYTE pIn, pOut, pOutAfter;
529 HANDLE_TO_PTR (hXform, g);
531 /**** Check if we were told to flush ****/
533 if (pbInputBuf == NULL) {
534 PRINT (_T("table_convert: Told to flush.\n"), 0, 0);
535 *pdwInputUsed = *pdwOutputUsed = 0;
536 *pdwInputNextPos = g->dwInNextPos;
537 *pdwOutputThisPos = g->dwOutNextPos;
541 /**** Output a Row ****/
543 nBytes = g->dwBytesPerRow;
544 INSURE (dwInputAvail >= (DWORD)nBytes);
545 INSURE (dwOutputAvail >= (DWORD)nBytes);
549 pOutAfter = pOut + nBytes;
551 if (g->bWhich == IP_TABLE_PASS_THRU)
553 memcpy (pOut, pIn, nBytes);
555 else if (g->traits.iBitsPerPixel==16 || g->traits.iBitsPerPixel==48)
557 /* 16 bits per channel -- interpolate between table-entries */
559 WORD *pwTable, *pwIn, *pwOut, *pwOutAfter;
564 pwOutAfter = (WORD*)pOutAfter;
568 /* we're using 12-bit table(s) */
569 while (pwOut < pwOutAfter) {
570 for (nTable=0; nTable<g->nTables; nTable++) {
571 pwTable = g->pwTables[nTable];
572 x = (unsigned)(*pwIn++);
573 xHi = x >> 4; /* hi 12 bits is used for indexing into the table */
574 y1 = (unsigned)pwTable[xHi ]; /* index is in 0..4095 */
575 y2 = (unsigned)pwTable[xHi+1]; /* extra entry in table is for index=4096 */
576 /* interpolate the lowest 4 bits */
577 *pwOut++ = (WORD)(((y2-y1)*(x&0x0f)>>4) + y1);
581 else /* we're using 8-bit table(s) */
583 while (pwOut < pwOutAfter) {
584 for (nTable=0; nTable<g->nTables; nTable++) {
585 pbTable = g->bTables[nTable];
586 x = (unsigned)(*pwIn++);
587 xHi = x >> 8; /* hi 8 bits is used for indexing into the table */
588 y1 = (unsigned)pbTable[xHi]; /* index is in 0..255 for both */
589 y2 = (unsigned)pbTable[xHi==255 ? 255 : xHi+1];
590 /* interpolate the lowest 8 bits */
591 *pwOut++ = (WORD)((y2-y1)*(x&0x0ff) + (y1<<8));
596 else /* 8 bits per channel -- the normal case */
600 /* using a big table for 8- or 24-bit data, for some reason */
601 while (pOut < pOutAfter)
602 for (nTable=0; nTable<g->nTables; nTable++)
603 *pOut++ = (BYTE)(g->pwTables[nTable][(unsigned)(*pIn++)<<4] >> 8);
605 else if (g->nTables == 3)
607 while (pOut < pOutAfter) {
608 /* process two pixels at a time for improved speed */
609 pOut[0] = g->bTables[0][pIn[0]];
610 pOut[1] = g->bTables[1][pIn[1]];
611 pOut[2] = g->bTables[2][pIn[2]];
612 pOut[3] = g->bTables[0][pIn[3]];
613 pOut[4] = g->bTables[1][pIn[4]];
614 pOut[5] = g->bTables[2][pIn[5]];
620 else /* using a single table */
622 while (pOut < pOutAfter) {
623 /* process eight pixels at a time for improved speed */
624 pOut[0] = g->bTables[0][pIn[0]];
625 pOut[1] = g->bTables[0][pIn[1]];
626 pOut[2] = g->bTables[0][pIn[2]];
627 pOut[3] = g->bTables[0][pIn[3]];
628 pOut[4] = g->bTables[0][pIn[4]];
629 pOut[5] = g->bTables[0][pIn[5]];
630 pOut[6] = g->bTables[0][pIn[6]];
631 pOut[7] = g->bTables[0][pIn[7]];
639 *pdwInputUsed = nBytes;
640 g->dwInNextPos += nBytes;
641 *pdwInputNextPos = g->dwInNextPos;
643 *pdwOutputUsed = nBytes;
644 *pdwOutputThisPos = g->dwOutNextPos;
645 g->dwOutNextPos += nBytes;
649 return IP_CONSUMED_ROW | IP_PRODUCED_ROW | IP_READY_FOR_DATA;
652 return IP_FATAL_ERROR;
657 /*****************************************************************************\
659 * table_insertedData - client inserted into our output stream
661 \*****************************************************************************/
663 static WORD table_insertedData (
664 IP_XFORM_HANDLE hXform,
668 return IP_FATAL_ERROR; /* must never be called (can't insert data) */
673 /*****************************************************************************\
675 * table_newPage - Tells us to flush this page, and start a new page
677 \*****************************************************************************/
679 static WORD table_newPage (
680 IP_XFORM_HANDLE hXform)
684 HANDLE_TO_PTR (hXform, g);
685 /* todo: return fatal error if convert is called again? */
686 return IP_DONE; /* can't insert page-breaks, so ignore this call */
689 return IP_FATAL_ERROR;
695 /*****************************************************************************\
697 * table_closeXform - Destroys this instance
699 \*****************************************************************************/
701 static WORD table_closeXform (IP_XFORM_HANDLE hXform)
706 HANDLE_TO_PTR (hXform, g);
709 if (g->pwTables[i] != NULL)
710 IP_MEM_FREE (g->pwTables[i]);
713 IP_MEM_FREE (g); /* free memory for the instance */
718 return IP_FATAL_ERROR;
723 /*****************************************************************************\
725 * tableTbl - Jump-table for transform driver
727 \*****************************************************************************/
729 IP_XFORM_TBL tableTbl = {
731 table_setDefaultInputTraits,
733 table_getHeaderBufSize,
734 table_getActualTraits,
735 table_getActualBufSizes,