From 625d54d8f44d16b243f26886d0b9c95cf24c9971 Mon Sep 17 00:00:00 2001 From: Denton Woods Date: Sat, 21 Jan 2017 16:54:19 -0600 Subject: - Added support for reading .pam files - Starting support for DXT10 .dds files --- DevIL/src-IL/include/il_dds.h | 162 ++++++++++++++++- DevIL/src-IL/include/il_pnm.h | 11 ++ DevIL/src-IL/src/il_dds.cpp | 411 +++++++++++++++++++++++++++++++++--------- DevIL/src-IL/src/il_dicom.cpp | 2 +- DevIL/src-IL/src/il_io.cpp | 6 +- DevIL/src-IL/src/il_pnm.cpp | 200 ++++++++++++++++++-- 6 files changed, 682 insertions(+), 110 deletions(-) diff --git a/DevIL/src-IL/include/il_dds.h b/DevIL/src-IL/include/il_dds.h index 42018ab1..d7db8e53 100644 --- a/DevIL/src-IL/include/il_dds.h +++ b/DevIL/src-IL/include/il_dds.h @@ -52,6 +52,21 @@ typedef struct DDSHEAD #endif +#ifdef _WIN32 +#pragma pack(push, dxt10_struct, 1) +#endif +typedef struct DXT10HEAD +{ + ILuint dxgiFormat; + ILuint resourceDimension; + ILuint miscFlag; + ILuint arraySize; + ILuint miscFlags2; +} IL_PACKSTRUCT DXT10HEAD; +#ifdef _WIN32 +#pragma pack(pop, dxt10_struct) +#endif + // use cast to struct instead of RGBA_MAKE as struct is // much @@ -162,9 +177,145 @@ enum PixFormat PF_R32F, PF_G32R32F, PF_A32B32G32R32F, + PF_DX10, PF_UNKNOWN = 0xFF }; +// From https://msdn.microsoft.com/en-us/library/windows/desktop/bb173059(v=vs.85).aspx +typedef enum DXGI_FORMAT +{ + DXGI_FORMAT_UNKNOWN = 0, + DXGI_FORMAT_R32G32B32A32_TYPELESS = 1, + DXGI_FORMAT_R32G32B32A32_FLOAT = 2, + DXGI_FORMAT_R32G32B32A32_UINT = 3, + DXGI_FORMAT_R32G32B32A32_SINT = 4, + DXGI_FORMAT_R32G32B32_TYPELESS = 5, + DXGI_FORMAT_R32G32B32_FLOAT = 6, + DXGI_FORMAT_R32G32B32_UINT = 7, + DXGI_FORMAT_R32G32B32_SINT = 8, + DXGI_FORMAT_R16G16B16A16_TYPELESS = 9, + DXGI_FORMAT_R16G16B16A16_FLOAT = 10, + DXGI_FORMAT_R16G16B16A16_UNORM = 11, + DXGI_FORMAT_R16G16B16A16_UINT = 12, + DXGI_FORMAT_R16G16B16A16_SNORM = 13, + DXGI_FORMAT_R16G16B16A16_SINT = 14, + DXGI_FORMAT_R32G32_TYPELESS = 15, + DXGI_FORMAT_R32G32_FLOAT = 16, + DXGI_FORMAT_R32G32_UINT = 17, + DXGI_FORMAT_R32G32_SINT = 18, + DXGI_FORMAT_R32G8X24_TYPELESS = 19, + DXGI_FORMAT_D32_FLOAT_S8X24_UINT = 20, + DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS = 21, + DXGI_FORMAT_X32_TYPELESS_G8X24_UINT = 22, + DXGI_FORMAT_R10G10B10A2_TYPELESS = 23, + DXGI_FORMAT_R10G10B10A2_UNORM = 24, + DXGI_FORMAT_R10G10B10A2_UINT = 25, + DXGI_FORMAT_R11G11B10_FLOAT = 26, + DXGI_FORMAT_R8G8B8A8_TYPELESS = 27, + DXGI_FORMAT_R8G8B8A8_UNORM = 28, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB = 29, + DXGI_FORMAT_R8G8B8A8_UINT = 30, + DXGI_FORMAT_R8G8B8A8_SNORM = 31, + DXGI_FORMAT_R8G8B8A8_SINT = 32, + DXGI_FORMAT_R16G16_TYPELESS = 33, + DXGI_FORMAT_R16G16_FLOAT = 34, + DXGI_FORMAT_R16G16_UNORM = 35, + DXGI_FORMAT_R16G16_UINT = 36, + DXGI_FORMAT_R16G16_SNORM = 37, + DXGI_FORMAT_R16G16_SINT = 38, + DXGI_FORMAT_R32_TYPELESS = 39, + DXGI_FORMAT_D32_FLOAT = 40, + DXGI_FORMAT_R32_FLOAT = 41, + DXGI_FORMAT_R32_UINT = 42, + DXGI_FORMAT_R32_SINT = 43, + DXGI_FORMAT_R24G8_TYPELESS = 44, + DXGI_FORMAT_D24_UNORM_S8_UINT = 45, + DXGI_FORMAT_R24_UNORM_X8_TYPELESS = 46, + DXGI_FORMAT_X24_TYPELESS_G8_UINT = 47, + DXGI_FORMAT_R8G8_TYPELESS = 48, + DXGI_FORMAT_R8G8_UNORM = 49, + DXGI_FORMAT_R8G8_UINT = 50, + DXGI_FORMAT_R8G8_SNORM = 51, + DXGI_FORMAT_R8G8_SINT = 52, + DXGI_FORMAT_R16_TYPELESS = 53, + DXGI_FORMAT_R16_FLOAT = 54, + DXGI_FORMAT_D16_UNORM = 55, + DXGI_FORMAT_R16_UNORM = 56, + DXGI_FORMAT_R16_UINT = 57, + DXGI_FORMAT_R16_SNORM = 58, + DXGI_FORMAT_R16_SINT = 59, + DXGI_FORMAT_R8_TYPELESS = 60, + DXGI_FORMAT_R8_UNORM = 61, + DXGI_FORMAT_R8_UINT = 62, + DXGI_FORMAT_R8_SNORM = 63, + DXGI_FORMAT_R8_SINT = 64, + DXGI_FORMAT_A8_UNORM = 65, + DXGI_FORMAT_R1_UNORM = 66, + DXGI_FORMAT_R9G9B9E5_SHAREDEXP = 67, + DXGI_FORMAT_R8G8_B8G8_UNORM = 68, + DXGI_FORMAT_G8R8_G8B8_UNORM = 69, + DXGI_FORMAT_BC1_TYPELESS = 70, + DXGI_FORMAT_BC1_UNORM = 71, + DXGI_FORMAT_BC1_UNORM_SRGB = 72, + DXGI_FORMAT_BC2_TYPELESS = 73, + DXGI_FORMAT_BC2_UNORM = 74, + DXGI_FORMAT_BC2_UNORM_SRGB = 75, + DXGI_FORMAT_BC3_TYPELESS = 76, + DXGI_FORMAT_BC3_UNORM = 77, + DXGI_FORMAT_BC3_UNORM_SRGB = 78, + DXGI_FORMAT_BC4_TYPELESS = 79, + DXGI_FORMAT_BC4_UNORM = 80, + DXGI_FORMAT_BC4_SNORM = 81, + DXGI_FORMAT_BC5_TYPELESS = 82, + DXGI_FORMAT_BC5_UNORM = 83, + DXGI_FORMAT_BC5_SNORM = 84, + DXGI_FORMAT_B5G6R5_UNORM = 85, + DXGI_FORMAT_B5G5R5A1_UNORM = 86, + DXGI_FORMAT_B8G8R8A8_UNORM = 87, + DXGI_FORMAT_B8G8R8X8_UNORM = 88, + DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM = 89, + DXGI_FORMAT_B8G8R8A8_TYPELESS = 90, + DXGI_FORMAT_B8G8R8A8_UNORM_SRGB = 91, + DXGI_FORMAT_B8G8R8X8_TYPELESS = 92, + DXGI_FORMAT_B8G8R8X8_UNORM_SRGB = 93, + DXGI_FORMAT_BC6H_TYPELESS = 94, + DXGI_FORMAT_BC6H_UF16 = 95, + DXGI_FORMAT_BC6H_SF16 = 96, + DXGI_FORMAT_BC7_TYPELESS = 97, + DXGI_FORMAT_BC7_UNORM = 98, + DXGI_FORMAT_BC7_UNORM_SRGB = 99, + DXGI_FORMAT_AYUV = 100, + DXGI_FORMAT_Y410 = 101, + DXGI_FORMAT_Y416 = 102, + DXGI_FORMAT_NV12 = 103, + DXGI_FORMAT_P010 = 104, + DXGI_FORMAT_P016 = 105, + DXGI_FORMAT_420_OPAQUE = 106, + DXGI_FORMAT_YUY2 = 107, + DXGI_FORMAT_Y210 = 108, + DXGI_FORMAT_Y216 = 109, + DXGI_FORMAT_NV11 = 110, + DXGI_FORMAT_AI44 = 111, + DXGI_FORMAT_IA44 = 112, + DXGI_FORMAT_P8 = 113, + DXGI_FORMAT_A8P8 = 114, + DXGI_FORMAT_B4G4R4A4_UNORM = 115, + DXGI_FORMAT_P208 = 130, + DXGI_FORMAT_V208 = 131, + DXGI_FORMAT_V408 = 132, + DXGI_FORMAT_FORCE_UINT = 0xffffffff +} DXGI_FORMAT; + +// From https://msdn.microsoft.com/en-us/library/windows/desktop/bb172411(v=vs.85).aspx +typedef enum D3D10_RESOURCE_DIMENSION +{ + D3D10_RESOURCE_DIMENSION_UNKNOWN = 0, + D3D10_RESOURCE_DIMENSION_BUFFER = 1, + D3D10_RESOURCE_DIMENSION_TEXTURE1D = 2, + D3D10_RESOURCE_DIMENSION_TEXTURE2D = 3, + D3D10_RESOURCE_DIMENSION_TEXTURE3D = 4 +} D3D10_RESOURCE_DIMENSION; + #define CUBEMAP_SIDES 6 #ifdef __cplusplus @@ -175,16 +326,17 @@ extern "C" { ILboolean iLoadDdsInternal(void); ILboolean iIsValidDds(void); ILboolean iCheckDds(DDSHEAD *Head); -void AdjustVolumeTexture(DDSHEAD *Head, ILuint CompFormat); -ILboolean ReadData(); -ILboolean AllocImage(ILuint CompFormat); -ILboolean DdsDecompress(ILuint CompFormat); -ILboolean ReadMipmaps(ILuint CompFormat); +void AdjustVolumeTexture(DDSHEAD *Head, ILuint CompFormat, ILboolean IsDXT10); +ILboolean ReadData(ILuint CompFormat, ILboolean IsDXT10); +ILboolean AllocImage(ILuint CompFormat, ILboolean IsDXT10); +ILboolean DdsDecompress(ILuint CompFormat, ILboolean IsDXT10); +ILboolean ReadMipmaps(ILuint CompFormat, ILboolean IsDXT10); ILuint DecodePixelFormat(ILuint *CompFormat); void DxtcReadColor(ILushort Data, Color8888* Out); void DxtcReadColors(const ILubyte* Data, Color8888* Out); ILboolean DecompressARGB(ILuint CompFormat); ILboolean DecompressARGB16(ILuint CompFormat); +ILboolean DecompressARGBDX10(ILuint CompFormat); ILboolean DecompressDXT1(ILimage *lImage, ILubyte *lCompData); ILboolean DecompressDXT2(ILimage *lImage, ILubyte *lCompData); ILboolean DecompressDXT3(ILimage *lImage, ILubyte *lCompData); diff --git a/DevIL/src-IL/include/il_pnm.h b/DevIL/src-IL/include/il_pnm.h index cce04a87..4ac1d0f2 100644 --- a/DevIL/src-IL/include/il_pnm.h +++ b/DevIL/src-IL/include/il_pnm.h @@ -15,6 +15,10 @@ #define PPMPGM_H #include "il_internal.h" +#include + +using namespace std; + #define IL_PBM_ASCII 0x0001 #define IL_PGM_ASCII 0x0002 @@ -22,14 +26,19 @@ #define IL_PBM_BINARY 0x0004 #define IL_PGM_BINARY 0x0005 #define IL_PPM_BINARY 0x0006 +#define IL_PAM 0x0007 + +enum PamTuples { PAM_BW = 1, PAM_GRAY, PAM_RGB, PAM_BW_ALPHA, PAM_GRAY_ALPHA, PAM_RGB_ALPHA }; typedef struct PPMINFO { ILenum Type; ILuint Width; ILuint Height; + ILuint Depth; ILuint MaxColour; ILubyte Bpp; + ILubyte TuplType; } PPMINFO; ILboolean iIsValidPnm(void); @@ -39,8 +48,10 @@ ILboolean iSavePnmInternal(void); ILimage *ilReadAsciiPpm(PPMINFO *Info); ILimage *ilReadBinaryPpm(PPMINFO *Info); ILimage *ilReadBitPbm(PPMINFO *Info); +ILboolean ilReadPam(void); ILboolean iGetWord(ILboolean); void PbmMaximize(ILimage *Image); +ILint DecodeTupleType(string &TupleStr); #endif//PPMPGM_H diff --git a/DevIL/src-IL/src/il_dds.cpp b/DevIL/src-IL/src/il_dds.cpp index 580faed1..daaec723 100644 --- a/DevIL/src-IL/src/il_dds.cpp +++ b/DevIL/src-IL/src/il_dds.cpp @@ -4,7 +4,7 @@ // Copyright (C) 2000-2017 by Denton Woods // Last modified: 02/28/2009 // -// Filename: src-IL/src/il_dds.c +// Filename: src-IL/src/il_dds.cpp // // Description: Reads from a DirectDraw Surface (.dds) file. // @@ -30,7 +30,9 @@ // Global variables +//@TODO: Move these out of global space static DDSHEAD Head; // Image header +static DXT10HEAD HeadDXT10; // DirectX 10 extension header static ILubyte *CompData = NULL; // Compressed data static ILuint CompSize; // Compressed size //static ILuint CompFormat; // Compressed format @@ -134,6 +136,19 @@ ILboolean iGetDdsHead(DDSHEAD *Header) } +// Internal function used to get the DirectX 10 DDS header extension (24 bytes) +ILboolean iGetDXT10Head(DXT10HEAD *Header) +{ + Header->dxgiFormat = GetLittleUInt(); + Header->resourceDimension = GetLittleUInt(); + Header->miscFlag = GetLittleUInt(); + Header->arraySize = GetLittleUInt(); + Header->miscFlags2 = GetLittleUInt(); + + return IL_TRUE; +} + + // Internal function to get the header and check it. ILboolean iIsValidDds() { @@ -167,6 +182,19 @@ ILboolean iCheckDds(DDSHEAD *Head) } +// Internal function used to check if the HEADER is a valid DirectX 10 extension header. +ILboolean iCheckDxt10(DXT10HEAD *Head) +{ + if (Head->resourceDimension < 2 && Head->resourceDimension > 4) + return IL_FALSE; + if (Head->dxgiFormat > DXGI_FORMAT_V408) + return IL_FALSE; + if (Head->arraySize > 1) //@TODO: Support texture arrays + return IL_FALSE; + return IL_TRUE; +} + + //! Reads a .dds file ILboolean ilLoadDds(ILconst_string FileName) { @@ -281,18 +309,21 @@ ILubyte iCompFormatToChannelCount(ILenum Format) } -ILboolean iLoadDdsCubemapInternal(ILuint CompFormat) +ILboolean iLoadDdsCubemapInternal(ILuint CompFormat, ILboolean IsDXT10) { ILuint i; ILubyte Bpp, Channels, Bpc; ILimage *startImage; + if (IsDXT10) //@TODO: Get this working with the DirectX 10 textures + return IL_FALSE; + CompData = NULL; Bpp = iCompFormatToBpp(CompFormat); Channels = iCompFormatToChannelCount(CompFormat); Bpc = iCompFormatToBpc(CompFormat); - if (CompFormat == PF_LUMINANCE && Head.RGBBitCount == 16 && Head.RBitMask == 0xFFFF) { //@TODO: This is a HACK. + if (CompFormat == PF_LUMINANCE && Head.RGBBitCount == 16 && Head.RBitMask == 0xFFFF) { //@TODO: This is a HACK. Bpc = 2; Bpp = 2; } @@ -328,10 +359,10 @@ ILboolean iLoadDdsCubemapInternal(ILuint CompFormat) ilActiveFace(i); } - if (!ReadData()) + if (!ReadData(CompFormat, IsDXT10)) return IL_FALSE; - if (!AllocImage(CompFormat)) { + if (!AllocImage(CompFormat, IsDXT10)) { if (CompData) { ifree(CompData); CompData = NULL; @@ -341,7 +372,7 @@ ILboolean iLoadDdsCubemapInternal(ILuint CompFormat) Image->CubeFlags = CubemapDirections[i]; - if (!DdsDecompress(CompFormat)) { + if (!DdsDecompress(CompFormat, IsDXT10)) { if (CompData) { ifree(CompData); CompData = NULL; @@ -349,7 +380,7 @@ ILboolean iLoadDdsCubemapInternal(ILuint CompFormat) return IL_FALSE; } - if (!ReadMipmaps(CompFormat)) { + if (!ReadMipmaps(CompFormat, IsDXT10)) { if (CompData) { ifree(CompData); CompData = NULL; @@ -371,8 +402,9 @@ ILboolean iLoadDdsCubemapInternal(ILuint CompFormat) ILboolean iLoadDdsInternal() { - ILuint BlockSize = 0; - ILuint CompFormat; + ILuint BlockSize = 0; + ILuint CompFormat; + ILboolean IsDXT10 = IL_FALSE; CompData = NULL; Image = NULL; @@ -396,6 +428,25 @@ ILboolean iLoadDdsInternal() ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } + + if (CompFormat == PF_DX10) { + IsDXT10 = IL_TRUE; + if (!iGetDXT10Head(&HeadDXT10)) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + if (!iCheckDxt10(&HeadDXT10)) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + + CompFormat = HeadDXT10.dxgiFormat; + } + else + { + } + + // Needed for DXT10? Check16BitComponents(&Head); // Microsoft bug, they're not following their own documentation. @@ -408,7 +459,7 @@ ILboolean iLoadDdsInternal() Image = iCurImage; if (Head.ddsCaps1 & DDS_COMPLEX) { if (Head.ddsCaps2 & DDS_CUBEMAP) { - if (!iLoadDdsCubemapInternal(CompFormat)) + if (!iLoadDdsCubemapInternal(CompFormat, IsDXT10)) return IL_FALSE; return IL_TRUE; } @@ -417,18 +468,18 @@ ILboolean iLoadDdsInternal() Width = Head.Width; Height = Head.Height; Depth = Head.Depth; - AdjustVolumeTexture(&Head, CompFormat); + AdjustVolumeTexture(&Head, CompFormat, IsDXT10); - if (!ReadData()) + if (!ReadData(CompFormat, IsDXT10)) return IL_FALSE; - if (!AllocImage(CompFormat)) { + if (!AllocImage(CompFormat, IsDXT10)) { if (CompData) { ifree(CompData); CompData = NULL; } return IL_FALSE; } - if (!DdsDecompress(CompFormat)) { + if (!DdsDecompress(CompFormat, IsDXT10)) { if (CompData) { ifree(CompData); CompData = NULL; @@ -436,7 +487,7 @@ ILboolean iLoadDdsInternal() return IL_FALSE; } - if (!ReadMipmaps(CompFormat)) { + if (!ReadMipmaps(CompFormat, IsDXT10)) { if (CompData) { ifree(CompData); CompData = NULL; @@ -487,6 +538,10 @@ ILuint DecodePixelFormat(ILuint *CompFormat) BlockSize *= 16; break; + case IL_MAKEFOURCC('D', 'X', '1', '0'): + *CompFormat = PF_DX10; + break; + case IL_MAKEFOURCC('A', 'T', 'I', '1'): *CompFormat = PF_ATI1N; BlockSize *= 8; @@ -565,12 +620,147 @@ ILuint DecodePixelFormat(ILuint *CompFormat) } +// From https://msdn.microsoft.com/en-us/windows/uwp/gaming/complete-code-for-ddstextureloader +// +//-------------------------------------------------------------------------------------- +// Return the BPP for a particular format. +//-------------------------------------------------------------------------------------- +static size_t BitsPerPixel(_In_ DXGI_FORMAT fmt) +{ + switch (fmt) + { + case DXGI_FORMAT_R32G32B32A32_TYPELESS: + case DXGI_FORMAT_R32G32B32A32_FLOAT: + case DXGI_FORMAT_R32G32B32A32_UINT: + case DXGI_FORMAT_R32G32B32A32_SINT: + return 128; + + case DXGI_FORMAT_R32G32B32_TYPELESS: + case DXGI_FORMAT_R32G32B32_FLOAT: + case DXGI_FORMAT_R32G32B32_UINT: + case DXGI_FORMAT_R32G32B32_SINT: + return 96; + + case DXGI_FORMAT_R16G16B16A16_TYPELESS: + case DXGI_FORMAT_R16G16B16A16_FLOAT: + case DXGI_FORMAT_R16G16B16A16_UNORM: + case DXGI_FORMAT_R16G16B16A16_UINT: + case DXGI_FORMAT_R16G16B16A16_SNORM: + case DXGI_FORMAT_R16G16B16A16_SINT: + case DXGI_FORMAT_R32G32_TYPELESS: + case DXGI_FORMAT_R32G32_FLOAT: + case DXGI_FORMAT_R32G32_UINT: + case DXGI_FORMAT_R32G32_SINT: + case DXGI_FORMAT_R32G8X24_TYPELESS: + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: + case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: + return 64; + + case DXGI_FORMAT_R10G10B10A2_TYPELESS: + case DXGI_FORMAT_R10G10B10A2_UNORM: + case DXGI_FORMAT_R10G10B10A2_UINT: + case DXGI_FORMAT_R11G11B10_FLOAT: + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + case DXGI_FORMAT_R8G8B8A8_UINT: + case DXGI_FORMAT_R8G8B8A8_SNORM: + case DXGI_FORMAT_R8G8B8A8_SINT: + case DXGI_FORMAT_R16G16_TYPELESS: + case DXGI_FORMAT_R16G16_FLOAT: + case DXGI_FORMAT_R16G16_UNORM: + case DXGI_FORMAT_R16G16_UINT: + case DXGI_FORMAT_R16G16_SNORM: + case DXGI_FORMAT_R16G16_SINT: + case DXGI_FORMAT_R32_TYPELESS: + case DXGI_FORMAT_D32_FLOAT: + case DXGI_FORMAT_R32_FLOAT: + case DXGI_FORMAT_R32_UINT: + case DXGI_FORMAT_R32_SINT: + case DXGI_FORMAT_R24G8_TYPELESS: + case DXGI_FORMAT_D24_UNORM_S8_UINT: + case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: + case DXGI_FORMAT_X24_TYPELESS_G8_UINT: + case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: + case DXGI_FORMAT_R8G8_B8G8_UNORM: + case DXGI_FORMAT_G8R8_G8B8_UNORM: + case DXGI_FORMAT_B8G8R8A8_UNORM: + case DXGI_FORMAT_B8G8R8X8_UNORM: + case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: + case DXGI_FORMAT_B8G8R8A8_TYPELESS: + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + case DXGI_FORMAT_B8G8R8X8_TYPELESS: + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + return 32; + + case DXGI_FORMAT_R8G8_TYPELESS: + case DXGI_FORMAT_R8G8_UNORM: + case DXGI_FORMAT_R8G8_UINT: + case DXGI_FORMAT_R8G8_SNORM: + case DXGI_FORMAT_R8G8_SINT: + case DXGI_FORMAT_R16_TYPELESS: + case DXGI_FORMAT_R16_FLOAT: + case DXGI_FORMAT_D16_UNORM: + case DXGI_FORMAT_R16_UNORM: + case DXGI_FORMAT_R16_UINT: + case DXGI_FORMAT_R16_SNORM: + case DXGI_FORMAT_R16_SINT: + case DXGI_FORMAT_B5G6R5_UNORM: + case DXGI_FORMAT_B5G5R5A1_UNORM: + case DXGI_FORMAT_B4G4R4A4_UNORM: + return 16; + + case DXGI_FORMAT_R8_TYPELESS: + case DXGI_FORMAT_R8_UNORM: + case DXGI_FORMAT_R8_UINT: + case DXGI_FORMAT_R8_SNORM: + case DXGI_FORMAT_R8_SINT: + case DXGI_FORMAT_A8_UNORM: + return 8; + + case DXGI_FORMAT_R1_UNORM: + return 1; + + case DXGI_FORMAT_BC1_TYPELESS: + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC1_UNORM_SRGB: + case DXGI_FORMAT_BC4_TYPELESS: + case DXGI_FORMAT_BC4_UNORM: + case DXGI_FORMAT_BC4_SNORM: + return 4; + + case DXGI_FORMAT_BC2_TYPELESS: + case DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT_BC2_UNORM_SRGB: + case DXGI_FORMAT_BC3_TYPELESS: + case DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT_BC3_UNORM_SRGB: + case DXGI_FORMAT_BC5_TYPELESS: + case DXGI_FORMAT_BC5_UNORM: + case DXGI_FORMAT_BC5_SNORM: + case DXGI_FORMAT_BC6H_TYPELESS: + case DXGI_FORMAT_BC6H_UF16: + case DXGI_FORMAT_BC6H_SF16: + case DXGI_FORMAT_BC7_TYPELESS: + case DXGI_FORMAT_BC7_UNORM: + case DXGI_FORMAT_BC7_UNORM_SRGB: + return 8; + + default: + return 0; + } +} + + // The few volume textures that I have don't have consistent LinearSize // entries, even though the DDS_LINEARSIZE flag is set. -void AdjustVolumeTexture(DDSHEAD *Head, ILuint CompFormat) +void AdjustVolumeTexture(DDSHEAD *Head, ILuint CompFormat, ILboolean IsDXT10) { if (Head->Depth <= 1) return; + if (IsDXT10) + return; // All volume textures I've seem so far didn't have the DDS_COMPLEX flag set, // even though this is normally required. But because noone does set it, @@ -627,7 +817,7 @@ void AdjustVolumeTexture(DDSHEAD *Head, ILuint CompFormat) // Reads the compressed data -ILboolean ReadData() +ILboolean ReadData(ILuint CompFormat, ILboolean IsDXT10) { ILuint Bps; ILint y, z; @@ -653,8 +843,15 @@ ILboolean ReadData() } } else { - Bps = Width * Head.RGBBitCount / 8; + if (IsDXT10) + Bps = Head.LinearSize; //@TODO: Head.RGBBitCount is always 0 from the texconv.exe tool? + else + Bps = Width * Head.RGBBitCount / 8; CompSize = Bps * Height * Depth; + if (CompSize == 0) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } CompData = (ILubyte*)ialloc(CompSize); if (CompData == NULL) { @@ -678,85 +875,110 @@ ILboolean ReadData() } -ILboolean AllocImage(ILuint CompFormat) +ILboolean AllocImage(ILuint CompFormat, ILboolean IsDXT10) { ILubyte channels = 4; ILenum format = IL_RGBA; - switch (CompFormat) + if (!IsDXT10) { - case PF_RGB: - if (!ilTexImage(Width, Height, Depth, 3, IL_RGB, IL_UNSIGNED_BYTE, NULL)) - return IL_FALSE; - break; - case PF_ARGB: - if (!ilTexImage(Width, Height, Depth, 4, IL_RGBA, Has16BitComponents ? IL_UNSIGNED_SHORT : IL_UNSIGNED_BYTE, NULL)) - return IL_FALSE; - break; + switch (CompFormat) + { + case PF_RGB: + if (!ilTexImage(Width, Height, Depth, 3, IL_RGB, IL_UNSIGNED_BYTE, NULL)) + return IL_FALSE; + break; + case PF_ARGB: + if (!ilTexImage(Width, Height, Depth, 4, IL_RGBA, Has16BitComponents ? IL_UNSIGNED_SHORT : IL_UNSIGNED_BYTE, NULL)) + return IL_FALSE; + break; - case PF_LUMINANCE: - if (Head.RGBBitCount == 16 && Head.RBitMask == 0xFFFF) { //HACK - if (!ilTexImage(Width, Height, Depth, 1, IL_LUMINANCE, IL_UNSIGNED_SHORT, NULL)) + case PF_LUMINANCE: + if (Head.RGBBitCount == 16 && Head.RBitMask == 0xFFFF) { //HACK + if (!ilTexImage(Width, Height, Depth, 1, IL_LUMINANCE, IL_UNSIGNED_SHORT, NULL)) + return IL_FALSE; + } + else + if (!ilTexImage(Width, Height, Depth, 1, IL_LUMINANCE, IL_UNSIGNED_BYTE, NULL)) + return IL_FALSE; + break; + + case PF_LUMINANCE_ALPHA: + if (!ilTexImage(Width, Height, Depth, 2, IL_LUMINANCE_ALPHA, IL_UNSIGNED_BYTE, NULL)) return IL_FALSE; - } - else + break; + + case PF_ATI1N: + //right now there's no OpenGL api to use the compressed 3dc data, so + //throw it away (I don't know how DirectX works, though)? if (!ilTexImage(Width, Height, Depth, 1, IL_LUMINANCE, IL_UNSIGNED_BYTE, NULL)) return IL_FALSE; - break; - - case PF_LUMINANCE_ALPHA: - if (!ilTexImage(Width, Height, Depth, 2, IL_LUMINANCE_ALPHA, IL_UNSIGNED_BYTE, NULL)) - return IL_FALSE; - break; + break; - case PF_ATI1N: - //right now there's no OpenGL api to use the compressed 3dc data, so - //throw it away (I don't know how DirectX works, though)? - if (!ilTexImage(Width, Height, Depth, 1, IL_LUMINANCE, IL_UNSIGNED_BYTE, NULL)) - return IL_FALSE; - break; + case PF_3DC: + //right now there's no OpenGL api to use the compressed 3dc data, so + //throw it away (I don't know how DirectX works, though)? + if (!ilTexImage(Width, Height, Depth, 3, IL_RGB, IL_UNSIGNED_BYTE, NULL)) + return IL_FALSE; + break; - case PF_3DC: - //right now there's no OpenGL api to use the compressed 3dc data, so - //throw it away (I don't know how DirectX works, though)? - if (!ilTexImage(Width, Height, Depth, 3, IL_RGB, IL_UNSIGNED_BYTE, NULL)) - return IL_FALSE; - break; + case PF_A16B16G16R16: + if (!ilTexImage(Width, Height, Depth, iCompFormatToChannelCount(CompFormat), + ilGetFormatBpp(iCompFormatToChannelCount(CompFormat)), IL_UNSIGNED_SHORT, NULL)) + return IL_FALSE; + break; - case PF_A16B16G16R16: - if (!ilTexImage(Width, Height, Depth, iCompFormatToChannelCount(CompFormat), - ilGetFormatBpp(iCompFormatToChannelCount(CompFormat)), IL_UNSIGNED_SHORT, NULL)) - return IL_FALSE; - break; + case PF_R16F: + case PF_G16R16F: + case PF_A16B16G16R16F: + case PF_R32F: + case PF_G32R32F: + case PF_A32B32G32R32F: + if (!ilTexImage(Width, Height, Depth, iCompFormatToChannelCount(CompFormat), + ilGetFormatBpp(iCompFormatToChannelCount(CompFormat)), IL_FLOAT, NULL)) + return IL_FALSE; + break; - case PF_R16F: - case PF_G16R16F: - case PF_A16B16G16R16F: - case PF_R32F: - case PF_G32R32F: - case PF_A32B32G32R32F: - if (!ilTexImage(Width, Height, Depth, iCompFormatToChannelCount(CompFormat), - ilGetFormatBpp(iCompFormatToChannelCount(CompFormat)), IL_FLOAT, NULL)) - return IL_FALSE; - break; + default: + if (CompFormat == PF_RXGB) { + channels = 3; //normal map + format = IL_RGB; + } - default: - if (CompFormat == PF_RXGB) { - channels = 3; //normal map - format = IL_RGB; - } + if (!ilTexImage(Width, Height, Depth, channels, format, IL_UNSIGNED_BYTE, NULL)) + return IL_FALSE; + if (ilGetInteger(IL_KEEP_DXTC_DATA) == IL_TRUE && CompData) { + iCurImage->DxtcData = (ILubyte*)ialloc(Head.LinearSize); + if (iCurImage->DxtcData == NULL) + return IL_FALSE; + iCurImage->DxtcFormat = CompFormat - PF_DXT1 + IL_DXT1; + iCurImage->DxtcSize = Head.LinearSize; + memcpy(iCurImage->DxtcData, CompData, iCurImage->DxtcSize); + } + break; + } + } + else + { + switch (CompFormat) + { + case DXGI_FORMAT_R8G8B8A8_UNORM: + if (!ilTexImage(Width, Height, Depth, 4, IL_RGBA, Has16BitComponents ? IL_UNSIGNED_SHORT : IL_UNSIGNED_BYTE, NULL)) + return IL_FALSE; + break; + case DXGI_FORMAT_B8G8R8A8_UNORM: + if (!ilTexImage(Width, Height, Depth, 4, IL_BGRA, Has16BitComponents ? IL_UNSIGNED_SHORT : IL_UNSIGNED_BYTE, NULL)) + return IL_FALSE; + break; + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + if (!ilTexImage(Width, Height, Depth, 4, IL_BGRA, Has16BitComponents ? IL_UNSIGNED_SHORT : IL_UNSIGNED_BYTE, NULL)) + return IL_FALSE; + break; - if (!ilTexImage(Width, Height, Depth, channels, format, IL_UNSIGNED_BYTE, NULL)) + default: + ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; - if (ilGetInteger(IL_KEEP_DXTC_DATA) == IL_TRUE && CompData) { - iCurImage->DxtcData = (ILubyte*)ialloc(Head.LinearSize); - if (iCurImage->DxtcData == NULL) - return IL_FALSE; - iCurImage->DxtcFormat = CompFormat - PF_DXT1 + IL_DXT1; - iCurImage->DxtcSize = Head.LinearSize; - memcpy(iCurImage->DxtcData, CompData, iCurImage->DxtcSize); - } - break; + } } Image->Origin = IL_ORIGIN_UPPER_LEFT; @@ -779,8 +1001,13 @@ ILboolean AllocImage(ILuint CompFormat) * * @TODO: don't use globals, clean this function (and this file) up */ -ILboolean DdsDecompress(ILuint CompFormat) +ILboolean DdsDecompress(ILuint CompFormat, ILboolean IsDXT10) { + if (IsDXT10) + { //@TODO: Put in compressed formats + return DecompressARGBDX10(CompFormat); + } + switch (CompFormat) { case PF_ARGB: @@ -833,7 +1060,7 @@ ILboolean DdsDecompress(ILuint CompFormat) } -ILboolean ReadMipmaps(ILuint CompFormat) +ILboolean ReadMipmaps(ILuint CompFormat, ILboolean IsDXT10) { ILuint i, CompFactor=0; ILubyte Bpp, Channels, Bpc; @@ -843,6 +1070,9 @@ ILboolean ReadMipmaps(ILuint CompFormat) ILboolean isCompressed = IL_FALSE; + if (IsDXT10) //@TODO: Add in mipmap support + return IL_TRUE; + Bpp = iCompFormatToBpp(CompFormat); Channels = iCompFormatToChannelCount(CompFormat); Bpc = iCompFormatToBpc(CompFormat); @@ -945,7 +1175,7 @@ ILboolean ReadMipmaps(ILuint CompFormat) Head.LinearSize >>= 1; } - if (!ReadData()) + if (!ReadData(CompFormat, IsDXT10)) goto mip_fail; if (ilGetInteger(IL_KEEP_DXTC_DATA) == IL_TRUE && isCompressed == IL_TRUE && CompData) { @@ -957,7 +1187,7 @@ ILboolean ReadMipmaps(ILuint CompFormat) memcpy(Image->DxtcData, CompData, Image->DxtcSize); } - if (!DdsDecompress(CompFormat)) + if (!DdsDecompress(CompFormat, IsDXT10)) goto mip_fail; } @@ -1681,6 +1911,14 @@ void CorrectPreMult() } +ILboolean DecompressARGBDX10(ILuint CompFormat) +{ + //@TODO: Will certainly fail if iCurImage->SizeOfData != "Compressed" Size + memcpy(iCurImage->Data, CompData, iCurImage->SizeOfData); + return IL_TRUE; +} + + ILboolean DecompressARGB(ILuint CompFormat) { ILuint ReadI = 0, TempBpp, i; @@ -1989,7 +2227,8 @@ ILAPI ILboolean ILAPIENTRY ilDxtcDataToSurface() case IL_DXT5: CompFormat = PF_DXT5; break; } CompData = iCurImage->DxtcData; - DdsDecompress(CompFormat); //globals suck...fix this + DdsDecompress(CompFormat, IL_FALSE); //@TODO: globals suck...fix this + //@TODO: Should we ever expect this to be IL_TRUE? //@TODO: origin should be set in Decompress()... iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; diff --git a/DevIL/src-IL/src/il_dicom.cpp b/DevIL/src-IL/src/il_dicom.cpp index 4d2f55dd..c8074a60 100644 --- a/DevIL/src-IL/src/il_dicom.cpp +++ b/DevIL/src-IL/src/il_dicom.cpp @@ -427,7 +427,7 @@ ILboolean GetUID(ILubyte *UID) return IL_FALSE; ValLen = GetLittleUShort(); - if (ValLen > 64) + if (ValLen > 64) // Addresses this vulnerability: https://vuldb.com/?id.51054 return IL_FALSE; if (iread(UID, ValLen, 1) != 1) return IL_FALSE; diff --git a/DevIL/src-IL/src/il_io.cpp b/DevIL/src-IL/src/il_io.cpp index e5af3cac..cc40de5a 100644 --- a/DevIL/src-IL/src/il_io.cpp +++ b/DevIL/src-IL/src/il_io.cpp @@ -125,7 +125,7 @@ ILenum ILAPIENTRY ilTypeFromExt(ILconst_string FileName) else if (!iStrCmp(Ext, IL_TEXT("pix"))) Type = IL_PIX; else if (!iStrCmp(Ext, IL_TEXT("pbm")) || !iStrCmp(Ext, IL_TEXT("pgm")) || - !iStrCmp(Ext, IL_TEXT("pnm")) || !iStrCmp(Ext, IL_TEXT("ppm"))) + !iStrCmp(Ext, IL_TEXT("pnm")) || !iStrCmp(Ext, IL_TEXT("ppm")) || !iStrCmp(Ext, IL_TEXT("pam"))) Type = IL_PNM; else if (!iStrCmp(Ext, IL_TEXT("psd")) || !iStrCmp(Ext, IL_TEXT("pdd"))) Type = IL_PSD; @@ -2058,6 +2058,10 @@ ILboolean ILAPIENTRY ilLoadImage(ILconst_string FileName) bRet = ilLoadPnm(FileName); goto finish; } + if (!iStrCmp(Ext, IL_TEXT("pam"))) { + bRet = ilLoadPnm(FileName); + goto finish; + } #endif #ifndef IL_NO_PSD diff --git a/DevIL/src-IL/src/il_pnm.cpp b/DevIL/src-IL/src/il_pnm.cpp index fdbf679a..794f6e55 100644 --- a/DevIL/src-IL/src/il_pnm.cpp +++ b/DevIL/src-IL/src/il_pnm.cpp @@ -17,11 +17,17 @@ #include "il_pnm.h" #include // for maximum values #include +#include #include "il_bits.h" +using namespace std; + + // According to the ppm specs, it's 70, but PSP // likes to output longer lines. #define MAX_BUFFER 180 + +//@TODO: Get rid of these globals static ILbyte LineBuffer[MAX_BUFFER]; static ILbyte SmallBuff[MAX_BUFFER]; @@ -38,7 +44,8 @@ ILboolean ilIsValidPnm(ILconst_string FileName) if ( !iCheckExtension(FileName, IL_TEXT("pbm")) && !iCheckExtension(FileName, IL_TEXT("pgm")) && !iCheckExtension(FileName, IL_TEXT("ppm")) - && !iCheckExtension(FileName, IL_TEXT("pnm"))) { + && !iCheckExtension(FileName, IL_TEXT("pnm")) + && !iCheckExtension(FileName, IL_TEXT("pam"))) { ilSetError(IL_INVALID_EXTENSION); return bPnm; } @@ -107,6 +114,7 @@ ILboolean iCheckPnm(char Header[2]) case '4': case '5': case '6': + case '7': return IL_TRUE; } @@ -179,7 +187,8 @@ ILboolean iLoadPnmInternal() return IL_FALSE; } - switch( SmallBuff[1] ) { + switch (SmallBuff[1]) + { case '1': Info.Type = IL_PBM_ASCII; break; @@ -202,6 +211,9 @@ ILboolean iLoadPnmInternal() case '6': Info.Type = IL_PPM_BINARY; break; + case '7': + //Info.Type = IL_PAM; + return ilReadPam(); default: ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; @@ -225,29 +237,40 @@ ILboolean iLoadPnmInternal() } // Retrieve the maximum colour component value - if (Info.Type != IL_PBM_ASCII && Info.Type != IL_PBM_BINARY) { + if (Info.Type != IL_PBM_ASCII && Info.Type != IL_PBM_BINARY) + { if (iGetWord(IL_TRUE) == IL_FALSE) return IL_FALSE; - if ((Info.MaxColour = atoi((const char*)SmallBuff)) == 0) { + if ((Info.MaxColour = atoi((const char*)SmallBuff)) == 0) + { ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } - } else { + } + else + { Info.MaxColour = 1; } if (Info.Type == IL_PBM_ASCII || Info.Type == IL_PBM_BINARY || - Info.Type == IL_PGM_ASCII || Info.Type == IL_PGM_BINARY) { - if (Info.Type == IL_PGM_ASCII) { + Info.Type == IL_PGM_ASCII || Info.Type == IL_PGM_BINARY) + { + if (Info.Type == IL_PGM_ASCII) + { Info.Bpp = Info.MaxColour < 256 ? 1 : 2; - } else { + } + else + { Info.Bpp = 1; } - } else { + } + else + { Info.Bpp = 3; } - switch (Info.Type) { + switch (Info.Type) + { case IL_PBM_ASCII: case IL_PGM_ASCII: case IL_PPM_ASCII: @@ -260,18 +283,22 @@ ILboolean iLoadPnmInternal() case IL_PPM_BINARY: PmImage = ilReadBinaryPpm(&Info); break; + /*case IL_PAM: + PmImage = ilReadPam(&Info);*/ default: return IL_FALSE; } - if (PmImage == NULL) { + if (PmImage == NULL) + { iCurImage->Format = ilGetFormatBpp(iCurImage->Bpp); ilSetError(IL_FILE_READ_ERROR); return IL_FALSE; } // Is this conversion needed? Just 0's and 1's shows up as all black - if (Info.Type == IL_PBM_ASCII) { + if (Info.Type == IL_PBM_ASCII) + { PbmMaximize(PmImage); } @@ -363,7 +390,7 @@ ILimage *ilReadAsciiPpm(PPMINFO *Info) ILimage *ilReadBinaryPpm(PPMINFO *Info) { - ILuint Size; + ILuint Size; Size = Info->Width * Info->Height * Info->Bpp; @@ -382,7 +409,7 @@ ILimage *ilReadBinaryPpm(PPMINFO *Info) ILuint size = itell(); iseek(size-Size,IL_SEEK_SET); */ - if (iread(iCurImage->Data, 1, Size ) != Size) { + if (iread(iCurImage->Data, 1, Size) != Size) { ilCloseImage(iCurImage); return NULL; } @@ -413,6 +440,143 @@ ILimage *ilReadBitPbm(PPMINFO *Info) } +ILboolean ilReadPam() +{ + PPMINFO Info; + string TempStr; + ILuint Size; + + memset(&Info, 0, sizeof(PPMINFO)); + + while (!ieof()) + { + if (iGetWord(IL_FALSE) == IL_FALSE) + return IL_FALSE; + if (!strncmp((const char*)SmallBuff, "ENDHDR", 6)) + break; + + TempStr = (char*)SmallBuff; // Save the first identifier of the line + if (iGetWord(IL_FALSE) == IL_FALSE) + return IL_FALSE; + if (!strncmp(TempStr.c_str(), "WIDTH", 5)) + Info.Width = atoi((const char*)SmallBuff); + else if (!strncmp(TempStr.c_str(), "HEIGHT", 6)) + Info.Height = atoi((const char*)SmallBuff); + else if (!strncmp(TempStr.c_str(), "DEPTH", 5)) + Info.Depth = atoi((const char*)SmallBuff); + else if (!strncmp(TempStr.c_str(), "MAXVAL", 6)) + Info.MaxColour = atoi((const char*)SmallBuff); + else if (!strncmp(TempStr.c_str(), "TUPLTYPE", 8)) + Info.TuplType = DecodeTupleType(string((char*)SmallBuff)); + } + + //@TODO: Handle other max colors and tuple types + if (Info.Width == 0 || Info.Height == 0 || Info.Depth == 0 || Info.Depth > 4 || Info.TuplType == 0) + { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + switch (Info.MaxColour) + { + case 255: + Info.Type = IL_UNSIGNED_BYTE; + Size = 1; + break; + case 65535: + Info.Type = IL_UNSIGNED_SHORT; + Size = 2; + break; + default: + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + + switch (Info.TuplType) + { + case PAM_GRAY: + if (Info.Depth != 1) + { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + if (!ilTexImage(Info.Width, Info.Height, 1, Info.Depth, 0, Info.Type, NULL)) + return IL_FALSE; + Size *= Info.Width * Info.Height * Info.Depth; + iCurImage->Format = IL_LUMINANCE; + break; + + case PAM_GRAY_ALPHA: + if (Info.Depth != 2) + { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + if (!ilTexImage(Info.Width, Info.Height, 1, Info.Depth, 0, Info.Type, NULL)) + return IL_FALSE; + Size *= Info.Width * Info.Height * Info.Depth; + iCurImage->Format = IL_LUMINANCE_ALPHA; + break; + + case PAM_RGB: + if (Info.Depth != 3) + { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + if (!ilTexImage(Info.Width, Info.Height, 1, Info.Depth, 0, Info.Type, NULL)) + return IL_FALSE; + Size *= Info.Width * Info.Height * Info.Depth; + iCurImage->Format = IL_RGB; + break; + + case PAM_RGB_ALPHA: + if (Info.Depth != 4) + { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + if (!ilTexImage(Info.Width, Info.Height, 1, Info.Depth, 0, Info.Type, NULL)) + return IL_FALSE; + Size *= Info.Width * Info.Height * Info.Depth; + iCurImage->Format = IL_RGBA; + break; + + default: + //@TODO: Handle black and white case + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; + + if (iread(iCurImage->Data, 1, Size) != Size) + { + ilCloseImage(iCurImage); + return NULL; + } + + return IL_TRUE; +} + + +ILint DecodeTupleType(string &TupleStr) +{ + if (TupleStr == "BLACKANDWHITE") + return PAM_BW; + else if (TupleStr == "GRAYSCALE") + return PAM_GRAY; + else if (TupleStr == "RGB") + return PAM_RGB; + else if (TupleStr == "BLACKANDWHITE_ALPHA") + return PAM_BW_ALPHA; + else if (TupleStr == "GRAYSCALE_ALPHA") + return PAM_GRAY_ALPHA; + else if (TupleStr == "RGB_ALPHA") + return PAM_RGB_ALPHA; + + return 0; +} + + ILboolean iGetWord(ILboolean final) { ILint WordPos = 0; @@ -423,12 +587,14 @@ ILboolean iGetWord(ILboolean final) if (ieof()) return IL_FALSE; - while (Looping) { - while ((Current = igetc()) != IL_EOF && Current != '\n' && Current != '#' && Current != ' ') { + while (Looping) + { + while ((Current = igetc()) != IL_EOF && Current != '\n' && Current != '#' && Current != ' ') + { if (WordPos >= MAX_BUFFER) // We have hit the maximum line length. return IL_FALSE; - if (!isalnum(Current)) { + if (!isalnum(Current) && Current != '_') { if (Started) { Looping = IL_FALSE; break; -- cgit v1.2.1