D3DX supports a wide range of file types for textures. Instead of rewriting everything from scratch, the best would certainly be to use some image processing library to handle them. As a bonus, this would allow lighter code.

Some of those library are :
SDL_Image : easy to use, but loading an image using a SDL_Surface is quite heavy. Moreover, the files supported are not enough for d3dx. MagickWand/MagickCore, the libraries on which imagemagick is based : Hard to use, and very heavy. Supports every format thet d3dx supports. FreeImage : Quite easy to use, the only files not supported are DIB and PFM... Not so widely represented. I had to recompile it, as packages for it are not available for 32 bits. (I use a 64 bits ubuntu system).

Here is an implementation of D3DXGetImageInfoFromFileInMemory using FreeImage.

Suggestions and comments are welcomed.

PS : Please CC me your potential answers, as I'm not a subscriber of this list.

>From 634259f60ae538f1f8eaeb2d34abaa2a9aa47d15 Mon Sep 17 00:00:00 2001
From: =?utf-8?q?J=C3=A9r=C3=B4me=20Gardou?= <[EMAIL PROTECTED](none)>
Date: Tue, 26 Aug 2008 15:37:17 +0200
Subject: Implements D3DXGetImageInfoFromFileInMemory using the FreeImage library.

---
 dlls/d3dx9_36/Makefile.in        |    5 +-
 dlls/d3dx9_36/d3dx9_36.spec      |    2 +-
 dlls/d3dx9_36/d3dx9_36_private.h |    5 +
 dlls/d3dx9_36/texture.c          |   79 ++++++++++++++++
 dlls/d3dx9_36/utils.c            |  190 ++++++++++++++++++++++++++++++++++++++
 include/d3dx9tex.h               |    2 +
 6 files changed, 281 insertions(+), 2 deletions(-)
 create mode 100644 dlls/d3dx9_36/texture.c
 create mode 100644 dlls/d3dx9_36/utils.c

diff --git a/dlls/d3dx9_36/Makefile.in b/dlls/d3dx9_36/Makefile.in
index 0b5a3d3..6455f15 100644
--- a/dlls/d3dx9_36/Makefile.in
+++ b/dlls/d3dx9_36/Makefile.in
@@ -5,13 +5,16 @@ VPATH     = @srcdir@
 MODULE    = d3dx9_36.dll
 IMPORTLIB = d3dx9
 IMPORTS   = d3d9 d3dx8 kernel32
+EXTRALIBS = -lfreeimage
 
 C_SRCS = \
 	d3dx9_36_main.c \
 	font.c \
 	math.c \
 	shader.c \
-	sprite.c
+	sprite.c \
+	texture.c \
+	utils.c
 
 RC_SRCS = version.rc
 
diff --git a/dlls/d3dx9_36/d3dx9_36.spec b/dlls/d3dx9_36/d3dx9_36.spec
index a2dab96..acfd183 100644
--- a/dlls/d3dx9_36/d3dx9_36.spec
+++ b/dlls/d3dx9_36/d3dx9_36.spec
@@ -152,7 +152,7 @@
 @ stdcall D3DXGetDriverLevel(ptr)
 @ stdcall D3DXGetFVFVertexSize(long) d3dx8.D3DXGetFVFVertexSize
 @ stdcall D3DXGetImageInfoFromFileA(ptr ptr) d3dx8.D3DXGetImageInfoFromFileA
-@ stdcall D3DXGetImageInfoFromFileInMemory(ptr long ptr) d3dx8.D3DXGetImageInfoFromFileInMemory
+@ stdcall D3DXGetImageInfoFromFileInMemory(ptr long ptr)
 @ stdcall D3DXGetImageInfoFromFileW(ptr ptr) d3dx8.D3DXGetImageInfoFromFileW
 @ stdcall D3DXGetImageInfoFromResourceA(long ptr ptr) d3dx8.D3DXGetImageInfoFromResourceA
 @ stdcall D3DXGetImageInfoFromResourceW(long ptr ptr) d3dx8.D3DXGetImageInfoFromResourceW
