fix compile errors
[wdl/wdl-ol.git] / WDL / lice / lice_jpg.cpp
blob327269ab987e6c037bc3c4f42fda558563787ab2
1 /*
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
6 */
8 #include <stdio.h>
9 #include "lice.h"
10 #include <setjmp.h>
11 #include "../wdltypes.h"
13 extern "C" {
14 #include "../jpeglib/jpeglib.h"
17 struct my_error_mgr {
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;
40 return TRUE;
42 static void LICEJPEG_skip_input_data(j_decompress_ptr cinfo, long num_bytes)
44 if (num_bytes > 0)
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)
59 #ifdef _WIN32
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,};
74 JSAMPARRAY buffer;
75 int row_stride;
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);
88 return 0;
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);
118 delete delbmp;
119 return 0;
122 LICE_pixel *bmpptr = bmp->getBits();
123 int dbmpptr=bmp->getRowSpan();
124 if (bmp->isFlipped())
126 bmpptr += dbmpptr*(bmp->getHeight()-1);
127 dbmpptr=-dbmpptr;
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)
141 int x;
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)
149 int x;
150 for (x = 0; x < (int)cinfo.output_width; x++)
152 int v=buffer[0][x];
153 bmpptr[x]=LICE_RGBA(v,v,v,255);
156 else
158 memset(bmpptr,0,4*cinfo.output_width);
160 bmpptr+=dbmpptr;
163 jpeg_finish_decompress(&cinfo);
164 jpeg_destroy_decompress(&cinfo); // we created cinfo.src with some special alloc so I think it gets collected
166 return bmp;
168 #else
169 return 0;
170 #endif
174 LICE_IBitmap *LICE_LoadJPG(const char *filename, LICE_IBitmap *bmp)
176 struct jpeg_decompress_struct cinfo;
177 struct my_error_mgr jerr={{0},};
178 JSAMPARRAY buffer;
179 int row_stride;
181 FILE *fp=NULL;
182 #if defined(_WIN32) && !defined(WDL_NO_SUPPORT_UTF8)
183 #ifdef WDL_SUPPORT_WIN9X
184 if (GetVersion()<0x80000000)
185 #endif
187 WCHAR wf[2048];
188 if (MultiByteToWideChar(CP_UTF8,MB_ERR_INVALID_CHARS,filename,-1,wf,2048))
189 fp = _wfopen(wf,L"rb");
191 #endif
192 if (!fp) fp = fopen(filename,"rb");
194 if (!fp) return 0;
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);
207 fclose(fp);
208 return 0;
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);
230 fclose(fp);
231 delete delbmp;
232 return 0;
235 LICE_pixel *bmpptr = bmp->getBits();
236 int dbmpptr=bmp->getRowSpan();
237 if (bmp->isFlipped())
239 bmpptr += dbmpptr*(bmp->getHeight()-1);
240 dbmpptr=-dbmpptr;
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)
253 int x;
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)
261 int x;
262 for (x = 0; x < (int)cinfo.output_width; x++)
264 int v=buffer[0][x];
265 bmpptr[x]=LICE_RGBA(v,v,v,255);
268 else
269 memset(bmpptr,0,4*cinfo.output_width);
270 bmpptr+=dbmpptr;
273 jpeg_finish_decompress(&cinfo);
274 jpeg_destroy_decompress(&cinfo);
275 fclose(fp);
277 return bmp;
281 class LICE_JPGLoader
283 public:
284 _LICE_ImageLoader_rec rec;
285 LICE_JPGLoader()
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)
295 if (checkFileName)
297 const char *p=filename;
298 while (*p)p++;
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;