source: golgotha/src/i4/loaders/jpg_load.cc @ 608

Last change on this file since 608 was 80, checked in by Sam Hocevar, 15 years ago
  • Adding the Golgotha source code. Not sure what's going to be interesting in there, but since it's all public domain, there's certainly stuff to pick up.
File size: 10.5 KB
Line 
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
19i4_profile_class pf_jpg_scanline_decode("jpg_scanline_decode");
20i4_profile_class pf_jpg_decode("jpg_decode");
21
22 
23w16 jpg_r_and; w8 jpg_r_shift; //r and g shifts are to the left
24w16 jpg_g_and; w8 jpg_g_shift;
25w16 jpg_b_and; w8 jpg_b_shift; //b shift is to the right
26
27void 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
39static 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
55i4_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
129i4_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
191i4_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
256i4_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
336class i4_jpg_loader_class i4_jpg_loader_instance;
Note: See TracBrowser for help on using the repository browser.