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