[PATCH 1/3] d3dx9_36: Add support for DIB file in D3DXGetImageInfoFromFileInMemory. (try 2)

Christian Costa titan.costa at gmail.com
Mon Apr 22 16:08:00 CDT 2013


Try 2:
  - handle BITMAPV4HEADER, BITMAPV5HEADER and BITMAPCOREHEADER2
  - handle BITMAPINFOHEADER with BI_BITFIELDS compression
---
 dlls/d3dx9_36/surface.c       |  107 +++++++++++++++++++++++++++++++++++++++--
 dlls/d3dx9_36/tests/surface.c |    6 +-
 2 files changed, 104 insertions(+), 9 deletions(-)

diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c
index ea77497..f7576dc 100644
--- a/dlls/d3dx9_36/surface.c
+++ b/dlls/d3dx9_36/surface.c
@@ -28,6 +28,28 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
 
+typedef struct {
+    DWORD bc2Size;
+    DWORD bc2Width;
+    DWORD bc2Height;
+    WORD  bc2Planes;
+    WORD  bc2BitCount;
+    DWORD bc2Compression;
+    DWORD bc2SizeImage;
+    DWORD bc2XRes;
+    DWORD bc2YRes;
+    DWORD bc2ClrUsed;
+    DWORD bc2ClrImportant;
+    /* same as BITMAPINFOHEADER until this point */
+    WORD  bc2ResUnit;
+    WORD  bc2Reserved;
+    WORD  bc2Orientation;
+    WORD  bc2Halftoning;
+    DWORD bc2HalftoneSize1;
+    DWORD bc2HalftoneSize2;
+    DWORD bc2ColorSpace;
+    DWORD bc2AppData;
+} BITMAPCOREHEADER2;
 
 /* Wine-specific WIC GUIDs */
 DEFINE_GUID(GUID_WineContainerFormatTga, 0x0c44fda1,0xa5c5,0x4298,0x96,0x85,0x47,0x3f,0xc1,0x7c,0xd3,0x22);
@@ -675,6 +697,71 @@ HRESULT load_volume_texture_from_dds(IDirect3DVolumeTexture9 *volume_texture, co
     return D3D_OK;
 }
 
+static BOOL convert_dib_to_bmp(void **data, UINT *size)
+{
+    ULONG header_size;
+    ULONG offset;
+    BITMAPFILEHEADER *header;
+    BYTE *new_data;
+    UINT new_size;
+
+    if ((*size < 4) || (*size < (header_size = *(ULONG*)*data)))
+        return FALSE;
+
+    if ((header_size == sizeof(BITMAPINFOHEADER)) ||
+        (header_size == sizeof(BITMAPV4HEADER)) ||
+        (header_size == sizeof(BITMAPV5HEADER)) ||
+        (header_size == sizeof(BITMAPCOREHEADER2)))
+    {
+        /* All structures have the same memory layout as BITMAPINFOHEADER */
+        BITMAPINFOHEADER *header = (BITMAPINFOHEADER*)*data;
+        ULONG count = header->biClrUsed;
+
+        if (!count && header->biBitCount <= 8)
+            count = 1 << header->biBitCount;
+
+        offset = sizeof(BITMAPFILEHEADER) + header_size + sizeof(RGBQUAD) * count;
+
+        /* For BITMAPINFOHEADER with BI_BITFIELDS compression, there are 3 additional color masks after header */
+        if ((header->biSize == sizeof(BITMAPINFOHEADER)) && (header->biCompression == BI_BITFIELDS))
+            offset += 3 * sizeof(DWORD);
+    }
+    else if (header_size == sizeof(BITMAPCOREHEADER))
+    {
+        BITMAPCOREHEADER *header = (BITMAPCOREHEADER*)*data;
+        ULONG count = 0;
+
+        if (header->bcBitCount <= 8)
+            count = 1 << header->bcBitCount;
+
+        offset = sizeof(BITMAPFILEHEADER) + header_size + sizeof(RGBTRIPLE) * count;
+    }
+    else
+    {
+        return FALSE;
+    }
+
+    TRACE("Converting DIB file to BMP\n");
+
+    new_size = *size + sizeof(BITMAPFILEHEADER);
+    new_data = HeapAlloc(GetProcessHeap(), 0, new_size);
+    CopyMemory(new_data + sizeof(BITMAPFILEHEADER), *data, *size);
+
+    /* Add BMP header */
+    header = (BITMAPFILEHEADER*)new_data;
+    header->bfType = 0x4d42; /* BM */
+    header->bfSize = new_size;
+    header->bfReserved1 = 0;
+    header->bfReserved2 = 0;
+    header->bfOffBits = offset;
+
+    /* Update input data */
+    *data = new_data;
+    *size = new_size;
+
+    return TRUE;
+}
+
 /************************************************************
  * D3DXGetImageInfoFromFileInMemory
  *
@@ -696,13 +783,14 @@ HRESULT load_volume_texture_from_dds(IDirect3DVolumeTexture9 *volume_texture, co
  *   datasize may be bigger than the actual file size
  *
  */
