[3/5] windowscodecs: Implement JpegEncoder_Frame_WritePixels.

Vincent Povirk madewokherd at gmail.com
Mon Apr 16 10:59:17 CDT 2012


-------------- next part --------------
From 98c0e66452e04c082db3182cec60e1ee54d02fae Mon Sep 17 00:00:00 2001
From: Vincent Povirk <vincent at codeweavers.com>
Date: Wed, 11 Apr 2012 16:37:56 -0500
Subject: [PATCH 3/8] windowscodecs: Implement JpegEncoder_Frame_WritePixels.

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

diff --git a/dlls/windowscodecs/jpegformat.c b/dlls/windowscodecs/jpegformat.c
index 2ae1fc7..ac11654 100644
--- a/dlls/windowscodecs/jpegformat.c
+++ b/dlls/windowscodecs/jpegformat.c
@@ -69,8 +69,11 @@ MAKE_FUNCPTR(jpeg_destroy_decompress);
 MAKE_FUNCPTR(jpeg_read_header);
 MAKE_FUNCPTR(jpeg_read_scanlines);
 MAKE_FUNCPTR(jpeg_resync_to_restart);
+MAKE_FUNCPTR(jpeg_set_defaults);
+MAKE_FUNCPTR(jpeg_start_compress);
 MAKE_FUNCPTR(jpeg_start_decompress);
 MAKE_FUNCPTR(jpeg_std_error);
+MAKE_FUNCPTR(jpeg_write_scanlines);
 #undef MAKE_FUNCPTR
 
 static void *load_libjpeg(void)
@@ -90,8 +93,11 @@ static void *load_libjpeg(void)
         LOAD_FUNCPTR(jpeg_read_header);
         LOAD_FUNCPTR(jpeg_read_scanlines);
         LOAD_FUNCPTR(jpeg_resync_to_restart);
+        LOAD_FUNCPTR(jpeg_set_defaults);
+        LOAD_FUNCPTR(jpeg_start_compress);
         LOAD_FUNCPTR(jpeg_start_decompress);
         LOAD_FUNCPTR(jpeg_std_error);
+        LOAD_FUNCPTR(jpeg_write_scanlines);
 #undef LOAD_FUNCPTR
     }
     return libjpeg_handle;
@@ -727,6 +733,7 @@ typedef struct JpegEncoder {
     int frame_count;
     int frame_initialized;
     int started_compress;
+    int lines_written;
     UINT width, height;
     double xres, yres;
     const jpeg_compress_format *format;
@@ -949,8 +956,105 @@ static HRESULT WINAPI JpegEncoder_Frame_SetThumbnail(IWICBitmapFrameEncode *ifac
 static HRESULT WINAPI JpegEncoder_Frame_WritePixels(IWICBitmapFrameEncode *iface,
     UINT lineCount, UINT cbStride, UINT cbBufferSize, BYTE *pbPixels)
 {
-    FIXME("(%p,%u,%u,%u,%p): stub\n", iface, lineCount, cbStride, cbBufferSize, pbPixels);
-    return E_NOTIMPL;
+    JpegEncoder *This = impl_from_IWICBitmapFrameEncode(iface);
+    jmp_buf jmpbuf;
+    BYTE *swapped_data = NULL, *current_row;
+    int line, row_size;
+    TRACE("(%p,%u,%u,%u,%p)\n", iface, lineCount, cbStride, cbBufferSize, pbPixels);
+
+    EnterCriticalSection(&This->lock);
+
+    if (!This->frame_initialized || !This->width || !This->height || !This->format)
+    {
+        LeaveCriticalSection(&This->lock);
+        return WINCODEC_ERR_WRONGSTATE;
+    }
+
+    if (lineCount == 0 || lineCount + This->lines_written > This->height)
+    {
+        LeaveCriticalSection(&This->lock);
+        return E_INVALIDARG;
+    }
+
+    /* set up setjmp/longjmp error handling */
+    if (setjmp(jmpbuf))
+    {
+        LeaveCriticalSection(&This->lock);
+        HeapFree(GetProcessHeap(), 0, swapped_data);
+        return E_FAIL;
+    }
+    This->cinfo.client_data = &jmpbuf;
+
+    if (!This->started_compress)
+    {
+        This->cinfo.image_width = This->width;
+        This->cinfo.image_height = This->height;
+        This->cinfo.input_components = This->format->num_components;
+        This->cinfo.in_color_space = This->format->color_space;
+
+        pjpeg_set_defaults(&This->cinfo);
+
+        if (This->xres != 0.0 && This->yres != 0.0)
+        {
+            This->cinfo.density_unit = 1; /* dots per inch */
+            This->cinfo.X_density = This->xres;
+            This->cinfo.Y_density = This->yres;
+        }
+
+        pjpeg_start_compress(&This->cinfo, TRUE);
+
+        This->started_compress = 1;
+    }
+
+    row_size = This->format->bpp / 8 * This->width;
+
+    if (This->format->swap_rgb)
+    {
+        swapped_data = HeapAlloc(GetProcessHeap(), 0, row_size);
+        if (!swapped_data)
+        {
+            LeaveCriticalSection(&This->lock);
+            return E_OUTOFMEMORY;
+        }
+    }
+
+    for (line=0; line < lineCount; line++)
+    {
+        if (This->format->swap_rgb)
+        {
+            int x;
+
+            memcpy(swapped_data, pbPixels + (cbStride * line), row_size);
+
+            for (x=0; x < This->width; x++)
+            {
+                BYTE b;
+
+                b = swapped_data[x*3];
+                swapped_data[x*3] = swapped_data[x*3+2];
+                swapped_data[x*3+2] = b;
+            }
+
+            current_row = swapped_data;
+        }
+        else
+            current_row = pbPixels + (cbStride * line);
+
+        if (!pjpeg_write_scanlines(&This->cinfo, &current_row, 1))
+        {
+            ERR("failed writing scanlines\n");
+            LeaveCriticalSection(&This->lock);
+            HeapFree(GetProcessHeap(), 0, swapped_data);
+            return E_FAIL;
+        }
+
+        This->lines_written++;
+    }
+
+    LeaveCriticalSection(&This->lock);
+    HeapFree(GetProcessHeap(), 0, swapped_data);
+
+    return S_OK;
 }
 
 static HRESULT WINAPI JpegEncoder_Frame_WriteSource(IWICBitmapFrameEncode *iface,
@@ -1228,6 +1332,7 @@ HRESULT JpegEncoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv)
     This->frame_count = 0;
     This->frame_initialized = 0;
     This->started_compress = 0;
+    This->lines_written = 0;
     This->width = This->height = 0;
     This->xres = This->yres = 0.0;
     This->format = NULL;
-- 
1.7.9.1


More information about the wine-patches mailing list