Logo Search packages:      
Sourcecode: wine version File versions  Download package

ds_image.c

/*
 * Copyright 2000 Corel Corporation
 * Copyright 2006 Marcus Meissner
 * Copyright 2006 CodeWeavers, Aric Stewart
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include "config.h"
#include "wine/port.h"
#include "wine/library.h"

#include <stdarg.h>
#include <stdio.h>

#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "twain.h"
#include "gphoto2_i.h"
#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(twain);

#ifdef HAVE_GPHOTO2
static void *libjpeg_handle;
#define MAKE_FUNCPTR(f) static typeof(f) * p##f
MAKE_FUNCPTR(jpeg_std_error);
MAKE_FUNCPTR(jpeg_CreateDecompress);
MAKE_FUNCPTR(jpeg_read_header);
MAKE_FUNCPTR(jpeg_start_decompress);
MAKE_FUNCPTR(jpeg_read_scanlines);
MAKE_FUNCPTR(jpeg_finish_decompress);
MAKE_FUNCPTR(jpeg_destroy_decompress);
#undef MAKE_FUNCPTR

static void *load_libjpeg(void)
{
    if((libjpeg_handle = wine_dlopen(SONAME_LIBJPEG, RTLD_NOW, NULL, 0)) != NULL) {

#define LOAD_FUNCPTR(f) \
    if((p##f = wine_dlsym(libjpeg_handle, #f, NULL, 0)) == NULL) { \
        libjpeg_handle = NULL; \
        return NULL; \
    }

        LOAD_FUNCPTR(jpeg_std_error);
        LOAD_FUNCPTR(jpeg_CreateDecompress);
        LOAD_FUNCPTR(jpeg_read_header);
        LOAD_FUNCPTR(jpeg_start_decompress);
        LOAD_FUNCPTR(jpeg_read_scanlines);
        LOAD_FUNCPTR(jpeg_finish_decompress);
        LOAD_FUNCPTR(jpeg_destroy_decompress);
#undef LOAD_FUNCPTR
    }
    return libjpeg_handle;
}


/* for the jpeg decompressor source manager. */
static void _jpeg_init_source(j_decompress_ptr cinfo) { }

static boolean _jpeg_fill_input_buffer(j_decompress_ptr cinfo) {
    ERR("(), should not get here.\n");
    return FALSE;
}

static void _jpeg_skip_input_data(j_decompress_ptr cinfo,long num_bytes) {
    TRACE("Skipping %ld bytes...\n", num_bytes);
    cinfo->src->next_input_byte += num_bytes;
    cinfo->src->bytes_in_buffer -= num_bytes;
}

static boolean _jpeg_resync_to_restart(j_decompress_ptr cinfo, int desired) {
    ERR("(desired=%d), should not get here.\n",desired);
    return FALSE;
}
static void _jpeg_term_source(j_decompress_ptr cinfo) { }
#endif

/* DG_IMAGE/DAT_CIECOLOR/MSG_GET */
TW_UINT16 GPHOTO2_CIEColorGet (pTW_IDENTITY pOrigin, 
                             TW_MEMREF pData)
{
    FIXME ("stub!\n");

    return TWRC_FAILURE;
}

/* DG_IMAGE/DAT_EXTIMAGEINFO/MSG_GET */
TW_UINT16 GPHOTO2_ExtImageInfoGet (pTW_IDENTITY pOrigin, 
                                 TW_MEMREF pData)
{
    FIXME ("stub!\n");

    return TWRC_FAILURE;
}

/* DG_IMAGE/DAT_GRAYRESPONSE/MSG_RESET */
TW_UINT16 GPHOTO2_GrayResponseReset (pTW_IDENTITY pOrigin, 
                                   TW_MEMREF pData)
{
    FIXME ("stub!\n");

    return TWRC_FAILURE;
}

/* DG_IMAGE/DAT_GRAYRESPONSE/MSG_SET */
TW_UINT16 GPHOTO2_GrayResponseSet (pTW_IDENTITY pOrigin, 
                                 TW_MEMREF pData)
{
    FIXME ("stub!\n");

    return TWRC_FAILURE;
}

/* DG_IMAGE/DAT_IMAGEFILEXFER/MSG_GET */
TW_UINT16 GPHOTO2_ImageFileXferGet (pTW_IDENTITY pOrigin, 
                                  TW_MEMREF pData)
{
    FIXME ("stub!\n");

    return TWRC_FAILURE;
}

#ifdef HAVE_GPHOTO2
static TW_UINT16 _get_image_and_startup_jpeg(void) {
    const char *folder = NULL, *filename = NULL;
    struct gphoto2_file *file;
    const unsigned char *filedata;
    unsigned long filesize;
    int ret;

    if (activeDS.file) /* Already loaded. */
      return TWRC_SUCCESS;

    if(!libjpeg_handle) {
      if(!load_libjpeg()) {
          FIXME("Failed reading JPEG because unable to find %s\n", SONAME_LIBJPEG);
          filedata = NULL;
          return TWRC_FAILURE;
      }
    }

    LIST_FOR_EACH_ENTRY( file, &activeDS.files, struct gphoto2_file, entry ) {
      if (strstr(file->filename,".JPG") || strstr(file->filename,".jpg")) {
          filename = file->filename;
          folder = file->folder;
          TRACE("downloading %s/%s\n", folder, filename);
          if (file->download) {
            file->download = FALSE; /* mark as done */
            break;
          }
      }
    }
    gp_file_new (&activeDS.file);
    ret = gp_camera_file_get(activeDS.camera, folder, filename, GP_FILE_TYPE_NORMAL,
                       activeDS.file, activeDS.context);
    if (ret < GP_OK) {
      FIXME("Failed to get file?\n");
      activeDS.twCC = TWCC_SEQERROR;
      return TWRC_FAILURE;
    }
    ret = gp_file_get_data_and_size (activeDS.file, (const char**)&filedata, &filesize);
    if (ret < GP_OK) {
      FIXME("Failed to get file data?\n");
      activeDS.twCC = TWCC_SEQERROR;
      return TWRC_FAILURE;
    }

    /* This is basically so we can use in-memory data for jpeg decompression.
     * We need to have all the functions.
     */
    activeDS.xjsm.next_input_byte   = filedata;
    activeDS.xjsm.bytes_in_buffer   = filesize;
    activeDS.xjsm.init_source = _jpeg_init_source;
    activeDS.xjsm.fill_input_buffer = _jpeg_fill_input_buffer;
    activeDS.xjsm.skip_input_data   = _jpeg_skip_input_data;
    activeDS.xjsm.resync_to_restart = _jpeg_resync_to_restart;
    activeDS.xjsm.term_source = _jpeg_term_source;

    activeDS.jd.err = pjpeg_std_error(&activeDS.jerr);
    /* jpeg_create_decompress is a macro that expands to jpeg_CreateDecompress - see jpeglib.h
     * jpeg_create_decompress(&jd); */
    pjpeg_CreateDecompress(&activeDS.jd, JPEG_LIB_VERSION, (size_t) sizeof(struct jpeg_decompress_struct));
    activeDS.jd.src = &activeDS.xjsm;
    ret=pjpeg_read_header(&activeDS.jd,TRUE);
    activeDS.jd.out_color_space = JCS_RGB;
    pjpeg_start_decompress(&activeDS.jd);
    if (ret != JPEG_HEADER_OK) {
      ERR("Jpeg image in stream has bad format, read header returned %d.\n",ret);
      gp_file_unref (activeDS.file);
      activeDS.file = NULL;
      return TWRC_FAILURE;
    }
    return TWRC_SUCCESS;
}
#endif

/* DG_IMAGE/DAT_IMAGEINFO/MSG_GET */
TW_UINT16 GPHOTO2_ImageInfoGet (pTW_IDENTITY pOrigin, 
                              TW_MEMREF pData)
{
#ifdef HAVE_GPHOTO2
    pTW_IMAGEINFO pImageInfo = (pTW_IMAGEINFO) pData;

    TRACE("DG_IMAGE/DAT_IMAGEINFO/MSG_GET\n");

    if (activeDS.currentState != 6 && activeDS.currentState != 7) {
        activeDS.twCC = TWCC_SEQERROR;
        return TWRC_FAILURE;
    }
    if (TWRC_SUCCESS != _get_image_and_startup_jpeg()) {
      FIXME("Failed to get an image\n");
        activeDS.twCC = TWCC_SEQERROR;
      return TWRC_FAILURE;
    }
    if (activeDS.currentState == 6)
    {
        /* return general image description information about the image about to be transferred */
        TRACE("Getting parameters\n");
    }
    TRACE("activeDS.jd.output_width = %d\n", activeDS.jd.output_width);
    TRACE("activeDS.jd.output_height = %d\n", activeDS.jd.output_height);
    pImageInfo->Compression   = TWCP_NONE;
    pImageInfo->SamplesPerPixel     = 3;
    pImageInfo->BitsPerSample[0]= 8;
    pImageInfo->BitsPerSample[1]= 8;
    pImageInfo->BitsPerSample[2]= 8;
    pImageInfo->PixelType     = TWPT_RGB;
    pImageInfo->Planar        = FALSE; /* R-G-B is chunky! */
    pImageInfo->XResolution.Whole = -1;
    pImageInfo->XResolution.Frac = 0;
    pImageInfo->YResolution.Whole = -1;
    pImageInfo->YResolution.Frac = 0;
    pImageInfo->ImageWidth    = activeDS.jd.output_width;
    pImageInfo->ImageLength   = activeDS.jd.output_height;
    pImageInfo->BitsPerPixel  = 24;
    return TWRC_SUCCESS;
#else
    return TWRC_FAILURE;
#endif
}

/* DG_IMAGE/DAT_IMAGELAYOUT/MSG_GET */
TW_UINT16 GPHOTO2_ImageLayoutGet (pTW_IDENTITY pOrigin, 
                                TW_MEMREF pData)
{
    FIXME ("stub!\n");

    return TWRC_FAILURE;
}

/* DG_IMAGE/DAT_IMAGELAYOUT/MSG_GETDEFAULT */
TW_UINT16 GPHOTO2_ImageLayoutGetDefault (pTW_IDENTITY pOrigin, 
                                       TW_MEMREF pData)
{
    FIXME ("stub!\n");

    return TWRC_FAILURE;
}

/* DG_IMAGE/DAT_IMAGELAYOUT/MSG_RESET */
TW_UINT16 GPHOTO2_ImageLayoutReset (pTW_IDENTITY pOrigin, 
                                  TW_MEMREF pData)
{
    FIXME ("stub!\n");

    return TWRC_FAILURE;
}

/* DG_IMAGE/DAT_IMAGELAYOUT/MSG_SET */
TW_UINT16 GPHOTO2_ImageLayoutSet (pTW_IDENTITY pOrigin, 
                                TW_MEMREF pData)
{
    FIXME ("stub!\n");

    return TWRC_FAILURE;
}

