• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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