Blame IlmImfTest/testConversion.cpp

Packit 0d464f
//////////////////////////////////////////////////////////////////////////////
Packit 0d464f
//
Packit 0d464f
// Copyright (c) 2003-2012, Industrial Light & Magic, a division of Lucasfilm
Packit 0d464f
// Entertainment Company Ltd.  Portions contributed and copyright held by
Packit 0d464f
// others as indicated.  All rights reserved.
Packit 0d464f
//
Packit 0d464f
// Redistribution and use in source and binary forms, with or without
Packit 0d464f
// modification, are permitted provided that the following conditions are
Packit 0d464f
// met:
Packit 0d464f
//
Packit 0d464f
//     * Redistributions of source code must retain the above
Packit 0d464f
//       copyright notice, this list of conditions and the following
Packit 0d464f
//       disclaimer.
Packit 0d464f
//
Packit 0d464f
//     * Redistributions in binary form must reproduce the above
Packit 0d464f
//       copyright notice, this list of conditions and the following
Packit 0d464f
//       disclaimer in the documentation and/or other materials provided with
Packit 0d464f
//       the distribution.
Packit 0d464f
//
Packit 0d464f
//     * Neither the name of Industrial Light & Magic nor the names of
Packit 0d464f
//       any other contributors to this software may be used to endorse or
Packit 0d464f
//       promote products derived from this software without specific prior
Packit 0d464f
//       written permission.
Packit 0d464f
//
Packit 0d464f
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
Packit 0d464f
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
Packit 0d464f
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
Packit 0d464f
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
Packit 0d464f
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
Packit 0d464f
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
Packit 0d464f
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
Packit 0d464f
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
Packit 0d464f
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
Packit 0d464f
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
Packit 0d464f
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit 0d464f
//
Packit 0d464f
//////////////////////////////////////////////////////////////////////////////
Packit 0d464f
Packit 0d464f
Packit 0d464f
#include <ImfOutputFile.h>
Packit 0d464f
#include <ImfInputFile.h>
Packit 0d464f
#include <ImfTiledOutputFile.h>
Packit 0d464f
#include <ImfTiledInputFile.h>
Packit 0d464f
#include <ImfChannelList.h>
Packit 0d464f
#include <ImfArray.h>
Packit 0d464f
#include <ImfConvert.h>
Packit 0d464f
#include <half.h>
Packit 0d464f
#include "compareFloat.h"
Packit 0d464f
Packit 0d464f
#include <stdio.h>
Packit 0d464f
#include <assert.h>
Packit 0d464f
Packit 0d464f
Packit 0d464f
namespace IMF = OPENEXR_IMF_NAMESPACE;
Packit 0d464f
using namespace IMF;
Packit 0d464f
using namespace std;
Packit 0d464f
using namespace IMATH_NAMESPACE;
Packit 0d464f
Packit 0d464f
Packit 0d464f
namespace {
Packit 0d464f
Packit 0d464f
//
Packit 0d464f
// Functions to test conversion of individual numbers
Packit 0d464f
//
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
testFloatToUint (unsigned int floatVal, unsigned int uintVal)
Packit 0d464f
{
Packit 0d464f
    union {unsigned int ui; float f;} u;
Packit 0d464f
    u.ui = floatVal;
Packit 0d464f
    cout << "floatToUint (" << u.f << ") == " << floatToUint(u.f) << endl;
Packit 0d464f
    assert (floatToUint (u.f) == uintVal);
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
testHalfToUint (unsigned int halfVal, unsigned int uintVal)
Packit 0d464f
{
Packit 0d464f
    half h;
Packit 0d464f
    h.setBits (halfVal);
Packit 0d464f
    cout << "halfToUint (" << h << ") == " << halfToUint(h) << endl;
Packit 0d464f
    assert (halfToUint (h) == uintVal);
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
testFloatToHalf (unsigned int floatVal, unsigned int halfVal)
Packit 0d464f
{
Packit 0d464f
    union {unsigned int ui; float f;} u;
Packit 0d464f
    u.ui = floatVal;
Packit 0d464f
    cout << "floatToHalf (" << u.f << ") == " << floatToHalf(u.f) << endl;
Packit 0d464f
    assert (floatToHalf(u.f).bits() == halfVal);
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
testUintToHalf (unsigned int uintVal, unsigned int halfVal)
Packit 0d464f
{
Packit 0d464f
    cout << "uintToHalf (" << uintVal << ") == " << uintToHalf(uintVal) << endl;
Packit 0d464f
    assert (uintToHalf(uintVal).bits() == halfVal);
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
testNumbers ()
Packit 0d464f
{
Packit 0d464f
    testFloatToUint (0x00000000, 0);		//  0.0
Packit 0d464f
    testFloatToUint (0x3f000000, 0);		// +0.5
Packit 0d464f
    testFloatToUint (0xbf000000, 0);		// -0.5
Packit 0d464f
    testFloatToUint (0x42f82000, 124);		// +124.0625
Packit 0d464f
    testFloatToUint (0xc2f82000, 0);		// -124.0625
Packit 0d464f
    testFloatToUint (0x58635fa9, 0xffffffff);	// +1.0e15
Packit 0d464f
    testFloatToUint (0xd8635fa9, 0);		// -1.0e15
Packit 0d464f
    testFloatToUint (0x7f800000, 0xffffffff);	// +infinity
Packit 0d464f
    testFloatToUint (0xff800000, 0);		// -infinity
Packit 0d464f
    testFloatToUint (0x7fffffff, 0);		//  NaN
Packit 0d464f
    testFloatToUint (0xffffffff, 0);		//  NaN
Packit 0d464f
Packit 0d464f
    testHalfToUint  (0x0000, 0);		//  0.0
Packit 0d464f
    testHalfToUint  (0x3800, 0);		// +0.5
Packit 0d464f
    testHalfToUint  (0xb800, 0);		// -0.5
Packit 0d464f
    testHalfToUint  (0x57c1, 124);		// +124.0625
Packit 0d464f
    testHalfToUint  (0xd7c1, 0);		// -124.0625
Packit 0d464f
    testHalfToUint  (0x7c00, 0xffffffff);	// +infinity
Packit 0d464f
    testHalfToUint  (0xfc00, 0);		// -infinity
Packit 0d464f
    testHalfToUint  (0x7fff, 0);		//  NaN
Packit 0d464f
    testHalfToUint  (0xffff, 0);		//  NaN
Packit 0d464f
Packit 0d464f
    testFloatToHalf (0x00000000, 0x0000);	//  0.0
Packit 0d464f
    testFloatToHalf (0x3f000000, 0x3800);	// +0.5
Packit 0d464f
    testFloatToHalf (0xbf000000, 0xb800);	// -0.5
Packit 0d464f
    testFloatToHalf (0x42f82000, 0x57c1);	// +124.0625
Packit 0d464f
    testFloatToHalf (0xc2f82000, 0xd7c1);	// -124.0625
Packit 0d464f
    testFloatToHalf (0x58635fa9, 0x7c00);	// +1.0e15
Packit 0d464f
    testFloatToHalf (0xd8635fa9, 0xfc00);	// -1.0e15
Packit 0d464f
    testFloatToHalf (0x7f800000, 0x7c00);	// +infinity
Packit 0d464f
    testFloatToHalf (0xff800000, 0xfc00);	// -infinity
Packit 0d464f
    testFloatToHalf (0x7fffffff, 0x7fff);	//  NaN
Packit 0d464f
    testFloatToHalf (0xffffffff, 0xffff);	//  NaN
Packit 0d464f
Packit 0d464f
    testUintToHalf  (0,          0x0000);	
Packit 0d464f
    testUintToHalf  (1,          0x3c00);
Packit 0d464f
    testUintToHalf  (124,        0x57c0);
Packit 0d464f
    testUintToHalf  (1000000,    0x7c00);
Packit 0d464f
    testUintToHalf  (0xffffffff, 0x7c00);
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
template <class T>
Packit 0d464f
bool
Packit 0d464f
isEquivalent (T t1, T t2, Compression compression)
Packit 0d464f
{
Packit 0d464f
    return t1 == t2;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
template<>
Packit 0d464f
bool
Packit 0d464f
isEquivalent (float t1, float t2, Compression compression)
Packit 0d464f
{
Packit 0d464f
    return equivalent (t1, t2, compression);
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
template 
Packit 0d464f
          class InType,  PixelType InTypeTag>
Packit 0d464f
void
Packit 0d464f
testScanLineImageChannel (const char fileName[],
Packit 0d464f
		          int width, int height,
Packit 0d464f
			  Compression compression)
Packit 0d464f
{
Packit 0d464f
    cout << "scan lines, "
Packit 0d464f
	    "compression " << compression << ", " <<
Packit 0d464f
	    "output type " << OutTypeTag << ", " <<
Packit 0d464f
	    "input type " << InTypeTag << ":\n    " << flush;
Packit 0d464f
Packit 0d464f
    Array2D<OutType> outPixels (height, width);
Packit 0d464f
Packit 0d464f
    for (int y = 0; y < height; ++y)
Packit 0d464f
	for (int x = 0; x < width; ++x)
Packit 0d464f
	    outPixels[y][x] = x * 10 + y;
Packit 0d464f
Packit 0d464f
    {
Packit 0d464f
	Header hdr (width, height);
Packit 0d464f
Packit 0d464f
	hdr.compression() = compression;
Packit 0d464f
Packit 0d464f
	hdr.channels().insert ("X", 				// name
Packit 0d464f
			       Channel (OutTypeTag));		// type
Packit 0d464f
Packit 0d464f
	FrameBuffer fb;
Packit 0d464f
Packit 0d464f
	fb.insert ("X",						// name
Packit 0d464f
		   Slice (OutTypeTag,				// type
Packit 0d464f
		          (char *) &outPixels[0][0],		// base
Packit 0d464f
			  sizeof (outPixels[0][0]),		// xStride
Packit 0d464f
			  sizeof (outPixels[0][0]) * width));	// yStride
Packit 0d464f
Packit 0d464f
	cout << "writing " << flush;
Packit 0d464f
Packit 0d464f
	OutputFile out (fileName, hdr);
Packit 0d464f
	out.setFrameBuffer (fb);
Packit 0d464f
	out.writePixels (height);
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    Array2D<InType> inPixels (height, width);
Packit 0d464f
Packit 0d464f
    {
Packit 0d464f
	cout << "reading " << flush;
Packit 0d464f
Packit 0d464f
	FrameBuffer fb;
Packit 0d464f
Packit 0d464f
	fb.insert ("X",						// name
Packit 0d464f
		   Slice (InTypeTag,				// type
Packit 0d464f
		          (char *) &inPixels[0][0],		// base
Packit 0d464f
			  sizeof (inPixels[0][0]),		// xStride
Packit 0d464f
			  sizeof (inPixels[0][0]) * width));	// yStride
Packit 0d464f
Packit 0d464f
	InputFile in (fileName);
Packit 0d464f
	in.setFrameBuffer (fb);
Packit 0d464f
	in.readPixels (0, height - 1);
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    cout << "comparing" << flush;
Packit 0d464f
Packit 0d464f
    for (int y = 0; y < height; ++y)
Packit 0d464f
    {
Packit 0d464f
	for (int x = 0; x < width; ++x)
Packit 0d464f
	{
Packit 0d464f
	    assert (isEquivalent (inPixels[y][x],
Packit 0d464f
				  InType (outPixels[y][x]),
Packit 0d464f
				  compression));
Packit 0d464f
	}
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    cout << endl;
Packit 0d464f
Packit 0d464f
    remove (fileName);
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
template 
Packit 0d464f
          class InType,  PixelType InTypeTag>
Packit 0d464f
void
Packit 0d464f
testTiledImageChannel (const char fileName[],
Packit 0d464f
		       int width, int height,
Packit 0d464f
		       Compression compression)
Packit 0d464f
{
Packit 0d464f
    cout << "tiles, "
Packit 0d464f
	    "compression " << compression << ", " <<
Packit 0d464f
	    "output type " << OutTypeTag << ", " <<
Packit 0d464f
	    "input type " << InTypeTag << ":\n    " << flush;
Packit 0d464f
Packit 0d464f
    Array2D<OutType> outPixels (height, width);
Packit 0d464f
Packit 0d464f
    for (int y = 0; y < height; ++y)
Packit 0d464f
	for (int x = 0; x < width; ++x)
Packit 0d464f
	    outPixels[y][x] = x * 10 + y;
Packit 0d464f
Packit 0d464f
    {
Packit 0d464f
	Header hdr (width, height);
Packit 0d464f
Packit 0d464f
	hdr.setTileDescription (TileDescription (67, 67, ONE_LEVEL));
Packit 0d464f
Packit 0d464f
	hdr.compression() = compression;
Packit 0d464f
Packit 0d464f
	hdr.channels().insert ("X", 				// name
Packit 0d464f
			       Channel (OutTypeTag));		// type
Packit 0d464f
Packit 0d464f
	FrameBuffer fb;
Packit 0d464f
Packit 0d464f
	fb.insert ("X",						// name
Packit 0d464f
		   Slice (OutTypeTag,				// type
Packit 0d464f
		          (char *) &outPixels[0][0],		// base
Packit 0d464f
			  sizeof (outPixels[0][0]),		// xStride
Packit 0d464f
			  sizeof (outPixels[0][0]) * width));	// yStride
Packit 0d464f
Packit 0d464f
	cout << "writing " << flush;
Packit 0d464f
Packit 0d464f
	TiledOutputFile out (fileName, hdr);
Packit 0d464f
	out.setFrameBuffer (fb);
Packit 0d464f
        out.writeTiles (0, out.numXTiles() - 1, 0, out.numYTiles() - 1);
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    Array2D<InType> inPixels (height, width);
Packit 0d464f
Packit 0d464f
    {
Packit 0d464f
	cout << "reading " << flush;
Packit 0d464f
Packit 0d464f
	FrameBuffer fb;
Packit 0d464f
Packit 0d464f
	fb.insert ("X",						// name
Packit 0d464f
		   Slice (InTypeTag,				// type
Packit 0d464f
		          (char *) &inPixels[0][0],		// base
Packit 0d464f
			  sizeof (inPixels[0][0]),		// xStride
Packit 0d464f
			  sizeof (inPixels[0][0]) * width));	// yStride
Packit 0d464f
Packit 0d464f
	TiledInputFile in (fileName);
Packit 0d464f
	in.setFrameBuffer (fb);
Packit 0d464f
        in.readTiles (0, in.numXTiles() - 1, 0, in.numYTiles() - 1);
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    cout << "comparing" << flush;
Packit 0d464f
Packit 0d464f
    for (int y = 0; y < height; ++y)
Packit 0d464f
    {
Packit 0d464f
	for (int x = 0; x < width; ++x)
Packit 0d464f
	{
Packit 0d464f
	    assert (isEquivalent (inPixels[y][x],
Packit 0d464f
				  InType (outPixels[y][x]),
Packit 0d464f
				  compression));
Packit 0d464f
	}
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    cout << endl;
Packit 0d464f
Packit 0d464f
    remove (fileName);
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
template 
Packit 0d464f
          class InType,  PixelType InTypeTag>
Packit 0d464f
void
Packit 0d464f
testImageChannel (const std::string &fileName,
Packit 0d464f
		  int width, int height,
Packit 0d464f
		  Compression compression)
Packit 0d464f
{
Packit 0d464f
    testScanLineImageChannel <OutType, OutTypeTag, InType, InTypeTag>
Packit 0d464f
	(fileName.c_str(), width, height, compression);
Packit 0d464f
Packit 0d464f
    testTiledImageChannel <OutType, OutTypeTag, InType, InTypeTag>
Packit 0d464f
	(fileName.c_str(), width, height, compression);
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
Packit 0d464f
} // namespace
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
testConversion (const std::string &tempDir)
Packit 0d464f
{
Packit 0d464f
    try
Packit 0d464f
    {
Packit 0d464f
	cout << "Testing conversion between pixel data types" << endl;
Packit 0d464f
Packit 0d464f
	cout << "individual numbers" << endl;
Packit 0d464f
Packit 0d464f
	testNumbers();
Packit 0d464f
Packit 0d464f
	cout << "conversion of image channels while reading a file " << endl;
Packit 0d464f
Packit 0d464f
	for (int comp = 0; comp < NUM_COMPRESSION_METHODS; ++comp)
Packit 0d464f
	{
Packit 0d464f
	    if (comp == B44_COMPRESSION ||
Packit 0d464f
                comp == B44A_COMPRESSION)
Packit 0d464f
            {
Packit 0d464f
		continue;
Packit 0d464f
            }
Packit 0d464f
Packit 0d464f
	    testImageChannel <unsigned int, IMF::UINT, unsigned int, IMF::UINT>
Packit 0d464f
			     (tempDir + "imf_test_conv.exr",
Packit 0d464f
			      317, 539,
Packit 0d464f
			      Compression (comp));
Packit 0d464f
Packit 0d464f
	    testImageChannel <unsigned int, IMF::UINT, half, IMF::HALF>
Packit 0d464f
			     (tempDir + "imf_test_conv.exr",
Packit 0d464f
			      317, 539,
Packit 0d464f
			      Compression (comp));
Packit 0d464f
Packit 0d464f
	    testImageChannel <unsigned int, IMF::UINT, float, IMF::FLOAT>
Packit 0d464f
			     (tempDir + "imf_test_conv.exr",
Packit 0d464f
			      317, 539,
Packit 0d464f
			      Compression (comp));
Packit 0d464f
Packit 0d464f
	    testImageChannel <half, IMF::HALF, unsigned int, IMF::UINT>
Packit 0d464f
			     (tempDir + "imf_test_conv.exr",
Packit 0d464f
			      317, 539,
Packit 0d464f
			      Compression (comp));
Packit 0d464f
Packit 0d464f
	    testImageChannel <half, IMF::HALF, half, IMF::HALF>
Packit 0d464f
			     (tempDir + "imf_test_conv.exr",
Packit 0d464f
			      317, 539,
Packit 0d464f
			      Compression (comp));
Packit 0d464f
Packit 0d464f
	    testImageChannel <half, IMF::HALF, float, IMF::FLOAT>
Packit 0d464f
			     (tempDir + "imf_test_conv.exr",
Packit 0d464f
			      317, 539,
Packit 0d464f
			      Compression (comp));
Packit 0d464f
Packit 0d464f
	    testImageChannel <float, IMF::FLOAT, unsigned int, IMF::UINT>
Packit 0d464f
			     (tempDir + "imf_test_conv.exr",
Packit 0d464f
			      317, 539,
Packit 0d464f
			      Compression (comp));
Packit 0d464f
Packit 0d464f
	    testImageChannel <float, IMF::FLOAT, half, IMF::HALF>
Packit 0d464f
			     (tempDir + "imf_test_conv.exr",
Packit 0d464f
			      317, 539,
Packit 0d464f
			      Compression (comp));
Packit 0d464f
Packit 0d464f
	    testImageChannel <float, IMF::FLOAT, float, IMF::FLOAT>
Packit 0d464f
			     (tempDir + "imf_test_conv.exr",
Packit 0d464f
			      317, 539,
Packit 0d464f
			      Compression (comp));
Packit 0d464f
Packit 0d464f
	}
Packit 0d464f
	cout << "ok\n" << endl;
Packit 0d464f
    }
Packit 0d464f
    catch (const std::exception &e)
Packit 0d464f
    {
Packit 0d464f
	cerr << "ERROR -- caught exception: " << e.what() << endl;
Packit 0d464f
	assert (false);
Packit 0d464f
    }
Packit 0d464f
}