Blame IlmImfTest/testTiledLineOrder.cpp

Packit 0d464f
///////////////////////////////////////////////////////////////////////////
Packit 0d464f
//
Packit 0d464f
// Copyright (c) 2004-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
Packit 0d464f
#include <ImfTiledOutputFile.h>
Packit 0d464f
#include <ImfInputFile.h>
Packit 0d464f
#include <ImathRandom.h>
Packit 0d464f
#include <ImfTiledInputFile.h>
Packit 0d464f
#include <ImfChannelList.h>
Packit 0d464f
#include <ImfArray.h>
Packit 0d464f
#include <ImfThreading.h>
Packit 0d464f
#include <IlmThread.h>
Packit 0d464f
#include <half.h>
Packit 0d464f
Packit 0d464f
#include <vector>
Packit 0d464f
#include <stdio.h>
Packit 0d464f
#include <assert.h>
Packit 0d464f
Packit 0d464f
Packit 0d464f
using namespace OPENEXR_IMF_NAMESPACE;
Packit 0d464f
using namespace std;
Packit 0d464f
using namespace IMATH_NAMESPACE;
Packit 0d464f
Packit 0d464f
Packit 0d464f
namespace {
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
fillPixels (Array2D<half> &ph, int width, int height)
Packit 0d464f
{
Packit 0d464f
    for (int y = 0; y < height; ++y)
Packit 0d464f
	for (int x = 0; x < width; ++x)
Packit 0d464f
	    ph[y][x] = sin (double (x)) + sin (y * 0.5);
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
writeCopyReadONE (const char fileName[],
Packit 0d464f
		  int width,
Packit 0d464f
		  int height,
Packit 0d464f
		  LineOrder lorder,
Packit 0d464f
		  LevelRoundingMode rmode,
Packit 0d464f
		  int xSize, 
Packit 0d464f
		  int ySize,
Packit 0d464f
		  Compression comp,
Packit 0d464f
		  bool triggerBuffering,
Packit 0d464f
		  bool triggerSeeks)
Packit 0d464f
{
Packit 0d464f
    cout << "LineOrder " << lorder << ", buffer " << triggerBuffering <<
Packit 0d464f
            ", seek " << triggerSeeks << ", levelMode 0, " <<
Packit 0d464f
	    "roundingMode " << rmode << ", "
Packit 0d464f
	    "compression " << comp << endl;
Packit 0d464f
    
Packit 0d464f
    Header hdr ((Box2i (V2i (0, 0),			// display window
Packit 0d464f
		        V2i (width - 1, height -1))),
Packit 0d464f
		(Box2i (V2i (0, 0),		// data window
Packit 0d464f
		        V2i (width - 1, height - 1))));
Packit 0d464f
Packit 0d464f
    hdr.compression() = comp;
Packit 0d464f
    hdr.lineOrder() = INCREASING_Y;
Packit 0d464f
    hdr.channels().insert ("H", Channel (HALF, 1, 1));
Packit 0d464f
    
Packit 0d464f
    hdr.setTileDescription(TileDescription(xSize, ySize, ONE_LEVEL, rmode));
Packit 0d464f
Packit 0d464f
    Array2D<half> ph1 (height, width);
Packit 0d464f
    fillPixels (ph1, width, height);
Packit 0d464f
    
Packit 0d464f
    {
Packit 0d464f
        FrameBuffer fb; 
Packit 0d464f
Packit 0d464f
        fb.insert ("H",
Packit 0d464f
                   Slice (HALF,
Packit 0d464f
                          (char *) &ph1[0][0],
Packit 0d464f
                          sizeof (ph1[0][0]),
Packit 0d464f
                          sizeof (ph1[0][0]) * width));
Packit 0d464f
Packit 0d464f
        cout << " writing" << flush;
Packit 0d464f
Packit 0d464f
        remove (fileName);
Packit 0d464f
        TiledOutputFile out (fileName, hdr);
Packit 0d464f
        out.setFrameBuffer (fb);
Packit 0d464f
Packit 0d464f
        int i;
Packit 0d464f
        
Packit 0d464f
        Rand32 rand1 = Rand32();
Packit 0d464f
        std::vector<int> tileYs = std::vector<int>(out.numYTiles());
Packit 0d464f
        std::vector<int> tileXs = std::vector<int>(out.numXTiles());
Packit 0d464f
        for (i = 0; i < out.numYTiles(); i++)
Packit 0d464f
        {
Packit 0d464f
            if (lorder == DECREASING_Y)
Packit 0d464f
                tileYs[out.numYTiles()-1-i] = i;    
Packit 0d464f
            else
Packit 0d464f
                tileYs[i] = i;
Packit 0d464f
        }
Packit 0d464f
Packit 0d464f
        for (i = 0; i < out.numXTiles(); i++)
Packit 0d464f
        {
Packit 0d464f
            tileXs[i] = i;
Packit 0d464f
        }
Packit 0d464f
        
Packit 0d464f
        if (triggerBuffering)
Packit 0d464f
        {
Packit 0d464f
            // shuffle the tile orders
Packit 0d464f
            for (i = 0; i < out.numYTiles(); i++)
Packit 0d464f
                std::swap(tileYs[i], tileYs[int(rand1.nextf(i,out.numYTiles()-1) + 0.5)]);
Packit 0d464f
Packit 0d464f
            for (i = 0; i < out.numXTiles(); i++)
Packit 0d464f
                std::swap(tileXs[i], tileXs[int(rand1.nextf(i,out.numXTiles()-1) + 0.5)]);
Packit 0d464f
        }
Packit 0d464f
Packit 0d464f
        for (int tileY = 0; tileY < out.numYTiles(); tileY++)
Packit 0d464f
            for (int tileX = 0; tileX < out.numXTiles(); tileX++)
Packit 0d464f
                out.writeTile (tileXs[tileX], tileYs[tileY]);
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    {
Packit 0d464f
        cout << " reading" << flush;
Packit 0d464f
Packit 0d464f
        TiledInputFile in (fileName);
Packit 0d464f
Packit 0d464f
        const Box2i &dw = in.header().dataWindow();
Packit 0d464f
        int w = dw.max.x - dw.min.x + 1;
Packit 0d464f
        int h = dw.max.y - dw.min.y + 1;
Packit 0d464f
        int dwx = dw.min.x;
Packit 0d464f
        int dwy = dw.min.y;
Packit 0d464f
Packit 0d464f
        Array2D<half> ph2 (h, w);
Packit 0d464f
Packit 0d464f
        FrameBuffer fb;
Packit 0d464f
Packit 0d464f
        fb.insert ("H",
Packit 0d464f
                   Slice (HALF,
Packit 0d464f
                          (char *) &ph2[-dwy][-dwx],
Packit 0d464f
                          sizeof (ph2[0][0]),
Packit 0d464f
                          sizeof (ph2[0][0]) * w));
Packit 0d464f
Packit 0d464f
        in.setFrameBuffer (fb);
Packit 0d464f
        
Packit 0d464f
        int startTileY, endTileY;
Packit 0d464f
        int dy;
Packit 0d464f
Packit 0d464f
        if ((lorder == DECREASING_Y && !triggerSeeks) ||
Packit 0d464f
            (lorder == INCREASING_Y && triggerSeeks) ||
Packit 0d464f
            (lorder == RANDOM_Y && triggerSeeks))
Packit 0d464f
        {
Packit 0d464f
            startTileY = in.numYTiles() - 1;
Packit 0d464f
            endTileY = -1;
Packit 0d464f
Packit 0d464f
            dy = -1;
Packit 0d464f
        }        
Packit 0d464f
        else
Packit 0d464f
        {
Packit 0d464f
            startTileY = 0;
Packit 0d464f
            endTileY = in.numYTiles();
Packit 0d464f
Packit 0d464f
            dy = 1;
Packit 0d464f
        }
Packit 0d464f
    
Packit 0d464f
        for (int tileY = startTileY; tileY != endTileY; tileY += dy)
Packit 0d464f
            for (int tileX = 0; tileX < in.numXTiles(); ++tileX)
Packit 0d464f
                in.readTile (tileX, tileY);
Packit 0d464f
Packit 0d464f
        cout << " comparing" << flush;
Packit 0d464f
Packit 0d464f
        assert (in.header().displayWindow() == hdr.displayWindow());
Packit 0d464f
        assert (in.header().dataWindow() == hdr.dataWindow());
Packit 0d464f
        assert (in.header().pixelAspectRatio() == hdr.pixelAspectRatio());
Packit 0d464f
        assert (in.header().screenWindowCenter() == hdr.screenWindowCenter());
Packit 0d464f
        assert (in.header().screenWindowWidth() == hdr.screenWindowWidth());
Packit 0d464f
        assert (in.header().lineOrder() == hdr.lineOrder());
Packit 0d464f
        assert (in.header().compression() == hdr.compression());
Packit 0d464f
        assert (in.header().channels() == hdr.channels());
Packit 0d464f
Packit 0d464f
        for (int y = 0; y < h; ++y)
Packit 0d464f
            for (int x = 0; x < w; ++x)
Packit 0d464f
            assert (ph1[y][x] == ph2[y][x]);
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    remove (fileName);
Packit 0d464f
    cout << endl;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
writeCopyReadMIP (const char fileName[],
Packit 0d464f
		  int width,
Packit 0d464f
		  int height,
Packit 0d464f
		  LineOrder lorder,
Packit 0d464f
		  LevelRoundingMode rmode,
Packit 0d464f
		  int xSize, 
Packit 0d464f
		  int ySize,
Packit 0d464f
		  Compression comp,
Packit 0d464f
		  bool triggerBuffering,
Packit 0d464f
		  bool triggerSeeks)
Packit 0d464f
{
Packit 0d464f
    cout << "LineOrder " << lorder << ", buffer " << triggerBuffering <<
Packit 0d464f
            ", seek " << triggerSeeks << ", levelMode 1, " <<
Packit 0d464f
	    "roundingMode " << rmode << ", "
Packit 0d464f
	    "compression " << comp << endl;
Packit 0d464f
    
Packit 0d464f
    Header hdr ((Box2i (V2i (0, 0),			// display window
Packit 0d464f
                        V2i (width - 1, height -1))),
Packit 0d464f
                (Box2i (V2i (0, 0),		// data window
Packit 0d464f
                        V2i (width - 1, height - 1))));
Packit 0d464f
Packit 0d464f
    hdr.compression() = comp;
Packit 0d464f
    hdr.lineOrder() = INCREASING_Y;
Packit 0d464f
    hdr.channels().insert ("H", Channel (HALF, 1, 1));
Packit 0d464f
    
Packit 0d464f
    hdr.setTileDescription(TileDescription(xSize, ySize, MIPMAP_LEVELS, rmode));
Packit 0d464f
    
Packit 0d464f
    Array < Array2D<half> > levels;
Packit 0d464f
Packit 0d464f
    {
Packit 0d464f
        cout << " writing" << flush;
Packit 0d464f
Packit 0d464f
        remove (fileName);
Packit 0d464f
        TiledOutputFile out (fileName, hdr);
Packit 0d464f
        
Packit 0d464f
        int numLevels = out.numLevels();
Packit 0d464f
	levels.resizeErase (numLevels);
Packit 0d464f
Packit 0d464f
        int i;
Packit 0d464f
        
Packit 0d464f
        Rand32 rand1 = Rand32();
Packit 0d464f
        std::vector<int> shuffled_levels = std::vector<int>(numLevels);
Packit 0d464f
        
Packit 0d464f
        for (i = 0; i < numLevels; i++)
Packit 0d464f
            shuffled_levels[i] = i;
Packit 0d464f
Packit 0d464f
        if (triggerBuffering)
Packit 0d464f
            // shuffle the level order
Packit 0d464f
            for (i = 0; i < numLevels; i++)
Packit 0d464f
                std::swap(shuffled_levels[i], shuffled_levels[int(rand1.nextf(i,numLevels-1) + 0.5)]);
Packit 0d464f
Packit 0d464f
        for (int level = 0; level < numLevels; ++level)
Packit 0d464f
        {
Packit 0d464f
            const int slevel = shuffled_levels[level];
Packit 0d464f
            
Packit 0d464f
            int levelWidth  = out.levelWidth(slevel);
Packit 0d464f
            int levelHeight = out.levelHeight(slevel);
Packit 0d464f
            levels[slevel].resizeErase(levelHeight, levelWidth);
Packit 0d464f
            fillPixels (levels[slevel], levelWidth, levelHeight);
Packit 0d464f
Packit 0d464f
            FrameBuffer fb; 
Packit 0d464f
Packit 0d464f
            fb.insert ("H",
Packit 0d464f
                       Slice (HALF,
Packit 0d464f
                              (char *) &levels[slevel][0][0],
Packit 0d464f
                              sizeof (levels[slevel][0][0]),
Packit 0d464f
                              sizeof (levels[slevel][0][0]) * levelWidth));
Packit 0d464f
        
Packit 0d464f
            out.setFrameBuffer (fb);
Packit 0d464f
Packit 0d464f
            std::vector<int> tileYs = std::vector<int>(out.numYTiles(slevel));
Packit 0d464f
            std::vector<int> tileXs = std::vector<int>(out.numXTiles(slevel));
Packit 0d464f
            for (i = 0; i < out.numYTiles(slevel); i++)
Packit 0d464f
            {
Packit 0d464f
                if (lorder == DECREASING_Y)
Packit 0d464f
                    tileYs[out.numYTiles(slevel)-1-i] = i;    
Packit 0d464f
                else
Packit 0d464f
                    tileYs[i] = i;
Packit 0d464f
            }
Packit 0d464f
Packit 0d464f
            for (i = 0; i < out.numXTiles(slevel); i++)
Packit 0d464f
                tileXs[i] = i;
Packit 0d464f
            
Packit 0d464f
            if (triggerBuffering)
Packit 0d464f
            {
Packit 0d464f
                // shuffle the tile orders
Packit 0d464f
                for (i = 0; i < out.numYTiles(slevel); i++)
Packit 0d464f
                    std::swap(tileYs[i], tileYs[int(rand1.nextf(i,out.numYTiles(slevel)-1) + 0.5)]);
Packit 0d464f
Packit 0d464f
                for (i = 0; i < out.numXTiles(slevel); i++)
Packit 0d464f
                    std::swap(tileXs[i], tileXs[int(rand1.nextf(i,out.numXTiles(slevel)-1) + 0.5)]);
Packit 0d464f
            }
Packit 0d464f
Packit 0d464f
            for (int tileY = 0; tileY < out.numYTiles(slevel); ++tileY)
Packit 0d464f
                for (int tileX = 0; tileX < out.numXTiles(slevel); ++tileX)
Packit 0d464f
                    out.writeTile (tileXs[tileX], tileYs[tileY], slevel);
Packit 0d464f
        }
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    {
Packit 0d464f
        cout << " reading" << flush;
Packit 0d464f
Packit 0d464f
        TiledInputFile in (fileName);
Packit 0d464f
Packit 0d464f
        const Box2i &dw = in.header().dataWindow();
Packit 0d464f
        int dwx = dw.min.x;
Packit 0d464f
        int dwy = dw.min.y;
Packit 0d464f
Packit 0d464f
        int numLevels = in.numLevels();
Packit 0d464f
        Array < Array2D<half> > levels2 (numLevels);
Packit 0d464f
Packit 0d464f
        int startTileY, endTileY;
Packit 0d464f
        int dy;
Packit 0d464f
        
Packit 0d464f
        for (int level = 0; level < in.numLevels(); ++level)
Packit 0d464f
        {
Packit 0d464f
            int levelWidth = in.levelWidth(level);
Packit 0d464f
            int levelHeight = in.levelHeight(level);
Packit 0d464f
            levels2[level].resizeErase(levelHeight, levelWidth);
Packit 0d464f
Packit 0d464f
            FrameBuffer fb; 
Packit 0d464f
Packit 0d464f
            fb.insert ("H",
Packit 0d464f
                       Slice (HALF,
Packit 0d464f
                              (char *) &levels2[level][-dwy][-dwx],
Packit 0d464f
                              sizeof (levels2[level][0][0]),
Packit 0d464f
                              sizeof (levels2[level][0][0]) * levelWidth));
Packit 0d464f
Packit 0d464f
            in.setFrameBuffer (fb);
Packit 0d464f
            
Packit 0d464f
            if ((lorder == DECREASING_Y && !triggerSeeks) ||
Packit 0d464f
                (lorder == INCREASING_Y && triggerSeeks) ||
Packit 0d464f
                (lorder == RANDOM_Y && triggerSeeks))
Packit 0d464f
            {
Packit 0d464f
                startTileY = in.numYTiles(level) - 1;
Packit 0d464f
                endTileY = -1;
Packit 0d464f
Packit 0d464f
                dy = -1;
Packit 0d464f
            }        
Packit 0d464f
            else
Packit 0d464f
            {
Packit 0d464f
                startTileY = 0;
Packit 0d464f
                endTileY = in.numYTiles(level);
Packit 0d464f
Packit 0d464f
                dy = 1;
Packit 0d464f
            }
Packit 0d464f
            
Packit 0d464f
            for (int tileY = startTileY; tileY != endTileY; tileY += dy)
Packit 0d464f
                for (int tileX = 0; tileX < in.numXTiles (level); ++tileX)
Packit 0d464f
                    in.readTile (tileX, tileY, level);
Packit 0d464f
        }
Packit 0d464f
Packit 0d464f
        cout << " comparing" << flush;
Packit 0d464f
Packit 0d464f
        assert (in.header().displayWindow() == hdr.displayWindow());
Packit 0d464f
        assert (in.header().dataWindow() == hdr.dataWindow());
Packit 0d464f
        assert (in.header().pixelAspectRatio() == hdr.pixelAspectRatio());
Packit 0d464f
        assert (in.header().screenWindowCenter() == hdr.screenWindowCenter());
Packit 0d464f
        assert (in.header().screenWindowWidth() == hdr.screenWindowWidth());
Packit 0d464f
        assert (in.header().lineOrder() == hdr.lineOrder());
Packit 0d464f
        assert (in.header().compression() == hdr.compression());
Packit 0d464f
        assert (in.header().channels() == hdr.channels());
Packit 0d464f
Packit 0d464f
        for (int l = 0; l < numLevels; ++l)
Packit 0d464f
            for (int y = 0; y < in.levelHeight(l); ++y)
Packit 0d464f
                for (int x = 0; x < in.levelWidth(l); ++x)                    
Packit 0d464f
                    assert ((levels2[l])[y][x] == (levels[l])[y][x]);
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    remove (fileName);
Packit 0d464f
    cout << endl;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
writeCopyReadRIP (const char fileName[],
Packit 0d464f
		  int width,
Packit 0d464f
		  int height,
Packit 0d464f
		  LineOrder lorder,
Packit 0d464f
		  LevelRoundingMode rmode,
Packit 0d464f
		  int xSize, 
Packit 0d464f
		  int ySize,
Packit 0d464f
		  Compression comp,
Packit 0d464f
		  bool triggerBuffering,
Packit 0d464f
		  bool triggerSeeks)
Packit 0d464f
{
Packit 0d464f
    cout << "LineOrder " << lorder << ", buffer " << triggerBuffering <<
Packit 0d464f
            ", seek " << triggerSeeks << ", levelMode 2, " <<
Packit 0d464f
	    "roundingMode " << rmode << ", "
Packit 0d464f
	    "compression " << comp << endl;
Packit 0d464f
    
Packit 0d464f
    Header hdr ((Box2i (V2i (0, 0),			// display window
Packit 0d464f
                        V2i (width - 1, height -1))),
Packit 0d464f
                (Box2i (V2i (0, 0),		// data window
Packit 0d464f
                        V2i (width - 1, height - 1))));
Packit 0d464f
Packit 0d464f
    hdr.compression() = comp;
Packit 0d464f
    hdr.lineOrder() = INCREASING_Y;
Packit 0d464f
    hdr.channels().insert ("H", Channel (HALF, 1, 1));
Packit 0d464f
    
Packit 0d464f
    hdr.setTileDescription(TileDescription(xSize, ySize, RIPMAP_LEVELS, rmode));
Packit 0d464f
    
Packit 0d464f
    Array2D < Array2D<half> > levels;
Packit 0d464f
Packit 0d464f
    {
Packit 0d464f
        cout << " writing" << flush;
Packit 0d464f
Packit 0d464f
        remove (fileName);
Packit 0d464f
        TiledOutputFile out (fileName, hdr);
Packit 0d464f
        
Packit 0d464f
	levels.resizeErase (out.numYLevels(), out.numXLevels());
Packit 0d464f
                                     
Packit 0d464f
        int i;
Packit 0d464f
        
Packit 0d464f
        Rand32 rand1 = Rand32();
Packit 0d464f
        std::vector<int> shuffled_xLevels = std::vector<int>(out.numXLevels());
Packit 0d464f
        std::vector<int> shuffled_yLevels = std::vector<int>(out.numYLevels());
Packit 0d464f
        
Packit 0d464f
        for (i = 0; i < out.numXLevels(); i++)
Packit 0d464f
            shuffled_xLevels[i] = i;
Packit 0d464f
        
Packit 0d464f
        for (i = 0; i < out.numYLevels(); i++)
Packit 0d464f
            shuffled_yLevels[i] = i;
Packit 0d464f
Packit 0d464f
        if (triggerBuffering)
Packit 0d464f
        {
Packit 0d464f
            // shuffle the level orders
Packit 0d464f
            for (i = 0; i < out.numXLevels(); i++)
Packit 0d464f
                std::swap(shuffled_xLevels[i], shuffled_xLevels[int(rand1.nextf(i,out.numXLevels()-1) + 0.5)]);
Packit 0d464f
                
Packit 0d464f
            for (i = 0; i < out.numYLevels(); i++)
Packit 0d464f
                std::swap(shuffled_yLevels[i], shuffled_yLevels[int(rand1.nextf(i,out.numYLevels()-1) + 0.5)]);
Packit 0d464f
        }
Packit 0d464f
Packit 0d464f
        for (int ylevel = 0; ylevel < out.numYLevels(); ++ylevel)
Packit 0d464f
        {
Packit 0d464f
            const int sylevel = shuffled_yLevels[ylevel];
Packit 0d464f
            
Packit 0d464f
            std::vector<int> tileYs = std::vector<int>(out.numYTiles(sylevel));
Packit 0d464f
            for (i = 0; i < out.numYTiles(sylevel); i++)
Packit 0d464f
            {
Packit 0d464f
                if (lorder == DECREASING_Y)
Packit 0d464f
                    tileYs[out.numYTiles(sylevel)-1-i] = i;    
Packit 0d464f
                else
Packit 0d464f
                    tileYs[i] = i;
Packit 0d464f
            }
Packit 0d464f
            
Packit 0d464f
            if (triggerBuffering)
Packit 0d464f
                // shuffle the tile orders
Packit 0d464f
                for (i = 0; i < out.numYTiles(sylevel); i++)
Packit 0d464f
                    std::swap(tileYs[i], tileYs[int(rand1.nextf(i,out.numYTiles(sylevel)-1) + 0.5)]);
Packit 0d464f
            
Packit 0d464f
            for (int xlevel = 0; xlevel < out.numXLevels(); ++xlevel)
Packit 0d464f
            {
Packit 0d464f
                const int sxlevel = shuffled_xLevels[xlevel];
Packit 0d464f
                
Packit 0d464f
                int levelWidth = out.levelWidth(sxlevel);
Packit 0d464f
                int levelHeight = out.levelHeight(sylevel);
Packit 0d464f
                levels[sylevel][sxlevel].resizeErase(levelHeight, levelWidth);          
Packit 0d464f
                fillPixels (levels[sylevel][sxlevel], levelWidth, levelHeight);
Packit 0d464f
                
Packit 0d464f
                FrameBuffer fb;
Packit 0d464f
                fb.insert ("H",
Packit 0d464f
                           Slice (HALF,
Packit 0d464f
                                  (char *) &levels[sylevel][sxlevel][0][0],
Packit 0d464f
                                  sizeof (levels[sylevel][sxlevel][0][0]),
Packit 0d464f
                                  sizeof (levels[sylevel][sxlevel][0][0]) * levelWidth));
Packit 0d464f
Packit 0d464f
                out.setFrameBuffer (fb);
Packit 0d464f
    
Packit 0d464f
                std::vector<int> tileXs = std::vector<int>(out.numXTiles(sxlevel));
Packit 0d464f
                for (i = 0; i < out.numXTiles(sxlevel); i++)
Packit 0d464f
                    tileXs[i] = i;
Packit 0d464f
Packit 0d464f
                if (triggerBuffering)
Packit 0d464f
                    // shuffle the tile orders
Packit 0d464f
                    for (i = 0; i < out.numXTiles(sxlevel); i++)
Packit 0d464f
                        std::swap(tileXs[i], tileXs[int(rand1.nextf(i,out.numXTiles(sxlevel)-1) + 0.5)]);
Packit 0d464f
                
Packit 0d464f
                for (int tileY = 0; tileY < out.numYTiles(sylevel); ++tileY)
Packit 0d464f
                    for (int tileX = 0; tileX < out.numXTiles(sxlevel); ++tileX)
Packit 0d464f
                        out.writeTile(tileXs[tileX], tileYs[tileY], sxlevel, sylevel);
Packit 0d464f
            }
Packit 0d464f
        }
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    {
Packit 0d464f
        cout << " reading" << flush;
Packit 0d464f
Packit 0d464f
        TiledInputFile in (fileName);
Packit 0d464f
Packit 0d464f
        const Box2i &dw = in.header().dataWindow();
Packit 0d464f
        int dwx = dw.min.x;
Packit 0d464f
        int dwy = dw.min.y;
Packit 0d464f
Packit 0d464f
        int numXLevels = in.numXLevels();
Packit 0d464f
        int numYLevels = in.numYLevels();
Packit 0d464f
	Array2D < Array2D<half> > levels2 (numYLevels, numXLevels);
Packit 0d464f
Packit 0d464f
        int startTileY, endTileY;
Packit 0d464f
        int dy;
Packit 0d464f
        
Packit 0d464f
        for (int ylevel = 0; ylevel < in.numYLevels(); ++ylevel)
Packit 0d464f
        {
Packit 0d464f
            if ((lorder == DECREASING_Y && !triggerSeeks) ||
Packit 0d464f
                (lorder == INCREASING_Y && triggerSeeks) ||
Packit 0d464f
                (lorder == RANDOM_Y && triggerSeeks))
Packit 0d464f
            {
Packit 0d464f
                startTileY = in.numYTiles(ylevel) - 1;
Packit 0d464f
                endTileY = -1;
Packit 0d464f
Packit 0d464f
                dy = -1;
Packit 0d464f
            }        
Packit 0d464f
            else
Packit 0d464f
            {
Packit 0d464f
                startTileY = 0;
Packit 0d464f
                endTileY = in.numYTiles(ylevel);
Packit 0d464f
Packit 0d464f
                dy = 1;
Packit 0d464f
            }
Packit 0d464f
            
Packit 0d464f
            for (int xlevel = 0; xlevel < in.numXLevels(); ++xlevel)
Packit 0d464f
            {
Packit 0d464f
                int levelWidth  = in.levelWidth(xlevel);
Packit 0d464f
                int levelHeight = in.levelHeight(ylevel);
Packit 0d464f
                levels2[ylevel][xlevel].resizeErase(levelHeight, levelWidth);
Packit 0d464f
Packit 0d464f
                FrameBuffer fb;
Packit 0d464f
                fb.insert ("H",
Packit 0d464f
                           Slice (HALF,
Packit 0d464f
                                  (char *) &levels2[ylevel][xlevel][-dwy][-dwx],
Packit 0d464f
                                  sizeof (levels2[ylevel][xlevel][0][0]),
Packit 0d464f
                                  sizeof (levels2[ylevel][xlevel][0][0]) * levelWidth));
Packit 0d464f
Packit 0d464f
                in.setFrameBuffer (fb);
Packit 0d464f
                
Packit 0d464f
                for (int tileY = startTileY; tileY != endTileY; tileY += dy)
Packit 0d464f
                    for (int tileX = 0; tileX < in.numXTiles (xlevel); ++tileX)
Packit 0d464f
                        in.readTile (tileX, tileY, xlevel, ylevel);
Packit 0d464f
            }
Packit 0d464f
        }
Packit 0d464f
Packit 0d464f
        cout << " comparing" << flush;
Packit 0d464f
Packit 0d464f
        assert (in.header().displayWindow() == hdr.displayWindow());
Packit 0d464f
        assert (in.header().dataWindow() == hdr.dataWindow());
Packit 0d464f
        assert (in.header().pixelAspectRatio() == hdr.pixelAspectRatio());
Packit 0d464f
        assert (in.header().screenWindowCenter() == hdr.screenWindowCenter());
Packit 0d464f
        assert (in.header().screenWindowWidth() == hdr.screenWindowWidth());
Packit 0d464f
        assert (in.header().lineOrder() == hdr.lineOrder());
Packit 0d464f
        assert (in.header().compression() == hdr.compression());
Packit 0d464f
        assert (in.header().channels() == hdr.channels());
Packit 0d464f
Packit 0d464f
        for (int ly = 0; ly < numYLevels; ++ly)
Packit 0d464f
            for (int lx = 0; lx < numXLevels; ++lx)
Packit 0d464f
                for (int y = 0; y < in.levelHeight(ly); ++y)
Packit 0d464f
                    for (int x = 0; x < in.levelWidth(lx); ++x)
Packit 0d464f
                        assert ((levels2[ly][lx])[y][x] ==
Packit 0d464f
                                (levels[ly][lx])[y][x]);
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    remove (fileName);
Packit 0d464f
    cout << endl;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
writeCopyRead (const std::string &tempDir, int w, int h, int xs, int ys)
Packit 0d464f
{
Packit 0d464f
    std::string filename = tempDir + "imf_test_copy.exr";
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
        for (int lorder = 0; lorder < RANDOM_Y; ++lorder)
Packit 0d464f
        {
Packit 0d464f
	    for (int rmode = 0; rmode < NUM_ROUNDINGMODES; ++rmode)
Packit 0d464f
	    {
Packit 0d464f
		for (int tb = 0; tb <= 1; ++tb)
Packit 0d464f
		{
Packit 0d464f
		    for (int ts = 0; ts <= 1; ++ts)
Packit 0d464f
		    {
Packit 0d464f
			writeCopyReadONE (filename.c_str(), w, h,
Packit 0d464f
					  (LineOrder)lorder,
Packit 0d464f
					  (LevelRoundingMode) rmode,
Packit 0d464f
					  xs, ys,
Packit 0d464f
					  Compression (comp),
Packit 0d464f
					  (bool)tb, (bool)ts);
Packit 0d464f
Packit 0d464f
			writeCopyReadMIP (filename.c_str(), w, h,
Packit 0d464f
					  (LineOrder)lorder,
Packit 0d464f
					  (LevelRoundingMode) rmode,
Packit 0d464f
					  xs, ys,
Packit 0d464f
					  Compression (comp),
Packit 0d464f
					  (bool)tb, (bool)ts);
Packit 0d464f
Packit 0d464f
			writeCopyReadRIP (filename.c_str(), w, h,
Packit 0d464f
					  (LineOrder)lorder,
Packit 0d464f
					  (LevelRoundingMode) rmode,
Packit 0d464f
					  xs, ys,
Packit 0d464f
					  Compression (comp),
Packit 0d464f
					  (bool)tb, (bool)ts);
Packit 0d464f
		    }
Packit 0d464f
		}
Packit 0d464f
	    }
Packit 0d464f
        }
Packit 0d464f
    }
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
} // namespace
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
testTiledLineOrder (const std::string &tempDir)
Packit 0d464f
{
Packit 0d464f
    try
Packit 0d464f
    {
Packit 0d464f
        cout << "Testing line orders for tiled files and "
Packit 0d464f
		"buffered/unbuffered tile writes" << endl;
Packit 0d464f
Packit 0d464f
        const int W = 171;
Packit 0d464f
        const int H = 259;
Packit 0d464f
        const int XS = 55;
Packit 0d464f
        const int YS = 55;
Packit 0d464f
Packit 0d464f
	int maxThreads = ILMTHREAD_NAMESPACE::supportsThreads()? 3: 0;
Packit 0d464f
Packit 0d464f
	for (int n = 0; n <= maxThreads; ++n)
Packit 0d464f
	{
Packit 0d464f
	    if (ILMTHREAD_NAMESPACE::supportsThreads())
Packit 0d464f
	    {
Packit 0d464f
		setGlobalThreadCount (n);
Packit 0d464f
		cout << "\nnumber of threads: " << globalThreadCount() << endl;
Packit 0d464f
	    }
Packit 0d464f
Packit 0d464f
	    writeCopyRead (tempDir, W, H, XS, YS);
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
}