Merge changes from the witness.

This commit is contained in:
castano
2014-11-04 17:49:29 +00:00
parent 4cb60cc5ba
commit d019cd7080
86 changed files with 3534 additions and 882 deletions

View File

@ -138,9 +138,9 @@ uint BlockDXT1::evaluatePaletteNV5x(Color32 color_array[4]) const
color_array[2].a = 0xFF;
// Set all components to 0 to match DXT specs.
color_array[3].r = 0x00; // color_array[2].r;
color_array[3].g = 0x00; // color_array[2].g;
color_array[3].b = 0x00; // color_array[2].b;
color_array[3].r = 0x00;
color_array[3].g = 0x00;
color_array[3].b = 0x00;
color_array[3].a = 0x00;
return 3;
@ -167,9 +167,9 @@ void BlockDXT1::evaluatePalette3(Color32 color_array[4], bool d3d9) const
color_array[2].a = 0xFF;
// Set all components to 0 to match DXT specs.
color_array[3].r = 0x00; // color_array[2].r;
color_array[3].g = 0x00; // color_array[2].g;
color_array[3].b = 0x00; // color_array[2].b;
color_array[3].r = 0x00;
color_array[3].g = 0x00;
color_array[3].b = 0x00;
color_array[3].a = 0x00;
}
@ -433,6 +433,22 @@ void AlphaBlockDXT5::decodeBlock(ColorBlock * block, bool d3d9/*= false*/) const
}
}
void AlphaBlockDXT5::decodeBlock(AlphaBlock4x4 * block, bool d3d9/*= false*/) const
{
nvDebugCheck(block != NULL);
uint8 alpha_array[8];
evaluatePalette(alpha_array, d3d9);
uint8 index_array[16];
indices(index_array);
for(uint i = 0; i < 16; i++) {
block->alpha[i] = alpha_array[index_array[i]];
}
}
void AlphaBlockDXT5::flip4()
{
uint64 * b = (uint64 *)this;

View File

@ -32,7 +32,8 @@
namespace nv
{
struct ColorBlock;
struct ColorSet;
struct ColorSet;
struct AlphaBlock4x4;
class Stream;
@ -152,6 +153,7 @@ namespace nv
void setIndex(uint index, uint value);
void decodeBlock(ColorBlock * block, bool d3d9 = false) const;
void decodeBlock(AlphaBlock4x4 * block, bool d3d9 = false) const;
void flip4();
void flip2();

View File

@ -6,6 +6,8 @@
#include "nvmath/Box.h"
#include "nvmath/Vector.inl"
#include "nvmath/ftoi.h"
#include "nvcore/Utils.h" // swap
#include <string.h> // memcpy
@ -519,11 +521,24 @@ void ColorSet::setColors(const float * data, uint img_w, uint img_h, uint img_x,
}
}
void ColorSet::setColors(const Vector3 colors[16], const float weights[16])
{
}
void ColorSet::setColors(const Vector4 colors[16], const float weights[16])
{
}
void ColorSet::setAlphaWeights()
{
for (uint i = 0; i < colorCount; i++)
{
weights[i] = max(colors[i].w, 0.001f); // Avoid division by zero.
//weights[i] = max(colors[i].w, 0.001f); // Avoid division by zero.
weights[i] = max(colors[i].w, 0.0f);
}
}
@ -539,6 +554,7 @@ void ColorSet::setUniformWeights()
// @@ Handle complex blocks (not 4x4).
void ColorSet::createMinimalSet(bool ignoreTransparent)
{
nvDebugCheck(indexCount == 16);
nvDebugCheck(colorCount <= 16);
Vector4 C[16];
@ -556,7 +572,7 @@ void ColorSet::createMinimalSet(bool ignoreTransparent)
Vector4 ci = C[indices[i]];
float wi = W[indices[i]];
if (ignoreTransparent && ci.w == 0) {
if (ignoreTransparent && wi == 0) {
indices[i] = -1;
continue;
}
@ -582,9 +598,10 @@ void ColorSet::createMinimalSet(bool ignoreTransparent)
n++;
}
}
nvDebugCheck(n != 0);
//nvDebugCheck(n != 0); // Fully transparent blocks are OK.
for (uint i = n; i < colorCount; i++) {
colors[i] = Vector4(0);
weights[i] = 0;
}
@ -594,6 +611,8 @@ void ColorSet::createMinimalSet(bool ignoreTransparent)
if (colorCount == 0) {
colorCount = 1;
indices[0] = 0;
//colors[0] = Vector4(0);
weights[0] = 1;
}
}
@ -661,3 +680,59 @@ bool ColorSet::hasAlpha() const
}
return false;
}
void AlphaBlock4x4::init(uint8 a)
{
for (int i = 0; i < 16; i++) {
alpha[i] = a;
weights[i] = 1.0f;
}
}
void AlphaBlock4x4::init(const ColorBlock & src, uint channel)
{
nvCheck(channel >= 0 && channel < 4);
// Colors are in BGRA format.
if (channel == 0) channel = 2;
else if (channel == 2) channel = 0;
for (int i = 0; i < 16; i++) {
alpha[i] = src.color(i).component[channel];
weights[i] = 1.0f;
}
}
void AlphaBlock4x4::init(const ColorSet & src, uint channel)
{
nvCheck(channel >= 0 && channel < 4);
for (int i = 0; i < 16; i++) {
float f = src.color(i).component[channel];
alpha[i] = unitFloatToFixed8(f);
weights[i] = 1.0f;
}
}
void AlphaBlock4x4::initMaxRGB(const ColorSet & src, float threshold)
{
for (int i = 0; i < 16; i++) {
float x = src.color(i).x;
float y = src.color(i).y;
float z = src.color(i).z;
alpha[i] = unitFloatToFixed8(max(max(x, y), max(z, threshold)));
weights[i] = 1.0f;
}
}
void AlphaBlock4x4::initWeights(const ColorSet & src)
{
for (int i = 0; i < 16; i++) {
weights[i] = src.weight(i);
}
}

