Add support for arbitrary rgb pixel formats.

2.0
castano 17 years ago
parent f420ee365c
commit 1cdcea3164

@ -53,7 +53,7 @@ namespace
static const uint FOURCC_ATI1 = MAKEFOURCC('A', 'T', 'I', '1');
static const uint FOURCC_ATI2 = MAKEFOURCC('A', 'T', 'I', '2');
// RGB formats.
// 32 bit RGB formats.
static const uint D3DFMT_R8G8B8 = 20;
static const uint D3DFMT_A8R8G8B8 = 21;
static const uint D3DFMT_X8R8G8B8 = 22;
@ -70,6 +70,7 @@ namespace
static const uint D3DFMT_X8B8G8R8 = 33;
static const uint D3DFMT_G16R16 = 34;
static const uint D3DFMT_A2R10G10B10 = 35;
static const uint D3DFMT_A16B16G16R16 = 36;
// Palette formats.
@ -80,6 +81,7 @@ namespace
static const uint D3DFMT_L8 = 50;
static const uint D3DFMT_A8L8 = 51;
static const uint D3DFMT_A4L4 = 52;
static const uint D3DFMT_L16 = 81;
// Floating point formats
static const uint D3DFMT_R16F = 111;
@ -167,8 +169,62 @@ namespace nv
s << header.notused;
return s;
}
struct FormatDescriptor
{
uint format;
uint bitcount;
uint rmask;
uint gmask;
uint bmask;
uint amask;
};
FormatDescriptor s_d3dFormats[] =
{
{ D3DFMT_R8G8B8, 24, 0xFF0000, 0xFF00, 0xFF, 0 },
{ D3DFMT_A8R8G8B8, 32, 0xFF0000, 0xFF00, 0xFF, 0xFF000000 }, // DXGI_FORMAT_B8G8R8A8_UNORM
{ D3DFMT_X8R8G8B8, 32, 0xFF0000, 0xFF00, 0xFF, 0 }, // DXGI_FORMAT_B8G8R8X8_UNORM
{ D3DFMT_R5G6B5, 16, 0xF800, 0x7E0, 0x1F, 0 }, // DXGI_FORMAT_B5G6R5_UNORM
{ D3DFMT_X1R5G5B5, 16, 0x7C00, 0x3E0, 0x1F, 0 },
{ D3DFMT_A1R5G5B5, 16, 0x7C00, 0x3E0, 0x1F, 0x8000 }, // DXGI_FORMAT_B5G5R5A1_UNORM
{ D3DFMT_A4R4G4B4, 16, 0xF00, 0xF0, 0xF, 0xF000 },
{ D3DFMT_R3G3B2, 8, 0xE0, 0x1C, 0x3, 0 },
{ D3DFMT_A8, 8, 0, 0, 0, 8 }, // DXGI_FORMAT_A8_UNORM
{ D3DFMT_A8R3G3B2, 16, 0xE0, 0x1C, 0x3, 0xFF00 },
{ D3DFMT_X4R4G4B4, 16, 0xF00, 0xF0, 0xF, 0 },
{ D3DFMT_A2B10G10R10, 32, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000 }, // DXGI_FORMAT_R10G10B10A2
{ D3DFMT_A8B8G8R8, 32, 0xFF, 0xFF00, 0xFF0000, 0xFF000000 }, // DXGI_FORMAT_R8G8B8A8_UNORM
{ D3DFMT_X8B8G8R8, 32, 0xFF, 0xFF00, 0xFF0000, 0 },
{ D3DFMT_G16R16, 32, 0xFFFF, 0xFFFF0000, 0, 0 }, // DXGI_FORMAT_R16G16_UNORM
{ D3DFMT_A2R10G10B10, 32, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000 },
{ D3DFMT_L8, 8, 8, 0, 0, 0 }, // DXGI_FORMAT_R8_UNORM
{ D3DFMT_L16, 16, 16, 0, 0, 0 }, // DXGI_FORMAT_R16_UNORM
};
const uint s_d3dFormatCount = sizeof(s_d3dFormats) / sizeof(s_d3dFormats[0]);
static uint findD3DFormat(uint bitcount, uint rmask, uint gmask, uint bmask, uint amask)
{
for (int i = 0; i < s_d3dFormatCount; i++)
{
if (s_d3dFormats[i].bitcount == bitcount &&
s_d3dFormats[i].rmask == rmask &&
s_d3dFormats[i].gmask == gmask &&
s_d3dFormats[i].bmask == bmask &&
s_d3dFormats[i].amask == amask)
{
return s_d3dFormats[i].format;
}
}
return 0;
}
}
DDSHeader::DDSHeader()
{
this->fourcc = FOURCC_DDS;
@ -307,10 +363,17 @@ void DDSHeader::setPixelFormat(uint bitcount, uint rmask, uint gmask, uint bmask
bitcount++;
total >>= 1;
}
// @@ Align to 8?
}
this->pf.fourcc = 0;
nvCheck(bitcount > 0 && bitcount <= 32);
// Align to 8.
if (bitcount < 8) bitcount = 8;
else if (bitcount < 16) bitcount = 16;
else if (bitcount < 24) bitcount = 24;
else bitcount = 32;
this->pf.fourcc = findD3DFormat(bitcount, rmask, gmask, bmask, amask);
this->pf.bitcount = bitcount;
this->pf.rmask = rmask;
this->pf.gmask = gmask;

