#include "wincodecs_private.h"
-#include <winerror.h>
-
#ifdef HAVE_PNG_H
#include <png.h>
#endif
int num_trans;
png_uint_32 transparency;
png_color_16p trans_values;
- png_colorp png_palette;
- int num_palette;
jmp_buf jmpbuf;
BYTE chunk_type[4];
ULONG chunk_size;
ppng_destroy_read_struct(&This->png_ptr, &This->info_ptr, &This->end_info);
HeapFree(GetProcessHeap(), 0, row_pointers);
This->png_ptr = NULL;
- hr = WINCODEC_ERR_UNKNOWNIMAGEFORMAT;
+ hr = E_FAIL;
goto end;
}
ppng_set_error_fn(This->png_ptr, jmpbuf, user_error_fn, user_warning_fn);
/* check for color-keyed alpha */
transparency = ppng_get_tRNS(This->png_ptr, This->info_ptr, &trans, &num_trans, &trans_values);
- if (!ppng_get_PLTE(This->png_ptr, This->info_ptr, &png_palette, &num_palette))
- num_palette = 0;
-
- TRACE("color_type %d, bit_depth %d, transparency %d, num_palette %d\n",
- color_type, bit_depth, transparency, num_palette);
+ if (transparency && (color_type == PNG_COLOR_TYPE_RGB ||
+ (color_type == PNG_COLOR_TYPE_GRAY && bit_depth == 16)))
+ {
+ /* expand to RGBA */
+ if (color_type == PNG_COLOR_TYPE_GRAY)
+ ppng_set_gray_to_rgb(This->png_ptr);
+ ppng_set_tRNS_to_alpha(This->png_ptr);
+ color_type = PNG_COLOR_TYPE_RGB_ALPHA;
+ }
switch (color_type)
{
- case PNG_COLOR_TYPE_GRAY:
- This->bpp = bit_depth;
- switch (bit_depth)
- {
- case 1:
- This->format = num_palette ? &GUID_WICPixelFormat1bppIndexed : &GUID_WICPixelFormatBlackWhite;
- break;
- case 2:
- This->format = num_palette ? &GUID_WICPixelFormat2bppIndexed : &GUID_WICPixelFormat2bppGray;
- break;
- case 4:
- This->format = num_palette ? &GUID_WICPixelFormat4bppIndexed : &GUID_WICPixelFormat4bppGray;
- break;
- case 8:
- This->format = num_palette ? &GUID_WICPixelFormat8bppIndexed : &GUID_WICPixelFormat8bppGray;
- break;
- case 16: This->format = &GUID_WICPixelFormat16bppGray; break;
- default:
- ERR("invalid grayscale bit depth: %i\n", bit_depth);
- hr = WINCODEC_ERR_UNKNOWNIMAGEFORMAT;
- goto end;
- }
- break;
case PNG_COLOR_TYPE_GRAY_ALPHA:
/* WIC does not support grayscale alpha formats so use RGBA */
ppng_set_gray_to_rgb(This->png_ptr);
goto end;
}
break;
+ case PNG_COLOR_TYPE_GRAY:
+ This->bpp = bit_depth;
+ if (!transparency)
+ {
+ switch (bit_depth)
+ {
+ case 1: This->format = &GUID_WICPixelFormatBlackWhite; break;
+ case 2: This->format = &GUID_WICPixelFormat2bppGray; break;
+ case 4: This->format = &GUID_WICPixelFormat4bppGray; break;
+ case 8: This->format = &GUID_WICPixelFormat8bppGray; break;
+ case 16: This->format = &GUID_WICPixelFormat16bppGray; break;
+ default:
+ ERR("invalid grayscale bit depth: %i\n", bit_depth);
+ hr = E_FAIL;
+ goto end;
+ }
+ break;
+ }
+ /* else fall through */
case PNG_COLOR_TYPE_PALETTE:
This->bpp = bit_depth;
switch (bit_depth)
}
static HRESULT WINAPI PngDecoder_GetMetadataQueryReader(IWICBitmapDecoder *iface,
- IWICMetadataQueryReader **reader)
+ IWICMetadataQueryReader **ppIMetadataQueryReader)
{
- FIXME("(%p,%p): stub\n", iface, reader);
-
- if (!reader) return E_INVALIDARG;
-
- *reader = NULL;
- return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+ FIXME("(%p,%p): stub\n", iface, ppIMetadataQueryReader);
+ return E_NOTIMPL;
}
static HRESULT WINAPI PngDecoder_GetPreview(IWICBitmapDecoder *iface,
IWICPalette *pIPalette)
{
PngDecoder *This = impl_from_IWICBitmapFrameDecode(iface);
- png_uint_32 ret;
+ png_uint_32 ret, color_type, bit_depth;
png_colorp png_palette;
int num_palette;
WICColor palette[256];
EnterCriticalSection(&This->lock);
- ret = ppng_get_PLTE(This->png_ptr, This->info_ptr, &png_palette, &num_palette);
- if (!ret)
- {
- hr = WINCODEC_ERR_PALETTEUNAVAILABLE;
- goto end;
- }
+ color_type = ppng_get_color_type(This->png_ptr, This->info_ptr);
+ bit_depth = ppng_get_bit_depth(This->png_ptr, This->info_ptr);
- if (num_palette > 256)
+ if (color_type == PNG_COLOR_TYPE_PALETTE)
{
- ERR("palette has %i colors?!\n", num_palette);
- hr = E_FAIL;
- goto end;
+ ret = ppng_get_PLTE(This->png_ptr, This->info_ptr, &png_palette, &num_palette);
+ if (!ret)
+ {
+ hr = WINCODEC_ERR_PALETTEUNAVAILABLE;
+ goto end;
+ }
+
+ if (num_palette > 256)
+ {
+ ERR("palette has %i colors?!\n", num_palette);
+ hr = E_FAIL;
+ goto end;
+ }
+
+ ret = ppng_get_tRNS(This->png_ptr, This->info_ptr, &trans_alpha, &num_trans, &trans_values);
+ if (!ret) num_trans = 0;
+
+ for (i=0; i<num_palette; i++)
+ {
+ BYTE alpha = (i < num_trans) ? trans_alpha[i] : 0xff;
+ palette[i] = (alpha << 24 |
+ png_palette[i].red << 16|
+ png_palette[i].green << 8|
+ png_palette[i].blue);
+ }
}
+ else if (color_type == PNG_COLOR_TYPE_GRAY) {
+ ret = ppng_get_tRNS(This->png_ptr, This->info_ptr, &trans_alpha, &num_trans, &trans_values);
- ret = ppng_get_tRNS(This->png_ptr, This->info_ptr, &trans_alpha, &num_trans, &trans_values);
- if (!ret) num_trans = 0;
+ if (!ret)
+ {
+ hr = WINCODEC_ERR_PALETTEUNAVAILABLE;
+ goto end;
+ }
- for (i=0; i<num_palette; i++)
+ num_palette = 1 << bit_depth;
+
+ for (i=0; i<num_palette; i++)
+ {
+ BYTE alpha = (i == trans_values[0].gray) ? 0 : 0xff;
+ BYTE val = i * 255 / (num_palette - 1);
+ palette[i] = (alpha << 24 | val << 16 | val << 8 | val);
+ }
+ }
+ else
{
- BYTE alpha = (i < num_trans) ? trans_alpha[i] : 0xff;
- palette[i] = (alpha << 24 |
- png_palette[i].red << 16|
- png_palette[i].green << 8|
- png_palette[i].blue);
+ hr = WINCODEC_ERR_PALETTEUNAVAILABLE;
}
end:
/* Newer libpng versions don't accept larger palettes than the declared
* bit depth, so we need to generate the palette of the correct length.
*/
- colors = 1 << This->format->bit_depth;
+ colors = min(This->colors, 1 << This->format->bit_depth);
for (i = 0; i < colors; i++)
{
- if (i < This->colors)
- {
- png_palette[i].red = (This->palette[i] >> 16) & 0xff;
- png_palette[i].green = (This->palette[i] >> 8) & 0xff;
- png_palette[i].blue = This->palette[i] & 0xff;
- trans[i] = (This->palette[i] >> 24) & 0xff;
- if (trans[i] != 0xff)
- num_trans++;
- }
- else
- {
- png_palette[i].red = 0;
- png_palette[i].green = 0;
- png_palette[i].blue = 0;
- }
+ png_palette[i].red = (This->palette[i] >> 16) & 0xff;
+ png_palette[i].green = (This->palette[i] >> 8) & 0xff;
+ png_palette[i].blue = This->palette[i] & 0xff;
+ trans[i] = (This->palette[i] >> 24) & 0xff;
+ if (trans[i] != 0xff)
+ num_trans = i+1;
}
ppng_set_PLTE(This->png_ptr, This->info_ptr, png_palette, colors);
if (num_trans)
- ppng_set_tRNS(This->png_ptr, This->info_ptr, trans, colors, NULL);
+ ppng_set_tRNS(This->png_ptr, This->info_ptr, trans, num_trans, NULL);
}
ppng_write_info(This->png_ptr, This->info_ptr);
return E_NOTIMPL;
}
-static HRESULT WINAPI PngEncoder_GetEncoderInfo(IWICBitmapEncoder *iface, IWICBitmapEncoderInfo **info)
+static HRESULT WINAPI PngEncoder_GetEncoderInfo(IWICBitmapEncoder *iface,
+ IWICBitmapEncoderInfo **ppIEncoderInfo)
{
- IWICComponentInfo *comp_info;
- HRESULT hr;
-
- TRACE("%p,%p\n", iface, info);
-
- if (!info) return E_INVALIDARG;
-
- hr = CreateComponentInfo(&CLSID_WICPngEncoder, &comp_info);
- if (hr == S_OK)
- {
- hr = IWICComponentInfo_QueryInterface(comp_info, &IID_IWICBitmapEncoderInfo, (void **)info);
- IWICComponentInfo_Release(comp_info);
- }
- return hr;
+ FIXME("(%p,%p): stub\n", iface, ppIEncoderInfo);
+ return E_NOTIMPL;
}
static HRESULT WINAPI PngEncoder_SetColorContexts(IWICBitmapEncoder *iface,