Commit 19033430 authored by Esme Povirk's avatar Esme Povirk Committed by Alexandre Julliard

windowscodecs: Start interface for unix encoders.

parent 26aae271
...@@ -611,6 +611,55 @@ HRESULT CDECL png_decoder_create(struct decoder_info *info, struct decoder **res ...@@ -611,6 +611,55 @@ HRESULT CDECL png_decoder_create(struct decoder_info *info, struct decoder **res
return S_OK; 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 #else
HRESULT CDECL png_decoder_create(struct decoder_info *info, struct decoder **result) 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 ...@@ -619,4 +668,10 @@ HRESULT CDECL png_decoder_create(struct decoder_info *info, struct decoder **res
return E_FAIL; 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 #endif
...@@ -309,9 +309,6 @@ static CRITICAL_SECTION_DEBUG init_png_cs_debug = ...@@ -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 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) static void *load_libpng(void)
{ {
void *result; void *result;
...@@ -392,6 +389,14 @@ static void user_warning_fn(png_structp png_ptr, png_const_charp warning_message ...@@ -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)); 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 { struct png_pixelformat {
const WICPixelFormatGUID *guid; const WICPixelFormatGUID *guid;
UINT bpp; UINT bpp;
...@@ -426,6 +431,8 @@ typedef struct PngEncoder { ...@@ -426,6 +431,8 @@ typedef struct PngEncoder {
IStream *stream; IStream *stream;
png_structp png_ptr; png_structp png_ptr;
png_infop info_ptr; png_infop info_ptr;
struct encoder *encoder;
struct encoder_info encoder_info;
UINT frame_count; UINT frame_count;
BOOL frame_initialized; BOOL frame_initialized;
const struct png_pixelformat *format; const struct png_pixelformat *format;
...@@ -964,6 +971,7 @@ static ULONG WINAPI PngEncoder_Release(IWICBitmapEncoder *iface) ...@@ -964,6 +971,7 @@ static ULONG WINAPI PngEncoder_Release(IWICBitmapEncoder *iface)
if (This->stream) if (This->stream)
IStream_Release(This->stream); IStream_Release(This->stream);
HeapFree(GetProcessHeap(), 0, This->data); HeapFree(GetProcessHeap(), 0, This->data);
encoder_destroy(This->encoder);
HeapFree(GetProcessHeap(), 0, This); HeapFree(GetProcessHeap(), 0, This);
} }
...@@ -1045,17 +1053,19 @@ static HRESULT WINAPI PngEncoder_Initialize(IWICBitmapEncoder *iface, ...@@ -1045,17 +1053,19 @@ static HRESULT WINAPI PngEncoder_Initialize(IWICBitmapEncoder *iface,
static HRESULT WINAPI PngEncoder_GetContainerFormat(IWICBitmapEncoder *iface, GUID *format) static HRESULT WINAPI PngEncoder_GetContainerFormat(IWICBitmapEncoder *iface, GUID *format)
{ {
PngEncoder *This = impl_from_IWICBitmapEncoder(iface);
TRACE("(%p,%p)\n", iface, format); TRACE("(%p,%p)\n", iface, format);
if (!format) if (!format)
return E_INVALIDARG; return E_INVALIDARG;
memcpy(format, &GUID_ContainerFormatPng, sizeof(*format)); memcpy(format, &This->encoder_info.container_format, sizeof(*format));
return S_OK; return S_OK;
} }
static HRESULT WINAPI PngEncoder_GetEncoderInfo(IWICBitmapEncoder *iface, IWICBitmapEncoderInfo **info) static HRESULT WINAPI PngEncoder_GetEncoderInfo(IWICBitmapEncoder *iface, IWICBitmapEncoderInfo **info)
{ {
PngEncoder *This = impl_from_IWICBitmapEncoder(iface);
IWICComponentInfo *comp_info; IWICComponentInfo *comp_info;
HRESULT hr; HRESULT hr;
...@@ -1063,7 +1073,7 @@ static HRESULT WINAPI PngEncoder_GetEncoderInfo(IWICBitmapEncoder *iface, IWICBi ...@@ -1063,7 +1073,7 @@ static HRESULT WINAPI PngEncoder_GetEncoderInfo(IWICBitmapEncoder *iface, IWICBi
if (!info) return E_INVALIDARG; if (!info) return E_INVALIDARG;
hr = CreateComponentInfo(&CLSID_WICPngEncoder, &comp_info); hr = CreateComponentInfo(&This->encoder_info.clsid, &comp_info);
if (hr == S_OK) if (hr == S_OK)
{ {
hr = IWICComponentInfo_QueryInterface(comp_info, &IID_IWICBitmapEncoderInfo, (void **)info); hr = IWICComponentInfo_QueryInterface(comp_info, &IID_IWICBitmapEncoderInfo, (void **)info);
...@@ -1112,11 +1122,8 @@ static HRESULT WINAPI PngEncoder_CreateNewFrame(IWICBitmapEncoder *iface, ...@@ -1112,11 +1122,8 @@ static HRESULT WINAPI PngEncoder_CreateNewFrame(IWICBitmapEncoder *iface,
{ {
PngEncoder *This = impl_from_IWICBitmapEncoder(iface); PngEncoder *This = impl_from_IWICBitmapEncoder(iface);
HRESULT hr; HRESULT hr;
static const PROPBAG2 opts[2] = DWORD opts_length;
{ PROPBAG2 opts[6];
{ PROPBAG2_TYPE_DATA, VT_BOOL, 0, 0, (LPOLESTR)wszPngInterlaceOption },
{ PROPBAG2_TYPE_DATA, VT_UI1, 0, 0, (LPOLESTR)wszPngFilterOption },
};
TRACE("(%p,%p,%p)\n", iface, ppIFrameEncode, ppIEncoderOptions); TRACE("(%p,%p,%p)\n", iface, ppIFrameEncode, ppIEncoderOptions);
...@@ -1136,7 +1143,12 @@ static HRESULT WINAPI PngEncoder_CreateNewFrame(IWICBitmapEncoder *iface, ...@@ -1136,7 +1143,12 @@ static HRESULT WINAPI PngEncoder_CreateNewFrame(IWICBitmapEncoder *iface,
if (ppIEncoderOptions) 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)) if (FAILED(hr))
{ {
LeaveCriticalSection(&This->lock); LeaveCriticalSection(&This->lock);
...@@ -1215,6 +1227,14 @@ HRESULT PngEncoder_CreateInstance(REFIID iid, void** ppv) ...@@ -1215,6 +1227,14 @@ HRESULT PngEncoder_CreateInstance(REFIID iid, void** ppv)
This = HeapAlloc(GetProcessHeap(), 0, sizeof(PngEncoder)); This = HeapAlloc(GetProcessHeap(), 0, sizeof(PngEncoder));
if (!This) return E_OUTOFMEMORY; 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->IWICBitmapEncoder_iface.lpVtbl = &PngEncoder_Vtbl;
This->IWICBitmapFrameEncode_iface.lpVtbl = &PngEncoder_FrameVtbl; This->IWICBitmapFrameEncode_iface.lpVtbl = &PngEncoder_FrameVtbl;
This->ref = 1; This->ref = 1;
......
...@@ -143,3 +143,53 @@ HRESULT get_unix_decoder(const CLSID *decoder_clsid, struct decoder_info *info, ...@@ -143,3 +143,53 @@ HRESULT get_unix_decoder(const CLSID *decoder_clsid, struct decoder_info *info,
return hr; 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 ...@@ -76,6 +76,14 @@ HRESULT CDECL decoder_create(const CLSID *decoder_clsid, struct decoder_info *in
return E_NOTIMPL; 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 = { static const struct unix_funcs unix_funcs = {
decoder_create, decoder_create,
decoder_initialize, decoder_initialize,
...@@ -83,7 +91,9 @@ static const struct unix_funcs unix_funcs = { ...@@ -83,7 +91,9 @@ static const struct unix_funcs unix_funcs = {
decoder_copy_pixels, decoder_copy_pixels,
decoder_get_metadata_blocks, decoder_get_metadata_blocks,
decoder_get_color_context, 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 ) 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) ...@@ -48,6 +48,11 @@ void CDECL decoder_destroy(struct decoder *decoder)
decoder->vtable->destroy(decoder); decoder->vtable->destroy(decoder);
} }
void CDECL encoder_destroy(struct encoder *encoder)
{
encoder->vtable->destroy(encoder);
}
HRESULT copy_pixels(UINT bpp, const BYTE *srcbuffer, HRESULT copy_pixels(UINT bpp, const BYTE *srcbuffer,
UINT srcwidth, UINT srcheight, INT srcstride, UINT srcwidth, UINT srcheight, INT srcstride,
const WICRect *rc, UINT dststride, UINT dstbuffersize, BYTE *dstbuffer) 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 ...@@ -332,10 +332,41 @@ HRESULT CDECL decoder_get_color_context(struct decoder* This, UINT frame, UINT n
BYTE **data, DWORD *datasize); BYTE **data, DWORD *datasize);
void CDECL decoder_destroy(struct decoder *This); 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 png_decoder_create(struct decoder_info *info, struct decoder **result);
HRESULT CDECL tiff_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 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 struct unix_funcs
{ {
HRESULT (CDECL *decoder_create)(const CLSID *decoder_clsid, struct decoder_info *info, struct decoder **result); HRESULT (CDECL *decoder_create)(const CLSID *decoder_clsid, struct decoder_info *info, struct decoder **result);
...@@ -348,9 +379,12 @@ struct unix_funcs ...@@ -348,9 +379,12 @@ struct unix_funcs
HRESULT (CDECL *decoder_get_color_context)(struct decoder* This, UINT frame, UINT num, HRESULT (CDECL *decoder_get_color_context)(struct decoder* This, UINT frame, UINT num,
BYTE **data, DWORD *datasize); BYTE **data, DWORD *datasize);
void (CDECL *decoder_destroy)(struct decoder* This); 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_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, extern HRESULT CommonDecoder_CreateInstance(struct decoder *decoder,
const struct decoder_info *decoder_info, REFIID iid, void** ppv) DECLSPEC_HIDDEN; const struct decoder_info *decoder_info, REFIID iid, void** ppv) DECLSPEC_HIDDEN;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment