winex11.drv: Map coordinates before calling send_mouse_input.
[wine/zf.git] / dlls / gphoto2.ds / ds_image.c
blobe5df69f4a625f2b76a59f0aaa3411d9d21958c75
1 /*
2 * Copyright 2000 Corel Corporation
3 * Copyright 2006 Marcus Meissner
4 * Copyright 2006 CodeWeavers, Aric Stewart
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "config.h"
22 #include "wine/port.h"
24 #include <stdarg.h>
25 #include <stdio.h>
27 #include "gphoto2_i.h"
28 #include "wingdi.h"
29 #include "winuser.h"
30 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(twain);
34 #ifdef HAVE_GPHOTO2
35 static void *libjpeg_handle;
36 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
37 MAKE_FUNCPTR(jpeg_std_error);
38 MAKE_FUNCPTR(jpeg_CreateDecompress);
39 MAKE_FUNCPTR(jpeg_read_header);
40 MAKE_FUNCPTR(jpeg_start_decompress);
41 MAKE_FUNCPTR(jpeg_read_scanlines);
42 MAKE_FUNCPTR(jpeg_finish_decompress);
43 MAKE_FUNCPTR(jpeg_destroy_decompress);
44 #undef MAKE_FUNCPTR
46 static void *load_libjpeg(void)
48 if((libjpeg_handle = dlopen(SONAME_LIBJPEG, RTLD_NOW)) != NULL) {
50 #define LOAD_FUNCPTR(f) \
51 if((p##f = dlsym(libjpeg_handle, #f)) == NULL) { \
52 libjpeg_handle = NULL; \
53 return NULL; \
56 LOAD_FUNCPTR(jpeg_std_error);
57 LOAD_FUNCPTR(jpeg_CreateDecompress);
58 LOAD_FUNCPTR(jpeg_read_header);
59 LOAD_FUNCPTR(jpeg_start_decompress);
60 LOAD_FUNCPTR(jpeg_read_scanlines);
61 LOAD_FUNCPTR(jpeg_finish_decompress);
62 LOAD_FUNCPTR(jpeg_destroy_decompress);
63 #undef LOAD_FUNCPTR
65 return libjpeg_handle;
69 /* for the jpeg decompressor source manager. */
70 static void _jpeg_init_source(j_decompress_ptr cinfo) { }
72 static boolean _jpeg_fill_input_buffer(j_decompress_ptr cinfo) {
73 ERR("(), should not get here.\n");
74 return FALSE;
77 static void _jpeg_skip_input_data(j_decompress_ptr cinfo,long num_bytes) {
78 TRACE("Skipping %ld bytes...\n", num_bytes);
79 cinfo->src->next_input_byte += num_bytes;
80 cinfo->src->bytes_in_buffer -= num_bytes;
83 static boolean _jpeg_resync_to_restart(j_decompress_ptr cinfo, int desired) {
84 ERR("(desired=%d), should not get here.\n",desired);
85 return FALSE;
87 static void _jpeg_term_source(j_decompress_ptr cinfo) { }
88 #endif
90 /* DG_IMAGE/DAT_CIECOLOR/MSG_GET */
91 TW_UINT16 GPHOTO2_CIEColorGet (pTW_IDENTITY pOrigin,
92 TW_MEMREF pData)
94 FIXME ("stub!\n");
96 return TWRC_FAILURE;
99 /* DG_IMAGE/DAT_EXTIMAGEINFO/MSG_GET */
100 TW_UINT16 GPHOTO2_ExtImageInfoGet (pTW_IDENTITY pOrigin,
101 TW_MEMREF pData)
103 FIXME ("stub!\n");
105 return TWRC_FAILURE;
108 /* DG_IMAGE/DAT_GRAYRESPONSE/MSG_RESET */
109 TW_UINT16 GPHOTO2_GrayResponseReset (pTW_IDENTITY pOrigin,
110 TW_MEMREF pData)
112 FIXME ("stub!\n");
114 return TWRC_FAILURE;
117 /* DG_IMAGE/DAT_GRAYRESPONSE/MSG_SET */
118 TW_UINT16 GPHOTO2_GrayResponseSet (pTW_IDENTITY pOrigin,
119 TW_MEMREF pData)
121 FIXME ("stub!\n");
123 return TWRC_FAILURE;
126 /* DG_IMAGE/DAT_IMAGEFILEXFER/MSG_GET */
127 TW_UINT16 GPHOTO2_ImageFileXferGet (pTW_IDENTITY pOrigin,
128 TW_MEMREF pData)
130 FIXME ("stub!\n");
132 return TWRC_FAILURE;
135 #ifdef HAVE_GPHOTO2
136 static TW_UINT16 _get_image_and_startup_jpeg(void) {
137 const char *folder = NULL, *filename = NULL;
138 struct gphoto2_file *file;
139 const unsigned char *filedata;
140 unsigned long filesize;
141 int ret;
143 if (activeDS.file) /* Already loaded. */
144 return TWRC_SUCCESS;
146 if(!libjpeg_handle) {
147 if(!load_libjpeg()) {
148 FIXME("Failed reading JPEG because unable to find %s\n", SONAME_LIBJPEG);
149 filedata = NULL;
150 return TWRC_FAILURE;
154 LIST_FOR_EACH_ENTRY( file, &activeDS.files, struct gphoto2_file, entry ) {
155 if (strstr(file->filename,".JPG") || strstr(file->filename,".jpg")) {
156 filename = file->filename;
157 folder = file->folder;
158 TRACE("downloading %s/%s\n", folder, filename);
159 if (file->download) {
160 file->download = FALSE; /* mark as done */
161 break;
165 gp_file_new (&activeDS.file);
166 ret = gp_camera_file_get(activeDS.camera, folder, filename, GP_FILE_TYPE_NORMAL,
167 activeDS.file, activeDS.context);
168 if (ret < GP_OK) {
169 FIXME("Failed to get file?\n");
170 activeDS.twCC = TWCC_SEQERROR;
171 return TWRC_FAILURE;
173 ret = gp_file_get_data_and_size (activeDS.file, (const char**)&filedata, &filesize);
174 if (ret < GP_OK) {
175 FIXME("Failed to get file data?\n");
176 activeDS.twCC = TWCC_SEQERROR;
177 return TWRC_FAILURE;
180 /* This is basically so we can use in-memory data for jpeg decompression.
181 * We need to have all the functions.
183 activeDS.xjsm.next_input_byte = filedata;
184 activeDS.xjsm.bytes_in_buffer = filesize;
185 activeDS.xjsm.init_source = _jpeg_init_source;
186 activeDS.xjsm.fill_input_buffer = _jpeg_fill_input_buffer;
187 activeDS.xjsm.skip_input_data = _jpeg_skip_input_data;
188 activeDS.xjsm.resync_to_restart = _jpeg_resync_to_restart;
189 activeDS.xjsm.term_source = _jpeg_term_source;
191 activeDS.jd.err = pjpeg_std_error(&activeDS.jerr);
192 /* jpeg_create_decompress is a macro that expands to jpeg_CreateDecompress - see jpeglib.h
193 * jpeg_create_decompress(&jd); */
194 pjpeg_CreateDecompress(&activeDS.jd, JPEG_LIB_VERSION, sizeof(struct jpeg_decompress_struct));
195 activeDS.jd.src = &activeDS.xjsm;
196 ret=pjpeg_read_header(&activeDS.jd,TRUE);
197 activeDS.jd.out_color_space = JCS_RGB;
198 pjpeg_start_decompress(&activeDS.jd);
199 if (ret != JPEG_HEADER_OK) {
200 ERR("Jpeg image in stream has bad format, read header returned %d.\n",ret);
201 gp_file_unref (activeDS.file);
202 activeDS.file = NULL;
203 return TWRC_FAILURE;
205 return TWRC_SUCCESS;
207 #endif
209 /* DG_IMAGE/DAT_IMAGEINFO/MSG_GET */
210 TW_UINT16 GPHOTO2_ImageInfoGet (pTW_IDENTITY pOrigin,
211 TW_MEMREF pData)
213 #ifdef HAVE_GPHOTO2
214 pTW_IMAGEINFO pImageInfo = (pTW_IMAGEINFO) pData;
216 TRACE("DG_IMAGE/DAT_IMAGEINFO/MSG_GET\n");
218 if (activeDS.currentState != 6 && activeDS.currentState != 7) {
219 activeDS.twCC = TWCC_SEQERROR;
220 return TWRC_FAILURE;
222 if (TWRC_SUCCESS != _get_image_and_startup_jpeg()) {
223 FIXME("Failed to get an image\n");
224 activeDS.twCC = TWCC_SEQERROR;
225 return TWRC_FAILURE;
227 if (activeDS.currentState == 6)
229 /* return general image description information about the image about to be transferred */
230 TRACE("Getting parameters\n");
232 TRACE("activeDS.jd.output_width = %d\n", activeDS.jd.output_width);
233 TRACE("activeDS.jd.output_height = %d\n", activeDS.jd.output_height);
234 pImageInfo->Compression = TWCP_NONE;
235 pImageInfo->SamplesPerPixel = 3;
236 pImageInfo->BitsPerSample[0]= 8;
237 pImageInfo->BitsPerSample[1]= 8;
238 pImageInfo->BitsPerSample[2]= 8;
239 pImageInfo->PixelType = TWPT_RGB;
240 pImageInfo->Planar = FALSE; /* R-G-B is chunky! */
241 pImageInfo->XResolution.Whole = -1;
242 pImageInfo->XResolution.Frac = 0;
243 pImageInfo->YResolution.Whole = -1;
244 pImageInfo->YResolution.Frac = 0;
245 pImageInfo->ImageWidth = activeDS.jd.output_width;
246 pImageInfo->ImageLength = activeDS.jd.output_height;
247 pImageInfo->BitsPerPixel = 24;
248 return TWRC_SUCCESS;
249 #else
250 return TWRC_FAILURE;
251 #endif
254 /* DG_IMAGE/DAT_IMAGELAYOUT/MSG_GET */
255 TW_UINT16 GPHOTO2_ImageLayoutGet (pTW_IDENTITY pOrigin,
256 TW_MEMREF pData)
258 FIXME ("stub!\n");
260 return TWRC_FAILURE;
263 /* DG_IMAGE/DAT_IMAGELAYOUT/MSG_GETDEFAULT */
264 TW_UINT16 GPHOTO2_ImageLayoutGetDefault (pTW_IDENTITY pOrigin,
265 TW_MEMREF pData)
267 FIXME ("stub!\n");
269 return TWRC_FAILURE;
272 /* DG_IMAGE/DAT_IMAGELAYOUT/MSG_RESET */
273 TW_UINT16 GPHOTO2_ImageLayoutReset (pTW_IDENTITY pOrigin,
274 TW_MEMREF pData)
276 FIXME ("stub!\n");
278 return TWRC_FAILURE;
281 /* DG_IMAGE/DAT_IMAGELAYOUT/MSG_SET */
282 TW_UINT16 GPHOTO2_ImageLayoutSet (pTW_IDENTITY pOrigin,
283 TW_MEMREF pData)
285 FIXME ("stub!\n");
287 return TWRC_FAILURE;
290 /* DG_IMAGE/DAT_IMAGEMEMXFER/MSG_GET */
291 TW_UINT16 GPHOTO2_ImageMemXferGet (pTW_IDENTITY pOrigin,
292 TW_MEMREF pData)
294 #ifdef HAVE_GPHOTO2
295 TW_UINT16 twRC = TWRC_SUCCESS;
296 pTW_IMAGEMEMXFER pImageMemXfer = (pTW_IMAGEMEMXFER) pData;
297 LPBYTE buffer;
298 int readrows;
299 unsigned int curoff;
301 TRACE ("DG_IMAGE/DAT_IMAGEMEMXFER/MSG_GET\n");
302 if (activeDS.currentState < 6 || activeDS.currentState > 7) {
303 activeDS.twCC = TWCC_SEQERROR;
304 return TWRC_FAILURE;
306 TRACE("pImageMemXfer.Compression is %d\n", pImageMemXfer->Compression);
307 if (activeDS.currentState == 6) {
308 if (TWRC_SUCCESS != _get_image_and_startup_jpeg()) {
309 FIXME("Failed to get an image\n");
310 activeDS.twCC = TWCC_SEQERROR;
311 return TWRC_FAILURE;
314 if (!activeDS.progressWnd)
315 activeDS.progressWnd = TransferringDialogBox(NULL,0);
316 TransferringDialogBox(activeDS.progressWnd,0);
318 activeDS.currentState = 7;
319 } else {
320 if (!activeDS.file) {
321 activeDS.twCC = TWRC_SUCCESS;
322 return TWRC_XFERDONE;
326 if (pImageMemXfer->Memory.Flags & TWMF_HANDLE) {
327 FIXME("Memory Handle, may not be locked correctly\n");
328 buffer = LocalLock(pImageMemXfer->Memory.TheMem);
329 } else
330 buffer = pImageMemXfer->Memory.TheMem;
332 memset(buffer,0,pImageMemXfer->Memory.Length);
333 curoff = 0; readrows = 0;
334 pImageMemXfer->YOffset = activeDS.jd.output_scanline;
335 pImageMemXfer->XOffset = 0; /* we do whole strips */
336 while ((activeDS.jd.output_scanline<activeDS.jd.output_height) &&
337 ((pImageMemXfer->Memory.Length - curoff) > activeDS.jd.output_width*activeDS.jd.output_components)
339 JSAMPROW row = buffer+curoff;
340 int x = pjpeg_read_scanlines(&activeDS.jd,&row,1);
341 if (x != 1) {
342 FIXME("failed to read current scanline?\n");
343 break;
345 readrows++;
346 curoff += activeDS.jd.output_width*activeDS.jd.output_components;
348 pImageMemXfer->Compression = TWCP_NONE;
349 pImageMemXfer->BytesPerRow = activeDS.jd.output_components * activeDS.jd.output_width;
350 pImageMemXfer->Rows = readrows;
351 pImageMemXfer->Columns = activeDS.jd.output_width; /* we do whole strips */
352 pImageMemXfer->BytesWritten = curoff;
354 TransferringDialogBox(activeDS.progressWnd,0);
356 if (activeDS.jd.output_scanline == activeDS.jd.output_height) {
357 pjpeg_finish_decompress(&activeDS.jd);
358 pjpeg_destroy_decompress(&activeDS.jd);
359 gp_file_unref (activeDS.file);
360 activeDS.file = NULL;
361 TRACE("xfer is done!\n");
363 /*TransferringDialogBox(activeDS.progressWnd, -1);*/
364 twRC = TWRC_XFERDONE;
366 activeDS.twCC = TWRC_SUCCESS;
367 if (pImageMemXfer->Memory.Flags & TWMF_HANDLE)
368 LocalUnlock(pImageMemXfer->Memory.TheMem);
369 return twRC;
370 #else
371 return TWRC_FAILURE;
372 #endif
375 /* DG_IMAGE/DAT_IMAGENATIVEXFER/MSG_GET */
376 TW_UINT16 GPHOTO2_ImageNativeXferGet (pTW_IDENTITY pOrigin,
377 TW_MEMREF pData)
379 #ifdef HAVE_GPHOTO2
380 pTW_UINT32 pHandle = (pTW_UINT32) pData;
381 HBITMAP hDIB;
382 BITMAPINFO bmpInfo;
383 LPBYTE bits;
384 JSAMPROW samprow, oldsamprow;
386 FIXME("DG_IMAGE/DAT_IMAGENATIVEXFER/MSG_GET: implemented, but expect program crash due to DIB.\n");
388 /* NOTE NOTE NOTE NOTE NOTE NOTE NOTE
390 * While this is a mandatory transfer mode and this function
391 * is correctly implemented and fully works, the calling program
392 * will likely crash after calling.
394 * Reason is that there is a lot of example code that does:
395 * bmpinfo = GlobalLock(hBITMAP); ... pointer access to bmpinfo
397 * Our current HBITMAP handles do not support getting GlobalLocked -> App Crash
399 * This needs a GDI Handle rewrite, at least for DIB sections.
400 * - Marcus
402 if (activeDS.currentState != 6) {
403 activeDS.twCC = TWCC_SEQERROR;
404 return TWRC_FAILURE;
406 if (TWRC_SUCCESS != _get_image_and_startup_jpeg()) {
407 FIXME("Failed to get an image\n");
408 activeDS.twCC = TWCC_OPERATIONERROR;
409 return TWRC_FAILURE;
411 TRACE("Acquiring image %dx%dx%d bits from gphoto.\n",
412 activeDS.jd.output_width, activeDS.jd.output_height,
413 activeDS.jd.output_components*8);
414 ZeroMemory (&bmpInfo, sizeof (BITMAPINFO));
415 bmpInfo.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
416 bmpInfo.bmiHeader.biWidth = activeDS.jd.output_width;
417 bmpInfo.bmiHeader.biHeight = -activeDS.jd.output_height;
418 bmpInfo.bmiHeader.biPlanes = 1;
419 bmpInfo.bmiHeader.biBitCount = activeDS.jd.output_components*8;
420 bmpInfo.bmiHeader.biCompression = BI_RGB;
421 bmpInfo.bmiHeader.biSizeImage = 0;
422 bmpInfo.bmiHeader.biXPelsPerMeter = 0;
423 bmpInfo.bmiHeader.biYPelsPerMeter = 0;
424 bmpInfo.bmiHeader.biClrUsed = 0;
425 bmpInfo.bmiHeader.biClrImportant = 0;
426 hDIB = CreateDIBSection (0, &bmpInfo, DIB_RGB_COLORS, (LPVOID)&bits, 0, 0);
427 if (!hDIB) {
428 FIXME("Failed creating DIB.\n");
429 gp_file_unref (activeDS.file);
430 activeDS.file = NULL;
431 activeDS.twCC = TWCC_LOWMEMORY;
432 return TWRC_FAILURE;
434 samprow = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,activeDS.jd.output_width*activeDS.jd.output_components);
435 oldsamprow = samprow;
436 while ( activeDS.jd.output_scanline<activeDS.jd.output_height ) {
437 unsigned int i;
438 int x = pjpeg_read_scanlines(&activeDS.jd,&samprow,1);
439 if (x != 1) {
440 FIXME("failed to read current scanline?\n");
441 break;
443 /* We have to convert from RGB to BGR, see MSDN/ BITMAPINFOHEADER */
444 for(i=0;i<activeDS.jd.output_width;i++,samprow+=activeDS.jd.output_components) {
445 *(bits++) = *(samprow+2);
446 *(bits++) = *(samprow+1);
447 *(bits++) = *(samprow);
449 bits = (LPBYTE)(((UINT_PTR)bits + 3) & ~3);
450 samprow = oldsamprow;
452 HeapFree (GetProcessHeap(), 0, samprow);
453 gp_file_unref (activeDS.file);
454 activeDS.file = NULL;
455 *pHandle = (UINT_PTR)hDIB;
456 activeDS.twCC = TWCC_SUCCESS;
457 activeDS.currentState = 7;
458 return TWRC_XFERDONE;
459 #else
460 return TWRC_FAILURE;
461 #endif
464 /* DG_IMAGE/DAT_JPEGCOMPRESSION/MSG_GET */
465 TW_UINT16 GPHOTO2_JPEGCompressionGet (pTW_IDENTITY pOrigin,
466 TW_MEMREF pData)
468 FIXME ("stub!\n");
470 return TWRC_FAILURE;
473 /* DG_IMAGE/DAT_JPEGCOMPRESSION/MSG_GETDEFAULT */
474 TW_UINT16 GPHOTO2_JPEGCompressionGetDefault (pTW_IDENTITY pOrigin,
476 TW_MEMREF pData)
478 FIXME ("stub!\n");
480 return TWRC_FAILURE;
483 /* DG_IMAGE/DAT_JPEGCOMPRESSION/MSG_RESET */
484 TW_UINT16 GPHOTO2_JPEGCompressionReset (pTW_IDENTITY pOrigin,
485 TW_MEMREF pData)
487 FIXME ("stub!\n");
489 return TWRC_FAILURE;
492 /* DG_IMAGE/DAT_JPEGCOMPRESSION/MSG_SET */
493 TW_UINT16 GPHOTO2_JPEGCompressionSet (pTW_IDENTITY pOrigin,
494 TW_MEMREF pData)
496 FIXME ("stub!\n");
498 return TWRC_FAILURE;
501 /* DG_IMAGE/DAT_PALETTE8/MSG_GET */
502 TW_UINT16 GPHOTO2_Palette8Get (pTW_IDENTITY pOrigin,
503 TW_MEMREF pData)
505 FIXME ("stub!\n");
507 return TWRC_FAILURE;
510 /* DG_IMAGE/DAT_PALETTE8/MSG_GETDEFAULT */
511 TW_UINT16 GPHOTO2_Palette8GetDefault (pTW_IDENTITY pOrigin,
512 TW_MEMREF pData)
514 FIXME ("stub!\n");
516 return TWRC_FAILURE;
519 /* DG_IMAGE/DAT_PALETTE8/MSG_RESET */
520 TW_UINT16 GPHOTO2_Palette8Reset (pTW_IDENTITY pOrigin,
521 TW_MEMREF pData)
523 FIXME ("stub!\n");
525 return TWRC_FAILURE;
528 /* DG_IMAGE/DAT_PALETTE8/MSG_SET */
529 TW_UINT16 GPHOTO2_Palette8Set (pTW_IDENTITY pOrigin,
530 TW_MEMREF pData)
532 FIXME ("stub!\n");
534 return TWRC_FAILURE;
537 /* DG_IMAGE/DAT_RGBRESPONSE/MSG_RESET */
538 TW_UINT16 GPHOTO2_RGBResponseReset (pTW_IDENTITY pOrigin,
539 TW_MEMREF pData)
541 FIXME ("stub!\n");
543 return TWRC_FAILURE;
546 /* DG_IMAGE/DAT_RGBRESPONSE/MSG_SET */
547 TW_UINT16 GPHOTO2_RGBResponseSet (pTW_IDENTITY pOrigin,
548 TW_MEMREF pData)
550 FIXME ("stub!\n");
552 return TWRC_FAILURE;
555 #ifdef HAVE_GPHOTO2
556 TW_UINT16
557 _get_gphoto2_file_as_DIB(
558 const char *folder, const char *filename, CameraFileType type,
559 HWND hwnd, HBITMAP *hDIB
561 const unsigned char *filedata;
562 unsigned long filesize;
563 int ret;
564 CameraFile *file;
565 struct jpeg_source_mgr xjsm;
566 struct jpeg_decompress_struct jd;
567 struct jpeg_error_mgr jerr;
568 BITMAPINFO bmpInfo;
569 LPBYTE bits;
570 JSAMPROW samprow, oldsamprow;
572 if(!libjpeg_handle) {
573 if(!load_libjpeg()) {
574 FIXME("Failed reading JPEG because unable to find %s\n", SONAME_LIBJPEG);
575 filedata = NULL;
576 return TWRC_FAILURE;
580 gp_file_new (&file);
581 ret = gp_camera_file_get(activeDS.camera, folder, filename, type, file, activeDS.context);
582 if (ret < GP_OK) {
583 FIXME("Failed to get file?\n");
584 gp_file_unref (file);
585 return TWRC_FAILURE;
587 ret = gp_file_get_data_and_size (file, (const char**)&filedata, &filesize);
588 if (ret < GP_OK) {
589 FIXME("Failed to get file data?\n");
590 return TWRC_FAILURE;
593 /* FIXME: Actually we might get other types than JPEG ... But only handle JPEG for now */
594 if (filedata[0] != 0xff) {
595 ERR("File %s/%s might not be JPEG, cannot decode!\n", folder, filename);
598 /* This is basically so we can use in-memory data for jpeg decompression.
599 * We need to have all the functions.
601 xjsm.next_input_byte = filedata;
602 xjsm.bytes_in_buffer = filesize;
603 xjsm.init_source = _jpeg_init_source;
604 xjsm.fill_input_buffer = _jpeg_fill_input_buffer;
605 xjsm.skip_input_data = _jpeg_skip_input_data;
606 xjsm.resync_to_restart = _jpeg_resync_to_restart;
607 xjsm.term_source = _jpeg_term_source;
609 jd.err = pjpeg_std_error(&jerr);
610 /* jpeg_create_decompress is a macro that expands to jpeg_CreateDecompress - see jpeglib.h
611 * jpeg_create_decompress(&jd); */
612 pjpeg_CreateDecompress(&jd, JPEG_LIB_VERSION, sizeof(struct jpeg_decompress_struct));
613 jd.src = &xjsm;
614 ret=pjpeg_read_header(&jd,TRUE);
615 jd.out_color_space = JCS_RGB;
616 pjpeg_start_decompress(&jd);
617 if (ret != JPEG_HEADER_OK) {
618 ERR("Jpeg image in stream has bad format, read header returned %d.\n",ret);
619 gp_file_unref (file);
620 return TWRC_FAILURE;
623 ZeroMemory (&bmpInfo, sizeof (BITMAPINFO));
624 bmpInfo.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
625 bmpInfo.bmiHeader.biWidth = jd.output_width;
626 bmpInfo.bmiHeader.biHeight = -jd.output_height;
627 bmpInfo.bmiHeader.biPlanes = 1;
628 bmpInfo.bmiHeader.biBitCount = jd.output_components*8;
629 bmpInfo.bmiHeader.biCompression = BI_RGB;
630 bmpInfo.bmiHeader.biSizeImage = 0;
631 bmpInfo.bmiHeader.biXPelsPerMeter = 0;
632 bmpInfo.bmiHeader.biYPelsPerMeter = 0;
633 bmpInfo.bmiHeader.biClrUsed = 0;
634 bmpInfo.bmiHeader.biClrImportant = 0;
635 *hDIB = CreateDIBSection(0, &bmpInfo, DIB_RGB_COLORS, (LPVOID)&bits, 0, 0);
636 if (!*hDIB) {
637 FIXME("Failed creating DIB.\n");
638 gp_file_unref (file);
639 return TWRC_FAILURE;
641 samprow = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,jd.output_width*jd.output_components);
642 oldsamprow = samprow;
643 while ( jd.output_scanline<jd.output_height ) {
644 unsigned int i;
645 int x = pjpeg_read_scanlines(&jd,&samprow,1);
646 if (x != 1) {
647 FIXME("failed to read current scanline?\n");
648 break;
650 /* We have to convert from RGB to BGR, see MSDN/ BITMAPINFOHEADER */
651 for(i=0;i<jd.output_width;i++,samprow+=jd.output_components) {
652 *(bits++) = *(samprow+2);
653 *(bits++) = *(samprow+1);
654 *(bits++) = *(samprow);
656 bits = (LPBYTE)(((UINT_PTR)bits + 3) & ~3);
657 samprow = oldsamprow;
659 HeapFree (GetProcessHeap(), 0, samprow);
660 gp_file_unref (file);
661 return TWRC_SUCCESS;
663 #endif