diff --git a/src/nvimage/DirectDrawSurface.cpp b/src/nvimage/DirectDrawSurface.cpp index 4bf0f21..d597979 100644 --- a/src/nvimage/DirectDrawSurface.cpp +++ b/src/nvimage/DirectDrawSurface.cpp @@ -765,12 +765,37 @@ void DirectDrawSurface::mipmap(Image * img, uint face, uint mipmap) } } -static uint8 bitExpand(uint8 c, uint bits) +// @@ Move this code to format conversion!! +namespace { - int shifts = 0; - uint8 output = c; - // @@ TODO!!! - + static uint convert(uint c, uint inbits, uint outbits) + { + if (inbits <= outbits) + { + // truncate + return c >> (inbits - outbits); + } + else + { + // bitexpand + return (c << (outbits - inbits)) | convert(c, inbits, outbits - inbits); + } + } + + static void maskShiftAndSize(uint mask, uint * shift, uint * size) + { + *shift = 0; + while((mask & 1) == 0) { + ++(*shift); + mask >>= 1; + } + + *size = 0; + while((mask & 1) == 1) { + ++(*size); + mask >>= 1; + } + } } void DirectDrawSurface::readLinearImage(Image * img) @@ -778,7 +803,45 @@ void DirectDrawSurface::readLinearImage(Image * img) nvDebugCheck(stream != NULL); nvDebugCheck(img != NULL); - // @@ Read linear RGB images. + const uint w = img->width(); + const uint h = img->height(); + + uint rshift, rsize; + maskShiftAndSize(header.pf.rmask, &rshift, &rsize); + + uint gshift, gsize; + maskShiftAndSize(header.pf.gmask, &gshift, &gsize); + + uint bshift, bsize; + maskShiftAndSize(header.pf.bmask, &bshift, &bsize); + + uint ashift, asize; + maskShiftAndSize(header.pf.amask, &ashift, &asize); + + uint byteCount = (header.pf.bitcount + 7) / 8; + + if (header.pf.amask != 0) + { + img->setFormat(Image::Format_ARGB); + } + + // Read linear RGB images. + 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 = convert(c >> rshift, rsize, 8); + pixel.g = convert(c >> gshift, gsize, 8); + pixel.b = convert(c >> bshift, bsize, 8); + pixel.a = convert(c >> ashift, asize, 8); + + img->pixel(x, y) = pixel; + } + } } void DirectDrawSurface::readBlockImage(Image * img) diff --git a/src/nvimage/ImageIO.cpp b/src/nvimage/ImageIO.cpp index 1a8e625..a117282 100644 --- a/src/nvimage/ImageIO.cpp +++ b/src/nvimage/ImageIO.cpp @@ -284,7 +284,7 @@ bool nv::ImageIO::saveTGA(Stream & s, const Image * img) tga.head.height = img->height(); if(img->format() == Image::Format_ARGB) { tga.head.pixel_size = 32; - tga.head.flags = TGA_ORIGIN_UPPER; + tga.head.flags = TGA_ORIGIN_UPPER | TGA_HAS_ALPHA; } else { tga.head.pixel_size = 24; diff --git a/src/nvimage/TgaFile.h b/src/nvimage/TgaFile.h index 86d0a51..bdbfce5 100644 --- a/src/nvimage/TgaFile.h +++ b/src/nvimage/TgaFile.h @@ -29,6 +29,8 @@ enum TGAType { #define TGA_ORIGIN_LOWER 0x00 #define TGA_ORIGIN_UPPER 0x20 +#define TGA_HAS_ALPHA 0x0F + /// Tga Header. struct TgaHeader { diff --git a/src/nvimage/nvtt/CompressRGB.cpp b/src/nvimage/nvtt/CompressRGB.cpp index d9afd49..c10d0f1 100644 --- a/src/nvimage/nvtt/CompressRGB.cpp +++ b/src/nvimage/nvtt/CompressRGB.cpp @@ -145,6 +145,7 @@ void nv::compressRGB(const Image * image, const OutputOptions & outputOptions, c c |= convert(src[x].b, 8, bsize) << bshift; c |= convert(src[x].a, 8, asize) << ashift; + // @@ This is wrong, this pixels overlaps with the previous one! *(uint *)(dst + x * byteCount) = c; } }