From 4fb9b87edfb24fe5676f5944fc6aaeff7fdbfdc3 Mon Sep 17 00:00:00 2001 From: Dmitry Timoshkov Date: Fri, 11 Mar 2016 03:48:46 +0100 Subject: windowscodecs: Implement WICCreateBitmapFromSection(Ex). (v2) --- dlls/windowscodecs/bitmap.c | 27 ++++++++----- dlls/windowscodecs/imgfactory.c | 73 ++++++++++++++++++++++++++++++++++- dlls/windowscodecs/windowscodecs.spec | 3 +- include/wincodec.idl | 8 ++++ 4 files changed, 100 insertions(+), 11 deletions(-) diff --git a/dlls/windowscodecs/bitmap.c b/dlls/windowscodecs/bitmap.c index 6adaab0..76298b2 100644 --- a/dlls/windowscodecs/bitmap.c +++ b/dlls/windowscodecs/bitmap.c @@ -45,6 +45,7 @@ typedef struct BitmapImpl { int palette_set; LONG lock; /* 0 if not locked, -1 if locked for writing, count if locked for reading */ BYTE *data; + BOOL is_section; /* TRUE if data is a section created by an application */ UINT width, height; UINT stride; UINT bpp; @@ -284,7 +285,10 @@ static ULONG WINAPI BitmapImpl_Release(IWICBitmap *iface) if (This->palette) IWICPalette_Release(This->palette); This->cs.DebugInfo->Spare[0] = 0; DeleteCriticalSection(&This->cs); - HeapFree(GetProcessHeap(), 0, This->data); + if (This->is_section) + UnmapViewOfFile(This->data); + else + HeapFree(GetProcessHeap(), 0, This->data); HeapFree(GetProcessHeap(), 0, This); } @@ -694,13 +698,12 @@ static const IMILUnknown2Vtbl IMILUnknown2Impl_Vtbl = }; HRESULT BitmapImpl_Create(UINT uiWidth, UINT uiHeight, - UINT stride, UINT datasize, BYTE *bits, + UINT stride, UINT datasize, BYTE *data, REFWICPixelFormatGUID pixelFormat, WICBitmapCreateCacheOption option, IWICBitmap **ppIBitmap) { HRESULT hr; BitmapImpl *This; - BYTE *data; UINT bpp; hr = get_pixelformat_bpp(pixelFormat, &bpp); @@ -713,14 +716,20 @@ HRESULT BitmapImpl_Create(UINT uiWidth, UINT uiHeight, if (stride < ((bpp*uiWidth)+7)/8) return E_INVALIDARG; This = HeapAlloc(GetProcessHeap(), 0, sizeof(BitmapImpl)); - data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, datasize); - if (!This || !data) + if (!This) return E_OUTOFMEMORY; + + if (!data) { - HeapFree(GetProcessHeap(), 0, This); - HeapFree(GetProcessHeap(), 0, data); - return E_OUTOFMEMORY; + data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, datasize); + if (!data) + { + HeapFree(GetProcessHeap(), 0, This); + return E_OUTOFMEMORY; + } + This->is_section = FALSE; } - if (bits) memcpy(data, bits, datasize); + else + This->is_section = TRUE; This->IWICBitmap_iface.lpVtbl = &BitmapImpl_Vtbl; This->IMILBitmapSource_iface.lpVtbl = &IMILBitmapImpl_Vtbl; diff --git a/dlls/windowscodecs/imgfactory.c b/dlls/windowscodecs/imgfactory.c index 659aa7e..3cd6fd0 100644 --- a/dlls/windowscodecs/imgfactory.c +++ b/dlls/windowscodecs/imgfactory.c @@ -595,12 +595,36 @@ static HRESULT WINAPI ComponentFactory_CreateBitmapFromMemory(IWICComponentFacto UINT width, UINT height, REFWICPixelFormatGUID format, UINT stride, UINT size, BYTE *buffer, IWICBitmap **bitmap) { + HRESULT hr; + TRACE("(%p,%u,%u,%s,%u,%u,%p,%p\n", iface, width, height, debugstr_guid(format), stride, size, buffer, bitmap); if (!stride || !size || !buffer || !bitmap) return E_INVALIDARG; - return BitmapImpl_Create(width, height, stride, size, buffer, format, WICBitmapCacheOnLoad, bitmap); + hr = BitmapImpl_Create(width, height, stride, size, NULL, format, WICBitmapCacheOnLoad, bitmap); + if (SUCCEEDED(hr)) + { + IWICBitmapLock *lock; + + hr = IWICBitmap_Lock(*bitmap, NULL, WICBitmapLockWrite, &lock); + if (SUCCEEDED(hr)) + { + UINT buffersize; + BYTE *data; + + IWICBitmapLock_GetDataPointer(lock, &buffersize, &data); + memcpy(data, buffer, buffersize); + + IWICBitmapLock_Release(lock); + } + else + { + IWICBitmap_Release(*bitmap); + *bitmap = NULL; + } + } + return hr; } static BOOL get_16bpp_format(HBITMAP hbm, WICPixelFormatGUID *format) @@ -1176,3 +1200,50 @@ HRESULT ComponentFactory_CreateInstance(REFIID iid, void** ppv) return ret; } + +HRESULT WINAPI WICCreateBitmapFromSectionEx(UINT width, UINT height, + REFWICPixelFormatGUID format, HANDLE section, UINT stride, + UINT offset, WICSectionAccessLevel wicaccess, IWICBitmap **bitmap) +{ + DWORD access; + void *buffer; + HRESULT hr; + + TRACE("%u,%u,%s,%p,%u,%#x,%#x,%p\n", width, height, debugstr_guid(format), + section, stride, offset, wicaccess, bitmap); + + if (!width || !height || !section || !bitmap) return E_INVALIDARG; + + switch (wicaccess) + { + case WICSectionAccessLevelReadWrite: + access = FILE_MAP_READ | FILE_MAP_WRITE; + break; + + case WICSectionAccessLevelRead: + access = FILE_MAP_READ; + break; + + default: + FIXME("unsupported access %#x\n", wicaccess); + return E_INVALIDARG; + } + + buffer = MapViewOfFile(section, access, 0, offset, 0); + if (!buffer) return HRESULT_FROM_WIN32(GetLastError()); + + hr = BitmapImpl_Create(width, height, stride, 0, buffer, format, WICBitmapCacheOnLoad, bitmap); + if (FAILED(hr)) UnmapViewOfFile(buffer); + return hr; +} + +HRESULT WINAPI WICCreateBitmapFromSection(UINT width, UINT height, + REFWICPixelFormatGUID format, HANDLE section, + UINT stride, UINT offset, IWICBitmap **bitmap) +{ + TRACE("%u,%u,%s,%p,%u,%u,%p\n", width, height, debugstr_guid(format), + section, stride, offset, bitmap); + + return WICCreateBitmapFromSectionEx(width, height, format, section, + stride, offset, WICSectionAccessLevelRead, bitmap); +} diff --git a/dlls/windowscodecs/windowscodecs.spec b/dlls/windowscodecs/windowscodecs.spec index 81a827e..7ee76d9 100644 --- a/dlls/windowscodecs/windowscodecs.spec +++ b/dlls/windowscodecs/windowscodecs.spec @@ -105,7 +105,8 @@ @ stdcall IWICStream_InitializeFromIStream_Proxy(ptr ptr) IWICStream_InitializeFromIStream_Proxy_W @ stdcall IWICStream_InitializeFromMemory_Proxy(ptr ptr long) IWICStream_InitializeFromMemory_Proxy_W @ stdcall WICConvertBitmapSource(ptr ptr ptr) -@ stub WICCreateBitmapFromSection +@ stdcall WICCreateBitmapFromSection(long long ptr long long long ptr) +@ stdcall WICCreateBitmapFromSectionEx(long long ptr long long long long ptr) @ stdcall WICCreateColorContext_Proxy(ptr ptr) @ stdcall WICCreateImagingFactory_Proxy(long ptr) @ stub WICGetMetadataContentSize diff --git a/include/wincodec.idl b/include/wincodec.idl index 406fe6b..c0afe52 100644 --- a/include/wincodec.idl +++ b/include/wincodec.idl @@ -179,6 +179,12 @@ typedef enum WICPngFilterOption { WICPNFFILTEROPTION_FORCE_DWORD = CODEC_FORCE_DWORD } WICPngFilterOption; +typedef enum WICSectionAccessLevel { + WICSectionAccessLevelRead = 0x00000001, + WICSectionAccessLevelReadWrite = 0x00000003, + WICSectionAccessLevel_FORCE_DWORD = CODEC_FORCE_DWORD +} WICSectionAccessLevel; + typedef GUID WICPixelFormatGUID; typedef REFGUID REFWICPixelFormatGUID; @@ -994,6 +1000,8 @@ interface IWICEnumMetadataItem : IUnknown } cpp_quote("HRESULT WINAPI WICConvertBitmapSource(REFWICPixelFormatGUID dstFormat, IWICBitmapSource *pISrc, IWICBitmapSource **ppIDst);") +cpp_quote("HRESULT WINAPI WICCreateBitmapFromSection(UINT width, UINT height, REFWICPixelFormatGUID format, HANDLE section, UINT stride, UINT offset, IWICBitmap **bitmap);") +cpp_quote("HRESULT WINAPI WICCreateBitmapFromSectionEx(UINT width, UINT height, REFWICPixelFormatGUID format, HANDLE section, UINT stride, UINT offset, WICSectionAccessLevel access, IWICBitmap **bitmap);") cpp_quote("DEFINE_GUID(CLSID_WICBmpDecoder, 0x6b462062,0x7cbf,0x400d,0x9f,0xdb,0x81,0x3d,0xd1,0x0f,0x27,0x78);") cpp_quote("DEFINE_GUID(CLSID_WICPngDecoder, 0x389ea17b,0x5078,0x4cde,0xb6,0xef,0x25,0xc1,0x51,0x75,0xc7,0x51);") -- 2.9.0