Improved floating point random number generation.

Fixed loading RGB images, as reported in issue 15.
Moved pixel format conversion helpers to PixelFormat.h
This commit is contained in:
castano
2007-10-08 00:56:58 +00:00
parent c9c7c42d2b
commit e7aca55ba3
5 changed files with 131 additions and 91 deletions

View File

@ -29,6 +29,7 @@
#include <nvimage/ColorBlock.h>
#include <nvimage/Image.h>
#include <nvimage/BlockDXT.h>
#include <nvimage/PixelFormat.h>
#include <string.h> // memset
@ -765,39 +766,6 @@ void DirectDrawSurface::mipmap(Image * img, uint face, uint mipmap)
}
}
// @@ Move this code to format conversion!!
namespace
{
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)
{
nvDebugCheck(stream != NULL);
@ -807,16 +775,16 @@ void DirectDrawSurface::readLinearImage(Image * img)
const uint h = img->height();
uint rshift, rsize;
maskShiftAndSize(header.pf.rmask, &rshift, &rsize);
PixelFormat::maskShiftAndSize(header.pf.rmask, &rshift, &rsize);
uint gshift, gsize;
maskShiftAndSize(header.pf.gmask, &gshift, &gsize);
PixelFormat::maskShiftAndSize(header.pf.gmask, &gshift, &gsize);
uint bshift, bsize;
maskShiftAndSize(header.pf.bmask, &bshift, &bsize);
PixelFormat::maskShiftAndSize(header.pf.bmask, &bshift, &bsize);
uint ashift, asize;
maskShiftAndSize(header.pf.amask, &ashift, &asize);
PixelFormat::maskShiftAndSize(header.pf.amask, &ashift, &asize);
uint byteCount = (header.pf.bitcount + 7) / 8;
@ -834,10 +802,10 @@ void DirectDrawSurface::readLinearImage(Image * img)
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);
pixel.r = PixelFormat::convert(c >> rshift, rsize, 8);
pixel.g = PixelFormat::convert(c >> gshift, gsize, 8);
pixel.b = PixelFormat::convert(c >> bshift, bsize, 8);
pixel.a = PixelFormat::convert(c >> ashift, asize, 8);
img->pixel(x, y) = pixel;
}

84
src/nvimage/PixelFormat.h Normal file
View File

@ -0,0 +1,84 @@
// 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.
#ifndef NV_IMAGE_PIXELFORMAT_H
#define NV_IMAGE_PIXELFORMAT_H
#include <nvimage.h>
// @@ Move this code to format conversion!!
namespace nv
{
namespace PixelFormat
{
// Convert component @a c having @a inbits to the returned value having @a outbits.
inline uint convert(uint c, uint inbits, uint outbits)
{
if (inbits == 0)
{
return 0;
}
else if (inbits >= outbits)
{
// truncate
return c >> (inbits - outbits);
}
else
{
// bitexpand
return (c << (outbits - inbits)) | convert(c, inbits, outbits - inbits);
}
}
// Get pixel component shift and size given its mask.
static void maskShiftAndSize(uint mask, uint * shift, uint * size)
{
if (!mask)
{
*shift = 0;
*size = 0;
return;
}
*shift = 0;
while((mask & 1) == 0) {
++(*shift);
mask >>= 1;
}
*size = 0;
while((mask & 1) == 1) {
++(*size);
mask >>= 1;
}
}
} // PixelFormat namespace
} // nv namespace
#endif // NV_IMAGE_PIXELFORMAT_H

View File

@ -24,6 +24,7 @@
#include <nvcore/Debug.h>
#include <nvimage/Image.h>
#include <nvimage/PixelFormat.h>
#include <nvmath/Color.h>
#include "CompressRGB.h"
@ -54,35 +55,6 @@ namespace
memcpy(dst, src, 4 * w);
}
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;
}
}
} // namespace
@ -101,21 +73,19 @@ void nv::compressRGB(const Image * image, const OutputOptions & outputOptions, c
const uint rmask = compressionOptions.rmask;
uint rshift, rsize;
maskShiftAndSize(rmask, &rshift, &rsize);
PixelFormat::maskShiftAndSize(rmask, &rshift, &rsize);
const uint gmask = compressionOptions.gmask;
uint gshift, gsize;
maskShiftAndSize(gmask, &gshift, &gsize);
PixelFormat::maskShiftAndSize(gmask, &gshift, &gsize);
const uint bmask = compressionOptions.bmask;
uint bshift, bsize;
maskShiftAndSize(bmask, &bshift, &bsize);
PixelFormat::maskShiftAndSize(bmask, &bshift, &bsize);
const uint amask = compressionOptions.amask;
uint ashift, asize;
maskShiftAndSize(amask, &ashift, &asize);
// @@ Perform error diffusion dithering.
PixelFormat::maskShiftAndSize(amask, &ashift, &asize);
// Determine pitch.
uint pitch = computePitch(w, compressionOptions.bitcount);
@ -140,13 +110,16 @@ void nv::compressRGB(const Image * image, const OutputOptions & outputOptions, c
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;
c |= PixelFormat::convert(src[x].r, 8, rsize) << rshift;
c |= PixelFormat::convert(src[x].g, 8, gsize) << gshift;
c |= PixelFormat::convert(src[x].b, 8, bsize) << bshift;
c |= PixelFormat::convert(src[x].a, 8, asize) << ashift;
// @@ This is wrong, this pixels overlaps with the previous one!
*(uint *)(dst + x * byteCount) = c;
// Output one byte at a time. @@ Not tested... Does this work on LE and BE?
for (int i = 0; i < byteCount; i++)
{
*(dst + x * byteCount) = (c >> (i * 8)) & 0xFF;
}
}
}