More cleanups. Assume static linking.

This commit is contained in:
Ignacio
2020-03-30 10:09:31 -07:00
parent 7f9c87713a
commit adce1a00da
14 changed files with 705 additions and 688 deletions

View File

@ -234,16 +234,16 @@ namespace nv
// Serialization functions. // Serialization functions.
NVIMAGE_API Stream & operator<<(Stream & stream, BlockDXT1 & block); Stream & operator<<(Stream & stream, BlockDXT1 & block);
NVIMAGE_API Stream & operator<<(Stream & stream, AlphaBlockDXT3 & block); Stream & operator<<(Stream & stream, AlphaBlockDXT3 & block);
NVIMAGE_API Stream & operator<<(Stream & stream, BlockDXT3 & block); Stream & operator<<(Stream & stream, BlockDXT3 & block);
NVIMAGE_API Stream & operator<<(Stream & stream, AlphaBlockDXT5 & block); Stream & operator<<(Stream & stream, AlphaBlockDXT5 & block);
NVIMAGE_API Stream & operator<<(Stream & stream, BlockDXT5 & block); Stream & operator<<(Stream & stream, BlockDXT5 & block);
NVIMAGE_API Stream & operator<<(Stream & stream, BlockATI1 & block); Stream & operator<<(Stream & stream, BlockATI1 & block);
NVIMAGE_API Stream & operator<<(Stream & stream, BlockATI2 & block); Stream & operator<<(Stream & stream, BlockATI2 & block);
NVIMAGE_API Stream & operator<<(Stream & stream, BlockCTX1 & block); Stream & operator<<(Stream & stream, BlockCTX1 & block);
NVIMAGE_API Stream & operator<<(Stream & stream, BlockBC6 & block); Stream & operator<<(Stream & stream, BlockBC6 & block);
NVIMAGE_API Stream & operator<<(Stream & stream, BlockBC7 & block); Stream & operator<<(Stream & stream, BlockBC7 & block);
} // nv namespace } // nv namespace

View File

@ -61,7 +61,7 @@ ColorBlock::ColorBlock(const Image * img, uint x, uint y)
void ColorBlock::init(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) void ColorBlock::init(uint w, uint h, const uint * data, uint x, uint y)

View File