diff --git a/dlls/d3dx9_36/d3dx9_36_private.h b/dlls/d3dx9_36/d3dx9_36_private.h
index e1c266d..7b7084c 100644
--- a/dlls/d3dx9_36/d3dx9_36_private.h
+++ b/dlls/d3dx9_36/d3dx9_36_private.h
@@ -45,5 +45,10 @@ typedef struct ID3DXSpriteImpl
     /* ID3DXSprite fields */
 } ID3DXSpriteImpl;
 
+/*Utilities*/
+D3DFORMAT GetD3DFMTFromMasks(UINT Rmask, UINT Gmask, UINT Bmask, UINT Bpp, BOOL isRGBA) ;
+const char* debug_d3dformat(D3DFORMAT) ;
+const char* debug_d3dxfileformat(D3DXIMAGE_FILEFORMAT fmt) ;
+
 
 #endif /* __WINE_D3DX9_36_PRIVATE_H */
diff --git a/dlls/d3dx9_36/texture.c b/dlls/d3dx9_36/texture.c
new file mode 100644
index 0000000..2bbfc8e
--- /dev/null
+++ b/dlls/d3dx9_36/texture.c
@@ -0,0 +1,79 @@
+
+
+#include "config.h"
+#include "wine/port.h"
+#include "wine/debug.h"
+#include "d3dx9_36_private.h"
+#define _WINDOWS_
+#include <FreeImage.h>
+#undef _WINDOWS_
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
+
+HRESULT WINAPI D3DXGetImageInfoFromFileInMemory(LPCVOID pSrcData, UINT SrcDataSize, D3DXIMAGE_INFO * pSrcInfo)
+{
+    /**the graphic files supported by d3dx are BMP, JPG, PNG, TGA, PPM, DDS, PFM, DIB, HDR
+    The freeimage library supports BMP, JPG, TGA, PNG, DDS, PPM, HDR
+    DIB will be handle with GDI
+    PFM is a very simple format. See http://netpbm.sourceforge.net/doc/pfm.html for more information**/
+    
+    /*First, let's see if freeimage handle this file*/
+    FIMEMORY* fim = FreeImage_OpenMemory((BYTE*) pSrcData, SrcDataSize) ;
+    FREE_IMAGE_FORMAT fif = FreeImage_GetFileTypeFromMemory(fim, 0) ;
+    TRACE("File is %p, size is %d, filling info %p\n", pSrcData, SrcDataSize, pSrcInfo) ;
+    if (fif != FIF_UNKNOWN) {
+        FIBITMAP* fib = FreeImage_LoadFromMemory(fif, fim, 0) ;
+        UINT bpp = FreeImage_GetBPP(fib) ;
+        UINT red_mask = FreeImage_GetRedMask(fib) ;
+        UINT blue_mask = FreeImage_GetRedMask(fib) ;
+        UINT green_mask = FreeImage_GetRedMask(fib) ;
+        FREE_IMAGE_COLOR_TYPE fict = FreeImage_GetColorType(fib) ;
+        pSrcInfo->Width = FreeImage_GetWidth(fib) ;
+        pSrcInfo->Height = FreeImage_GetHeight(fib) ;
+        /*No idea about them... return something logical...*/
+        pSrcInfo->Depth = 1 ;
+        pSrcInfo->MipLevels = 1 ;
+        pSrcInfo->ResourceType = D3DRTYPE_TEXTURE ;
+        switch (fif) {
+            case FIF_BMP :
+            pSrcInfo->ImageFileFormat = D3DXIFF_BMP ;
+            break ;
+            case FIF_JPEG :
+            pSrcInfo->ImageFileFormat = D3DXIFF_JPG ;
+            break ;
+            case FIF_TARGA :
+            pSrcInfo->ImageFileFormat = D3DXIFF_TGA ;
+            break ;
+            case FIF_PNG :
+            pSrcInfo->ImageFileFormat = D3DXIFF_PNG ;
+            break ;
+            case FIF_DDS :
+            pSrcInfo->ImageFileFormat = D3DXIFF_DDS ;
+            break ;
+            case FIF_PPM :
+            pSrcInfo->ImageFileFormat = D3DXIFF_PPM ;
+            break ;
+            case FIF_HDR :
+            pSrcInfo->ImageFileFormat = D3DXIFF_HDR ;
+            break ;
+            default :
+            break ;
+        }
+        pSrcInfo->Format = D3DFMT_UNKNOWN ;
+        if (fict == FIC_RGB) 
+            pSrcInfo->Format = GetD3DFMTFromMasks(red_mask, green_mask, blue_mask, bpp/8, FALSE) ;
+        else if (fict == FIC_RGBALPHA)
+            pSrcInfo->Format = GetD3DFMTFromMasks(red_mask, green_mask, blue_mask, bpp/8, TRUE) ;
+        else if ((fict == FIC_PALETTE) && (bpp == 8))
+            pSrcInfo->Format = D3DFMT_P8 ;
+        TRACE("Format is %s, fileformat is %s, width is %d, height is %d\n", debug_d3dformat(pSrcInfo->Format), 
+            debug_d3dxfileformat(pSrcInfo->ImageFileFormat), pSrcInfo->Width, pSrcInfo->Height) ;
+        FreeImage_Unload(fib) ;
+        FreeImage_CloseMemory(fim) ;
+        return D3D_OK ;
+        
+    } /*freeimage doesn't handle it*/
+    FreeImage_CloseMemory(fim) ;
+    FIXME("Format unsupported : stub !") ;
+    return D3D_OK ;
+}
diff --git a/dlls/d3dx9_36/utils.c b/dlls/d3dx9_36/utils.c
new file mode 100644
index 0000000..10ec592
--- /dev/null
+++ b/dlls/d3dx9_36/utils.c
@@ -0,0 +1,190 @@
+#include "wine/debug.h"
+#include "d3dx9_36_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
+
+typedef struct {
+D3DFORMAT format ; UINT alphamask  ,redmask    ,greenmask  ,bluemask   ,bpp ;
+} StaticPixelFormatDesc ;
+
+/*Stolen from dlls/wined3d/utils.c*/
+static const StaticPixelFormatDesc formats[] = { 
+    {D3DFMT_UNKNOWN     ,0x0        ,0x0        ,0x0        ,0x0        ,1      },
+    /* Float */
+    {D3DFMT_R16F        ,0x0        ,0x0        ,0x0        ,0x0        ,2      },
+    {D3DFMT_G16R16F     ,0x0        ,0x0        ,0x0        ,0x0        ,4      },
+    {D3DFMT_A16B16G16R16F,0x1       ,0x0        ,0x0        ,0x0        ,8      },
+    /* Palettized formats */
+    {D3DFMT_A8P8        ,0x0000ff00 ,0x0        ,0x0        ,0x0        ,2      },
+    {D3DFMT_P8          ,0x0        ,0x0        ,0x0        ,0x0        ,1      },
+    /* Standard ARGB formats. Keep D3DFMT_R8G8B8(=20) at position 20 */
+    {D3DFMT_R8G8B8      ,0x0        ,0x00ff0000 ,0x0000ff00 ,0x000000ff ,3      },
+    {D3DFMT_A8R8G8B8    ,0xff000000 ,0x00ff0000 ,0x0000ff00 ,0x000000ff ,4      },
+    {D3DFMT_X8R8G8B8    ,0x0        ,0x00ff0000 ,0x0000ff00 ,0x000000ff ,4      },
+    {D3DFMT_R5G6B5      ,0x0        ,0x0000F800 ,0x000007e0 ,0x0000001f ,2      },
+    {D3DFMT_X1R5G5B5    ,0x0        ,0x00007c00 ,0x000003e0 ,0x0000001f ,2      },
+    {D3DFMT_A1R5G5B5    ,0x00008000 ,0x00007c00 ,0x000003e0 ,0x0000001f ,2      },
+    {D3DFMT_A4R4G4B4    ,0x0000f000 ,0x00000f00 ,0x000000f0 ,0x0000000f ,2      },
+    {D3DFMT_R3G3B2      ,0x0        ,0x000000e0 ,0x0000001c ,0x00000003 ,1      },
+    {D3DFMT_A8          ,0x000000ff ,0x0        ,0x0        ,0x0        ,1      },
+    {D3DFMT_A8R3G3B2    ,0x0000ff00 ,0x000000e0 ,0x0000001c ,0x00000003 ,2      },
+    {D3DFMT_X4R4G4B4    ,0x0        ,0x00000f00 ,0x000000f0 ,0x0000000f ,2      },
+    {D3DFMT_A2B10G10R10 ,0xb0000000 ,0x000003ff ,0x000ffc00 ,0x3ff00000 ,4      },
+    {D3DFMT_A8B8G8R8    ,0xff000000 ,0x000000ff ,0x0000ff00 ,0x00ff0000 ,4      },
+    {D3DFMT_X8B8G8R8    ,0x0        ,0x000000ff ,0x0000ff00 ,0x00ff0000 ,4      },
+    {D3DFMT_G16R16      ,0x0        ,0x0000ffff ,0xffff0000 ,0x0        ,4      },
+    {D3DFMT_A2R10G10B10 ,0xb0000000 ,0x3ff00000 ,0x000ffc00 ,0x000003ff ,4      },
+    {D3DFMT_A16B16G16R16,0x1        ,0x0000ffff ,0xffff0000 ,0x0        ,8      },
+    /* Luminance */
+    {D3DFMT_L8          ,0x0        ,0x0        ,0x0        ,0x0        ,1      },
+    {D3DFMT_A8L8        ,0x0000ff00 ,0x0        ,0x0        ,0x0        ,2      },
+    {D3DFMT_A4L4        ,0x000000f0 ,0x0        ,0x0        ,0x0        ,1      },
+    /* Bump mapping stuff */
+    {D3DFMT_V8U8        ,0x0        ,0x0        ,0x0        ,0x0        ,2      },
+    {D3DFMT_L6V5U5      ,0x0        ,0x0        ,0x0        ,0x0        ,2      },
+    {D3DFMT_X8L8V8U8    ,0x0        ,0x0        ,0x0        ,0x0        ,4      },
+    {D3DFMT_Q8W8V8U8    ,0x0        ,0x0        ,0x0        ,0x0        ,4      },
+    {D3DFMT_V16U16      ,0x0        ,0x0        ,0x0        ,0x0        ,4      },
+    {D3DFMT_A2W10V10U10 ,0xb0000000 ,0x0        ,0x0        ,0x0        ,4      },
+    /* Depth stencil formats */
+    {D3DFMT_D16_LOCKABLE,0x0        ,0x0        ,0x0        ,0x0        ,2      },
+    {D3DFMT_D32         ,0x0        ,0x0        ,0x0        ,0x0        ,4      },
+    {D3DFMT_D15S1       ,0x0        ,0x0        ,0x0        ,0x0        ,2      },
+    {D3DFMT_D24S8       ,0x0        ,0x0        ,0x0        ,0x0        ,4      },
+    {D3DFMT_D24X8       ,0x0        ,0x0        ,0x0        ,0x0        ,4      },
+    {D3DFMT_D24X4S4     ,0x0        ,0x0        ,0x0        ,0x0        ,4      },
+    {D3DFMT_D16         ,0x0        ,0x0        ,0x0        ,0x0        ,2      },
+    {D3DFMT_L16         ,0x0        ,0x0        ,0x0        ,0x0        ,2      },
+    {D3DFMT_D32F_LOCKABLE,0x0       ,0x0        ,0x0        ,0x0        ,4      },
+    {D3DFMT_D24FS8      ,0x0        ,0x0        ,0x0        ,0x0        ,4      },
+    /* Is this a vertex buffer? */
+    {D3DFMT_VERTEXDATA  ,0x0        ,0x0        ,0x0        ,0x0        ,0      },
+    {D3DFMT_INDEX16     ,0x0        ,0x0        ,0x0        ,0x0        ,2      },
+    {D3DFMT_INDEX32     ,0x0        ,0x0        ,0x0        ,0x0        ,4      },
+    {D3DFMT_Q16W16V16U16,0x0        ,0x0        ,0x0        ,0x0        ,8      },
+};
+
+D3DFORMAT GetD3DFMTFromMasks(UINT Rmask, UINT Gmask, UINT Bmask, UINT Bpp, BOOL isRGBA)
+{
+    UINT i = 0 ;
+    if(isRGBA) {
+        for(i=1; i<60; i++) {
+            if ((formats[i].redmask == Rmask) && (formats[i].greenmask == Gmask) && (formats[i].bluemask == Bmask)
+                && (formats[i].alphamask != 0x0) && (formats[i].bpp == Bpp)) {
+                return formats[i].format ;
+            }
+        }
+    } else {
+        for(i=1; i<60; i++) {
+            if ((formats[i].redmask == Rmask) && (formats[i].greenmask == Gmask) && (formats[i].bluemask == Bmask)
+                && (formats[i].alphamask == 0x0) && (formats[i].bpp == Bpp)) {
+                return formats[i].format ;
+            }
+        }
+    }
+    return D3DFMT_UNKNOWN ;
+}
+
+/*****************************************************************************
+ * Trace formatting of useful values
+ */
+const char* debug_d3dformat(D3DFORMAT fmt) {
+  switch (fmt) {
+#define FMT_TO_STR(fmt) case fmt: return #fmt
+    FMT_TO_STR(D3DFMT_UNKNOWN);
+    FMT_TO_STR(D3DFMT_R8G8B8);
+    FMT_TO_STR(D3DFMT_A8R8G8B8);
+    FMT_TO_STR(D3DFMT_X8R8G8B8);
+    FMT_TO_STR(D3DFMT_R5G6B5);
+    FMT_TO_STR(D3DFMT_X1R5G5B5);
+    FMT_TO_STR(D3DFMT_A1R5G5B5);
+    FMT_TO_STR(D3DFMT_A4R4G4B4);
+    FMT_TO_STR(D3DFMT_R3G3B2);
+    FMT_TO_STR(D3DFMT_A8);
+    FMT_TO_STR(D3DFMT_A8R3G3B2);
+    FMT_TO_STR(D3DFMT_X4R4G4B4);
+    FMT_TO_STR(D3DFMT_A2B10G10R10);
+    FMT_TO_STR(D3DFMT_A8B8G8R8);
+    FMT_TO_STR(D3DFMT_X8B8G8R8);
+    FMT_TO_STR(D3DFMT_G16R16);
+    FMT_TO_STR(D3DFMT_A2R10G10B10);
+    FMT_TO_STR(D3DFMT_A16B16G16R16);
+    FMT_TO_STR(D3DFMT_A8P8);
+    FMT_TO_STR(D3DFMT_P8);
+    FMT_TO_STR(D3DFMT_L8);
+    FMT_TO_STR(D3DFMT_A8L8);
+    FMT_TO_STR(D3DFMT_A4L4);
+    FMT_TO_STR(D3DFMT_V8U8);
+    FMT_TO_STR(D3DFMT_L6V5U5);
+    FMT_TO_STR(D3DFMT_X8L8V8U8);
+    FMT_TO_STR(D3DFMT_Q8W8V8U8);
+    FMT_TO_STR(D3DFMT_V16U16);
+    FMT_TO_STR(D3DFMT_A2W10V10U10);
+    FMT_TO_STR(D3DFMT_UYVY);
+    FMT_TO_STR(D3DFMT_YUY2);
+    FMT_TO_STR(D3DFMT_DXT1);
+    FMT_TO_STR(D3DFMT_DXT2);
+    FMT_TO_STR(D3DFMT_DXT3);
+    FMT_TO_STR(D3DFMT_DXT4);
+    FMT_TO_STR(D3DFMT_DXT5);
+    FMT_TO_STR(D3DFMT_MULTI2_ARGB8);
+    FMT_TO_STR(D3DFMT_G8R8_G8B8);
+    FMT_TO_STR(D3DFMT_R8G8_B8G8);
+    FMT_TO_STR(D3DFMT_D16_LOCKABLE);
+    FMT_TO_STR(D3DFMT_D32);
+    FMT_TO_STR(D3DFMT_D15S1);
+    FMT_TO_STR(D3DFMT_D24S8);
+    FMT_TO_STR(D3DFMT_D24X8);
+    FMT_TO_STR(D3DFMT_D24X4S4);
+    FMT_TO_STR(D3DFMT_D16);
+    FMT_TO_STR(D3DFMT_L16);
+    FMT_TO_STR(D3DFMT_D32F_LOCKABLE);
+    FMT_TO_STR(D3DFMT_D24FS8);
+    FMT_TO_STR(D3DFMT_VERTEXDATA);
+    FMT_TO_STR(D3DFMT_INDEX16);
+    FMT_TO_STR(D3DFMT_INDEX32);
+    FMT_TO_STR(D3DFMT_Q16W16V16U16);
+    FMT_TO_STR(D3DFMT_R16F);
+    FMT_TO_STR(D3DFMT_G16R16F);
+    FMT_TO_STR(D3DFMT_A16B16G16R16F);
+    FMT_TO_STR(D3DFMT_R32F);
+    FMT_TO_STR(D3DFMT_G32R32F);
+    FMT_TO_STR(D3DFMT_A32B32G32R32F);
+    FMT_TO_STR(D3DFMT_CxV8U8);
+#undef FMT_TO_STR
+  default:
+    {
+      char fourcc[5];
+      fourcc[0] = (char)(fmt);
+      fourcc[1] = (char)(fmt >> 8);
+      fourcc[2] = (char)(fmt >> 16);
+      fourcc[3] = (char)(fmt >> 24);
+      fourcc[4] = 0;
+      if( isprint(fourcc[0]) && isprint(fourcc[1]) && isprint(fourcc[2]) && isprint(fourcc[3]) )
+        FIXME("Unrecognized %u (as fourcc: %s) D3DFORMAT!\n", fmt, fourcc);
+      else
+        FIXME("Unrecognized %u D3DFORMAT!\n", fmt);
+    }
+    return "unrecognized";
+  }
+}
+
+const char* debug_d3dxfileformat(D3DXIMAGE_FILEFORMAT fmt)
+{
+#define FMT_TO_STR(fmt) case fmt: return #fmt
+    switch(fmt) {
+    FMT_TO_STR(D3DXIFF_BMP) ;
+    FMT_TO_STR(D3DXIFF_JPG) ;
+    FMT_TO_STR(D3DXIFF_TGA) ;
+    FMT_TO_STR(D3DXIFF_PNG) ;
+    FMT_TO_STR(D3DXIFF_DDS) ;
+    FMT_TO_STR(D3DXIFF_PPM) ;
+    FMT_TO_STR(D3DXIFF_HDR) ;
+    FMT_TO_STR(D3DXIFF_PFM) ;
+#undef FMT_TO_STR
+    default :
+        FIXME ("Unrecognized D3DXIMAGE_FILEFORMAT %u !\n", fmt) ;
+        return "unrecognized" ;
+    }
+}
+    
\ No newline at end of file
diff --git a/include/d3dx9tex.h b/include/d3dx9tex.h
index 8e553e0..8073ab8 100644
--- a/include/d3dx9tex.h
+++ b/include/d3dx9tex.h
@@ -63,6 +63,8 @@ typedef enum _D3DXIMAGE_FILEFORMAT
     D3DXIFF_DDS,
     D3DXIFF_PPM,
     D3DXIFF_DIB,
+    D3DXIFF_HDR,
+    D3DXIFF_PFM,
     D3DXIFF_FORCE_DWORD = 0x7fffffff
 } D3DXIMAGE_FILEFORMAT;
 
-- 
1.5.4.3



Reply via email to