Dmitry Timoshkov : windowscodecs: Move JPEG frame image data initialization from Frame:: CopyPixels to Decoder::Initialize.

Alexandre Julliard julliard at winehq.org
Fri Feb 22 15:22:11 CST 2019


Module: wine
Branch: master
Commit: 361b0ed5ba4d88c9a18c0ae71da621b077fb4ed7
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=361b0ed5ba4d88c9a18c0ae71da621b077fb4ed7

Author: Dmitry Timoshkov <dmitry at baikal.ru>
Date:   Thu Feb 21 09:24:43 2019 +0300

windowscodecs: Move JPEG frame image data initialization from Frame::CopyPixels to Decoder::Initialize.

This is how PNG decoder does things, and it avoids image data corruption
in some cases (presumably when libjpeg reuses existing scanline data).

Signed-off-by: Dmitry Timoshkov <dmitry at baikal.ru>
Signed-off-by: Vincent Povirk <vincent at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/windowscodecs/jpegformat.c | 152 +++++++++++++++-------------------------
 1 file changed, 56 insertions(+), 96 deletions(-)

diff --git a/dlls/windowscodecs/jpegformat.c b/dlls/windowscodecs/jpegformat.c
index 54f77a7..1df898f 100644
--- a/dlls/windowscodecs/jpegformat.c
+++ b/dlls/windowscodecs/jpegformat.c
@@ -50,6 +50,7 @@
 
 #include "wincodecs_private.h"
 
+#include "wine/heap.h"
 #include "wine/debug.h"
 #include "wine/library.h"
 
@@ -155,6 +156,7 @@ typedef struct {
     struct jpeg_error_mgr jerr;
     struct jpeg_source_mgr source_mgr;
     BYTE source_buffer[1024];
+    UINT bpp, stride;
     BYTE *image_data;
     CRITICAL_SECTION lock;
 } JpegDecoder;
