1 /*
2 Code for JPEG decompression by the Independent JPEG Group. Please see
3 README.jpeg in the top level directory.
4 */
5
6 #include "../include/sane/config.h"
7
8 #ifdef HAVE_LIBJPEG
9
10 #include "../include/sane/sanei_jpeg.h"
11
12 typedef struct
13 {
14 struct djpeg_dest_struct pub; /* public fields */
15
16 /* Usually these two pointers point to the same place: */
17 char *iobuffer; /* fwrite's I/O buffer */
18 JSAMPROW pixrow; /* decompressor output buffer */
19 size_t buffer_width; /* width of I/O buffer */
20 JDIMENSION samples_per_row; /* JSAMPLEs per output row */
21 }
22 ppm_dest_struct;
23
24 typedef ppm_dest_struct *ppm_dest_ptr;
25
26 /*
27 * For 12-bit JPEG data, we either downscale the values to 8 bits
28 * (to write standard byte-per-sample PPM/PGM files), or output
29 * nonstandard word-per-sample PPM/PGM files. Downscaling is done
30 * if PPM_NORAWWORD is defined (this can be done in the Makefile
31 * or in jconfig.h).
32 * (When the core library supports data precision reduction, a cleaner
33 * implementation will be to ask for that instead.)
34 */
35
36 #if BITS_IN_JSAMPLE==8
37 #define PUTPPMSAMPLE(ptr,v) *ptr++=(char) (v)
38 #define BYTESPERSAMPLE 1
39 #define PPM_MAXVAL 255
40 #else
41 #ifdef PPM_NORAWWORD
42 #define PUTPPMSAMPLE(ptr,v) *ptr++=(char) ((v) >> (BITS_IN_JSAMPLE-8))
43 #define BYTESPERSAMPLE 1
44 #define PPM_MAXVAL 255
45 #else
46 /* The word-per-sample format always puts the LSB first. */
47 #define PUTPPMSAMPLE(ptr,v) \
48 { register int val_=v; \
49 *ptr++=(char) (val_ & 0xFF); \
50 *ptr++=(char) ((val_ >> 8) & 0xFF); \
51 }
52 #define BYTESPERSAMPLE 2
53 #define PPM_MAXVAL ((1<<BITS_IN_JSAMPLE)-1)
54 #endif
55 #endif
56
57 METHODDEF (void)
sanei_jpeg_start_output_ppm(j_decompress_ptr cinfo,djpeg_dest_ptr dinfo)58 sanei_jpeg_start_output_ppm (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
59 {
60 (void) cinfo;
61 (void) dinfo;
62 /* header image is supplied for us */
63
64 }
65
66 METHODDEF (void)
sanei_jpeg_finish_output_ppm(j_decompress_ptr cinfo,djpeg_dest_ptr dinfo)67 sanei_jpeg_finish_output_ppm (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
68 {
69 (void) cinfo;
70 (void) dinfo;
71
72 /* nothing to do */
73 }
74
75 /*
76 * Write some pixel data.
77 * In this module rows_supplied will always be 1.
78 *
79 * put_pixel_rows handles the "normal" 8-bit case where the decompressor
80 * output buffer is physically the same as the fwrite buffer.
81 */
82
83 METHODDEF (void)
sanei_jpeg_put_pixel_rows(j_decompress_ptr cinfo,djpeg_dest_ptr dinfo,JDIMENSION rows_supplied,char * data)84 sanei_jpeg_put_pixel_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
85 JDIMENSION rows_supplied, char *data)
86 {
87 ppm_dest_ptr dest = (ppm_dest_ptr) dinfo;
88 (void) cinfo;
89 (void) dinfo;
90 (void) rows_supplied;
91
92 memcpy (data, dest->iobuffer, dest->buffer_width);
93 }
94
95
96 /*
97 * This code is used when we have to copy the data and apply a pixel
98 * format translation. Typically this only happens in 12-bit mode.
99 */
100
101 METHODDEF (void)
sanei_jpeg_copy_pixel_rows(j_decompress_ptr cinfo,djpeg_dest_ptr dinfo,JDIMENSION rows_supplied,char * data)102 sanei_jpeg_copy_pixel_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
103 JDIMENSION rows_supplied, char *data)
104 {
105 ppm_dest_ptr dest = (ppm_dest_ptr) dinfo;
106 register char *bufferptr;
107 register JSAMPROW ptr;
108 register JDIMENSION col;
109
110 (void) cinfo;
111 (void) dinfo;
112 (void) rows_supplied;
113
114 ptr = dest->pub.buffer[0];
115 bufferptr = dest->iobuffer;
116 for (col = dest->samples_per_row; col > 0; col--)
117 {
118 PUTPPMSAMPLE (bufferptr, GETJSAMPLE (*ptr++));
119 }
120 memcpy (data, dest->iobuffer, dest->buffer_width);
121 }
122
123
124 /*
125 * Write some pixel data when color quantization is in effect.
126 * We have to demap the color index values to straight data.
127 */
128
129 METHODDEF (void)
sanei_jpeg_put_demapped_rgb(j_decompress_ptr cinfo,djpeg_dest_ptr dinfo,JDIMENSION rows_supplied,char * data)130 sanei_jpeg_put_demapped_rgb (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
131 JDIMENSION rows_supplied, char *data)
132 {
133
134 ppm_dest_ptr dest = (ppm_dest_ptr) dinfo;
135 register char *bufferptr;
136 register int pixval;
137 register JSAMPROW ptr;
138 register JSAMPROW color_map0 = cinfo->colormap[0];
139 register JSAMPROW color_map1 = cinfo->colormap[1];
140 register JSAMPROW color_map2 = cinfo->colormap[2];
141 register JDIMENSION col;
142
143 (void) rows_supplied;
144
145 ptr = dest->pub.buffer[0];
146 bufferptr = dest->iobuffer;
147 for (col = cinfo->output_width; col > 0; col--)
148 {
149 pixval = GETJSAMPLE (*ptr++);
150 PUTPPMSAMPLE (bufferptr, GETJSAMPLE (color_map0[pixval]));
151 PUTPPMSAMPLE (bufferptr, GETJSAMPLE (color_map1[pixval]));
152 PUTPPMSAMPLE (bufferptr, GETJSAMPLE (color_map2[pixval]));
153 }
154 memcpy (data, dest->iobuffer, dest->buffer_width);
155 }
156
157
158 METHODDEF (void)
sanei_jpeg_put_demapped_gray(j_decompress_ptr cinfo,djpeg_dest_ptr dinfo,JDIMENSION rows_supplied,char * data)159 sanei_jpeg_put_demapped_gray (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
160 JDIMENSION rows_supplied, char *data)
161 {
162 ppm_dest_ptr dest = (ppm_dest_ptr) dinfo;
163 register char *bufferptr;
164 register JSAMPROW ptr;
165 register JSAMPROW color_map = cinfo->colormap[0];
166 register JDIMENSION col;
167
168 (void) rows_supplied;
169
170 ptr = dest->pub.buffer[0];
171 bufferptr = dest->iobuffer;
172 for (col = cinfo->output_width; col > 0; col--)
173 {
174 PUTPPMSAMPLE (bufferptr,
175 GETJSAMPLE (color_map[GETJSAMPLE (*ptr++)]));
176 }
177 memcpy (data, dest->iobuffer, dest->buffer_width);
178 }
179
180 GLOBAL (djpeg_dest_ptr)
sanei_jpeg_jinit_write_ppm(j_decompress_ptr cinfo)181 sanei_jpeg_jinit_write_ppm (j_decompress_ptr cinfo)
182 {
183
184 ppm_dest_ptr dest;
185
186 /* Create module interface object, fill in method pointers */
187 dest = (ppm_dest_ptr)
188 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
189 SIZEOF (ppm_dest_struct));
190 dest->pub.start_output = sanei_jpeg_start_output_ppm;
191 dest->pub.finish_output = sanei_jpeg_finish_output_ppm;
192
193 /* Calculate output image dimensions so we can allocate space */
194 jpeg_calc_output_dimensions (cinfo);
195
196 /* Create physical I/O buffer. Note we make this near on a PC. */
197 dest->samples_per_row = cinfo->output_width * cinfo->out_color_components;
198 dest->buffer_width = dest->samples_per_row * (BYTESPERSAMPLE * SIZEOF (char));
199 dest->iobuffer = (char *) (*cinfo->mem->alloc_small)
200 ((j_common_ptr) cinfo, JPOOL_IMAGE, dest->buffer_width);
201
202 if (cinfo->quantize_colors || BITS_IN_JSAMPLE != 8 ||
203 SIZEOF (JSAMPLE) != SIZEOF (char))
204 {
205 /* When quantizing, we need an output buffer for clrmap indexes
206 * that's separate from the physical I/O buffer. We also need a
207 * separate buffer if pixel format translation must take place.
208 */
209 dest->pub.buffer = (*cinfo->mem->alloc_sarray)
210 ((j_common_ptr) cinfo, JPOOL_IMAGE,
211 cinfo->output_width * cinfo->output_components,
212 (JDIMENSION) 1);
213 dest->pub.buffer_height = 1;
214 if (!cinfo->quantize_colors)
215 dest->pub.put_pixel_rows = sanei_jpeg_copy_pixel_rows;
216 else if (cinfo->out_color_space == JCS_GRAYSCALE)
217 dest->pub.put_pixel_rows = sanei_jpeg_put_demapped_gray;
218 else
219 dest->pub.put_pixel_rows = sanei_jpeg_put_demapped_rgb;
220 }
221 else
222 {
223 /* We will fwrite() directly from decompressor output buffer. */
224 /* Synthesize a JSAMPARRAY pointer structure */
225 /* Cast here implies near->far pointer conversion on PCs */
226 dest->pixrow = (JSAMPROW) dest->iobuffer;
227 dest->pub.buffer = &dest->pixrow;
228 dest->pub.buffer_height = 1;
229 dest->pub.put_pixel_rows = sanei_jpeg_put_pixel_rows;
230 }
231
232 return (djpeg_dest_ptr) dest;
233 }
234
235 #endif
236