@ -1,25 +1,4 @@
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com> // MIT license see full LICENSE text at end of file
//
// 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.
#include "DirectDrawSurface.h" #include "DirectDrawSurface.h"
#include "ColorBlock.h" #include "ColorBlock.h"
@ -352,6 +331,76 @@ namespace
nvUnreachable(); 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
namespace nv namespace nv
@ -508,6 +557,20 @@ const RGBAPixelFormat *nv::findDXGIPixelFormat(uint dxgiFormat)
return NULL; 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() DDSHeader::DDSHeader()
{ {
this->fourcc = FOURCC_DDS; 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() DirectDrawSurface::~DirectDrawSurface()
{ {
delete stream; delete stream;
@ -1020,7 +1073,8 @@ bool DirectDrawSurface::isSupported() const
return false; return false;
} }
if (isTextureCube()) { if (isTextureCube())
{
if (header.width != header.height) return false; if (header.width != header.height) return false;
if ((header.caps.caps2 & DDSCAPS2_CUBEMAP_ALL_FACES) != DDSCAPS2_CUBEMAP_ALL_FACES) if ((header.caps.caps2 & DDSCAPS2_CUBEMAP_ALL_FACES) != DDSCAPS2_CUBEMAP_ALL_FACES)
@ -1036,40 +1090,56 @@ bool DirectDrawSurface::isSupported() const
bool DirectDrawSurface::hasAlpha() 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()) if (header.hasDX10Header())
{ {
#pragma NV_MESSAGE("TODO: Update hasAlpha to handle all DX10 formats.") return ::hasAlpha((DXGI_FORMAT)header.header10.dxgiFormat);
return
header.header10.dxgiFormat == DXGI_FORMAT_BC1_UNORM ||
header.header10.dxgiFormat == DXGI_FORMAT_BC2_UNORM ||
header.header10.dxgiFormat == DXGI_FORMAT_BC3_UNORM;
} }
else else
{ {
//if (header.pf.flags & DDPF_ALPHAPIXELS) return true;
if (header.pf.flags & DDPF_RGB) if (header.pf.flags & DDPF_RGB)
{ {
return header.pf.amask != 0; return header.pf.amask != 0;
} }
else if (header.pf.flags & DDPF_FOURCC) else if (header.pf.flags & DDPF_FOURCC)
{ {
if (header.pf.fourcc == FOURCC_RXGB || return ::hasAlpha((D3DFORMAT)header.pf.fourcc);
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 false; 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 uint DirectDrawSurface::mipmapCount() const
{ {
nvDebugCheck(isValid()); nvDebugCheck(isValid());
@ -1172,331 +1242,6 @@ void DirectDrawSurface::setUserVersion(int version)
header.setUserVersion(version); header.setUserVersion(version);
} }
void DirectDrawSurface::mipmap(Image * img, uint face, uint mipmap)
{
nvDebugCheck(isValid());
stream->seek(offset(face, mipmap));
uint w = width();
uint h = height();
uint d = depth();
// 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);
}
img->allocate(w, h, d);
if (hasAlpha())
{
img->setFormat(Image::Format_ARGB);
}
else
{
img->setFormat(Image::Format_RGB);
}
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);
}
}
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);
}
}
}
/*void * DirectDrawSurface::readData(uint * sizePtr)
{
uint header_size = 128; // sizeof(DDSHeader);
if (header.hasDX10Header())
{
header_size += 20; // sizeof(DDSHeader10);
}
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;
}*/
/*uint DirectDrawSurface::surfaceSize(uint mipmap) const
{
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;
if (header.hasDX10Header()) {
blockOrPixelSize = blockSize(header10.dxgiFormat);
isBlockFormat = (blockOrPixelSize != 0);
if (isBlockFormat) {
blockOrPixelSize = pixelSize(header10.dxgiFormat);
}
}
else {
header.pf.flags
}
if (isBlockFormat) {
w = (w + 3) / 4;
h = (h + 3) / 4;
d = (d + 3) / 4; // @@ Is it necessary to align the depths?
}
uint blockOrPixelCount = w * h * d;
return blockCount = blockOrPixelSize;
}*/
bool DirectDrawSurface::readSurface(uint face, uint mipmap, void * data, uint size)
{
if (size != surfaceSize(mipmap)) return false;
stream->seek(offset(face, mipmap));
if (stream->isError()) return false;
return stream->serialize(data, size) == size;
}
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);
uint ashift, asize;
PixelFormat::maskShiftAndSize(amask, &ashift, &asize);
uint byteCount = (bitcount + 7) / 8;
#pragma NV_MESSAGE("TODO: Support floating point linear images and other FOURCC codes.")
// Read linear RGB images.
for (uint z = 0; z < d; z++)
{
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);
img->pixel(x, y, z) = pixel;
}
}
}
}
void DirectDrawSurface::readBlockImage(Image * img)
{
nvDebugCheck(stream != NULL);
nvDebugCheck(img != NULL);
const uint w = img->width();
const uint h = img->height();
const uint bw = (w + 3) / 4;
const uint bh = (h + 3) / 4;
for (uint by = 0; by < bh; by++)
{
for (uint bx = 0; bx < bw; bx++)
{
ColorBlock block;
// Read color block.
readBlock(&block);
// 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);
}
}
}
}
}
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);
}
void DirectDrawSurface::readBlock(ColorBlock * rgba)
{
nvDebugCheck(stream != NULL);
nvDebugCheck(rgba != 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)
{
BlockDXT1 block;
*stream << block;
block.decodeBlock(rgba);
}
else if (fourcc == FOURCC_DXT2 || fourcc == FOURCC_DXT3)
{
BlockDXT3 block;
*stream << block;
block.decodeBlock(rgba);
}
else if (fourcc == FOURCC_DXT4 || fourcc == FOURCC_DXT5 || fourcc == FOURCC_RXGB)
{
BlockDXT5 block;
*stream << block;
block.decodeBlock(rgba);
if (fourcc == FOURCC_RXGB)
{
// Swap R & A.
for (int i = 0; i < 16; i++)
{
Color32 & c = rgba->color(i);
uint tmp = c.r;
c.r = c.a;
c.a = tmp;
}
}
}
else if (fourcc == FOURCC_ATI1)
{
BlockATI1 block;
*stream << block;
block.decodeBlock(rgba);
}
else if (fourcc == FOURCC_ATI2)
{
BlockATI2 block;
*stream << block;
block.decodeBlock(rgba);
}
else if (header.hasDX10Header() && header.header10.dxgiFormat == DXGI_FORMAT_BC6H_UF16)
{
BlockBC6 block;
*stream << block;
Vector4 colors[16];
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];
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);
}
}
}
else if (header.hasDX10Header() && header.header10.dxgiFormat == DXGI_FORMAT_BC7_UNORM)
{
BlockBC7 block;
*stream << block;
block.decodeBlock(rgba);
}
else
{
nvDebugCheck(false);
}
// If normal flag set, convert to normal.
if (header.pf.flags & DDPF_NORMAL)
{
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++)
{
Color32 & c = rgba->color(i);
c = buildNormal(c.a, c.g);
}
}
}
}
static uint mipmapExtent(uint mipmap, uint x) static uint mipmapExtent(uint mipmap, uint x)
{ {
for (uint m = 0; m < mipmap; m++) { for (uint m = 0; m < mipmap; m++) {
@ -1554,7 +1299,7 @@ uint DirectDrawSurface::faceSize() const
return size; return size;
} }
uint DirectDrawSurface::offset(const uint face, const uint mipmap) uint DirectDrawSurface::offset(uint face, uint mipmap)
{ {
uint size = 128; // sizeof(DDSHeader); uint size = 128; // sizeof(DDSHeader);
@ -1576,6 +1321,17 @@ uint DirectDrawSurface::offset(const uint face, const uint mipmap)
return size; return size;
} }
bool DirectDrawSurface::readSurface(uint face, uint mipmap, void * data, uint size)
{
if (size != surfaceSize(mipmap)) return false;
stream->seek(offset(face, mipmap));
if (stream->isError()) return false;
return stream->serialize(data, size) == size;
}
void DirectDrawSurface::printInfo() const void DirectDrawSurface::printInfo() const
{ {
@ -1689,3 +1445,345 @@ void DirectDrawSurface::printInfo() const
} }
} }
static bool readLinearImage(Image * img, uint8 * data, uint bitcount, uint rmask, uint gmask, uint bmask, uint amask)
{
nvDebugCheck(img != NULL);
nvDebugCheck(data != 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);
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 y = 0; y < h; y++)
{
for (uint x = 0; x < w; x++)
{
uint c;
memcpy(&c, data, byteCount);
data += 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);
img->pixel(x, y, z) = pixel;
}
}
}
return true;
}
static void readBlock(ColorBlock * rgba, uint8 * data, uint dxgiFormat, bool isNormalMap, bool swapRA)
{
nvDebugCheck(rgba != NULL);
nvDebugCheck(data != NULL);
if (dxgiFormat == DXGI_FORMAT_BC1_UNORM)
{
BlockDXT1 * block = (BlockDXT1 *)data;
block->decodeBlock(rgba);
}
else if (dxgiFormat == DXGI_FORMAT_BC2_UNORM)
{
BlockDXT3 * block = (BlockDXT3 *)data;
block->decodeBlock(rgba);
}
else if (dxgiFormat == DXGI_FORMAT_BC3_UNORM)
{
BlockDXT5 * block = (BlockDXT5 *)data;
block->decodeBlock(rgba);
if (swapRA) {
// Swap R & A.
for (int i = 0; i < 16; i++)
{
Color32 & c = rgba->color(i);
uint tmp = c.r;
c.r = c.a;
c.a = tmp;
}
}
}
else if (DXGI_FORMAT_BC4_UNORM)
{
BlockATI1 * block = (BlockATI1 *)data;
block->decodeBlock(rgba);
}
else if (DXGI_FORMAT_BC5_UNORM)
{
BlockATI2 * block = (BlockATI2 *)data;
block->decodeBlock(rgba);
}
else if (dxgiFormat == DXGI_FORMAT_BC6H_UF16)
{
BlockBC6 * block = (BlockBC6 *)data;
Vector4 colors[16];
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];
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);
}
}
}
else if (dxgiFormat == DXGI_FORMAT_BC7_UNORM)
{
BlockBC7 * block = (BlockBC7 *)data;
block->decodeBlock(rgba);
}
else
{
nvDebugCheck(false);
}
// If normal flag set, reconstruct Z from XY.
if (isNormalMap)
{
for (int i = 0; i < 16; i++)
{
Color32 & c = rgba->color(i);
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);
}
}
}
static bool readBlockImage(Image * img, uint8 * data, uint dxgiFormat, bool isNormalMap, bool swapRA)
{
nvDebugCheck(img != NULL);
nvDebugCheck(data != NULL);
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;
}
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;
for (uint z = 0; z < d; z++)
{
for (uint by = 0; by < bh; by++)
{
for (uint bx = 0; bx < bw; bx++)
{
ColorBlock block;
// Read color block.
readBlock(&block, data, dxgiFormat, isNormalMap, swapRA);
// 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 true;
}
bool nv::imageFromDDS(Image * img, DirectDrawSurface & dds, uint face, uint mipmap)
{
if (!dds.isValid()) return false;
uint size = dds.surfaceSize(mipmap);
uint8 * data = malloc<uint8>(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);
img->allocate(w, h, d);
if (dds.hasAlpha())
{
img->format = Image::Format_ARGB;
}
else
{
img->format = Image::Format_XRGB;
}
img->sRGB = dds.isColorsRGB();
if (dds.header.isBlockFormat())
{
bool isNormalMap = false;
bool swapRA = false;
uint dxgiFormat = DXGI_FORMAT_UNKNOWN;
if (dds.header.hasDX10Header()) {
dxgiFormat = dds.header.header10.dxgiFormat;
}
else {
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;
}
}
if (dds.header.pf.flags & DDPF_NORMAL) isNormalMap = true;
return readBlockImage(img, data, dxgiFormat, isNormalMap, swapRA);
}
else
{
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);
}
}
}
}
return false; // Not supported.
}
bool nv::imageFromDDS(FloatImage * img, DirectDrawSurface & dds, uint face, uint mipmap)
{
if (!dds.isValid()) return false;
uint size = dds.surfaceSize(mipmap);
uint8 * data = malloc<uint8>(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 <icastano@nvidia.com>
// Copyright (c) 2008-2020 -- Ignacio Castano <castano@gmail.com>
//
// 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.

View File

@ -1,29 +1,5 @@
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com> // MIT license see full LICENSE text at end of file
//
// 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.
#pragma once #pragma once
#ifndef NV_IMAGE_DIRECTDRAWSURFACE_H
#define NV_IMAGE_DIRECTDRAWSURFACE_H
#include "nvimage.h" #include "nvimage.h"
@ -34,8 +10,8 @@
namespace nv namespace nv
{ {
class Image; class Image;
class FloatImage;
class Stream; class Stream;
struct ColorBlock;
enum DDPF enum DDPF
{ {
@ -269,7 +245,6 @@ namespace nv
}; };
extern uint findD3D9Format(uint bitcount, uint rmask, uint gmask, uint bmask, uint amask); 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); extern uint findDXGIFormat(uint bitcount, uint rmask, uint gmask, uint bmask, uint amask);
struct RGBAPixelFormat struct RGBAPixelFormat
@ -281,9 +256,10 @@ namespace nv
uint amask; uint amask;
}; };
extern const RGBAPixelFormat *findD3D9PixelFormat(uint dxgiFormat);
extern const RGBAPixelFormat *findDXGIPixelFormat(uint dxgiFormat); extern const RGBAPixelFormat *findDXGIPixelFormat(uint dxgiFormat);
struct NVIMAGE_CLASS DDSPixelFormat struct DDSPixelFormat
{ {
uint size; uint size;
uint flags; uint flags;
@ -295,7 +271,7 @@ namespace nv
uint amask; uint amask;
}; };
struct NVIMAGE_CLASS DDSCaps struct DDSCaps
{ {
uint caps1; uint caps1;
uint caps2; uint caps2;
@ -304,7 +280,7 @@ namespace nv
}; };
/// DDS file header for DX10. /// DDS file header for DX10.
struct NVIMAGE_CLASS DDSHeader10 struct DDSHeader10
{ {
uint dxgiFormat; uint dxgiFormat;
uint resourceDimension; uint resourceDimension;
@ -314,7 +290,7 @@ namespace nv
}; };
/// DDS file header. /// DDS file header.
struct NVIMAGE_CLASS DDSHeader struct DDSHeader
{ {
uint fourcc; uint fourcc;
uint size; uint size;
@ -369,16 +345,14 @@ namespace nv
bool isBlockFormat() const; bool isBlockFormat() const;
}; };
NVIMAGE_API Stream & operator<< (Stream & s, DDSHeader & header); Stream & operator<< (Stream & s, DDSHeader & header);
/// DirectDraw Surface. (DDS) /// DirectDraw Surface. (DDS)
class NVIMAGE_CLASS DirectDrawSurface class DirectDrawSurface
{ {
public: public:
DirectDrawSurface(); DirectDrawSurface();
DirectDrawSurface(const char * file);
DirectDrawSurface(Stream * stream);
~DirectDrawSurface(); ~DirectDrawSurface();
bool load(const char * filename); bool load(const char * filename);
@ -388,6 +362,7 @@ namespace nv
bool isSupported() const; bool isSupported() const;
bool hasAlpha() const; bool hasAlpha() const;
bool isColorsRGB() const;
uint mipmapCount() const; uint mipmapCount() const;
uint width() const; uint width() const;
@ -399,13 +374,12 @@ namespace nv
bool isTexture3D() const; bool isTexture3D() const;
bool isTextureCube() const; bool isTextureCube() const;
bool isTextureArray() const; bool isTextureArray() const;
bool isBlockFormat() const;
void setNormalFlag(bool b); void setNormalFlag(bool b);
void setHasAlphaFlag(bool b); void setHasAlphaFlag(bool b);
void setUserVersion(int version); void setUserVersion(int version);
void mipmap(Image * img, uint f, uint m);
uint surfaceWidth(uint mipmap) const; uint surfaceWidth(uint mipmap) const;
uint surfaceHeight(uint mipmap) const; uint surfaceHeight(uint mipmap) const;
uint surfaceDepth(uint mipmap) const; uint surfaceDepth(uint mipmap) const;
@ -422,15 +396,35 @@ namespace nv
uint faceSize() const; uint faceSize() const;
uint offset(uint face, uint mipmap); 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; 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 } // nv namespace
#endif // NV_IMAGE_DIRECTDRAWSURFACE_H // Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
// Copyright (c) 2008-2020 -- Ignacio Castano <castano@gmail.com>
//
// 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.

View File

@ -1,8 +1,5 @@
// This code is in the public domain -- castanyo@yahoo.es // This code is in the public domain -- castanyo@yahoo.es
#pragma once #pragma once
#ifndef NV_IMAGE_FILTER_H
#define NV_IMAGE_FILTER_H
#include "nvimage.h" #include "nvimage.h"
#include "nvcore/Debug.h" #include "nvcore/Debug.h"
@ -12,7 +9,7 @@ namespace nv
class Vector4; class Vector4;
/// Base filter class. /// Base filter class.
class NVIMAGE_CLASS Filter class Filter
{ {
public: public:
Filter(float width); Filter(float width);
@ -30,7 +27,7 @@ namespace nv
}; };
// Box filter. // Box filter.
class NVIMAGE_CLASS BoxFilter : public Filter class BoxFilter : public Filter
{ {
public: public:
BoxFilter(); BoxFilter();
@ -39,7 +36,7 @@ namespace nv
}; };
// Triangle (bilinear/tent) filter. // Triangle (bilinear/tent) filter.
class NVIMAGE_CLASS TriangleFilter : public Filter class TriangleFilter : public Filter
{ {
public: public:
TriangleFilter(); TriangleFilter();
@ -48,7 +45,7 @@ namespace nv
}; };
// Quadratic (bell) filter. // Quadratic (bell) filter.
class NVIMAGE_CLASS QuadraticFilter : public Filter class QuadraticFilter : public Filter
{ {
public: public:
QuadraticFilter(); QuadraticFilter();
@ -56,7 +53,7 @@ namespace nv
}; };
// Cubic filter from Thatcher Ulrich. // Cubic filter from Thatcher Ulrich.
class NVIMAGE_CLASS CubicFilter : public Filter class CubicFilter : public Filter
{ {
public: public:
CubicFilter(); CubicFilter();
@ -64,7 +61,7 @@ namespace nv
}; };
// Cubic b-spline filter from Paul Heckbert. // Cubic b-spline filter from Paul Heckbert.
class NVIMAGE_CLASS BSplineFilter : public Filter class BSplineFilter : public Filter
{ {
public: public:
BSplineFilter(); BSplineFilter();
@ -73,7 +70,7 @@ namespace nv
/// Mitchell & Netravali's two-param cubic /// Mitchell & Netravali's two-param cubic
/// @see "Reconstruction Filters in Computer Graphics", SIGGRAPH 88 /// @see "Reconstruction Filters in Computer Graphics", SIGGRAPH 88
class NVIMAGE_CLASS MitchellFilter : public Filter class MitchellFilter : public Filter
{ {
public: public:
MitchellFilter(); MitchellFilter();
@ -87,7 +84,7 @@ namespace nv
}; };
// Lanczos3 filter. // Lanczos3 filter.
class NVIMAGE_CLASS LanczosFilter : public Filter class LanczosFilter : public Filter
{ {
public: public:
LanczosFilter(); LanczosFilter();
@ -95,7 +92,7 @@ namespace nv
}; };
// Sinc filter. // Sinc filter.
class NVIMAGE_CLASS SincFilter : public Filter class SincFilter : public Filter
{ {
public: public:
SincFilter(float w); SincFilter(float w);
@ -103,7 +100,7 @@ namespace nv
}; };
// Kaiser filter. // Kaiser filter.
class NVIMAGE_CLASS KaiserFilter : public Filter class KaiserFilter : public Filter
{ {
public: public:
KaiserFilter(float w); KaiserFilter(float w);
@ -132,7 +129,7 @@ namespace nv
/// A 1D kernel. Used to precompute filter weights. /// A 1D kernel. Used to precompute filter weights.
class NVIMAGE_CLASS Kernel1 class Kernel1
{ {
NV_FORBID_COPY(Kernel1); NV_FORBID_COPY(Kernel1);
public: public:
@ -162,7 +159,7 @@ namespace nv
/// A 2D kernel. /// A 2D kernel.
class NVIMAGE_CLASS Kernel2 class Kernel2
{ {
public: public:
Kernel2(uint width); Kernel2(uint width);
@ -195,7 +192,7 @@ namespace nv
/// A 1D polyphase kernel /// A 1D polyphase kernel
class NVIMAGE_CLASS PolyphaseKernel class PolyphaseKernel
{ {
NV_FORBID_COPY(PolyphaseKernel); NV_FORBID_COPY(PolyphaseKernel);
public: public:
@ -230,5 +227,3 @@ namespace nv
}; };
} // nv namespace } // nv namespace
#endif // NV_IMAGE_FILTER_H

View File

@ -56,9 +56,9 @@ void FloatImage::initFrom(const Image * img)
nvCheck(img != NULL); nvCheck(img != NULL);
uint channel_count = 3; 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 * red_channel = channel(0);
float * green_channel = channel(1); float * green_channel = channel(1);

View File

@ -34,78 +34,78 @@ namespace nv
WrapMode_Mirror WrapMode_Mirror
}; };
NVIMAGE_API FloatImage(); FloatImage();
NVIMAGE_API FloatImage(const FloatImage & img); FloatImage(const FloatImage & img);
NVIMAGE_API FloatImage(const Image * img); FloatImage(const Image * img);
NVIMAGE_API ~FloatImage(); ~FloatImage();
/** @name Conversion. */ /** @name Conversion. */
//@{ //@{
NVIMAGE_API void initFrom(const Image * img); void initFrom(const Image * img);
NVIMAGE_API Image * createImage(uint base_component = 0, uint num = 4) const; Image * createImage(uint base_component = 0, uint num = 4) const;
NVIMAGE_API Image * createImageGammaCorrect(float gamma = 2.2f) const; Image * createImageGammaCorrect(float gamma = 2.2f) const;
//@} //@}
/** @name Allocation. */ /** @name Allocation. */
//@{ //@{
NVIMAGE_API void allocate(uint c, uint w, uint h, uint d = 1); void allocate(uint c, uint w, uint h, uint d = 1);
NVIMAGE_API void free(); // Does not clear members. void free(); // Does not clear members.
NVIMAGE_API void resizeChannelCount(uint c); void resizeChannelCount(uint c);
//@} //@}
/** @name Manipulation. */ /** @name Manipulation. */
//@{ //@{
NVIMAGE_API void clear(float f = 0.0f); void clear(float f = 0.0f);
NVIMAGE_API void clear(uint component, float f = 0.0f); void clear(uint component, float f = 0.0f);
NVIMAGE_API void copyChannel(uint src, uint dst); 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); void packNormals(uint base_component);
NVIMAGE_API void expandNormals(uint base_component); void expandNormals(uint base_component);
NVIMAGE_API void scaleBias(uint base_component, uint num, float scale, float add); 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); void toLinear(uint base_component, uint num, float gamma = 2.2f);
NVIMAGE_API void toGamma(uint base_component, uint num, float gamma = 2.2f); void toGamma(uint base_component, uint num, float gamma = 2.2f);
NVIMAGE_API void exponentiate(uint base_component, uint num, float power); void exponentiate(uint base_component, uint num, float power);
NVIMAGE_API void transform(uint base_component, const Matrix & m, const Vector4 & offset); 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 swizzle(uint base_component, uint r, uint g, uint b, uint a);
NVIMAGE_API FloatImage * fastDownSample() const; FloatImage * fastDownSample() const;
NVIMAGE_API FloatImage * downSample(const Filter & filter, WrapMode wm) const; FloatImage * downSample(const Filter & filter, WrapMode wm) const;
NVIMAGE_API FloatImage * downSample(const Filter & filter, WrapMode wm, uint alpha) const; FloatImage * downSample(const Filter & filter, WrapMode wm, uint alpha) const;
NVIMAGE_API FloatImage * resize(const Filter & filter, uint w, uint h, WrapMode wm) const; 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; 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; 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 * 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; //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, 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; void applyKernelZ(const PolyphaseKernel & k, int x, int y, uint c, uint a, WrapMode wm, float * output) const;
NVIMAGE_API void flipX(); void flipX();
NVIMAGE_API void flipY(); void flipY();
NVIMAGE_API void flipZ(); void flipZ();
NVIMAGE_API float alphaTestCoverage(float alphaRef, int alphaChannel, float alphaScale = 1.0f) const; float alphaTestCoverage(float alphaRef, int alphaChannel, float alphaScale = 1.0f) const;
NVIMAGE_API void scaleAlphaToCoverage(float coverage, float alphaRef, int alphaChannel); void scaleAlphaToCoverage(float coverage, float alphaRef, int alphaChannel);
uint width() const { return m_width; } uint width() const { return m_width; }

View File

@ -15,15 +15,11 @@
using namespace nv; using namespace nv;
Image::Image() : m_width(0), m_height(0), m_format(Format_RGB), m_data(NULL) Image::Image(const Image & img)
{ {
} allocate(img.width, img.height, img.depth);
format = img.format;
Image::Image(const Image & img) : m_data(NULL) memcpy(data, img.data, sizeof(Color32) * width * height * depth);
{
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);
} }
Image::~Image() Image::~Image()
@ -33,28 +29,35 @@ Image::~Image()
const Image & Image::operator=(const Image & img) const Image & Image::operator=(const Image & img)
{ {
allocate(img.m_width, img.m_height, m_depth); allocate(img.width, img.height, depth);
m_format = img.m_format; format = img.format;
memcpy(m_data, img.m_data, sizeof(Color32) * m_width * m_height * m_depth); memcpy(data, img.data, sizeof(Color32) * width * height * depth);
return *this; return *this;
} }
void Image::allocate(uint w, uint h, uint d/*= 1*/) void Image::allocate(uint w, uint h, uint d/*= 1*/)
{ {
m_width = w; width = w;
m_height = h; height = h;
m_depth = d; depth = d;
m_data = realloc<Color32>(m_data, w * h * d); data = realloc<Color32>(data, w * h * d);
} }
void Image::acquire(Color32 * data, uint w, uint h, uint d/*= 1*/) void Image::acquire(Color32 * data, uint w, uint h, uint d/*= 1*/)
{ {
free(); free();
m_width = w; width = w;
m_height = h; height = h;
m_depth = d; depth = d;
m_data = data; data = data;
}
void Image::free()
{
::free(data);
width = height = depth = 0;
data = NULL;
} }
void Image::resize(uint w, uint h, uint d/*= 1*/) { 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. // Copy image.
uint x, y, z; uint x, y, z;
for(z = 0; z < min(d, m_depth); z++) { for(z = 0; z < min(d, depth); z++) {
for(y = 0; y < min(h, m_height); y++) { for(y = 0; y < min(h, height); y++) {
for(x = 0; x < min(w, m_width); x++) { for(x = 0; x < min(w, width); x++) {
img.pixel(x, y, z) = pixel(x, y, z); img.pixel(x, y, z) = pixel(x, y, z);
} }
for(; x < w; x++) { 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(width, img.width);
swap(m_height, img.m_height); swap(height, img.height);
swap(m_depth, img.m_depth); swap(depth, img.depth);
swap(m_format, img.m_format); swap(format, img.format);
swap(m_data, img.m_data); swap(sRGB, img.sRGB);
swap(data, img.data);
} }
bool Image::load(const char * name) bool Image::load(const char * name)
@ -105,106 +109,74 @@ bool Image::load(const char * name)
return false; return false;
} }
swap(m_width, img->m_width); swap(width, img->width);
swap(m_height, img->m_height); swap(height, img->height);
swap(m_depth, img->m_depth); swap(depth, img->depth);
swap(m_format, img->m_format); swap(format, img->format);
swap(m_data, img->m_data); swap(sRGB, img->sRGB);
swap(data, img->data);
return true; 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(); free();
m_data = (Color32 *)data; data = (Color32 *)_data;
m_width = w; width = w;
m_height = h; height = h;
m_depth = d; depth = d;
} }
void Image::unwrap() void Image::unwrap()
{ {
m_data = NULL; data = NULL;
m_width = 0; width = 0;
m_height = 0; height = 0;
m_depth = 0; depth = 0;
} }
void Image::free()
{
::free(m_data);
m_data = NULL;
}
uint Image::width() const
{
return m_width;
}
uint Image::height() const
{
return m_height;
}
uint Image::depth() const
{
return m_depth;
}
const Color32 * Image::scanline(uint h) const const Color32 * Image::scanline(uint h) const
{ {
nvDebugCheck(h < m_height); nvDebugCheck(h < height);
return m_data + h * m_width; return data + h * width;
} }
Color32 * Image::scanline(uint h) Color32 * Image::scanline(uint h)
{ {
nvDebugCheck(h < m_height); nvDebugCheck(h < height);
return m_data + h * m_width; return data + h * width;
} }
const Color32 * Image::pixels() const const Color32 * Image::pixels() const
{ {
return m_data; return data;
} }
Color32 * Image::pixels() Color32 * Image::pixels()
{ {
return m_data; return data;
} }
const Color32 & Image::pixel(uint idx) const const Color32 & Image::pixel(uint idx) const
{ {
nvDebugCheck(idx < m_width * m_height * m_depth); nvDebugCheck(idx < width * height * depth);
return m_data[idx]; return data[idx];
} }
Color32 & Image::pixel(uint idx) Color32 & Image::pixel(uint idx)
{ {
nvDebugCheck(idx < m_width * m_height * m_depth); nvDebugCheck(idx < width * height * depth);
return m_data[idx]; return data[idx];
}
Image::Format Image::format() const
{
return m_format;
}
void Image::setFormat(Image::Format f)
{
m_format = f;
} }
void Image::fill(Color32 c) 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) for (uint i = 0; i < size; ++i)
{ {
m_data[i] = c; data[i] = c;
} }
} }

View File

@ -1,8 +1,5 @@
// This code is in the public domain -- castanyo@yahoo.es // This code is in the public domain -- castanyo@yahoo.es
#pragma once #pragma once
#ifndef NV_IMAGE_IMAGE_H
#define NV_IMAGE_IMAGE_H
#include "nvimage.h" #include "nvimage.h"
#include "nvcore/Debug.h" #include "nvcore/Debug.h"
@ -15,18 +12,17 @@ namespace nv
{ {
class Color32; class Color32;
/// 32 bit RGBA image. // 32 bit ARGB image.
class NVIMAGE_CLASS Image class Image
{ {
public: public:
enum Format enum Format : uint8 {
{ Format_XRGB,
Format_RGB,
Format_ARGB, Format_ARGB,
}; };
Image(); Image() {}
Image(const Image & img); Image(const Image & img);
~Image(); ~Image();
@ -36,16 +32,13 @@ namespace nv
void allocate(uint w, uint h, uint d = 1); void allocate(uint w, uint h, uint d = 1);
void acquire(Color32 * data, uint w, uint h, uint d = 1); void acquire(Color32 * data, uint w, uint h, uint d = 1);
bool load(const char * name); bool load(const char * name);
void free();
void resize(uint w, uint h, uint d = 1); void resize(uint w, uint h, uint d = 1);
void wrap(void * data, uint w, uint h, uint d = 1); void wrap(void * data, uint w, uint h, uint d = 1);
void unwrap(); void unwrap();
uint width() const;
uint height() const;
uint depth() const;
const Color32 * scanline(uint h) const; const Color32 * scanline(uint h) const;
Color32 * scanline(uint h); Color32 * scanline(uint h);
@ -58,36 +51,28 @@ namespace nv
const Color32 & pixel(uint x, uint y, uint z = 0) const; const Color32 & pixel(uint x, uint y, uint z = 0) const;
Color32 & pixel(uint x, uint y, uint z = 0); Color32 & pixel(uint x, uint y, uint z = 0);
Format format() const;
void setFormat(Format f);
void fill(Color32 c); void fill(Color32 c);
private:
void free();
private: uint width = 0;
uint m_width; uint height = 0;
uint m_height; uint depth = 0;
uint m_depth; Format format = Format_XRGB;
Format m_format; bool sRGB = false;
Color32 * m_data; Color32 * data = NULL;
}; };
inline const Color32 & Image::pixel(uint x, uint y, uint z) const inline const Color32 & Image::pixel(uint x, uint y, uint z) const
{ {
nvDebugCheck(x < m_width && y < m_height && z < m_depth); nvDebugCheck(x < width && y < height && z < depth);
return pixel((z * m_height + y) * m_width + x); return pixel((z * height + y) * width + x);
} }
inline Color32 & Image::pixel(uint x, uint y, uint z) inline Color32 & Image::pixel(uint x, uint y, uint z)
{ {
nvDebugCheck(x < m_width && y < m_height && z < m_depth); nvDebugCheck(x < width && y < height && z < depth);
return pixel((z * m_height + y) * m_width + x); return pixel((z * height + y) * width + x);
} }
} // nv namespace } // nv namespace
#endif // NV_IMAGE_IMAGE_H

View File

@ -55,12 +55,15 @@ extern "C" {
#endif #endif
#if defined(NV_HAVE_STBIMAGE) #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 STB_IMAGE_IMPLEMENTATION
# define STBI_NO_STDIO # define STBI_NO_STDIO
# pragma warning(push) # include "stb_image.h"
# pragma warning(disable: 4312)
# include <stb_image.h> //# define STB_IMAGE_WRITE_STATIC
# pragma warning(pop) //# define STB_IMAGE_WRITE_IMPLEMENTATION
//# define STBI_WRITE_NO_STDIO
//# include "stb_image_write.h"
#endif #endif
@ -68,7 +71,7 @@ using namespace nv;
struct Color555 { /*struct Color555 {
uint16 b : 5; uint16 b : 5;
uint16 g : 5; uint16 g : 5;
uint16 r : 5; uint16 r : 5;
@ -198,7 +201,7 @@ static Image * loadTGA(Stream & s)
} }
} }
else if( grey ) { else if( grey ) {
img->setFormat(Image::Format_ARGB); img->format = Image::Format_ARGB;
for( int y = 0; y < tga.height; y++ ) { for( int y = 0; y < tga.height; y++ ) {
for( int x = 0; x < tga.width; x++ ) { for( int x = 0; x < tga.width; x++ ) {
@ -233,7 +236,7 @@ static Image * loadTGA(Stream & s)
} }
} }
else if( tga.pixel_size == 32 ) { 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 y = 0; y < tga.height; y++ ) {
for( int x = 0; x < tga.width; x++ ) { for( int x = 0; x < tga.width; x++ ) {
@ -250,6 +253,7 @@ static Image * loadTGA(Stream & s)
return img.release(); return img.release();
} }
*/
// Save TGA image. // Save TGA image.
static bool saveTGA(Stream & s, const Image * img) 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.x_origin = 0;
tga.head.y_origin = 0; tga.head.y_origin = 0;
tga.head.width = img->width(); tga.head.width = img->width;
tga.head.height = img->height(); tga.head.height = img->height;
if(img->format() == Image::Format_ARGB) { if(img->format == Image::Format_ARGB) {
tga.head.pixel_size = 32; tga.head.pixel_size = 32;
tga.head.flags = TGA_ORIGIN_UPPER | TGA_HAS_ALPHA; tga.head.flags = TGA_ORIGIN_UPPER | TGA_HAS_ALPHA;
} }
@ -283,8 +287,8 @@ static bool saveTGA(Stream & s, const Image * img)
// @@ Serialize directly. // @@ Serialize directly.
tga.allocate(); tga.allocate();
const uint n = img->width() * img->height(); const uint n = img->width * img->height;
if(img->format() == Image::Format_ARGB) { if(img->format == Image::Format_ARGB) {
for(uint i = 0; i < n; i++) { for(uint i = 0; i < n; i++) {
Color32 color = img->pixel(i); Color32 color = img->pixel(i);
tga.mem[4 * i + 0] = color.b; tga.mem[4 * i + 0] = color.b;
@ -309,13 +313,13 @@ static bool saveTGA(Stream & s, const Image * img)
return true; return true;
} }
#pragma optimize("", off) /*#pragma optimize("", off)
// Save BMP image. // Save BMP image.
static bool saveBMP(Stream & s, const Image * img) static bool saveBMP(Stream & s, const Image * img)
{ {
int w = img->width(); int w = img->width;
int h = img->height(); int h = img->height;
int image_size = w * h * 3; int image_size = w * h * 3;
BmpFileHeader header; BmpFileHeader header;
@ -352,7 +356,7 @@ static bool saveBMP(Stream & s, const Image * img)
} }
return true; return true;
} }*/
/*static Image * loadPPM(Stream & s) /*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->depth() != 1) return false;
//if (img->format() == Image::Format_ARGB) return false; //if (img->format() == Image::Format_ARGB) return false;
uint w = img->width(); uint w = img->width;
uint h = img->height(); uint h = img->height;
TextWriter writer(&s); TextWriter writer(&s);
writer.format("P6\n"); writer.format("P6\n");
@ -396,7 +400,7 @@ static bool savePPM(Stream & s, const Image * img)
}*/ }*/
// Load PSD image. // Load PSD image.
static Image * loadPSD(Stream & s) /*static Image * loadPSD(Stream & s)
{ {
nvCheck(!s.isError()); nvCheck(!s.isError());
nvCheck(s.isLoading()); nvCheck(s.isLoading());
@ -457,7 +461,7 @@ static Image * loadPSD(Stream & s)
else else
{ {
// Enable alpha. // Enable alpha.
img->setFormat(Image::Format_ARGB); img->format = Image::Format_ARGB;
// Ignore remaining channels. // Ignore remaining channels.
channel_num = 4; channel_num = 4;
@ -545,7 +549,7 @@ static Image * loadPSD(Stream & s)
} }
return img.release(); return img.release();
} }*/
static FloatImage * loadFloatDDS(Stream & s) static FloatImage * loadFloatDDS(Stream & s)
{ {
@ -1766,7 +1770,7 @@ static Image * loadSTB(Stream & s)
if (data != NULL) { if (data != NULL) {
Image * img = new Image; Image * img = new Image;
img->acquire((Color32 *)data, w, h); 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; int count = w * h;
for (int i = 0; i < count; ++i) { 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); const char * extension = Path::extension(fileName);
if (strCaseDiff(extension, ".tga") == 0) { /*if (strCaseDiff(extension, ".tga") == 0) {
return loadTGA(s); return loadTGA(s);
} }*/
if (strCaseDiff(extension, ".psd") == 0) { /*if (strCaseDiff(extension, ".psd") == 0) {
return loadPSD(s); return loadPSD(s);
} }*/
/*if (strCaseDiff(extension, ".ppm") == 0) { /*if (strCaseDiff(extension, ".ppm") == 0) {
return loadPPM(s); 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); const char * extension = Path::extension(fileName);
if (strCaseDiff(extension, ".bmp") == 0) { /*if (strCaseDiff(extension, ".bmp") == 0) {
return saveBMP(s, img); return saveBMP(s, img);
} }*/
if (strCaseDiff(extension, ".tga") == 0) { if (strCaseDiff(extension, ".tga") == 0) {
return saveTGA(s, img); return saveTGA(s, img);
@ -2030,7 +2034,7 @@ bool nv::ImageIO::saveFloat(const char * fileName, Stream & s, const FloatImage
if (componentCount == 1) if (componentCount == 1)
{ {
Color32 * c = image->pixels(); 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++) for (uint i = 0; i < count; i++)
{ {
c[i].b = c[i].g = c[i].r; 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) if (componentCount == 4)
{ {
image->setFormat(Image::Format_ARGB); image->format = Image::Format_ARGB;
} }
return ImageIO::save(fileName, s, image.ptr()); return ImageIO::save(fileName, s, image.ptr());

View File

@ -1,14 +1,8 @@
// This code is in the public domain -- castanyo@yahoo.es // This code is in the public domain -- castanyo@yahoo.es
#pragma once #pragma once
#ifndef NV_IMAGE_IMAGEIO_H
#define NV_IMAGE_IMAGEIO_H
#include "nvimage.h" #include "nvimage.h"
#include "nvcore/StrLib.h"
namespace nv namespace nv
{ {
class Image; class Image;
@ -17,21 +11,18 @@ namespace nv
namespace ImageIO namespace ImageIO
{ {
NVIMAGE_API Image * load(const char * fileName); Image * load(const char * fileName);
NVIMAGE_API Image * load(const char * fileName, Stream & s); Image * load(const char * fileName, Stream & s);
NVIMAGE_API FloatImage * loadFloat(const char * fileName); FloatImage * loadFloat(const char * fileName);
NVIMAGE_API FloatImage * loadFloat(const char * fileName, Stream & s); FloatImage * loadFloat(const char * fileName, Stream & s);
NVIMAGE_API bool save(const char * fileName, const Image * img, const char ** tags=NULL); // NULL terminated list. 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, Stream & s, const Image * img, const char ** tags=NULL);
NVIMAGE_API bool saveFloat(const char * fileName, const FloatImage * fimage, uint baseComponent, uint componentCount); 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, Stream & s, const FloatImage * fimage, uint baseComponent, uint componentCount);
} // ImageIO namespace } // ImageIO namespace
} // nv namespace } // nv namespace
#endif // NV_IMAGE_IMAGEIO_H

View File

@ -130,7 +130,7 @@ namespace nv
}; };
NVIMAGE_API Stream & operator<< (Stream & s, KtxHeader & header); Stream & operator<< (Stream & s, KtxHeader & header);
/* struct KtxFile { /* struct KtxFile {

View File

@ -43,8 +43,8 @@ static FloatImage * createNormalMap(const Image * img, FloatImage::WrapMode wm,
nvDebugCheck(kdv != NULL); nvDebugCheck(kdv != NULL);
nvDebugCheck(img != NULL); nvDebugCheck(img != NULL);
const uint w = img->width(); const uint w = img->width;
const uint h = img->height(); const uint h = img->height;
AutoPtr<FloatImage> fimage(new FloatImage()); AutoPtr<FloatImage> fimage(new FloatImage());
fimage->allocate(4, w, h); fimage->allocate(4, w, h);

View File

@ -1,32 +1,13 @@
// This code is in the public domain -- castanyo@yahoo.es // This code is in the public domain -- castanyo@yahoo.es
#pragma once #pragma once
#ifndef NV_IMAGE_H
#define NV_IMAGE_H
#include "nvcore/nvcore.h" #include "nvcore/nvcore.h"
#include "nvcore/Debug.h" // nvDebugCheck #include "nvcore/Debug.h" // nvDebugCheck
#include "nvcore/Utils.h" // isPowerOfTwo #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 { namespace nv {
// Some utility functions: // Some utility functions:
inline uint computeBitPitch(uint w, uint bitsize, uint alignmentInBits) inline uint computeBitPitch(uint w, uint bitsize, uint alignmentInBits)
{ {
nvDebugCheck(isPowerOfTwo(alignmentInBits)); nvDebugCheck(isPowerOfTwo(alignmentInBits));
@ -42,7 +23,4 @@ namespace nv {
return (pitch + 7) / 8; return (pitch + 7) / 8;
} }
} // nv namespace } // nv namespace
#endif // NV_IMAGE_H