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:
parent
26aae271bb
commit
19033430ae
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue