Skip to content
This repository has been archived by the owner on Dec 31, 2020. It is now read-only.

Commit

Permalink
Improved floating point random number generation.
Browse files Browse the repository at this point in the history
Fixed loading RGB images, as reported in issue 15.
Moved pixel format conversion helpers to PixelFormat.h
  • Loading branch information
castano committed Oct 8, 2007
1 parent c9c7c42 commit e7aca55
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 91 deletions.
50 changes: 9 additions & 41 deletions src/nvimage/DirectDrawSurface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <nvimage/ColorBlock.h>
#include <nvimage/Image.h>
#include <nvimage/BlockDXT.h>
#include <nvimage/PixelFormat.h>

#include <string.h> // memset

Expand Down Expand Up @@ -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);
Expand All @@ -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;

Expand All @@ -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;
}
Expand Down
84 changes: 84 additions & 0 deletions src/nvimage/PixelFormat.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <[email protected]>
//
// 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
55 changes: 14 additions & 41 deletions src/nvimage/nvtt/CompressRGB.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <nvcore/Debug.h>

#include <nvimage/Image.h>
#include <nvimage/PixelFormat.h>
#include <nvmath/Color.h>

#include "CompressRGB.h"
Expand Down Expand Up @@ -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


Expand All @@ -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);
Expand All @@ -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;
}
}
}

Expand Down
14 changes: 7 additions & 7 deletions src/nvmath/Montecarlo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ void SampleDistribution::redistributeRandom(const Distribution dist)
// This is the worst method possible!
for(uint i = 0; i < sampleCount; i++)
{
float x = m_rand.getReal();
float y = m_rand.getReal();
float x = m_rand.getFloat();
float y = m_rand.getFloat();

// Map uniform distribution in the square to the (hemi)sphere.
if( dist == Distribution_Uniform ) {
Expand All @@ -53,8 +53,8 @@ void SampleDistribution::redistributeStratified(const Distribution dist)
// Create a uniform distribution of points on the hemisphere with low variance.
for(uint v = 0, i = 0; v < sqrtSampleCount; v++) {
for(uint u = 0; u < sqrtSampleCount; u++, i++) {
float x = (u + m_rand.getReal()) / float(sqrtSampleCount);
float y = (v + m_rand.getReal()) / float(sqrtSampleCount);
float x = (u + m_rand.getFloat()) / float(sqrtSampleCount);
float y = (v + m_rand.getFloat()) / float(sqrtSampleCount);

// Map uniform distribution in the square to the (hemi)sphere.
if( dist == Distribution_Uniform ) {
Expand Down Expand Up @@ -82,7 +82,7 @@ void SampleDistribution::multiStageNRooks(const int size, int* cells)
int size2 = size >> 1;

if (size & 1) {
if (m_rand.getReal() > 0.5) {
if (m_rand.getFloat() > 0.5) {
size1++;
}
else {
Expand Down Expand Up @@ -138,8 +138,8 @@ void SampleDistribution::redistributeNRook(const Distribution dist)

for(uint i = 0; i < sampleCount; i++)
{
float x = (i + m_rand.getReal()) / sampleCount;
float y = (cells[i] + m_rand.getReal()) / sampleCount;
float x = (i + m_rand.getFloat()) / sampleCount;
float y = (cells[i] + m_rand.getFloat()) / sampleCount;

// Map uniform distribution in the square to the (hemi)sphere.
if( dist == Distribution_Uniform ) {
Expand Down
19 changes: 17 additions & 2 deletions src/nvmath/Random.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,20 @@ class Rand
return n;
}

/// Random number on [0.0, 1.0] interval.
float getFloat()
{
union
{
uint32 i;
float f;
} pun;

pun.i = 0x3f800000UL | (get() & 0x007fffffUL);
return pun.f - 1.0f;
}

/*
/// Random number on [0.0, 1.0] interval.
double getReal()
{
Expand All @@ -45,7 +59,8 @@ class Rand
double getRealExclusive()
{
return double(get()) * (1.0/4294967296.0); // 2^32
}
}
*/

/// Get the max value of the random number.
uint max() const { return 4294967295U; }
Expand Down Expand Up @@ -301,7 +316,7 @@ class Rand48 : public Rand
}

/** Get a random number. */
virtual uint Get() {
virtual uint get() {

advance();

Expand Down

0 comments on commit e7aca55

Please sign in to comment.