2 Cockos WDL - LICE - Lightweight Image Compositing Engine
3 Copyright (C) 2007 and later, Cockos Incorporated
4 File: lice_jpg.cpp (JPG loading for LICE)
5 See lice.h for license and other information
11 #include "../wdltypes.h"
14 #include "../jpeglib/jpeglib.h"
18 struct jpeg_error_mgr pub
; /* "public" fields */
19 jmp_buf setjmp_buffer
; /* for return to caller */
21 static void LICEJPEG_Error(j_common_ptr cinfo
)
23 longjmp(((my_error_mgr
*)cinfo
->err
)->setjmp_buffer
,1);
25 static void LICEJPEG_EmitMsg(j_common_ptr cinfo
, int msg_level
) { }
26 static void LICEJPEG_FmtMsg(j_common_ptr cinfo
, char *) { }
27 static void LICEJPEG_OutMsg(j_common_ptr cinfo
) { }
28 static void LICEJPEG_reset_error_mgr(j_common_ptr cinfo
)
30 cinfo
->err
->num_warnings
= 0;
31 cinfo
->err
->msg_code
= 0;
34 static void LICEJPEG_init_source(j_decompress_ptr cinfo
) {}
35 static unsigned char EOI_data
[2] = { 0xFF, 0xD9 };
36 static boolean
LICEJPEG_fill_input_buffer(j_decompress_ptr cinfo
)
38 cinfo
->src
->next_input_byte
= EOI_data
;
39 cinfo
->src
->bytes_in_buffer
= 2;
42 static void LICEJPEG_skip_input_data(j_decompress_ptr cinfo
, long num_bytes
)
46 if (num_bytes
> (long) cinfo
->src
->bytes_in_buffer
)
48 num_bytes
= (long) cinfo
->src
->bytes_in_buffer
;
50 cinfo
->src
->next_input_byte
+= (size_t) num_bytes
;
51 cinfo
->src
->bytes_in_buffer
-= (size_t) num_bytes
;
54 static void LICEJPEG_term_source(j_decompress_ptr cinfo
) {}
57 LICE_IBitmap
*LICE_LoadJPGFromResource(HINSTANCE hInst
, const char *resid
, LICE_IBitmap
*bmp
)
60 HRSRC hResource
= FindResource(hInst
, resid
, "JPG");
61 if(!hResource
) return NULL
;
63 DWORD imageSize
= SizeofResource(hInst
, hResource
);
64 if(imageSize
< 8) return NULL
;
66 HGLOBAL res
= LoadResource(hInst
, hResource
);
67 const void* pResourceData
= LockResource(res
);
68 if(!pResourceData
) return NULL
;
70 unsigned char *data
= (unsigned char *)pResourceData
;
72 struct jpeg_decompress_struct cinfo
;
73 struct my_error_mgr jerr
={0,};
77 jerr
.pub
.error_exit
= LICEJPEG_Error
;
78 jerr
.pub
.emit_message
= LICEJPEG_EmitMsg
;
79 jerr
.pub
.output_message
= LICEJPEG_OutMsg
;
80 jerr
.pub
.format_message
= LICEJPEG_FmtMsg
;
81 jerr
.pub
.reset_error_mgr
= LICEJPEG_reset_error_mgr
;
83 cinfo
.err
= &jerr
.pub
;
85 if (setjmp(jerr
.setjmp_buffer
))
87 jpeg_destroy_decompress(&cinfo
);
90 jpeg_create_decompress(&cinfo
);
92 cinfo
.src
= (struct jpeg_source_mgr
*) (*cinfo
.mem
->alloc_small
) ((j_common_ptr
) &cinfo
, JPOOL_PERMANENT
, sizeof (struct jpeg_source_mgr
));
94 cinfo
.src
->init_source
= LICEJPEG_init_source
;
95 cinfo
.src
->fill_input_buffer
= LICEJPEG_fill_input_buffer
;
96 cinfo
.src
->skip_input_data
= LICEJPEG_skip_input_data
;
97 cinfo
.src
->resync_to_restart
= jpeg_resync_to_restart
;
98 cinfo
.src
->term_source
= LICEJPEG_term_source
;
100 cinfo
.src
->next_input_byte
= data
;
101 cinfo
.src
->bytes_in_buffer
= imageSize
;
103 jpeg_read_header(&cinfo
, TRUE
);
104 jpeg_start_decompress(&cinfo
);
106 row_stride
= cinfo
.output_width
* cinfo
.output_components
;
108 buffer
= (*cinfo
.mem
->alloc_sarray
) ((j_common_ptr
) &cinfo
, JPOOL_IMAGE
, row_stride
, 1);
110 LICE_IBitmap
*delbmp
= NULL
;
111 if (bmp
) bmp
->resize(cinfo
.output_width
,cinfo
.output_height
);
112 else delbmp
= bmp
= new WDL_NEW
LICE_MemBitmap(cinfo
.output_width
,cinfo
.output_height
);
114 if (!bmp
|| bmp
->getWidth() != (int)cinfo
.output_width
|| bmp
->getHeight() != (int)cinfo
.output_height
)
116 jpeg_finish_decompress(&cinfo
);
117 jpeg_destroy_decompress(&cinfo
);
122 LICE_pixel
*bmpptr
= bmp
->getBits();
123 int dbmpptr
=bmp
->getRowSpan();
124 if (bmp
->isFlipped())
126 bmpptr
+= dbmpptr
*(bmp
->getHeight()-1);
130 while (cinfo
.output_scanline
< cinfo
.output_height
)
132 /* jpeg_read_scanlines expects an array of pointers to scanlines.
133 * Here the array is only one element long, but you could ask for
134 * more than one scanline at a time if that's more convenient.
136 jpeg_read_scanlines(&cinfo
, buffer
, 1);
137 /* Assume put_scanline_someplace wants a pointer and sample count. */
138 // put_scanline_someplace(buffer[0], row_stride);
139 if (cinfo
.output_components
==3)
142 for (x
= 0; x
< (int)cinfo
.output_width
; x
++)
144 bmpptr
[x
]=LICE_RGBA(buffer
[0][x
*3],buffer
[0][x
*3+1],buffer
[0][x
*3+2],255);
147 else if (cinfo
.output_components
==1)
150 for (x
= 0; x
< (int)cinfo
.output_width
; x
++)
153 bmpptr
[x
]=LICE_RGBA(v
,v
,v
,255);
158 memset(bmpptr
,0,4*cinfo
.output_width
);
163 jpeg_finish_decompress(&cinfo
);
164 jpeg_destroy_decompress(&cinfo
); // we created cinfo.src with some special alloc so I think it gets collected
174 LICE_IBitmap
*LICE_LoadJPG(const char *filename
, LICE_IBitmap
*bmp
)
176 struct jpeg_decompress_struct cinfo
;
177 struct my_error_mgr jerr
={{0},};
182 #if defined(_WIN32) && !defined(WDL_NO_SUPPORT_UTF8)
183 #ifdef WDL_SUPPORT_WIN9X
184 if (GetVersion()<0x80000000)
188 if (MultiByteToWideChar(CP_UTF8
,MB_ERR_INVALID_CHARS
,filename
,-1,wf
,2048))
189 fp
= _wfopen(wf
,L
"rb");
192 if (!fp
) fp
= fopen(filename
,"rb");
196 jerr
.pub
.error_exit
= LICEJPEG_Error
;
197 jerr
.pub
.emit_message
= LICEJPEG_EmitMsg
;
198 jerr
.pub
.output_message
= LICEJPEG_OutMsg
;
199 jerr
.pub
.format_message
= LICEJPEG_FmtMsg
;
200 jerr
.pub
.reset_error_mgr
= LICEJPEG_reset_error_mgr
;
202 cinfo
.err
= &jerr
.pub
;
204 if (setjmp(jerr
.setjmp_buffer
))
206 jpeg_destroy_decompress(&cinfo
);
210 jpeg_create_decompress(&cinfo
);
212 jpeg_stdio_src(&cinfo
, fp
);
213 jpeg_read_header(&cinfo
, TRUE
);
214 jpeg_start_decompress(&cinfo
);
216 row_stride
= cinfo
.output_width
* cinfo
.output_components
;
218 buffer
= (*cinfo
.mem
->alloc_sarray
)
219 ((j_common_ptr
) &cinfo
, JPOOL_IMAGE
, row_stride
, 1);
222 LICE_IBitmap
*delbmp
= NULL
;
223 if (bmp
) bmp
->resize(cinfo
.output_width
,cinfo
.output_height
);
224 else delbmp
= bmp
= new WDL_NEW
LICE_MemBitmap(cinfo
.output_width
,cinfo
.output_height
);
226 if (!bmp
|| bmp
->getWidth() != (int)cinfo
.output_width
|| bmp
->getHeight() != (int)cinfo
.output_height
)
228 jpeg_finish_decompress(&cinfo
);
229 jpeg_destroy_decompress(&cinfo
);
235 LICE_pixel
*bmpptr
= bmp
->getBits();
236 int dbmpptr
=bmp
->getRowSpan();
237 if (bmp
->isFlipped())
239 bmpptr
+= dbmpptr
*(bmp
->getHeight()-1);
243 while (cinfo
.output_scanline
< cinfo
.output_height
) {
244 /* jpeg_read_scanlines expects an array of pointers to scanlines.
245 * Here the array is only one element long, but you could ask for
246 * more than one scanline at a time if that's more convenient.
248 jpeg_read_scanlines(&cinfo
, buffer
, 1);
249 /* Assume put_scanline_someplace wants a pointer and sample count. */
250 // put_scanline_someplace(buffer[0], row_stride);
251 if (cinfo
.output_components
==3)
254 for (x
= 0; x
< (int)cinfo
.output_width
; x
++)
256 bmpptr
[x
]=LICE_RGBA(buffer
[0][x
*3],buffer
[0][x
*3+1],buffer
[0][x
*3+2],255);
259 else if (cinfo
.output_components
==1)
262 for (x
= 0; x
< (int)cinfo
.output_width
; x
++)
265 bmpptr
[x
]=LICE_RGBA(v
,v
,v
,255);
269 memset(bmpptr
,0,4*cinfo
.output_width
);
273 jpeg_finish_decompress(&cinfo
);
274 jpeg_destroy_decompress(&cinfo
);
284 _LICE_ImageLoader_rec rec
;
287 rec
.loadfunc
= loadfunc
;
288 rec
.get_extlist
= get_extlist
;
289 rec
._next
= LICE_ImageLoader_list
;
290 LICE_ImageLoader_list
= &rec
;
293 static LICE_IBitmap
*loadfunc(const char *filename
, bool checkFileName
, LICE_IBitmap
*bmpbase
)
297 const char *p
=filename
;
299 while (p
>filename
&& *p
!= '\\' && *p
!= '/' && *p
!= '.') p
--;
300 if (stricmp(p
,".jpg")&&stricmp(p
,".jpeg")&&stricmp(p
,".jfif")) return 0;
302 return LICE_LoadJPG(filename
,bmpbase
);
304 static const char *get_extlist()
306 return "JPEG files (*.JPG;*.JPEG;*.JFIF)\0*.JPG;*.JPEG;*.JFIF\0";
311 LICE_JPGLoader LICE_jgpldr
;