View File

@ -12,6 +12,7 @@ namespace nv
class Image;
class FloatImage;
/// Uncompressed 4x4 color block.
struct ColorBlock
{
@ -89,6 +90,8 @@ namespace nv
void allocate(uint w, uint h);
void setColors(const float * data, uint img_w, uint img_h, uint img_x, uint img_y);
void setColors(const Vector3 colors[16], const float weights[16]);
void setColors(const Vector4 colors[16], const float weights[16]);
void setAlphaWeights();
void setUniformWeights();
@ -108,6 +111,8 @@ namespace nv
Vector4 color(uint i) const { nvDebugCheck(i < indexCount); return colors[indices[i]]; }
Vector4 & color(uint i) { nvDebugCheck(i < indexCount); return colors[indices[i]]; }
float weight(uint i) const { nvDebugCheck(i < indexCount); return weights[indices[i]]; }
bool isValidIndex(uint i) const { return i < indexCount && indices[i] >= 0; }
uint colorCount;
@ -116,10 +121,40 @@ namespace nv
// Allocate color set dynamically and add support for sets larger than 4x4.
Vector4 colors[16];
float weights[16];
float weights[16]; // @@ Add mask to indicate what color components are weighted?
int indices[16];
};
/// Uncompressed 4x4 alpha block.
struct AlphaBlock4x4
{
void init(uint8 value);
void init(const ColorBlock & src, uint channel);
void init(const ColorSet & src, uint channel);
void initMaxRGB(const ColorSet & src, float threshold);
void initWeights(const ColorSet & src);
uint8 alpha[4*4];
float weights[16];
};
struct FloatAlphaBlock4x4
{
float alphas[4 * 4];
float weights[4 * 4];
};
struct FloatColorBlock4x4
{
Vector4 colors[4 * 4];
float weights[4 * 4];
};
} // nv namespace
#endif // NV_IMAGE_COLORBLOCK_H

View File

