[PATCH] windowscodecs: Move jpeg encoding to the unix lib.
Esme Povirk
esme at codeweavers.com
Tue Nov 24 15:22:06 CST 2020
Signed-off-by: Esme Povirk <esme at codeweavers.com>
---
dlls/windowscodecs/Makefile.in | 1 -
dlls/windowscodecs/encoder.c | 14 +-
dlls/windowscodecs/jpegformat.c | 920 -------------------------
dlls/windowscodecs/libjpeg.c | 313 +++++++++
dlls/windowscodecs/main.c | 28 +
dlls/windowscodecs/unix_lib.c | 3 +
dlls/windowscodecs/wincodecs_private.h | 7 +
7 files changed, 364 insertions(+), 922 deletions(-)
delete mode 100644 dlls/windowscodecs/jpegformat.c
diff --git a/dlls/windowscodecs/Makefile.in b/dlls/windowscodecs/Makefile.in
index d7f9336916b..2ab89eac84c 100644
--- a/dlls/windowscodecs/Makefile.in
+++ b/dlls/windowscodecs/Makefile.in
@@ -22,7 +22,6 @@ C_SRCS = \
icoformat.c \
imgfactory.c \
info.c \
- jpegformat.c \
libjpeg.c \
libpng.c \
libtiff.c \
diff --git a/dlls/windowscodecs/encoder.c b/dlls/windowscodecs/encoder.c
index bb673b13076..b17895a6c9c 100644
--- a/dlls/windowscodecs/encoder.c
+++ b/dlls/windowscodecs/encoder.c
@@ -38,12 +38,24 @@ static const WCHAR wszPngInterlaceOption[] = {'I','n','t','e','r','l','a','c','e
static const WCHAR wszPngFilterOption[] = {'F','i','l','t','e','r','O','p','t','i','o','n',0};
static const WCHAR wszTiffCompressionMethod[] = {'T','i','f','f','C','o','m','p','r','e','s','s','i','o','n','M','e','t','h','o','d',0};
static const WCHAR wszCompressionQuality[] = {'C','o','m','p','r','e','s','s','i','o','n','Q','u','a','l','i','t','y',0};
+static const WCHAR wszImageQuality[] = {'I','m','a','g','e','Q','u','a','l','i','t','y',0};
+static const WCHAR wszBitmapTransform[] = {'B','i','t','m','a','p','T','r','a','n','s','f','o','r','m',0};
+static const WCHAR wszLuminance[] = {'L','u','m','i','n','a','n','c','e',0};
+static const WCHAR wszChrominance[] = {'C','h','r','o','m','i','n','a','n','c','e',0};
+static const WCHAR wszJpegYCrCbSubsampling[] = {'J','p','e','g','Y','C','r','C','b','S','u','b','s','a','m','p','l','i','n','g',0};
+static const WCHAR wszSuppressApp0[] = {'S','u','p','p','r','e','s','s','A','p','p','0',0};
static const PROPBAG2 encoder_option_properties[ENCODER_OPTION_END] = {
{ PROPBAG2_TYPE_DATA, VT_BOOL, 0, 0, (LPOLESTR)wszPngInterlaceOption },
{ PROPBAG2_TYPE_DATA, VT_UI1, 0, 0, (LPOLESTR)wszPngFilterOption },
{ PROPBAG2_TYPE_DATA, VT_UI1, 0, 0, (LPOLESTR)wszTiffCompressionMethod },
- { PROPBAG2_TYPE_DATA, VT_R4, 0, 0, (LPOLESTR)wszCompressionQuality }
+ { PROPBAG2_TYPE_DATA, VT_R4, 0, 0, (LPOLESTR)wszCompressionQuality },
+ { PROPBAG2_TYPE_DATA, VT_R4, 0, 0, (LPOLESTR)wszImageQuality },
+ { PROPBAG2_TYPE_DATA, VT_UI1, 0, 0, (LPOLESTR)wszBitmapTransform },
+ { PROPBAG2_TYPE_DATA, VT_I4 | VT_ARRAY, 0, 0, (LPOLESTR)wszLuminance },
+ { PROPBAG2_TYPE_DATA, VT_I4 | VT_ARRAY, 0, 0, (LPOLESTR)wszChrominance },
+ { PROPBAG2_TYPE_DATA, VT_UI1, 0, 0, (LPOLESTR)wszJpegYCrCbSubsampling },
+ { PROPBAG2_TYPE_DATA, VT_BOOL, 0, 0, (LPOLESTR)wszSuppressApp0 }
};
typedef struct CommonEncoder {
diff --git a/dlls/windowscodecs/jpegformat.c b/dlls/windowscodecs/jpegformat.c
deleted file mode 100644
index 5be35a1ccb4..00000000000
--- a/dlls/windowscodecs/jpegformat.c
+++ /dev/null
@@ -1,920 +0,0 @@
-/*
- * Copyright 2009 Vincent Povirk for CodeWeavers
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-#include "config.h"
-#include "wine/port.h"
-
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-#include <setjmp.h>
-
-#ifdef SONAME_LIBJPEG
-/* This is a hack, so jpeglib.h does not redefine INT32 and the like*/
-#define XMD_H
-#define UINT8 JPEG_UINT8
-#define UINT16 JPEG_UINT16
-#define boolean jpeg_boolean
-#undef HAVE_STDLIB_H
-# include <jpeglib.h>
-#undef HAVE_STDLIB_H
-#define HAVE_STDLIB_H 1
-#undef UINT8
-#undef UINT16
-#undef boolean
-#endif
-
-#define COBJMACROS
-
-#include "windef.h"
-#include "winbase.h"
-#include "objbase.h"
-
-#include "wincodecs_private.h"
-
-#include "wine/heap.h"
-#include "wine/debug.h"
-
-WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
-
-#ifdef SONAME_LIBJPEG
-WINE_DECLARE_DEBUG_CHANNEL(jpeg);
-
-static void *libjpeg_handle;
-
-static const WCHAR wszImageQuality[] = {'I','m','a','g','e','Q','u','a','l','i','t','y',0};
-static const WCHAR wszBitmapTransform[] = {'B','i','t','m','a','p','T','r','a','n','s','f','o','r','m',0};
-static const WCHAR wszLuminance[] = {'L','u','m','i','n','a','n','c','e',0};
-static const WCHAR wszChrominance[] = {'C','h','r','o','m','i','n','a','n','c','e',0};
-static const WCHAR wszJpegYCrCbSubsampling[] = {'J','p','e','g','Y','C','r','C','b','S','u','b','s','a','m','p','l','i','n','g',0};
-static const WCHAR wszSuppressApp0[] = {'S','u','p','p','r','e','s','s','A','p','p','0',0};
-
-#define MAKE_FUNCPTR(f) static typeof(f) * p##f
-MAKE_FUNCPTR(jpeg_CreateCompress);
-MAKE_FUNCPTR(jpeg_CreateDecompress);
-MAKE_FUNCPTR(jpeg_destroy_compress);
-MAKE_FUNCPTR(jpeg_destroy_decompress);
-MAKE_FUNCPTR(jpeg_finish_compress);
-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)
-{
- if((libjpeg_handle = dlopen(SONAME_LIBJPEG, RTLD_NOW)) != NULL) {
-
-#define LOAD_FUNCPTR(f) \
- if((p##f = dlsym(libjpeg_handle, #f)) == NULL) { \
- libjpeg_handle = NULL; \
- return NULL; \
- }
-
- LOAD_FUNCPTR(jpeg_CreateCompress);
- LOAD_FUNCPTR(jpeg_CreateDecompress);
- LOAD_FUNCPTR(jpeg_destroy_compress);
- LOAD_FUNCPTR(jpeg_destroy_decompress);
- LOAD_FUNCPTR(jpeg_finish_compress);
- 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;
-}
-
-static void error_exit_fn(j_common_ptr cinfo)
-{
- char message[JMSG_LENGTH_MAX];
- if (ERR_ON(jpeg))
- {
- cinfo->err->format_message(cinfo, message);
- ERR_(jpeg)("%s\n", message);
- }
- longjmp(*(jmp_buf*)cinfo->client_data, 1);
-}
-
-static void emit_message_fn(j_common_ptr cinfo, int msg_level)
-{
- char message[JMSG_LENGTH_MAX];
-
- if (msg_level < 0 && ERR_ON(jpeg))
- {
- cinfo->err->format_message(cinfo, message);
- ERR_(jpeg)("%s\n", message);
- }
- else if (msg_level == 0 && WARN_ON(jpeg))
- {
- cinfo->err->format_message(cinfo, message);
- WARN_(jpeg)("%s\n", message);
- }
- else if (msg_level > 0 && TRACE_ON(jpeg))
- {
- cinfo->err->format_message(cinfo, message);
- TRACE_(jpeg)("%s\n", message);
- }
-}
-
-typedef struct jpeg_compress_format {
- const WICPixelFormatGUID *guid;
- int bpp;
- int num_components;
- J_COLOR_SPACE color_space;
- int swap_rgb;
-} jpeg_compress_format;
-
-static const jpeg_compress_format compress_formats[] = {
- { &GUID_WICPixelFormat24bppBGR, 24, 3, JCS_RGB, 1 },
- { &GUID_WICPixelFormat32bppCMYK, 32, 4, JCS_CMYK },
- { &GUID_WICPixelFormat8bppGray, 8, 1, JCS_GRAYSCALE },
- { 0 }
-};
-
-typedef struct JpegEncoder {
- IWICBitmapEncoder IWICBitmapEncoder_iface;
- IWICBitmapFrameEncode IWICBitmapFrameEncode_iface;
- LONG ref;
- struct jpeg_compress_struct cinfo;
- struct jpeg_error_mgr jerr;
- struct jpeg_destination_mgr dest_mgr;
- BOOL initialized;
- int frame_count;
- BOOL frame_initialized;
- BOOL started_compress;
- int lines_written;
- BOOL frame_committed;
- BOOL committed;
- UINT width, height;
- double xres, yres;
- const jpeg_compress_format *format;
- IStream *stream;
- WICColor palette[256];
- UINT colors;
- CRITICAL_SECTION lock;
- BYTE dest_buffer[1024];
-} JpegEncoder;
-
-static inline JpegEncoder *impl_from_IWICBitmapEncoder(IWICBitmapEncoder *iface)
-{
- return CONTAINING_RECORD(iface, JpegEncoder, IWICBitmapEncoder_iface);
-}
-
-static inline JpegEncoder *impl_from_IWICBitmapFrameEncode(IWICBitmapFrameEncode *iface)
-{
- return CONTAINING_RECORD(iface, JpegEncoder, IWICBitmapFrameEncode_iface);
-}
-
-static inline JpegEncoder *encoder_from_compress(j_compress_ptr compress)
-{
- return CONTAINING_RECORD(compress, JpegEncoder, cinfo);
-}
-
-static void dest_mgr_init_destination(j_compress_ptr cinfo)
-{
- JpegEncoder *This = encoder_from_compress(cinfo);
-
- This->dest_mgr.next_output_byte = This->dest_buffer;
- This->dest_mgr.free_in_buffer = sizeof(This->dest_buffer);
-}
-
-static jpeg_boolean dest_mgr_empty_output_buffer(j_compress_ptr cinfo)
-{
- JpegEncoder *This = encoder_from_compress(cinfo);
- HRESULT hr;
- ULONG byteswritten;
-
- hr = IStream_Write(This->stream, This->dest_buffer,
- sizeof(This->dest_buffer), &byteswritten);
-
- if (hr != S_OK || byteswritten == 0)
- {
- ERR("Failed writing data, hr=%x\n", hr);
- return FALSE;
- }
-
- This->dest_mgr.next_output_byte = This->dest_buffer;
- This->dest_mgr.free_in_buffer = sizeof(This->dest_buffer);
- return TRUE;
-}
-
-static void dest_mgr_term_destination(j_compress_ptr cinfo)
-{
- JpegEncoder *This = encoder_from_compress(cinfo);
- ULONG byteswritten;
- HRESULT hr;
-
- if (This->dest_mgr.free_in_buffer != sizeof(This->dest_buffer))
- {
- hr = IStream_Write(This->stream, This->dest_buffer,
- sizeof(This->dest_buffer) - This->dest_mgr.free_in_buffer, &byteswritten);
-
- if (hr != S_OK || byteswritten == 0)
- ERR("Failed writing data, hr=%x\n", hr);
- }
-}
-
-static HRESULT WINAPI JpegEncoder_Frame_QueryInterface(IWICBitmapFrameEncode *iface, REFIID iid,
- void **ppv)
-{
- JpegEncoder *This = impl_from_IWICBitmapFrameEncode(iface);
- TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
-
- if (!ppv) return E_INVALIDARG;
-
- if (IsEqualIID(&IID_IUnknown, iid) ||
- IsEqualIID(&IID_IWICBitmapFrameEncode, iid))
- {
- *ppv = &This->IWICBitmapFrameEncode_iface;
- }
- else
- {
- *ppv = NULL;
- return E_NOINTERFACE;
- }
-
- IUnknown_AddRef((IUnknown*)*ppv);
- return S_OK;
-}
-
-static ULONG WINAPI JpegEncoder_Frame_AddRef(IWICBitmapFrameEncode *iface)
-{
- JpegEncoder *This = impl_from_IWICBitmapFrameEncode(iface);
- return IWICBitmapEncoder_AddRef(&This->IWICBitmapEncoder_iface);
-}
-
-static ULONG WINAPI JpegEncoder_Frame_Release(IWICBitmapFrameEncode *iface)
-{
- JpegEncoder *This = impl_from_IWICBitmapFrameEncode(iface);
- return IWICBitmapEncoder_Release(&This->IWICBitmapEncoder_iface);
-}
-
-static HRESULT WINAPI JpegEncoder_Frame_Initialize(IWICBitmapFrameEncode *iface,
- IPropertyBag2 *pIEncoderOptions)
-{
- JpegEncoder *This = impl_from_IWICBitmapFrameEncode(iface);
- TRACE("(%p,%p)\n", iface, pIEncoderOptions);
-
- EnterCriticalSection(&This->lock);
-
- if (This->frame_initialized)
- {
- LeaveCriticalSection(&This->lock);
- return WINCODEC_ERR_WRONGSTATE;
- }
-
- This->frame_initialized = TRUE;
-
- LeaveCriticalSection(&This->lock);
-
- return S_OK;
-}
-
-static HRESULT WINAPI JpegEncoder_Frame_SetSize(IWICBitmapFrameEncode *iface,
- UINT uiWidth, UINT uiHeight)
-{
- JpegEncoder *This = impl_from_IWICBitmapFrameEncode(iface);
- TRACE("(%p,%u,%u)\n", iface, uiWidth, uiHeight);
-
- EnterCriticalSection(&This->lock);
-
- if (!This->frame_initialized || This->started_compress)
- {
- LeaveCriticalSection(&This->lock);
- return WINCODEC_ERR_WRONGSTATE;
- }
-
- This->width = uiWidth;
- This->height = uiHeight;
-
- LeaveCriticalSection(&This->lock);
-
- return S_OK;
-}
-
-static HRESULT WINAPI JpegEncoder_Frame_SetResolution(IWICBitmapFrameEncode *iface,
- double dpiX, double dpiY)
-{
- JpegEncoder *This = impl_from_IWICBitmapFrameEncode(iface);
- TRACE("(%p,%0.2f,%0.2f)\n", iface, dpiX, dpiY);
-
- EnterCriticalSection(&This->lock);
-
- if (!This->frame_initialized || This->started_compress)
- {
- LeaveCriticalSection(&This->lock);
- return WINCODEC_ERR_WRONGSTATE;
- }
-
- This->xres = dpiX;
- This->yres = dpiY;
-
- LeaveCriticalSection(&This->lock);
-
- return S_OK;
-}
-
-static HRESULT WINAPI JpegEncoder_Frame_SetPixelFormat(IWICBitmapFrameEncode *iface,
- WICPixelFormatGUID *pPixelFormat)
-{
- JpegEncoder *This = impl_from_IWICBitmapFrameEncode(iface);
- int i;
- TRACE("(%p,%s)\n", iface, debugstr_guid(pPixelFormat));
-
- EnterCriticalSection(&This->lock);
-
- if (!This->frame_initialized || This->started_compress)
- {
- LeaveCriticalSection(&This->lock);
- return WINCODEC_ERR_WRONGSTATE;
- }
-
- for (i=0; compress_formats[i].guid; i++)
- {
- if (memcmp(compress_formats[i].guid, pPixelFormat, sizeof(GUID)) == 0)
- break;
- }
-
- if (!compress_formats[i].guid) i = 0;
-
- This->format = &compress_formats[i];
- memcpy(pPixelFormat, This->format->guid, sizeof(GUID));
-
- LeaveCriticalSection(&This->lock);
-
- return S_OK;
-}
-
-static HRESULT WINAPI JpegEncoder_Frame_SetColorContexts(IWICBitmapFrameEncode *iface,
- UINT cCount, IWICColorContext **ppIColorContext)
-{
- FIXME("(%p,%u,%p): stub\n", iface, cCount, ppIColorContext);
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI JpegEncoder_Frame_SetPalette(IWICBitmapFrameEncode *iface,
- IWICPalette *palette)
-{
- JpegEncoder *This = impl_from_IWICBitmapFrameEncode(iface);
- HRESULT hr;
-
- TRACE("(%p,%p)\n", iface, palette);
-
- if (!palette) return E_INVALIDARG;
-
- EnterCriticalSection(&This->lock);
-
- if (This->frame_initialized)
- hr = IWICPalette_GetColors(palette, 256, This->palette, &This->colors);
- else
- hr = WINCODEC_ERR_NOTINITIALIZED;
-
- LeaveCriticalSection(&This->lock);
- return hr;
-}
-
-static HRESULT WINAPI JpegEncoder_Frame_SetThumbnail(IWICBitmapFrameEncode *iface,
- IWICBitmapSource *pIThumbnail)
-{
- FIXME("(%p,%p): stub\n", iface, pIThumbnail);
- return WINCODEC_ERR_UNSUPPORTEDOPERATION;
-}
-
-static HRESULT WINAPI JpegEncoder_Frame_WritePixels(IWICBitmapFrameEncode *iface,
- UINT lineCount, UINT cbStride, UINT cbBufferSize, BYTE *pbPixels)
-{
- JpegEncoder *This = impl_from_IWICBitmapFrameEncode(iface);
- jmp_buf jmpbuf;
- BYTE *swapped_data = NULL, *current_row;
- UINT line;
- int 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 = TRUE;
- }
-
- 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)
- {
- UINT 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, ¤t_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,
- IWICBitmapSource *pIBitmapSource, WICRect *prc)
-{
- JpegEncoder *This = impl_from_IWICBitmapFrameEncode(iface);
- HRESULT hr;
- TRACE("(%p,%p,%s)\n", iface, pIBitmapSource, debug_wic_rect(prc));
-
- if (!This->frame_initialized)
- return WINCODEC_ERR_WRONGSTATE;
-
- hr = configure_write_source(iface, pIBitmapSource, prc,
- This->format ? This->format->guid : NULL, This->width, This->height,
- This->xres, This->yres);
-
- if (SUCCEEDED(hr))
- {
- hr = write_source(iface, pIBitmapSource, prc,
- This->format->guid, This->format->bpp, FALSE,
- This->width, This->height);
- }
-
- return hr;
-}
-
-static HRESULT WINAPI JpegEncoder_Frame_Commit(IWICBitmapFrameEncode *iface)
-{
- JpegEncoder *This = impl_from_IWICBitmapFrameEncode(iface);
- jmp_buf jmpbuf;
- TRACE("(%p)\n", iface);
-
- EnterCriticalSection(&This->lock);
-
- if (!This->started_compress || This->lines_written != This->height || This->frame_committed)
- {
- LeaveCriticalSection(&This->lock);
- return WINCODEC_ERR_WRONGSTATE;
- }
-
- /* set up setjmp/longjmp error handling */
- if (setjmp(jmpbuf))
- {
- LeaveCriticalSection(&This->lock);
- return E_FAIL;
- }
- This->cinfo.client_data = jmpbuf;
-
- pjpeg_finish_compress(&This->cinfo);
-
- This->frame_committed = TRUE;
-
- LeaveCriticalSection(&This->lock);
-
- return S_OK;
-}
-
-static HRESULT WINAPI JpegEncoder_Frame_GetMetadataQueryWriter(IWICBitmapFrameEncode *iface,
- IWICMetadataQueryWriter **ppIMetadataQueryWriter)
-{
- FIXME("(%p, %p): stub\n", iface, ppIMetadataQueryWriter);
- return E_NOTIMPL;
-}
-
-static const IWICBitmapFrameEncodeVtbl JpegEncoder_FrameVtbl = {
- JpegEncoder_Frame_QueryInterface,
- JpegEncoder_Frame_AddRef,
- JpegEncoder_Frame_Release,
- JpegEncoder_Frame_Initialize,
- JpegEncoder_Frame_SetSize,
- JpegEncoder_Frame_SetResolution,
- JpegEncoder_Frame_SetPixelFormat,
- JpegEncoder_Frame_SetColorContexts,
- JpegEncoder_Frame_SetPalette,
- JpegEncoder_Frame_SetThumbnail,
- JpegEncoder_Frame_WritePixels,
- JpegEncoder_Frame_WriteSource,
- JpegEncoder_Frame_Commit,
- JpegEncoder_Frame_GetMetadataQueryWriter
-};
-
-static HRESULT WINAPI JpegEncoder_QueryInterface(IWICBitmapEncoder *iface, REFIID iid,
- void **ppv)
-{
- JpegEncoder *This = impl_from_IWICBitmapEncoder(iface);
- TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
-
- if (!ppv) return E_INVALIDARG;
-
- if (IsEqualIID(&IID_IUnknown, iid) ||
- IsEqualIID(&IID_IWICBitmapEncoder, iid))
- {
- *ppv = &This->IWICBitmapEncoder_iface;
- }
- else
- {
- *ppv = NULL;
- return E_NOINTERFACE;
- }
-
- IUnknown_AddRef((IUnknown*)*ppv);
- return S_OK;
-}
-
-static ULONG WINAPI JpegEncoder_AddRef(IWICBitmapEncoder *iface)
-{
- JpegEncoder *This = impl_from_IWICBitmapEncoder(iface);
- ULONG ref = InterlockedIncrement(&This->ref);
-
- TRACE("(%p) refcount=%u\n", iface, ref);
-
- return ref;
-}
-
-static ULONG WINAPI JpegEncoder_Release(IWICBitmapEncoder *iface)
-{
- JpegEncoder *This = impl_from_IWICBitmapEncoder(iface);
- ULONG ref = InterlockedDecrement(&This->ref);
-
- TRACE("(%p) refcount=%u\n", iface, ref);
-
- if (ref == 0)
- {
- This->lock.DebugInfo->Spare[0] = 0;
- DeleteCriticalSection(&This->lock);
- if (This->initialized) pjpeg_destroy_compress(&This->cinfo);
- if (This->stream) IStream_Release(This->stream);
- HeapFree(GetProcessHeap(), 0, This);
- }
-
- return ref;
-}
-
-static HRESULT WINAPI JpegEncoder_Initialize(IWICBitmapEncoder *iface,
- IStream *pIStream, WICBitmapEncoderCacheOption cacheOption)
-{
- JpegEncoder *This = impl_from_IWICBitmapEncoder(iface);
- jmp_buf jmpbuf;
-
- TRACE("(%p,%p,%u)\n", iface, pIStream, cacheOption);
-
- EnterCriticalSection(&This->lock);
-
- if (This->initialized)
- {
- LeaveCriticalSection(&This->lock);
- return WINCODEC_ERR_WRONGSTATE;
- }
-
- pjpeg_std_error(&This->jerr);
-
- This->jerr.error_exit = error_exit_fn;
- This->jerr.emit_message = emit_message_fn;
-
- This->cinfo.err = &This->jerr;
-
- This->cinfo.client_data = jmpbuf;
-
- if (setjmp(jmpbuf))
- {
- LeaveCriticalSection(&This->lock);
- return E_FAIL;
- }
-
- pjpeg_CreateCompress(&This->cinfo, JPEG_LIB_VERSION, sizeof(struct jpeg_compress_struct));
-
- This->stream = pIStream;
- IStream_AddRef(pIStream);
-
- This->dest_mgr.next_output_byte = This->dest_buffer;
- This->dest_mgr.free_in_buffer = sizeof(This->dest_buffer);
-
- This->dest_mgr.init_destination = dest_mgr_init_destination;
- This->dest_mgr.empty_output_buffer = dest_mgr_empty_output_buffer;
- This->dest_mgr.term_destination = dest_mgr_term_destination;
-
- This->cinfo.dest = &This->dest_mgr;
-
- This->initialized = TRUE;
-
- LeaveCriticalSection(&This->lock);
-
- return S_OK;
-}
-
-static HRESULT WINAPI JpegEncoder_GetContainerFormat(IWICBitmapEncoder *iface, GUID *format)
-{
- TRACE("(%p,%p)\n", iface, format);
-
- if (!format)
- return E_INVALIDARG;
-
- memcpy(format, &GUID_ContainerFormatJpeg, sizeof(*format));
- return S_OK;
-}
-
-static HRESULT WINAPI JpegEncoder_GetEncoderInfo(IWICBitmapEncoder *iface, IWICBitmapEncoderInfo **info)
-{
- IWICComponentInfo *comp_info;
- HRESULT hr;
-
- TRACE("%p,%p\n", iface, info);
-
- if (!info) return E_INVALIDARG;
-
- hr = CreateComponentInfo(&CLSID_WICJpegEncoder, &comp_info);
- if (hr == S_OK)
- {
- hr = IWICComponentInfo_QueryInterface(comp_info, &IID_IWICBitmapEncoderInfo, (void **)info);
- IWICComponentInfo_Release(comp_info);
- }
- return hr;
-}
-
-static HRESULT WINAPI JpegEncoder_SetColorContexts(IWICBitmapEncoder *iface,
- UINT cCount, IWICColorContext **ppIColorContext)
-{
- FIXME("(%p,%u,%p): stub\n", iface, cCount, ppIColorContext);
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI JpegEncoder_SetPalette(IWICBitmapEncoder *iface, IWICPalette *pIPalette)
-{
- JpegEncoder *This = impl_from_IWICBitmapEncoder(iface);
- HRESULT hr;
-
- TRACE("(%p,%p)\n", iface, pIPalette);
-
- EnterCriticalSection(&This->lock);
-
- hr = This->initialized ? WINCODEC_ERR_UNSUPPORTEDOPERATION : WINCODEC_ERR_NOTINITIALIZED;
-
- LeaveCriticalSection(&This->lock);
-
- return hr;
-}
-
-static HRESULT WINAPI JpegEncoder_SetThumbnail(IWICBitmapEncoder *iface, IWICBitmapSource *pIThumbnail)
-{
- TRACE("(%p,%p)\n", iface, pIThumbnail);
- return WINCODEC_ERR_UNSUPPORTEDOPERATION;
-}
-
-static HRESULT WINAPI JpegEncoder_SetPreview(IWICBitmapEncoder *iface, IWICBitmapSource *pIPreview)
-{
- TRACE("(%p,%p)\n", iface, pIPreview);
- return WINCODEC_ERR_UNSUPPORTEDOPERATION;
-}
-
-static HRESULT WINAPI JpegEncoder_CreateNewFrame(IWICBitmapEncoder *iface,
- IWICBitmapFrameEncode **ppIFrameEncode, IPropertyBag2 **ppIEncoderOptions)
-{
- JpegEncoder *This = impl_from_IWICBitmapEncoder(iface);
- HRESULT hr;
- static const PROPBAG2 opts[6] =
- {
- { PROPBAG2_TYPE_DATA, VT_R4, 0, 0, (LPOLESTR)wszImageQuality },
- { PROPBAG2_TYPE_DATA, VT_UI1, 0, 0, (LPOLESTR)wszBitmapTransform },
- { PROPBAG2_TYPE_DATA, VT_I4 | VT_ARRAY, 0, 0, (LPOLESTR)wszLuminance },
- { PROPBAG2_TYPE_DATA, VT_I4 | VT_ARRAY, 0, 0, (LPOLESTR)wszChrominance },
- { PROPBAG2_TYPE_DATA, VT_UI1, 0, 0, (LPOLESTR)wszJpegYCrCbSubsampling },
- { PROPBAG2_TYPE_DATA, VT_BOOL, 0, 0, (LPOLESTR)wszSuppressApp0 },
- };
-
- TRACE("(%p,%p,%p)\n", iface, ppIFrameEncode, ppIEncoderOptions);
-
- EnterCriticalSection(&This->lock);
-
- if (This->frame_count != 0)
- {
- LeaveCriticalSection(&This->lock);
- return WINCODEC_ERR_UNSUPPORTEDOPERATION;
- }
-
- if (!This->initialized)
- {
- LeaveCriticalSection(&This->lock);
- return WINCODEC_ERR_NOTINITIALIZED;
- }
-
- if (ppIEncoderOptions)
- {
- hr = CreatePropertyBag2(opts, ARRAY_SIZE(opts), ppIEncoderOptions);
- if (FAILED(hr))
- {
- LeaveCriticalSection(&This->lock);
- return hr;
- }
- }
-
- This->frame_count = 1;
-
- LeaveCriticalSection(&This->lock);
-
- IWICBitmapEncoder_AddRef(iface);
- *ppIFrameEncode = &This->IWICBitmapFrameEncode_iface;
-
- return S_OK;
-}
-
-static HRESULT WINAPI JpegEncoder_Commit(IWICBitmapEncoder *iface)
-{
- JpegEncoder *This = impl_from_IWICBitmapEncoder(iface);
- TRACE("(%p)\n", iface);
-
- EnterCriticalSection(&This->lock);
-
- if (!This->frame_committed || This->committed)
- {
- LeaveCriticalSection(&This->lock);
- return WINCODEC_ERR_WRONGSTATE;
- }
-
- This->committed = TRUE;
-
- LeaveCriticalSection(&This->lock);
-
- return S_OK;
-}
-
-static HRESULT WINAPI JpegEncoder_GetMetadataQueryWriter(IWICBitmapEncoder *iface,
- IWICMetadataQueryWriter **ppIMetadataQueryWriter)
-{
- FIXME("(%p,%p): stub\n", iface, ppIMetadataQueryWriter);
- return E_NOTIMPL;
-}
-
-static const IWICBitmapEncoderVtbl JpegEncoder_Vtbl = {
- JpegEncoder_QueryInterface,
- JpegEncoder_AddRef,
- JpegEncoder_Release,
- JpegEncoder_Initialize,
- JpegEncoder_GetContainerFormat,
- JpegEncoder_GetEncoderInfo,
- JpegEncoder_SetColorContexts,
- JpegEncoder_SetPalette,
- JpegEncoder_SetThumbnail,
- JpegEncoder_SetPreview,
- JpegEncoder_CreateNewFrame,
- JpegEncoder_Commit,
- JpegEncoder_GetMetadataQueryWriter
-};
-
-HRESULT JpegEncoder_CreateInstance(REFIID iid, void** ppv)
-{
- JpegEncoder *This;
- HRESULT ret;
-
- TRACE("(%s,%p)\n", debugstr_guid(iid), ppv);
-
- *ppv = NULL;
-
- if (!libjpeg_handle && !load_libjpeg())
- {
- ERR("Failed writing JPEG because unable to find %s\n",SONAME_LIBJPEG);
- return E_FAIL;
- }
-
- This = HeapAlloc(GetProcessHeap(), 0, sizeof(JpegEncoder));
- if (!This) return E_OUTOFMEMORY;
-
- This->IWICBitmapEncoder_iface.lpVtbl = &JpegEncoder_Vtbl;
- This->IWICBitmapFrameEncode_iface.lpVtbl = &JpegEncoder_FrameVtbl;
- This->ref = 1;
- This->initialized = FALSE;
- This->frame_count = 0;
- This->frame_initialized = FALSE;
- This->started_compress = FALSE;
- This->lines_written = 0;
- This->frame_committed = FALSE;
- This->committed = FALSE;
- This->width = This->height = 0;
- This->xres = This->yres = 0.0;
- This->format = NULL;
- This->stream = NULL;
- This->colors = 0;
- InitializeCriticalSection(&This->lock);
- This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JpegEncoder.lock");
-
- ret = IWICBitmapEncoder_QueryInterface(&This->IWICBitmapEncoder_iface, iid, ppv);
- IWICBitmapEncoder_Release(&This->IWICBitmapEncoder_iface);
-
- return ret;
-}
-
-#else /* !defined(SONAME_LIBJPEG) */
-
-HRESULT JpegEncoder_CreateInstance(REFIID iid, void** ppv)
-{
- ERR("Trying to save JPEG picture, but JPEG support is not compiled in.\n");
- return E_FAIL;
-}
-
-#endif
-
-HRESULT JpegDecoder_CreateInstance(REFIID iid, void** ppv)
-{
- HRESULT hr;
- struct decoder *decoder;
- struct decoder_info decoder_info;
-
- hr = get_unix_decoder(&CLSID_WICJpegDecoder, &decoder_info, &decoder);
-
- if (SUCCEEDED(hr))
- hr = CommonDecoder_CreateInstance(decoder, &decoder_info, iid, ppv);
-
- return hr;
-}
diff --git a/dlls/windowscodecs/libjpeg.c b/dlls/windowscodecs/libjpeg.c
index 58ca58e93b4..84e4df5e007 100644
--- a/dlls/windowscodecs/libjpeg.c
+++ b/dlls/windowscodecs/libjpeg.c
@@ -453,6 +453,313 @@ HRESULT CDECL jpeg_decoder_create(struct decoder_info *info, struct decoder **re
return S_OK;
}
+typedef struct jpeg_compress_format {
+ const WICPixelFormatGUID *guid;
+ int bpp;
+ int num_components;
+ J_COLOR_SPACE color_space;
+ int swap_rgb;
+} jpeg_compress_format;
+
+static const jpeg_compress_format compress_formats[] = {
+ { &GUID_WICPixelFormat24bppBGR, 24, 3, JCS_RGB, 1 },
+ { &GUID_WICPixelFormat32bppCMYK, 32, 4, JCS_CMYK },
+ { &GUID_WICPixelFormat8bppGray, 8, 1, JCS_GRAYSCALE },
+ { 0 }
+};
+
+struct jpeg_encoder
+{
+ struct encoder encoder;
+ IStream *stream;
+ BOOL cinfo_initialized;
+ struct jpeg_compress_struct cinfo;
+ struct jpeg_error_mgr jerr;
+ struct jpeg_destination_mgr dest_mgr;
+ struct encoder_frame encoder_frame;
+ const jpeg_compress_format *format;
+ BYTE dest_buffer[1024];
+};
+
+static inline struct jpeg_encoder *impl_from_encoder(struct encoder* iface)
+{
+ return CONTAINING_RECORD(iface, struct jpeg_encoder, encoder);
+}
+
+static inline struct jpeg_encoder *encoder_from_compress(j_compress_ptr compress)
+{
+ return CONTAINING_RECORD(compress, struct jpeg_encoder, cinfo);
+}
+
+static void dest_mgr_init_destination(j_compress_ptr cinfo)
+{
+ struct jpeg_encoder *This = encoder_from_compress(cinfo);
+
+ This->dest_mgr.next_output_byte = This->dest_buffer;
+ This->dest_mgr.free_in_buffer = sizeof(This->dest_buffer);
+}
+
+static jpeg_boolean dest_mgr_empty_output_buffer(j_compress_ptr cinfo)
+{
+ struct jpeg_encoder *This = encoder_from_compress(cinfo);
+ HRESULT hr;
+ ULONG byteswritten;
+
+ hr = stream_write(This->stream, This->dest_buffer,
+ sizeof(This->dest_buffer), &byteswritten);
+
+ if (hr != S_OK || byteswritten == 0)
+ {
+ ERR("Failed writing data, hr=%x\n", hr);
+ return FALSE;
+ }
+
+ This->dest_mgr.next_output_byte = This->dest_buffer;
+ This->dest_mgr.free_in_buffer = sizeof(This->dest_buffer);
+ return TRUE;
+}
+
+static void dest_mgr_term_destination(j_compress_ptr cinfo)
+{
+ struct jpeg_encoder *This = encoder_from_compress(cinfo);
+ ULONG byteswritten;
+ HRESULT hr;
+
+ if (This->dest_mgr.free_in_buffer != sizeof(This->dest_buffer))
+ {
+ hr = stream_write(This->stream, This->dest_buffer,
+ sizeof(This->dest_buffer) - This->dest_mgr.free_in_buffer, &byteswritten);
+
+ if (hr != S_OK || byteswritten == 0)
+ ERR("Failed writing data, hr=%x\n", hr);
+ }
+}
+
+HRESULT CDECL jpeg_encoder_initialize(struct encoder* iface, IStream *stream)
+{
+ struct jpeg_encoder *This = impl_from_encoder(iface);
+ jmp_buf jmpbuf;
+
+ pjpeg_std_error(&This->jerr);
+
+ This->jerr.error_exit = error_exit_fn;
+ This->jerr.emit_message = emit_message_fn;
+
+ This->cinfo.err = &This->jerr;
+
+ This->cinfo.client_data = jmpbuf;
+
+ if (setjmp(jmpbuf))
+ return E_FAIL;
+
+ pjpeg_CreateCompress(&This->cinfo, JPEG_LIB_VERSION, sizeof(struct jpeg_compress_struct));
+
+ This->stream = stream;
+
+ This->dest_mgr.next_output_byte = This->dest_buffer;
+ This->dest_mgr.free_in_buffer = sizeof(This->dest_buffer);
+
+ This->dest_mgr.init_destination = dest_mgr_init_destination;
+ This->dest_mgr.empty_output_buffer = dest_mgr_empty_output_buffer;
+ This->dest_mgr.term_destination = dest_mgr_term_destination;
+
+ This->cinfo.dest = &This->dest_mgr;
+
+ This->cinfo_initialized = TRUE;
+
+ return S_OK;
+}
+
+HRESULT CDECL jpeg_encoder_get_supported_format(struct encoder* iface, GUID *pixel_format,
+ DWORD *bpp, BOOL *indexed)
+{
+ int i;
+
+ for (i=0; compress_formats[i].guid; i++)
+ {
+ if (memcmp(compress_formats[i].guid, pixel_format, sizeof(GUID)) == 0)
+ break;
+ }
+
+ if (!compress_formats[i].guid) i = 0;
+
+ *pixel_format = *compress_formats[i].guid;
+ *bpp = compress_formats[i].bpp;
+ *indexed = FALSE;
+
+ return S_OK;
+}
+
+HRESULT CDECL jpeg_encoder_create_frame(struct encoder* iface, const struct encoder_frame *frame)
+{
+ struct jpeg_encoder *This = impl_from_encoder(iface);
+ jmp_buf jmpbuf;
+ int i;
+
+ This->encoder_frame = *frame;
+
+ if (setjmp(jmpbuf))
+ return E_FAIL;
+
+ This->cinfo.client_data = jmpbuf;
+
+ for (i=0; compress_formats[i].guid; i++)
+ {
+ if (memcmp(compress_formats[i].guid, &frame->pixel_format, sizeof(GUID)) == 0)
+ break;
+ }
+ This->format = &compress_formats[i];
+
+ This->cinfo.image_width = frame->width;
+ This->cinfo.image_height = frame->height;
+ This->cinfo.input_components = This->format->num_components;
+ This->cinfo.in_color_space = This->format->color_space;
+
+ pjpeg_set_defaults(&This->cinfo);
+
+ if (frame->dpix != 0.0 && frame->dpiy != 0.0)
+ {
+ This->cinfo.density_unit = 1; /* dots per inch */
+ This->cinfo.X_density = frame->dpix;
+ This->cinfo.Y_density = frame->dpiy;
+ }
+
+ pjpeg_start_compress(&This->cinfo, TRUE);
+
+ return S_OK;
+}
+
+HRESULT CDECL jpeg_encoder_write_lines(struct encoder* iface, BYTE *data,
+ DWORD line_count, DWORD stride)
+{
+ struct jpeg_encoder *This = impl_from_encoder(iface);
+ jmp_buf jmpbuf;
+ BYTE *swapped_data = NULL, *current_row;
+ UINT line;
+ int row_size;
+
+ if (setjmp(jmpbuf))
+ {
+ free(swapped_data);
+ return E_FAIL;
+ }
+
+ This->cinfo.client_data = jmpbuf;
+
+ row_size = This->format->bpp / 8 * This->encoder_frame.width;
+
+ if (This->format->swap_rgb)
+ {
+ swapped_data = malloc(row_size);
+ if (!swapped_data)
+ return E_OUTOFMEMORY;
+ }
+
+ for (line=0; line < line_count; line++)
+ {
+ if (This->format->swap_rgb)
+ {
+ UINT x;
+
+ memcpy(swapped_data, data + (stride * line), row_size);
+
+ for (x=0; x < This->encoder_frame.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 = data + (stride * line);
+
+ if (!pjpeg_write_scanlines(&This->cinfo, ¤t_row, 1))
+ {
+ ERR("failed writing scanlines\n");
+ free(swapped_data);
+ return E_FAIL;
+ }
+ }
+
+ free(swapped_data);
+
+ return S_OK;
+}
+
+HRESULT CDECL jpeg_encoder_commit_frame(struct encoder* iface)
+{
+ struct jpeg_encoder *This = impl_from_encoder(iface);
+ jmp_buf jmpbuf;
+
+ if (setjmp(jmpbuf))
+ return E_FAIL;
+
+ This->cinfo.client_data = jmpbuf;
+
+ pjpeg_finish_compress(&This->cinfo);
+
+ return S_OK;
+}
+
+HRESULT CDECL jpeg_encoder_commit_file(struct encoder* iface)
+{
+ return S_OK;
+}
+
+void CDECL jpeg_encoder_destroy(struct encoder* iface)
+{
+ struct jpeg_encoder *This = impl_from_encoder(iface);
+ if (This->cinfo_initialized)
+ pjpeg_destroy_compress(&This->cinfo);
+ RtlFreeHeap(GetProcessHeap(), 0, This);
+};
+
+static const struct encoder_funcs jpeg_encoder_vtable = {
+ jpeg_encoder_initialize,
+ jpeg_encoder_get_supported_format,
+ jpeg_encoder_create_frame,
+ jpeg_encoder_write_lines,
+ jpeg_encoder_commit_frame,
+ jpeg_encoder_commit_file,
+ jpeg_encoder_destroy
+};
+
+HRESULT CDECL jpeg_encoder_create(struct encoder_info *info, struct encoder **result)
+{
+ struct jpeg_encoder *This;
+
+ if (!load_libjpeg())
+ {
+ ERR("Failed writing JPEG because unable to find %s\n", SONAME_LIBJPEG);
+ return E_FAIL;
+ }
+
+ This = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(struct jpeg_encoder));
+ if (!This) return E_OUTOFMEMORY;
+
+ This->encoder.vtable = &jpeg_encoder_vtable;
+ This->stream = NULL;
+ This->cinfo_initialized = FALSE;
+ *result = &This->encoder;
+
+ info->flags = 0;
+ info->container_format = GUID_ContainerFormatJpeg;
+ info->clsid = CLSID_WICJpegEncoder;
+ info->encoder_options[0] = ENCODER_OPTION_IMAGE_QUALITY;
+ info->encoder_options[1] = ENCODER_OPTION_BITMAP_TRANSFORM;
+ info->encoder_options[2] = ENCODER_OPTION_LUMINANCE;
+ info->encoder_options[3] = ENCODER_OPTION_CHROMINANCE;
+ info->encoder_options[4] = ENCODER_OPTION_YCRCB_SUBSAMPLING;
+ info->encoder_options[5] = ENCODER_OPTION_SUPPRESS_APP0;
+ info->encoder_options[6] = ENCODER_OPTION_END;
+
+ return S_OK;
+}
+
#else /* !defined(SONAME_LIBJPEG) */
HRESULT CDECL jpeg_decoder_create(struct decoder_info *info, struct decoder **result)
@@ -461,4 +768,10 @@ HRESULT CDECL jpeg_decoder_create(struct decoder_info *info, struct decoder **re
return E_FAIL;
}
+HRESULT CDECL jpeg_encoder_create(struct encoder_info *info, struct encoder **result)
+{
+ ERR("Trying to save JPEG picture, but JPEG support is not compiled in.\n");
+ return E_FAIL;
+}
+
#endif
diff --git a/dlls/windowscodecs/main.c b/dlls/windowscodecs/main.c
index bc12eb2fda1..b8ffb216186 100644
--- a/dlls/windowscodecs/main.c
+++ b/dlls/windowscodecs/main.c
@@ -279,3 +279,31 @@ HRESULT TiffEncoder_CreateInstance(REFIID iid, void** ppv)
return hr;
}
+
+HRESULT JpegDecoder_CreateInstance(REFIID iid, void** ppv)
+{
+ HRESULT hr;
+ struct decoder *decoder;
+ struct decoder_info decoder_info;
+
+ hr = get_unix_decoder(&CLSID_WICJpegDecoder, &decoder_info, &decoder);
+
+ if (SUCCEEDED(hr))
+ hr = CommonDecoder_CreateInstance(decoder, &decoder_info, iid, ppv);
+
+ return hr;
+}
+
+HRESULT JpegEncoder_CreateInstance(REFIID iid, void** ppv)
+{
+ HRESULT hr;
+ struct encoder *encoder;
+ struct encoder_info encoder_info;
+
+ hr = get_unix_encoder(&CLSID_WICJpegEncoder, &encoder_info, &encoder);
+
+ if (SUCCEEDED(hr))
+ hr = CommonEncoder_CreateInstance(encoder, &encoder_info, iid, ppv);
+
+ return hr;
+}
diff --git a/dlls/windowscodecs/unix_lib.c b/dlls/windowscodecs/unix_lib.c
index 7101880b93c..f94340fc971 100644
--- a/dlls/windowscodecs/unix_lib.c
+++ b/dlls/windowscodecs/unix_lib.c
@@ -89,6 +89,9 @@ HRESULT CDECL encoder_create(const CLSID *encoder_clsid, struct encoder_info *in
if (IsEqualGUID(encoder_clsid, &CLSID_WICTiffEncoder))
return tiff_encoder_create(info, result);
+ if (IsEqualGUID(encoder_clsid, &CLSID_WICJpegEncoder))
+ return jpeg_encoder_create(info, result);
+
return E_NOTIMPL;
}
diff --git a/dlls/windowscodecs/wincodecs_private.h b/dlls/windowscodecs/wincodecs_private.h
index ab0329b8bb3..3814edb32bb 100644
--- a/dlls/windowscodecs/wincodecs_private.h
+++ b/dlls/windowscodecs/wincodecs_private.h
@@ -343,6 +343,12 @@ enum encoder_option
ENCODER_OPTION_FILTER,
ENCODER_OPTION_COMPRESSION_METHOD,
ENCODER_OPTION_COMPRESSION_QUALITY,
+ ENCODER_OPTION_IMAGE_QUALITY,
+ ENCODER_OPTION_BITMAP_TRANSFORM,
+ ENCODER_OPTION_LUMINANCE,
+ ENCODER_OPTION_CHROMINANCE,
+ ENCODER_OPTION_YCRCB_SUBSAMPLING,
+ ENCODER_OPTION_SUPPRESS_APP0,
ENCODER_OPTION_END
};
@@ -400,6 +406,7 @@ HRESULT CDECL jpeg_decoder_create(struct decoder_info *info, struct decoder **re
HRESULT CDECL png_encoder_create(struct encoder_info *info, struct encoder **result);
HRESULT CDECL tiff_encoder_create(struct encoder_info *info, struct encoder **result);
+HRESULT CDECL jpeg_encoder_create(struct encoder_info *info, struct encoder **result);
struct unix_funcs
{
--
2.17.1
More information about the wine-devel
mailing list