riched20: Move underline drawing to a common function.
[wine.git] / dlls / gphoto2.ds / ds_image.c
blobcb3bbed3279964ad84fc745f8bc3cda86be33085
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/library.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(twain);
35 #ifdef HAVE_GPHOTO2
36 static void *libjpeg_handle;
37 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
38 MAKE_FUNCPTR(jpeg_std_error);
39 MAKE_FUNCPTR(jpeg_CreateDecompress);
40 MAKE_FUNCPTR(jpeg_read_header);
41 MAKE_FUNCPTR(jpeg_start_decompress);
42 MAKE_FUNCPTR(jpeg_read_scanlines);
43 MAKE_FUNCPTR(jpeg_finish_decompress);
44 MAKE_FUNCPTR(jpeg_destroy_decompress);
45 #undef MAKE_FUNCPTR
47 static void *load_libjpeg(void)
49 if((libjpeg_handle = wine_dlopen(SONAME_LIBJPEG, RTLD_NOW, NULL, 0)) != NULL) {
51 #define LOAD_FUNCPTR(f) \
52 if((p##f = wine_dlsym(libjpeg_handle, #f, NULL, 0)) == NULL) { \
53 libjpeg_handle = NULL; \
54 return NULL; \
57 LOAD_FUNCPTR(jpeg_std_error);
58 LOAD_FUNCPTR(jpeg_CreateDecompress);
59 LOAD_FUNCPTR(jpeg_read_header);
60 LOAD_FUNCPTR(jpeg_start_decompress);
61 LOAD_FUNCPTR(jpeg_read_scanlines);
62 LOAD_FUNCPTR(jpeg_finish_decompress);
63 LOAD_FUNCPTR(jpeg_destroy_decompress);
64 #undef LOAD_FUNCPTR
66 return libjpeg_handle;
70 /* for the jpeg decompressor source manager. */
71 static void _jpeg_init_source(j_decompress_ptr cinfo) { }
73 static boolean _jpeg_fill_input_buffer(j_decompress_ptr cinfo) {
74 ERR("(), should not get here.\n");
75 return FALSE;
78 static void _jpeg_skip_input_data(j_decompress_ptr cinfo,long num_bytes) {
79 TRACE("Skipping %ld bytes...\n", num_bytes);
80 cinfo->src->next_input_byte += num_bytes;
81 cinfo->src->bytes_in_buffer -= num_bytes;
84 static boolean _jpeg_resync_to_restart(j_decompress_ptr cinfo, int desired) {
85 ERR("(desired=%d), should not get here.\n",desired);
86 return FALSE;
88 static void _jpeg_term_source(j_decompress_ptr cinfo) { }
89 #endif
91 /* DG_IMAGE/DAT_CIECOLOR/MSG_GET */
92 TW_UINT16 GPHOTO2_CIEColorGet (pTW_IDENTITY pOrigin,
93 TW_MEMREF pData)
95 FIXME ("stub!\n");
97 return TWRC_FAILURE;
100 /* DG_IMAGE/DAT_EXTIMAGEINFO/MSG_GET */
101 TW_UINT16 GPHOTO2_ExtImageInfoGet (pTW_IDENTITY pOrigin,
102 TW_MEMREF pData)
104 FIXME ("stub!\n");
106 return TWRC_FAILURE;
109 /* DG_IMAGE/DAT_GRAYRESPONSE/MSG_RESET */
110 TW_UINT16 GPHOTO2_GrayResponseReset (pTW_IDENTITY pOrigin,
111 TW_MEMREF pData)
113 FIXME ("stub!\n");
115 return TWRC_FAILURE;
118 /* DG_IMAGE/DAT_GRAYRESPONSE/MSG_SET */
119 TW_UINT16 GPHOTO2_GrayResponseSet (pTW_IDENTITY pOrigin,
120 TW_MEMREF pData)
122 FIXME ("stub!\n");
124 return TWRC_FAILURE;
127 /* DG_IMAGE/DAT_IMAGEFILEXFER/MSG_GET */
128 TW_UINT16 GPHOTO2_ImageFileXferGet (pTW_IDENTITY pOrigin,
129 TW_MEMREF pData)
131 FIXME ("stub!\n");
133 return TWRC_FAILURE;
136 #ifdef HAVE_GPHOTO2
137 static TW_UINT16 _get_image_and_startup_jpeg(void) {
138 const char *folder = NULL, *filename = NULL;
139 struct gphoto2_file *file;
140 const unsigned char *filedata;
141 unsigned long filesize;
142 int ret;
144 if (activeDS.file) /* Already loaded. */
145 return TWRC_SUCCESS;
147 if(!libjpeg_handle) {
148 if(!load_libjpeg()) {
149 FIXME("Failed reading JPEG because unable to find %s\n", SONAME_LIBJPEG);
150 filedata = NULL;
151 return TWRC_FAILURE;
155 LIST_FOR_EACH_ENTRY( file, &activeDS.files, struct gphoto2_file, entry ) {
156 if (strstr(file->filename,".JPG") || strstr(file->filename,".jpg")) {
157 filename = file->filename;
158 folder = file->folder;
159 TRACE("downloading %s/%s\n", folder, filename);
160 if (file->download) {
161 file->download = FALSE; /* mark as done */
162 break;
166 gp_file_new (&activeDS.file);
167 ret = gp_camera_file_get(activeDS.camera, folder, filename, GP_FILE_TYPE_NORMAL,
168 activeDS.file, activeDS.context);
169 if (ret < GP_OK) {
170 FIXME("Failed to get file?\n");
171 activeDS.twCC = TWCC_SEQERROR;
172 return TWRC_FAILURE;
174 ret = gp_file_get_data_and_size (activeDS.file, (const char**)&filedata, &filesize);
175 if (ret < GP_OK) {
176 FIXME("Failed to get file data?\n");
177 activeDS.twCC = TWCC_SEQERROR;
178 return TWRC_FAILURE;
181 /* This is basically so we can use in-memory data for jpeg decompression.
182 * We need to have all the functions.
184 activeDS.xjsm.next_input_byte = filedata;
185 activeDS.xjsm.bytes_in_buffer = filesize;
186 activeDS.xjsm.init_source = _jpeg_init_source;
187 activeDS.xjsm.fill_input_buffer = _jpeg_fill_input_buffer;
188 activeDS.xjsm.skip_input_data = _jpeg_skip_input_data;
189 activeDS.xjsm.resync_to_restart = _jpeg_resync_to_restart;
190 activeDS.xjsm.term_source = _jpeg_term_source;
192 activeDS.jd.err = pjpeg_std_error(&activeDS.jerr);
193 /* jpeg_create_decompress is a macro that expands to jpeg_CreateDecompress - see jpeglib.h
194 * jpeg_create_decompress(&jd); */
195 pjpeg_CreateDecompress(&activeDS.jd, JPEG_LIB_VERSION, (size_t) sizeof(struct jpeg_decompress_struct));
196 activeDS.jd.src = &activeDS.xjsm;
197 ret=pjpeg_read_header(&activeDS.jd,TRUE);
198 activeDS.jd.out_color_space = JCS_RGB;
199 pjpeg_start_decompress(&activeDS.jd);
200 if (ret != JPEG_HEADER_OK) {
201 ERR("Jpeg image in stream has bad format, read header returned %d.\n",ret);
202 gp_file_unref (activeDS.file);
203 activeDS.file = NULL;
204 return TWRC_FAILURE;
206 return TWRC_SUCCESS;
208 #endif
210 /* DG_IMAGE/DAT_IMAGEINFO/MSG_GET */
211 TW_UINT16 GPHOTO2_ImageInfoGet (pTW_IDENTITY pOrigin,
212 TW_MEMREF pData)
214 #ifdef HAVE_GPHOTO2
215 pTW_IMAGEINFO pImageInfo = (pTW_IMAGEINFO) pData;
217 TRACE("DG_IMAGE/DAT_IMAGEINFO/MSG_GET\n");
219 if (activeDS.currentState != 6 && activeDS.currentState != 7) {
220 activeDS.twCC = TWCC_SEQERROR;
221 return TWRC_FAILURE;
223 if (TWRC_SUCCESS != _get_image_and_startup_jpeg()) {
224 FIXME("Failed to get an image\n");
225 activeDS.twCC = TWCC_SEQERROR;
226 return TWRC_FAILURE;
228 if (activeDS.currentState == 6)
230 /* return general image description information about the image about to be transferred */
231 TRACE("Getting parameters\n");
233 TRACE("activeDS.jd.output_width = %d\n", activeDS.jd.output_width);
234 TRACE("activeDS.jd.output_height = %d\n", activeDS.jd.output_height);
235 pImageInfo->Compression = TWCP_NONE;
236 pImageInfo->SamplesPerPixel = 3;
237 pImageInfo->BitsPerSample[0]= 8;
238 pImageInfo->BitsPerSample[1]= 8;
239 pImageInfo->BitsPerSample[2]= 8;
240 pImageInfo->PixelType = TWPT_RGB;
241 pImageInfo->Planar = FALSE; /* R-G-B is chunky! */
242 pImageInfo->XResolution.Whole = -1;
243 pImageInfo->XResolution.Frac = 0;
244 pImageInfo->YResolution.Whole = -1;
245 pImageInfo->YResolution.Frac = 0;
246 pImageInfo->ImageWidth = activeDS.jd.output_width;
247 pImageInfo->ImageLength = activeDS.jd.output_height;
248 pImageInfo->BitsPerPixel = 24;
249 return TWRC_SUCCESS;
250 #else
251 return TWRC_FAILURE;
252 #endif
255 /* DG_IMAGE/DAT_IMAGELAYOUT/MSG_GET */
256 TW_UINT16 GPHOTO2_ImageLayoutGet (pTW_IDENTITY pOrigin,
257 TW_MEMREF pData)
259 FIXME ("stub!\n");
261 return TWRC_FAILURE;
264 /* DG_IMAGE/DAT_IMAGELAYOUT/MSG_GETDEFAULT */
265 TW_UINT16 GPHOTO2_ImageLayoutGetDefault (pTW_IDENTITY pOrigin,
266 TW_MEMREF pData)
268 FIXME ("stub!\n");
270 return TWRC_FAILURE;
273 /* DG_IMAGE/DAT_IMAGELAYOUT/MSG_RESET */
274 TW_UINT16 GPHOTO2_ImageLayoutReset (pTW_IDENTITY pOrigin,
275 TW_MEMREF pData)
277 FIXME ("stub!\n");
279 return TWRC_FAILURE;
282 /* DG_IMAGE/DAT_IMAGELAYOUT/MSG_SET */
283 TW_UINT16 GPHOTO2_ImageLayoutSet (pTW_IDENTITY pOrigin,
284 TW_MEMREF pData)
286 FIXME ("stub!\n");
288 return TWRC_FAILURE;
291 /* DG_IMAGE/DAT_IMAGEMEMXFER/MSG_GET */
292 TW_UINT16 GPHOTO2_ImageMemXferGet (pTW_IDENTITY pOrigin,
293 TW_MEMREF pData)
295 #ifdef HAVE_GPHOTO2
296 TW_UINT16 twRC = TWRC_SUCCESS;
297 pTW_IMAGEMEMXFER pImageMemXfer = (pTW_IMAGEMEMXFER) pData;
298 LPBYTE buffer;
299 int readrows;
300 unsigned int curoff;
302 TRACE ("DG_IMAGE/DAT_IMAGEMEMXFER/MSG_GET\n");
303 if (activeDS.currentState < 6 || activeDS.currentState > 7) {
304 activeDS.twCC = TWCC_SEQERROR;
305 return TWRC_FAILURE;
307 TRACE("pImageMemXfer.Compression is %d\n", pImageMemXfer->Compression);
308 if (activeDS.currentState == 6) {
309 if (TWRC_SUCCESS != _get_image_and_startup_jpeg()) {
310 FIXME("Failed to get an image\n");
311 activeDS.twCC = TWCC_SEQERROR;
312 return TWRC_FAILURE;
315 if (!activeDS.progressWnd)
316 activeDS.progressWnd = TransferringDialogBox(NULL,0);
317 TransferringDialogBox(activeDS.progressWnd,0);
319 activeDS.currentState = 7;
320 } else {
321 if (!activeDS.file) {
322 activeDS.twCC = TWRC_SUCCESS;
323 return TWRC_XFERDONE;
327 if (pImageMemXfer->Memory.Flags & TWMF_HANDLE) {
328 FIXME("Memory Handle, may not be locked correctly\n");
329 buffer = LocalLock(pImageMemXfer->Memory.TheMem);
330 } else
331 buffer = pImageMemXfer->Memory.TheMem;
333 memset(buffer,0,pImageMemXfer->Memory.Length);
334 curoff = 0; readrows = 0;
335 pImageMemXfer->YOffset = activeDS.jd.output_scanline;
336 pImageMemXfer->XOffset = 0; /* we do whole strips */
337 while ((activeDS.jd.output_scanline<activeDS.jd.output_height) &&
338 ((pImageMemXfer->Memory.Length - curoff) > activeDS.jd.output_width*activeDS.jd.output_components)
340 JSAMPROW row = buffer+curoff;
341 int x = pjpeg_read_scanlines(&activeDS.jd,&row,1);
342 if (x != 1) {
343 FIXME("failed to read current scanline?\n");
344 break;
346 readrows++;
347 curoff += activeDS.jd.output_width*activeDS.jd.output_components;
349 pImageMemXfer->Compression = TWCP_NONE;
350 pImageMemXfer->BytesPerRow = activeDS.jd.output_components * activeDS.jd.output_width;
351 pImageMemXfer->Rows = readrows;
352 pImageMemXfer->Columns = activeDS.jd.output_width; /* we do whole strips */
353 pImageMemXfer->BytesWritten = curoff;
355 TransferringDialogBox(activeDS.progressWnd,0);
357 if (activeDS.jd.output_scanline == activeDS.jd.output_height) {
358 pjpeg_finish_decompress(&activeDS.jd);
359 pjpeg_destroy_decompress(&activeDS.jd);
360 gp_file_unref (activeDS.file);
361 activeDS.file = NULL;
362 TRACE("xfer is done!\n");
364 /*TransferringDialogBox(activeDS.progressWnd, -1);*/
365 twRC = TWRC_XFERDONE;
367 activeDS.twCC = TWRC_SUCCESS;
368 if (pImageMemXfer->Memory.Flags & TWMF_HANDLE)
369 LocalUnlock(pImageMemXfer->Memory.TheMem);
370 return twRC;
371 #else
372 return TWRC_FAILURE;
373 #endif
376 /* DG_IMAGE/DAT_IMAGENATIVEXFER/MSG_GET */
377 TW_UINT16 GPHOTO2_ImageNativeXferGet (pTW_IDENTITY pOrigin,
378 TW_MEMREF pData)
380 #ifdef HAVE_GPHOTO2
381 pTW_UINT32 pHandle = (pTW_UINT32) pData;
382 HBITMAP hDIB;
383 BITMAPINFO bmpInfo;
384 LPBYTE bits;
385 JSAMPROW samprow, oldsamprow;
387 FIXME("DG_IMAGE/DAT_IMAGENATIVEXFER/MSG_GET: implemented, but expect program crash due to DIB.\n");
389 /* NOTE NOTE NOTE NOTE NOTE NOTE NOTE
391 * While this is a mandatory transfer mode and this function
392 * is correctly implemented and fully works, the calling program
393 * will likely crash after calling.
395 * Reason is that there is a lot of example code that does:
396 * bmpinfo = GlobalLock(hBITMAP); ... pointer access to bmpinfo
398 * Our current HBITMAP handles do not support getting GlobalLocked -> App Crash
400 * This needs a GDI Handle rewrite, at least for DIB sections.
401 * - Marcus
403 if (activeDS.currentState != 6) {
404 activeDS.twCC = TWCC_SEQERROR;
405 return TWRC_FAILURE;
407 if (TWRC_SUCCESS != _get_image_and_startup_jpeg()) {
408 FIXME("Failed to get an image\n");
409 activeDS.twCC = TWCC_OPERATIONERROR;
410 return TWRC_FAILURE;
412 TRACE("Acquiring image %dx%dx%d bits from gphoto.\n",
413 activeDS.jd.output_width, activeDS.jd.output_height,
414 activeDS.jd.output_components*8);
415 ZeroMemory (&bmpInfo, sizeof (BITMAPINFO));
416 bmpInfo.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
417 bmpInfo.bmiHeader.biWidth = activeDS.jd.output_width;
418 bmpInfo.bmiHeader.biHeight = -activeDS.jd.output_height;
419 bmpInfo.bmiHeader.biPlanes = 1;
420 bmpInfo.bmiHeader.biBitCount = activeDS.jd.output_components*8;
421 bmpInfo.bmiHeader.biCompression = BI_RGB;
422 bmpInfo.bmiHeader.biSizeImage = 0;
423 bmpInfo.bmiHeader.biXPelsPerMeter = 0;
424 bmpInfo.bmiHeader.biYPelsPerMeter = 0;
425 bmpInfo.bmiHeader.biClrUsed = 0;
426 bmpInfo.bmiHeader.biClrImportant = 0;
427 hDIB = CreateDIBSection (0, &bmpInfo, DIB_RGB_COLORS, (LPVOID)&bits, 0, 0);
428 if (!hDIB) {
429 FIXME("Failed creating DIB.\n");
430 gp_file_unref (activeDS.file);
431 activeDS.file = NULL;
432 activeDS.twCC = TWCC_LOWMEMORY;
433 return TWRC_FAILURE;
435 samprow = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,activeDS.jd.output_width*activeDS.jd.output_components);
436 oldsamprow = samprow;
437 while ( activeDS.jd.output_scanline<activeDS.jd.output_height ) {
438 unsigned int i;
439 int x = pjpeg_read_scanlines(&activeDS.jd,&samprow,1);
440 if (x != 1) {
441 FIXME("failed to read current scanline?\n");
442 break;
444 /* We have to convert from RGB to BGR, see MSDN/ BITMAPINFOHEADER */
445 for(i=0;i<activeDS.jd.output_width;i++,samprow+=activeDS.jd.output_components) {
446 *(bits++) = *(samprow+2);
447 *(bits++) = *(samprow+1);
448 *(bits++) = *(samprow);
450 bits = (LPBYTE)(((UINT_PTR)bits + 3) & ~3);
451 samprow = oldsamprow;
453 HeapFree (GetProcessHeap(), 0, samprow);
454 gp_file_unref (activeDS.file);
455 activeDS.file = NULL;
456 *pHandle = (UINT_PTR)hDIB;
457 activeDS.twCC = TWCC_SUCCESS;
458 activeDS.currentState = 7;
459 return TWRC_XFERDONE;
460 #else
461 return TWRC_FAILURE;
462 #endif
465 /* DG_IMAGE/DAT_JPEGCOMPRESSION/MSG_GET */
466 TW_UINT16 GPHOTO2_JPEGCompressionGet (pTW_IDENTITY pOrigin,
467 TW_MEMREF pData)
469 FIXME ("stub!\n");
471 return TWRC_FAILURE;
474 /* DG_IMAGE/DAT_JPEGCOMPRESSION/MSG_GETDEFAULT */
475 TW_UINT16 GPHOTO2_JPEGCompressionGetDefault (pTW_IDENTITY pOrigin,
477 TW_MEMREF pData)
479 FIXME ("stub!\n");
481 return TWRC_FAILURE;
484 /* DG_IMAGE/DAT_JPEGCOMPRESSION/MSG_RESET */
485 TW_UINT16 GPHOTO2_JPEGCompressionReset (pTW_IDENTITY pOrigin,
486 TW_MEMREF pData)
488 FIXME ("stub!\n");
490 return TWRC_FAILURE;
493 /* DG_IMAGE/DAT_JPEGCOMPRESSION/MSG_SET */
494 TW_UINT16 GPHOTO2_JPEGCompressionSet (pTW_IDENTITY pOrigin,
495 TW_MEMREF pData)
497 FIXME ("stub!\n");
499 return TWRC_FAILURE;
502 /* DG_IMAGE/DAT_PALETTE8/MSG_GET */
503 TW_UINT16 GPHOTO2_Palette8Get (pTW_IDENTITY pOrigin,
504 TW_MEMREF pData)
506 FIXME ("stub!\n");
508 return TWRC_FAILURE;
511 /* DG_IMAGE/DAT_PALETTE8/MSG_GETDEFAULT */
512 TW_UINT16 GPHOTO2_Palette8GetDefault (pTW_IDENTITY pOrigin,
513 TW_MEMREF pData)
515 FIXME ("stub!\n");
517 return TWRC_FAILURE;
520 /* DG_IMAGE/DAT_PALETTE8/MSG_RESET */
521 TW_UINT16 GPHOTO2_Palette8Reset (pTW_IDENTITY pOrigin,
522 TW_MEMREF pData)
524 FIXME ("stub!\n");
526 return TWRC_FAILURE;
529 /* DG_IMAGE/DAT_PALETTE8/MSG_SET */
530 TW_UINT16 GPHOTO2_Palette8Set (pTW_IDENTITY pOrigin,
531 TW_MEMREF pData)
533 FIXME ("stub!\n");
535 return TWRC_FAILURE;
538 /* DG_IMAGE/DAT_RGBRESPONSE/MSG_RESET */
539 TW_UINT16 GPHOTO2_RGBResponseReset (pTW_IDENTITY pOrigin,
540 TW_MEMREF pData)
542 FIXME ("stub!\n");
544 return TWRC_FAILURE;
547 /* DG_IMAGE/DAT_RGBRESPONSE/MSG_SET */
548 TW_UINT16 GPHOTO2_RGBResponseSet (pTW_IDENTITY pOrigin,
549 TW_MEMREF pData)
551 FIXME ("stub!\n");
553 return TWRC_FAILURE;
556 #ifdef HAVE_GPHOTO2
557 TW_UINT16
558 _get_gphoto2_file_as_DIB(
559 const char *folder, const char *filename, CameraFileType type,
560 HWND hwnd, HBITMAP *hDIB
562 const unsigned char *filedata;
563 unsigned long filesize;
564 int ret;
565 CameraFile *file;
566 struct jpeg_source_mgr xjsm;
567 struct jpeg_decompress_struct jd;
568 struct jpeg_error_mgr jerr;
569 BITMAPINFO bmpInfo;
570 LPBYTE bits;
571 JSAMPROW samprow, oldsamprow;
573 if(!libjpeg_handle) {
574 if(!load_libjpeg()) {
575 FIXME("Failed reading JPEG because unable to find %s\n", SONAME_LIBJPEG);
576 filedata = NULL;
577 return TWRC_FAILURE;
581 gp_file_new (&file);
582 ret = gp_camera_file_get(activeDS.camera, folder, filename, type, file, activeDS.context);
583 if (ret < GP_OK) {
584 FIXME("Failed to get file?\n");
585 gp_file_unref (file);
586 return TWRC_FAILURE;
588 ret = gp_file_get_data_and_size (file, (const char**)&filedata, &filesize);
589 if (ret < GP_OK) {
590 FIXME("Failed to get file data?\n");
591 return TWRC_FAILURE;
594 /* FIXME: Actually we might get other types than JPEG ... But only handle JPEG for now */
595 if (filedata[0] != 0xff) {
596 ERR("File %s/%s might not be JPEG, cannot decode!\n", folder, filename);
599 /* This is basically so we can use in-memory data for jpeg decompression.
600 * We need to have all the functions.
602 xjsm.next_input_byte = filedata;
603 xjsm.bytes_in_buffer = filesize;
604 xjsm.init_source = _jpeg_init_source;
605 xjsm.fill_input_buffer = _jpeg_fill_input_buffer;
606 xjsm.skip_input_data = _jpeg_skip_input_data;
607 xjsm.resync_to_restart = _jpeg_resync_to_restart;
608 xjsm.term_source = _jpeg_term_source;
610 jd.err = pjpeg_std_error(&jerr);
611 /* jpeg_create_decompress is a macro that expands to jpeg_CreateDecompress - see jpeglib.h
612 * jpeg_create_decompress(&jd); */
613 pjpeg_CreateDecompress(&jd, JPEG_LIB_VERSION, (size_t) sizeof(struct jpeg_decompress_struct));
614 jd.src = &xjsm;
615 ret=pjpeg_read_header(&jd,TRUE);
616 jd.out_color_space = JCS_RGB;
617 pjpeg_start_decompress(&jd);
618 if (ret != JPEG_HEADER_OK) {
619 ERR("Jpeg image in stream has bad format, read header returned %d.\n",ret);
620 gp_file_unref (file);
621 return TWRC_FAILURE;
624 ZeroMemory (&bmpInfo, sizeof (BITMAPINFO));
625 bmpInfo.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
626 bmpInfo.bmiHeader.biWidth = jd.output_width;
627 bmpInfo.bmiHeader.biHeight = -jd.output_height;
628 bmpInfo.bmiHeader.biPlanes = 1;
629 bmpInfo.bmiHeader.biBitCount = jd.output_components*8;
630 bmpInfo.bmiHeader.biCompression = BI_RGB;
631 bmpInfo.bmiHeader.biSizeImage = 0;
632 bmpInfo.bmiHeader.biXPelsPerMeter = 0;
633 bmpInfo.bmiHeader.biYPelsPerMeter = 0;
634 bmpInfo.bmiHeader.biClrUsed = 0;
635 bmpInfo.bmiHeader.biClrImportant = 0;
636 *hDIB = CreateDIBSection(0, &bmpInfo, DIB_RGB_COLORS, (LPVOID)&bits, 0, 0);
637 if (!*hDIB) {
638 FIXME("Failed creating DIB.\n");
639 gp_file_unref (file);
640 return TWRC_FAILURE;
642 samprow = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,jd.output_width*jd.output_components);
643 oldsamprow = samprow;
644 while ( jd.output_scanline<jd.output_height ) {
645 unsigned int i;
646 int x = pjpeg_read_scanlines(&jd,&samprow,1);
647 if (x != 1) {
648 FIXME("failed to read current scanline?\n");
649 break;
651 /* We have to convert from RGB to BGR, see MSDN/ BITMAPINFOHEADER */
652 for(i=0;i<jd.output_width;i++,samprow+=jd.output_components) {
653 *(bits++) = *(samprow+2);
654 *(bits++) = *(samprow+1);
655 *(bits++) = *(samprow);
657 bits = (LPBYTE)(((UINT_PTR)bits + 3) & ~3);
658 samprow = oldsamprow;
660 HeapFree (GetProcessHeap(), 0, samprow);
661 gp_file_unref (file);
662 return TWRC_SUCCESS;
664 #endif