// Stores the first non-zero sized color profile from 'frame' to 'iccp'. // Returns an HRESULT to indicate success or failure. The caller is responsible // for freeing 'iccp->bytes' in either case. static HRESULT ExtractICCP(IWICImagingFactory* const factory, IWICBitmapFrameDecode* const frame, MetadataPayload* const iccp) { HRESULT hr = S_OK; UINT i, count; IWICColorContext** color_contexts; IFS(IWICBitmapFrameDecode_GetColorContexts(frame, 0, NULL, &count)); if (FAILED(hr) || count == 0) return hr; color_contexts = (IWICColorContext**)calloc(count, sizeof(*color_contexts)); if (color_contexts == NULL) return E_OUTOFMEMORY; for (i = 0; SUCCEEDED(hr) && i < count; ++i) { IFS(IWICImagingFactory_CreateColorContext(factory, &color_contexts[i])); } if (SUCCEEDED(hr)) { UINT num_color_contexts; IFS(IWICBitmapFrameDecode_GetColorContexts(frame, count, color_contexts, &num_color_contexts)); assert(FAILED(hr) || num_color_contexts <= count); for (i = 0; SUCCEEDED(hr) && i < num_color_contexts; ++i) { WICColorContextType type; IFS(IWICColorContext_GetType(color_contexts[i], &type)); if (SUCCEEDED(hr) && type == WICColorContextProfile) { UINT size; IFS(IWICColorContext_GetProfileBytes(color_contexts[i], 0, NULL, &size)); if (SUCCEEDED(hr) && size > 0) { iccp->bytes = (uint8_t*)malloc(size); if (iccp->bytes == NULL) { hr = E_OUTOFMEMORY; break; } iccp->size = size; IFS(IWICColorContext_GetProfileBytes(color_contexts[i], (UINT)iccp->size, iccp->bytes, &size)); if (SUCCEEDED(hr) && size != iccp->size) { fprintf(stderr, "Warning! ICC profile size (%u) != expected (%u)\n", size, (uint32_t)iccp->size); iccp->size = size; } break; } } } } for (i = 0; i < count; ++i) { if (color_contexts[i] != NULL) IUnknown_Release(color_contexts[i]); } free(color_contexts); return hr; }
HRESULT WINAPI IWICBitmapFrameDecode_GetColorContexts_Proxy_W(IWICBitmapFrameDecode *iface, UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount) { return IWICBitmapFrameDecode_GetColorContexts(iface, cCount, ppIColorContexts, pcActualCount); }
static void test_decode_24bpp(void) { IWICBitmapDecoder *decoder, *decoder2; IWICBitmapFrameDecode *framedecode; IWICMetadataQueryReader *queryreader; IWICColorContext *colorcontext; IWICBitmapSource *thumbnail; HRESULT hr; HGLOBAL hbmpdata; char *bmpdata; IStream *bmpstream; DWORD capability=0; GUID guidresult; UINT count=0, width=0, height=0; double dpiX, dpiY; BYTE imagedata[36] = {1}; const BYTE expected_imagedata[36] = { 255,0,255, 255,255,255, 255,0,0, 255,255,0, 0,0,0, 0,255,0}; WICRect rc; hr = CoCreateInstance(&CLSID_WICBmpDecoder, NULL, CLSCTX_INPROC_SERVER, &IID_IWICBitmapDecoder, (void**)&decoder); ok(SUCCEEDED(hr), "CoCreateInstance failed, hr=%x\n", hr); if (FAILED(hr)) return; hbmpdata = GlobalAlloc(GMEM_MOVEABLE, sizeof(testbmp_24bpp)); ok(hbmpdata != 0, "GlobalAlloc failed\n"); if (hbmpdata) { bmpdata = GlobalLock(hbmpdata); memcpy(bmpdata, testbmp_24bpp, sizeof(testbmp_24bpp)); GlobalUnlock(hbmpdata); hr = CreateStreamOnHGlobal(hbmpdata, FALSE, &bmpstream); ok(SUCCEEDED(hr), "CreateStreamOnHGlobal failed, hr=%x\n", hr); if (SUCCEEDED(hr)) { hr = IWICBitmapDecoder_Initialize(decoder, bmpstream, WICDecodeMetadataCacheOnLoad); ok(hr == S_OK || broken(hr == WINCODEC_ERR_BADIMAGE) /* XP */, "Initialize failed, hr=%x\n", hr); if (FAILED(hr)) { win_skip("BMP decoder failed to initialize\n"); GlobalFree(hbmpdata); IWICBitmapDecoder_Release(decoder); return; } hr = IWICBitmapDecoder_GetContainerFormat(decoder, &guidresult); ok(SUCCEEDED(hr), "GetContainerFormat failed, hr=%x\n", hr); ok(IsEqualGUID(&guidresult, &GUID_ContainerFormatBmp), "unexpected container format\n"); hr = IWICBitmapDecoder_GetMetadataQueryReader(decoder, &queryreader); ok(hr == WINCODEC_ERR_UNSUPPORTEDOPERATION, "expected WINCODEC_ERR_UNSUPPORTEDOPERATION, got %x\n", hr); hr = IWICBitmapDecoder_GetColorContexts(decoder, 1, &colorcontext, &count); ok(hr == WINCODEC_ERR_UNSUPPORTEDOPERATION, "expected WINCODEC_ERR_UNSUPPORTEDOPERATION, got %x\n", hr); hr = IWICBitmapDecoder_GetThumbnail(decoder, &thumbnail); ok(hr == WINCODEC_ERR_CODECNOTHUMBNAIL, "expected WINCODEC_ERR_CODECNOTHUMBNAIL, got %x\n", hr); hr = IWICBitmapDecoder_GetPreview(decoder, &thumbnail); ok(hr == WINCODEC_ERR_UNSUPPORTEDOPERATION, "expected WINCODEC_ERR_UNSUPPORTEDOPERATION, got %x\n", hr); hr = IWICBitmapDecoder_GetFrameCount(decoder, &count); ok(SUCCEEDED(hr), "GetFrameCount failed, hr=%x\n", hr); ok(count == 1, "unexpected count %u\n", count); hr = IWICBitmapDecoder_GetFrame(decoder, 1, &framedecode); ok(hr == E_INVALIDARG || hr == WINCODEC_ERR_FRAMEMISSING, "GetFrame returned %x\n", hr); hr = IWICBitmapDecoder_GetFrame(decoder, 0, &framedecode); ok(SUCCEEDED(hr), "GetFrame failed, hr=%x\n", hr); if (SUCCEEDED(hr)) { IWICImagingFactory *factory; IWICPalette *palette; hr = IWICBitmapFrameDecode_GetSize(framedecode, &width, &height); ok(SUCCEEDED(hr), "GetSize failed, hr=%x\n", hr); ok(width == 2, "expected width=2, got %u\n", width); ok(height == 3, "expected height=2, got %u\n", height); hr = IWICBitmapFrameDecode_GetResolution(framedecode, &dpiX, &dpiY); ok(SUCCEEDED(hr), "GetResolution failed, hr=%x\n", hr); ok(dpiX == 96.0, "expected dpiX=96.0, got %f\n", dpiX); ok(dpiY == 96.0, "expected dpiY=96.0, got %f\n", dpiY); hr = IWICBitmapFrameDecode_GetPixelFormat(framedecode, &guidresult); ok(SUCCEEDED(hr), "GetPixelFormat failed, hr=%x\n", hr); ok(IsEqualGUID(&guidresult, &GUID_WICPixelFormat24bppBGR), "unexpected pixel format\n"); hr = IWICBitmapFrameDecode_GetMetadataQueryReader(framedecode, &queryreader); ok(hr == WINCODEC_ERR_UNSUPPORTEDOPERATION, "expected WINCODEC_ERR_UNSUPPORTEDOPERATION, got %x\n", hr); hr = IWICBitmapFrameDecode_GetColorContexts(framedecode, 1, &colorcontext, &count); ok(hr == WINCODEC_ERR_UNSUPPORTEDOPERATION, "expected WINCODEC_ERR_UNSUPPORTEDOPERATION, got %x\n", hr); hr = IWICBitmapFrameDecode_GetThumbnail(framedecode, &thumbnail); ok(hr == WINCODEC_ERR_CODECNOTHUMBNAIL, "expected WINCODEC_ERR_CODECNOTHUMBNAIL, got %x\n", hr); hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, &IID_IWICImagingFactory, (void**)&factory); ok(SUCCEEDED(hr), "CoCreateInstance failed, hr=%x\n", hr); if (SUCCEEDED(hr)) { hr = IWICImagingFactory_CreatePalette(factory, &palette); ok(SUCCEEDED(hr), "CreatePalette failed, hr=%x\n", hr); if (SUCCEEDED(hr)) { hr = IWICBitmapDecoder_CopyPalette(decoder, palette); ok(hr == WINCODEC_ERR_PALETTEUNAVAILABLE, "expected WINCODEC_ERR_PALETTEUNAVAILABLE, got %x\n", hr); hr = IWICBitmapFrameDecode_CopyPalette(framedecode, palette); ok(hr == WINCODEC_ERR_PALETTEUNAVAILABLE, "expected WINCODEC_ERR_PALETTEUNAVAILABLE, got %x\n", hr); IWICPalette_Release(palette); } IWICImagingFactory_Release(factory); } rc.X = 0; rc.Y = 0; rc.Width = 3; rc.Height = 3; hr = IWICBitmapFrameDecode_CopyPixels(framedecode, &rc, 6, sizeof(imagedata), imagedata); ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %x\n", hr); rc.X = -1; rc.Y = 0; rc.Width = 2; rc.Height = 3; hr = IWICBitmapFrameDecode_CopyPixels(framedecode, &rc, 6, sizeof(imagedata), imagedata); ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %x\n", hr); rc.X = 0; rc.Y = 0; rc.Width = 2; rc.Height = 3; hr = IWICBitmapFrameDecode_CopyPixels(framedecode, &rc, 4, sizeof(imagedata), imagedata); ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %x\n", hr); rc.X = 0; rc.Y = 0; rc.Width = 2; rc.Height = 3; hr = IWICBitmapFrameDecode_CopyPixels(framedecode, &rc, 4, 5, imagedata); ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %x\n", hr); rc.X = 0; rc.Y = 0; rc.Width = 2; rc.Height = 3; hr = IWICBitmapFrameDecode_CopyPixels(framedecode, &rc, 6, sizeof(imagedata), imagedata); ok(SUCCEEDED(hr), "CopyPixels failed, hr=%x\n", hr); ok(!memcmp(imagedata, expected_imagedata, sizeof(imagedata)), "unexpected image data\n"); hr = IWICBitmapFrameDecode_CopyPixels(framedecode, NULL, 6, sizeof(imagedata), imagedata); ok(SUCCEEDED(hr), "CopyPixels(rect=NULL) failed, hr=%x\n", hr); ok(!memcmp(imagedata, expected_imagedata, sizeof(imagedata)), "unexpected image data\n"); IWICBitmapFrameDecode_Release(framedecode); } /* cannot initialize twice */ hr = IWICBitmapDecoder_Initialize(decoder, bmpstream, WICDecodeMetadataCacheOnLoad); ok(hr == WINCODEC_ERR_WRONGSTATE, "expected WINCODEC_ERR_WRONGSTATE, hr=%x\n", hr); /* cannot querycapability after initialize */ hr = IWICBitmapDecoder_QueryCapability(decoder, bmpstream, &capability); ok(hr == WINCODEC_ERR_WRONGSTATE, "expected WINCODEC_ERR_WRONGSTATE, hr=%x\n", hr); hr = CoCreateInstance(&CLSID_WICBmpDecoder, NULL, CLSCTX_INPROC_SERVER, &IID_IWICBitmapDecoder, (void**)&decoder2); ok(SUCCEEDED(hr), "CoCreateInstance failed, hr=%x\n", hr); if (SUCCEEDED(hr)) { hr = IWICBitmapDecoder_QueryCapability(decoder2, bmpstream, &capability); ok(hr == S_OK, "QueryCapability failed, hr=%x\n", hr); ok(capability == (WICBitmapDecoderCapabilityCanDecodeAllImages), "unexpected capabilities: %x\n", capability); /* cannot initialize after querycapability */ hr = IWICBitmapDecoder_Initialize(decoder2, bmpstream, WICDecodeMetadataCacheOnLoad); ok(hr == WINCODEC_ERR_WRONGSTATE, "expected WINCODEC_ERR_WRONGSTATE, hr=%x\n", hr); /* cannot querycapability twice */ hr = IWICBitmapDecoder_QueryCapability(decoder2, bmpstream, &capability); ok(hr == WINCODEC_ERR_WRONGSTATE, "expected WINCODEC_ERR_WRONGSTATE, hr=%x\n", hr); IWICBitmapDecoder_Release(decoder2); } IStream_Release(bmpstream); } GlobalFree(hbmpdata); } IWICBitmapDecoder_Release(decoder); }
static void test_color_contexts(void) { HRESULT hr; IWICBitmapDecoder *decoder; IWICBitmapFrameDecode *frame; IWICColorContext *context; WICColorContextType type; UINT count, colorspace, size; WCHAR *tmpfile; BYTE *buffer; BOOL ret; decoder = create_decoder(png_no_color_profile, sizeof(png_no_color_profile)); ok(decoder != 0, "Failed to load PNG image data\n"); if (!decoder) return; /* global color context */ hr = IWICBitmapDecoder_GetColorContexts(decoder, 0, NULL, NULL); ok(hr == WINCODEC_ERR_UNSUPPORTEDOPERATION, "GetColorContexts error %#x\n", hr); count = 0xdeadbeef; hr = IWICBitmapDecoder_GetColorContexts(decoder, 0, NULL, &count); ok(hr == WINCODEC_ERR_UNSUPPORTEDOPERATION, "GetColorContexts error %#x\n", hr); ok(count == 0xdeadbeef, "unexpected count %u\n", count); /* frame color context */ hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame); ok(hr == S_OK, "GetFrame error %#x\n", hr); hr = IWICBitmapFrameDecode_GetColorContexts(frame, 0, NULL, NULL); ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#x\n", hr); count = 0xdeadbeef; hr = IWICBitmapFrameDecode_GetColorContexts(frame, 0, NULL, &count); ok(hr == S_OK, "GetColorContexts error %#x\n", hr); ok(!count, "unexpected count %u\n", count); IWICBitmapFrameDecode_Release(frame); IWICBitmapDecoder_Release(decoder); decoder = create_decoder(png_color_profile, sizeof(png_color_profile)); ok(decoder != 0, "Failed to load PNG image data\n"); if (!decoder) return; /* global color context */ count = 0xdeadbeef; hr = IWICBitmapDecoder_GetColorContexts(decoder, 0, NULL, &count); ok(hr == WINCODEC_ERR_UNSUPPORTEDOPERATION, "GetColorContexts error %#x\n", hr); ok(count == 0xdeadbeef, "unexpected count %u\n", count); /* frame color context */ hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame); ok(hr == S_OK, "GetFrame error %#x\n", hr); count = 0xdeadbeef; hr = IWICBitmapFrameDecode_GetColorContexts(frame, 0, NULL, &count); ok(hr == S_OK, "GetColorContexts error %#x\n", hr); ok(count == 1, "unexpected count %u\n", count); hr = IWICImagingFactory_CreateColorContext(factory, NULL); ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#x\n", hr); hr = IWICImagingFactory_CreateColorContext(factory, &context); ok(hr == S_OK, "CreateColorContext error %#x\n", hr); hr = IWICColorContext_GetType(context, NULL); ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#x\n", hr); type = 0xdeadbeef; hr = IWICColorContext_GetType(context, &type); ok(hr == S_OK, "GetType error %#x\n", hr); ok(type == WICColorContextUninitialized, "unexpected type %u\n", type); hr = IWICColorContext_GetProfileBytes(context, 0, NULL, NULL); ok(hr == WINCODEC_ERR_NOTINITIALIZED, "GetProfileBytes error %#x\n", hr); size = 0; hr = IWICColorContext_GetProfileBytes(context, 0, NULL, &size); ok(hr == WINCODEC_ERR_NOTINITIALIZED, "GetProfileBytes error %#x\n", hr); ok(!size, "unexpected size %u\n", size); hr = IWICColorContext_GetExifColorSpace(context, NULL); ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#x\n", hr); colorspace = 0xdeadbeef; hr = IWICColorContext_GetExifColorSpace(context, &colorspace); ok(hr == S_OK, "GetExifColorSpace error %#x\n", hr); ok(colorspace == 0xffffffff, "unexpected color space %u\n", colorspace); hr = IWICColorContext_InitializeFromExifColorSpace(context, 0); ok(hr == S_OK, "InitializeFromExifColorSpace error %#x\n", hr); hr = IWICColorContext_InitializeFromExifColorSpace(context, 1); ok(hr == S_OK, "InitializeFromExifColorSpace error %#x\n", hr); hr = IWICColorContext_InitializeFromExifColorSpace(context, 2); ok(hr == S_OK, "InitializeFromExifColorSpace error %#x\n", hr); colorspace = 0xdeadbeef; hr = IWICColorContext_GetExifColorSpace(context, &colorspace); ok(hr == S_OK, "GetExifColorSpace error %#x\n", hr); ok(colorspace == 2, "unexpected color space %u\n", colorspace); size = 0; hr = IWICColorContext_GetProfileBytes(context, 0, NULL, &size); ok(hr == WINCODEC_ERR_NOTINITIALIZED, "GetProfileBytes error %#x\n", hr); ok(!size, "unexpected size %u\n", size); type = 0xdeadbeef; hr = IWICColorContext_GetType(context, &type); ok(hr == S_OK, "GetType error %#x\n", hr); ok(type == WICColorContextExifColorSpace, "unexpected type %u\n", type); hr = IWICBitmapFrameDecode_GetColorContexts(frame, count, &context, &count); ok(hr == WINCODEC_ERR_WRONGSTATE, "GetColorContexts error %#x\n", hr); IWICColorContext_Release(context); IWICBitmapFrameDecode_Release(frame); hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame); ok(hr == S_OK, "GetFrame error %#x\n", hr); hr = IWICImagingFactory_CreateColorContext(factory, &context); ok(hr == S_OK, "CreateColorContext error %#x\n", hr); count = 1; hr = IWICBitmapFrameDecode_GetColorContexts(frame, count, &context, &count); ok(hr == S_OK, "GetColorContexts error %#x\n", hr); hr = IWICColorContext_GetProfileBytes(context, 0, NULL, NULL); ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#x\n", hr); size = 0; hr = IWICColorContext_GetProfileBytes(context, 0, NULL, &size); ok(hr == S_OK, "GetProfileBytes error %#x\n", hr); ok(size, "unexpected size %u\n", size); buffer = HeapAlloc(GetProcessHeap(), 0, size); hr = IWICColorContext_GetProfileBytes(context, size, buffer, &size); ok(hr == S_OK, "GetProfileBytes error %#x\n", hr); tmpfile = save_profile( buffer, size ); HeapFree(GetProcessHeap(), 0, buffer); type = 0xdeadbeef; hr = IWICColorContext_GetType(context, &type); ok(hr == S_OK, "GetType error %#x\n", hr); ok(type == WICColorContextProfile, "unexpected type %u\n", type); colorspace = 0xdeadbeef; hr = IWICColorContext_GetExifColorSpace(context, &colorspace); ok(hr == S_OK, "GetExifColorSpace error %#x\n", hr); ok(colorspace == 0xffffffff, "unexpected color space %u\n", colorspace); hr = IWICColorContext_InitializeFromExifColorSpace(context, 1); ok(hr == WINCODEC_ERR_WRONGSTATE, "InitializeFromExifColorSpace error %#x\n", hr); if (tmpfile) { hr = IWICColorContext_InitializeFromFilename(context, NULL); ok(hr == E_INVALIDARG, "InitializeFromFilename error %#x\n", hr); hr = IWICColorContext_InitializeFromFilename(context, tmpfile); ok(hr == S_OK, "InitializeFromFilename error %#x\n", hr); ret = DeleteFileW(tmpfile); ok(ret, "DeleteFileW failed %u\n", GetLastError()); type = 0xdeadbeef; hr = IWICColorContext_GetType(context, &type); ok(hr == S_OK, "GetType error %#x\n", hr); ok(type == WICColorContextProfile, "unexpected type %u\n", type); colorspace = 0xdeadbeef; hr = IWICColorContext_GetExifColorSpace(context, &colorspace); ok(hr == S_OK, "GetExifColorSpace error %#x\n", hr); ok(colorspace == 0xffffffff, "unexpected color space %u\n", colorspace); hr = IWICColorContext_InitializeFromExifColorSpace(context, 1); ok(hr == WINCODEC_ERR_WRONGSTATE, "InitializeFromExifColorSpace error %#x\n", hr); size = 0; hr = IWICColorContext_GetProfileBytes(context, 0, NULL, &size); ok(hr == S_OK, "GetProfileBytes error %#x\n", hr); ok(size, "unexpected size %u\n", size); buffer = HeapAlloc(GetProcessHeap(), 0, size); hr = IWICColorContext_GetProfileBytes(context, size, buffer, &size); ok(hr == S_OK, "GetProfileBytes error %#x\n", hr); HeapFree(GetProcessHeap(), 0, buffer); HeapFree(GetProcessHeap(), 0, tmpfile); } IWICColorContext_Release(context); IWICBitmapFrameDecode_Release(frame); IWICBitmapDecoder_Release(decoder); }