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 * xsaturation.c - Changes the saturation of color data
41 ******************************************************************************
43 * Name of Global Jump-Table:
47 * Items in aXformInfo array passed into setXformSpec:
49 * aXformInfo[IP_SATURATION_FACTOR] = saturation factor, in 24.8 fixed point (8 bits of frac)
51 * A conceptual value of 1.0 (aXformInfo[0] = 256) means no change in
52 * saturation. 2.0 doubles it; 0.5 cuts it in half. 0.0 eliminates all
53 * color, outputting RGB grayscale.
55 * Capabilities and Limitations:
57 * The incoming data can be 24-bit color or 48-bit color.
58 * The pixels are assumed to be RGB.
60 * Default Input Traits, and Output Traits:
62 * trait default input output
63 * ------------------- --------------------- ------------------------
64 * iPixelsPerRow * passed into output same as default input
65 * iBitsPerPixel * passed into output same as default input
66 * iComponentsPerPixel passed into output same as default input
67 * lHorizDPI passed into output same as default input
68 * lVertDPI passed into output same as default input
69 * lNumRows passed into output same as default input
70 * iNumPages passed into output same as default input
71 * iPageNum passed into output same as default input
73 * Above, a "*" by an item indicates it must be valid (not negative).
75 * Feb 2000 Mark Overton -- wrote original code
77 \******************************************************************************/
81 #include "string.h" /* for memset and memcpy */
88 #define PRINT(msg,arg1,arg2) \
89 _ftprintf(stderr, msg, (int)arg1, (int)arg2)
91 #define PRINT(msg,arg1,arg2)
94 #define CHECK_VALUE 0x4ba1dace
98 IP_IMAGE_TRAITS traits; /* traits of the input and output image */
99 DWORD dwSatFac; /* desired saturation factor */
100 DWORD dwBytesPerRow; /* # of bytes in each row */
101 DWORD dwRowsDone; /* number of rows converted so far */
102 DWORD dwInNextPos; /* file pos for subsequent input */
103 DWORD dwOutNextPos; /* file pos for subsequent output */
104 DWORD dwValidChk; /* struct validity check value */
105 } SAT_INST, *PSAT_INST;
109 /*****************************************************************************\
111 * saturation_openXform - Creates a new instance of the transformer
113 *****************************************************************************
115 * This returns a handle for the new instance to be passed into
116 * all subsequent calls.
118 * Return value: IP_DONE=success; IP_FATAL_ERROR=misc error.
120 \*****************************************************************************/
122 static WORD saturation_openXform (
123 IP_XFORM_HANDLE *pXform) /* out: returned handle */
127 INSURE (pXform != NULL);
128 IP_MEM_ALLOC (sizeof(SAT_INST), g);
130 memset (g, 0, sizeof(SAT_INST));
131 g->dwValidChk = CHECK_VALUE;
135 return IP_FATAL_ERROR;
140 /*****************************************************************************\
142 * saturation_setDefaultInputTraits - Specifies default input image traits
144 *****************************************************************************
146 * The header of the file-type handled by the transform probably does
147 * not include *all* the image traits we'd like to know. Those not
148 * specified in the file-header are filled in from info provided by
151 * Return value: IP_DONE=success; IP_FATAL_ERROR=misc error.
153 \*****************************************************************************/
155 static WORD saturation_setDefaultInputTraits (
156 IP_XFORM_HANDLE hXform, /* in: handle for xform */
157 PIP_IMAGE_TRAITS pTraits) /* in: default image traits */
161 HANDLE_TO_PTR (hXform, g);
163 /* insure that traits we care about are known */
164 INSURE (pTraits->iPixelsPerRow>0
165 && (pTraits->iBitsPerPixel==24 || pTraits->iBitsPerPixel==48));
166 g->traits = *pTraits; /* a structure copy */
167 g->dwBytesPerRow = (g->traits.iPixelsPerRow*g->traits.iBitsPerPixel + 7) / 8;
171 return IP_FATAL_ERROR;
176 /*****************************************************************************\
178 * saturation_setXformSpec - Provides xform-specific information
180 \*****************************************************************************/
182 static WORD saturation_setXformSpec (
183 IP_XFORM_HANDLE hXform, /* in: handle for xform */
184 DWORD_OR_PVOID aXformInfo[]) /* in: xform information */
188 HANDLE_TO_PTR (hXform, g);
189 g->dwSatFac = aXformInfo[IP_SATURATION_FACTOR].dword;
193 return IP_FATAL_ERROR;
198 /*****************************************************************************\
200 * saturation_getHeaderBufSize- Returns size of input buf needed to hold header
202 \*****************************************************************************/
204 static WORD saturation_getHeaderBufSize (
205 IP_XFORM_HANDLE hXform, /* in: handle for xform */
206 DWORD *pdwInBufLen) /* out: buf size for parsing header */
208 /* since input is raw pixels, there is no header, so set it to zero */
215 /*****************************************************************************\
217 * saturation_getActualTraits - Parses header, and returns input & output traits
219 \*****************************************************************************/
221 static WORD saturation_getActualTraits (
222 IP_XFORM_HANDLE hXform, /* in: handle for xform */
223 DWORD dwInputAvail, /* in: # avail bytes in input buf */
224 PBYTE pbInputBuf, /* in: ptr to input buffer */
225 PDWORD pdwInputUsed, /* out: # bytes used from input buf */
226 PDWORD pdwInputNextPos,/* out: file-pos to read from next */
227 PIP_IMAGE_TRAITS pIntraits, /* out: input image traits */
228 PIP_IMAGE_TRAITS pOutTraits) /* out: output image traits */
232 HANDLE_TO_PTR (hXform, g);
234 /* Since there is no header, we'll report no usage of input */
236 *pdwInputNextPos = 0;
238 *pIntraits = g->traits; /* structure copies */
239 *pOutTraits = g->traits;
241 return IP_DONE | IP_READY_FOR_DATA;
244 return IP_FATAL_ERROR;
249 /****************************************************************************\
251 * saturation_getActualBufSizes - Returns buf sizes needed for remainder of job
253 \****************************************************************************/
255 static WORD saturation_getActualBufSizes (
256 IP_XFORM_HANDLE hXform, /* in: handle for xform */
257 PDWORD pdwMinInBufLen, /* out: min input buf size */
258 PDWORD pdwMinOutBufLen) /* out: min output buf size */
262 HANDLE_TO_PTR (hXform, g);
264 *pdwMinInBufLen = *pdwMinOutBufLen = g->dwBytesPerRow;
268 return IP_FATAL_ERROR;
273 /*****************************************************************************\
275 * saturation_convert - Converts one row
277 \*****************************************************************************/
279 static WORD saturation_convert (
280 IP_XFORM_HANDLE hXform,
281 DWORD dwInputAvail, /* in: # avail bytes in in-buf */
282 PBYTE pbInputBuf, /* in: ptr to in-buffer */
283 PDWORD pdwInputUsed, /* out: # bytes used from in-buf */
284 PDWORD pdwInputNextPos, /* out: file-pos to read from next */
285 DWORD dwOutputAvail, /* in: # avail bytes in out-buf */
286 PBYTE pbOutputBuf, /* in: ptr to out-buffer */
287 PDWORD pdwOutputUsed, /* out: # bytes written in out-buf */
288 PDWORD pdwOutputThisPos) /* out: file-pos to write the data */
292 PBYTE pIn, pOut, pOutAfter;
295 HANDLE_TO_PTR (hXform, g);
297 /**** Check if we were told to flush ****/
299 if (pbInputBuf == NULL) {
300 PRINT (_T("saturation_convert: Told to flush.\n"), 0, 0);
301 *pdwInputUsed = *pdwOutputUsed = 0;
302 *pdwInputNextPos = g->dwInNextPos;
303 *pdwOutputThisPos = g->dwOutNextPos;
307 /**** Output a Row ****/
309 nBytes = g->dwBytesPerRow;
310 INSURE (dwInputAvail >= (DWORD)nBytes );
311 INSURE (dwOutputAvail >= (DWORD)nBytes);
315 pOutAfter = pOut + nBytes;
317 if (g->traits.iBitsPerPixel == 24) {
318 /* 24-bit color in RGB */
320 while (pOut < pOutAfter) {
325 l = NTSC_LUMINANCE (rv,gv,bv);
327 rv = l + (((rv-l)*(int)g->dwSatFac + (1<<7)) >> 8);
328 gv = l + (((gv-l)*(int)g->dwSatFac + (1<<7)) >> 8);
329 bv = l + (((bv-l)*(int)g->dwSatFac + (1<<7)) >> 8);
331 if (rv > 255) rv = 255; else if (rv < 0) rv = 0;
332 if (gv > 255) gv = 255; else if (gv < 0) gv = 0;
333 if (bv > 255) bv = 255; else if (bv < 0) bv = 0;
339 } else { /* 48 bits/pixel */
340 PWORD src = (PWORD)pIn;
341 PWORD dst = (PWORD)pOut;
342 PWORD dstAfter = (PWORD)pOutAfter;
344 while (dst < dstAfter) {
345 rv = (unsigned)(*src++);
346 gv = (unsigned)(*src++);
347 bv = (unsigned)(*src++);
349 l = NTSC_LUMINANCE (rv,gv,bv);
351 rv = l + (((rv-l)*(int)g->dwSatFac + (1<<7)) >> 8);
352 gv = l + (((gv-l)*(int)g->dwSatFac + (1<<7)) >> 8);
353 bv = l + (((bv-l)*(int)g->dwSatFac + (1<<7)) >> 8);
355 if (rv > 65535) rv = 65535; else if (rv < 0) rv = 0;
356 if (gv > 65535) gv = 65535; else if (gv < 0) gv = 0;
357 if (bv > 65535) bv = 65535; else if (bv < 0) bv = 0;
365 *pdwInputUsed = nBytes;
366 g->dwInNextPos += nBytes;
367 *pdwInputNextPos = g->dwInNextPos;
369 *pdwOutputUsed = nBytes;
370 *pdwOutputThisPos = g->dwOutNextPos;
371 g->dwOutNextPos += nBytes;
375 return IP_CONSUMED_ROW | IP_PRODUCED_ROW | IP_READY_FOR_DATA;
378 return IP_FATAL_ERROR;
383 /*****************************************************************************\
385 * saturation_insertedData - client inserted into our output stream
387 \*****************************************************************************/
389 static WORD saturation_insertedData (
390 IP_XFORM_HANDLE hXform,
394 return IP_FATAL_ERROR; /* must never be called (can't insert data) */
399 /*****************************************************************************\
401 * saturation_newPage - Tells us to flush this page, and start a new page
403 \*****************************************************************************/
405 static WORD saturation_newPage (
406 IP_XFORM_HANDLE hXform)
410 HANDLE_TO_PTR (hXform, g);
411 /* todo: return fatal error if convert is called again? */
412 return IP_DONE; /* can't insert page-breaks, so ignore this call */
415 return IP_FATAL_ERROR;
421 /*****************************************************************************\
423 * saturation_closeXform - Destroys this instance
425 \*****************************************************************************/
427 static WORD saturation_closeXform (IP_XFORM_HANDLE hXform)
431 HANDLE_TO_PTR (hXform, g);
434 IP_MEM_FREE (g); /* free memory for the instance */
439 return IP_FATAL_ERROR;
444 /*****************************************************************************\
446 * saturationTbl - Jump-table for transform driver
448 \*****************************************************************************/
450 IP_XFORM_TBL saturationTbl = {
451 saturation_openXform,
452 saturation_setDefaultInputTraits,
453 saturation_setXformSpec,
454 saturation_getHeaderBufSize,
455 saturation_getActualTraits,
456 saturation_getActualBufSizes,
459 saturation_insertedData,
460 saturation_closeXform