diff --git a/src/nvimage/BlockDXT.cpp b/src/nvimage/BlockDXT.cpp index 6e185b5..8066f78 100644 --- a/src/nvimage/BlockDXT.cpp +++ b/src/nvimage/BlockDXT.cpp @@ -22,6 +22,7 @@ // OTHER DEALINGS IN THE SOFTWARE. #include +#include // swap #include "ColorBlock.h" #include "BlockDXT.h" diff --git a/src/nvimage/ColorBlock.cpp b/src/nvimage/ColorBlock.cpp index fac8859..c664fb2 100644 --- a/src/nvimage/ColorBlock.cpp +++ b/src/nvimage/ColorBlock.cpp @@ -1,5 +1,6 @@ // This code is in the public domain -- castanyo@yahoo.es +#include // swap #include #include #include diff --git a/src/nvimage/DirectDrawSurface.cpp b/src/nvimage/DirectDrawSurface.cpp index 7bf8575..d63910a 100644 --- a/src/nvimage/DirectDrawSurface.cpp +++ b/src/nvimage/DirectDrawSurface.cpp @@ -1241,8 +1241,23 @@ void DirectDrawSurface::printInfo() const if (header.pf.flags & DDPF_ALPHAPREMULT) printf("\t\tDDPF_ALPHAPREMULT\n"); if (header.pf.flags & DDPF_NORMAL) printf("\t\tDDPF_NORMAL\n"); - printf("\tFourCC: '%c%c%c%c'\n", ((header.pf.fourcc >> 0) & 0xFF), ((header.pf.fourcc >> 8) & 0xFF), ((header.pf.fourcc >> 16) & 0xFF), ((header.pf.fourcc >> 24) & 0xFF)); - printf("\tBit count: %d (0x%.8X)\n", header.pf.bitcount, header.pf.bitcount); + printf("\tFourCC: '%c%c%c%c'\n", + ((header.pf.fourcc >> 0) & 0xFF), + ((header.pf.fourcc >> 8) & 0xFF), + ((header.pf.fourcc >> 16) & 0xFF), + ((header.pf.fourcc >> 24) & 0xFF)); + if ((header.pf.fourcc & DDPF_FOURCC) && (header.pf.bitcount != 0)) + { + printf("\tSwizzle: '%c%c%c%c'\n", + (header.pf.bitcount >> 0) & 0xFF, + (header.pf.bitcount >> 8) & 0xFF, + (header.pf.bitcount >> 16) & 0xFF, + (header.pf.bitcount >> 24) & 0xFF); + } + else + { + printf("\tBit count: %d\n", header.pf.bitcount); + } printf("\tRed mask: 0x%.8X\n", header.pf.rmask); printf("\tGreen mask: 0x%.8X\n", header.pf.gmask); printf("\tBlue mask: 0x%.8X\n", header.pf.bmask); diff --git a/src/nvimage/Filter.h b/src/nvimage/Filter.h index 55171ac..ae762f6 100644 --- a/src/nvimage/Filter.h +++ b/src/nvimage/Filter.h @@ -11,16 +11,16 @@ namespace nv class Vector4; /// Base filter class. - class Filter + class NVIMAGE_CLASS Filter { public: - NVIMAGE_API Filter(float width); - NVIMAGE_API virtual ~Filter(); + Filter(float width); + virtual ~Filter(); - NVIMAGE_API float width() const { return m_width; } - NVIMAGE_API float sampleDelta(float x, float scale) const; - NVIMAGE_API float sampleBox(float x, float scale, int samples) const; - NVIMAGE_API float sampleTriangle(float x, float scale, int samples) const; + float width() const { return m_width; } + float sampleDelta(float x, float scale) const; + float sampleBox(float x, float scale, int samples) const; + float sampleTriangle(float x, float scale, int samples) const; virtual float evaluate(float x) const = 0; @@ -29,56 +29,56 @@ namespace nv }; // Box filter. - class BoxFilter : public Filter + class NVIMAGE_CLASS BoxFilter : public Filter { public: - NVIMAGE_API BoxFilter(); - NVIMAGE_API BoxFilter(float width); - NVIMAGE_API virtual float evaluate(float x) const; + BoxFilter(); + BoxFilter(float width); + virtual float evaluate(float x) const; }; // Triangle (bilinear/tent) filter. - class TriangleFilter : public Filter + class NVIMAGE_CLASS TriangleFilter : public Filter { public: - NVIMAGE_API TriangleFilter(); - NVIMAGE_API TriangleFilter(float width); - NVIMAGE_API virtual float evaluate(float x) const; + TriangleFilter(); + TriangleFilter(float width); + virtual float evaluate(float x) const; }; // Quadratic (bell) filter. - class QuadraticFilter : public Filter + class NVIMAGE_CLASS QuadraticFilter : public Filter { public: - NVIMAGE_API QuadraticFilter(); - NVIMAGE_API virtual float evaluate(float x) const; + QuadraticFilter(); + virtual float evaluate(float x) const; }; // Cubic filter from Thatcher Ulrich. - class CubicFilter : public Filter + class NVIMAGE_CLASS CubicFilter : public Filter { public: - NVIMAGE_API CubicFilter(); - NVIMAGE_API virtual float evaluate(float x) const; + CubicFilter(); + virtual float evaluate(float x) const; }; // Cubic b-spline filter from Paul Heckbert. - class BSplineFilter : public Filter + class NVIMAGE_CLASS BSplineFilter : public Filter { public: - NVIMAGE_API BSplineFilter(); - NVIMAGE_API virtual float evaluate(float x) const; + BSplineFilter(); + virtual float evaluate(float x) const; }; /// Mitchell & Netravali's two-param cubic /// @see "Reconstruction Filters in Computer Graphics", SIGGRAPH 88 - class MitchellFilter : public Filter + class NVIMAGE_CLASS MitchellFilter : public Filter { public: - NVIMAGE_API MitchellFilter(); - NVIMAGE_API virtual float evaluate(float x) const; + MitchellFilter(); + virtual float evaluate(float x) const; - NVIMAGE_API void setParameters(float a, float b); + void setParameters(float a, float b); private: float p0, p2, p3; @@ -86,29 +86,29 @@ namespace nv }; // Lanczos3 filter. - class LanczosFilter : public Filter + class NVIMAGE_CLASS LanczosFilter : public Filter { public: - NVIMAGE_API LanczosFilter(); - NVIMAGE_API virtual float evaluate(float x) const; + LanczosFilter(); + virtual float evaluate(float x) const; }; // Sinc filter. - class SincFilter : public Filter + class NVIMAGE_CLASS SincFilter : public Filter { public: - NVIMAGE_API SincFilter(float w); - NVIMAGE_API virtual float evaluate(float x) const; + SincFilter(float w); + virtual float evaluate(float x) const; }; // Kaiser filter. - class KaiserFilter : public Filter + class NVIMAGE_CLASS KaiserFilter : public Filter { public: - NVIMAGE_API KaiserFilter(float w); - NVIMAGE_API virtual float evaluate(float x) const; + KaiserFilter(float w); + virtual float evaluate(float x) const; - NVIMAGE_API void setParameters(float a, float stretch); + void setParameters(float a, float stretch); private: float alpha; @@ -118,12 +118,12 @@ namespace nv /// A 1D kernel. Used to precompute filter weights. - class Kernel1 + class NVIMAGE_CLASS Kernel1 { NV_FORBID_COPY(Kernel1); public: - NVIMAGE_API Kernel1(const Filter & f, int iscale, int samples = 32); - NVIMAGE_API ~Kernel1(); + Kernel1(const Filter & f, int iscale, int samples = 32); + ~Kernel1(); float valueAt(uint x) const { nvDebugCheck(x < (uint)m_windowSize); @@ -138,7 +138,7 @@ namespace nv return m_width; } - NVIMAGE_API void debugPrint(); + void debugPrint(); private: int m_windowSize; @@ -148,15 +148,15 @@ namespace nv /// A 2D kernel. - class Kernel2 + class NVIMAGE_CLASS Kernel2 { public: - NVIMAGE_API Kernel2(uint width); - NVIMAGE_API Kernel2(const Kernel2 & k); - NVIMAGE_API ~Kernel2(); + Kernel2(uint width); + Kernel2(const Kernel2 & k); + ~Kernel2(); - NVIMAGE_API void normalize(); - NVIMAGE_API void transpose(); + void normalize(); + void transpose(); float valueAt(uint x, uint y) const { return m_data[y * m_windowSize + x]; @@ -166,12 +166,12 @@ namespace nv return m_windowSize; } - NVIMAGE_API void initLaplacian(); - NVIMAGE_API void initEdgeDetection(); - NVIMAGE_API void initSobel(); - NVIMAGE_API void initPrewitt(); + void initLaplacian(); + void initEdgeDetection(); + void initSobel(); + void initPrewitt(); - NVIMAGE_API void initBlendedSobel(const Vector4 & scale); + void initBlendedSobel(const Vector4 & scale); private: const uint m_windowSize; @@ -180,12 +180,12 @@ namespace nv /// A 1D polyphase kernel - class PolyphaseKernel + class NVIMAGE_CLASS PolyphaseKernel { NV_FORBID_COPY(PolyphaseKernel); public: - NVIMAGE_API PolyphaseKernel(const Filter & f, uint srcLength, uint dstLength, int samples = 32); - NVIMAGE_API ~PolyphaseKernel(); + PolyphaseKernel(const Filter & f, uint srcLength, uint dstLength, int samples = 32); + ~PolyphaseKernel(); int windowSize() const { return m_windowSize; @@ -205,7 +205,7 @@ namespace nv return m_data[column * m_windowSize + x]; } - NVIMAGE_API void debugPrint() const; + void debugPrint() const; private: int m_windowSize; diff --git a/src/nvimage/FloatImage.cpp b/src/nvimage/FloatImage.cpp index 75d02a1..8cfb5f7 100644 --- a/src/nvimage/FloatImage.cpp +++ b/src/nvimage/FloatImage.cpp @@ -636,7 +636,7 @@ FloatImage * FloatImage::downSample(const Filter & filter, uint w, uint h, WrapM float * dst_channel = dst_image->channel(c); for (uint x = 0; x < w; x++) { - tmp_image->applyKernelVertical(ykernel, x, c, wm, tmp_column.unsecureBuffer()); + tmp_image->applyKernelVertical(ykernel, x, c, wm, tmp_column.mutableBuffer()); for (uint y = 0; y < h; y++) { dst_channel[y * w + x] = tmp_column[y]; @@ -657,7 +657,7 @@ FloatImage * FloatImage::downSample(const Filter & filter, uint w, uint h, WrapM float * tmp_channel = tmp_image->channel(c); for (uint x = 0; x < w; x++) { - tmp_image->applyKernelVertical(ykernel, x, c, wm, tmp_column.unsecureBuffer()); + tmp_image->applyKernelVertical(ykernel, x, c, wm, tmp_column.mutableBuffer()); for (uint y = 0; y < h; y++) { tmp_channel[y * w + x] = tmp_column[y]; diff --git a/src/nvimage/FloatImage.h b/src/nvimage/FloatImage.h index b51a0d6..4bbdae0 100644 --- a/src/nvimage/FloatImage.h +++ b/src/nvimage/FloatImage.h @@ -3,8 +3,10 @@ #ifndef NV_IMAGE_FLOATIMAGE_H #define NV_IMAGE_FLOATIMAGE_H +#include // abs + #include -#include // clamp +#include // clamp #include namespace nv diff --git a/src/nvimage/Image.cpp b/src/nvimage/Image.cpp index 53c0b5f..d96b0d9 100644 --- a/src/nvimage/Image.cpp +++ b/src/nvimage/Image.cpp @@ -2,6 +2,7 @@ #include #include +#include // swap #include diff --git a/src/nvimage/ImageIO.cpp b/src/nvimage/ImageIO.cpp index 0b24600..0ed979a 100644 --- a/src/nvimage/ImageIO.cpp +++ b/src/nvimage/ImageIO.cpp @@ -162,6 +162,9 @@ FloatImage * nv::ImageIO::loadFloat(const char * fileName, Stream & s) if (strCaseCmp(extension, ".pfm") == 0) { return loadFloatPFM(fileName, s); } + if (strCaseCmp(extension, ".hdr") == 0) { + return loadGridFloat(fileName, s); + } */ return NULL; @@ -794,7 +797,7 @@ Image * nv::ImageIO::loadJPG(Stream & s) // Read the entire file. Array byte_array; byte_array.resize(s.size()); - s.serialize(byte_array.unsecureBuffer(), s.size()); + s.serialize(byte_array.mutableBuffer(), s.size()); jpeg_decompress_struct cinfo; jpeg_error_mgr jerr; @@ -1089,7 +1092,8 @@ namespace virtual void seekg(Imf::Int64 pos) { - m_stream.seek(pos); + nvDebugCheck(pos >= 0 && pos < UINT_MAX); + m_stream.seek((uint)pos); } virtual void clear() @@ -1298,6 +1302,77 @@ bool nv::ImageIO::saveFloatPFM(const char * fileName, const FloatImage * fimage, return true; } +#pragma warning(disable : 4996) + +NVIMAGE_API FloatImage * nv::ImageIO::loadGridFloat(const char * fileName, Stream & s) +{ + nvCheck(s.isLoading()); + nvCheck(!s.isError()); + + Tokenizer parser(&s); + + parser.nextLine(); + + if (parser.token() != "ncols") + { + nvDebug("Failed to find 'ncols' token in file '%s'.\n", fileName); + return NULL; + } + + parser.nextToken(true); + const int nCols = parser.token().toInt(); + + parser.nextToken(true); + if (parser.token() != "nrows") + { + nvDebug("Failed to find 'nrows' token in file '%s'.\n", fileName); + return NULL; + } + + parser.nextToken(true); + const int nRows = parser.token().toInt(); + + /* There's a byte order defined in the header. We could read it. However, here we + just assume that it matches the platform's byte order. + // There is then a bunch of data that we don't care about (lat, long definitions, etc). + for (int i=0; i!=9; ++i) + parser.nextToken(true); + + if (parser.token() != "byteorder") + return NULL; + + parser.nextToken(true); + + const Stream::ByteOrder byteOrder = (parser.token() == "LSBFIRST")? Stream::LittleEndian: Stream::BigEndian; + */ + + // GridFloat comes in two files: an ASCII header which was parsed above (.hdr) and a big blob + // of binary data in a .flt file. + Path dataPath(fileName); + dataPath.stripExtension(); + dataPath.append(".flt"); + + // Open the binary data. + FILE* file = fopen(dataPath.fileName(), "rb"); + if (!file) + { + nvDebug("Failed to find GridFloat blob file '%s' corresponding to '%s'.\n", dataPath.fileName(), fileName); + return NULL; + } + + // Allocate image. + AutoPtr fimage(new FloatImage()); + fimage->allocate(1, nCols, nRows); + + float * channel = fimage->channel(0); + + // The binary blob is defined to be in row-major order, containing IEEE floats. + // So we can just slurp it in. Theoretically, we ought to use the byte order. + const size_t nRead = fread((void*) channel, sizeof(float), nRows * nCols, file); + fclose(file); + + return fimage.release(); +} #endif #if 0 diff --git a/src/nvimage/ImageIO.h b/src/nvimage/ImageIO.h index 0902a5d..8e64093 100644 --- a/src/nvimage/ImageIO.h +++ b/src/nvimage/ImageIO.h @@ -47,10 +47,15 @@ namespace nv NVIMAGE_API bool saveFloatEXR(const char * fileName, const FloatImage * fimage, uint base_component, uint num_components); #endif +/* + NVIMAGE_API FloatImage * loadFloatPFM(const char * fileName, Stream & s); + NVIMAGE_API bool saveFloatPFM(const char * fileName, const FloatImage * fimage, uint base_component, uint num_components); - // NVIMAGE_API FloatImage * loadFloatPFM(const char * fileName, Stream & s); - // NVIMAGE_API bool saveFloatPFM(const char * fileName, const FloatImage * fimage, uint base_component, uint num_components); - + // GridFloat is a simple, open format for terrain elevation data. See http://ned.usgs.gov/Ned/faq.asp. + // Expects: 1) fileName will be an ".hdr" header file, 2) there will also exist a corresponding float data + // blob in a ".flt" file. (This is what USGS gives you.) + NVIMAGE_API FloatImage * loadGridFloat(const char * fileName, Stream & s); +*/ } // ImageIO namespace } // nv namespace diff --git a/src/nvimage/Quantize.cpp b/src/nvimage/Quantize.cpp index 8dd3a67..0f0b075 100644 --- a/src/nvimage/Quantize.cpp +++ b/src/nvimage/Quantize.cpp @@ -12,6 +12,10 @@ http://www.efg2.com/Lab/Library/ImageProcessing/DHALF.TXT @@ This code needs to be reviewed, I'm not sure it's correct. */ +#include // memset + +#include // swap + #include #include