windowscodecs: Start interface for unix encoders.

Signed-off-by: Esme Povirk <esme@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Esme Povirk 2020-11-15 14:12:24 -06:00 committed by Alexandre Julliard
parent 26aae271bb
commit 19033430ae
6 changed files with 186 additions and 12 deletions

View File

@ -611,6 +611,55 @@ HRESULT CDECL png_decoder_create(struct decoder_info *info, struct decoder **res
return S_OK;
}
struct png_encoder
{
struct encoder encoder;
};
static inline struct png_encoder *impl_from_encoder(struct encoder* iface)
{
return CONTAINING_RECORD(iface, struct png_encoder, encoder);
}
static void CDECL png_encoder_destroy(struct encoder *encoder)
{
struct png_encoder *This = impl_from_encoder(encoder);
RtlFreeHeap(GetProcessHeap(), 0, This);
}
static const struct encoder_funcs png_encoder_vtable = {
png_encoder_destroy
};
HRESULT CDECL png_encoder_create(struct encoder_info *info, struct encoder **result)
{
struct png_encoder *This;
if (!load_libpng())
{
ERR("Failed reading PNG because unable to find %s\n",SONAME_LIBPNG);
return E_FAIL;
}
This = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(*This));
if (!This)
{
return E_OUTOFMEMORY;
}
This->encoder.vtable = &png_encoder_vtable;
*result = &This->encoder;
info->container_format = GUID_ContainerFormatPng;
info->clsid = CLSID_WICPngEncoder;
info->encoder_options[0] = ENCODER_OPTION_INTERLACE;
info->encoder_options[1] = ENCODER_OPTION_FILTER;
info->encoder_options[2] = ENCODER_OPTION_END;
return S_OK;
}
#else
HRESULT CDECL png_decoder_create(struct decoder_info *info, struct decoder **result)
@ -619,4 +668,10 @@ HRESULT CDECL png_decoder_create(struct decoder_info *info, struct decoder **res
return E_FAIL;
}
HRESULT CDECL png_encoder_create(struct encoder_info *info, struct encoder **result)
{
ERR("Trying to save PNG picture, but PNG support is not compiled in.\n");
return E_FAIL;
}
#endif

View File

