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

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


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

Author: Vincent Povirk <vincent at codeweavers.com>
Date:   Mon Aug 24 11:45:46 2009 -0500

windowscodecs: Implement Initialize for the JPEG decoder.

---

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

diff --git a/dlls/windowscodecs/jpegformat.c b/dlls/windowscodecs/jpegformat.c
index ecbc167..8759905 100644
--- a/dlls/windowscodecs/jpegformat.c
+++ b/dlls/windowscodecs/jpegformat.c
@@ -60,6 +60,11 @@ WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
 static void *libjpeg_handle;
 
 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
+MAKE_FUNCPTR(jpeg_CreateDecompress);
+MAKE_FUNCPTR(jpeg_destroy_decompress);
+MAKE_FUNCPTR(jpeg_read_header);
+MAKE_FUNCPTR(jpeg_resync_to_restart);
+MAKE_FUNCPTR(jpeg_start_decompress);
 MAKE_FUNCPTR(jpeg_std_error);
 #undef MAKE_FUNCPTR
 
@@ -73,6 +78,11 @@ static void *load_libjpeg(void)
         return NULL; \
     }
 
+        LOAD_FUNCPTR(jpeg_CreateDecompress);
+        LOAD_FUNCPTR(jpeg_destroy_decompress);
+        LOAD_FUNCPTR(jpeg_read_header);
+        LOAD_FUNCPTR(jpeg_resync_to_restart);
+        LOAD_FUNCPTR(jpeg_start_decompress);
         LOAD_FUNCPTR(jpeg_std_error);
 #undef LOAD_FUNCPTR
     }
@@ -82,8 +92,20 @@ static void *load_libjpeg(void)
 typedef struct {
     const IWICBitmapDecoderVtbl *lpVtbl;
     LONG ref;
+    BOOL initialized;
+    BOOL cinfo_initialized;
+    IStream *stream;
+    struct jpeg_decompress_struct cinfo;
+    struct jpeg_error_mgr jerr;
+    struct jpeg_source_mgr source_mgr;
+    BYTE source_buffer[1024];
 } JpegDecoder;
 
+static inline JpegDecoder *decoder_from_decompress(j_decompress_ptr decompress)
+{
+    return CONTAINING_RECORD(decompress, JpegDecoder, cinfo);
+}
+
 static HRESULT WINAPI JpegDecoder_QueryInterface(IWICBitmapDecoder *iface, REFIID iid,
     void **ppv)
 {
@@ -125,6 +147,8 @@ static ULONG WINAPI JpegDecoder_Release(IWICBitmapDecoder *iface)
 
     if (ref == 0)
     {
+        if (This->cinfo_initialized) pjpeg_destroy_decompress(&This->cinfo);
+        if (This->stream) IStream_Release(This->stream);
         HeapFree(GetProcessHeap(), 0, This);
     }
 
@@ -138,11 +162,100 @@ static HRESULT WINAPI JpegDecoder_QueryCapability(IWICBitmapDecoder *iface, IStr
     return E_NOTIMPL;
 }
 
+static void source_mgr_init_source(j_decompress_ptr cinfo)
+{
+}
+
+static jpeg_boolean source_mgr_fill_input_buffer(j_decompress_ptr cinfo)
+{
+    JpegDecoder *This = decoder_from_decompress(cinfo);
+    HRESULT hr;
+    ULONG bytesread;
+
+    hr = IStream_Read(This->stream, This->source_buffer, 1024, &bytesread);
+
+    if (hr != S_OK || bytesread == 0)
+    {
+        return FALSE;
+    }
+    else
+    {
+        This->source_mgr.next_input_byte = This->source_buffer;
+        This->source_mgr.bytes_in_buffer = bytesread;
+        return TRUE;
+    }
+}
+
+static void source_mgr_skip_input_data(j_decompress_ptr cinfo, long num_bytes)
+{
+    JpegDecoder *This = decoder_from_decompress(cinfo);
+    LARGE_INTEGER seek;
+
+    if (num_bytes > This->source_mgr.bytes_in_buffer)
+    {
+        seek.QuadPart = num_bytes - This->source_mgr.bytes_in_buffer;
+        IStream_Seek(This->stream, seek, STREAM_SEEK_CUR, NULL);
+        This->source_mgr.bytes_in_buffer = 0;
+    }
+    else if (num_bytes > 0)
+    {
+        This->source_mgr.next_input_byte += num_bytes;
+        This->source_mgr.bytes_in_buffer -= num_bytes;
+    }
+}
+
+static void source_mgr_term_source(j_decompress_ptr cinfo)
+{
+}
+
 static HRESULT WINAPI JpegDecoder_Initialize(IWICBitmapDecoder *iface, IStream *pIStream,
     WICDecodeOptions cacheOptions)
 {
-    FIXME("(%p,%p,%u): stub\n", iface, pIStream, cacheOptions);
-    return E_NOTIMPL;
+    JpegDecoder *This = (JpegDecoder*)iface;
+    int ret;
+    TRACE("(%p,%p,%u)\n", iface, pIStream, cacheOptions);
+
+    if (This->cinfo_initialized) return WINCODEC_ERR_WRONGSTATE;
+
+    This->cinfo.err = pjpeg_std_error(&This->jerr);
+
+    pjpeg_CreateDecompress(&This->cinfo, JPEG_LIB_VERSION, sizeof(struct jpeg_decompress_struct));
+
+    This->cinfo_initialized = TRUE;
+
+    This->stream = pIStream;
+    IStream_AddRef(pIStream);
+
+    This->source_mgr.bytes_in_buffer = 0;
+    This->source_mgr.init_source = source_mgr_init_source;
+    This->source_mgr.fill_input_buffer = source_mgr_fill_input_buffer;
+    This->source_mgr.skip_input_data = source_mgr_skip_input_data;
+    This->source_mgr.resync_to_restart = pjpeg_resync_to_restart;
+    This->source_mgr.term_source = source_mgr_term_source;
+
+    This->cinfo.src = &This->source_mgr;
+
+    ret = pjpeg_read_header(&This->cinfo, TRUE);
+
+    if (ret != JPEG_HEADER_OK) {
+        WARN("Jpeg image in stream has bad format, read header returned %d.\n",ret);
+        return E_FAIL;
+    }
+
+    if (This->cinfo.jpeg_color_space == JCS_GRAYSCALE)
+        This->cinfo.out_color_space = JCS_GRAYSCALE;
+    else
+        This->cinfo.out_color_space = JCS_RGB;
+
+    if (!pjpeg_start_decompress(&This->cinfo))
+    {
+        ERR("jpeg_start_decompress failed\n");
+        return E_FAIL;
+    }
+
+    This->initialized = TRUE;
+
+    return S_OK;
 }
 
 static HRESULT WINAPI JpegDecoder_GetContainerFormat(IWICBitmapDecoder *iface,
@@ -248,6 +361,9 @@ HRESULT JpegDecoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv)
 
     This->lpVtbl = &JpegDecoder_Vtbl;
     This->ref = 1;
+    This->initialized = FALSE;
+    This->cinfo_initialized = FALSE;
+    This->stream = NULL;
 
     ret = IUnknown_QueryInterface((IUnknown*)This, iid, ppv);
     IUnknown_Release((IUnknown*)This);




More information about the wine-cvs mailing list