-HRESULT WINAPI D3DXGetImageInfoFromFileInMemory(LPCVOID data, UINT datasize, D3DXIMAGE_INFO *info)
+HRESULT WINAPI D3DXGetImageInfoFromFileInMemory(const void *data, UINT datasize, D3DXIMAGE_INFO *info)
 {
     IWICImagingFactory *factory;
     IWICBitmapDecoder *decoder = NULL;
     IWICStream *stream;
     HRESULT hr;
     HRESULT initresult;
+    BOOL dib;
 
     TRACE("(%p, %d, %p)\n", data, datasize, info);
 
@@ -717,6 +805,9 @@ HRESULT WINAPI D3DXGetImageInfoFromFileInMemory(LPCVOID data, UINT datasize, D3D
         return get_image_info_from_dds(data, datasize, info);
     }
 
+    /* In case of DIB file, convert it to BMP */
+    dib = convert_dib_to_bmp((void**)&data, &datasize);
+
     initresult = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
 
     hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, &IID_IWICImagingFactory, (void**)&factory);
@@ -732,8 +823,6 @@ HRESULT WINAPI D3DXGetImageInfoFromFileInMemory(LPCVOID data, UINT datasize, D3D
     if (FAILED(hr)) {
         if ((datasize >= 2) && (!strncmp(data, "P3", 2) || !strncmp(data, "P6", 2)))
             FIXME("File type PPM is not supported yet\n");
-        else if ((datasize >= 4) && (*(DWORD*)data == sizeof(BITMAPINFOHEADER)))
-            FIXME("File type DIB is not supported yet\n");
         else if ((datasize >= 10) && !strncmp(data, "#?RADIANCE", 10))
             FIXME("File type HDR is not supported yet\n");
         else if ((datasize >= 2) && (!strncmp(data, "PF", 2) || !strncmp(data, "Pf", 2)))
@@ -747,8 +836,13 @@ HRESULT WINAPI D3DXGetImageInfoFromFileInMemory(LPCVOID data, UINT datasize, D3D
         hr = IWICBitmapDecoder_GetContainerFormat(decoder, &container_format);
         if (SUCCEEDED(hr)) {
             if (IsEqualGUID(&container_format, &GUID_ContainerFormatBmp)) {
-                TRACE("File type is BMP\n");
-                info->ImageFileFormat = D3DXIFF_BMP;
+                if (dib) {
+                    TRACE("File type is DIB\n");
+                    info->ImageFileFormat = D3DXIFF_DIB;
+                } else {
+                    TRACE("File type is BMP\n");
+                    info->ImageFileFormat = D3DXIFF_BMP;
+                }
             } else if (IsEqualGUID(&container_format, &GUID_ContainerFormatPng)) {
                 TRACE("File type is PNG\n");
                 info->ImageFileFormat = D3DXIFF_PNG;
@@ -805,6 +899,9 @@ HRESULT WINAPI D3DXGetImageInfoFromFileInMemory(LPCVOID data, UINT datasize, D3D
     if (SUCCEEDED(initresult))
         CoUninitialize();
 
+    if (dib)
+        HeapFree(GetProcessHeap(), 0, (void*)data);
+
     if (FAILED(hr)) {
         TRACE("Invalid or unsupported image file\n");
         return D3DXERR_INVALIDDATA;
diff --git a/dlls/d3dx9_36/tests/surface.c b/dlls/d3dx9_36/tests/surface.c
index bb1104b..759f9e1 100644
--- a/dlls/d3dx9_36/tests/surface.c
+++ b/dlls/d3dx9_36/tests/surface.c
@@ -377,10 +377,8 @@ static void test_D3DXGetImageInfo(void)
 
 
     /* D3DXGetImageInfoFromResource */
-    todo_wine {
-        hr = D3DXGetImageInfoFromResourceA(NULL, MAKEINTRESOURCEA(IDB_BITMAP_1x1), &info); /* RT_BITMAP */
-        ok(hr == D3D_OK, "D3DXGetImageInfoFromResource returned %#x, expected %#x\n", hr, D3D_OK);
-    }
+    hr = D3DXGetImageInfoFromResourceA(NULL, MAKEINTRESOURCEA(IDB_BITMAP_1x1), &info); /* RT_BITMAP */
+    ok(hr == D3D_OK, "D3DXGetImageInfoFromResource returned %#x, expected %#x\n", hr, D3D_OK);
 
     hr = D3DXGetImageInfoFromResourceA(NULL, MAKEINTRESOURCEA(IDB_BITMAP_1x1), NULL);
     ok(hr == D3D_OK, "D3DXGetImageInfoFromResource returned %#x, expected %#x\n", hr, D3D_OK);




More information about the wine-patches mailing list