Blame IlmImfTest/testBackwardCompatibility.cpp

Packit 0d464f
///////////////////////////////////////////////////////////////////////////
Packit 0d464f
//
Packit 0d464f
// Copyright (c) 2012, Industrial Light & Magic, a division of Lucas
Packit 0d464f
// Digital Ltd. LLC
Packit 0d464f
//
Packit 0d464f
// 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
// *       Redistributions of source code must retain the above copyright
Packit 0d464f
// notice, this list of conditions and the following disclaimer.
Packit 0d464f
// *       Redistributions in binary form must reproduce the above
Packit 0d464f
// copyright notice, this list of conditions and the following disclaimer
Packit 0d464f
// in the documentation and/or other materials provided with the
Packit 0d464f
// distribution.
Packit 0d464f
// *       Neither the name of Industrial Light & Magic nor the names of
Packit 0d464f
// its contributors may be used to endorse or promote products derived
Packit 0d464f
// from this software without specific prior written permission.
Packit 0d464f
//
Packit 0d464f
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
Packit 0d464f
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
Packit 0d464f
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
Packit 0d464f
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
Packit 0d464f
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
Packit 0d464f
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
Packit 0d464f
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
Packit 0d464f
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
Packit 0d464f
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Packit 0d464f
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
Packit 0d464f
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit 0d464f
//
Packit 0d464f
///////////////////////////////////////////////////////////////////////////
Packit 0d464f
Packit 0d464f
#include "testBackwardCompatibility.h"
Packit 0d464f
Packit 0d464f
#include <ImfArray.h>
Packit 0d464f
#include <ImfHeader.h>
Packit 0d464f
#include <IlmThreadPool.h>
Packit 0d464f
#include <ImfFrameBuffer.h>
Packit 0d464f
#include <ImfOutputFile.h>
Packit 0d464f
#include <ImfPreviewImage.h>
Packit 0d464f
#include <ImfTiledOutputFile.h>
Packit 0d464f
#include <stdlib.h>
Packit 0d464f
#include <stdio.h>
Packit 0d464f
#include <tmpDir.h>
Packit 0d464f
#include <ImathBox.h>
Packit 0d464f
#include <ImfChannelList.h>
Packit 0d464f
#include <IexMacros.h>
Packit 0d464f
Packit 0d464f
#include <ImfBoxAttribute.h>
Packit 0d464f
#include <ImfChannelListAttribute.h>
Packit 0d464f
#include <ImfCompressionAttribute.h>
Packit 0d464f
#include <ImfChromaticitiesAttribute.h>
Packit 0d464f
#include <ImfFloatAttribute.h>
Packit 0d464f
#include <ImfEnvmapAttribute.h>
Packit 0d464f
#include <ImfDoubleAttribute.h>
Packit 0d464f
#include <ImfIntAttribute.h>
Packit 0d464f
#include <ImfLineOrderAttribute.h>
Packit 0d464f
#include <ImfMatrixAttribute.h>
Packit 0d464f
#include <ImfOpaqueAttribute.h>
Packit 0d464f
#include <ImfStringAttribute.h>
Packit 0d464f
#include <ImfStringVectorAttribute.h>
Packit 0d464f
#include <ImfVecAttribute.h>
Packit 0d464f
Packit 0d464f
#include <half.h>
Packit 0d464f
Packit 0d464f
#include <iostream>
Packit 0d464f
#include <fstream>
Packit 0d464f
#include <string>
Packit 0d464f
#include <assert.h>
Packit 0d464f
#include <time.h>
Packit 0d464f
#ifndef WIN32
Packit 0d464f
#include <sys/times.h>
Packit 0d464f
#endif // WIN32
Packit 0d464f
Packit 0d464f
#ifndef ILM_IMF_TEST_IMAGEDIR
Packit 0d464f
    #define ILM_IMF_TEST_IMAGEDIR
