1 | /********************************************************************** <BR>
|
---|
2 | This file is part of Crack dot Com's free source code release of
|
---|
3 | Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for
|
---|
4 | information about compiling & licensing issues visit this URL</a>
|
---|
5 | <PRE> If that doesn't help, contact Jonathan Clark at
|
---|
6 | golgotha_source@usa.net (Subject should have "GOLG" in it)
|
---|
7 | ***********************************************************************/
|
---|
8 |
|
---|
9 | //#define JPEG_INTERNALS
|
---|
10 | //TODO clean up memory management
|
---|
11 | //convert types and memory and file stuff to I4
|
---|
12 | #include "loaders/load.hh"
|
---|
13 | #include "loaders/jpg_load.hh"
|
---|
14 | #include "time/profile.hh"
|
---|
15 | #include "memory/malloc.hh"
|
---|
16 | #include "palette/pal.hh"
|
---|
17 | #include "status/status.hh"
|
---|
18 |
|
---|
19 | i4_profile_class pf_jpg_scanline_decode("jpg_scanline_decode");
|
---|
20 | i4_profile_class pf_jpg_decode("jpg_decode");
|
---|
21 |
|
---|
22 |
|
---|
23 | w16 jpg_r_and; w8 jpg_r_shift; //r and g shifts are to the left
|
---|
24 | w16 jpg_g_and; w8 jpg_g_shift;
|
---|
25 | w16 jpg_b_and; w8 jpg_b_shift; //b shift is to the right
|
---|
26 |
|
---|
27 | void setup_pix_format(const i4_pixel_format *fmt)
|
---|
28 | {
|
---|
29 | jpg_b_shift = 8-fmt->blue_bits;
|
---|
30 | jpg_b_and = fmt->blue_mask;
|
---|
31 |
|
---|
32 | jpg_g_shift = fmt->blue_bits - (8-fmt->green_bits);
|
---|
33 | jpg_g_and = fmt->green_mask;
|
---|
34 |
|
---|
35 | jpg_r_shift = fmt->green_bits + fmt->blue_bits - (8-fmt->red_bits);
|
---|
36 | jpg_r_and = fmt->red_mask;
|
---|
37 | }
|
---|
38 |
|
---|
39 | static inline void pack_colorbgr(w16 *dest, w8 *src, sw32 num_pixels)
|
---|
40 | {
|
---|
41 | while (num_pixels)
|
---|
42 | {
|
---|
43 | //shifts must go first, ands last
|
---|
44 | *dest = ((src[0] << jpg_r_shift) & jpg_r_and) |
|
---|
45 | ((src[1] << jpg_g_shift) & jpg_g_and) |
|
---|
46 | ((src[2] >> jpg_b_shift) & jpg_b_and);
|
---|
47 |
|
---|
48 | dest++;
|
---|
49 | src += 3;
|
---|
50 |
|
---|
51 | num_pixels--;
|
---|
52 | }
|
---|
53 | }
|
---|
54 |
|
---|
55 | i4_bool i4_jpg_loader_class::convert_to_raw16(i4_file_class *src_fp,
|
---|
56 | FILE *dst_fp,
|
---|
57 | i4_status_class *status,
|
---|
58 | const i4_pal *pal,
|
---|
59 | sw32 expected_width,
|
---|
60 | sw32 expected_height)
|
---|
61 | {
|
---|
62 | djpeg_dest_ptr dest_mgr = NULL;
|
---|
63 | JDIMENSION num_scanlines;
|
---|
64 | int i,x;
|
---|
65 |
|
---|
66 | //setup this conversion stuff
|
---|
67 | setup_pix_format(&pal->source);
|
---|
68 |
|
---|
69 | /* Initialize the JPEG decompression object with default error handling. */
|
---|
70 | cinfo.err = jpeg_std_error(&jerr);
|
---|
71 | jpeg_create_decompress(&cinfo);
|
---|
72 | /* Add some application-specific error messages (from cderror.h) */
|
---|
73 | jerr.addon_message_table = cdjpeg_message_table;
|
---|
74 | jerr.first_addon_message = JMSG_FIRSTADDONCODE;
|
---|
75 | jerr.last_addon_message = JMSG_LASTADDONCODE;
|
---|
76 | /* Insert custom COM marker processor. */
|
---|
77 | jpeg_set_marker_processor(&cinfo, JPEG_COM, COM_handler);
|
---|
78 | /* Specify data source for decompression */
|
---|
79 | jpeg_stdio_src(&cinfo, src_fp);
|
---|
80 |
|
---|
81 | /* Read file header, set default decompression parameters */
|
---|
82 | (void) jpeg_read_header(&cinfo, TRUE);
|
---|
83 |
|
---|
84 | dest_mgr = jinit_write_targa(&cinfo);
|
---|
85 |
|
---|
86 | /* Start decompressor */
|
---|
87 | (void) jpeg_start_decompress(&cinfo);
|
---|
88 |
|
---|
89 | w16 *data = (w16 *)i4_malloc(cinfo.image_width*2, "jpeg 16-bit buffer");
|
---|
90 |
|
---|
91 | w32 scn=0;
|
---|
92 | /* Process data */
|
---|
93 | while (cinfo.output_scanline < cinfo.output_height)
|
---|
94 | {
|
---|
95 | pf_jpg_scanline_decode.start();
|
---|
96 | num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,dest_mgr->buffer_height);
|
---|
97 | pf_jpg_scanline_decode.stop();
|
---|
98 |
|
---|
99 | for(i=0;i<num_scanlines;i++)
|
---|
100 | {
|
---|
101 | if (status)
|
---|
102 | status->update(i/(float)num_scanlines);
|
---|
103 |
|
---|
104 | pack_colorbgr(data,dest_mgr->buffer[i],cinfo.image_width);
|
---|
105 | fwrite(data,cinfo.image_width*2,1,dst_fp);
|
---|
106 | /*
|
---|
107 | for(x=0;x<cinfo.image_width;x++)
|
---|
108 | {
|
---|
109 | *((w16 *)(data+x)) = pack_colorbgr((((w8 *)((dest_mgr->buffer[i])+(x*3)))));
|
---|
110 | }
|
---|
111 |
|
---|
112 | scn += cinfo.image_width;
|
---|
113 | */
|
---|
114 | }
|
---|
115 | }
|
---|
116 |
|
---|
117 | /* Finish decompression and release memory.
|
---|
118 | * I must do it in this order because output module has allocated memory
|
---|
119 | * of lifespan JPOOL_IMAGE; it needs to finish before releasing memory.
|
---|
120 | */
|
---|
121 | i4_free(data);
|
---|
122 |
|
---|
123 | (void) jpeg_finish_decompress(&cinfo);
|
---|
124 | jpeg_destroy_decompress(&cinfo);
|
---|
125 |
|
---|
126 | return i4_T;
|
---|
127 | }
|
---|
128 |
|
---|
129 | i4_bool i4_jpg_loader_class::special_load16(i4_file_class *src_fp,
|
---|
130 | w16 *dst_tex,
|
---|
131 | sw32 base_width,
|
---|
132 | const i4_pal *pal)
|
---|
133 | {
|
---|
134 | pf_jpg_decode.start();
|
---|
135 |
|
---|
136 | djpeg_dest_ptr dest_mgr = NULL;
|
---|
137 | JDIMENSION num_scanlines;
|
---|
138 | int i,x;
|
---|
139 |
|
---|
140 | //setup this conversion stuff
|
---|
141 | setup_pix_format(&pal->source);
|
---|
142 |
|
---|
143 | /* Initialize the JPEG decompression object with default error handling. */
|
---|
144 | cinfo.err = jpeg_std_error(&jerr);
|
---|
145 | jpeg_create_decompress(&cinfo);
|
---|
146 | /* Add some application-specific error messages (from cderror.h) */
|
---|
147 | jerr.addon_message_table = cdjpeg_message_table;
|
---|
148 | jerr.first_addon_message = JMSG_FIRSTADDONCODE;
|
---|
149 | jerr.last_addon_message = JMSG_LASTADDONCODE;
|
---|
150 | /* Insert custom COM marker processor. */
|
---|
151 | jpeg_set_marker_processor(&cinfo, JPEG_COM, COM_handler);
|
---|
152 | /* Specify data source for decompression */
|
---|
153 | jpeg_stdio_src(&cinfo, src_fp);
|
---|
154 |
|
---|
155 | /* Read file header, set default decompression parameters */
|
---|
156 | (void) jpeg_read_header(&cinfo, TRUE);
|
---|
157 |
|
---|
158 | dest_mgr = jinit_write_targa(&cinfo);
|
---|
159 |
|
---|
160 | /* Start decompressor */
|
---|
161 | (void) jpeg_start_decompress(&cinfo);
|
---|
162 |
|
---|
163 | w16 *data = dst_tex;
|
---|
164 |
|
---|
165 | w32 scn=0;
|
---|
166 | /* Process data */
|
---|
167 | while (cinfo.output_scanline < cinfo.output_height)
|
---|
168 | {
|
---|
169 | pf_jpg_scanline_decode.start();
|
---|
170 | num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,dest_mgr->buffer_height);
|
---|
171 | pf_jpg_scanline_decode.stop();
|
---|
172 |
|
---|
173 | for(i=0;i<num_scanlines;i++,data += base_width)
|
---|
174 | {
|
---|
175 | pack_colorbgr(data,dest_mgr->buffer[i],cinfo.image_width);
|
---|
176 | }
|
---|
177 | }
|
---|
178 |
|
---|
179 | /* Finish decompression and release memory.
|
---|
180 | * I must do it in this order because output module has allocated memory
|
---|
181 | * of lifespan JPOOL_IMAGE; it needs to finish before releasing memory.
|
---|
182 | */
|
---|
183 |
|
---|
184 | (void) jpeg_finish_decompress(&cinfo);
|
---|
185 | jpeg_destroy_decompress(&cinfo);
|
---|
186 |
|
---|
187 | pf_jpg_decode.stop();
|
---|
188 | return i4_T;
|
---|
189 | }
|
---|
190 |
|
---|
191 | i4_bool i4_jpg_loader_class::special_load24(i4_file_class *src_fp,
|
---|
192 | w8 *dst_tex,
|
---|
193 | sw32 *dst_width,
|
---|
194 | sw32 *dst_height)
|
---|
195 | {
|
---|
196 | pf_jpg_decode.start();
|
---|
197 |
|
---|
198 | djpeg_dest_ptr dest_mgr = NULL;
|
---|
199 | JDIMENSION num_scanlines;
|
---|
200 | int i,x;
|
---|
201 |
|
---|
202 | /* Initialize the JPEG decompression object with default error handling. */
|
---|
203 | cinfo.err = jpeg_std_error(&jerr);
|
---|
204 | jpeg_create_decompress(&cinfo);
|
---|
205 | /* Add some application-specific error messages (from cderror.h) */
|
---|
206 | jerr.addon_message_table = cdjpeg_message_table;
|
---|
207 | jerr.first_addon_message = JMSG_FIRSTADDONCODE;
|
---|
208 | jerr.last_addon_message = JMSG_LASTADDONCODE;
|
---|
209 | /* Insert custom COM marker processor. */
|
---|
210 | jpeg_set_marker_processor(&cinfo, JPEG_COM, COM_handler);
|
---|
211 | /* Specify data source for decompression */
|
---|
212 | jpeg_stdio_src(&cinfo, src_fp);
|
---|
213 |
|
---|
214 | /* Read file header, set default decompression parameters */
|
---|
215 | (void) jpeg_read_header(&cinfo, TRUE);
|
---|
216 |
|
---|
217 | dest_mgr = jinit_write_targa(&cinfo);
|
---|
218 |
|
---|
219 | /* Start decompressor */
|
---|
220 | (void) jpeg_start_decompress(&cinfo);
|
---|
221 |
|
---|
222 | w8 *data = dst_tex;
|
---|
223 | sw32 data_add = cinfo.image_width*3;
|
---|
224 |
|
---|
225 | *dst_width = cinfo.image_width;
|
---|
226 | *dst_height = cinfo.image_height;
|
---|
227 |
|
---|
228 | /* Process data */
|
---|
229 | while (cinfo.output_scanline < cinfo.output_height)
|
---|
230 | {
|
---|
231 | pf_jpg_scanline_decode.start();
|
---|
232 | num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,dest_mgr->buffer_height);
|
---|
233 | pf_jpg_scanline_decode.stop();
|
---|
234 |
|
---|
235 | for(i=0; i<num_scanlines; i++)
|
---|
236 | {
|
---|
237 | memcpy(data,dest_mgr->buffer[i],cinfo.image_width*3);
|
---|
238 | data += data_add;
|
---|
239 | }
|
---|
240 | }
|
---|
241 |
|
---|
242 | /* Finish decompression and release memory.
|
---|
243 | * I must do it in this order because output module has allocated memory
|
---|
244 | * of lifespan JPOOL_IMAGE; it needs to finish before releasing memory.
|
---|
245 | */
|
---|
246 |
|
---|
247 | (void) jpeg_finish_decompress(&cinfo);
|
---|
248 | jpeg_destroy_decompress(&cinfo);
|
---|
249 |
|
---|
250 | pf_jpg_decode.stop();
|
---|
251 |
|
---|
252 | return i4_T;
|
---|
253 | }
|
---|
254 |
|
---|
255 |
|
---|
256 | i4_image_class *i4_jpg_loader_class::load(i4_file_class *fp,
|
---|
257 | i4_status_class *status)
|
---|
258 | {
|
---|
259 | djpeg_dest_ptr dest_mgr = NULL;
|
---|
260 | JDIMENSION num_scanlines;
|
---|
261 | int i,x;
|
---|
262 |
|
---|
263 | // Initialize the JPEG decompression object with default error handling.
|
---|
264 | cinfo.err = jpeg_std_error(&jerr);
|
---|
265 | jpeg_create_decompress(&cinfo);
|
---|
266 | // Add some application-specific error messages (from cderror.h)
|
---|
267 | jerr.addon_message_table = cdjpeg_message_table;
|
---|
268 | jerr.first_addon_message = JMSG_FIRSTADDONCODE;
|
---|
269 | jerr.last_addon_message = JMSG_LASTADDONCODE;
|
---|
270 | // Insert custom COM marker processor.
|
---|
271 | jpeg_set_marker_processor(&cinfo, JPEG_COM, COM_handler);
|
---|
272 |
|
---|
273 | /* Specify data source for decompression */
|
---|
274 | jpeg_stdio_src(&cinfo, fp);
|
---|
275 |
|
---|
276 | /* Read file header, set default decompression parameters */
|
---|
277 | (void) jpeg_read_header(&cinfo, TRUE);
|
---|
278 |
|
---|
279 | dest_mgr = jinit_write_targa(&cinfo);
|
---|
280 |
|
---|
281 | /* Start decompressor */
|
---|
282 | (void) jpeg_start_decompress(&cinfo);
|
---|
283 |
|
---|
284 |
|
---|
285 | w32 *data=(w32 *)i4_malloc(cinfo.image_width*cinfo.image_height*4,"jpeg image");
|
---|
286 | w32 scn=0;
|
---|
287 | /* Process data */
|
---|
288 | while (cinfo.output_scanline < cinfo.output_height) {
|
---|
289 | num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,
|
---|
290 | dest_mgr->buffer_height);
|
---|
291 | for(i=0;i<num_scanlines;i++)
|
---|
292 | {
|
---|
293 | if (status)
|
---|
294 | status->update(i/(float)num_scanlines);
|
---|
295 |
|
---|
296 |
|
---|
297 |
|
---|
298 | for(x=0;x<cinfo.image_width;x++)
|
---|
299 | {
|
---|
300 | *((w32 *)(data+x+scn))=read_colorbgr((((w8 *)((dest_mgr->buffer[i])+(x*3)))));
|
---|
301 | }
|
---|
302 | scn+=cinfo.image_width;
|
---|
303 | }
|
---|
304 | }
|
---|
305 |
|
---|
306 | /* Finish decompression and release memory.
|
---|
307 | * I must do it in this order because output module has allocated memory
|
---|
308 | * of lifespan JPOOL_IMAGE; it needs to finish before releasing memory.
|
---|
309 | */
|
---|
310 | (void) jpeg_finish_decompress(&cinfo);
|
---|
311 | jpeg_destroy_decompress(&cinfo);
|
---|
312 |
|
---|
313 |
|
---|
314 | i4_pixel_format fmt;
|
---|
315 | fmt.default_format();
|
---|
316 |
|
---|
317 | fmt.alpha_mask=0; // no alpha in jpegs?
|
---|
318 | fmt.calc_shift();
|
---|
319 |
|
---|
320 |
|
---|
321 | const i4_pal *pal=i4_pal_man.register_pal(&fmt);
|
---|
322 |
|
---|
323 | i4_image_class *im=i4_create_image(
|
---|
324 | cinfo.image_width,
|
---|
325 | cinfo.image_height, // width & height
|
---|
326 | pal, // palette (should be 32 bit by default)
|
---|
327 | data,
|
---|
328 | cinfo.image_width*4); // bytes per line
|
---|
329 |
|
---|
330 | im->dont_free_data=i4_F;
|
---|
331 |
|
---|
332 | return im;
|
---|
333 | }
|
---|
334 |
|
---|
335 |
|
---|
336 | class i4_jpg_loader_class i4_jpg_loader_instance;
|
---|