@ -21,9 +21,10 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
#include <string.h>
#include <nvcore/Debug.h>
#include <nvimage/Image.h>
#include <nvmath/Color.h>
#include "CompressRGB.h"
#include "CompressionOptions.h"
@ -43,42 +44,41 @@ namespace
return ((p + 3) / 4) * 4;
}
static void convert_to_rgba8888(void * src, void * dst, uint w)
{
// @@ TODO
}
static void convert_to_bgra8888(const void * src, void * dst, uint w)
static void convert_to_a8r8g8b8(const void * src, void * dst, uint w)
{
memcpy(dst, src, 4 * w);
}
static void convert_to_rgb888(const void * src, void * dst, uint w)
static void convert_to_x8r8g8b8(const void * src, void * dst, uint w)
{
// @@ TODO
memcpy(dst, src, 4 * w);
}
static uint truncate(uint c, uint inbits, uint outbits)
static uint convert(uint c, uint inbits, uint outbits)
{
nvDebugCheck(inbits > outbits);
c >>= inbits - outbits;
if (inbits <= outbits)
{
// truncate
return c >> (inbits - outbits);
}
else
{
// bitexpand
return (c << (outbits - inbits)) | convert(c, inbits, outbits - inbits);
}
}
static uint bitexpand(uint c, uint inbits, uint outbits)
static void maskShiftAndSize(uint mask, uint * shift, uint * size)
{
// @@ TODO
}
static void maskShiftAndSize(uint mask, uint & shift, uint & size)
{
shift = 0;
*shift = 0;
while((mask & 1) == 0) {
shift++;
*shift++;
mask >>= 1;
}
*size = 0;
while((mask & 1) == 1) {
size++;
*size++;
mask >>= 1;
}
}
@ -94,52 +94,63 @@ void nv::compressRGB(const Image * image, const OutputOptions & outputOptions, c
const uint w = image->width();
const uint h = image->height();
const uint bitCount = compressionOptions.bitcount;
nvCheck(bitCount == 8 || bitCount == 16 || bitCount == 24 || bitCount == 32);
const uint byteCount = bitCount / 8;
const uint rmask = compressionOptions.rmask;
uint rshift, rsize;
maskShiftAndSize(compressionOptions.rmask, rshift, rsize);
maskShiftAndSize(rmask, &rshift, &rsize);
const uint gmask = compressionOptions.gmask;
uint gshift, gsize;
maskShiftAndSize(compressionOptions.gmask, gshift, gsize);
maskShiftAndSize(gmask, &gshift, &gsize);
const uint bmask = compressionOptions.bmask;
uint bshift, bsize;
maskShiftAndSize(compressionOptions.bmask, bshift, bsize);
maskShiftAndSize(bmask, &bshift, &bsize);
const uint amask = compressionOptions.amask;
uint ashift, asize;
maskShiftAndSize(compressionOptions.amask, ashift, asize);
maskShiftAndSize(amask, &ashift, &asize);
// @@ Perform error diffusion dithering.
// Determine pitch.
uint pitch = computePitch(w, compressionOptions.bitcount);
void * dst = malloc(pitch);
void * dst = mem::malloc(pitch);
for (uint y = 0; y < h; y++)
{
const Color32 * src = image->scanline(y);
convert_to_bgra8888(src, dst, w);
if (false)
if (bitCount == 32 && rmask == 0xFF0000 && gmask == 0xFF00 && bmask == 0xFF && amask == 0xFF000000)
{
// uint c = 0;
// c |= (src[i].r >> (8 - rsize)) << rshift;
// c |= (src[i].g >> (8 - gsize)) << gshift;
// c |= (src[i].b >> (8 - bsize)) << bshift;
convert_to_a8r8g8b8(src, dst, w);
}
/*
if (rmask == 0xFF000000 && gmask == 0xFF0000 && bmask == 0xFF00 && amask == 0xFF)
else if (bitCount == 32 && rmask == 0xFF0000 && gmask == 0xFF00 && bmask == 0xFF && amask == 0)
{
convert_to_rgba8888(src, dst, w);
}
else if (rmask == 0xFF0000 && gmask == 0xFF00 && bmask == 0xFF && amask == 0)
{
convert_to_rgb888(src, dst, w);
convert_to_x8r8g8b8(src, dst, w);
}
else
{
// @@ Not supported.
// Generic pixel format conversion.
for (uint x = 0; x < w; x++)
{
uint c = 0;
c |= convert(src[x].r, 8, rsize) << rshift;
c |= convert(src[x].g, 8, gsize) << gshift;
c |= convert(src[x].b, 8, bsize) << bshift;
c |= convert(src[x].a, 8, asize) << ashift;
*(uint *)dst = c;
++src;
dst = (uint8 *)dst + byteCount;
}
}
*/
if (outputOptions.outputHandler != NULL)
{
@ -147,7 +158,6 @@ void nv::compressRGB(const Image * image, const OutputOptions & outputOptions, c
}
}
free(dst);
mem::free(dst);
}

Loading…
Cancel
Save