Packit 0d464f
#endif
Packit 0d464f
Packit 0d464f
Packit 0d464f
namespace IMF = OPENEXR_IMF_NAMESPACE;
Packit 0d464f
using namespace IMF;
Packit 0d464f
using namespace IMATH_NAMESPACE;
Packit 0d464f
using namespace ILMTHREAD_NAMESPACE;
Packit 0d464f
using namespace std;
Packit 0d464f
Packit 0d464f
Packit 0d464f
namespace {
Packit 0d464f
Packit 0d464f
//
Packit 0d464f
// Make this true if you wish to generate images when building
Packit 0d464f
// the v1.7 code base.
Packit 0d464f
//
Packit 0d464f
const int generateImagesOnly = false;
Packit 0d464f
Packit 0d464f
Packit 0d464f
const int W = 217;
Packit 0d464f
const int H = 197;
Packit 0d464f
Packit 0d464f
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
diffImageFiles (const char * fn1, const char * fn2)
Packit 0d464f
{
Packit 0d464f
    ifstream i1 (fn1, ios::binary);
Packit 0d464f
    ifstream i2 (fn2, ios::binary);
Packit 0d464f
Packit 0d464f
    if(!i1.good()){THROW (IEX_NAMESPACE::BaseExc, string("cannot open ") + string(fn1));}
Packit 0d464f
    if(!i2.good()){THROW (IEX_NAMESPACE::BaseExc, string("cannot open ") + string(fn2));}
Packit 0d464f
Packit 0d464f
    while (!i1.eof() && !i2.eof())
Packit 0d464f
    {
Packit 0d464f
        if (i1.get() != i2.get())
Packit 0d464f
        {
Packit 0d464f
            string e = string ("v1.7 and current differences between '") +
Packit 0d464f
                       string (fn1) + string ("' & '") +  string (fn2) +
Packit 0d464f
                       string ("'");
Packit 0d464f
            THROW (IEX_NAMESPACE::BaseExc, e);
Packit 0d464f
        }
Packit 0d464f
    }
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
addPreviewImageToHeader (OPENEXR_IMF_NAMESPACE::Header & hdr)
Packit 0d464f
{
Packit 0d464f
    size_t pW = 32;
Packit 0d464f
    size_t pH = 32;
Packit 0d464f
Packit 0d464f
    OPENEXR_IMF_NAMESPACE::Array2D <OPENEXR_IMF_NAMESPACE::PreviewRgba> previewPixels (pW, pH);
Packit 0d464f
    for (size_t h=0; h
Packit 0d464f
    {
Packit 0d464f
        for (size_t w=0; w
Packit 0d464f
        {
Packit 0d464f
            previewPixels[w][h] = (w*h) % 255;
Packit 0d464f
        }
Packit 0d464f
    }
Packit 0d464f
    hdr.setPreviewImage (OPENEXR_IMF_NAMESPACE::PreviewImage (pW, pH, &previewPixels[0][0]));
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
addUserAttributesToHeader (OPENEXR_IMF_NAMESPACE::Header & hdr)
Packit 0d464f
{
Packit 0d464f
    Box2i  a1  (V2i (1, 2), V2i (3, 4));
Packit 0d464f
    Box2f  a2  (V2f (1.5, 2.5), V2f (3.5, 4.5));
Packit 0d464f
    float  a3  (3.14159);
Packit 0d464f
    int    a4  (17);
Packit 0d464f
    M33f   a5  (11, 12, 13, 14, 15, 16, 17, 18, 19);
Packit 0d464f
    M44f   a6  (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
Packit 0d464f
    string a7  ("extensive rebuilding by Nebuchadrezzar has left");
Packit 0d464f
    V2i    a8  (27, 28);
Packit 0d464f
    V2f    a9  (27.5, 28.5);
Packit 0d464f
    V3i    a10 (37, 38, 39);
Packit 0d464f
    V3f    a11 (37.5, 38.5, 39.5);
Packit 0d464f
    double a12 (7.12342341419);
Packit 0d464f
    Chromaticities a13 (V2f (1, 2), V2f (3, 4), V2f (5, 6), V2f (7, 8));
Packit 0d464f
//    Envmap a14 (ENVMAP_CUBE);
Packit 0d464f
    StringVector a15;
Packit 0d464f
    a15.push_back ("who can spin");
Packit 0d464f
    a15.push_back ("");
Packit 0d464f
    a15.push_back ("straw into");
Packit 0d464f
    a15.push_back ("gold");
Packit 0d464f
Packit 0d464f
    M33d   a16 (12, 13, 14, 15, 16, 17, 18, 19, 20);
Packit 0d464f
    M44d   a17 (2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17);
Packit 0d464f
    V2d    a18 (27.51, 28.51);
Packit 0d464f
    V3d    a19 (37.51, 38.51, 39.51);
Packit 0d464f
Packit 0d464f
    hdr.insert ("a1",  Box2iAttribute  (a1));
Packit 0d464f
    hdr.insert ("a2",  Box2fAttribute  (a2));
Packit 0d464f
    hdr.insert ("a3",  FloatAttribute  (a3));
Packit 0d464f
    hdr.insert ("a4",  IntAttribute    (a4));
Packit 0d464f
    hdr.insert ("a5",  M33fAttribute   (a5));
Packit 0d464f
    hdr.insert ("a6",  M44fAttribute   (a6));
Packit 0d464f
    hdr.insert ("a7",  StringAttribute (a7));
Packit 0d464f
    hdr.insert ("a8",  V2iAttribute    (a8));
Packit 0d464f
    hdr.insert ("a9",  V2fAttribute    (a9));
Packit 0d464f
    hdr.insert ("a10", V3iAttribute    (a10));
Packit 0d464f
    hdr.insert ("a11", V3fAttribute    (a11));
Packit 0d464f
    hdr.insert ("a12", DoubleAttribute (a12));
Packit 0d464f
    hdr.insert ("a13", ChromaticitiesAttribute (a13));
Packit 0d464f
//    hdr.insert ("a14", EnvmapAttribute         (a14));
Packit 0d464f
    hdr.insert ("a15", StringVectorAttribute   (a15));
Packit 0d464f
    hdr.insert ("a16", M33dAttribute   (a16));
Packit 0d464f
    hdr.insert ("a17", M44dAttribute   (a17));
Packit 0d464f
    hdr.insert ("a18", V2dAttribute    (a18));
Packit 0d464f
    hdr.insert ("a19", V3dAttribute    (a19));
Packit 0d464f
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
generateScanlinePlanarImage (const char * fn)
Packit 0d464f
{
Packit 0d464f
    // generate a v 1.7 image and check against ground truth on disk
Packit 0d464f
    Array2D<float> pf (H, W);  pf.resizeErase(H, W);
Packit 0d464f
    Array2D<half>  ph (H, W);  ph.resizeErase(H, W);
Packit 0d464f
Packit 0d464f
    for (int i = 0; i < H; i++)
Packit 0d464f
    {
Packit 0d464f
        for (int j = 0; j < W; j++)
Packit 0d464f
        {
Packit 0d464f
            pf[i][j] = (float)((i * W + j) /  (float(W*H)));
Packit 0d464f
            ph[i][j] = (half)(pf[i][j]);
Packit 0d464f
        }
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    IMATH_NAMESPACE::Box2i dod (IMATH_NAMESPACE::V2f(20), IMATH_NAMESPACE::V2f(W-20, H-23));
Packit 0d464f
    OPENEXR_IMF_NAMESPACE::Header header = Header (W, H, dod);
Packit 0d464f
    header.channels().insert("Z", Channel(IMF::FLOAT));
Packit 0d464f
    header.channels().insert("R", Channel(IMF::HALF));
Packit 0d464f
    header.channels().insert("G", Channel(IMF::HALF));
Packit 0d464f
    header.channels().insert("B", Channel(IMF::HALF));
Packit 0d464f
    addUserAttributesToHeader (header);
Packit 0d464f
Packit 0d464f
    FrameBuffer fb;
Packit 0d464f
Packit 0d464f
    fb.insert ("Z",
Packit 0d464f
               Slice (IMF::FLOAT,
Packit 0d464f
                      (char *) &pf[0][0],
Packit 0d464f
                      sizeof (pf[0][0]),
Packit 0d464f
                      sizeof (pf[0][0]) * W));
Packit 0d464f
Packit 0d464f
    fb.insert ("R",
Packit 0d464f
               Slice (IMF::HALF,
Packit 0d464f
                      (char *) &ph[0][0],
Packit 0d464f
                      sizeof (ph[0][0]),
Packit 0d464f
                      sizeof (ph[0][0]) * W));
Packit 0d464f
    fb.insert ("G",
Packit 0d464f
               Slice (IMF::HALF,
Packit 0d464f
                      (char *) &ph[0][0],
Packit 0d464f
                      sizeof (ph[0][0]),
Packit 0d464f
                      sizeof (ph[0][0]) * W));
Packit 0d464f
    fb.insert ("B",
Packit 0d464f
               Slice (IMF::HALF,
Packit 0d464f
                      (char *) &ph[0][0],
Packit 0d464f
                      sizeof (ph[0][0]),
Packit 0d464f
                      sizeof (ph[0][0]) * W));
Packit 0d464f
Packit 0d464f
    OutputFile file (fn, header);
Packit 0d464f
    file.setFrameBuffer (fb);
Packit 0d464f
    file.writePixels (H-40);
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
struct RZ
Packit 0d464f
{
Packit 0d464f
    float z;
Packit 0d464f
    half g;
Packit 0d464f
};
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
generateScanlineInterleavedImage (const char * fn)
Packit 0d464f
{
Packit 0d464f
    // generate a v 1.7 image and check against ground truth on disk
Packit 0d464f
    Array2D<RZ> rz (H, W);  rz.resizeErase(H, W);
Packit 0d464f
Packit 0d464f
    for (int i = 0; i < H; i++)
Packit 0d464f
    {
Packit 0d464f
        for (int j = 0; j < W; j++)
Packit 0d464f
        {
Packit 0d464f
            rz[i][j].z = (float)((i * W + j) /  (float(W*H)));
Packit 0d464f
            rz[i][j].g = (half)(rz[i][j].z);
Packit 0d464f
        }
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    IMATH_NAMESPACE::Box2i dod (IMATH_NAMESPACE::V2f(20), IMATH_NAMESPACE::V2f(W-20, H-23));
Packit 0d464f
    OPENEXR_IMF_NAMESPACE::Header header = Header (W, H, dod);
Packit 0d464f
    header.channels().insert("Z", Channel(IMF::FLOAT));
Packit 0d464f
    header.channels().insert("R", Channel(IMF::HALF));
Packit 0d464f
    addUserAttributesToHeader (header);
Packit 0d464f
Packit 0d464f
    FrameBuffer fb;
Packit 0d464f
Packit 0d464f
    fb.insert ("Z",
Packit 0d464f
               Slice (IMF::FLOAT,
Packit 0d464f
                      (char *) &(rz[0][0].z),
Packit 0d464f
                      sizeof (rz[0][0]),
Packit 0d464f
                      sizeof (rz[0][0]) * W));
Packit 0d464f
Packit 0d464f
    fb.insert ("G",
Packit 0d464f
               Slice (IMF::HALF,
Packit 0d464f
                      (char *) &(rz[0][0].g),
Packit 0d464f
                      sizeof (rz[0][0]),
Packit 0d464f
                      sizeof (rz[0][0]) * W));
Packit 0d464f
Packit 0d464f
    OutputFile file (fn, header);
Packit 0d464f
    file.setFrameBuffer (fb);
Packit 0d464f
    file.writePixels (H-40);
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
diffScanlineImages (const std::string & planarScanlineName,
Packit 0d464f
                    const std::string & interleavedScanlineName)
Packit 0d464f
{
Packit 0d464f
    // Planar Images
Packit 0d464f
    generateScanlinePlanarImage (planarScanlineName.c_str());
Packit 0d464f
    diffImageFiles (planarScanlineName.c_str(),
Packit 0d464f
                    ILM_IMF_TEST_IMAGEDIR "v1.7.test.planar.exr");
Packit 0d464f
Packit 0d464f
    // Interleaved Images
Packit 0d464f
    generateScanlineInterleavedImage (interleavedScanlineName.c_str());
Packit 0d464f
    diffImageFiles (interleavedScanlineName.c_str(),
Packit 0d464f
                    ILM_IMF_TEST_IMAGEDIR "v1.7.test.interleaved.exr");
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
generateTiledImage (const char * fn)
Packit 0d464f
{
Packit 0d464f
    Array2D<RZ> rz (H, W);  rz.resizeErase(H, W);
Packit 0d464f
Packit 0d464f
    for (int i = 0; i < H; i++)
Packit 0d464f
    {
Packit 0d464f
        for (int j = 0; j < W; j++)
Packit 0d464f
        {
Packit 0d464f
            rz[i][j].z = (float)((i * W + j) /  (float(W*H)));
Packit 0d464f
            rz[i][j].g = (half)(rz[i][j].z);
Packit 0d464f
        }
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    Header header (W, H);
Packit 0d464f
    header.channels().insert ("G", Channel (IMF::HALF));
Packit 0d464f
    header.channels().insert ("Z", Channel (IMF::FLOAT));
Packit 0d464f
Packit 0d464f
    int tileW = 12;
Packit 0d464f
    int tileH = 24;
Packit 0d464f
    header.setTileDescription (TileDescription (tileW, tileH, ONE_LEVEL));
Packit 0d464f
Packit 0d464f
    OPENEXR_IMF_NAMESPACE::TiledOutputFile out (fn, header);
Packit 0d464f
    OPENEXR_IMF_NAMESPACE::FrameBuffer frameBuffer; // 6
Packit 0d464f
    frameBuffer.insert ("G",
Packit 0d464f
                        Slice (IMF::HALF,
Packit 0d464f
                               (char *) &rz[0][0].g,
Packit 0d464f
                               sizeof (rz[0][0]) * 1,
Packit 0d464f
                               sizeof (rz[0][0]) * W));
Packit 0d464f
Packit 0d464f
    frameBuffer.insert ("Z",
Packit 0d464f
                        Slice (IMF::FLOAT,
Packit 0d464f
                               (char *) &rz[0][0].z,
Packit 0d464f
                               sizeof (rz[0][0]) * 1,
Packit 0d464f
                               sizeof (rz[0][0]) * W));
Packit 0d464f
Packit 0d464f
    out.setFrameBuffer (frameBuffer);
Packit 0d464f
    out.writeTiles (0, out.numXTiles() - 1, 0, out.numYTiles() - 1);
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
diffTiledImages (const std::string & fn)
Packit 0d464f
{
Packit 0d464f
    // Planar Images
Packit 0d464f
    generateTiledImage (fn.c_str());
Packit 0d464f
    diffImageFiles (fn.c_str(), ILM_IMF_TEST_IMAGEDIR "v1.7.test.tiled.exr");
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
} // namespace
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
testBackwardCompatibility (const std::string & tempDir)
Packit 0d464f
{
Packit 0d464f
    try
Packit 0d464f
    {
Packit 0d464f
        cout << "Testing backward compatibility" << endl;
Packit 0d464f
Packit 0d464f
Packit 0d464f
        // Run this code with the 1.7 code base to generate the
Packit 0d464f
        // images used in the test.
Packit 0d464f
        if (generateImagesOnly)
Packit 0d464f
        {
Packit 0d464f
            generateScanlinePlanarImage ("v1.7.test.planar.exr");
Packit 0d464f
            generateScanlineInterleavedImage ("v1.7.test.interleaved.exr");
Packit 0d464f
            generateTiledImage ("v1.7.test.tiled.exr");
Packit 0d464f
        }
Packit 0d464f
        else
Packit 0d464f
        {
Packit 0d464f
            std::string planarFn      = tempDir + "v1.7.test.planar.exr";
Packit 0d464f
            std::string interleavedFn = tempDir + "v1.7.test.interleaved.exr";
Packit 0d464f
            diffScanlineImages (planarFn, interleavedFn);
Packit 0d464f
Packit 0d464f
            std::string fn = tempDir + "v1.7.test.tiled.exr";
Packit 0d464f
            diffTiledImages (fn);
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
}