wincodecs: Implement FilterOption property for PNG encoder.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Vincent Povirk <vincent@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
62830143d1
commit
5107ef7566
|
@ -39,8 +39,6 @@
|
|||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
|
||||
|
||||
static const WCHAR wszPngInterlaceOption[] = {'I','n','t','e','r','l','a','c','e','O','p','t','i','o','n',0};
|
||||
|
||||
static inline ULONG read_ulong_be(BYTE* data)
|
||||
{
|
||||
return data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
|
||||
|
@ -327,6 +325,7 @@ MAKE_FUNCPTR(png_set_expand_gray_1_2_4_to_8);
|
|||
MAKE_FUNCPTR(png_set_gray_1_2_4_to_8);
|
||||
#endif
|
||||
MAKE_FUNCPTR(png_set_filler);
|
||||
MAKE_FUNCPTR(png_set_filter);
|
||||
MAKE_FUNCPTR(png_set_gray_to_rgb);
|
||||
MAKE_FUNCPTR(png_set_interlace_handling);
|
||||
MAKE_FUNCPTR(png_set_IHDR);
|
||||
|
@ -353,6 +352,9 @@ 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 +394,7 @@ static void *load_libpng(void)
|
|||
LOAD_FUNCPTR(png_set_gray_1_2_4_to_8);
|
||||
#endif
|
||||
LOAD_FUNCPTR(png_set_filler);
|
||||
LOAD_FUNCPTR(png_set_filter);
|
||||
LOAD_FUNCPTR(png_set_gray_to_rgb);
|
||||
LOAD_FUNCPTR(png_set_interlace_handling);
|
||||
LOAD_FUNCPTR(png_set_IHDR);
|
||||
|
@ -1356,6 +1359,7 @@ typedef struct PngEncoder {
|
|||
BOOL committed;
|
||||
CRITICAL_SECTION lock;
|
||||
BOOL interlace;
|
||||
WICPngFilterOption filter;
|
||||
BYTE *data;
|
||||
UINT stride;
|
||||
UINT passes;
|
||||
|
@ -1410,31 +1414,44 @@ static HRESULT WINAPI PngFrameEncode_Initialize(IWICBitmapFrameEncode *iface,
|
|||
IPropertyBag2 *pIEncoderOptions)
|
||||
{
|
||||
PngEncoder *This = impl_from_IWICBitmapFrameEncode(iface);
|
||||
WICPngFilterOption filter;
|
||||
BOOL interlace;
|
||||
PROPBAG2 opts[1]= {{0}};
|
||||
VARIANT opt_values[1];
|
||||
HRESULT opt_hres[1];
|
||||
PROPBAG2 opts[2]= {{0}};
|
||||
VARIANT opt_values[2];
|
||||
HRESULT opt_hres[2];
|
||||
HRESULT hr;
|
||||
|
||||
TRACE("(%p,%p)\n", iface, pIEncoderOptions);
|
||||
|
||||
opts[0].pstrName = (LPOLESTR)wszPngInterlaceOption;
|
||||
opts[0].vt = VT_BOOL;
|
||||
opts[1].pstrName = (LPOLESTR)wszPngFilterOption;
|
||||
opts[1].vt = VT_UI1;
|
||||
|
||||
if (pIEncoderOptions)
|
||||
{
|
||||
hr = IPropertyBag2_Read(pIEncoderOptions, 1, opts, NULL, opt_values, opt_hres);
|
||||
hr = IPropertyBag2_Read(pIEncoderOptions, sizeof(opts)/sizeof(opts[0]), opts, NULL, opt_values, opt_hres);
|
||||
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
if (V_VT(&opt_values[0]) == VT_EMPTY)
|
||||
interlace = FALSE;
|
||||
else
|
||||
interlace = (V_BOOL(&opt_values[0]) != 0);
|
||||
|
||||
filter = V_UI1(&opt_values[1]);
|
||||
if (filter > WICPngFilterAdaptive)
|
||||
{
|
||||
WARN("Unrecognized filter option value %u.\n", filter);
|
||||
filter = WICPngFilterUnspecified;
|
||||
}
|
||||
}
|
||||
else
|
||||
memset(opt_values, 0, sizeof(opt_values));
|
||||
|
||||
if (V_VT(&opt_values[0]) == VT_EMPTY)
|
||||
{
|
||||
interlace = FALSE;
|
||||
else
|
||||
interlace = (V_BOOL(&opt_values[0]) != 0);
|
||||
filter = WICPngFilterUnspecified;
|
||||
}
|
||||
|
||||
EnterCriticalSection(&This->lock);
|
||||
|
||||
|
@ -1445,6 +1462,7 @@ static HRESULT WINAPI PngFrameEncode_Initialize(IWICBitmapFrameEncode *iface,
|
|||
}
|
||||
|
||||
This->interlace = interlace;
|
||||
This->filter = filter;
|
||||
|
||||
This->frame_initialized = TRUE;
|
||||
|
||||
|
@ -1617,6 +1635,22 @@ static HRESULT WINAPI PngFrameEncode_WritePixels(IWICBitmapFrameEncode *iface,
|
|||
if (This->interlace)
|
||||
This->passes = ppng_set_interlace_handling(This->png_ptr);
|
||||
|
||||
if (This->filter != WICPngFilterUnspecified)
|
||||
{
|
||||
static const int png_filter_map[] =
|
||||
{
|
||||
/* WICPngFilterUnspecified */ PNG_NO_FILTERS,
|
||||
/* WICPngFilterNone */ PNG_FILTER_NONE,
|
||||
/* WICPngFilterSub */ PNG_FILTER_SUB,
|
||||
/* WICPngFilterUp */ PNG_FILTER_UP,
|
||||
/* WICPngFilterAverage */ PNG_FILTER_AVG,
|
||||
/* WICPngFilterPaeth */ PNG_FILTER_PAETH,
|
||||
/* WICPngFilterAdaptive */ PNG_ALL_FILTERS,
|
||||
};
|
||||
|
||||
ppng_set_filter(This->png_ptr, 0, png_filter_map[This->filter]);
|
||||
}
|
||||
|
||||
This->info_written = TRUE;
|
||||
}
|
||||
|
||||
|
@ -1926,7 +1960,7 @@ static HRESULT WINAPI PngEncoder_CreateNewFrame(IWICBitmapEncoder *iface,
|
|||
{
|
||||
PngEncoder *This = impl_from_IWICBitmapEncoder(iface);
|
||||
HRESULT hr;
|
||||
PROPBAG2 opts[1]= {{0}};
|
||||
PROPBAG2 opts[2]= {{0}};
|
||||
|
||||
TRACE("(%p,%p,%p)\n", iface, ppIFrameEncode, ppIEncoderOptions);
|
||||
|
||||
|
@ -1947,8 +1981,11 @@ static HRESULT WINAPI PngEncoder_CreateNewFrame(IWICBitmapEncoder *iface,
|
|||
opts[0].pstrName = (LPOLESTR)wszPngInterlaceOption;
|
||||
opts[0].vt = VT_BOOL;
|
||||
opts[0].dwType = PROPBAG2_TYPE_DATA;
|
||||
opts[1].pstrName = (LPOLESTR)wszPngFilterOption;
|
||||
opts[1].vt = VT_UI1;
|
||||
opts[1].dwType = PROPBAG2_TYPE_DATA;
|
||||
|
||||
hr = CreatePropertyBag2(opts, 1, ppIEncoderOptions);
|
||||
hr = CreatePropertyBag2(opts, sizeof(opts)/sizeof(opts[0]), ppIEncoderOptions);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
LeaveCriticalSection(&This->lock);
|
||||
|
|
|
@ -418,11 +418,13 @@ typedef struct property_opt_test_data
|
|||
VARTYPE initial_var_type;
|
||||
int i_init_val;
|
||||
float f_init_val;
|
||||
BOOL skippable;
|
||||
} property_opt_test_data;
|
||||
|
||||
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 wszInterlaceOption[] = {'I','n','t','e','r','l','a','c','e','O','p','t','i','o','n',0};
|
||||
static const WCHAR wszFilterOption[] = {'F','i','l','t','e','r','O','p','t','i','o','n',0};
|
||||
|
||||
static const struct property_opt_test_data testdata_tiff_props[] = {
|
||||
{ wszTiffCompressionMethod, VT_UI1, VT_UI1, WICTiffCompressionDontCare },
|
||||
|
@ -430,6 +432,12 @@ static const struct property_opt_test_data testdata_tiff_props[] = {
|
|||
{ NULL }
|
||||
};
|
||||
|
||||
static const struct property_opt_test_data testdata_png_props[] = {
|
||||
{ wszInterlaceOption, VT_BOOL, VT_BOOL, 0 },
|
||||
{ wszFilterOption, VT_UI1, VT_UI1, WICPngFilterUnspecified, 0.0f, TRUE /* not supported on XP/2k3 */},
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static int find_property_index(const WCHAR* name, PROPBAG2* all_props, int all_prop_cnt)
|
||||
{
|
||||
int i;
|
||||
|
@ -456,6 +464,13 @@ static void test_specific_encoder_properties(IPropertyBag2 *options, const prope
|
|||
|
||||
hr = IPropertyBag2_Read(options, 1, &pb, NULL, &pvarValue, &phrError);
|
||||
|
||||
if (data[i].skippable && idx == -1)
|
||||
{
|
||||
win_skip("Property %s is not supported on this machine.\n", wine_dbgstr_w(data[i].name));
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
ok(idx >= 0, "Property %s not in output of GetPropertyInfo\n",
|
||||
wine_dbgstr_w(data[i].name));
|
||||
if (idx >= 0)
|
||||
|
@ -543,8 +558,10 @@ static void test_encoder_properties(const CLSID* clsid_encoder, IPropertyBag2 *o
|
|||
(int)cProperties, (int)cProperties2);
|
||||
}
|
||||
|
||||
if (clsid_encoder == &CLSID_WICTiffEncoder)
|
||||
if (IsEqualCLSID(clsid_encoder, &CLSID_WICTiffEncoder))
|
||||
test_specific_encoder_properties(options, testdata_tiff_props, all_props, cProperties2);
|
||||
else if (IsEqualCLSID(clsid_encoder, &CLSID_WICPngEncoder))
|
||||
test_specific_encoder_properties(options, testdata_png_props, all_props, cProperties2);
|
||||
|
||||
for (i=0; i < cProperties2; i++)
|
||||
{
|
||||
|
|
|
@ -168,6 +168,17 @@ typedef enum WICTiffCompressionOption {
|
|||
WICTIFFCOMPRESSIONOPTION_FORCE_DWORD = CODEC_FORCE_DWORD
|
||||
} WICTiffCompressionOption;
|
||||
|
||||
typedef enum WICPngFilterOption {
|
||||
WICPngFilterUnspecified = 0,
|
||||
WICPngFilterNone = 1,
|
||||
WICPngFilterSub = 2,
|
||||
WICPngFilterUp = 3,
|
||||
WICPngFilterAverage = 4,
|
||||
WICPngFilterPaeth = 5,
|
||||
WICPngFilterAdaptive = 6,
|
||||
WICPNFFILTEROPTION_FORCE_DWORD = CODEC_FORCE_DWORD
|
||||
} WICPngFilterOption;
|
||||
|
||||
typedef GUID WICPixelFormatGUID;
|
||||
typedef REFGUID REFWICPixelFormatGUID;
|
||||
|
||||
|
|
Loading…
Reference in New Issue