Vincent Povirk : windowscodecs: Implement CopyPixels for the JPEG decoder.

Alexandre Julliard julliard at winehq.org
Tue Aug 25 08:44:11 CDT 2009


Module: wine
Branch: master
Commit: 529bdca8a85cf1803fb855cc221abcf5f036fab8
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=529bdca8a85cf1803fb855cc221abcf5f036fab8

Author: Vincent Povirk <vincent at codeweavers.com>
Date:   Mon Aug 24 13:08:30 2009 -0500

windowscodecs: Implement CopyPixels for the JPEG decoder.

---

 dlls/windowscodecs/jpegformat.c |   70 +++++++++++++++++++++++++++++++++++++-
 1 files changed, 68 insertions(+), 2 deletions(-)

diff --git a/dlls/windowscodecs/jpegformat.c b/dlls/windowscodecs/jpegformat.c
index 50ee013..6f78821 100644
--- a/dlls/windowscodecs/jpegformat.c
+++ b/dlls/windowscodecs/jpegformat.c
@@ -63,6 +63,7 @@ static void *libjpeg_handle;
 MAKE_FUNCPTR(jpeg_CreateDecompress);
 MAKE_FUNCPTR(jpeg_destroy_decompress);
 MAKE_FUNCPTR(jpeg_read_header);
+MAKE_FUNCPTR(jpeg_read_scanlines);
 MAKE_FUNCPTR(jpeg_resync_to_restart);
 MAKE_FUNCPTR(jpeg_start_decompress);
 MAKE_FUNCPTR(jpeg_std_error);
@@ -81,6 +82,7 @@ static void *load_libjpeg(void)
         LOAD_FUNCPTR(jpeg_CreateDecompress);
         LOAD_FUNCPTR(jpeg_destroy_decompress);
         LOAD_FUNCPTR(jpeg_read_header);
+        LOAD_FUNCPTR(jpeg_read_scanlines);
         LOAD_FUNCPTR(jpeg_resync_to_restart);
         LOAD_FUNCPTR(jpeg_start_decompress);
         LOAD_FUNCPTR(jpeg_std_error);
@@ -100,6 +102,7 @@ typedef struct {
     struct jpeg_error_mgr jerr;
     struct jpeg_source_mgr source_mgr;
     BYTE source_buffer[1024];
+    BYTE *image_data;
 } JpegDecoder;
 
 static inline JpegDecoder *decoder_from_decompress(j_decompress_ptr decompress)
@@ -155,6 +158,7 @@ static ULONG WINAPI JpegDecoder_Release(IWICBitmapDecoder *iface)
     {
         if (This->cinfo_initialized) pjpeg_destroy_decompress(&This->cinfo);
         if (This->stream) IStream_Release(This->stream);
+        HeapFree(GetProcessHeap(), 0, This->image_data);
         HeapFree(GetProcessHeap(), 0, This);
     }
 
@@ -428,8 +432,69 @@ static HRESULT WINAPI JpegDecoder_Frame_CopyPalette(IWICBitmapFrameDecode *iface
 static HRESULT WINAPI JpegDecoder_Frame_CopyPixels(IWICBitmapFrameDecode *iface,
     const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer)
 {
-    FIXME("(%p,%p,%u,%u,%p): stub\n", iface, prc, cbStride, cbBufferSize, pbBuffer);
-    return E_NOTIMPL;
+    JpegDecoder *This = decoder_from_frame(iface);
+    UINT bpp;
+    UINT stride;
+    UINT data_size;
+    UINT max_row_needed;
+    TRACE("(%p,%p,%u,%u,%p)\n", iface, prc, cbStride, cbBufferSize, pbBuffer);
+
+    if (This->cinfo.out_color_space == JCS_GRAYSCALE) bpp = 8;
+    else bpp = 24;
+
+    stride = bpp * This->cinfo.output_width;
+    data_size = stride * This->cinfo.output_height;
+
+    max_row_needed = prc->Y + prc->Height;
+    if (max_row_needed > This->cinfo.output_height) return E_INVALIDARG;
+
+    if (!This->image_data)
+    {
+        This->image_data = HeapAlloc(GetProcessHeap(), 0, data_size);
+        if (!This->image_data) return E_OUTOFMEMORY;
+    }
+
+    while (max_row_needed > This->cinfo.output_scanline)
+    {
+        UINT first_scanline = This->cinfo.output_scanline;
+        UINT max_rows;
+        JSAMPROW out_rows[4];
+        UINT i, j;
+        JDIMENSION ret;
+
+        max_rows = min(This->cinfo.output_height-first_scanline, 4);
+        for (i=0; i<max_rows; i++)
+            out_rows[i] = This->image_data + stride * (first_scanline+i);
+
+        ret = pjpeg_read_scanlines(&This->cinfo, out_rows, max_rows);
+
+        if (ret == 0)
+        {
+            ERR("read_scanlines failed\n");
+            return E_FAIL;
+        }
+
+        if (bpp == 24)
+        {
+            /* libjpeg gives us RGB data and we want BGR, so byteswap the data */
+            for (i=first_scanline; i<This->cinfo.output_scanline; i++)
+            {
+                BYTE *pixel = This->image_data + stride * i;
+                for (j=0; j<This->cinfo.output_width; j++)
+                {
+                    BYTE red=pixel[0];
+                    BYTE blue=pixel[2];
+                    pixel[0]=blue;
+                    pixel[2]=red;
+                    pixel+=3;
+                }
+            }
+        }
+    }
+
+    return copy_pixels(bpp, This->image_data,
+        This->cinfo.output_width, This->cinfo.output_height, stride,
+        prc, cbStride, cbBufferSize, pbBuffer);
 }
 
 static HRESULT WINAPI JpegDecoder_Frame_GetMetadataQueryReader(IWICBitmapFrameDecode *iface,
@@ -493,6 +558,7 @@ HRESULT JpegDecoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv)
     This->initialized = FALSE;
     This->cinfo_initialized = FALSE;
     This->stream = NULL;
+    This->image_data = NULL;
 
     ret = IUnknown_QueryInterface((IUnknown*)This, iid, ppv);
     IUnknown_Release((IUnknown*)This);




More information about the wine-cvs mailing list