Tizen 2.1 base
[platform/upstream/hplip.git] / ip / xyxtract.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  * xyxtract.c - Y-extract - Extracts Y-component from YCC color data
40  *
41  ******************************************************************************
42  *
43  * Name of Global Jump-Table:
44  *
45  *    yXtractTbl
46  *
47  * Items in aXformInfo array passed into setXformSpec:
48  *
49  *    xXformInfo[IP_Y_EXTRACT_COLOR_SPACE] tells us something about the color-space
50  *       of input data:  See the enum IP_Y_EXTRACT_WHICH_SPACE:
51  *       IP_Y_EXTRACT_LUM_CHROME = luminance-chrominance, we merely fetch 1st component,
52  *       IP_Y_EXTRACT_RGB        = input is RGB,
53  *       IP_Y_EXTRACT_BGR        = input is BGR.
54  *
55  * Capabilities and Limitations:
56  *
57  *    Inputs rows of 24-bit color data, and outputs rows of 8-bit gray
58  *    consisting of the first component of the color data.
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         * must be 24           8
66  *    iComponentsPerPixel   * must be 3            1
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  * Jan  1998 Mark Overton -- wrote 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 0x1ce5ca7e
95
96 typedef struct {
97     IP_IMAGE_TRAITS inTraits; /* traits of the input image */
98     IP_Y_EXTRACT_WHICH_SPACE eInputType;  /* type of input data */
99     DWORD    dwRowsDone;      /* number of rows converted so far */
100     DWORD    dwInNextPos;     /* file pos for subsequent input */
101     DWORD    dwOutNextPos;    /* file pos for subsequent output */
102     DWORD    dwValidChk;      /* struct validity check value */
103 } YEX_INST, *PYEX_INST;
104
105
106
107 /*****************************************************************************\
108  *
109  * yXtract_openXform - Creates a new instance of the transformer
110  *
111  *****************************************************************************
112  *
113  * This returns a handle for the new instance to be passed into
114  * all subsequent calls.
115  *
116  * Return value: IP_DONE=success; IP_FATAL_ERROR=misc error.
117  *
118 \*****************************************************************************/
119
120 static WORD yXtract_openXform (
121     IP_XFORM_HANDLE *pXform)   /* out: returned handle */
122 {
123     PYEX_INST g;
124
125     INSURE (pXform != NULL);
126     IP_MEM_ALLOC (sizeof(YEX_INST), g);
127     *pXform = g;
128     memset (g, 0, sizeof(YEX_INST));
129     g->dwValidChk = CHECK_VALUE;
130     return IP_DONE;
131
132     fatal_error:
133     return IP_FATAL_ERROR;
134 }
135
136
137
138 /*****************************************************************************\
139  *
140  * yXtract_setDefaultInputTraits - Specifies default input image traits
141  *
142  *****************************************************************************
143  *
144  * The header of the file-type handled by the transform probably does
145  * not include *all* the image traits we'd like to know.  Those not
146  * specified in the file-header are filled in from info provided by
147  * this routine.
148  *
149  * Return value: IP_DONE=success; IP_FATAL_ERROR=misc error.
150  *
151 \*****************************************************************************/
152
153 static WORD yXtract_setDefaultInputTraits (
154     IP_XFORM_HANDLE  hXform,     /* in: handle for xform */
155     PIP_IMAGE_TRAITS pTraits)    /* in: default image traits */
156 {
157     PYEX_INST g;
158
159     HANDLE_TO_PTR (hXform, g);
160
161     /* Insure that values we care about are correct */
162     INSURE (pTraits->iBitsPerPixel == 24);
163     INSURE (pTraits->iComponentsPerPixel == 3);
164     INSURE (pTraits->iPixelsPerRow > 0);
165
166     g->inTraits = *pTraits;   /* a structure copy */
167     return IP_DONE;
168
169     fatal_error:
170     return IP_FATAL_ERROR;
171 }
172
173
174
175 /*****************************************************************************\
176  *
177  * yXtract_setXformSpec - Provides xform-specific information
178  *
179 \*****************************************************************************/
180
181 static WORD yXtract_setXformSpec (
182     IP_XFORM_HANDLE hXform,         /* in: handle for xform */
183     DWORD_OR_PVOID  aXformInfo[])   /* in: xform information */
184 {
185     PYEX_INST g;
186     HANDLE_TO_PTR (hXform, g);
187     g->eInputType = (IP_Y_EXTRACT_WHICH_SPACE)aXformInfo[IP_Y_EXTRACT_COLOR_SPACE].dword;
188     return IP_DONE;
189
190     fatal_error:
191     return IP_FATAL_ERROR;
192 }
193
194
195
196 /*****************************************************************************\
197  *
198  * yXtract_getHeaderBufSize- Returns size of input buf needed to hold header
199  *
200 \*****************************************************************************/
201
202 static WORD yXtract_getHeaderBufSize (
203     IP_XFORM_HANDLE  hXform,         /* in:  handle for xform */
204     DWORD           *pdwInBufLen)    /* out: buf size for parsing header */
205 {
206     /* since input is raw pixels, there is no header, so set it to zero */
207     *pdwInBufLen = 0;
208     return IP_DONE;
209 }
210
211
212
213 /*****************************************************************************\
214  *
215  * yXtract_getActualTraits - Parses header, and returns input & output traits
216  *
217 \*****************************************************************************/
218
219 static WORD yXtract_getActualTraits (
220     IP_XFORM_HANDLE  hXform,         /* in:  handle for xform */
221     DWORD            dwInputAvail,   /* in:  # avail bytes in input buf */
222     PBYTE            pbInputBuf,     /* in:  ptr to input buffer */
223     PDWORD           pdwInputUsed,   /* out: # bytes used from input buf */
224     PDWORD           pdwInputNextPos,/* out: file-pos to read from next */
225     PIP_IMAGE_TRAITS pInTraits,      /* out: input image traits */
226     PIP_IMAGE_TRAITS pOutTraits)     /* out: output image traits */
227 {
228     PYEX_INST g;
229
230     HANDLE_TO_PTR (hXform, g);
231
232     /* Since there is no header, we'll report no usage of input */
233     *pdwInputUsed    = 0;
234     *pdwInputNextPos = 0;
235
236     *pInTraits  = g->inTraits;
237     *pOutTraits = g->inTraits;
238     pOutTraits->iBitsPerPixel = 8;
239     pOutTraits->iComponentsPerPixel = 1;
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  * yXtract_getActualBufSizes - Returns buf sizes needed for remainder of job
252  *
253 \****************************************************************************/
254
255 static WORD yXtract_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     PYEX_INST g;
261
262     HANDLE_TO_PTR (hXform, g);
263     *pdwMinInBufLen  = 3 * g->inTraits.iPixelsPerRow;
264     *pdwMinOutBufLen =     g->inTraits.iPixelsPerRow;
265
266     return IP_DONE;
267
268     fatal_error:
269     return IP_FATAL_ERROR;
270 }
271
272
273
274 /*****************************************************************************\
275  *
276  * yXtract_convert - Converts one row
277  *
278 \*****************************************************************************/
279
280 static WORD yXtract_convert (
281     IP_XFORM_HANDLE hXform,
282     DWORD           dwInputAvail,     /* in:  # avail bytes in in-buf */
283     PBYTE           pbInputBuf,       /* in:  ptr to in-buffer */
284     PDWORD          pdwInputUsed,     /* out: # bytes used from in-buf */
285     PDWORD          pdwInputNextPos,  /* out: file-pos to read from next */
286     DWORD           dwOutputAvail,    /* in:  # avail bytes in out-buf */
287     PBYTE           pbOutputBuf,      /* in:  ptr to out-buffer */
288     PDWORD          pdwOutputUsed,    /* out: # bytes written in out-buf */
289     PDWORD          pdwOutputThisPos) /* out: file-pos to write the data */
290 {
291     PYEX_INST g;
292     int       inBytes, outBytes;
293     PBYTE     pIn, pOut, pOutAfter;
294     UINT      red, grn, blu;
295
296     HANDLE_TO_PTR (hXform, g);
297
298     /**** Check if we were told to flush ****/
299
300     if (pbInputBuf == NULL) {
301         PRINT (_T("yXtract_convert: Told to flush.\n"), 0, 0);
302         *pdwInputUsed = *pdwOutputUsed = 0;
303         *pdwInputNextPos  = g->dwInNextPos;
304         *pdwOutputThisPos = g->dwOutNextPos;
305         return IP_DONE;
306     }
307
308     /**** Output a Row ****/
309
310     outBytes = g->inTraits.iPixelsPerRow;
311     inBytes  = 3 * outBytes;
312     INSURE (dwInputAvail  >= (DWORD)inBytes );
313     INSURE (dwOutputAvail >= (DWORD)outBytes);
314
315     pIn  = pbInputBuf;
316     pOut = pbOutputBuf;
317     pOutAfter = pOut + outBytes;
318
319     switch (g->eInputType) {
320         case IP_Y_EXTRACT_LUM_CHROME:
321             while (pOut < pOutAfter) {
322                 *pOut++ = *pIn;
323                 pIn  += 3;
324             }
325             break;
326
327         case IP_Y_EXTRACT_RGB:
328             while (pOut < pOutAfter) {
329                 red = (UINT)(*pIn++);
330                 grn = (UINT)(*pIn++);
331                 blu = (UINT)(*pIn++);
332                 /* the formula below is:  Y = (5*R + 9*G + 2*B) / 16  */
333                 *pOut++ =
334                   (BYTE)((((red<<2)+red) + ((grn<<3)+grn) + (blu<<1) + 8) >> 4);
335             }
336             break;
337
338         case IP_Y_EXTRACT_BGR:
339             while (pOut < pOutAfter) {
340                 blu = (UINT)(*pIn++);
341                 grn = (UINT)(*pIn++);
342                 red = (UINT)(*pIn++);
343                 /* the formula below is:  Y = (5*R + 9*G + 2*B) / 16  */
344                 *pOut++ =
345                   (BYTE)((((red<<2)+red) + ((grn<<3)+grn) + (blu<<1) + 8) >> 4);
346             }
347             break;
348
349         default:
350             goto fatal_error;
351     }
352
353     *pdwInputUsed     = inBytes;
354     g->dwInNextPos   += inBytes;
355     *pdwInputNextPos  = g->dwInNextPos;
356
357     *pdwOutputUsed    = outBytes;
358     *pdwOutputThisPos = g->dwOutNextPos;
359     g->dwOutNextPos  += outBytes;
360
361     g->dwRowsDone += 1;
362
363     return IP_CONSUMED_ROW | IP_PRODUCED_ROW | IP_READY_FOR_DATA;
364
365     fatal_error:
366     return IP_FATAL_ERROR;
367 }
368
369
370
371 /*****************************************************************************\
372  *
373  * yXtract_insertedData - client inserted into our output stream
374  *
375 \*****************************************************************************/
376
377 static WORD yXtract_insertedData (
378     IP_XFORM_HANDLE hXform,
379     DWORD           dwNumBytes)
380 {
381     fatalBreakPoint ();
382     return IP_FATAL_ERROR;   /* must never be called (can't insert data) */
383 }
384
385
386
387 /*****************************************************************************\
388  *
389  * yXtract_newPage - Tells us to flush this page, and start a new page
390  *
391 \*****************************************************************************/
392
393 static WORD yXtract_newPage (
394     IP_XFORM_HANDLE hXform)
395 {
396     PYEX_INST g;
397
398     HANDLE_TO_PTR (hXform, g);
399     /* todo: return fatal error if convert is called again? */
400     return IP_DONE;   /* can't insert page-breaks, so ignore this call */
401
402     fatal_error:
403     return IP_FATAL_ERROR;
404
405 }
406
407
408
409 /*****************************************************************************\
410  *
411  * yXtract_closeXform - Destroys this instance
412  *
413 \*****************************************************************************/
414
415 static WORD yXtract_closeXform (IP_XFORM_HANDLE hXform)
416 {
417     PYEX_INST g;
418
419     HANDLE_TO_PTR (hXform, g);
420
421     g->dwValidChk = 0;
422     IP_MEM_FREE (g);       /* free memory for the instance */
423
424     return IP_DONE;
425
426     fatal_error:
427     return IP_FATAL_ERROR;
428 }
429
430
431
432 /*****************************************************************************\
433  *
434  * yXtractTbl - Jump-table for encoder
435  *
436 \*****************************************************************************/
437
438 IP_XFORM_TBL yXtractTbl = {
439     yXtract_openXform,
440     yXtract_setDefaultInputTraits,
441     yXtract_setXformSpec,
442     yXtract_getHeaderBufSize,
443     yXtract_getActualTraits,
444     yXtract_getActualBufSizes,
445     yXtract_convert,
446     yXtract_newPage,
447     yXtract_insertedData,
448     yXtract_closeXform
449 };
450
451 /* End of File */