[PATCH] windowscodecs: Implement WICCreateBitmapFromSectionEx.

Hans Leidekker hans at codeweavers.com
Mon Mar 19 05:50:04 CDT 2018


Based on a patch by Dmitry Timoshkov.

Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
 dlls/windowscodecs/bitmap.c            | 28 ++++++----
 dlls/windowscodecs/imgfactory.c        | 95 ++++++++++++++++++++++++++++++++--
 dlls/windowscodecs/tests/bitmap.c      | 60 +++++++++++++++++++++
 dlls/windowscodecs/wincodecs_private.h |  2 +-
 dlls/windowscodecs/windowscodecs.spec  |  3 +-
 include/wincodec.idl                   |  8 +++
 6 files changed, 180 insertions(+), 16 deletions(-)

diff --git a/dlls/windowscodecs/bitmap.c b/dlls/windowscodecs/bitmap.c
index 6adaab0aea..5de7e39901 100644
--- a/dlls/windowscodecs/bitmap.c
+++ b/dlls/windowscodecs/bitmap.c
@@ -45,6 +45,8 @@ typedef struct BitmapImpl {
     int palette_set;
     LONG lock; /* 0 if not locked, -1 if locked for writing, count if locked for reading */
     BYTE *data;
+    void *view; /* used if data is a section created by an application */
+    UINT offset; /* offset into view */
     UINT width, height;
     UINT stride;
     UINT bpp;
@@ -284,7 +286,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->view)
+            UnmapViewOfFile(This->view);
+        else
+            HeapFree(GetProcessHeap(), 0, This->data);
         HeapFree(GetProcessHeap(), 0, This);
     }
 
@@ -694,13 +699,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, void *view, UINT offset,
     REFWICPixelFormatGUID pixelFormat, WICBitmapCreateCacheOption option,
     IWICBitmap **ppIBitmap)
 {
     HRESULT hr;
     BitmapImpl *This;
-    BYTE *data;
     UINT bpp;
 
     hr = get_pixelformat_bpp(pixelFormat, &bpp);
@@ -713,14 +717,18 @@ 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 (view) data = (BYTE *)view + offset;
+    else 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;
+        }
     }
-    if (bits) memcpy(data, bits, datasize);
 
     This->IWICBitmap_iface.lpVtbl = &BitmapImpl_Vtbl;
     This->IMILBitmapSource_iface.lpVtbl = &IMILBitmapImpl_Vtbl;