@ -1,12 +1,11 @@
// This code is in the public domain -- jim@tilander.org
#include <nvcore/nvcore.h>
#include <nvmath/Color.h>
#include <nvimage/Image.h>
#include "ColorSpace.h"
#include "nvimage/Image.h"
#include "nvmath/Color.h"
namespace nv
{
void ColorSpace::RGBtoYCoCg_R(Image* img)

View File

@ -952,7 +952,8 @@ bool DirectDrawSurface::isSupported() const
header.header10.dxgiFormat == DXGI_FORMAT_BC3_UNORM ||
header.header10.dxgiFormat == DXGI_FORMAT_BC4_UNORM ||
header.header10.dxgiFormat == DXGI_FORMAT_BC5_UNORM ||
header.header10.dxgiFormat == DXGI_FORMAT_BC6H_UF16)
header.header10.dxgiFormat == DXGI_FORMAT_BC6H_UF16 ||
header.header10.dxgiFormat == DXGI_FORMAT_BC7_UNORM)
{
return true;
}
@ -1390,37 +1391,37 @@ void DirectDrawSurface::readBlock(ColorBlock * rgba)
*stream << block;
block.decodeBlock(rgba);
}
else if (header.hasDX10Header() && header.header10.dxgiFormat == DXGI_FORMAT_BC6H_UF16)
{
BlockBC6 block;
*stream << block;
ColorSet set;
block.decodeBlock(&set);
else if (header.hasDX10Header() && header.header10.dxgiFormat == DXGI_FORMAT_BC6H_UF16)
{
BlockBC6 block;
*stream << block;
ColorSet set;
block.decodeBlock(&set);
// 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 = set.colors[y*4 + x];
rgba->color(x, y).setRGBA(
uint8(clamp(px.x, 0.0f, 1.0f) * 255.0f + 0.5f),
uint8(clamp(px.y, 0.0f, 1.0f) * 255.0f + 0.5f),
uint8(clamp(px.z, 0.0f, 1.0f) * 255.0f + 0.5f),
uint8(clamp(px.w, 0.0f, 1.0f) * 255.0f + 0.5f));
}
}
}
// 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 = set.colors[y*4 + x];
rgba->color(x, y).setRGBA(
uint8(clamp(px.x, 0.0f, 1.0f) * 255.0f + 0.5f),
uint8(clamp(px.y, 0.0f, 1.0f) * 255.0f + 0.5f),
uint8(clamp(px.z, 0.0f, 1.0f) * 255.0f + 0.5f),
uint8(clamp(px.w, 0.0f, 1.0f) * 255.0f + 0.5f));
}
}
}
else if (header.hasDX10Header() && header.header10.dxgiFormat == DXGI_FORMAT_BC7_UNORM)
{
BlockBC7 block;
*stream << block;
block.decodeBlock(rgba);
}
else
{
nvDebugCheck(false);
}
else
{
nvDebugCheck(false);
}
// If normal flag set, convert to normal.
if (header.pf.flags & DDPF_NORMAL)

View File

@ -7,6 +7,7 @@
#include "nvmath/Color.h"
#include "nvmath/Vector.inl"
#include "nvmath/Matrix.inl"
#include "nvmath/ftoi.h"
#include "nvcore/Utils.h" // max
#include "nvcore/Ptr.h"

View File