/* DG_IMAGE/DAT_IMAGEMEMXFER/MSG_GET */
TW_UINT16 GPHOTO2_ImageMemXferGet (pTW_IDENTITY pOrigin, 
                                 TW_MEMREF pData)
{
#ifdef HAVE_GPHOTO2
    TW_UINT16 twRC = TWRC_SUCCESS;
    pTW_IMAGEMEMXFER pImageMemXfer = (pTW_IMAGEMEMXFER) pData;
    LPBYTE buffer;
    int readrows;
    unsigned int curoff;

    TRACE ("DG_IMAGE/DAT_IMAGEMEMXFER/MSG_GET\n");
    if (activeDS.currentState < 6 || activeDS.currentState > 7) {
        activeDS.twCC = TWCC_SEQERROR;
        return TWRC_FAILURE;
    }
    TRACE("pImageMemXfer.Compression is %d\n", pImageMemXfer->Compression);
    if (activeDS.currentState == 6) {
      if (TWRC_SUCCESS != _get_image_and_startup_jpeg()) {
          FIXME("Failed to get an image\n");
          activeDS.twCC = TWCC_SEQERROR;
          return TWRC_FAILURE;
      }

    if (!activeDS.progressWnd)
        activeDS.progressWnd = TransferringDialogBox(NULL,0);
    TransferringDialogBox(activeDS.progressWnd,0);

        activeDS.currentState = 7;
    } else {
      if (!activeDS.file) {
          activeDS.twCC = TWRC_SUCCESS;
          return TWRC_XFERDONE;
      }
    }

    if (pImageMemXfer->Memory.Flags & TWMF_HANDLE) {
      FIXME("Memory Handle, may not be locked correctly\n");
      buffer = LocalLock(pImageMemXfer->Memory.TheMem);
    } else
      buffer = pImageMemXfer->Memory.TheMem;
   
    memset(buffer,0,pImageMemXfer->Memory.Length);
    curoff = 0; readrows = 0;
    pImageMemXfer->YOffset    = activeDS.jd.output_scanline;
    pImageMemXfer->XOffset    = 0;  /* we do whole strips */
    while ((activeDS.jd.output_scanline<activeDS.jd.output_height) &&
         ((pImageMemXfer->Memory.Length - curoff) > activeDS.jd.output_width*activeDS.jd.output_components)
    ) {
      JSAMPROW row = buffer+curoff;
      int x = pjpeg_read_scanlines(&activeDS.jd,&row,1);
      if (x != 1) {
            FIXME("failed to read current scanline?\n");
            break;
      }
      readrows++;
      curoff += activeDS.jd.output_width*activeDS.jd.output_components;
    }
    pImageMemXfer->Compression      = TWCP_NONE;
    pImageMemXfer->BytesPerRow      = activeDS.jd.output_components * activeDS.jd.output_width;
    pImageMemXfer->Rows       = readrows;
    pImageMemXfer->Columns    = activeDS.jd.output_width; /* we do whole strips */
    pImageMemXfer->BytesWritten = curoff;

    TransferringDialogBox(activeDS.progressWnd,0);

    if (activeDS.jd.output_scanline == activeDS.jd.output_height) {
        pjpeg_finish_decompress(&activeDS.jd);
        pjpeg_destroy_decompress(&activeDS.jd);
      gp_file_unref (activeDS.file);
      activeDS.file = NULL;
      TRACE("xfer is done!\n");

      /*TransferringDialogBox(activeDS.progressWnd, -1);*/
      twRC = TWRC_XFERDONE;
    }
    activeDS.twCC = TWRC_SUCCESS;
    if (pImageMemXfer->Memory.Flags & TWMF_HANDLE)
        LocalUnlock(pImageMemXfer->Memory.TheMem);
    return twRC;
#else
    return TWRC_FAILURE;
#endif
}

