More cleanups. Assume static linking.
This commit is contained in:
parent
7f9c87713a
commit
adce1a00da
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
@ -1,25 +1,4 @@
|
||||
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.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.
|
||||
// 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,331 +1242,6 @@ void DirectDrawSurface::setUserVersion(int 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)
|
||||
{
|
||||
for (uint m = 0; m < mipmap; m++) {
|
||||
@ -1554,7 +1299,7 @@ uint DirectDrawSurface::faceSize() const
|
||||
return size;
|
||||
}
|
||||
|
||||
uint DirectDrawSurface::offset(const uint face, const uint mipmap)
|
||||
uint DirectDrawSurface::offset(uint face, uint mipmap)
|
||||
{
|
||||
uint size = 128; // sizeof(DDSHeader);
|
||||
|
||||
@ -1576,6 +1321,17 @@ uint DirectDrawSurface::offset(const uint face, const uint mipmap)
|
||||
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
|
||||
{
|
||||
@ -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.
|
||||
|
@ -1,29 +1,5 @@
|
||||
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.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.
|
||||
|
||||
// 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 <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.
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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; }
|
||||
|
@ -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<Color32>(m_data, w * h * d);
|
||||
width = w;
|
||||
height = h;
|
||||
depth = d;
|
||||
data = realloc<Color32>(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;
|
||||
data = NULL;
|
||||
width = 0;
|
||||
height = 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
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 <stb_image.h>
|
||||
# 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());
|
||||
|
@ -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
|
||||
|
@ -130,7 +130,7 @@ namespace nv
|
||||
|
||||
};
|
||||
|
||||
NVIMAGE_API Stream & operator<< (Stream & s, KtxHeader & header);
|
||||
Stream & operator<< (Stream & s, KtxHeader & header);
|
||||
|
||||
|
||||
/* struct KtxFile {
|
||||
|
@ -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<FloatImage> fimage(new FloatImage());
|
||||
fimage->allocate(4, w, 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
|
||||
|
Loading…
Reference in New Issue
Block a user