Tizen 2.1 base
[platform/upstream/hplip.git] / ip / xjpg_fix.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: David Paschal (based on Mark Overton's "skel" template
33  * and a few bits and pieces from xjpg_{enc,dec}.c). */
34
35 /******************************************************************************\
36  *
37  * xjpg_fix.c - Fixes JPEG files to have a standard JFIF APP0 header and
38  *              a correct row-count value in the SOF header.
39  *
40  ******************************************************************************
41  *
42  * Name of Global Jump-Table:
43  *
44  *    jpgFixTbl
45  *
46  * Items in aXformInfo array passed into setXformSpec:
47  *
48  *    None.
49  *
50  * Capabilities and Limitations:
51  *
52  *    Looks at the header, and converts an OfficeJet APP1 short header to
53  *    a standard JFIF APP0 header.  Passes the resulting header and data
54  *    through to the JPEG decoder in order to count the number of rows in
55  *    the image.  Discards the decompressed data and passes the original
56  *    compressed data (possibly with modified header) to the output.  At
57  *    the end of the file, seeks back to the SOF header and rewrites the
58  *    row count field.
59  *
60  *    Able to handle JPEG files with JFIF APP0 or OfficeJet APP1 headers,
61  *    but not color-fax APP1 headers or Denali-style compression (in
62  *    these cases, you must do the full decode, any necessary color-space
63  *    conversion, and encode).
64  *
65  * Default Input Traits, and Output Traits:
66  *
67  *          trait             default input             output
68  *    -------------------  -------------------  ------------------------
69  *    iPixelsPerRow           ignored              based on header
70  *    iBitsPerPixel           ignored              based on header
71  *    iComponentsPerPixel     ignored              based on header
72  *    lHorizDPI               ignored              based on header
73  *    lVertDPI                ignored              based on header
74  *    lNumRows                ignored              based on header
75  *    iNumPages               passed into output   same as default input
76  *    iPageNum                passed into output   same as default input
77  *
78  *    Above, a "*" by an item indicates it must be valid (not negative).
79  *
80 \******************************************************************************/
81
82 #include "hpip.h"
83 #include "ipdefs.h"
84 #include "string.h"    /* for memset and memcpy */
85 #include <stdio.h>
86
87 #define PRINTF(args...) fprintf(stderr,args)
88
89 /* TODO: Move this to a separate .h file: */
90 extern IP_XFORM_TBL jpgDecodeTbl;
91 extern WORD jpgDecode_getRowCountInfo(IP_XFORM_HANDLE hXform,
92     int *pRcCountup,int *pRcTraits,int *pSofOffset);
93
94 #if 0
95     #include "stdio.h"
96     #include <tchar.h>
97     #define PRINT(msg,arg1,arg2) \
98         _ftprintf(stderr, msg, (int)arg1, (int)arg2)
99 #else
100     #define PRINT(msg,arg1,arg2)
101 #endif
102
103 #define CHECK_VALUE 0x4ba1dace
104
105 #define FUNC_STATUS static
106
107 #define BEND_GET_SHORT(s) (((s)[0]<<8)|((s)[1]))
108 #define BEND_SET_SHORT(s,x) ((s)[0]=((x)>>8)&0xFF,(s)[1]=(x)&0xFF)
109
110 typedef struct {
111     IP_XFORM_HANDLE pSlaveXform;   /* JPEG-decoder slave transformer. */
112     PBYTE    headerBuffer;
113     DWORD    outNextPos;
114     DWORD    lenHeader;
115     DWORD    lenAddedHeader;
116     DWORD    lenHeaderBuffer;
117     DWORD    readyForSofRewrite;
118     DWORD    dwValidChk;      /* struct validity check value */
119 } JFIX_INST, *PJFIX_INST;
120
121
122 /* TODO: Move the tables to a separate common file. */
123
124 /* Since the firmware does not supply tables in its header,
125  * the tables used in the firmware are supplied below.  */
126
127 /*____________________________________________________________________________
128  |                                                                            |
129  | Zigzag of Normal Quantization Tables                                       |
130  |____________________________________________________________________________|
131 */ 
132
133 static const unsigned char orig_lum_quant[64] = {
134      16,  11,  12,  14,  12,  10,  16,  14,
135      13,  14,  18,  17,  16,  19,  24,  40,
136      26,  24,  22,  22,  24,  49,  35,  37,
137      29,  40,  58,  51,  61,  60,  57,  51,
138      56,  55,  64,  72,  92,  78,  64,  68,
139      87,  69,  55,  56,  80, 109,  81,  87,
140      95,  98, 103, 104, 103,  62,  77, 113,
141     121, 112, 100, 120,  92, 101, 103,  99
142 };
143
144 static const unsigned char orig_chrom_quant[64] = {
145     17,  18,  18,  24,  21,  24,  47,  26,
146     26,  47,  99,  66,  56,  66,  99,  99,
147     99,  99,  99,  99,  99,  99,  99,  99,
148     99,  99,  99,  99,  99,  99,  99,  99,
149     99,  99,  99,  99,  99,  99,  99,  99,
150     99,  99,  99,  99,  99,  99,  99,  99,
151     99,  99,  99,  99,  99,  99,  99,  99,
152     99,  99,  99,  99,  99,  99,  99,  99
153 };
154
155 /*____________________________________________________________________________
156  |                                                                            |
157  | Huffman Tables                                                             |
158  |____________________________________________________________________________|
159 */
160  
161 static const unsigned char lum_DC_counts[16] = {
162     0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,
163     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
164 };
165  
166 static const unsigned char lum_DC_values[12] = {
167     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b
168 };
169  
170 static const unsigned char chrom_DC_counts[16] = {
171     0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
172     0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
173 };
174  
175 static const unsigned char chrom_DC_values[12] = {
176     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b
177 };
178  
179 static const unsigned char lum_AC_counts[16] = {
180     0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03,
181     0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d
182 };
183
184 static const unsigned char lum_AC_values[162] = {
185     0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
186     0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
187     0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
188     0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
189     0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
190     0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
191     0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
192     0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
193     0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
194     0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
195     0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
196     0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
197     0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
198     0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
199     0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
200     0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
201     0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
202     0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
203     0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
204     0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
205     0xf9, 0xfa
206 };
207  
208 static const unsigned char chrom_AC_counts[16] = {
209     0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
210     0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77
211 };
212
213 static const unsigned char chrom_AC_values[162] = {
214     0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
215     0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
216     0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
217     0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
218     0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
219     0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
220     0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
221     0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
222     0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
223     0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
224     0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
225     0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
226     0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
227     0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
228     0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
229     0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
230     0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
231     0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
232     0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
233     0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
234     0xf9, 0xfa
235 };
236
237 /*____________________________________________________________________________
238  |               |                                                            |
239  | scale_q_table | scales a q-table according to the q-factors                |
240  |_______________|____________________________________________________________|
241 */
242 /* TODO: Reference this from a common .h file. */
243 void scale_q_table(int dc_q_factor,int ac_q_factor,int ident,
244   unsigned char *out) {
245     static const int Q_DEFAULT=20;
246     static const int FINAL_DC_INDEX=9;
247     int i,val;
248     int q=dc_q_factor;
249     const unsigned char *in=orig_lum_quant;
250     if (ident) in=orig_chrom_quant;
251  
252     for (i=0; i<64; i++) {
253         val = ((*in++)*q + Q_DEFAULT/2) / Q_DEFAULT;
254         if (val < 1)   val = 1;
255         if (val > 255) val = 255;
256         *out++ = (unsigned char)val;
257         if (i == FINAL_DC_INDEX) {
258             q = ac_q_factor;
259         }
260     }
261 }
262
263
264 /*****************************************************************************\
265  *
266  * jpgFix_openXform - Creates a new instance of the transformer
267  *
268  *****************************************************************************
269  *
270  * This returns a handle for the new instance to be passed into
271  * all subsequent calls.
272  *
273  * Return value: IP_DONE=success; IP_FATAL_ERROR=misc error.
274  *
275 \*****************************************************************************/
276
277 FUNC_STATUS WORD jpgFix_openXform (
278     IP_XFORM_HANDLE *pXform)   /* out: returned handle */
279 {
280     PJFIX_INST g;
281
282     INSURE (pXform != NULL);
283     IP_MEM_ALLOC (sizeof(JFIX_INST), g);
284     *pXform = g;
285     memset (g, 0, sizeof(JFIX_INST));
286     if (jpgDecodeTbl.openXform(&g->pSlaveXform)!=IP_DONE) {
287         IP_MEM_FREE(g);
288         goto fatal_error;
289     }
290     g->dwValidChk = CHECK_VALUE;
291     return IP_DONE;
292
293     fatal_error:
294     return IP_FATAL_ERROR;
295 }
296
297
298
299 /*****************************************************************************\
300  *
301  * jpgFix_setDefaultInputTraits - Specifies default input image traits
302  *
303  *****************************************************************************
304  *
305  * The header of the file-type handled by the transform probably does
306  * not include *all* the image traits we'd like to know.  Those not
307  * specified in the file-header are filled in from info provided by
308  * this routine.
309  *
310  * Return value: IP_DONE=success; IP_FATAL_ERROR=misc error.
311  *
312 \*****************************************************************************/
313
314 FUNC_STATUS WORD jpgFix_setDefaultInputTraits (
315     IP_XFORM_HANDLE  hXform,     /* in: handle for xform */
316     PIP_IMAGE_TRAITS pTraits)    /* in: default image traits */
317 {
318     PJFIX_INST g;
319
320     HANDLE_TO_PTR (hXform, g);
321
322     return jpgDecodeTbl.setDefaultInputTraits(g->pSlaveXform,pTraits);
323
324     fatal_error:
325     return IP_FATAL_ERROR;
326 }
327
328
329
330 /*****************************************************************************\
331  *
332  * jpgFix_setXformSpec - Provides xform-specific information
333  *
334 \*****************************************************************************/
335
336 FUNC_STATUS WORD jpgFix_setXformSpec (
337     IP_XFORM_HANDLE hXform,         /* in: handle for xform */
338     DWORD_OR_PVOID  aXformInfo[])   /* in: xform information */
339 {
340     PJFIX_INST g;
341
342     HANDLE_TO_PTR (hXform, g);
343
344     /* Check your options in aXformInfo here, and save them.
345      * Use the INSURE macro like you'd use assert.  INSURE jumps to
346      * fatal_error below if it fails.
347      */
348
349     return IP_DONE;
350
351     fatal_error:
352     return IP_FATAL_ERROR;
353 }
354
355
356
357 /*****************************************************************************\
358  *
359  * jpgFix_getHeaderBufSize- Returns size of input buf needed to hold header
360  *
361 \*****************************************************************************/
362
363 FUNC_STATUS WORD jpgFix_getHeaderBufSize (
364     IP_XFORM_HANDLE  hXform,         /* in:  handle for xform */
365     DWORD           *pdwInBufLen)    /* out: buf size for parsing header */
366 {
367     WORD r;
368     PJFIX_INST g;
369
370     HANDLE_TO_PTR (hXform, g);
371
372     r=jpgDecodeTbl.getHeaderBufSize(g->pSlaveXform,pdwInBufLen);
373     if (r!=IP_DONE) return r;
374
375     g->lenHeaderBuffer=*pdwInBufLen;
376     IP_MEM_ALLOC(g->lenHeaderBuffer,g->headerBuffer);
377     return IP_DONE;
378
379     fatal_error:
380     return IP_FATAL_ERROR;
381 }
382
383
384
385 /*****************************************************************************\
386  *
387  * jpgFix_getActualTraits - Parses header, and returns input & output traits
388  *
389 \*****************************************************************************/
390
391
392 //#define MYLOCATE(p) (void *)(p)=(g->headerBuffer+lenAddedHeader)
393 #define MYLOCATE(p) (p)=(void *)(g->headerBuffer+lenAddedHeader)
394 #define MYWRITE(p) lenAddedHeader+=sizeof(*(p))
395 #define MYWRITEBUF(data,datalen) \
396     do { \
397         INSURE((datalen)<=g->lenHeaderBuffer-lenAddedHeader); \
398         memcpy(g->headerBuffer+lenAddedHeader,(char *)(data),(datalen)); \
399         lenAddedHeader+=(datalen); \
400     } while(0)
401
402 FUNC_STATUS WORD jpgFix_getActualTraits (
403     IP_XFORM_HANDLE  hXform,         /* in:  handle for xform */
404     DWORD            dwInputAvail,   /* in:  # avail bytes in input buf */
405     PBYTE            pbInputBuf,     /* in:  ptr to input buffer */
406     PDWORD           pdwInputUsed,   /* out: # bytes used from input buf */
407     PDWORD           pdwInputNextPos,/* out: file-pos to read from next */
408     PIP_IMAGE_TRAITS pInTraits,      /* out: input image traits */
409     PIP_IMAGE_TRAITS pOutTraits)     /* out: output image traits */
410 {
411     struct shortHeader_s {
412         unsigned char soi[2];              /* 0xFF, 0xD8 */
413
414         unsigned char app1[2];             /* 0xFF, 0xE1 */
415         unsigned char app1Length[2];       /* 0x00, 0x12 */
416         unsigned char height[2];
417         unsigned char width[2];
418         unsigned char xres[2];
419         unsigned char yres[2];
420         unsigned char ac_q_factor;
421         unsigned char numComponents;       /* 1=gray, 3=color */
422         unsigned char xSampleFactors[2];
423         unsigned char ySampleFactors[2];
424         unsigned char dc_q_factor;
425         unsigned char reserved;            /* 0x00 */
426     } *pInputHeader=(struct shortHeader_s *)pbInputBuf;
427     struct outputSoiApp0_s {
428         unsigned char soi[2];              /* 0xFF, 0xD8 */
429
430         unsigned char app0[2];             /* 0xFF, 0xE0 */
431         unsigned char app0Length[2];       /* 0x00, 0x10 */
432         unsigned char jfif[5];             /* "JFIF\0" */
433         unsigned char majorVersion;        /* 0x01 */
434         unsigned char minorVersion;        /* 0x00 */
435         unsigned char units;               /* 0x01 = DPI */
436         unsigned char xres[2];
437         unsigned char yres[2];
438         unsigned char xthumb;              /* 0x00 */
439         unsigned char ythumb;              /* 0x00 */
440     } *pOutputSoiApp0;
441     struct {
442         unsigned char sof0[2];             /* 0xFF, 0xC0 */
443         unsigned char sof0Length[2];       /* 0x00, 0x?? */
444         unsigned char eight;               /* 0x08 */
445         unsigned char height[2];
446         unsigned char width[2];
447         unsigned char numComponents;       /* 1=gray, 3=color */
448     } *pOutputSof0Part1;
449     struct {
450         unsigned char iComponent;
451         unsigned char xySampleFactors;
452         unsigned char isNotFirstComponent;
453     } *pOutputSofComponent;
454     struct {
455         unsigned char dqt[2];              /* 0xFF, 0xDB */
456         unsigned char dqtLength[2];        /* 0x00, 0x43 */
457         unsigned char ident;               /* 0=lum., 1=chrom. */
458         unsigned char elements[64];
459     } *pOutputDqt;
460     struct {
461         unsigned char dht[2];              /* 0xFF, 0xC4 */
462         unsigned char dhtLength[2];        /* 0x00, 0x?? */
463     } *pOutputDhtPart1;
464     struct {
465         unsigned char hclass_ident;
466         unsigned char counts[16];
467         /* Variable-length huffval table follows. */
468     } *pOutputDhtPart2;
469     static const struct {
470         unsigned char hclass_ident;
471         const unsigned char *counts;
472         const unsigned char *huffval;
473     } dhtInfo[4]={
474         {0x00,lum_DC_counts,lum_DC_values},
475         {0x10,lum_AC_counts,lum_AC_values},
476         {0x01,chrom_DC_counts,chrom_DC_values},
477         {0x11,chrom_AC_counts,chrom_AC_values}
478     };
479     int dhtCountCounts[4];
480     struct {
481         unsigned char sos[2];              /* 0xFF, 0xDA */
482         unsigned char sosLength[2];        /* 0x00, 0x?? */
483         unsigned char numComponents;       /* 1=gray, 3=color */
484     } *pOutputSosPart1;
485     struct {
486         unsigned char iComponent;
487         unsigned char x00x11;              /* (i==0 ? 0x00 : 0x11) */
488     } *pOutputSosComponent;
489     struct {
490         unsigned char zero1;               /* 0x00 */
491         unsigned char sixtythree;          /* 0x3F */
492         unsigned char zero2;               /* 0x00 */
493     } *pOutputSosPart2;
494
495     PJFIX_INST g;
496     DWORD lenRemovedHeader=0,lenAddedHeader=0;
497     int imax,i,j,x,y,r,len;
498
499     HANDLE_TO_PTR (hXform, g);
500
501     /* Validate APP1 (OfficeJet short header) record.
502      * If we actually get a JFIF standard APP0 record, then
503      * skip parsing the header. */
504     if (dwInputAvail>=sizeof(*pInputHeader) &&
505         pInputHeader->soi[0]==0xFF && pInputHeader->soi[1]==0xD8 &&
506         pInputHeader->app1[0]==0xFF && pInputHeader->app1[1]==0xE1 &&
507         !pInputHeader->app1Length[0] && pInputHeader->app1Length[1]==0x12) {
508
509         /* Write standard JPEG/JFIF records... */
510         lenRemovedHeader=sizeof(*pInputHeader);
511
512         /* Start Of Image record. */
513         MYLOCATE(pOutputSoiApp0);
514         pOutputSoiApp0->soi[0]=0xFF;
515         pOutputSoiApp0->soi[1]=0xD8;
516         /* APP0 (JFIF header) record. */
517         pOutputSoiApp0->app0[0]=0xFF;
518         pOutputSoiApp0->app0[1]=0xE0;
519         pOutputSoiApp0->app0Length[0]=0x00;
520         pOutputSoiApp0->app0Length[1]=sizeof(*pOutputSoiApp0)-4;
521         strcpy((char *)pOutputSoiApp0->jfif,"JFIF");
522         pOutputSoiApp0->majorVersion=0x01;
523         pOutputSoiApp0->minorVersion=0x00;
524         pOutputSoiApp0->units=0x01;
525         pOutputSoiApp0->xres[0]=pInputHeader->xres[0];
526         pOutputSoiApp0->xres[1]=pInputHeader->xres[1];
527         pOutputSoiApp0->yres[0]=pInputHeader->yres[0];
528         pOutputSoiApp0->yres[1]=pInputHeader->yres[1];
529         pOutputSoiApp0->xthumb=0;
530         pOutputSoiApp0->ythumb=0;
531         MYWRITE(pOutputSoiApp0);
532
533         /* Start Of Frame record. */
534         MYLOCATE(pOutputSof0Part1);
535         pOutputSof0Part1->sof0[0]=0xFF;
536         pOutputSof0Part1->sof0[1]=0xC0;
537         pOutputSof0Part1->sof0Length[0]=0x00;
538         pOutputSof0Part1->sof0Length[1]=sizeof(*pOutputSof0Part1)-2+
539             pInputHeader->numComponents*sizeof(*pOutputSofComponent);
540         pOutputSof0Part1->eight=0x08;
541         pOutputSof0Part1->height[0]=pInputHeader->height[0];
542         pOutputSof0Part1->height[1]=pInputHeader->height[1];
543         pOutputSof0Part1->width[0]=pInputHeader->width[0];
544         pOutputSof0Part1->width[1]=pInputHeader->width[1];
545         pOutputSof0Part1->numComponents=pInputHeader->numComponents;
546         MYWRITE(pOutputSof0Part1);
547         x=BEND_GET_SHORT(pInputHeader->xSampleFactors);
548         y=BEND_GET_SHORT(pInputHeader->ySampleFactors);
549         for (i=0;i<pInputHeader->numComponents;i++) {
550             MYLOCATE(pOutputSofComponent);
551             pOutputSofComponent->iComponent=i;
552             pOutputSofComponent->xySampleFactors=
553                 (((x>>(4*(3-i)))&0x0F)<<4) | ((y>>(4*(3-i)))&0x0F);
554             pOutputSofComponent->isNotFirstComponent=(!i?0:1);
555             MYWRITE(pOutputSofComponent);
556         }
557
558         /* Define Quantization Table record. */
559         imax=pInputHeader->numComponents>1?1:0;
560         for (i=0;i<=imax;i++) {
561             MYLOCATE(pOutputDqt);
562             pOutputDqt->dqt[0]=0xFF;
563             pOutputDqt->dqt[1]=0xDB;
564             pOutputDqt->dqtLength[0]=0x00;
565             pOutputDqt->dqtLength[1]=sizeof(*pOutputDqt)-2;
566             pOutputDqt->ident=i;    /* Upper nibble=0 for 8-bit table. */
567             scale_q_table(pInputHeader->dc_q_factor,pInputHeader->ac_q_factor,
568                 i,pOutputDqt->elements);
569             MYWRITE(pOutputDqt);
570         }
571         imax=pInputHeader->numComponents>1?4:2;
572         x=sizeof(*pOutputDhtPart1)-2;
573         for (i=0;i<imax;i++) {
574             dhtCountCounts[i]=0;
575             x+=sizeof(*pOutputDhtPart2);
576             for (j=0;j<16;j++) {
577                 y=dhtInfo[i].counts[j];
578                 dhtCountCounts[i]+=y;
579                 x+=y;
580             }
581         }
582         MYLOCATE(pOutputDhtPart1);
583         pOutputDhtPart1->dht[0]=0xFF;
584         pOutputDhtPart1->dht[1]=0xC4;
585         BEND_SET_SHORT(pOutputDhtPart1->dhtLength,x);
586         MYWRITE(pOutputDhtPart1);
587         for (i=0;i<imax;i++) {
588             MYLOCATE(pOutputDhtPart2);
589             pOutputDhtPart2->hclass_ident=dhtInfo[i].hclass_ident;
590             memcpy(pOutputDhtPart2->counts,dhtInfo[i].counts,16);
591             MYWRITE(pOutputDhtPart2);
592             MYWRITEBUF(dhtInfo[i].huffval,dhtCountCounts[i]);
593         }
594
595         /* Start Of Scan record. */
596         MYLOCATE(pOutputSosPart1);
597         imax=pInputHeader->numComponents;
598         pOutputSosPart1->sos[0]=0xFF;
599         pOutputSosPart1->sos[1]=0xDA;
600         pOutputSosPart1->sosLength[0]=0;
601         pOutputSosPart1->sosLength[1]=sizeof(*pOutputSosPart1)-2+
602             imax*sizeof(*pOutputSosComponent)+sizeof(*pOutputSosPart2);
603         pOutputSosPart1->numComponents=imax;
604         MYWRITE(pOutputSosPart1);
605         for (i=0;i<imax;i++) {
606             MYLOCATE(pOutputSosComponent);
607             pOutputSosComponent->iComponent=i;
608             pOutputSosComponent->x00x11=(!i?0x00:0x11);
609             MYWRITE(pOutputSosComponent);
610         }
611         MYLOCATE(pOutputSosPart2);
612         pOutputSosPart2->zero1=0;
613         pOutputSosPart2->sixtythree=63;
614         pOutputSosPart2->zero2=0;
615         MYWRITE(pOutputSosPart2);
616     }
617
618     /* Save a copy of the (possibly rewritten) header (plus any residual
619      * data) so we can emit it later. */
620     len=dwInputAvail-(lenAddedHeader-lenRemovedHeader);
621     if (len>g->lenHeaderBuffer-lenAddedHeader) {
622         len=g->lenHeaderBuffer-lenAddedHeader;
623     }
624     memcpy(g->headerBuffer+lenAddedHeader,pbInputBuf+lenRemovedHeader,len);
625
626     /* Pass the (possibly rewritten) header to the slave transformer. */
627     r=jpgDecodeTbl.getActualTraits(g->pSlaveXform,
628         len+lenAddedHeader,g->headerBuffer,
629         pdwInputUsed,pdwInputNextPos,
630         pInTraits,pOutTraits);
631     if ((r&(IP_DONE|IP_READY_FOR_DATA))!=(IP_DONE|IP_READY_FOR_DATA)) {
632         return (r|IP_FATAL_ERROR);
633     }
634
635     g->lenHeader=*pdwInputUsed;
636     g->lenAddedHeader=lenAddedHeader-lenRemovedHeader;
637     *pdwInputUsed-=g->lenAddedHeader;
638     *pdwInputNextPos-=g->lenAddedHeader;
639
640     return r;
641
642     fatal_error:
643     return IP_FATAL_ERROR;
644 }
645
646
647
648 /****************************************************************************\
649  *
650  * jpgFix_getActualBufSizes - Returns buf sizes needed for remainder of job
651  *
652 \****************************************************************************/
653
654 FUNC_STATUS WORD jpgFix_getActualBufSizes (
655     IP_XFORM_HANDLE hXform,          /* in:  handle for xform */
656     PDWORD          pdwMinInBufLen,  /* out: min input buf size */
657     PDWORD          pdwMinOutBufLen) /* out: min output buf size */
658 {
659     WORD r;
660     PJFIX_INST g;
661
662     HANDLE_TO_PTR (hXform, g);
663
664     r=jpgDecodeTbl.getActualBufSizes(g->pSlaveXform,
665         pdwMinInBufLen,pdwMinOutBufLen);
666     if (r==IP_DONE) {
667         INSURE(*pdwMinOutBufLen<=g->lenHeaderBuffer);
668     }
669     *pdwMinOutBufLen=g->lenHeaderBuffer;
670     return r;
671
672     fatal_error:
673     return IP_FATAL_ERROR;
674 }
675
676
677
678 /*****************************************************************************\
679  *
680  * jpgFix_convert - Converts one row
681  *
682 \*****************************************************************************/
683
684 FUNC_STATUS WORD jpgFix_convert (
685     IP_XFORM_HANDLE hXform,
686     DWORD           dwInputAvail,     /* in:  # avail bytes in in-buf */
687     PBYTE           pbInputBuf,       /* in:  ptr to in-buffer */
688     PDWORD          pdwInputUsed,     /* out: # bytes used from in-buf */
689     PDWORD          pdwInputNextPos,  /* out: file-pos to read from next */
690     DWORD           dwOutputAvail,    /* in:  # avail bytes in out-buf */
691     PBYTE           pbOutputBuf,      /* in:  ptr to out-buffer */
692     PDWORD          pdwOutputUsed,    /* out: # bytes written in out-buf */
693     PDWORD          pdwOutputThisPos) /* out: file-pos to write the data */
694 {
695     PJFIX_INST g;
696     WORD r=0;
697
698     HANDLE_TO_PTR (hXform, g);
699
700     if (g->outNextPos<g->lenHeader) {
701         DWORD len=g->lenHeader-g->outNextPos;
702         if (len>dwOutputAvail) len=dwOutputAvail;
703         if (len) {
704             memcpy(pbOutputBuf,g->headerBuffer+g->outNextPos,len);
705         }
706         *pdwInputUsed=0;
707         *pdwInputNextPos=g->lenHeader-g->lenAddedHeader;
708         *pdwOutputUsed=len;
709         *pdwOutputThisPos=g->outNextPos;
710         g->outNextPos+=len;
711         r|=IP_READY_FOR_DATA;
712
713     } else if (!g->readyForSofRewrite) {
714         DWORD dwOutputUsed,dwOutputThisPos;
715         r=jpgDecodeTbl.convert(g->pSlaveXform,
716           dwInputAvail,pbInputBuf,pdwInputUsed,pdwInputNextPos,
717           g->lenHeaderBuffer,g->headerBuffer,
718           &dwOutputUsed,&dwOutputThisPos);
719         *pdwInputNextPos-=g->lenAddedHeader;
720         if (r&IP_DONE) {
721             g->readyForSofRewrite=1;
722             if (!*pdwInputUsed) goto rewriteSof;
723         }
724         if (*pdwInputUsed) {
725             INSURE(*pdwInputUsed<=dwOutputAvail);
726             memcpy(pbOutputBuf,pbInputBuf,*pdwInputUsed);
727         }
728         *pdwOutputUsed=*pdwInputUsed;
729         *pdwOutputThisPos=g->outNextPos;
730         g->outNextPos+=*pdwInputUsed;
731
732     } else {
733 rewriteSof:
734         r|=IP_DONE;
735         *pdwInputUsed=0;
736         *pdwInputNextPos=g->outNextPos-g->lenAddedHeader;
737         *pdwOutputUsed=0;
738         *pdwOutputThisPos=g->outNextPos;
739         if (g->readyForSofRewrite>0) {
740             int rcCountup,rcTraits,sofOffset;
741             r=jpgDecode_getRowCountInfo(g->pSlaveXform,
742                 &rcCountup,&rcTraits,&sofOffset);
743             BEND_SET_SHORT(pbOutputBuf,rcCountup);
744             *pdwOutputUsed=2;
745             *pdwOutputThisPos=sofOffset;
746             g->readyForSofRewrite=-1;
747         }
748     }
749
750     return r;
751
752     fatal_error:
753     return IP_FATAL_ERROR;
754 }
755
756
757
758 /*****************************************************************************\
759  *
760  * jpgFix_insertedData - client inserted into our output stream
761  *
762 \*****************************************************************************/
763
764 FUNC_STATUS WORD jpgFix_insertedData (
765     IP_XFORM_HANDLE hXform,
766     DWORD           dwNumBytes)
767 {
768     fatalBreakPoint ();
769     return IP_FATAL_ERROR;   /* must never be called (can't insert data) */
770 }
771
772
773
774 /*****************************************************************************\
775  *
776  * jpgFix_newPage - Tells us to flush this page, and start a new page
777  *
778 \*****************************************************************************/
779
780 FUNC_STATUS WORD jpgFix_newPage (
781     IP_XFORM_HANDLE hXform)
782 {
783     PJFIX_INST g;
784
785     HANDLE_TO_PTR (hXform, g);
786     /* todo: return fatal error if convert is called again? */
787     return IP_DONE;   /* can't insert page-breaks, so ignore this call */
788
789     fatal_error:
790     return IP_FATAL_ERROR;
791
792 }
793
794
795
796 /*****************************************************************************\
797  *
798  * jpgFix_closeXform - Destroys this instance
799  *
800 \*****************************************************************************/
801
802 FUNC_STATUS WORD jpgFix_closeXform (IP_XFORM_HANDLE hXform)
803 {
804     PJFIX_INST g;
805
806     HANDLE_TO_PTR (hXform, g);
807
808     if (g->pSlaveXform) jpgDecodeTbl.closeXform(g->pSlaveXform);
809     if (g->headerBuffer) IP_MEM_FREE(g->headerBuffer);
810     g->dwValidChk = 0;
811     IP_MEM_FREE (g);       /* free memory for the instance */
812
813     return IP_DONE;
814
815     fatal_error:
816     return IP_FATAL_ERROR;
817 }
818
819
820
821 /*****************************************************************************\
822  *
823  * jpgFixTbl - Jump-table for transform driver
824  *
825 \*****************************************************************************/
826 IP_XFORM_TBL jpgFixTbl = {
827     jpgFix_openXform,
828     jpgFix_setDefaultInputTraits,
829     jpgFix_setXformSpec,
830     jpgFix_getHeaderBufSize,
831     jpgFix_getActualTraits,
832     jpgFix_getActualBufSizes,
833     jpgFix_convert,
834     jpgFix_newPage,
835     jpgFix_insertedData,
836     jpgFix_closeXform
837 };
838
839 /* End of File */