/* DG_IMAGE/DAT_IMAGENATIVEXFER/MSG_GET */
TW_UINT16 GPHOTO2_ImageNativeXferGet (pTW_IDENTITY pOrigin, 
                                    TW_MEMREF pData)
{
#ifdef HAVE_GPHOTO2
    pTW_UINT32 pHandle = (pTW_UINT32) pData;
    HBITMAP hDIB;
    BITMAPINFO bmpInfo;
    LPBYTE bits, oldbits;
    JSAMPROW samprow, oldsamprow;
    HDC dc;

    FIXME("DG_IMAGE/DAT_IMAGENATIVEXFER/MSG_GET: implemented, but expect program crash due to DIB.\n");

/*  NOTE NOTE NOTE NOTE NOTE NOTE NOTE
 *
 *  While this is a mandatory transfer mode and this function
 *  is correctly implemented and fully works, the calling program
 *  will likely crash after calling.
 *
 *  Reason is that there is a lot of example code that does:
 *  bmpinfo = (LPBITMAPINFOHEADER)GlobalLock(hBITMAP); ... pointer access to bmpinfo
 *
 *  Our current HBITMAP handles do not support getting GlobalLocked -> App Crash
 *
 *  This needs a GDI Handle rewrite, at least for DIB sections.
 *  - Marcus
 */
    if (activeDS.currentState != 6) {
        activeDS.twCC = TWCC_SEQERROR;
        return TWRC_FAILURE;
    }
    if (TWRC_SUCCESS != _get_image_and_startup_jpeg()) {
      FIXME("Failed to get an image\n");
      activeDS.twCC = TWCC_OPERATIONERROR;
      return TWRC_FAILURE;
    }
    TRACE("Acquiring image %dx%dx%d bits from gphoto.\n",
      activeDS.jd.output_width, activeDS.jd.output_height,
      activeDS.jd.output_components*8);
    ZeroMemory (&bmpInfo, sizeof (BITMAPINFO));
    bmpInfo.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
    bmpInfo.bmiHeader.biWidth = activeDS.jd.output_width;
    bmpInfo.bmiHeader.biHeight = -activeDS.jd.output_height;
    bmpInfo.bmiHeader.biPlanes = 1;
    bmpInfo.bmiHeader.biBitCount = activeDS.jd.output_components*8;
    bmpInfo.bmiHeader.biCompression = BI_RGB;
    bmpInfo.bmiHeader.biSizeImage = 0;
    bmpInfo.bmiHeader.biXPelsPerMeter = 0;
    bmpInfo.bmiHeader.biYPelsPerMeter = 0;
    bmpInfo.bmiHeader.biClrUsed = 0;
    bmpInfo.bmiHeader.biClrImportant = 0;
    hDIB = CreateDIBSection ((dc = GetDC(activeDS.hwndOwner)), &bmpInfo,
                       DIB_RGB_COLORS, (LPVOID)&bits, 0, 0);
    if (!hDIB) {
      FIXME("Failed creating DIB.\n");
      gp_file_unref (activeDS.file);
      activeDS.file = NULL;
      activeDS.twCC = TWCC_LOWMEMORY;
      return TWRC_FAILURE;
    }
    samprow = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,activeDS.jd.output_width*activeDS.jd.output_components);
    oldbits = bits;
    oldsamprow = samprow;
    while ( activeDS.jd.output_scanline<activeDS.jd.output_height ) {
      int i, x = pjpeg_read_scanlines(&activeDS.jd,&samprow,1);
      if (x != 1) {
            FIXME("failed to read current scanline?\n");
            break;
      }
      /* We have to convert from RGB to BGR, see MSDN/ BITMAPINFOHEADER */
      for(i=0;i<activeDS.jd.output_width;i++,samprow+=activeDS.jd.output_components) {
          *(bits++) = *(samprow+2);
          *(bits++) = *(samprow+1);
          *(bits++) = *(samprow);
      }
      bits = (LPBYTE)(((UINT_PTR)bits + 3) & ~3);
      samprow = oldsamprow;
    }
    bits = oldbits;
    HeapFree (GetProcessHeap(), 0, samprow);
    gp_file_unref (activeDS.file);
    activeDS.file = NULL;
    ReleaseDC (activeDS.hwndOwner, dc);
    *pHandle = (TW_UINT32)hDIB;
    activeDS.twCC = TWCC_SUCCESS;
    activeDS.currentState = 7;
    return TWRC_XFERDONE;
#else
    return TWRC_FAILURE;
#endif
}

/* DG_IMAGE/DAT_JPEGCOMPRESSION/MSG_GET */
TW_UINT16 GPHOTO2_JPEGCompressionGet (pTW_IDENTITY pOrigin, 
                                    TW_MEMREF pData)
{
    FIXME ("stub!\n");

    return TWRC_FAILURE;
}

