diff --git a/src/nvimage/BlockDXT.h b/src/nvimage/BlockDXT.h index c462761..d0d7060 100644 --- a/src/nvimage/BlockDXT.h +++ b/src/nvimage/BlockDXT.h @@ -234,16 +234,16 @@ namespace nv // Serialization functions. - NVIMAGE_API Stream & operator<<(Stream & stream, BlockDXT1 & block); - NVIMAGE_API Stream & operator<<(Stream & stream, AlphaBlockDXT3 & block); - NVIMAGE_API Stream & operator<<(Stream & stream, BlockDXT3 & block); - NVIMAGE_API Stream & operator<<(Stream & stream, AlphaBlockDXT5 & block); - NVIMAGE_API Stream & operator<<(Stream & stream, BlockDXT5 & block); - NVIMAGE_API Stream & operator<<(Stream & stream, BlockATI1 & block); - NVIMAGE_API Stream & operator<<(Stream & stream, BlockATI2 & block); - NVIMAGE_API Stream & operator<<(Stream & stream, BlockCTX1 & block); - NVIMAGE_API Stream & operator<<(Stream & stream, BlockBC6 & block); - NVIMAGE_API Stream & operator<<(Stream & stream, BlockBC7 & block); + Stream & operator<<(Stream & stream, BlockDXT1 & block); + Stream & operator<<(Stream & stream, AlphaBlockDXT3 & block); + Stream & operator<<(Stream & stream, BlockDXT3 & block); + Stream & operator<<(Stream & stream, AlphaBlockDXT5 & block); + Stream & operator<<(Stream & stream, BlockDXT5 & block); + Stream & operator<<(Stream & stream, BlockATI1 & block); + Stream & operator<<(Stream & stream, BlockATI2 & block); + Stream & operator<<(Stream & stream, BlockCTX1 & block); + Stream & operator<<(Stream & stream, BlockBC6 & block); + Stream & operator<<(Stream & stream, BlockBC7 & block); } // nv namespace diff --git a/src/nvimage/ColorBlock.cpp b/src/nvimage/ColorBlock.cpp index ad8f2b7..e111243 100644 --- a/src/nvimage/ColorBlock.cpp +++ b/src/nvimage/ColorBlock.cpp @@ -61,7 +61,7 @@ ColorBlock::ColorBlock(const Image * img, uint x, uint y) void ColorBlock::init(const Image * img, uint x, uint y) { - init(img->width(), img->height(), (const uint *)img->pixels(), x, y); + init(img->width, img->height, (const uint *)img->pixels(), x, y); } void ColorBlock::init(uint w, uint h, const uint * data, uint x, uint y) diff --git a/src/nvimage/DirectDrawSurface.cpp b/src/nvimage/DirectDrawSurface.cpp index be8146e..2275b19 100644 --- a/src/nvimage/DirectDrawSurface.cpp +++ b/src/nvimage/DirectDrawSurface.cpp @@ -1,25 +1,4 @@ -// Copyright NVIDIA Corporation 2007 -- Ignacio Castano -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. +// MIT license see full LICENSE text at end of file #include "DirectDrawSurface.h" #include "ColorBlock.h" @@ -352,6 +331,76 @@ namespace nvUnreachable(); } + static bool hasAlpha(DXGI_FORMAT format) { + switch(format) { + case DXGI_FORMAT_R32G32B32A32_TYPELESS: + case DXGI_FORMAT_R32G32B32A32_FLOAT: + case DXGI_FORMAT_R32G32B32A32_UINT: + case DXGI_FORMAT_R32G32B32A32_SINT: + 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_R10G10B10A2_TYPELESS: + case DXGI_FORMAT_R10G10B10A2_UNORM: + case DXGI_FORMAT_R10G10B10A2_UINT: + 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_A8_UNORM: + case DXGI_FORMAT_B5G5R5A1_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: + case DXGI_FORMAT_BC1_UNORM: // BC1a + case DXGI_FORMAT_BC1_UNORM_SRGB: + case DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT_BC2_UNORM_SRGB: + case DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT_BC3_UNORM_SRGB: + case DXGI_FORMAT_BC7_UNORM: + case DXGI_FORMAT_BC7_UNORM_SRGB: + return true; + } + return false; + } + + static bool hasAlpha(D3DFORMAT format) { + switch(format) { + case D3DFMT_A8R8G8B8: + case D3DFMT_A1R5G5B5: + case D3DFMT_A4R4G4B4: + case D3DFMT_A8: + case D3DFMT_A8R3G3B2: + case D3DFMT_A2B10G10R10: + case D3DFMT_A8B8G8R8: + case D3DFMT_A2R10G10B10: + case D3DFMT_A16B16G16R16: + case D3DFMT_A8P8: + case D3DFMT_A8L8: + case D3DFMT_A4L4: + case D3DFMT_A16B16G16R16F: + case D3DFMT_A32B32G32R32F: + case FOURCC_DXT1: // DXT1a + case FOURCC_DXT2: + case FOURCC_DXT3: + case FOURCC_DXT4: + case FOURCC_DXT5: + case FOURCC_BC7L: + return true; + } + return false; + } + } // namespace namespace nv @@ -508,6 +557,20 @@ const RGBAPixelFormat *nv::findDXGIPixelFormat(uint dxgiFormat) return NULL; } +const RGBAPixelFormat *nv::findD3D9PixelFormat(uint d3d9Format) +{ + for (int i = 0; i < s_formatCount; i++) + { + if (s_formats[i].d3d9Format == d3d9Format) { + return &s_formats[i].pixelFormat; + } + } + + return NULL; +} + + + DDSHeader::DDSHeader() { this->fourcc = FOURCC_DDS; @@ -912,16 +975,6 @@ DirectDrawSurface::DirectDrawSurface() : stream(NULL) { } -DirectDrawSurface::DirectDrawSurface(const char * name) : stream(NULL) -{ - load(name); -} - -DirectDrawSurface::DirectDrawSurface(Stream * s) : stream(NULL) -{ - load(s); -} - DirectDrawSurface::~DirectDrawSurface() { delete stream; @@ -1020,7 +1073,8 @@ bool DirectDrawSurface::isSupported() const return false; } - if (isTextureCube()) { + if (isTextureCube()) + { if (header.width != header.height) return false; if ((header.caps.caps2 & DDSCAPS2_CUBEMAP_ALL_FACES) != DDSCAPS2_CUBEMAP_ALL_FACES) @@ -1036,40 +1090,56 @@ bool DirectDrawSurface::isSupported() const bool DirectDrawSurface::hasAlpha() const { + // If the file was generated by us, just use the DDPF_ALPHAPIXELS flag. + if (header.reserved[9] == FOURCC_NVTT) { + return (header.pf.flags & DDPF_ALPHAPIXELS); + } + + // Otherwise make assumptions based on the pixel format. if (header.hasDX10Header()) { -#pragma NV_MESSAGE("TODO: Update hasAlpha to handle all DX10 formats.") - return - header.header10.dxgiFormat == DXGI_FORMAT_BC1_UNORM || - header.header10.dxgiFormat == DXGI_FORMAT_BC2_UNORM || - header.header10.dxgiFormat == DXGI_FORMAT_BC3_UNORM; + return ::hasAlpha((DXGI_FORMAT)header.header10.dxgiFormat); } else { + //if (header.pf.flags & DDPF_ALPHAPIXELS) return true; + if (header.pf.flags & DDPF_RGB) { return header.pf.amask != 0; } else if (header.pf.flags & DDPF_FOURCC) { - if (header.pf.fourcc == FOURCC_RXGB || - header.pf.fourcc == FOURCC_ATI1 || - header.pf.fourcc == FOURCC_ATI2 || - header.pf.flags & DDPF_NORMAL) - { - return false; - } - else - { - // @@ Here we could check the ALPHA_PIXELS flag, but nobody sets it. (except us?) - return true; - } + return ::hasAlpha((D3DFORMAT)header.pf.fourcc); } return false; } } +bool DirectDrawSurface::isColorsRGB() const +{ + if (header.hasDX10Header()) { + switch (header.header10.dxgiFormat) { + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + case DXGI_FORMAT_BC1_UNORM_SRGB: + case DXGI_FORMAT_BC2_UNORM_SRGB: + case DXGI_FORMAT_BC3_UNORM_SRGB: + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + case DXGI_FORMAT_BC7_UNORM_SRGB: + return true; + } + } + else { + //if (header.reserved[9] == FOURCC_NVTT) + if (header.pf.flags & DDPF_SRGB) return true; + } + + return false; +} + + uint DirectDrawSurface::mipmapCount() const { nvDebugCheck(isValid()); @@ -1172,114 +1242,84 @@ void DirectDrawSurface::setUserVersion(int version) header.setUserVersion(version); } -void DirectDrawSurface::mipmap(Image * img, uint face, uint mipmap) +static uint mipmapExtent(uint mipmap, uint x) { - nvDebugCheck(isValid()); + for (uint m = 0; m < mipmap; m++) { + x = max(1U, x / 2); + } + return x; +} - stream->seek(offset(face, mipmap)); +uint DirectDrawSurface::surfaceWidth(uint mipmap) const +{ + return mipmapExtent(mipmap, width()); +} - uint w = width(); - uint h = height(); - uint d = depth(); +uint DirectDrawSurface::surfaceHeight(uint mipmap) const +{ + return mipmapExtent(mipmap, height()); +} - // Compute width and height. - for (uint m = 0; m < mipmap; m++) - { - w = max(1U, w / 2); - h = max(1U, h / 2); - d = max(1U, d / 2); - } +uint DirectDrawSurface::surfaceDepth(uint mipmap) const +{ + return mipmapExtent(mipmap, depth()); +} - img->allocate(w, h, d); +uint DirectDrawSurface::surfaceSize(uint mipmap) const +{ + uint w = surfaceWidth(mipmap); + uint h = surfaceHeight(mipmap); + uint d = surfaceDepth(mipmap); - if (hasAlpha()) - { - img->setFormat(Image::Format_ARGB); - } - else - { - img->setFormat(Image::Format_RGB); - } + uint blockSize = header.blockSize(); - if (header.hasDX10Header()) - { - if (const RGBAPixelFormat *format = findDXGIPixelFormat(header.header10.dxgiFormat)) { - readLinearImage(img, format->bitcount, format->rmask, format->gmask, format->bmask, format->amask); - } - else { - readBlockImage(img); - } + if (blockSize == 0) { + uint bitCount = header.pixelSize(); + uint pitch = computeBytePitch(w, bitCount, 1); // Asuming 1 byte alignment, which is the same D3DX expects. + return pitch * h * d; } - else - { - if (header.pf.flags & DDPF_RGB) - { - readLinearImage(img, header.pf.bitcount, header.pf.rmask, header.pf.gmask, header.pf.bmask, header.pf.amask); - } - else if (header.pf.flags & DDPF_FOURCC) - { - readBlockImage(img); - } + else { + w = (w + 3) / 4; + h = (h + 3) / 4; + //d = d; // @@ How are 3D textures aligned? + return blockSize * w * h * d; } } -/*void * DirectDrawSurface::readData(uint * sizePtr) +uint DirectDrawSurface::faceSize() const { - uint header_size = 128; // sizeof(DDSHeader); + const uint count = mipmapCount(); + uint size = 0; - if (header.hasDX10Header()) + for (uint m = 0; m < count; m++) { - header_size += 20; // sizeof(DDSHeader10); + size += surfaceSize(m); } - stream->seek(header_size); - - int size = stream->size() - header_size; - *sizePtr = size; - - void * data = new unsigned char [size]; - - size = stream->serialize(data, size); - nvDebugCheck(size == *sizePtr); - - return data; -}*/ + return size; +} -/*uint DirectDrawSurface::surfaceSize(uint mipmap) const +uint DirectDrawSurface::offset(uint face, uint mipmap) { - uint w = header.width(); - uint h = header.height(); - uint d = header.depth(); - for (int m = 0; m < mipmap; m++) { - w = (w + 1) / 2; - h = (h + 1) / 2; - d = (d + 1) / 2; - } - - bool isBlockFormat; - uint blockOrPixelSize; + uint size = 128; // sizeof(DDSHeader); - if (header.hasDX10Header()) { - blockOrPixelSize = blockSize(header10.dxgiFormat); - isBlockFormat = (blockOrPixelSize != 0); - if (isBlockFormat) { - blockOrPixelSize = pixelSize(header10.dxgiFormat); - } - } - else { - header.pf.flags + if (header.hasDX10Header()) + { + size += 20; // sizeof(DDSHeader10); } - if (isBlockFormat) { - w = (w + 3) / 4; - h = (h + 3) / 4; - d = (d + 3) / 4; // @@ Is it necessary to align the depths? + if (face != 0) + { + size += face * faceSize(); } - uint blockOrPixelCount = w * h * d; + for (uint m = 0; m < mipmap; m++) + { + size += surfaceSize(m); + } - return blockCount = blockOrPixelSize; -}*/ + return size; +} bool DirectDrawSurface::readSurface(uint face, uint mipmap, void * data, uint size) { @@ -1292,134 +1332,190 @@ bool DirectDrawSurface::readSurface(uint face, uint mipmap, void * data, uint si } -void DirectDrawSurface::readLinearImage(Image * img, uint bitcount, uint rmask, uint gmask, uint bmask, uint amask) -{ - nvDebugCheck(stream != NULL); - nvDebugCheck(img != NULL); - - const uint w = img->width(); - const uint h = img->height(); - const uint d = img->depth(); - - uint rshift, rsize; - PixelFormat::maskShiftAndSize(rmask, &rshift, &rsize); - - uint gshift, gsize; - PixelFormat::maskShiftAndSize(gmask, &gshift, &gsize); - uint bshift, bsize; - PixelFormat::maskShiftAndSize(bmask, &bshift, &bsize); +void DirectDrawSurface::printInfo() const +{ + printf("Flags: 0x%.8X\n", header.flags); + if (header.flags & DDSD_CAPS) printf("\tDDSD_CAPS\n"); + if (header.flags & DDSD_PIXELFORMAT) printf("\tDDSD_PIXELFORMAT\n"); + if (header.flags & DDSD_WIDTH) printf("\tDDSD_WIDTH\n"); + if (header.flags & DDSD_HEIGHT) printf("\tDDSD_HEIGHT\n"); + if (header.flags & DDSD_DEPTH) printf("\tDDSD_DEPTH\n"); + if (header.flags & DDSD_PITCH) printf("\tDDSD_PITCH\n"); + if (header.flags & DDSD_LINEARSIZE) printf("\tDDSD_LINEARSIZE\n"); + if (header.flags & DDSD_MIPMAPCOUNT) printf("\tDDSD_MIPMAPCOUNT\n"); - uint ashift, asize; - PixelFormat::maskShiftAndSize(amask, &ashift, &asize); + printf("Height: %d\n", header.height); + printf("Width: %d\n", header.width); + printf("Depth: %d\n", header.depth); + if (header.flags & DDSD_PITCH) printf("Pitch: %d\n", header.pitch); + else if (header.flags & DDSD_LINEARSIZE) printf("Linear size: %d\n", header.pitch); + printf("Mipmap count: %d\n", header.mipmapcount); - uint byteCount = (bitcount + 7) / 8; + printf("Pixel Format:\n"); + printf("\tFlags: 0x%.8X\n", header.pf.flags); + if (header.pf.flags & DDPF_RGB) printf("\t\tDDPF_RGB\n"); + if (header.pf.flags & DDPF_LUMINANCE) printf("\t\tDDPF_LUMINANCE\n"); + if (header.pf.flags & DDPF_FOURCC) printf("\t\tDDPF_FOURCC\n"); + if (header.pf.flags & DDPF_ALPHAPIXELS) printf("\t\tDDPF_ALPHAPIXELS\n"); + if (header.pf.flags & DDPF_ALPHA) printf("\t\tDDPF_ALPHA\n"); + if (header.pf.flags & DDPF_PALETTEINDEXED1) printf("\t\tDDPF_PALETTEINDEXED1\n"); + if (header.pf.flags & DDPF_PALETTEINDEXED2) printf("\t\tDDPF_PALETTEINDEXED2\n"); + if (header.pf.flags & DDPF_PALETTEINDEXED4) printf("\t\tDDPF_PALETTEINDEXED4\n"); + if (header.pf.flags & DDPF_PALETTEINDEXED8) printf("\t\tDDPF_PALETTEINDEXED8\n"); + if (header.pf.flags & DDPF_ALPHAPREMULT) printf("\t\tDDPF_ALPHAPREMULT\n"); + if (header.pf.flags & DDPF_NORMAL) printf("\t\tDDPF_NORMAL\n"); -#pragma NV_MESSAGE("TODO: Support floating point linear images and other FOURCC codes.") + if (header.pf.fourcc != 0) { + // Display fourcc code even when DDPF_FOURCC flag not set. + printf("\tFourCC: '%c%c%c%c' (0x%.8X)\n", + ((header.pf.fourcc >> 0) & 0xFF), + ((header.pf.fourcc >> 8) & 0xFF), + ((header.pf.fourcc >> 16) & 0xFF), + ((header.pf.fourcc >> 24) & 0xFF), + header.pf.fourcc); + } - // Read linear RGB images. - for (uint z = 0; z < d; z++) + if ((header.pf.flags & DDPF_FOURCC) && (header.pf.bitcount != 0)) { - for (uint y = 0; y < h; y++) - { - for (uint x = 0; x < w; x++) - { - uint c = 0; - stream->serialize(&c, byteCount); - - Color32 pixel(0, 0, 0, 0xFF); - pixel.r = PixelFormat::convert((c & rmask) >> rshift, rsize, 8); - pixel.g = PixelFormat::convert((c & gmask) >> gshift, gsize, 8); - pixel.b = PixelFormat::convert((c & bmask) >> bshift, bsize, 8); - pixel.a = PixelFormat::convert((c & amask) >> ashift, asize, 8); + printf("\tSwizzle: '%c%c%c%c' (0x%.8X)\n", + (header.pf.bitcount >> 0) & 0xFF, + (header.pf.bitcount >> 8) & 0xFF, + (header.pf.bitcount >> 16) & 0xFF, + (header.pf.bitcount >> 24) & 0xFF, + header.pf.bitcount); + } + else + { + printf("\tBit count: %d\n", header.pf.bitcount); + } - img->pixel(x, y, z) = pixel; - } + printf("\tRed mask: 0x%.8X\n", header.pf.rmask); + printf("\tGreen mask: 0x%.8X\n", header.pf.gmask); + printf("\tBlue mask: 0x%.8X\n", header.pf.bmask); + printf("\tAlpha mask: 0x%.8X\n", header.pf.amask); + + printf("Caps:\n"); + printf("\tCaps 1: 0x%.8X\n", header.caps.caps1); + if (header.caps.caps1 & DDSCAPS_COMPLEX) printf("\t\tDDSCAPS_COMPLEX\n"); + if (header.caps.caps1 & DDSCAPS_TEXTURE) printf("\t\tDDSCAPS_TEXTURE\n"); + if (header.caps.caps1 & DDSCAPS_MIPMAP) printf("\t\tDDSCAPS_MIPMAP\n"); + + printf("\tCaps 2: 0x%.8X\n", header.caps.caps2); + if (header.caps.caps2 & DDSCAPS2_VOLUME) printf("\t\tDDSCAPS2_VOLUME\n"); + else if (header.caps.caps2 & DDSCAPS2_CUBEMAP) + { + printf("\t\tDDSCAPS2_CUBEMAP\n"); + if ((header.caps.caps2 & DDSCAPS2_CUBEMAP_ALL_FACES) == DDSCAPS2_CUBEMAP_ALL_FACES) printf("\t\tDDSCAPS2_CUBEMAP_ALL_FACES\n"); + else { + if (header.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEX) printf("\t\tDDSCAPS2_CUBEMAP_POSITIVEX\n"); + if (header.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEX) printf("\t\tDDSCAPS2_CUBEMAP_NEGATIVEX\n"); + if (header.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEY) printf("\t\tDDSCAPS2_CUBEMAP_POSITIVEY\n"); + if (header.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEY) printf("\t\tDDSCAPS2_CUBEMAP_NEGATIVEY\n"); + if (header.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEZ) printf("\t\tDDSCAPS2_CUBEMAP_POSITIVEZ\n"); + if (header.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEZ) printf("\t\tDDSCAPS2_CUBEMAP_NEGATIVEZ\n"); } } + + printf("\tCaps 3: 0x%.8X\n", header.caps.caps3); + printf("\tCaps 4: 0x%.8X\n", header.caps.caps4); + + if (header.hasDX10Header()) + { + printf("DX10 Header:\n"); + printf("\tDXGI Format: %u (%s)\n", header.header10.dxgiFormat, getDxgiFormatString((DXGI_FORMAT)header.header10.dxgiFormat)); + printf("\tResource dimension: %u (%s)\n", header.header10.resourceDimension, getD3d10ResourceDimensionString((DDS_DIMENSION)header.header10.resourceDimension)); + printf("\tMisc flag: %u\n", header.header10.miscFlag); + printf("\tArray size: %u\n", header.header10.arraySize); + } + + if (header.reserved[9] == FOURCC_NVTT) + { + int major = (header.reserved[10] >> 16) & 0xFF; + int minor = (header.reserved[10] >> 8) & 0xFF; + int revision= header.reserved[10] & 0xFF; + + printf("Version:\n"); + printf("\tNVIDIA Texture Tools %d.%d.%d\n", major, minor, revision); + } + + if (header.reserved[7] == FOURCC_UVER) + { + printf("User Version: %d\n", header.reserved[8]); + } } -void DirectDrawSurface::readBlockImage(Image * img) + +static bool readLinearImage(Image * img, uint8 * data, uint bitcount, uint rmask, uint gmask, uint bmask, uint amask) { - nvDebugCheck(stream != NULL); nvDebugCheck(img != NULL); + nvDebugCheck(data != NULL); - const uint w = img->width(); - const uint h = img->height(); + const uint w = img->width; + const uint h = img->height; + const uint d = img->depth; - const uint bw = (w + 3) / 4; - const uint bh = (h + 3) / 4; + uint rshift, rsize; + PixelFormat::maskShiftAndSize(rmask, &rshift, &rsize); + + uint gshift, gsize; + PixelFormat::maskShiftAndSize(gmask, &gshift, &gsize); + + uint bshift, bsize; + PixelFormat::maskShiftAndSize(bmask, &bshift, &bsize); - for (uint by = 0; by < bh; by++) + uint ashift, asize; + PixelFormat::maskShiftAndSize(amask, &ashift, &asize); + + uint byteCount = (bitcount + 7) / 8; + + // Read linear RGB images. + for (uint z = 0; z < d; z++) { - for (uint bx = 0; bx < bw; bx++) + for (uint y = 0; y < h; y++) { - ColorBlock block; + for (uint x = 0; x < w; x++) + { + uint c; + memcpy(&c, data, byteCount); + data += byteCount; - // Read color block. - readBlock(&block); + Color32 pixel(0, 0, 0, 0xFF); + pixel.r = PixelFormat::convert((c & rmask) >> rshift, rsize, 8); + pixel.g = PixelFormat::convert((c & gmask) >> gshift, gsize, 8); + pixel.b = PixelFormat::convert((c & bmask) >> bshift, bsize, 8); + pixel.a = PixelFormat::convert((c & amask) >> ashift, asize, 8); - // Write color block. - for (uint y = 0; y < min(4U, h-4*by); y++) - { - for (uint x = 0; x < min(4U, w-4*bx); x++) - { - img->pixel(4*bx+x, 4*by+y) = block.color(x, y); - } + img->pixel(x, y, z) = pixel; } } } -} - -static Color32 buildNormal(uint8 x, uint8 y) -{ - float nx = 2 * (x / 255.0f) - 1; - float ny = 2 * (y / 255.0f) - 1; - float nz = 0.0f; - if (1 - nx*nx - ny*ny > 0) nz = sqrtf(1 - nx*nx - ny*ny); - uint8 z = clamp(int(255.0f * (nz + 1) / 2.0f), 0, 255); - return Color32(x, y, z); + return true; } -void DirectDrawSurface::readBlock(ColorBlock * rgba) +static void readBlock(ColorBlock * rgba, uint8 * data, uint dxgiFormat, bool isNormalMap, bool swapRA) { - nvDebugCheck(stream != NULL); nvDebugCheck(rgba != NULL); + nvDebugCheck(data != NULL); - uint fourcc = header.pf.fourcc; - - // Map DX10 block formats to fourcc codes. - if (header.hasDX10Header()) - { - if (header.header10.dxgiFormat == DXGI_FORMAT_BC1_UNORM) fourcc = FOURCC_DXT1; - else if (header.header10.dxgiFormat == DXGI_FORMAT_BC2_UNORM) fourcc = FOURCC_DXT3; - else if (header.header10.dxgiFormat == DXGI_FORMAT_BC3_UNORM) fourcc = FOURCC_DXT5; - else if (header.header10.dxgiFormat == DXGI_FORMAT_BC4_UNORM) fourcc = FOURCC_ATI1; - else if (header.header10.dxgiFormat == DXGI_FORMAT_BC5_UNORM) fourcc = FOURCC_ATI2; - } - - if (fourcc == FOURCC_DXT1) + if (dxgiFormat == DXGI_FORMAT_BC1_UNORM) { - BlockDXT1 block; - *stream << block; - block.decodeBlock(rgba); + BlockDXT1 * block = (BlockDXT1 *)data; + block->decodeBlock(rgba); } - else if (fourcc == FOURCC_DXT2 || fourcc == FOURCC_DXT3) + else if (dxgiFormat == DXGI_FORMAT_BC2_UNORM) { - BlockDXT3 block; - *stream << block; - block.decodeBlock(rgba); + BlockDXT3 * block = (BlockDXT3 *)data; + block->decodeBlock(rgba); } - else if (fourcc == FOURCC_DXT4 || fourcc == FOURCC_DXT5 || fourcc == FOURCC_RXGB) + else if (dxgiFormat == DXGI_FORMAT_BC3_UNORM) { - BlockDXT5 block; - *stream << block; - block.decodeBlock(rgba); + BlockDXT5 * block = (BlockDXT5 *)data; + block->decodeBlock(rgba); - if (fourcc == FOURCC_RXGB) - { + if (swapRA) { // Swap R & A. for (int i = 0; i < 16; i++) { @@ -1430,262 +1526,264 @@ void DirectDrawSurface::readBlock(ColorBlock * rgba) } } } - else if (fourcc == FOURCC_ATI1) + else if (DXGI_FORMAT_BC4_UNORM) { - BlockATI1 block; - *stream << block; - block.decodeBlock(rgba); + BlockATI1 * block = (BlockATI1 *)data; + block->decodeBlock(rgba); } - else if (fourcc == FOURCC_ATI2) + else if (DXGI_FORMAT_BC5_UNORM) { - BlockATI2 block; - *stream << block; - block.decodeBlock(rgba); + BlockATI2 * block = (BlockATI2 *)data; + block->decodeBlock(rgba); } - else if (header.hasDX10Header() && header.header10.dxgiFormat == DXGI_FORMAT_BC6H_UF16) + else if (dxgiFormat == DXGI_FORMAT_BC6H_UF16) { - BlockBC6 block; - *stream << block; + BlockBC6 * block = (BlockBC6 *)data; Vector4 colors[16]; - block.decodeBlock(colors); + block->decodeBlock(colors); // Clamp to [0, 1] and round to 8-bit for (int y = 0; y < 4; ++y) { for (int x = 0; x < 4; ++x) { - Vector4 px = colors[y*4 + x]; + Vector4 px = colors[y * 4 + x]; rgba->color(x, y).setRGBA( - ftoi_round(clamp(px.x, 0.0f, 1.0f) * 255.0f), - ftoi_round(clamp(px.y, 0.0f, 1.0f) * 255.0f), - ftoi_round(clamp(px.z, 0.0f, 1.0f) * 255.0f), - 0xFF); + ftoi_round(clamp(px.x, 0.0f, 1.0f) * 255.0f), + ftoi_round(clamp(px.y, 0.0f, 1.0f) * 255.0f), + ftoi_round(clamp(px.z, 0.0f, 1.0f) * 255.0f), + 0xFF); } } } - else if (header.hasDX10Header() && header.header10.dxgiFormat == DXGI_FORMAT_BC7_UNORM) + else if (dxgiFormat == DXGI_FORMAT_BC7_UNORM) { - BlockBC7 block; - *stream << block; - block.decodeBlock(rgba); + BlockBC7 * block = (BlockBC7 *)data; + block->decodeBlock(rgba); } else { nvDebugCheck(false); } - // If normal flag set, convert to normal. - if (header.pf.flags & DDPF_NORMAL) + // If normal flag set, reconstruct Z from XY. + if (isNormalMap) { - if (fourcc == FOURCC_ATI2) - { - for (int i = 0; i < 16; i++) - { - Color32 & c = rgba->color(i); - c = buildNormal(c.r, c.g); - } - } - else if (fourcc == FOURCC_DXT5) + for (int i = 0; i < 16; i++) { - for (int i = 0; i < 16; i++) - { - Color32 & c = rgba->color(i); - c = buildNormal(c.a, c.g); - } - } - } -} + Color32 & c = rgba->color(i); - -static uint mipmapExtent(uint mipmap, uint x) -{ - for (uint m = 0; m < mipmap; m++) { - x = max(1U, x / 2); + float nx = 2 * (c.r / 255.0f) - 1; + float ny = 2 * (c.g / 255.0f) - 1; + float nz = 0.0f; + if (1 - nx * nx - ny * ny > 0) nz = sqrtf(1 - nx * nx - ny * ny); + c.b = clamp(int(255.0f * (nz + 1) / 2.0f), 0, 255); + } } - return x; -} - -uint DirectDrawSurface::surfaceWidth(uint mipmap) const -{ - return mipmapExtent(mipmap, width()); -} - -uint DirectDrawSurface::surfaceHeight(uint mipmap) const -{ - return mipmapExtent(mipmap, height()); } -uint DirectDrawSurface::surfaceDepth(uint mipmap) const -{ - return mipmapExtent(mipmap, depth()); -} - -uint DirectDrawSurface::surfaceSize(uint mipmap) const -{ - uint w = surfaceWidth(mipmap); - uint h = surfaceHeight(mipmap); - uint d = surfaceDepth(mipmap); - - uint blockSize = header.blockSize(); - - if (blockSize == 0) { - uint bitCount = header.pixelSize(); - uint pitch = computeBytePitch(w, bitCount, 1); // Asuming 1 byte alignment, which is the same D3DX expects. - return pitch * h * d; - } - else { - w = (w + 3) / 4; - h = (h + 3) / 4; - //d = d; // @@ How are 3D textures aligned? - return blockSize * w * h * d; - } -} -uint DirectDrawSurface::faceSize() const +static bool readBlockImage(Image * img, uint8 * data, uint dxgiFormat, bool isNormalMap, bool swapRA) { - const uint count = mipmapCount(); - uint size = 0; + nvDebugCheck(img != NULL); + nvDebugCheck(data != NULL); - for (uint m = 0; m < count; m++) - { - size += surfaceSize(m); + switch (dxgiFormat) { + case DXGI_FORMAT_BC1_TYPELESS: + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC1_UNORM_SRGB: + dxgiFormat = DXGI_FORMAT_BC1_UNORM; + break; + case DXGI_FORMAT_BC2_TYPELESS: + case DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT_BC2_UNORM_SRGB: + dxgiFormat = DXGI_FORMAT_BC2_UNORM; + break; + case DXGI_FORMAT_BC3_TYPELESS: + case DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT_BC3_UNORM_SRGB: + dxgiFormat = DXGI_FORMAT_BC3_UNORM; + break; + case DXGI_FORMAT_BC4_TYPELESS: + case DXGI_FORMAT_BC4_UNORM: + //case DXGI_FORMAT_BC4_SNORM; // Not supported. + dxgiFormat = DXGI_FORMAT_BC4_UNORM; + break; + case DXGI_FORMAT_BC5_TYPELESS: + case DXGI_FORMAT_BC5_UNORM: + //case DXGI_FORMAT_BC5_SNORM: // Not supported. + dxgiFormat = DXGI_FORMAT_BC5_UNORM; + break; + case DXGI_FORMAT_BC6H_TYPELESS: + case DXGI_FORMAT_BC6H_UF16: + case DXGI_FORMAT_BC6H_SF16: + dxgiFormat = DXGI_FORMAT_BC6H_UF16; + break; + case DXGI_FORMAT_BC7_TYPELESS: + case DXGI_FORMAT_BC7_UNORM: + case DXGI_FORMAT_BC7_UNORM_SRGB: + dxgiFormat = DXGI_FORMAT_BC7_UNORM; + break; + default: + return false; } - return size; -} + const uint w = img->width; + const uint h = img->height; + const uint d = img->depth; -uint DirectDrawSurface::offset(const uint face, const uint mipmap) -{ - uint size = 128; // sizeof(DDSHeader); + const uint bw = (w + 3) / 4; + const uint bh = (h + 3) / 4; - if (header.hasDX10Header()) + for (uint z = 0; z < d; z++) { - size += 20; // sizeof(DDSHeader10); - } + for (uint by = 0; by < bh; by++) + { + for (uint bx = 0; bx < bw; bx++) + { + ColorBlock block; - if (face != 0) - { - size += face * faceSize(); - } + // Read color block. + readBlock(&block, data, dxgiFormat, isNormalMap, swapRA); - for (uint m = 0; m < mipmap; m++) - { - size += surfaceSize(m); + // Write color block. + for (uint y = 0; y < min(4U, h - 4 * by); y++) + { + for (uint x = 0; x < min(4U, w - 4 * bx); x++) + { + img->pixel(4 * bx + x, 4 * by + y) = block.color(x, y); + } + } + } + } } - return size; + return true; } -void DirectDrawSurface::printInfo() const +bool nv::imageFromDDS(Image * img, DirectDrawSurface & dds, uint face, uint mipmap) { - printf("Flags: 0x%.8X\n", header.flags); - if (header.flags & DDSD_CAPS) printf("\tDDSD_CAPS\n"); - if (header.flags & DDSD_PIXELFORMAT) printf("\tDDSD_PIXELFORMAT\n"); - if (header.flags & DDSD_WIDTH) printf("\tDDSD_WIDTH\n"); - if (header.flags & DDSD_HEIGHT) printf("\tDDSD_HEIGHT\n"); - if (header.flags & DDSD_DEPTH) printf("\tDDSD_DEPTH\n"); - if (header.flags & DDSD_PITCH) printf("\tDDSD_PITCH\n"); - if (header.flags & DDSD_LINEARSIZE) printf("\tDDSD_LINEARSIZE\n"); - if (header.flags & DDSD_MIPMAPCOUNT) printf("\tDDSD_MIPMAPCOUNT\n"); + if (!dds.isValid()) return false; - printf("Height: %d\n", header.height); - printf("Width: %d\n", header.width); - printf("Depth: %d\n", header.depth); - if (header.flags & DDSD_PITCH) printf("Pitch: %d\n", header.pitch); - else if (header.flags & DDSD_LINEARSIZE) printf("Linear size: %d\n", header.pitch); - printf("Mipmap count: %d\n", header.mipmapcount); - - printf("Pixel Format:\n"); - printf("\tFlags: 0x%.8X\n", header.pf.flags); - if (header.pf.flags & DDPF_RGB) printf("\t\tDDPF_RGB\n"); - if (header.pf.flags & DDPF_LUMINANCE) printf("\t\tDDPF_LUMINANCE\n"); - if (header.pf.flags & DDPF_FOURCC) printf("\t\tDDPF_FOURCC\n"); - if (header.pf.flags & DDPF_ALPHAPIXELS) printf("\t\tDDPF_ALPHAPIXELS\n"); - if (header.pf.flags & DDPF_ALPHA) printf("\t\tDDPF_ALPHA\n"); - if (header.pf.flags & DDPF_PALETTEINDEXED1) printf("\t\tDDPF_PALETTEINDEXED1\n"); - if (header.pf.flags & DDPF_PALETTEINDEXED2) printf("\t\tDDPF_PALETTEINDEXED2\n"); - if (header.pf.flags & DDPF_PALETTEINDEXED4) printf("\t\tDDPF_PALETTEINDEXED4\n"); - if (header.pf.flags & DDPF_PALETTEINDEXED8) printf("\t\tDDPF_PALETTEINDEXED8\n"); - if (header.pf.flags & DDPF_ALPHAPREMULT) printf("\t\tDDPF_ALPHAPREMULT\n"); - if (header.pf.flags & DDPF_NORMAL) printf("\t\tDDPF_NORMAL\n"); + uint size = dds.surfaceSize(mipmap); + uint8 * data = malloc(size); + defer { free(data); }; - if (header.pf.fourcc != 0) { - // Display fourcc code even when DDPF_FOURCC flag not set. - printf("\tFourCC: '%c%c%c%c' (0x%.8X)\n", - ((header.pf.fourcc >> 0) & 0xFF), - ((header.pf.fourcc >> 8) & 0xFF), - ((header.pf.fourcc >> 16) & 0xFF), - ((header.pf.fourcc >> 24) & 0xFF), - header.pf.fourcc); + if (!dds.readSurface(face, mipmap, data, size)) { + return false; } - if ((header.pf.flags & DDPF_FOURCC) && (header.pf.bitcount != 0)) + uint w = dds.surfaceWidth(mipmap); + uint h = dds.surfaceHeight(mipmap); + uint d = dds.surfaceDepth(mipmap); + + img->allocate(w, h, d); + + if (dds.hasAlpha()) { - printf("\tSwizzle: '%c%c%c%c' (0x%.8X)\n", - (header.pf.bitcount >> 0) & 0xFF, - (header.pf.bitcount >> 8) & 0xFF, - (header.pf.bitcount >> 16) & 0xFF, - (header.pf.bitcount >> 24) & 0xFF, - header.pf.bitcount); + img->format = Image::Format_ARGB; } else { - printf("\tBit count: %d\n", header.pf.bitcount); + img->format = Image::Format_XRGB; } - printf("\tRed mask: 0x%.8X\n", header.pf.rmask); - printf("\tGreen mask: 0x%.8X\n", header.pf.gmask); - printf("\tBlue mask: 0x%.8X\n", header.pf.bmask); - printf("\tAlpha mask: 0x%.8X\n", header.pf.amask); - - printf("Caps:\n"); - printf("\tCaps 1: 0x%.8X\n", header.caps.caps1); - if (header.caps.caps1 & DDSCAPS_COMPLEX) printf("\t\tDDSCAPS_COMPLEX\n"); - if (header.caps.caps1 & DDSCAPS_TEXTURE) printf("\t\tDDSCAPS_TEXTURE\n"); - if (header.caps.caps1 & DDSCAPS_MIPMAP) printf("\t\tDDSCAPS_MIPMAP\n"); + img->sRGB = dds.isColorsRGB(); - printf("\tCaps 2: 0x%.8X\n", header.caps.caps2); - if (header.caps.caps2 & DDSCAPS2_VOLUME) printf("\t\tDDSCAPS2_VOLUME\n"); - else if (header.caps.caps2 & DDSCAPS2_CUBEMAP) + if (dds.header.isBlockFormat()) { - printf("\t\tDDSCAPS2_CUBEMAP\n"); - if ((header.caps.caps2 & DDSCAPS2_CUBEMAP_ALL_FACES) == DDSCAPS2_CUBEMAP_ALL_FACES) printf("\t\tDDSCAPS2_CUBEMAP_ALL_FACES\n"); + bool isNormalMap = false; + bool swapRA = false; + uint dxgiFormat = DXGI_FORMAT_UNKNOWN; + if (dds.header.hasDX10Header()) { + dxgiFormat = dds.header.header10.dxgiFormat; + } else { - if (header.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEX) printf("\t\tDDSCAPS2_CUBEMAP_POSITIVEX\n"); - if (header.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEX) printf("\t\tDDSCAPS2_CUBEMAP_NEGATIVEX\n"); - if (header.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEY) printf("\t\tDDSCAPS2_CUBEMAP_POSITIVEY\n"); - if (header.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEY) printf("\t\tDDSCAPS2_CUBEMAP_NEGATIVEY\n"); - if (header.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEZ) printf("\t\tDDSCAPS2_CUBEMAP_POSITIVEZ\n"); - if (header.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEZ) printf("\t\tDDSCAPS2_CUBEMAP_NEGATIVEZ\n"); + switch (dds.header.pf.fourcc) { + case FOURCC_DXT1: dxgiFormat = DXGI_FORMAT_BC1_UNORM; break; + case FOURCC_DXT3: dxgiFormat = DXGI_FORMAT_BC2_UNORM; break; + case FOURCC_DXT5: dxgiFormat = DXGI_FORMAT_BC3_UNORM; break; + case FOURCC_ATI1: dxgiFormat = DXGI_FORMAT_BC4_UNORM; break; + case FOURCC_ATI2: dxgiFormat = DXGI_FORMAT_BC5_UNORM; break; + case FOURCC_RXGB: dxgiFormat = DXGI_FORMAT_BC3_UNORM; swapRA = true; break; + } } - } - - printf("\tCaps 3: 0x%.8X\n", header.caps.caps3); - printf("\tCaps 4: 0x%.8X\n", header.caps.caps4); + if (dds.header.pf.flags & DDPF_NORMAL) isNormalMap = true; - if (header.hasDX10Header()) + return readBlockImage(img, data, dxgiFormat, isNormalMap, swapRA); + } + else { - printf("DX10 Header:\n"); - printf("\tDXGI Format: %u (%s)\n", header.header10.dxgiFormat, getDxgiFormatString((DXGI_FORMAT)header.header10.dxgiFormat)); - printf("\tResource dimension: %u (%s)\n", header.header10.resourceDimension, getD3d10ResourceDimensionString((DDS_DIMENSION)header.header10.resourceDimension)); - printf("\tMisc flag: %u\n", header.header10.miscFlag); - printf("\tArray size: %u\n", header.header10.arraySize); + if (dds.header.hasDX10Header()) + { + if (const RGBAPixelFormat *format = findDXGIPixelFormat(dds.header.header10.dxgiFormat)) { + return readLinearImage(img, data, format->bitcount, format->rmask, format->gmask, format->bmask, format->amask); + } + } + else + { + if (dds.header.pf.flags & DDPF_RGB) + { + return readLinearImage(img, data, dds.header.pf.bitcount, dds.header.pf.rmask, dds.header.pf.gmask, dds.header.pf.bmask, dds.header.pf.amask); + } + else if (dds.header.pf.flags & DDPF_FOURCC) + { + if (const RGBAPixelFormat *format = findD3D9PixelFormat(dds.header.pf.fourcc)) { + return readLinearImage(img, data, format->bitcount, format->rmask, format->gmask, format->bmask, format->amask); + } + } + } } - if (header.reserved[9] == FOURCC_NVTT) - { - int major = (header.reserved[10] >> 16) & 0xFF; - int minor = (header.reserved[10] >> 8) & 0xFF; - int revision= header.reserved[10] & 0xFF; + return false; // Not supported. +} - printf("Version:\n"); - printf("\tNVIDIA Texture Tools %d.%d.%d\n", major, minor, revision); - } +bool nv::imageFromDDS(FloatImage * img, DirectDrawSurface & dds, uint face, uint mipmap) +{ + if (!dds.isValid()) return false; - if (header.reserved[7] == FOURCC_UVER) - { - printf("User Version: %d\n", header.reserved[8]); + uint size = dds.surfaceSize(mipmap); + uint8 * data = malloc(size); + defer{ free(data); }; + + if (!dds.readSurface(face, mipmap, data, size)) { + return false; } + + uint w = dds.surfaceWidth(mipmap); + uint h = dds.surfaceHeight(mipmap); + uint d = dds.surfaceDepth(mipmap); + + // @@ + + return false; } + + + + +// Copyright NVIDIA Corporation 2007 -- Ignacio Castano +// Copyright (c) 2008-2020 -- Ignacio Castano +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. diff --git a/src/nvimage/DirectDrawSurface.h b/src/nvimage/DirectDrawSurface.h index 1049f06..b741ac4 100644 --- a/src/nvimage/DirectDrawSurface.h +++ b/src/nvimage/DirectDrawSurface.h @@ -1,29 +1,5 @@ -// Copyright NVIDIA Corporation 2007 -- Ignacio Castano -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - +// MIT license see full LICENSE text at end of file #pragma once -#ifndef NV_IMAGE_DIRECTDRAWSURFACE_H -#define NV_IMAGE_DIRECTDRAWSURFACE_H #include "nvimage.h" @@ -34,8 +10,8 @@ namespace nv { class Image; + class FloatImage; class Stream; - struct ColorBlock; enum DDPF { @@ -269,7 +245,6 @@ namespace nv }; extern uint findD3D9Format(uint bitcount, uint rmask, uint gmask, uint bmask, uint amask); - extern uint findDXGIFormat(uint bitcount, uint rmask, uint gmask, uint bmask, uint amask); struct RGBAPixelFormat @@ -281,9 +256,10 @@ namespace nv uint amask; }; + extern const RGBAPixelFormat *findD3D9PixelFormat(uint dxgiFormat); extern const RGBAPixelFormat *findDXGIPixelFormat(uint dxgiFormat); - struct NVIMAGE_CLASS DDSPixelFormat + struct DDSPixelFormat { uint size; uint flags; @@ -295,7 +271,7 @@ namespace nv uint amask; }; - struct NVIMAGE_CLASS DDSCaps + struct DDSCaps { uint caps1; uint caps2; @@ -304,7 +280,7 @@ namespace nv }; /// DDS file header for DX10. - struct NVIMAGE_CLASS DDSHeader10 + struct DDSHeader10 { uint dxgiFormat; uint resourceDimension; @@ -314,7 +290,7 @@ namespace nv }; /// DDS file header. - struct NVIMAGE_CLASS DDSHeader + struct DDSHeader { uint fourcc; uint size; @@ -369,16 +345,14 @@ namespace nv bool isBlockFormat() const; }; - NVIMAGE_API Stream & operator<< (Stream & s, DDSHeader & header); + Stream & operator<< (Stream & s, DDSHeader & header); /// DirectDraw Surface. (DDS) - class NVIMAGE_CLASS DirectDrawSurface + class DirectDrawSurface { public: DirectDrawSurface(); - DirectDrawSurface(const char * file); - DirectDrawSurface(Stream * stream); ~DirectDrawSurface(); bool load(const char * filename); @@ -388,6 +362,7 @@ namespace nv bool isSupported() const; bool hasAlpha() const; + bool isColorsRGB() const; uint mipmapCount() const; uint width() const; @@ -399,13 +374,12 @@ namespace nv bool isTexture3D() const; bool isTextureCube() const; bool isTextureArray() const; + bool isBlockFormat() const; void setNormalFlag(bool b); void setHasAlphaFlag(bool b); void setUserVersion(int version); - void mipmap(Image * img, uint f, uint m); - uint surfaceWidth(uint mipmap) const; uint surfaceHeight(uint mipmap) const; uint surfaceDepth(uint mipmap) const; @@ -422,15 +396,35 @@ namespace nv uint faceSize() const; uint offset(uint face, uint mipmap); - void readLinearImage(Image * img, uint bitcount, uint rmask, uint gmask, uint bmask, uint amask); - void readBlockImage(Image * img); - void readBlock(ColorBlock * rgba); - - - private: Stream * stream; + //void * data; }; + bool imageFromDDS(Image * img, DirectDrawSurface & dds, uint face, uint mipmap); + bool imageFromDDS(FloatImage * img, DirectDrawSurface & dds, uint face, uint mipmap); + } // nv namespace -#endif // NV_IMAGE_DIRECTDRAWSURFACE_H +// Copyright NVIDIA Corporation 2007 -- Ignacio Castano +// Copyright (c) 2008-2020 -- Ignacio Castano +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. diff --git a/src/nvimage/Filter.h b/src/nvimage/Filter.h index ab814f1..dd47838 100644 --- a/src/nvimage/Filter.h +++ b/src/nvimage/Filter.h @@ -1,8 +1,5 @@ // This code is in the public domain -- castanyo@yahoo.es - #pragma once -#ifndef NV_IMAGE_FILTER_H -#define NV_IMAGE_FILTER_H #include "nvimage.h" #include "nvcore/Debug.h" @@ -12,7 +9,7 @@ namespace nv class Vector4; /// Base filter class. - class NVIMAGE_CLASS Filter + class Filter { public: Filter(float width); @@ -30,7 +27,7 @@ namespace nv }; // Box filter. - class NVIMAGE_CLASS BoxFilter : public Filter + class BoxFilter : public Filter { public: BoxFilter(); @@ -39,7 +36,7 @@ namespace nv }; // Triangle (bilinear/tent) filter. - class NVIMAGE_CLASS TriangleFilter : public Filter + class TriangleFilter : public Filter { public: TriangleFilter(); @@ -48,7 +45,7 @@ namespace nv }; // Quadratic (bell) filter. - class NVIMAGE_CLASS QuadraticFilter : public Filter + class QuadraticFilter : public Filter { public: QuadraticFilter(); @@ -56,7 +53,7 @@ namespace nv }; // Cubic filter from Thatcher Ulrich. - class NVIMAGE_CLASS CubicFilter : public Filter + class CubicFilter : public Filter { public: CubicFilter(); @@ -64,7 +61,7 @@ namespace nv }; // Cubic b-spline filter from Paul Heckbert. - class NVIMAGE_CLASS BSplineFilter : public Filter + class BSplineFilter : public Filter { public: BSplineFilter(); @@ -73,7 +70,7 @@ namespace nv /// Mitchell & Netravali's two-param cubic /// @see "Reconstruction Filters in Computer Graphics", SIGGRAPH 88 - class NVIMAGE_CLASS MitchellFilter : public Filter + class MitchellFilter : public Filter { public: MitchellFilter(); @@ -87,7 +84,7 @@ namespace nv }; // Lanczos3 filter. - class NVIMAGE_CLASS LanczosFilter : public Filter + class LanczosFilter : public Filter { public: LanczosFilter(); @@ -95,7 +92,7 @@ namespace nv }; // Sinc filter. - class NVIMAGE_CLASS SincFilter : public Filter + class SincFilter : public Filter { public: SincFilter(float w); @@ -103,7 +100,7 @@ namespace nv }; // Kaiser filter. - class NVIMAGE_CLASS KaiserFilter : public Filter + class KaiserFilter : public Filter { public: KaiserFilter(float w); @@ -132,7 +129,7 @@ namespace nv /// A 1D kernel. Used to precompute filter weights. - class NVIMAGE_CLASS Kernel1 + class Kernel1 { NV_FORBID_COPY(Kernel1); public: @@ -162,7 +159,7 @@ namespace nv /// A 2D kernel. - class NVIMAGE_CLASS Kernel2 + class Kernel2 { public: Kernel2(uint width); @@ -195,7 +192,7 @@ namespace nv /// A 1D polyphase kernel - class NVIMAGE_CLASS PolyphaseKernel + class PolyphaseKernel { NV_FORBID_COPY(PolyphaseKernel); public: @@ -230,5 +227,3 @@ namespace nv }; } // nv namespace - -#endif // NV_IMAGE_FILTER_H diff --git a/src/nvimage/FloatImage.cpp b/src/nvimage/FloatImage.cpp index fa4d1bd..20a5452 100644 --- a/src/nvimage/FloatImage.cpp +++ b/src/nvimage/FloatImage.cpp @@ -56,9 +56,9 @@ void FloatImage::initFrom(const Image * img) nvCheck(img != NULL); uint channel_count = 3; - if (img->format() == Image::Format_ARGB) channel_count = 4; + if (img->format == Image::Format_ARGB) channel_count = 4; - allocate(channel_count, img->width(), img->height(), img->depth()); + allocate(channel_count, img->width, img->height, img->depth); float * red_channel = channel(0); float * green_channel = channel(1); diff --git a/src/nvimage/FloatImage.h b/src/nvimage/FloatImage.h index fe9e76e..2c1213f 100644 --- a/src/nvimage/FloatImage.h +++ b/src/nvimage/FloatImage.h @@ -34,78 +34,78 @@ namespace nv WrapMode_Mirror }; - NVIMAGE_API FloatImage(); - NVIMAGE_API FloatImage(const FloatImage & img); - NVIMAGE_API FloatImage(const Image * img); - NVIMAGE_API ~FloatImage(); + FloatImage(); + FloatImage(const FloatImage & img); + FloatImage(const Image * img); + ~FloatImage(); /** @name Conversion. */ //@{ - NVIMAGE_API void initFrom(const Image * img); - NVIMAGE_API Image * createImage(uint base_component = 0, uint num = 4) const; - NVIMAGE_API Image * createImageGammaCorrect(float gamma = 2.2f) const; + void initFrom(const Image * img); + Image * createImage(uint base_component = 0, uint num = 4) const; + Image * createImageGammaCorrect(float gamma = 2.2f) const; //@} /** @name Allocation. */ //@{ - NVIMAGE_API void allocate(uint c, uint w, uint h, uint d = 1); - NVIMAGE_API void free(); // Does not clear members. - NVIMAGE_API void resizeChannelCount(uint c); + void allocate(uint c, uint w, uint h, uint d = 1); + void free(); // Does not clear members. + void resizeChannelCount(uint c); //@} /** @name Manipulation. */ //@{ - NVIMAGE_API void clear(float f = 0.0f); - NVIMAGE_API void clear(uint component, float f = 0.0f); - NVIMAGE_API void copyChannel(uint src, uint dst); + void clear(float f = 0.0f); + void clear(uint component, float f = 0.0f); + void copyChannel(uint src, uint dst); - NVIMAGE_API void normalize(uint base_component); + void normalize(uint base_component); - NVIMAGE_API void packNormals(uint base_component); - NVIMAGE_API void expandNormals(uint base_component); - NVIMAGE_API void scaleBias(uint base_component, uint num, float scale, float add); + void packNormals(uint base_component); + void expandNormals(uint base_component); + void scaleBias(uint base_component, uint num, float scale, float add); - NVIMAGE_API void clamp(uint base_component, uint num, float low, float high); + void clamp(uint base_component, uint num, float low, float high); - NVIMAGE_API void toLinear(uint base_component, uint num, float gamma = 2.2f); - NVIMAGE_API void toGamma(uint base_component, uint num, float gamma = 2.2f); - NVIMAGE_API void exponentiate(uint base_component, uint num, float power); + void toLinear(uint base_component, uint num, float gamma = 2.2f); + void toGamma(uint base_component, uint num, float gamma = 2.2f); + void exponentiate(uint base_component, uint num, float power); - NVIMAGE_API void transform(uint base_component, const Matrix & m, const Vector4 & offset); - NVIMAGE_API void swizzle(uint base_component, uint r, uint g, uint b, uint a); + void transform(uint base_component, const Matrix & m, const Vector4 & offset); + void swizzle(uint base_component, uint r, uint g, uint b, uint a); - NVIMAGE_API FloatImage * fastDownSample() const; - NVIMAGE_API FloatImage * downSample(const Filter & filter, WrapMode wm) const; - NVIMAGE_API FloatImage * downSample(const Filter & filter, WrapMode wm, uint alpha) const; - NVIMAGE_API FloatImage * resize(const Filter & filter, uint w, uint h, WrapMode wm) const; - NVIMAGE_API FloatImage * resize(const Filter & filter, uint w, uint h, uint d, WrapMode wm) const; - NVIMAGE_API FloatImage * resize(const Filter & filter, uint w, uint h, WrapMode wm, uint alpha) const; - NVIMAGE_API FloatImage * resize(const Filter & filter, uint w, uint h, uint d, WrapMode wm, uint alpha) const; + FloatImage * fastDownSample() const; + FloatImage * downSample(const Filter & filter, WrapMode wm) const; + FloatImage * downSample(const Filter & filter, WrapMode wm, uint alpha) const; + FloatImage * resize(const Filter & filter, uint w, uint h, WrapMode wm) const; + FloatImage * resize(const Filter & filter, uint w, uint h, uint d, WrapMode wm) const; + FloatImage * resize(const Filter & filter, uint w, uint h, WrapMode wm, uint alpha) const; + FloatImage * resize(const Filter & filter, uint w, uint h, uint d, WrapMode wm, uint alpha) const; - NVIMAGE_API void convolve(const Kernel2 & k, uint c, WrapMode wm); + void convolve(const Kernel2 & k, uint c, WrapMode wm); - //NVIMAGE_API FloatImage * downSample(const Kernel1 & filter, WrapMode wm) const; - //NVIMAGE_API FloatImage * downSample(const Kernel1 & filter, uint w, uint h, WrapMode wm) const; + //FloatImage * downSample(const Kernel1 & filter, WrapMode wm) const; + //FloatImage * downSample(const Kernel1 & filter, uint w, uint h, WrapMode wm) const; //@} - NVIMAGE_API float applyKernelXY(const Kernel2 * k, int x, int y, int z, uint c, WrapMode wm) const; - NVIMAGE_API float applyKernelX(const Kernel1 * k, int x, int y, int z, uint c, WrapMode wm) const; - NVIMAGE_API float applyKernelY(const Kernel1 * k, int x, int y, int z, uint c, WrapMode wm) const; - NVIMAGE_API float applyKernelZ(const Kernel1 * k, int x, int y, int z, uint c, WrapMode wm) const; - NVIMAGE_API void applyKernelX(const PolyphaseKernel & k, int y, int z, uint c, WrapMode wm, float * output) const; - NVIMAGE_API void applyKernelY(const PolyphaseKernel & k, int x, int z, uint c, WrapMode wm, float * output, int output_stride) const; - NVIMAGE_API void applyKernelZ(const PolyphaseKernel & k, int x, int y, uint c, WrapMode wm, float * output) const; - NVIMAGE_API void applyKernelX(const PolyphaseKernel & k, int y, int z, uint c, uint a, WrapMode wm, float * output) const; - NVIMAGE_API void applyKernelY(const PolyphaseKernel & k, int x, int z, uint c, uint a, WrapMode wm, float * output, int output_stride) const; - NVIMAGE_API void applyKernelZ(const PolyphaseKernel & k, int x, int y, uint c, uint a, WrapMode wm, float * output) const; + float applyKernelXY(const Kernel2 * k, int x, int y, int z, uint c, WrapMode wm) const; + float applyKernelX(const Kernel1 * k, int x, int y, int z, uint c, WrapMode wm) const; + float applyKernelY(const Kernel1 * k, int x, int y, int z, uint c, WrapMode wm) const; + float applyKernelZ(const Kernel1 * k, int x, int y, int z, uint c, WrapMode wm) const; + void applyKernelX(const PolyphaseKernel & k, int y, int z, uint c, WrapMode wm, float * output) const; + void applyKernelY(const PolyphaseKernel & k, int x, int z, uint c, WrapMode wm, float * output, int output_stride) const; + void applyKernelZ(const PolyphaseKernel & k, int x, int y, uint c, WrapMode wm, float * output) const; + void applyKernelX(const PolyphaseKernel & k, int y, int z, uint c, uint a, WrapMode wm, float * output) const; + void applyKernelY(const PolyphaseKernel & k, int x, int z, uint c, uint a, WrapMode wm, float * output, int output_stride) const; + void applyKernelZ(const PolyphaseKernel & k, int x, int y, uint c, uint a, WrapMode wm, float * output) const; - NVIMAGE_API void flipX(); - NVIMAGE_API void flipY(); - NVIMAGE_API void flipZ(); + void flipX(); + void flipY(); + void flipZ(); - NVIMAGE_API float alphaTestCoverage(float alphaRef, int alphaChannel, float alphaScale = 1.0f) const; - NVIMAGE_API void scaleAlphaToCoverage(float coverage, float alphaRef, int alphaChannel); + float alphaTestCoverage(float alphaRef, int alphaChannel, float alphaScale = 1.0f) const; + void scaleAlphaToCoverage(float coverage, float alphaRef, int alphaChannel); uint width() const { return m_width; } diff --git a/src/nvimage/Image.cpp b/src/nvimage/Image.cpp index 0ac84a6..5ff362b 100644 --- a/src/nvimage/Image.cpp +++ b/src/nvimage/Image.cpp @@ -15,15 +15,11 @@ using namespace nv; -Image::Image() : m_width(0), m_height(0), m_format(Format_RGB), m_data(NULL) +Image::Image(const Image & img) { -} - -Image::Image(const Image & img) : m_data(NULL) -{ - allocate(img.m_width, img.m_height, img.m_depth); - m_format = img.m_format; - memcpy(m_data, img.m_data, sizeof(Color32) * m_width * m_height * m_depth); + allocate(img.width, img.height, img.depth); + format = img.format; + memcpy(data, img.data, sizeof(Color32) * width * height * depth); } Image::~Image() @@ -33,28 +29,35 @@ Image::~Image() const Image & Image::operator=(const Image & img) { - allocate(img.m_width, img.m_height, m_depth); - m_format = img.m_format; - memcpy(m_data, img.m_data, sizeof(Color32) * m_width * m_height * m_depth); + allocate(img.width, img.height, depth); + format = img.format; + memcpy(data, img.data, sizeof(Color32) * width * height * depth); return *this; } void Image::allocate(uint w, uint h, uint d/*= 1*/) { - m_width = w; - m_height = h; - m_depth = d; - m_data = realloc(m_data, w * h * d); + width = w; + height = h; + depth = d; + data = realloc(data, w * h * d); } void Image::acquire(Color32 * data, uint w, uint h, uint d/*= 1*/) { free(); - m_width = w; - m_height = h; - m_depth = d; - m_data = data; + width = w; + height = h; + depth = d; + data = data; +} + +void Image::free() +{ + ::free(data); + width = height = depth = 0; + data = NULL; } void Image::resize(uint w, uint h, uint d/*= 1*/) { @@ -66,9 +69,9 @@ void Image::resize(uint w, uint h, uint d/*= 1*/) { // Copy image. uint x, y, z; - for(z = 0; z < min(d, m_depth); z++) { - for(y = 0; y < min(h, m_height); y++) { - for(x = 0; x < min(w, m_width); x++) { + for(z = 0; z < min(d, depth); z++) { + for(y = 0; y < min(h, height); y++) { + for(x = 0; x < min(w, width); x++) { img.pixel(x, y, z) = pixel(x, y, z); } for(; x < w; x++) { @@ -89,11 +92,12 @@ void Image::resize(uint w, uint h, uint d/*= 1*/) { } } - swap(m_width, img.m_width); - swap(m_height, img.m_height); - swap(m_depth, img.m_depth); - swap(m_format, img.m_format); - swap(m_data, img.m_data); + swap(width, img.width); + swap(height, img.height); + swap(depth, img.depth); + swap(format, img.format); + swap(sRGB, img.sRGB); + swap(data, img.data); } bool Image::load(const char * name) @@ -105,106 +109,74 @@ bool Image::load(const char * name) return false; } - swap(m_width, img->m_width); - swap(m_height, img->m_height); - swap(m_depth, img->m_depth); - swap(m_format, img->m_format); - swap(m_data, img->m_data); + swap(width, img->width); + swap(height, img->height); + swap(depth, img->depth); + swap(format, img->format); + swap(sRGB, img->sRGB); + swap(data, img->data); return true; } -void Image::wrap(void * data, uint w, uint h, uint d) +void Image::wrap(void * _data, uint w, uint h, uint d) { free(); - m_data = (Color32 *)data; - m_width = w; - m_height = h; - m_depth = d; + data = (Color32 *)_data; + width = w; + height = h; + depth = d; } void Image::unwrap() { - m_data = NULL; - m_width = 0; - m_height = 0; - m_depth = 0; -} - - -void Image::free() -{ - ::free(m_data); - m_data = NULL; -} - - -uint Image::width() const -{ - return m_width; + data = NULL; + width = 0; + height = 0; + depth = 0; } -uint Image::height() const -{ - return m_height; -} - -uint Image::depth() const -{ - return m_depth; -} const Color32 * Image::scanline(uint h) const { - nvDebugCheck(h < m_height); - return m_data + h * m_width; + nvDebugCheck(h < height); + return data + h * width; } Color32 * Image::scanline(uint h) { - nvDebugCheck(h < m_height); - return m_data + h * m_width; + nvDebugCheck(h < height); + return data + h * width; } const Color32 * Image::pixels() const { - return m_data; + return data; } Color32 * Image::pixels() { - return m_data; + return data; } const Color32 & Image::pixel(uint idx) const { - nvDebugCheck(idx < m_width * m_height * m_depth); - return m_data[idx]; + nvDebugCheck(idx < width * height * depth); + return data[idx]; } Color32 & Image::pixel(uint idx) { - nvDebugCheck(idx < m_width * m_height * m_depth); - return m_data[idx]; -} - - -Image::Format Image::format() const -{ - return m_format; -} - -void Image::setFormat(Image::Format f) -{ - m_format = f; + nvDebugCheck(idx < width * height * depth); + return data[idx]; } void Image::fill(Color32 c) { - const uint size = m_width * m_height * m_depth; + const uint size = width * height * depth; for (uint i = 0; i < size; ++i) { - m_data[i] = c; + data[i] = c; } } diff --git a/src/nvimage/Image.h b/src/nvimage/Image.h index e8f6fa6..901526c 100644 --- a/src/nvimage/Image.h +++ b/src/nvimage/Image.h @@ -1,8 +1,5 @@ // This code is in the public domain -- castanyo@yahoo.es - #pragma once -#ifndef NV_IMAGE_IMAGE_H -#define NV_IMAGE_IMAGE_H #include "nvimage.h" #include "nvcore/Debug.h" @@ -15,18 +12,17 @@ namespace nv { class Color32; - /// 32 bit RGBA image. - class NVIMAGE_CLASS Image + // 32 bit ARGB image. + class Image { public: - enum Format - { - Format_RGB, + enum Format : uint8 { + Format_XRGB, Format_ARGB, }; - Image(); + Image() {} Image(const Image & img); ~Image(); @@ -36,16 +32,13 @@ namespace nv void allocate(uint w, uint h, uint d = 1); void acquire(Color32 * data, uint w, uint h, uint d = 1); bool load(const char * name); + void free(); void resize(uint w, uint h, uint d = 1); void wrap(void * data, uint w, uint h, uint d = 1); void unwrap(); - uint width() const; - uint height() const; - uint depth() const; - const Color32 * scanline(uint h) const; Color32 * scanline(uint h); @@ -58,36 +51,28 @@ namespace nv const Color32 & pixel(uint x, uint y, uint z = 0) const; Color32 & pixel(uint x, uint y, uint z = 0); - Format format() const; - void setFormat(Format f); - void fill(Color32 c); - private: - void free(); - private: - uint m_width; - uint m_height; - uint m_depth; - Format m_format; - Color32 * m_data; + uint width = 0; + uint height = 0; + uint depth = 0; + Format format = Format_XRGB; + bool sRGB = false; + Color32 * data = NULL; }; inline const Color32 & Image::pixel(uint x, uint y, uint z) const { - nvDebugCheck(x < m_width && y < m_height && z < m_depth); - return pixel((z * m_height + y) * m_width + x); + nvDebugCheck(x < width && y < height && z < depth); + return pixel((z * height + y) * width + x); } inline Color32 & Image::pixel(uint x, uint y, uint z) { - nvDebugCheck(x < m_width && y < m_height && z < m_depth); - return pixel((z * m_height + y) * m_width + x); + nvDebugCheck(x < width && y < height && z < depth); + return pixel((z * height + y) * width + x); } } // nv namespace - - -#endif // NV_IMAGE_IMAGE_H diff --git a/src/nvimage/ImageIO.cpp b/src/nvimage/ImageIO.cpp index 18f0feb..f4c0b13 100644 --- a/src/nvimage/ImageIO.cpp +++ b/src/nvimage/ImageIO.cpp @@ -55,12 +55,15 @@ extern "C" { #endif #if defined(NV_HAVE_STBIMAGE) +# define STB_IMAGE_STATIC // To avoid conflicts with users importing stb_image on their own. # define STB_IMAGE_IMPLEMENTATION # define STBI_NO_STDIO -# pragma warning(push) -# pragma warning(disable: 4312) -# include -# pragma warning(pop) +# include "stb_image.h" + +//# define STB_IMAGE_WRITE_STATIC +//# define STB_IMAGE_WRITE_IMPLEMENTATION +//# define STBI_WRITE_NO_STDIO +//# include "stb_image_write.h" #endif @@ -68,7 +71,7 @@ using namespace nv; -struct Color555 { +/*struct Color555 { uint16 b : 5; uint16 g : 5; uint16 r : 5; @@ -198,7 +201,7 @@ static Image * loadTGA(Stream & s) } } else if( grey ) { - img->setFormat(Image::Format_ARGB); + img->format = Image::Format_ARGB; for( int y = 0; y < tga.height; y++ ) { for( int x = 0; x < tga.width; x++ ) { @@ -233,7 +236,7 @@ static Image * loadTGA(Stream & s) } } else if( tga.pixel_size == 32 ) { - img->setFormat(Image::Format_ARGB); + img->format = Image::Format_ARGB; for( int y = 0; y < tga.height; y++ ) { for( int x = 0; x < tga.width; x++ ) { @@ -250,6 +253,7 @@ static Image * loadTGA(Stream & s) return img.release(); } +*/ // Save TGA image. static bool saveTGA(Stream & s, const Image * img) @@ -269,9 +273,9 @@ static bool saveTGA(Stream & s, const Image * img) tga.head.x_origin = 0; tga.head.y_origin = 0; - tga.head.width = img->width(); - tga.head.height = img->height(); - if(img->format() == Image::Format_ARGB) { + tga.head.width = img->width; + tga.head.height = img->height; + if(img->format == Image::Format_ARGB) { tga.head.pixel_size = 32; tga.head.flags = TGA_ORIGIN_UPPER | TGA_HAS_ALPHA; } @@ -283,8 +287,8 @@ static bool saveTGA(Stream & s, const Image * img) // @@ Serialize directly. tga.allocate(); - const uint n = img->width() * img->height(); - if(img->format() == Image::Format_ARGB) { + const uint n = img->width * img->height; + if(img->format == Image::Format_ARGB) { for(uint i = 0; i < n; i++) { Color32 color = img->pixel(i); tga.mem[4 * i + 0] = color.b; @@ -309,13 +313,13 @@ static bool saveTGA(Stream & s, const Image * img) return true; } -#pragma optimize("", off) +/*#pragma optimize("", off) // Save BMP image. static bool saveBMP(Stream & s, const Image * img) { - int w = img->width(); - int h = img->height(); + int w = img->width; + int h = img->height; int image_size = w * h * 3; BmpFileHeader header; @@ -352,7 +356,7 @@ static bool saveBMP(Stream & s, const Image * img) } return true; -} +}*/ /*static Image * loadPPM(Stream & s) { @@ -366,8 +370,8 @@ static bool savePPM(Stream & s, const Image * img) //if (img->depth() != 1) return false; //if (img->format() == Image::Format_ARGB) return false; - uint w = img->width(); - uint h = img->height(); + uint w = img->width; + uint h = img->height; TextWriter writer(&s); writer.format("P6\n"); @@ -396,7 +400,7 @@ static bool savePPM(Stream & s, const Image * img) }*/ // Load PSD image. -static Image * loadPSD(Stream & s) +/*static Image * loadPSD(Stream & s) { nvCheck(!s.isError()); nvCheck(s.isLoading()); @@ -457,7 +461,7 @@ static Image * loadPSD(Stream & s) else { // Enable alpha. - img->setFormat(Image::Format_ARGB); + img->format = Image::Format_ARGB; // Ignore remaining channels. channel_num = 4; @@ -545,7 +549,7 @@ static Image * loadPSD(Stream & s) } return img.release(); -} +}*/ static FloatImage * loadFloatDDS(Stream & s) { @@ -1766,7 +1770,7 @@ static Image * loadSTB(Stream & s) if (data != NULL) { Image * img = new Image; img->acquire((Color32 *)data, w, h); - img->setFormat(n == 4 ? Image::Format_ARGB : Image::Format_RGB); + img->format = (n == 4) ? Image::Format_ARGB : Image::Format_XRGB; int count = w * h; for (int i = 0; i < count; ++i) { @@ -1840,13 +1844,13 @@ Image * nv::ImageIO::load(const char * fileName, Stream & s) const char * extension = Path::extension(fileName); - if (strCaseDiff(extension, ".tga") == 0) { + /*if (strCaseDiff(extension, ".tga") == 0) { return loadTGA(s); - } + }*/ - if (strCaseDiff(extension, ".psd") == 0) { + /*if (strCaseDiff(extension, ".psd") == 0) { return loadPSD(s); - } + }*/ /*if (strCaseDiff(extension, ".ppm") == 0) { return loadPPM(s); @@ -1887,9 +1891,9 @@ bool nv::ImageIO::save(const char * fileName, Stream & s, const Image * img, con const char * extension = Path::extension(fileName); - if (strCaseDiff(extension, ".bmp") == 0) { + /*if (strCaseDiff(extension, ".bmp") == 0) { return saveBMP(s, img); - } + }*/ if (strCaseDiff(extension, ".tga") == 0) { return saveTGA(s, img); @@ -2030,7 +2034,7 @@ bool nv::ImageIO::saveFloat(const char * fileName, Stream & s, const FloatImage if (componentCount == 1) { Color32 * c = image->pixels(); - const uint count = image->width() * image->height(); + const uint count = image->width * image->height; for (uint i = 0; i < count; i++) { c[i].b = c[i].g = c[i].r; @@ -2039,7 +2043,7 @@ bool nv::ImageIO::saveFloat(const char * fileName, Stream & s, const FloatImage if (componentCount == 4) { - image->setFormat(Image::Format_ARGB); + image->format = Image::Format_ARGB; } return ImageIO::save(fileName, s, image.ptr()); diff --git a/src/nvimage/ImageIO.h b/src/nvimage/ImageIO.h index 25490ab..3911f7d 100644 --- a/src/nvimage/ImageIO.h +++ b/src/nvimage/ImageIO.h @@ -1,14 +1,8 @@ // This code is in the public domain -- castanyo@yahoo.es - #pragma once -#ifndef NV_IMAGE_IMAGEIO_H -#define NV_IMAGE_IMAGEIO_H #include "nvimage.h" -#include "nvcore/StrLib.h" - - namespace nv { class Image; @@ -17,21 +11,18 @@ namespace nv namespace ImageIO { - NVIMAGE_API Image * load(const char * fileName); - NVIMAGE_API Image * load(const char * fileName, Stream & s); + Image * load(const char * fileName); + Image * load(const char * fileName, Stream & s); - NVIMAGE_API FloatImage * loadFloat(const char * fileName); - NVIMAGE_API FloatImage * loadFloat(const char * fileName, Stream & s); + FloatImage * loadFloat(const char * fileName); + FloatImage * loadFloat(const char * fileName, Stream & s); - NVIMAGE_API bool save(const char * fileName, const Image * img, const char ** tags=NULL); // NULL terminated list. - NVIMAGE_API bool save(const char * fileName, Stream & s, const Image * img, const char ** tags=NULL); + bool save(const char * fileName, const Image * img, const char ** tags=NULL); // NULL terminated list. + bool save(const char * fileName, Stream & s, const Image * img, const char ** tags=NULL); - NVIMAGE_API bool saveFloat(const char * fileName, const FloatImage * fimage, uint baseComponent, uint componentCount); - NVIMAGE_API bool saveFloat(const char * fileName, Stream & s, const FloatImage * fimage, uint baseComponent, uint componentCount); + bool saveFloat(const char * fileName, const FloatImage * fimage, uint baseComponent, uint componentCount); + bool saveFloat(const char * fileName, Stream & s, const FloatImage * fimage, uint baseComponent, uint componentCount); } // ImageIO namespace } // nv namespace - - -#endif // NV_IMAGE_IMAGEIO_H diff --git a/src/nvimage/KtxFile.h b/src/nvimage/KtxFile.h index b1b3674..555bd34 100644 --- a/src/nvimage/KtxFile.h +++ b/src/nvimage/KtxFile.h @@ -130,7 +130,7 @@ namespace nv }; - NVIMAGE_API Stream & operator<< (Stream & s, KtxHeader & header); + Stream & operator<< (Stream & s, KtxHeader & header); /* struct KtxFile { diff --git a/src/nvimage/NormalMap.cpp b/src/nvimage/NormalMap.cpp index 754166a..b8215cf 100644 --- a/src/nvimage/NormalMap.cpp +++ b/src/nvimage/NormalMap.cpp @@ -43,8 +43,8 @@ static FloatImage * createNormalMap(const Image * img, FloatImage::WrapMode wm, nvDebugCheck(kdv != NULL); nvDebugCheck(img != NULL); - const uint w = img->width(); - const uint h = img->height(); + const uint w = img->width; + const uint h = img->height; AutoPtr fimage(new FloatImage()); fimage->allocate(4, w, h); diff --git a/src/nvimage/nvimage.h b/src/nvimage/nvimage.h index e6edc55..e46b48c 100644 --- a/src/nvimage/nvimage.h +++ b/src/nvimage/nvimage.h @@ -1,32 +1,13 @@ // This code is in the public domain -- castanyo@yahoo.es - #pragma once -#ifndef NV_IMAGE_H -#define NV_IMAGE_H #include "nvcore/nvcore.h" #include "nvcore/Debug.h" // nvDebugCheck #include "nvcore/Utils.h" // isPowerOfTwo -// Function linkage -#if NVIMAGE_SHARED -#ifdef NVIMAGE_EXPORTS -#define NVIMAGE_API DLL_EXPORT -#define NVIMAGE_CLASS DLL_EXPORT_CLASS -#else -#define NVIMAGE_API DLL_IMPORT -#define NVIMAGE_CLASS DLL_IMPORT -#endif -#else -#define NVIMAGE_API -#define NVIMAGE_CLASS -#endif - - namespace nv { // Some utility functions: - inline uint computeBitPitch(uint w, uint bitsize, uint alignmentInBits) { nvDebugCheck(isPowerOfTwo(alignmentInBits)); @@ -42,7 +23,4 @@ namespace nv { return (pitch + 7) / 8; } - } // nv namespace - -#endif // NV_IMAGE_H