@ -309,9 +309,6 @@ static CRITICAL_SECTION_DEBUG init_png_cs_debug =
};
static CRITICAL_SECTION init_png_cs = { &init_png_cs_debug, -1, 0, 0, 0, 0 };
static const WCHAR wszPngInterlaceOption[] = {'I','n','t','e','r','l','a','c','e','O','p','t','i','o','n',0};
static const WCHAR wszPngFilterOption[] = {'F','i','l','t','e','r','O','p','t','i','o','n',0};
static void *load_libpng(void)
{
void *result;
@ -392,6 +389,14 @@ static void user_warning_fn(png_structp png_ptr, png_const_charp warning_message
WARN("PNG warning: %s\n", debugstr_a(warning_message));
}
static const WCHAR wszPngInterlaceOption[] = {'I','n','t','e','r','l','a','c','e','O','p','t','i','o','n',0};
static const WCHAR wszPngFilterOption[] = {'F','i','l','t','e','r','O','p','t','i','o','n',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 }
};
struct png_pixelformat {
const WICPixelFormatGUID *guid;
UINT bpp;
@ -426,6 +431,8 @@ typedef struct PngEncoder {
IStream *stream;
png_structp png_ptr;
png_infop info_ptr;
struct encoder *encoder;
struct encoder_info encoder_info;
UINT frame_count;
BOOL frame_initialized;
const struct png_pixelformat *format;
@ -964,6 +971,7 @@ static ULONG WINAPI PngEncoder_Release(IWICBitmapEncoder *iface)
if (This->stream)
IStream_Release(This->stream);
HeapFree(GetProcessHeap(), 0, This->data);
encoder_destroy(This->encoder);
HeapFree(GetProcessHeap(), 0, This);
}
@ -1045,17 +1053,19 @@ static HRESULT WINAPI PngEncoder_Initialize(IWICBitmapEncoder *iface,
static HRESULT WINAPI PngEncoder_GetContainerFormat(IWICBitmapEncoder *iface, GUID *format)
{
PngEncoder *This = impl_from_IWICBitmapEncoder(iface);
TRACE("(%p,%p)\n", iface, format);
if (!format)
return E_INVALIDARG;
memcpy(format, &GUID_ContainerFormatPng, sizeof(*format));
memcpy(format, &This->encoder_info.container_format, sizeof(*format));
return S_OK;
}
static HRESULT WINAPI PngEncoder_GetEncoderInfo(IWICBitmapEncoder *iface, IWICBitmapEncoderInfo **info)
{
PngEncoder *This = impl_from_IWICBitmapEncoder(iface);
IWICComponentInfo *comp_info;
HRESULT hr;
@ -1063,7 +1073,7 @@ static HRESULT WINAPI PngEncoder_GetEncoderInfo(IWICBitmapEncoder *iface, IWICBi
if (!info) return E_INVALIDARG;
hr = CreateComponentInfo(&CLSID_WICPngEncoder, &comp_info);
hr = CreateComponentInfo(&This->encoder_info.clsid, &comp_info);
if (hr == S_OK)
{
hr = IWICComponentInfo_QueryInterface(comp_info, &IID_IWICBitmapEncoderInfo, (void **)info);
@ -1112,11 +1122,8 @@ static HRESULT WINAPI PngEncoder_CreateNewFrame(IWICBitmapEncoder *iface,
{
PngEncoder *This = impl_from_IWICBitmapEncoder(iface);
HRESULT hr;
static const PROPBAG2 opts[2] =
{
{ PROPBAG2_TYPE_DATA, VT_BOOL, 0, 0, (LPOLESTR)wszPngInterlaceOption },
{ PROPBAG2_TYPE_DATA, VT_UI1, 0, 0, (LPOLESTR)wszPngFilterOption },
};
DWORD opts_length;
PROPBAG2 opts[6];
TRACE("(%p,%p,%p)\n", iface, ppIFrameEncode, ppIEncoderOptions);
@ -1136,7 +1143,12 @@ static HRESULT WINAPI PngEncoder_CreateNewFrame(IWICBitmapEncoder *iface,
if (ppIEncoderOptions)
{
hr = CreatePropertyBag2(opts, ARRAY_SIZE(opts), ppIEncoderOptions);
for (opts_length = 0; This->encoder_info.encoder_options[opts_length] < ENCODER_OPTION_END; opts_length++)
{
opts[opts_length] = encoder_option_properties[This->encoder_info.encoder_options[opts_length]];
}
hr = CreatePropertyBag2(opts, opts_length, ppIEncoderOptions);
if (FAILED(hr))
{
LeaveCriticalSection(&This->lock);
@ -1215,6 +1227,14 @@ HRESULT PngEncoder_CreateInstance(REFIID iid, void** ppv)
This = HeapAlloc(GetProcessHeap(), 0, sizeof(PngEncoder));
if (!This) return E_OUTOFMEMORY;
ret = get_unix_encoder(&CLSID_WICPngEncoder, &This->encoder_info, &This->encoder);
if (FAILED(ret))
{
HeapFree(GetProcessHeap(), 0, This);
return ret;
}
This->IWICBitmapEncoder_iface.lpVtbl = &PngEncoder_Vtbl;
This->IWICBitmapFrameEncode_iface.lpVtbl = &PngEncoder_FrameVtbl;
This->ref = 1;

View File

@ -143,3 +143,53 @@ HRESULT get_unix_decoder(const CLSID *decoder_clsid, struct decoder_info *info,
return hr;
}
struct encoder_wrapper
{
struct encoder win32_encoder;
struct encoder *unix_encoder;
};
static inline struct encoder_wrapper *impl_from_encoder(struct encoder* iface)
{
return CONTAINING_RECORD(iface, struct encoder_wrapper, win32_encoder);
}
void CDECL encoder_wrapper_destroy(struct encoder* iface)
{
struct encoder_wrapper* This = impl_from_encoder(iface);
unix_funcs->encoder_destroy(This->unix_encoder);
HeapFree(GetProcessHeap(), 0, This);
}
static const struct encoder_funcs encoder_wrapper_vtable = {
encoder_wrapper_destroy
};
HRESULT get_unix_encoder(const CLSID *encoder_clsid, struct encoder_info *info, struct encoder **result)
{
HRESULT hr;
struct encoder_wrapper *wrapper;
struct encoder *unix_encoder;
init_unixlib();
hr = unix_funcs->encoder_create(encoder_clsid, info, &unix_encoder);
if (SUCCEEDED(hr))
{
wrapper = HeapAlloc(GetProcessHeap(), 0, sizeof(*wrapper));
if (!wrapper)
{
unix_funcs->encoder_destroy(unix_encoder);
return E_OUTOFMEMORY;
}
wrapper->win32_encoder.vtable = &encoder_wrapper_vtable;
wrapper->unix_encoder = unix_encoder;
*result = &wrapper->win32_encoder;
}
return hr;
}

View File

@ -76,6 +76,14 @@ HRESULT CDECL decoder_create(const CLSID *decoder_clsid, struct decoder_info *in
return E_NOTIMPL;
}
HRESULT CDECL encoder_create(const CLSID *encoder_clsid, struct encoder_info *info, struct encoder **result)
{
if (IsEqualGUID(encoder_clsid, &CLSID_WICPngEncoder))
return png_encoder_create(info, result);
return E_NOTIMPL;
}
static const struct unix_funcs unix_funcs = {
decoder_create,
decoder_initialize,
@ -83,7 +91,9 @@ static const struct unix_funcs unix_funcs = {
decoder_copy_pixels,
decoder_get_metadata_blocks,
decoder_get_color_context,
decoder_destroy
decoder_destroy,
encoder_create,
encoder_destroy
};
NTSTATUS CDECL __wine_init_unix_lib( HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out )

View File

@ -48,6 +48,11 @@ void CDECL decoder_destroy(struct decoder *decoder)
decoder->vtable->destroy(decoder);
}
void CDECL encoder_destroy(struct encoder *encoder)
{
encoder->vtable->destroy(encoder);
}
HRESULT copy_pixels(UINT bpp, const BYTE *srcbuffer,
UINT srcwidth, UINT srcheight, INT srcstride,
const WICRect *rc, UINT dststride, UINT dstbuffersize, BYTE *dstbuffer)

View File

@ -332,10 +332,41 @@ HRESULT CDECL decoder_get_color_context(struct decoder* This, UINT frame, UINT n
BYTE **data, DWORD *datasize);
void CDECL decoder_destroy(struct decoder *This);
struct encoder_funcs;
/* sync with encoder_option_properties */
enum encoder_option
{
ENCODER_OPTION_INTERLACE,
ENCODER_OPTION_FILTER,
ENCODER_OPTION_END
};
struct encoder_info
{
GUID container_format;
CLSID clsid;
DWORD encoder_options[7];
};
struct encoder
{
const struct encoder_funcs *vtable;
};
struct encoder_funcs
{
void (CDECL *destroy)(struct encoder* This);
};
void CDECL encoder_destroy(struct encoder* This);
HRESULT CDECL png_decoder_create(struct decoder_info *info, struct decoder **result);
HRESULT CDECL tiff_decoder_create(struct decoder_info *info, struct decoder **result);
HRESULT CDECL jpeg_decoder_create(struct decoder_info *info, struct decoder **result);
HRESULT CDECL png_encoder_create(struct encoder_info *info, struct encoder **result);
struct unix_funcs
{
HRESULT (CDECL *decoder_create)(const CLSID *decoder_clsid, struct decoder_info *info, struct decoder **result);
@ -348,9 +379,12 @@ struct unix_funcs
HRESULT (CDECL *decoder_get_color_context)(struct decoder* This, UINT frame, UINT num,
BYTE **data, DWORD *datasize);
void (CDECL *decoder_destroy)(struct decoder* This);
HRESULT (CDECL *encoder_create)(const CLSID *encoder_clsid, struct encoder_info *info, struct encoder **result);
void (CDECL *encoder_destroy)(struct encoder* This);
};
HRESULT get_unix_decoder(const CLSID *decoder_clsid, struct decoder_info *info, struct decoder **result);
HRESULT get_unix_encoder(const CLSID *encoder_clsid, struct encoder_info *info, struct encoder **result);
extern HRESULT CommonDecoder_CreateInstance(struct decoder *decoder,
const struct decoder_info *decoder_info, REFIID iid, void** ppv) DECLSPEC_HIDDEN;