/* DG_IMAGE/DAT_JPEGCOMPRESSION/MSG_GETDEFAULT */
TW_UINT16 GPHOTO2_JPEGCompressionGetDefault (pTW_IDENTITY pOrigin,
                                           
                                           TW_MEMREF pData)
{
    FIXME ("stub!\n");

    return TWRC_FAILURE;
}

/* DG_IMAGE/DAT_JPEGCOMPRESSION/MSG_RESET */
TW_UINT16 GPHOTO2_JPEGCompressionReset (pTW_IDENTITY pOrigin, 
                                      TW_MEMREF pData)
{
    FIXME ("stub!\n");

    return TWRC_FAILURE;
}

/* DG_IMAGE/DAT_JPEGCOMPRESSION/MSG_SET */
TW_UINT16 GPHOTO2_JPEGCompressionSet (pTW_IDENTITY pOrigin, 
                                    TW_MEMREF pData)
{
    FIXME ("stub!\n");

    return TWRC_FAILURE;
}

/* DG_IMAGE/DAT_PALETTE8/MSG_GET */
TW_UINT16 GPHOTO2_Palette8Get (pTW_IDENTITY pOrigin, 
                             TW_MEMREF pData)
{
    FIXME ("stub!\n");

    return TWRC_FAILURE;
}

/* DG_IMAGE/DAT_PALETTE8/MSG_GETDEFAULT */
TW_UINT16 GPHOTO2_Palette8GetDefault (pTW_IDENTITY pOrigin, 
                                    TW_MEMREF pData)
{
    FIXME ("stub!\n");

    return TWRC_FAILURE;
}

/* DG_IMAGE/DAT_PALETTE8/MSG_RESET */
TW_UINT16 GPHOTO2_Palette8Reset (pTW_IDENTITY pOrigin, 
                               TW_MEMREF pData)
{
    FIXME ("stub!\n");

    return TWRC_FAILURE;
}

/* DG_IMAGE/DAT_PALETTE8/MSG_SET */
TW_UINT16 GPHOTO2_Palette8Set (pTW_IDENTITY pOrigin, 
                             TW_MEMREF pData)
{
    FIXME ("stub!\n");

    return TWRC_FAILURE;
}

/* DG_IMAGE/DAT_RGBRESPONSE/MSG_RESET */
TW_UINT16 GPHOTO2_RGBResponseReset (pTW_IDENTITY pOrigin, 
                                  TW_MEMREF pData)
{
    FIXME ("stub!\n");

    return TWRC_FAILURE;
}

/* DG_IMAGE/DAT_RGBRESPONSE/MSG_SET */
TW_UINT16 GPHOTO2_RGBResponseSet (pTW_IDENTITY pOrigin, 
                                TW_MEMREF pData)
{
    FIXME ("stub!\n");

    return TWRC_FAILURE;
}

