Tizen 2.1 base
[platform/upstream/hplip.git] / ip / xsaturation.c
1 /* libhpojip -- HP OfficeJet image-processing library. */
2
3 /* Copyright (C) 1995-2002 Hewlett-Packard Company
4  *
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.
9  *
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.
14  *
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,
18  * MA 02111-1307, USA.
19  *
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.
30  */
31
32 /* Original author: Mark Overton and others.
33  *
34  * Ported to Linux by David Paschal.
35  */
36
37 /******************************************************************************\
38  *
39  * xsaturation.c - Changes the saturation of color data
40  *
41  ******************************************************************************
42  *
43  * Name of Global Jump-Table:
44  *
45  *    saturationTbl
46  *
47  * Items in aXformInfo array passed into setXformSpec:
48  *
49  *    aXformInfo[IP_SATURATION_FACTOR] = saturation factor, in 24.8 fixed point (8 bits of frac)
50  *
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.
54  *
55  * Capabilities and Limitations:
56  *
57  *    The incoming data can be 24-bit color or 48-bit color.
58  *    The pixels are assumed to be RGB.
59  *
60  * Default Input Traits, and Output Traits:
61  *
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
72  *
73  *    Above, a "*" by an item indicates it must be valid (not negative).
74  *
75  * Feb 2000 Mark Overton -- wrote original code
76  *
77 \******************************************************************************/
78
79 #include "hpip.h"
80 #include "ipdefs.h"
81 #include "string.h"    /* for memset and memcpy */
82
83
84 #if 0
85     #include "stdio.h"
86     #include <tchar.h>
87
88     #define PRINT(msg,arg1,arg2) \
89         _ftprintf(stderr, msg, (int)arg1, (int)arg2)
90 #else
91     #define PRINT(msg,arg1,arg2)
92 #endif
93
94 #define CHECK_VALUE 0x4ba1dace
95
96
97 typedef struct {
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;
106
107
108
109 /*****************************************************************************\
110  *
111  * saturation_openXform - Creates a new instance of the transformer
112  *
113  *****************************************************************************
114  *
115  * This returns a handle for the new instance to be passed into
116  * all subsequent calls.
117  *
118  * Return value: IP_DONE=success; IP_FATAL_ERROR=misc error.
119  *
120 \*****************************************************************************/
121
122 static WORD saturation_openXform (
123     IP_XFORM_HANDLE *pXform)   /* out: returned handle */
124 {
125     PSAT_INST g;
126
127     INSURE (pXform != NULL);
128     IP_MEM_ALLOC (sizeof(SAT_INST), g);
129     *pXform = g;
130     memset (g, 0, sizeof(SAT_INST));
131     g->dwValidChk = CHECK_VALUE;
132     return IP_DONE;
133
134     fatal_error:
135     return IP_FATAL_ERROR;
136 }
137
138
139
140 /*****************************************************************************\
141  *
142  * saturation_setDefaultInputTraits - Specifies default input image traits
143  *
144  *****************************************************************************
145  *
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
149  * this routine.
150  *
151  * Return value: IP_DONE=success; IP_FATAL_ERROR=misc error.
152  *
153 \*****************************************************************************/
154
155 static WORD saturation_setDefaultInputTraits (
156     IP_XFORM_HANDLE  hXform,     /* in: handle for xform */
157     PIP_IMAGE_TRAITS pTraits)    /* in: default image traits */
158 {
159     PSAT_INST g;
160
161     HANDLE_TO_PTR (hXform, g);
162
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;
168     return IP_DONE;
169
170     fatal_error:
171     return IP_FATAL_ERROR;
172 }
173
174
175
176 /*****************************************************************************\
177  *
178  * saturation_setXformSpec - Provides xform-specific information
179  *
180 \*****************************************************************************/
181
182 static WORD saturation_setXformSpec (
183     IP_XFORM_HANDLE hXform,         /* in: handle for xform */
184     DWORD_OR_PVOID  aXformInfo[])   /* in: xform information */
185 {
186     PSAT_INST g;
187
188     HANDLE_TO_PTR (hXform, g);
189     g->dwSatFac = aXformInfo[IP_SATURATION_FACTOR].dword;
190     return IP_DONE;
191
192     fatal_error:
193     return IP_FATAL_ERROR;
194 }
195
196
197
198 /*****************************************************************************\
199  *
200  * saturation_getHeaderBufSize- Returns size of input buf needed to hold header
201  *
202 \*****************************************************************************/
203
204 static WORD saturation_getHeaderBufSize (
205     IP_XFORM_HANDLE  hXform,         /* in:  handle for xform */
206     DWORD           *pdwInBufLen)    /* out: buf size for parsing header */
207 {
208     /* since input is raw pixels, there is no header, so set it to zero */
209     *pdwInBufLen = 0;
210     return IP_DONE;
211 }
212
213
214
215 /*****************************************************************************\
216  *
217  * saturation_getActualTraits - Parses header, and returns input & output traits
218  *
219 \*****************************************************************************/
220
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 */
229 {
230     PSAT_INST g;
231
232     HANDLE_TO_PTR (hXform, g);
233
234     /* Since there is no header, we'll report no usage of input */
235     *pdwInputUsed    = 0;
236     *pdwInputNextPos = 0;
237
238     *pIntraits  = g->traits;   /* structure copies */
239     *pOutTraits = g->traits;
240
241     return IP_DONE | IP_READY_FOR_DATA;
242
243     fatal_error:
244     return IP_FATAL_ERROR;
245 }
246
247
248
249 /****************************************************************************\
250  *
251  * saturation_getActualBufSizes - Returns buf sizes needed for remainder of job
252  *
253 \****************************************************************************/
254
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 */
259 {
260     PSAT_INST g;
261
262     HANDLE_TO_PTR (hXform, g);
263
264     *pdwMinInBufLen = *pdwMinOutBufLen = g->dwBytesPerRow;
265     return IP_DONE;
266
267     fatal_error:
268     return IP_FATAL_ERROR;
269 }
270
271
272
273 /*****************************************************************************\
274  *
275  * saturation_convert - Converts one row
276  *
277 \*****************************************************************************/
278
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 */
289 {
290     PSAT_INST g;
291     int       nBytes;
292     PBYTE     pIn, pOut, pOutAfter;
293     int       l, rv, gv, bv;
294
295     HANDLE_TO_PTR (hXform, g);
296
297     /**** Check if we were told to flush ****/
298
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;
304         return IP_DONE;
305     }
306
307     /**** Output a Row ****/
308
309     nBytes = g->dwBytesPerRow;
310     INSURE (dwInputAvail  >= (DWORD)nBytes );
311     INSURE (dwOutputAvail >= (DWORD)nBytes);
312
313     pIn  = pbInputBuf;
314     pOut = pbOutputBuf;
315     pOutAfter = pOut + nBytes;
316
317     if (g->traits.iBitsPerPixel == 24) {
318         /* 24-bit color in RGB */
319
320         while (pOut < pOutAfter) {
321             rv = *pIn++;
322             gv = *pIn++;
323             bv = *pIn++;
324
325             l = NTSC_LUMINANCE (rv,gv,bv);
326
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);
330
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;
334
335             *pOut++ = (BYTE)rv;
336             *pOut++ = (BYTE)gv;
337             *pOut++ = (BYTE)bv;
338         }
339     } else {   /* 48 bits/pixel */
340         PWORD src      = (PWORD)pIn;
341         PWORD dst      = (PWORD)pOut;
342         PWORD dstAfter = (PWORD)pOutAfter;
343
344         while (dst < dstAfter) {
345             rv = (unsigned)(*src++);
346             gv = (unsigned)(*src++);
347             bv = (unsigned)(*src++);
348
349             l = NTSC_LUMINANCE (rv,gv,bv);
350
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);
354
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;
358
359             *dst++ = (WORD)rv;
360             *dst++ = (WORD)gv;
361             *dst++ = (WORD)bv;
362         }
363     }
364
365     *pdwInputUsed     = nBytes;
366     g->dwInNextPos   += nBytes;
367     *pdwInputNextPos  = g->dwInNextPos;
368
369     *pdwOutputUsed    = nBytes;
370     *pdwOutputThisPos = g->dwOutNextPos;
371     g->dwOutNextPos  += nBytes;
372
373     g->dwRowsDone += 1;
374
375     return IP_CONSUMED_ROW | IP_PRODUCED_ROW | IP_READY_FOR_DATA;
376
377     fatal_error:
378     return IP_FATAL_ERROR;
379 }
380
381
382
383 /*****************************************************************************\
384  *
385  * saturation_insertedData - client inserted into our output stream
386  *
387 \*****************************************************************************/
388
389 static WORD saturation_insertedData (
390     IP_XFORM_HANDLE hXform,
391     DWORD           dwNumBytes)
392 {
393     fatalBreakPoint ();
394     return IP_FATAL_ERROR;   /* must never be called (can't insert data) */
395 }
396
397
398
399 /*****************************************************************************\
400  *
401  * saturation_newPage - Tells us to flush this page, and start a new page
402  *
403 \*****************************************************************************/
404
405 static WORD saturation_newPage (
406     IP_XFORM_HANDLE hXform)
407 {
408     PSAT_INST g;
409
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 */
413
414     fatal_error:
415     return IP_FATAL_ERROR;
416
417 }
418
419
420
421 /*****************************************************************************\
422  *
423  * saturation_closeXform - Destroys this instance
424  *
425 \*****************************************************************************/
426
427 static WORD saturation_closeXform (IP_XFORM_HANDLE hXform)
428 {
429     PSAT_INST g;
430
431     HANDLE_TO_PTR (hXform, g);
432
433     g->dwValidChk = 0;
434     IP_MEM_FREE (g);       /* free memory for the instance */
435
436     return IP_DONE;
437
438     fatal_error:
439     return IP_FATAL_ERROR;
440 }
441
442
443
444 /*****************************************************************************\
445  *
446  * saturationTbl - Jump-table for transform driver
447  *
448 \*****************************************************************************/
449
450 IP_XFORM_TBL saturationTbl = {
451     saturation_openXform,
452     saturation_setDefaultInputTraits,
453     saturation_setXformSpec,
454     saturation_getHeaderBufSize,
455     saturation_getActualTraits,
456     saturation_getActualBufSizes,
457     saturation_convert,
458     saturation_newPage,
459     saturation_insertedData,
460     saturation_closeXform
461 };
462
463 /* End of File */