Tizen 2.1 base
[platform/upstream/hplip.git] / ip / xbi2gray.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  * xbi2gray.c - Converts bilevel into gray (8-bit gray or 24-bit gray)
40  *
41  ******************************************************************************
42  *
43  * Name of Global Jump-Table:
44  *
45  *    yBi2GrayTbl
46  *
47  * Items in aXformInfo array passed into setXformSpec:
48  *
49  *    aXformInfo[IP_BI_2_GRAY_OUTPUT_BPP] = format of output:
50  *          8  = output 8-bit gray,
51  *          24 = output 24-bit gray.
52  *    aXformInfo[IP_BI_2_GRAY_WHITE_PIXEL] =
53  *            an RGBQUAD representing a white output pixel.
54  *    aXformInfo[IP_BI_2_GRAY_BLACK_PIXEL] =
55  *            an RGBQUAD representing a black output pixel.
56  *
57  *    Each bilevel pixel is output as a full white or full black pixel.
58  *    This xform needs to know what values to use for those white and
59  *    black output pixels.  Hence the two RGBQUAD items above.
60  *    For 8-bit gray output, only the rgbRed field is used in each.
61  *
62  * Capabilities and Limitations:
63  *
64  *    Translates each white or black bilevel input pixel into an 8-bit
65  *      or 24-bit output white or black output pixel.
66  *
67  * Default Input Traits, and Output Traits:
68  *
69  *          trait             default input             output
70  *    -------------------  ---------------------  ------------------------
71  *    iPixelsPerRow         * passed into output   same as default input
72  *    iBitsPerPixel         * must be 1            8 or 24
73  *    iComponentsPerPixel   * must be 1            1 or 3
74  *    lHorizDPI               passed into output   same as default input
75  *    lVertDPI                passed into output   same as default input
76  *    lNumRows                passed into output   same as default input
77  *    iNumPages               passed into output   same as default input
78  *    iPageNum                passed into output   same as default input
79  *
80  *    Above, a "*" by an item indicates it must be valid (not negative).
81  *
82  * Mar 1998 Mark Overton -- wrote code
83  *
84 \******************************************************************************/
85
86 #include "hpip.h"
87 #include "ipdefs.h"
88 #include "string.h"    /* for memset and memcpy */
89
90
91 #if 0
92     #include "stdio.h"
93     #include <tchar.h>
94
95     #define PRINT(msg,arg1,arg2) \
96         _ftprintf(stderr, msg, (int)arg1, (int)arg2)
97 #else
98     #define PRINT(msg,arg1,arg2)
99 #endif
100
101 #define CHECK_VALUE 0x1ce5ca7e
102
103 typedef struct {
104     IP_IMAGE_TRAITS inTraits;  /* traits of the input image */
105     UINT     uRowsDone;        /* number of rows converted so far */
106     WORD     wOutBitsPerPixel; /* bits/pixel to output (8 or 24) */
107     RGBQUAD  rgbWhite;         /* value of an output white */
108     RGBQUAD  rgbBlack;         /* value of an output black */
109     DWORD    dwInRowBytes;     /* # bytes per input row */
110     DWORD    dwOutRowBytes;    /* # bytes per output row */
111     DWORD    dwInNextPos;      /* file pos for subsequent input */
112     DWORD    dwOutNextPos;     /* file pos for subsequent output */
113     DWORD    dwValidChk;       /* struct validity check value */
114 } B2G_INST, *PB2G_INST;
115
116
117
118 /*****************************************************************************\
119  *
120  * bi2gray_openXform - Creates a new instance of the transformer
121  *
122  *****************************************************************************
123  *
124  * This returns a handle for the new instance to be passed into
125  * all subsequent calls.
126  *
127  * Return value: IP_DONE=success; IP_FATAL_ERROR=misc error.
128  *
129 \*****************************************************************************/
130
131 static WORD bi2gray_openXform (
132     IP_XFORM_HANDLE *pXform)   /* out: returned handle */
133 {
134     PB2G_INST g;
135
136     INSURE (pXform != NULL);
137     IP_MEM_ALLOC (sizeof(B2G_INST), g);
138     *pXform = g;
139     memset (g, 0, sizeof(B2G_INST));
140     g->dwValidChk = CHECK_VALUE;
141     return IP_DONE;
142
143     fatal_error:
144     return IP_FATAL_ERROR;
145 }
146
147
148
149 /*****************************************************************************\
150  *
151  * bi2gray_setDefaultInputTraits - Specifies default input image traits
152  *
153  *****************************************************************************
154  *
155  * The header of the file-type handled by the transform probably does
156  * not include *all* the image traits we'd like to know.  Those not
157  * specified in the file-header are filled in from info provided by
158  * this routine.
159  *
160  * Return value: IP_DONE=success; IP_FATAL_ERROR=misc error.
161  *
162 \*****************************************************************************/
163
164 static WORD bi2gray_setDefaultInputTraits (
165     IP_XFORM_HANDLE  hXform,     /* in: handle for xform */
166     PIP_IMAGE_TRAITS pTraits)    /* in: default image traits */
167 {
168     PB2G_INST g;
169
170     HANDLE_TO_PTR (hXform, g);
171
172     /* Insure that values we care about are correct */
173     INSURE (pTraits->iBitsPerPixel == 1);
174     INSURE (pTraits->iComponentsPerPixel == 1);
175     INSURE (pTraits->iPixelsPerRow > 0);
176
177     g->inTraits = *pTraits;   /* a structure copy */
178     return IP_DONE;
179
180     fatal_error:
181     return IP_FATAL_ERROR;
182 }
183
184
185
186 /*****************************************************************************\
187  *
188  * bi2gray_setXformSpec - Provides xform-specific information
189  *
190 \*****************************************************************************/
191
192 static WORD bi2gray_setXformSpec (
193     IP_XFORM_HANDLE hXform,         /* in: handle for xform */
194     DWORD_OR_PVOID  aXformInfo[])   /* in: xform information */
195 {
196     PB2G_INST g;
197     UINT      nBits;
198
199     HANDLE_TO_PTR (hXform, g);
200     nBits = aXformInfo[IP_BI_2_GRAY_OUTPUT_BPP].dword;
201     INSURE (nBits==8 || nBits==24);
202     g->wOutBitsPerPixel = (WORD)nBits;
203     g->rgbWhite = aXformInfo[IP_BI_2_GRAY_WHITE_PIXEL].rgbquad;
204     g->rgbBlack = aXformInfo[IP_BI_2_GRAY_BLACK_PIXEL].rgbquad;
205     return IP_DONE;
206
207     fatal_error:
208     return IP_FATAL_ERROR;
209 }
210
211
212
213 /*****************************************************************************\
214  *
215  * bi2gray_getHeaderBufSize- Returns size of input buf needed to hold header
216  *
217 \*****************************************************************************/
218
219 static WORD bi2gray_getHeaderBufSize (
220     IP_XFORM_HANDLE  hXform,         /* in:  handle for xform */
221     DWORD           *pdwInBufLen)    /* out: buf size for parsing header */
222 {
223     /* since input is raw pixels, there is no header, so set it to zero */
224     *pdwInBufLen = 0;
225     return IP_DONE;
226 }
227
228
229
230 /*****************************************************************************\
231  *
232  * bi2gray_getActualTraits - Parses header, and returns input & output traits
233  *
234 \*****************************************************************************/
235
236 static WORD bi2gray_getActualTraits (
237     IP_XFORM_HANDLE  hXform,         /* in:  handle for xform */
238     DWORD            dwInputAvail,   /* in:  # avail bytes in input buf */
239     PBYTE            pbInputBuf,     /* in:  ptr to input buffer */
240     PDWORD           pdwInputUsed,   /* out: # bytes used from input buf */
241     PDWORD           pdwInputNextPos,/* out: file-pos to read from next */
242     PIP_IMAGE_TRAITS pInTraits,      /* out: input image traits */
243     PIP_IMAGE_TRAITS pOutTraits)     /* out: output image traits */
244 {
245     PB2G_INST g;
246
247     HANDLE_TO_PTR (hXform, g);
248
249     /* Since there is no header, we'll report no usage of input */
250     *pdwInputUsed    = 0;
251     *pdwInputNextPos = 0;
252
253     *pInTraits  = g->inTraits;   /* structure copies */
254     *pOutTraits = g->inTraits;
255     pOutTraits->iBitsPerPixel       = g->wOutBitsPerPixel;
256     pOutTraits->iComponentsPerPixel = g->wOutBitsPerPixel==8 ? 1 : 3;
257
258     g->dwInRowBytes  = (g->inTraits.iPixelsPerRow+7) / 8;
259     g->dwOutRowBytes = g->inTraits.iPixelsPerRow * pOutTraits->iComponentsPerPixel;
260
261     return IP_DONE | IP_READY_FOR_DATA;
262
263     fatal_error:
264     return IP_FATAL_ERROR;
265 }
266
267
268
269 /****************************************************************************\
270  *
271  * bi2gray_getActualBufSizes - Returns buf sizes needed for remainder of job
272  *
273 \****************************************************************************/
274
275 static WORD bi2gray_getActualBufSizes (
276     IP_XFORM_HANDLE hXform,            /* in:  handle for xform */
277     PDWORD           pdwMinInBufLen,   /* out: min input buf size */
278     PDWORD           pdwMinOutBufLen)  /* out: min output buf size */
279 {
280     PB2G_INST g;
281
282     HANDLE_TO_PTR (hXform, g);
283     *pdwMinInBufLen  = g->dwInRowBytes;
284     *pdwMinOutBufLen = g->dwOutRowBytes;
285
286     return IP_DONE;
287
288     fatal_error:
289     return IP_FATAL_ERROR;
290 }
291
292
293
294 /*****************************************************************************\
295  *
296  * bi2gray_convert - Converts one row
297  *
298 \*****************************************************************************/
299
300 static WORD bi2gray_convert (
301     IP_XFORM_HANDLE hXform,
302     DWORD           dwInputAvail,      /* in:  # avail bytes in in-buf */
303     PBYTE           pbInputBuf,        /* in:  ptr to in-buffer */
304     PDWORD          pdwInputUsed,      /* out: # bytes used from in-buf */
305     PDWORD          pdwInputNextPos,   /* out: file-pos to read from next */
306     DWORD           dwOutputAvail,     /* in:  # avail bytes in out-buf */
307     PBYTE           pbOutputBuf,       /* in:  ptr to out-buffer */
308     PDWORD          pdwOutputUsed,     /* out: # bytes written in out-buf */
309     PDWORD          pdwOutputThisPos)  /* out: file-pos to write the data */
310 {
311     PB2G_INST g;
312     PBYTE     pIn, pOut, pInAfter;
313     BYTE      bMask, bBilevel;
314
315     HANDLE_TO_PTR (hXform, g);
316
317     /**** Check if we were told to flush ****/
318
319     if (pbInputBuf == NULL) {
320         PRINT (_T("bi2gray_convert: Told to flush.\n"), 0, 0);
321         *pdwInputUsed     = *pdwOutputUsed = 0;
322         *pdwInputNextPos  = g->dwInNextPos;
323         *pdwOutputThisPos = g->dwOutNextPos;
324         return IP_DONE;
325     }
326
327     /**** Output a Row ****/
328
329     INSURE (dwInputAvail  >= g->dwInRowBytes );
330     INSURE (dwOutputAvail >= g->dwOutRowBytes);
331
332     pIn  = pbInputBuf;
333     pOut = pbOutputBuf;
334     pInAfter = pIn + g->dwInRowBytes;
335
336     while (pIn < pInAfter) {
337         bBilevel = *pIn++;
338
339         if (g->wOutBitsPerPixel == 24) {
340             for (bMask=0x80u; bMask!=0; bMask>>=1) {
341                 *(RGBQUAD*)pOut = (bMask & bBilevel)
342                              ? g->rgbBlack
343                              : g->rgbWhite;
344                 pOut += 3;
345             }
346         } else {    /* 8 bits per output pixel */
347             for (bMask=0x80u; bMask!=0; bMask>>=1) {
348                 *pOut++ = (bMask & bBilevel)
349                              ? g->rgbBlack.rgbRed
350                              : g->rgbWhite.rgbRed;
351             }
352         }
353     }
354
355     *pdwInputUsed     = g->dwInRowBytes;
356     g->dwInNextPos   += g->dwInRowBytes;
357     *pdwInputNextPos  = g->dwInNextPos;
358
359     *pdwOutputUsed    = g->dwOutRowBytes;
360     *pdwOutputThisPos = g->dwOutNextPos;
361     g->dwOutNextPos  += g->dwOutRowBytes;
362
363     g->uRowsDone += 1;
364
365     return IP_CONSUMED_ROW | IP_PRODUCED_ROW | IP_READY_FOR_DATA;
366
367     fatal_error:
368     return IP_FATAL_ERROR;
369 }
370
371
372
373 /*****************************************************************************\
374  *
375  * bi2gray_insertedData - client inserted into our output stream
376  *
377 \*****************************************************************************/
378
379 static WORD bi2gray_insertedData (
380     IP_XFORM_HANDLE hXform,
381     DWORD           dwNumBytes)
382 {
383     fatalBreakPoint ();
384     return IP_FATAL_ERROR;   /* must never be called (can't insert data) */
385 }
386
387
388
389 /*****************************************************************************\
390  *
391  * bi2gray_newPage - Tells us to flush this page, and start a new page
392  *
393 \*****************************************************************************/
394
395 static WORD bi2gray_newPage (
396     IP_XFORM_HANDLE hXform)
397 {
398     PB2G_INST g;
399
400     HANDLE_TO_PTR (hXform, g);
401     /* todo: return fatal error if convert is called again? */
402     return IP_DONE;   /* can't insert page-breaks, so ignore this call */
403
404     fatal_error:
405     return IP_FATAL_ERROR;
406
407 }
408
409
410
411 /*****************************************************************************\
412  *
413  * bi2gray_closeXform - Destroys this instance
414  *
415 \*****************************************************************************/
416
417 static WORD bi2gray_closeXform (IP_XFORM_HANDLE hXform)
418 {
419     PB2G_INST g;
420
421     HANDLE_TO_PTR (hXform, g);
422
423     g->dwValidChk = 0;
424     IP_MEM_FREE (g);       /* free memory for the instance */
425
426     return IP_DONE;
427
428     fatal_error:
429     return IP_FATAL_ERROR;
430 }
431
432
433
434 /*****************************************************************************\
435  *
436  * bi2grayTbl - Jump-table for encoder
437  *
438 \*****************************************************************************/
439
440 IP_XFORM_TBL bi2grayTbl = {
441     bi2gray_openXform,
442     bi2gray_setDefaultInputTraits,
443     bi2gray_setXformSpec,
444     bi2gray_getHeaderBufSize,
445     bi2gray_getActualTraits,
446     bi2gray_getActualBufSizes,
447     bi2gray_convert,
448     bi2gray_newPage,
449     bi2gray_insertedData,
450     bi2gray_closeXform
451 };
452
453 /* End of File */