@@ -303,6 +305,8 @@ static HRESULT WINAPI JpegDecoder_Initialize(IWICBitmapDecoder *iface, IStream *
     int ret;
     LARGE_INTEGER seek;
     jmp_buf jmpbuf;
+    UINT data_size, i;
+
     TRACE("(%p,%p,%u)\n", iface, pIStream, cacheOptions);
 
     EnterCriticalSection(&This->lock);
@@ -381,6 +385,55 @@ static HRESULT WINAPI JpegDecoder_Initialize(IWICBitmapDecoder *iface, IStream *
         return E_FAIL;
     }
 
+    if (This->cinfo.out_color_space == JCS_GRAYSCALE) This->bpp = 8;
+    else if (This->cinfo.out_color_space == JCS_CMYK) This->bpp = 32;
+    else This->bpp = 24;
+
+    This->stride = (This->bpp * This->cinfo.output_width + 7) / 8;
+    data_size = This->stride * This->cinfo.output_height;
+
+    This->image_data = heap_alloc(data_size);
+    if (!This->image_data)
+    {
+        LeaveCriticalSection(&This->lock);
+        return E_OUTOFMEMORY;
+    }
+
+    while (This->cinfo.output_scanline < This->cinfo.output_height)
+    {
+        UINT first_scanline = This->cinfo.output_scanline;
+        UINT max_rows;
+        JSAMPROW out_rows[4];
+        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 + This->stride * (first_scanline+i);
+
+        ret = pjpeg_read_scanlines(&This->cinfo, out_rows, max_rows);
+        if (ret == 0)
+        {
+            ERR("read_scanlines failed\n");
+            LeaveCriticalSection(&This->lock);
+            return E_FAIL;
+        }
+    }
+
+    if (This->bpp == 24)
+    {
+        /* libjpeg gives us RGB data and we want BGR, so byteswap the data */
+        reverse_bgr8(3, This->image_data,
+            This->cinfo.output_width, This->cinfo.output_height,
+            This->stride);
+    }
+
+    if (This->cinfo.out_color_space == JCS_CMYK && This->cinfo.saw_Adobe_marker)
+    {
+        /* Adobe JPEG's have inverted CMYK data. */
+        for (i=0; i<data_size; i++)
+            This->image_data[i] ^= 0xff;
+    }
+
     This->initialized = TRUE;
 
     LeaveCriticalSection(&This->lock);
@@ -590,104 +643,11 @@ static HRESULT WINAPI JpegDecoder_Frame_CopyPixels(IWICBitmapFrameDecode *iface,
     const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer)
 {
     JpegDecoder *This = impl_from_IWICBitmapFrameDecode(iface);
-    UINT bpp;
-    UINT stride;
-    UINT data_size;
-    UINT max_row_needed;
-    jmp_buf jmpbuf;
-    WICRect rect;
-    TRACE("(%p,%s,%u,%u,%p)\n", iface, debug_wic_rect(prc), cbStride, cbBufferSize, pbBuffer);
-
-    if (!prc)
-    {
-        rect.X = 0;
-        rect.Y = 0;
-        rect.Width = This->cinfo.output_width;
-        rect.Height = This->cinfo.output_height;
-        prc = ▭
-    }
-    else
-    {
-        if (prc->X < 0 || prc->Y < 0 || prc->X+prc->Width > This->cinfo.output_width ||
-            prc->Y+prc->Height > This->cinfo.output_height)
-            return E_INVALIDARG;
-    }
-
-    if (This->cinfo.out_color_space == JCS_GRAYSCALE) bpp = 8;
-    else if (This->cinfo.out_color_space == JCS_CMYK) bpp = 32;
-    else bpp = 24;
-
-    stride = (bpp * This->cinfo.output_width + 7) / 8;
-    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;
-
-    EnterCriticalSection(&This->lock);
 
-    if (!This->image_data)
-    {
-        This->image_data = HeapAlloc(GetProcessHeap(), 0, data_size);
-        if (!This->image_data)
-        {
-            LeaveCriticalSection(&This->lock);
-            return E_OUTOFMEMORY;
-        }
-    }
-
-    This->cinfo.client_data = jmpbuf;
-
-    if (setjmp(jmpbuf))
-    {
-        LeaveCriticalSection(&This->lock);
-        return E_FAIL;
-    }
-
-    while (max_row_needed > This->cinfo.output_scanline)
-    {
-        UINT first_scanline = This->cinfo.output_scanline;
-        UINT max_rows;
-        JSAMPROW out_rows[4];
-        UINT i;
-        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");
-            LeaveCriticalSection(&This->lock);
-            return E_FAIL;
-        }
-
-        if (bpp == 24)
-        {
-            /* libjpeg gives us RGB data and we want BGR, so byteswap the data */
-            reverse_bgr8(3, This->image_data + stride * first_scanline,
-                This->cinfo.output_width, This->cinfo.output_scanline - first_scanline,
-                stride);
-        }
-
-        if (This->cinfo.out_color_space == JCS_CMYK && This->cinfo.saw_Adobe_marker)
-        {
-            DWORD *pDwordData = (DWORD*) (This->image_data + stride * first_scanline);
-            DWORD *pDwordDataEnd = (DWORD*) (This->image_data + This->cinfo.output_scanline * stride);
-
-            /* Adobe JPEG's have inverted CMYK data. */
-            while(pDwordData < pDwordDataEnd)
-                *pDwordData++ ^= 0xffffffff;
-        }
-
-    }
-
-    LeaveCriticalSection(&This->lock);
+    TRACE("(%p,%s,%u,%u,%p)\n", iface, debug_wic_rect(prc), cbStride, cbBufferSize, pbBuffer);
 
-    return copy_pixels(bpp, This->image_data,
-        This->cinfo.output_width, This->cinfo.output_height, stride,
+    return copy_pixels(This->bpp, This->image_data,
+        This->cinfo.output_width, This->cinfo.output_height, This->stride,
         prc, cbStride, cbBufferSize, pbBuffer);
 }
 




More information about the wine-cvs mailing list