@@ -731,6 +739,8 @@ HRESULT BitmapImpl_Create(UINT uiWidth, UINT uiHeight,
     This->palette_set = 0;
     This->lock = 0;
     This->data = data;
+    This->view = view;
+    This->offset = offset;
     This->width = uiWidth;
     This->height = uiHeight;
     This->stride = stride;
diff --git a/dlls/windowscodecs/imgfactory.c b/dlls/windowscodecs/imgfactory.c
index e1bcc89a8b..2cef8dc37f 100644
--- a/dlls/windowscodecs/imgfactory.c
+++ b/dlls/windowscodecs/imgfactory.c
@@ -473,7 +473,7 @@ static HRESULT WINAPI ComponentFactory_CreateBitmap(IWICComponentFactory *iface,
 {
     TRACE("(%p,%u,%u,%s,%u,%p)\n", iface, uiWidth, uiHeight,
         debugstr_guid(pixelFormat), option, ppIBitmap);
-    return BitmapImpl_Create(uiWidth, uiHeight, 0, 0, NULL, pixelFormat, option, ppIBitmap);
+    return BitmapImpl_Create(uiWidth, uiHeight, 0, 0, NULL, NULL, 0, pixelFormat, option, ppIBitmap);
 }
 
 static HRESULT WINAPI ComponentFactory_CreateBitmapFromSource(IWICComponentFactory *iface,
@@ -520,7 +520,7 @@ static HRESULT WINAPI ComponentFactory_CreateBitmapFromSource(IWICComponentFacto
     }
 
     if (SUCCEEDED(hr))
-        hr = BitmapImpl_Create(width, height, 0, 0, NULL, &pixelformat, option, &result);
+        hr = BitmapImpl_Create(width, height, 0, 0, NULL, NULL, 0, &pixelformat, option, &result);
 
     if (SUCCEEDED(hr))
     {
@@ -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, NULL, 0, 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)
@@ -710,7 +734,8 @@ static HRESULT WINAPI ComponentFactory_CreateBitmapFromHBITMAP(IWICComponentFact
         return E_INVALIDARG;
     }
 
-    hr = BitmapImpl_Create(bm.bmWidth, bm.bmHeight, bm.bmWidthBytes, 0, NULL, &format, WICBitmapCacheOnLoad, bitmap);
+    hr = BitmapImpl_Create(bm.bmWidth, bm.bmHeight, bm.bmWidthBytes, 0, NULL, NULL, 0, &format,
+                           WICBitmapCacheOnLoad, bitmap);
     if (hr != S_OK) return hr;
 
     hr = IWICBitmap_Lock(*bitmap, NULL, WICBitmapLockWrite, &lock);
@@ -794,7 +819,7 @@ static HRESULT WINAPI ComponentFactory_CreateBitmapFromHICON(IWICComponentFactor
     stride = width * 4;
     size = stride * height;
 
-    hr = BitmapImpl_Create(width, height, stride, size, NULL,
+    hr = BitmapImpl_Create(width, height, stride, size, NULL, NULL, 0,
                            &GUID_WICPixelFormat32bppBGRA, WICBitmapCacheOnLoad, bitmap);
     if (hr != S_OK) goto failed;
 
@@ -1176,3 +1201,63 @@ 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)
+{
+    SYSTEM_INFO sysinfo;
+    UINT bpp, access, size, view_offset, view_size;
+    void *view;
+    HRESULT hr;
+
+    TRACE("%u,%u,%s,%p,%u,%u,%#x,%p\n", width, height, debugstr_guid(format),
+          section, stride, offset, wicaccess, bitmap);
+
+    if (!width || !height || !section || !bitmap) return E_INVALIDARG;
+
+    hr = get_pixelformat_bpp(format, &bpp);
+    if (FAILED(hr)) return hr;
+
+    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;
+    }
+
+    if (!stride) stride = (((bpp * width) + 31) / 32) * 4;
+    size = stride * height;
+    if (size / height != stride || offset > size) return E_INVALIDARG;
+
+    GetSystemInfo(&sysinfo);
+    view_offset = offset - (offset % sysinfo.dwAllocationGranularity);
+    view_size = size + (offset - view_offset);
+
+    view = MapViewOfFile(section, access, 0, view_offset, view_size);
+    if (!view) return HRESULT_FROM_WIN32(GetLastError());
+
+    offset -= view_offset;
+    hr = BitmapImpl_Create(width, height, stride, 0, NULL, view, offset, format, WICBitmapCacheOnLoad, bitmap);
+    if (FAILED(hr)) UnmapViewOfFile(view);
+    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/tests/bitmap.c b/dlls/windowscodecs/tests/bitmap.c
index 42f452acaf..6e01f0b1d1 100644
--- a/dlls/windowscodecs/tests/bitmap.c
+++ b/dlls/windowscodecs/tests/bitmap.c
@@ -972,6 +972,64 @@ static void test_clipper(void)
     IWICBitmapClipper_Release(clipper);
 }
 
+static HRESULT (WINAPI *pWICCreateBitmapFromSectionEx)
+    (UINT, UINT, REFWICPixelFormatGUID, HANDLE, UINT, UINT, WICSectionAccessLevel, IWICBitmap **);
+
+static void test_WICCreateBitmapFromSectionEx(void)
+{
+    SYSTEM_INFO sysinfo;
+    HANDLE hsection;
+    BITMAPINFO info;
+    void *bits;
+    HBITMAP hdib;
+    IWICBitmap *bitmap;
+    HRESULT hr;
+    pWICCreateBitmapFromSectionEx =
+        (void *)GetProcAddress(LoadLibraryA("windowscodecs"), "WICCreateBitmapFromSectionEx");
+
+    if (!pWICCreateBitmapFromSectionEx)
+    {
+        win_skip("WICCreateBitmapFromSectionEx not available\n");
+        return;
+    }
+
+    GetSystemInfo(&sysinfo);
+    hsection = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0,
+                                  sysinfo.dwAllocationGranularity * 2, NULL);
+    ok(hsection != NULL, "CreateFileMapping failed %u\n", GetLastError());
+
+    memset(&info, 0, sizeof(info));
+    info.bmiHeader.biSize        = sizeof(info.bmiHeader);
+    info.bmiHeader.biWidth       = 3;
+    info.bmiHeader.biHeight      = -3;
+    info.bmiHeader.biBitCount    = 24;
+    info.bmiHeader.biPlanes      = 1;
+    info.bmiHeader.biCompression = BI_RGB;
+
+    hdib = CreateDIBSection(0, &info, DIB_RGB_COLORS, &bits, hsection, 0);
+    ok(hdib != NULL, "CreateDIBSection failed\n");
+
+    hr = pWICCreateBitmapFromSectionEx(3, 3, &GUID_WICPixelFormat24bppBGR, hsection, 0, 0,
+                                       WICSectionAccessLevelReadWrite, &bitmap);
+    ok(hr == S_OK, "WICCreateBitmapFromSectionEx returned %#x\n", hr);
+    IWICBitmap_Release(bitmap);
+
+    /* non-zero offset, smaller than allocation granularity */
+    hr = pWICCreateBitmapFromSectionEx(3, 3, &GUID_WICPixelFormat24bppBGR, hsection, 0, 0x100,
+                                       WICSectionAccessLevelReadWrite, &bitmap);
+    ok(hr == S_OK, "WICCreateBitmapFromSectionEx returned %#x\n", hr);
+    IWICBitmap_Release(bitmap);
+
+    /* offset larger than allocation granularity */
+    hr = pWICCreateBitmapFromSectionEx(3, 3, &GUID_WICPixelFormat24bppBGR, hsection, 0,
+                                       sysinfo.dwAllocationGranularity + 1,
+                                       WICSectionAccessLevelReadWrite, &bitmap);
+    ok(hr == S_OK, "WICCreateBitmapFromSectionEx returned %#x\n", hr);
+    IWICBitmap_Release(bitmap);
+    DeleteObject(hdib);
+    CloseHandle(hsection);
+}
+
 START_TEST(bitmap)
 {
     HRESULT hr;
@@ -992,4 +1050,6 @@ START_TEST(bitmap)
     IWICImagingFactory_Release(factory);
 
     CoUninitialize();
+
+    test_WICCreateBitmapFromSectionEx();
 }
diff --git a/dlls/windowscodecs/wincodecs_private.h b/dlls/windowscodecs/wincodecs_private.h
index 8bba811250..4647d07fa8 100644
--- a/dlls/windowscodecs/wincodecs_private.h
+++ b/dlls/windowscodecs/wincodecs_private.h
@@ -91,7 +91,7 @@ extern HRESULT IcnsEncoder_CreateInstance(REFIID iid, void** ppv) DECLSPEC_HIDDE
 extern HRESULT TgaDecoder_CreateInstance(REFIID iid, void** ppv) DECLSPEC_HIDDEN;
 
 extern HRESULT BitmapImpl_Create(UINT uiWidth, UINT uiHeight,
-    UINT stride, UINT datasize, BYTE *bits,
+    UINT stride, UINT datasize, BYTE *bits, void *view, UINT offset,
     REFWICPixelFormatGUID pixelFormat, WICBitmapCreateCacheOption option,
     IWICBitmap **ppIBitmap) DECLSPEC_HIDDEN;
 extern HRESULT BitmapScaler_Create(IWICBitmapScaler **scaler) DECLSPEC_HIDDEN;
diff --git a/dlls/windowscodecs/windowscodecs.spec b/dlls/windowscodecs/windowscodecs.spec
index 49346fc86b..905ef835af 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 f2c5a9e626..50d7db7620 100644
--- a/include/wincodec.idl
+++ b/include/wincodec.idl
@@ -189,6 +189,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;
 
@@ -1058,6 +1064,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("HRESULT WINAPI WICMapGuidToShortName(REFGUID,UINT,WCHAR *,UINT *);")
 cpp_quote("HRESULT WINAPI WICMapShortNameToGuid(PCWSTR,GUID *);")
-- 
2.11.0




More information about the wine-devel mailing list