#ifdef HAVE_GPHOTO2
TW_UINT16
_get_gphoto2_file_as_DIB(
    const char *folder, const char *filename, CameraFileType type,
    HWND hwnd, HBITMAP *hDIB
) {
    const unsigned char *filedata;
    unsigned long filesize;
    int                 ret;
    CameraFile          *file;
    struct jpeg_source_mgr          xjsm;
    struct jpeg_decompress_struct   jd;
    struct jpeg_error_mgr           jerr;
    HDC           dc;
    BITMAPINFO          bmpInfo;
    LPBYTE        bits, oldbits;
    JSAMPROW            samprow, oldsamprow;

    if(!libjpeg_handle) {
      if(!load_libjpeg()) {
          FIXME("Failed reading JPEG because unable to find %s\n", SONAME_LIBJPEG);
          filedata = NULL;
          return TWRC_FAILURE;
      }
    }

    gp_file_new (&file);
    ret = gp_camera_file_get(activeDS.camera, folder, filename, type, file, activeDS.context);
    if (ret < GP_OK) {
      FIXME("Failed to get file?\n");
      gp_file_unref (file);
      return TWRC_FAILURE;
    }
    ret = gp_file_get_data_and_size (file, (const char**)&filedata, &filesize);
    if (ret < GP_OK) {
      FIXME("Failed to get file data?\n");
      return TWRC_FAILURE;
    }

    /* FIXME: Actually we might get other types than JPEG ... But only handle JPEG for now */
    if (filedata[0] != 0xff) {
      ERR("File %s/%s might not be JPEG, cannot decode!\n", folder, filename);
    }

    /* This is basically so we can use in-memory data for jpeg decompression.
     * We need to have all the functions.
     */
    xjsm.next_input_byte      = filedata;
    xjsm.bytes_in_buffer      = filesize;
    xjsm.init_source    = _jpeg_init_source;
    xjsm.fill_input_buffer    = _jpeg_fill_input_buffer;
    xjsm.skip_input_data      = _jpeg_skip_input_data;
    xjsm.resync_to_restart    = _jpeg_resync_to_restart;
    xjsm.term_source    = _jpeg_term_source;

    jd.err = pjpeg_std_error(&jerr);
    /* jpeg_create_decompress is a macro that expands to jpeg_CreateDecompress - see jpeglib.h
     * jpeg_create_decompress(&jd); */
    pjpeg_CreateDecompress(&jd, JPEG_LIB_VERSION, (size_t) sizeof(struct jpeg_decompress_struct));
    jd.src = &xjsm;
    ret=pjpeg_read_header(&jd,TRUE);
    jd.out_color_space = JCS_RGB;
    pjpeg_start_decompress(&jd);
    if (ret != JPEG_HEADER_OK) {
      ERR("Jpeg image in stream has bad format, read header returned %d.\n",ret);
      gp_file_unref (file);
      return TWRC_FAILURE;
    }

    ZeroMemory (&bmpInfo, sizeof (BITMAPINFO));
    bmpInfo.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
    bmpInfo.bmiHeader.biWidth = jd.output_width;
    bmpInfo.bmiHeader.biHeight = -jd.output_height;
    bmpInfo.bmiHeader.biPlanes = 1;
    bmpInfo.bmiHeader.biBitCount = jd.output_components*8;
    bmpInfo.bmiHeader.biCompression = BI_RGB;
    bmpInfo.bmiHeader.biSizeImage = 0;
    bmpInfo.bmiHeader.biXPelsPerMeter = 0;
    bmpInfo.bmiHeader.biYPelsPerMeter = 0;
    bmpInfo.bmiHeader.biClrUsed = 0;
    bmpInfo.bmiHeader.biClrImportant = 0;
    *hDIB = CreateDIBSection ((dc = GetDC(hwnd)), &bmpInfo, DIB_RGB_COLORS, (LPVOID)&bits, 0, 0);
    if (!*hDIB) {
      FIXME("Failed creating DIB.\n");
      gp_file_unref (file);
      return TWRC_FAILURE;
    }
    samprow = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,jd.output_width*jd.output_components);
    oldbits = bits;
    oldsamprow = samprow;
    while ( jd.output_scanline<jd.output_height ) {
      int i, x = pjpeg_read_scanlines(&jd,&samprow,1);
      if (x != 1) {
          FIXME("failed to read current scanline?\n");
          break;
      }
      /* We have to convert from RGB to BGR, see MSDN/ BITMAPINFOHEADER */
      for(i=0;i<jd.output_width;i++,samprow+=jd.output_components) {
          *(bits++) = *(samprow+2);
          *(bits++) = *(samprow+1);
          *(bits++) = *(samprow);
      }
      bits = (LPBYTE)(((UINT_PTR)bits + 3) & ~3);
      samprow = oldsamprow;
    }
    if (hwnd) ReleaseDC (hwnd, dc);
    HeapFree (GetProcessHeap(), 0, samprow);
    gp_file_unref (file);
    return TWRC_SUCCESS;
}
#endif

Generated by  Doxygen 1.6.0   Back to index