Sync with perforce repository.

Several bugfixes in nvcore.
Add imgdiff to cmakefiles and fix compilation errors on linux.
2.0
castano 17 years ago
parent 9fe9f6cc7a
commit cf1d93ebf4

@ -34,10 +34,10 @@ Do not use memmove in insert & remove, use copy ctors instead.
#define NV_FOREACH(i, container) \ #define NV_FOREACH(i, container) \
typedef typeof(container) NV_STRING_JOIN2(cont,__LINE__); \ typedef typeof(container) NV_STRING_JOIN2(cont,__LINE__); \
for(NV_STRING_JOIN2(cont,__LINE__)::PseudoIndex i((container).start()); (container).isDone(i); (container).advance(i)) for(NV_STRING_JOIN2(cont,__LINE__)::PseudoIndex i((container).start()); !(container).isDone(i); (container).advance(i))
/* /*
#define NV_FOREACH(i, container) \ #define NV_FOREACH(i, container) \
for(typename typeof(container)::PseudoIndex i((container).start()); (container).isDone(i); (container).advance(i)) for(typename typeof(container)::PseudoIndex i((container).start()); !(container).isDone(i); (container).advance(i))
*/ */
#else // If typeof not available: #else // If typeof not available:
@ -61,7 +61,7 @@ struct PseudoIndexWrapper {
}; };
#define NV_FOREACH(i, container) \ #define NV_FOREACH(i, container) \
for(PseudoIndexWrapper i(container); (container).isDone(i(&(container))); (container).advance(i(&(container)))) for(PseudoIndexWrapper i(container); !(container).isDone(i(&(container))); (container).advance(i(&(container))))
#endif #endif
@ -145,7 +145,7 @@ namespace nv
template <typename T> template <typename T>
void deleteAll(T & container) void deleteAll(T & container)
{ {
for(typename T::PseudoIndex i = container.start(); container.isDone(i); container.advance(i)) for(typename T::PseudoIndex i = container.start(); !container.isDone(i); container.advance(i))
{ {
delete container[i]; delete container[i];
} }
@ -272,14 +272,19 @@ namespace nv
/// Push an element at the end of the vector. /// Push an element at the end of the vector.
void push_back( const T & val ) void push_back( const T & val )
{ {
// DO NOT pass elements of your own vector into uint new_size = m_size + 1;
// push_back()! Since we're using references,
// resize() may munge the element storage! if (new_size > m_buffer_size)
nvDebugCheck( &val < &m_buffer[0] || &val > &m_buffer[m_size] ); {
const T copy(val); // create a copy in case value is inside of this array.
int new_size = m_size + 1; resize(new_size);
resize( new_size ); m_buffer[new_size-1] = copy;
m_buffer[new_size-1] = val; }
else
{
m_size = new_size;
m_buffer[new_size-1] = val;
}
} }
void pushBack( const T & val ) void pushBack( const T & val )
{ {
@ -364,7 +369,7 @@ namespace nv
/// Remove the first instance of the given element. /// Remove the first instance of the given element.
void remove(const T & element) void remove(const T & element)
{ {
for(PseudoIndex i = start(); isDone(i); advance(i)) { for(PseudoIndex i = start(); !isDone(i); advance(i)) {
removeAt(i); removeAt(i);
break; break;
} }
@ -560,8 +565,8 @@ namespace nv
typedef uint PseudoIndex; typedef uint PseudoIndex;
PseudoIndex start() const { return 0; } PseudoIndex start() const { return 0; }
bool isDone(const PseudoIndex & i) const { return i < this->m_size; }; bool isDone(const PseudoIndex & i) const { nvDebugCheck(i <= this->m_size); return i == this->m_size; };
void advance(PseudoIndex & i) const { i++; } void advance(PseudoIndex & i) const { nvDebugCheck(i <= this->m_size); i++; }
#if NV_CC_MSVC #if NV_CC_MSVC
T & operator[]( const PseudoIndexWrapper & i ) { T & operator[]( const PseudoIndexWrapper & i ) {
@ -642,7 +647,7 @@ namespace nv
~HashMap() { clear(); } ~HashMap() { clear(); }
/** Set a new or existing value under the key, to the value. */ /// Set a new or existing value under the key, to the value.
void set(const T& key, const U& value) void set(const T& key, const U& value)
{ {
int index = findIndex(key); int index = findIndex(key);
@ -657,7 +662,7 @@ namespace nv
} }
/** Add a new value to the hash table, under the specified key. */ /// Add a new value to the hash table, under the specified key.
void add(const T& key, const U& value) void add(const T& key, const U& value)
{ {
nvCheck(findIndex(key) == -1); nvCheck(findIndex(key) == -1);
@ -732,7 +737,7 @@ namespace nv
} }
/** Remove the first value under the specified key. */ /// Remove the first value under the specified key.
bool remove(const T& key) bool remove(const T& key)
{ {
if (table == NULL) if (table == NULL)
@ -767,7 +772,7 @@ namespace nv
} }
/** Remove all entries from the hash table. */ /// Remove all entries from the hash table.
void clear() void clear()
{ {
if (table != NULL) if (table != NULL)
@ -789,25 +794,24 @@ namespace nv
} }
/** Returns true if the hash is empty. */ /// Returns true if the hash is empty.
bool isEmpty() const bool isEmpty() const
{ {
return table == NULL || entry_count == 0; return table == NULL || entry_count == 0;
} }
/** /** Retrieve the value under the given key.
* Retrieve the value under the given key. *
* * If there's no value under the key, then return false and leave
* If there's no value under the key, then return false and leave * *value alone.
* *value alone. *
* * If there is a value, return true, and set *value to the entry's
* If there is a value, return true, and set *value to the entry's * value.
* value. *
* * If value == NULL, return true or false according to the
* If value == NULL, return true or false according to the * presence of the key, but don't touch *value.
* presence of the key, but don't touch *value. */
*/
bool get(const T& key, U* value = NULL) const bool get(const T& key, U* value = NULL) const
{ {
int index = findIndex(key); int index = findIndex(key);
@ -821,6 +825,7 @@ namespace nv
return false; return false;
} }
/// Determine if the given key is contained in the hash.
bool contains(const T & key) const bool contains(const T & key) const
{ {
return get(key); return get(key);
@ -856,7 +861,7 @@ namespace nv
} }
/** Hint the bucket count to >= n. */ /// Hint the bucket count to >= n.
void resize(int n) void resize(int n)
{ {
// Not really sure what this means in relation to // Not really sure what this means in relation to
@ -881,7 +886,7 @@ namespace nv
setRawCapacity(new_raw_size); setRawCapacity(new_raw_size);
} }
/** Behaves much like std::pair. */ /// Behaves much like std::pair.
struct Entry struct Entry
{ {
int next_in_chain; // internal chaining for collisions int next_in_chain; // internal chaining for collisions
@ -910,11 +915,11 @@ namespace nv
}; };
/** HashMap enumerator. */ // HashMap enumerator.
typedef int PseudoIndex; typedef int PseudoIndex;
PseudoIndex start() const { PseudoIndex i = 0; findNext(i); return i; } PseudoIndex start() const { PseudoIndex i = 0; findNext(i); return i; }
bool isDone(const PseudoIndex & i) const { return i <= size_mask; }; bool isDone(const PseudoIndex & i) const { nvDebugCheck(i <= size_mask+1); return i == size_mask+1; };
void advance(PseudoIndex & i) const { i++; findNext(i); } void advance(PseudoIndex & i) const { nvDebugCheck(i <= size_mask+1); i++; findNext(i); }
#if NV_CC_GNUC #if NV_CC_GNUC
Entry & operator[]( const PseudoIndex & i ) { Entry & operator[]( const PseudoIndex & i ) {
@ -936,7 +941,7 @@ namespace nv
private: private:
/** Find the index of the matching entry. If no match, then return -1. */ // Find the index of the matching entry. If no match, then return -1.
int findIndex(const T& key) const int findIndex(const T& key) const
{ {
if (table == NULL) return -1; if (table == NULL) return -1;
@ -987,11 +992,11 @@ namespace nv
/** /**
* Resize the hash table to the given size (Rehash the * Resize the hash table to the given size (Rehash the
* contents of the current table). The arg is the number of * contents of the current table). The arg is the number of
* hash table entries, not the number of elements we should * hash table entries, not the number of elements we should
* actually contain (which will be less than this). * actually contain (which will be less than this).
*/ */
void setRawCapacity(int new_size) void setRawCapacity(int new_size)
{ {
if (new_size <= 0) { if (new_size <= 0) {
@ -1041,7 +1046,7 @@ namespace nv
new_hash.table = NULL; new_hash.table = NULL;
} }
/** Move the enumerator to the next valid element. */ // Move the enumerator to the next valid element.
void findNext(PseudoIndex & i) const { void findNext(PseudoIndex & i) const {
while (i <= size_mask && E(i).isEmpty()) { while (i <= size_mask && E(i).isEmpty()) {
i++; i++;

@ -102,6 +102,18 @@ void nv::strCpy(char * dst, int size, const char * src)
#endif #endif
} }
void nv::strCpy(char * dst, int size, const char * src, int len)
{
nvDebugCheck(dst != NULL);
nvDebugCheck(src != NULL);
#if NV_CC_MSVC && _MSC_VER >= 1400
strncpy_s(dst, size, src, len);
#else
NV_UNUSED(size);
strncpy(dst, src, len);
#endif
}
void nv::strCat(char * dst, int size, const char * src) void nv::strCat(char * dst, int size, const char * src)
{ {
nvDebugCheck(dst != NULL); nvDebugCheck(dst != NULL);

@ -32,6 +32,7 @@ namespace nv
NVCORE_API int strCaseCmp(const char * s1, const char * s2) NV_PURE; NVCORE_API int strCaseCmp(const char * s1, const char * s2) NV_PURE;
NVCORE_API int strCmp(const char * s1, const char * s2) NV_PURE; NVCORE_API int strCmp(const char * s1, const char * s2) NV_PURE;
NVCORE_API void strCpy(char * dst, int size, const char * src); NVCORE_API void strCpy(char * dst, int size, const char * src);
NVCORE_API void strCpy(char * dst, int size, const char * src, int len);
NVCORE_API void strCat(char * dst, int size, const char * src); NVCORE_API void strCat(char * dst, int size, const char * src);
NVCORE_API bool strMatch(const char * str, const char * pat) NV_PURE; NVCORE_API bool strMatch(const char * str, const char * pat) NV_PURE;
@ -327,7 +328,10 @@ namespace nv
setRefCount( 0 ); setRefCount( 0 );
// Copy string. // Copy string.
strCpy(const_cast<char *>(data), len + 1, str); strCpy(const_cast<char *>(data), len+1, str, len);
// Add terminating character.
const_cast<char *>(data)[len] = '\0';
} }
NVCORE_API void setString(const char * str); NVCORE_API void setString(const char * str);

@ -27,12 +27,13 @@ char TextReader::read()
{ {
nvDebugCheck(m_stream != NULL); nvDebugCheck(m_stream != NULL);
char c;
m_stream->serialize(&c, 1);
if( m_stream->isAtEnd() ) { if( m_stream->isAtEnd() ) {
return 0; return 0;
} }
char c;
m_stream->serialize(&c, 1);
return c; return c;
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -752,44 +752,57 @@ FloatImage * nv::ImageIO::loadFloatTIFF(const char * fileName)
return NULL; return NULL;
} }
::uint16 spp, bpp; ::uint16 spp, bpp, format;
::uint32 width, height; ::uint32 width, height;
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height); TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height);
TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width); TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width);
TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bpp); TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bpp);
TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &spp); TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &spp);
TIFFGetField(tif, TIFFTAG_SAMPLEFORMAT, &format);
if (spp != 1 || (bpp != 8 && bpp != 16 && bpp != 32)) { if (bpp != 8 && bpp != 16 && bpp != 32) {
nvDebug("Can't load '%s', only 1 sample per pixel supported\n", fileName); nvDebug("Can't load '%s', only 1 sample per pixel supported\n", fileName);
TIFFClose(tif); TIFFClose(tif);
return NULL; return NULL;
} }
FloatImage * fimage = new FloatImage(); AutoPtr<FloatImage> fimage(new FloatImage());
fimage->allocate(spp, width, height); fimage->allocate(spp, width, height);
int linesize = TIFFScanlineSize(tif); int linesize = TIFFScanlineSize(tif);
tdata_t buf = (::uint8 *)nv::mem::malloc(linesize); tdata_t buf = (::uint8 *)nv::mem::malloc(linesize);
for (uint y = 0; y < height; y++) { for (uint y = 0; y < height; y++)
{
TIFFReadScanline(tif, buf, y, 0); TIFFReadScanline(tif, buf, y, 0);
float * dst = fimage->scanline(y, 0); for (uint c=0; c<spp; c++ )
{
if (bpp == 8) { float * dst = fimage->scanline(y, c);
for(uint x = 0; x < width; x++) {
dst[x] = float(((::uint8 *)buf)[x]) / float(0xFF); for(uint x = 0; x < width; x++)
} {
} if (bpp == 8)
else if (bpp == 16) { {
for(uint x = 0; x < width; x++) { dst[x] = float(((::uint8 *)buf)[x*spp+c]) / float(0xFF);
dst[x] = float(((::uint16 *)buf)[x]) / float(0xFFFF); }
} else if (bpp == 16)
} {
else /*if (bpp == 32)*/ { dst[x] = float(((::uint16 *)buf)[x*spp+c]) / float(0xFFFF);
// Mantissa has only 24 bits, so drop 8 bits. }
for(uint x = 0; x < width; x++) { else if (bpp == 32)
dst[x] = float(((::uint32 *)buf)[x] >> 8) / float(0xFFFFFF); {
if (format==SAMPLEFORMAT_IEEEFP)
{
dst[x] = float(((float *)buf)[x*spp+c]);
}
else
{
dst[x] = float(((::uint32 *)buf)[x*spp+c] >> 8) / float(0xFFFFFF);
}
}
} }
} }
} }
@ -798,9 +811,63 @@ FloatImage * nv::ImageIO::loadFloatTIFF(const char * fileName)
TIFFClose(tif); TIFFClose(tif);
return fimage; return fimage.release();
} }
bool nv::ImageIO::saveFloatTIFF(const char * fileName, FloatImage *fimage)
{
int iW=fimage->width();
int iH=fimage->height();
int iC=fimage->componentNum();
TIFF * image = TIFFOpen(fileName, "w");
// Open the TIFF file
if (image == NULL)
{
nvDebug("Could not open '%s' for writing\n", fileName);
return false;
}
TIFFSetField(image, TIFFTAG_IMAGEWIDTH, iW);
TIFFSetField(image, TIFFTAG_IMAGELENGTH, iH);
TIFFSetField(image, TIFFTAG_SAMPLESPERPIXEL, iC);
TIFFSetField(image, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP);
TIFFSetField(image, TIFFTAG_BITSPERSAMPLE, 32);
uint32 rowsperstrip = TIFFDefaultStripSize(image, -1);
TIFFSetField(image, TIFFTAG_ROWSPERSTRIP, rowsperstrip);
TIFFSetField(image, TIFFTAG_COMPRESSION, COMPRESSION_PACKBITS);
TIFFSetField(image, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
TIFFSetField(image, TIFFTAG_ROWSPERSTRIP, -1L);
TIFFSetField(image, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
float *scanline = new float[iW * iC];
for (int y=0; y<iH; y++)
{
for (int c=0; c<iC; c++)
{
float *src = fimage->scanline(y, c);
for (int x=0; x<iW; x++) scanline[x*iC+c]=src[x];
}
if (TIFFWriteScanline(image, scanline, y, 0)==-1)
{
nvDebug("Error writing scanline %d\n", y);
return -1;
}
}
delete [] scanline;
// Close the file
TIFFClose(image);
return true;
}
#endif #endif
#if 0 #if 0

@ -31,8 +31,9 @@ namespace nv
#endif #endif
#if defined(HAVE_TIFF) #if defined(HAVE_TIFF)
// Hack! // Hacks!
NVIMAGE_API FloatImage * loadFloatTIFF(const char * fileName); NVIMAGE_API FloatImage * loadFloatTIFF(const char * fileName);
NVIMAGE_API bool saveFloatTIFF(const char * fileName, FloatImage *fimage);
NVIMAGE_API FloatImage * loadFloatTIFF(Stream & s); NVIMAGE_API FloatImage * loadFloatTIFF(Stream & s);
#endif #endif

@ -52,6 +52,9 @@ TARGET_LINK_LIBRARIES(nvdecompress nvcore nvmath nvimage)
ADD_EXECUTABLE(nvddsinfo tools/ddsinfo.cpp) ADD_EXECUTABLE(nvddsinfo tools/ddsinfo.cpp)
TARGET_LINK_LIBRARIES(nvddsinfo nvcore nvmath nvimage) TARGET_LINK_LIBRARIES(nvddsinfo nvcore nvmath nvimage)
INSTALL(TARGETS nvcompress nvdecompress nvddsinfo DESTINATION bin) ADD_EXECUTABLE(nvimgdiff tools/imgdiff.cpp)
TARGET_LINK_LIBRARIES(nvimgdiff nvcore nvmath nvimage)
INSTALL(TARGETS nvcompress nvdecompress nvddsinfo nvimgdiff DESTINATION bin)

@ -35,7 +35,6 @@
#include "cmdline.h" #include "cmdline.h"
static bool loadImage(nv::Image & image, const char * fileName) static bool loadImage(nv::Image & image, const char * fileName)
{ {
if (nv::strCaseCmp(nv::Path::extension(fileName), ".dds") == 0) if (nv::strCaseCmp(nv::Path::extension(fileName), ".dds") == 0)
@ -77,7 +76,7 @@ struct Error
{ {
samples++; samples++;
mabse += fabs(e); mabse += fabs(e);
maxabse = nv::max(maxabse, fabs(e)); maxabse = nv::max(maxabse, fabsf(e));
mse += e * e; mse += e * e;
} }

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save