@ -40,7 +40,7 @@ const Image & Image::operator=(const Image & img)
}
void Image::allocate(uint w, uint h, uint d)
void Image::allocate(uint w, uint h, uint d/*= 1*/)
{
free();
m_width = w;
@ -49,6 +49,45 @@ void Image::allocate(uint w, uint h, uint d)
m_data = realloc<Color32>(m_data, w * h * d);
}
void Image::resize(uint w, uint h, uint d/*= 1*/) {
Image img;
img.allocate(w, h, d);
Color32 background(0,0,0,0);
// 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++) {
img.pixel(x, y, z) = pixel(x, y, z);
}
for(; x < w; x++) {
img.pixel(x, y, z) = background;
}
}
for(; y < h; y++) {
for(x = 0; x < w; x++) {
img.pixel(x, y, z) = background;
}
}
}
for(; z < d; z++) {
for(y = 0; y < h; y++) {
for(x = 0; x < w; x++) {
img.pixel(x, y, z) = background;
}
}
}
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);
}
bool Image::load(const char * name)
{
free();

View File

@ -32,6 +32,8 @@ namespace nv
void allocate(uint w, uint h, uint d = 1);
bool load(const char * name);
void resize(uint w, uint h, uint d = 1);
void wrap(void * data, uint w, uint h, uint d = 1);
void unwrap();

View File

@ -319,9 +319,9 @@ static bool savePPM(Stream & s, const Image * img)
uint h = img->height();
TextWriter writer(&s);
writer.write("P6\n");
writer.write("%d %d\n", w, h);
writer.write("255\n");
writer.format("P6\n");
writer.format("%d %d\n", w, h);
writer.writeString("255\n");
for (uint i = 0; i < w * h; i++) {
Color32 c = img->pixel(i);
s << c.r << c.g << c.b;
@ -501,14 +501,16 @@ static FloatImage * loadFloatDDS(Stream & s)
DDSHeader header;
s << header;
static const uint D3DFMT_A16B16G16R16F = 113;
// @@ We only support a few formats for now.
// @@ We only support RGBA16F for now.
if (header.pf.fourcc == D3DFMT_A16B16G16R16F) {
const int size = header.width * header.height;
uint16 * const data = new uint16[size * 4];
s.serialize(data, size * 4 * sizeof(uint16));
//s.serialize(data, size * 4 * sizeof(uint16));
for (int i = 0; i < 4* size; i++) {
s << data[i];
}
FloatImage * img = new FloatImage;
img->allocate(4, header.width, header.height);
@ -530,7 +532,84 @@ static FloatImage * loadFloatDDS(Stream & s)
return img;
}
else if (header.pf.fourcc == D3DFMT_R32F) {
const int size = header.width * header.height;
float * const data = new float[size];
for (int i = 0; i < size; i++) {
s << data[i];
}
FloatImage * img = new FloatImage;
img->allocate(4, header.width, header.height);
float * r = img->channel(0);
float * ptr = data;
for (int i = 0; i < size; i++) {
*r++ = *ptr++;
}
delete [] data;
img->clear(1, 0.0f);
img->clear(2, 0.0f);
img->clear(3, 1.0f);
return img;
}
else if (header.pf.fourcc == D3DFMT_L16 || (header.pf.bitcount == 16 && header.pf.rmask == 0xFFFF && header.pf.gmask == 0 && header.pf.bmask == 0 && header.pf.amask == 0))
{
const int size = header.width * header.height;
uint16 * const data = new uint16[size];
for (int i = 0; i < size; i++) {
s << data[i];
}
FloatImage * img = new FloatImage;
img->allocate(4, header.width, header.height);
float * r = img->channel(0);
uint16 * ptr = data;
for (int i = 0; i < size; i++) {
*r++ = float(*ptr++) / 65535.0f;
}
delete [] data;
img->clear(1, 0.0f);
img->clear(2, 0.0f);
img->clear(3, 1.0f);
return img;
}
else if (header.pf.fourcc == D3DFMT_L8 || (header.pf.bitcount == 8 && header.pf.rmask == 0xFF && header.pf.gmask == 0 && header.pf.bmask == 0 && header.pf.amask == 0))
{
const int size = header.width * header.height;
uint8 * const data = new uint8[size];
s.serialize(data, size);
FloatImage * img = new FloatImage;
img->allocate(4, header.width, header.height);
float * r = img->channel(0);
uint8 * ptr = data;
for (int i = 0; i < size; i++) {
*r++ = float(*ptr++) / 255.0f;
}
delete [] data;
img->clear(1, 0.0f);
img->clear(2, 0.0f);
img->clear(3, 1.0f);
return img;
}
return NULL;
}
@ -1713,26 +1792,26 @@ Image * nv::ImageIO::load(const char * fileName, Stream & s)
const char * extension = Path::extension(fileName);
if (strCaseCmp(extension, ".tga") == 0) {
if (strCaseDiff(extension, ".tga") == 0) {
return loadTGA(s);
}
if (strCaseCmp(extension, ".psd") == 0) {
if (strCaseDiff(extension, ".psd") == 0) {
return loadPSD(s);
}
/*if (strCaseCmp(extension, ".ppm") == 0) {
/*if (strCaseDiff(extension, ".ppm") == 0) {
return loadPPM(s);
}*/
#if defined(HAVE_JPEG)
if (strCaseCmp(extension, ".jpg") == 0 || strCaseCmp(extension, ".jpeg") == 0) {
if (strCaseDiff(extension, ".jpg") == 0 || strCaseDiff(extension, ".jpeg") == 0) {
return loadJPG(s);
}
#endif
#if defined(HAVE_PNG)
if (strCaseCmp(extension, ".png") == 0) {
if (strCaseDiff(extension, ".png") == 0) {
return loadPNG(s);
}
#endif
@ -1759,16 +1838,16 @@ bool nv::ImageIO::save(const char * fileName, Stream & s, const Image * img, con
const char * extension = Path::extension(fileName);
if (strCaseCmp(extension, ".tga") == 0) {
if (strCaseDiff(extension, ".tga") == 0) {
return saveTGA(s, img);
}
if (strCaseCmp(extension, ".ppm") == 0) {
if (strCaseDiff(extension, ".ppm") == 0) {
return savePPM(s, img);
}
#if defined(HAVE_PNG)
if (strCaseCmp(extension, ".png") == 0) {
if (strCaseDiff(extension, ".png") == 0) {
return savePNG(s, img, tags);
}
#endif
@ -1816,20 +1895,20 @@ FloatImage * nv::ImageIO::loadFloat(const char * fileName, Stream & s)
const char * extension = Path::extension(fileName);
/*if (strCaseCmp(extension, ".pfm") == 0) {
/*if (strCaseDiff(extension, ".pfm") == 0) {
return loadFloatPFM(s);
}*/
#if defined(HAVE_TIFF)
#pragma NV_MESSAGE("TODO: Load TIFF from stream.")
if (strCaseCmp(extension, ".tif") == 0 || strCaseCmp(extension, ".tiff") == 0) {
if (strCaseDiff(extension, ".tif") == 0 || strCaseDiff(extension, ".tiff") == 0) {
return loadFloatTIFF(fileName, s);
}
#endif
#if defined(HAVE_OPENEXR)
#pragma NV_MESSAGE("TODO: Load EXR from stream.")
if (strCaseCmp(extension, ".exr") == 0) {
if (strCaseDiff(extension, ".exr") == 0) {
return loadFloatEXR(fileName, s);
}
#endif
@ -1841,7 +1920,7 @@ FloatImage * nv::ImageIO::loadFloat(const char * fileName, Stream & s)
}
#endif
if (strCaseCmp(extension, ".dds") == 0) {
if (strCaseDiff(extension, ".dds") == 0) {
const uint spos = s.tell(); // Save stream position.
FloatImage * floatImage = loadFloatDDS(s);
if (floatImage != NULL) return floatImage;
@ -1868,11 +1947,11 @@ bool nv::ImageIO::saveFloat(const char * fileName, Stream & s, const FloatImage
const char * extension = Path::extension(fileName);
if (strCaseCmp(extension, ".dds") == 0) {
if (strCaseDiff(extension, ".dds") == 0) {
return saveFloatDDS(s, fimage, baseComponent, componentCount);
}
/*if (strCaseCmp(extension, ".pfm") == 0) {
/*if (strCaseDiff(extension, ".pfm") == 0) {
return saveFloatPFM(s, fimage, baseComponent, componentCount);
}*/
@ -1922,13 +2001,13 @@ bool nv::ImageIO::saveFloat(const char * fileName, const FloatImage * fimage, ui
const char * extension = Path::extension(fileName);
#if defined(HAVE_OPENEXR)
if (strCaseCmp(extension, ".exr") == 0) {
if (strCaseDiff(extension, ".exr") == 0) {
return saveFloatEXR(fileName, fimage, baseComponent, componentCount);
}
#endif
#if defined(HAVE_TIFF)
if (strCaseCmp(extension, ".tif") == 0 || strCaseCmp(extension, ".tiff") == 0) {
if (strCaseDiff(extension, ".tif") == 0 || strCaseDiff(extension, ".tiff") == 0) {
return saveFloatTIFF(fileName, fimage, baseComponent, componentCount);
}
#endif