po: Fix Finnish translation.
[wine/multimedia.git] / dlls / gphoto2.ds / ds_image.c
blobc870ec4bdfbc0c74c3b382aa59156c65c00da97c
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;
386 HDC dc;
388 FIXME("DG_IMAGE/DAT_IMAGENATIVEXFER/MSG_GET: implemented, but expect program crash due to DIB.\n");
390 /* NOTE NOTE NOTE NOTE NOTE NOTE NOTE
392 * While this is a mandatory transfer mode and this function
393 * is correctly implemented and fully works, the calling program
394 * will likely crash after calling.
396 * Reason is that there is a lot of example code that does:
397 * bmpinfo = GlobalLock(hBITMAP); ... pointer access to bmpinfo
399 * Our current HBITMAP handles do not support getting GlobalLocked -> App Crash
401 * This needs a GDI Handle rewrite, at least for DIB sections.
402 * - Marcus
404 if (activeDS.currentState != 6) {
405 activeDS.twCC = TWCC_SEQERROR;
406 return TWRC_FAILURE;
408 if (TWRC_SUCCESS != _get_image_and_startup_jpeg()) {
409 FIXME("Failed to get an image\n");
410 activeDS.twCC = TWCC_OPERATIONERROR;
411 return TWRC_FAILURE;
413 TRACE("Acquiring image %dx%dx%d bits from gphoto.\n",
414 activeDS.jd.output_width, activeDS.jd.output_height,
415 activeDS.jd.output_components*8);
416 ZeroMemory (&bmpInfo, sizeof (BITMAPINFO));
417 bmpInfo.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
418 bmpInfo.bmiHeader.biWidth = activeDS.jd.output_width;
419 bmpInfo.bmiHeader.biHeight = -activeDS.jd.output_height;
420 bmpInfo.bmiHeader.biPlanes = 1;
421 bmpInfo.bmiHeader.biBitCount = activeDS.jd.output_components*8;
422 bmpInfo.bmiHeader.biCompression = BI_RGB;
423 bmpInfo.bmiHeader.biSizeImage = 0;
424 bmpInfo.bmiHeader.biXPelsPerMeter = 0;
425 bmpInfo.bmiHeader.biYPelsPerMeter = 0;
426 bmpInfo.bmiHeader.biClrUsed = 0;
427 bmpInfo.bmiHeader.biClrImportant = 0;
428 hDIB = CreateDIBSection ((dc = GetDC(activeDS.hwndOwner)), &bmpInfo,
429 DIB_RGB_COLORS, (LPVOID)&bits, 0, 0);
430 if (!hDIB) {
431 FIXME("Failed creating DIB.\n");
432 gp_file_unref (activeDS.file);
433 activeDS.file = NULL;
434 activeDS.twCC = TWCC_LOWMEMORY;
435 return TWRC_FAILURE;
437 samprow = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,activeDS.jd.output_width*activeDS.jd.output_components);
438 oldsamprow = samprow;
439 while ( activeDS.jd.output_scanline<activeDS.jd.output_height ) {
440 int i, x = pjpeg_read_scanlines(&activeDS.jd,&samprow,1);
441 if (x != 1) {
442 FIXME("failed to read current scanline?\n");
443 break;
445 /* We have to convert from RGB to BGR, see MSDN/ BITMAPINFOHEADER */
446 for(i=0;i<activeDS.jd.output_width;i++,samprow+=activeDS.jd.output_components) {
447 *(bits++) = *(samprow+2);
448 *(bits++) = *(samprow+1);
449 *(bits++) = *(samprow);
451 bits = (LPBYTE)(((UINT_PTR)bits + 3) & ~3);
452 samprow = oldsamprow;
454 HeapFree (GetProcessHeap(), 0, samprow);
455 gp_file_unref (activeDS.file);
456 activeDS.file = NULL;
457 ReleaseDC (activeDS.hwndOwner, dc);
458 *pHandle = (UINT_PTR)hDIB;
459 activeDS.twCC = TWCC_SUCCESS;
460 activeDS.currentState = 7;
461 return TWRC_XFERDONE;
462 #else
463 return TWRC_FAILURE;
464 #endif
467 /* DG_IMAGE/DAT_JPEGCOMPRESSION/MSG_GET */
468 TW_UINT16 GPHOTO2_JPEGCompressionGet (pTW_IDENTITY pOrigin,
469 TW_MEMREF pData)
471 FIXME ("stub!\n");
473 return TWRC_FAILURE;
476 /* DG_IMAGE/DAT_JPEGCOMPRESSION/MSG_GETDEFAULT */
477 TW_UINT16 GPHOTO2_JPEGCompressionGetDefault (pTW_IDENTITY pOrigin,
479 TW_MEMREF pData)
481 FIXME ("stub!\n");
483 return TWRC_FAILURE;
486 /* DG_IMAGE/DAT_JPEGCOMPRESSION/MSG_RESET */
487 TW_UINT16 GPHOTO2_JPEGCompressionReset (pTW_IDENTITY pOrigin,
488 TW_MEMREF pData)
490 FIXME ("stub!\n");
492 return TWRC_FAILURE;
495 /* DG_IMAGE/DAT_JPEGCOMPRESSION/MSG_SET */
496 TW_UINT16 GPHOTO2_JPEGCompressionSet (pTW_IDENTITY pOrigin,
497 TW_MEMREF pData)
499 FIXME ("stub!\n");
501 return TWRC_FAILURE;
504 /* DG_IMAGE/DAT_PALETTE8/MSG_GET */
505 TW_UINT16 GPHOTO2_Palette8Get (pTW_IDENTITY pOrigin,
506 TW_MEMREF pData)
508 FIXME ("stub!\n");
510 return TWRC_FAILURE;
513 /* DG_IMAGE/DAT_PALETTE8/MSG_GETDEFAULT */
514 TW_UINT16 GPHOTO2_Palette8GetDefault (pTW_IDENTITY pOrigin,
515 TW_MEMREF pData)
517 FIXME ("stub!\n");
519 return TWRC_FAILURE;
522 /* DG_IMAGE/DAT_PALETTE8/MSG_RESET */
523 TW_UINT16 GPHOTO2_Palette8Reset (pTW_IDENTITY pOrigin,
524 TW_MEMREF pData)
526 FIXME ("stub!\n");
528 return TWRC_FAILURE;
531 /* DG_IMAGE/DAT_PALETTE8/MSG_SET */
532 TW_UINT16 GPHOTO2_Palette8Set (pTW_IDENTITY pOrigin,
533 TW_MEMREF pData)
535 FIXME ("stub!\n");
537 return TWRC_FAILURE;
540 /* DG_IMAGE/DAT_RGBRESPONSE/MSG_RESET */
541 TW_UINT16 GPHOTO2_RGBResponseReset (pTW_IDENTITY pOrigin,
542 TW_MEMREF pData)
544 FIXME ("stub!\n");
546 return TWRC_FAILURE;
549 /* DG_IMAGE/DAT_RGBRESPONSE/MSG_SET */
550 TW_UINT16 GPHOTO2_RGBResponseSet (pTW_IDENTITY pOrigin,
551 TW_MEMREF pData)
553 FIXME ("stub!\n");
555 return TWRC_FAILURE;
558 #ifdef HAVE_GPHOTO2
559 TW_UINT16
560 _get_gphoto2_file_as_DIB(
561 const char *folder, const char *filename, CameraFileType type,
562 HWND hwnd, HBITMAP *hDIB
564 const unsigned char *filedata;
565 unsigned long filesize;
566 int ret;
567 CameraFile *file;
568 struct jpeg_source_mgr xjsm;
569 struct jpeg_decompress_struct jd;
570 struct jpeg_error_mgr jerr;
571 HDC dc;
572 BITMAPINFO bmpInfo;
573 LPBYTE bits;
574 JSAMPROW samprow, oldsamprow;
576 if(!libjpeg_handle) {
577 if(!load_libjpeg()) {
578 FIXME("Failed reading JPEG because unable to find %s\n", SONAME_LIBJPEG);
579 filedata = NULL;
580 return TWRC_FAILURE;
584 gp_file_new (&file);
585 ret = gp_camera_file_get(activeDS.camera, folder, filename, type, file, activeDS.context);
586 if (ret < GP_OK) {
587 FIXME("Failed to get file?\n");
588 gp_file_unref (file);
589 return TWRC_FAILURE;
591 ret = gp_file_get_data_and_size (file, (const char**)&filedata, &filesize);
592 if (ret < GP_OK) {
593 FIXME("Failed to get file data?\n");
594 return TWRC_FAILURE;
597 /* FIXME: Actually we might get other types than JPEG ... But only handle JPEG for now */
598 if (filedata[0] != 0xff) {
599 ERR("File %s/%s might not be JPEG, cannot decode!\n", folder, filename);
602 /* This is basically so we can use in-memory data for jpeg decompression.
603 * We need to have all the functions.
605 xjsm.next_input_byte = filedata;
606 xjsm.bytes_in_buffer = filesize;
607 xjsm.init_source = _jpeg_init_source;
608 xjsm.fill_input_buffer = _jpeg_fill_input_buffer;
609 xjsm.skip_input_data = _jpeg_skip_input_data;
610 xjsm.resync_to_restart = _jpeg_resync_to_restart;
611 xjsm.term_source = _jpeg_term_source;
613 jd.err = pjpeg_std_error(&jerr);
614 /* jpeg_create_decompress is a macro that expands to jpeg_CreateDecompress - see jpeglib.h
615 * jpeg_create_decompress(&jd); */
616 pjpeg_CreateDecompress(&jd, JPEG_LIB_VERSION, (size_t) sizeof(struct jpeg_decompress_struct));
617 jd.src = &xjsm;
618 ret=pjpeg_read_header(&jd,TRUE);
619 jd.out_color_space = JCS_RGB;
620 pjpeg_start_decompress(&jd);
621 if (ret != JPEG_HEADER_OK) {
622 ERR("Jpeg image in stream has bad format, read header returned %d.\n",ret);
623 gp_file_unref (file);
624 return TWRC_FAILURE;
627 ZeroMemory (&bmpInfo, sizeof (BITMAPINFO));
628 bmpInfo.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
629 bmpInfo.bmiHeader.biWidth = jd.output_width;
630 bmpInfo.bmiHeader.biHeight = -jd.output_height;
631 bmpInfo.bmiHeader.biPlanes = 1;
632 bmpInfo.bmiHeader.biBitCount = jd.output_components*8;
633 bmpInfo.bmiHeader.biCompression = BI_RGB;
634 bmpInfo.bmiHeader.biSizeImage = 0;
635 bmpInfo.bmiHeader.biXPelsPerMeter = 0;
636 bmpInfo.bmiHeader.biYPelsPerMeter = 0;
637 bmpInfo.bmiHeader.biClrUsed = 0;
638 bmpInfo.bmiHeader.biClrImportant = 0;
639 *hDIB = CreateDIBSection ((dc = GetDC(hwnd)), &bmpInfo, DIB_RGB_COLORS, (LPVOID)&bits, 0, 0);
640 if (!*hDIB) {
641 FIXME("Failed creating DIB.\n");
642 gp_file_unref (file);
643 return TWRC_FAILURE;
645 samprow = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,jd.output_width*jd.output_components);
646 oldsamprow = samprow;
647 while ( jd.output_scanline<jd.output_height ) {
648 int i, x = pjpeg_read_scanlines(&jd,&samprow,1);
649 if (x != 1) {
650 FIXME("failed to read current scanline?\n");
651 break;
653 /* We have to convert from RGB to BGR, see MSDN/ BITMAPINFOHEADER */
654 for(i=0;i<jd.output_width;i++,samprow+=jd.output_components) {
655 *(bits++) = *(samprow+2);
656 *(bits++) = *(samprow+1);
657 *(bits++) = *(samprow);
659 bits = (LPBYTE)(((UINT_PTR)bits + 3) & ~3);
660 samprow = oldsamprow;
662 if (hwnd) ReleaseDC (hwnd, dc);
663 HeapFree (GetProcessHeap(), 0, samprow);
664 gp_file_unref (file);
665 return TWRC_SUCCESS;
667 #endif