Disabled external gits
This commit is contained in:
16
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/.cvsignore
Normal file
16
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/.cvsignore
Normal file
@@ -0,0 +1,16 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
config.h.in
|
||||
config.h
|
||||
config.log
|
||||
config.status
|
||||
configure
|
||||
libtool
|
||||
stamp-h
|
||||
aclocal.m4
|
||||
OpenEXR.pc
|
||||
autom4te.cache
|
||||
ltmain.sh
|
||||
stamp-h.in
|
||||
depcomp
|
||||
.deps
|
||||
74
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/CMakeLists.txt
Normal file
74
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/CMakeLists.txt
Normal file
@@ -0,0 +1,74 @@
|
||||
# yue.nicholas@gmail.com
|
||||
|
||||
# IlmImfTest
|
||||
|
||||
ADD_EXECUTABLE ( IlmImfTest
|
||||
compareB44.cpp
|
||||
compareDwa.cpp
|
||||
compareFloat.cpp
|
||||
main.cpp
|
||||
testAttributes.cpp
|
||||
testBackwardCompatibility.cpp
|
||||
testBadTypeAttributes.cpp
|
||||
testChannels.cpp
|
||||
testCompositeDeepScanLine.cpp
|
||||
testCompression.cpp
|
||||
testConversion.cpp
|
||||
testCopyDeepScanLine.cpp
|
||||
testCopyDeepTiled.cpp
|
||||
testCopyMultiPartFile.cpp
|
||||
testCopyPixels.cpp
|
||||
testCustomAttributes.cpp
|
||||
testDeepScanLineBasic.cpp
|
||||
testDeepScanLineHuge.cpp
|
||||
testDeepScanLineMultipleRead.cpp
|
||||
testDeepTiledBasic.cpp
|
||||
testDwaCompressorSimd.cpp
|
||||
testExistingStreams.cpp
|
||||
testFutureProofing.cpp
|
||||
testHuf.cpp
|
||||
testInputPart.cpp
|
||||
testIsComplete.cpp
|
||||
testLineOrder.cpp
|
||||
testLut.cpp
|
||||
testMagic.cpp
|
||||
testMultiPartApi.cpp
|
||||
testMultiPartFileMixingBasic.cpp
|
||||
testMultiPartSharedAttributes.cpp
|
||||
testMultiPartThreading.cpp
|
||||
testMultiScanlinePartThreading.cpp
|
||||
testMultiTiledPartThreading.cpp
|
||||
testMultiView.cpp
|
||||
testNativeFormat.cpp
|
||||
testOptimized.cpp
|
||||
testOptimizedInterleavePatterns.cpp
|
||||
testPartHelper.cpp
|
||||
testPreviewImage.cpp
|
||||
testRgba.cpp
|
||||
testRgbaThreading.cpp
|
||||
testRle.cpp
|
||||
testSampleImages.cpp
|
||||
testScanLineApi.cpp
|
||||
testSharedFrameBuffer.cpp
|
||||
testStandardAttributes.cpp
|
||||
testTiledCompression.cpp
|
||||
testTiledCopyPixels.cpp
|
||||
testTiledLineOrder.cpp
|
||||
testTiledRgba.cpp
|
||||
testTiledYa.cpp
|
||||
testWav.cpp
|
||||
testXdr.cpp
|
||||
testYca.cpp
|
||||
)
|
||||
|
||||
|
||||
ADD_TEST ( TestIlmImf IlmImfTest )
|
||||
TARGET_LINK_LIBRARIES ( IlmImfTest
|
||||
IlmImf
|
||||
Half
|
||||
Iex${ILMBASE_LIBSUFFIX}
|
||||
Imath${ILMBASE_LIBSUFFIX}
|
||||
IlmThread${ILMBASE_LIBSUFFIX}
|
||||
${PTHREAD_LIB} ${ZLIB_LIBRARIES}
|
||||
)
|
||||
|
||||
84
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/Makefile.am
Normal file
84
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/Makefile.am
Normal file
@@ -0,0 +1,84 @@
|
||||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
check_PROGRAMS = IlmImfTest
|
||||
|
||||
IlmImfTest_SOURCES = main.cpp tmpDir.h testAttributes.cpp testChannels.cpp \
|
||||
testCompression.cpp testCopyPixels.cpp \
|
||||
testCustomAttributes.cpp testHuf.cpp testLineOrder.cpp \
|
||||
testLut.cpp testRgba.cpp testRgbaThreading.cpp \
|
||||
testSampleImages.cpp testSharedFrameBuffer.cpp \
|
||||
testWav.cpp testXdr.cpp testAttributes.h testChannels.h \
|
||||
testCompression.h testCopyPixels.h \
|
||||
testCustomAttributes.h testHuf.h testLineOrder.h \
|
||||
testLut.h testRgba.h testRgbaThreading.h \
|
||||
testSampleImages.h testWav.h testSharedFrameBuffer.h \
|
||||
testXdr.h testConversion.cpp testConversion.h \
|
||||
testNativeFormat.cpp testNativeFormat.h \
|
||||
testPreviewImage.cpp testPreviewImage.h \
|
||||
testMagic.cpp testMagic.h testStandardAttributes.cpp \
|
||||
testStandardAttributes.h testExistingStreams.cpp \
|
||||
testExistingStreams.h testScanLineApi.cpp \
|
||||
testScanLineApi.h testTiledCompression.cpp \
|
||||
testTiledCompression.h testTiledCopyPixels.cpp \
|
||||
testTiledCopyPixels.h testTiledLineOrder.cpp \
|
||||
testTiledLineOrder.h testTiledRgba.cpp \
|
||||
testTiledRgba.h compareFloat.h compareFloat.cpp \
|
||||
testTiledYa.cpp testTiledYa.h \
|
||||
testYca.cpp testYca.h compareB44.h compareB44.cpp \
|
||||
testMultiView.cpp testMultiView.h \
|
||||
testIsComplete.cpp testIsComplete.h \
|
||||
testMultiPartApi.cpp testMultiPartApi.h \
|
||||
testMultiPartThreading.cpp testMultiPartThreading.h \
|
||||
testMultiScanlinePartThreading.cpp testMultiScanlinePartThreading.h \
|
||||
testMultiTiledPartThreading.cpp testMultiTiledPartThreading.h \
|
||||
testDeepScanLineBasic.cpp testDeepScanLineBasic.h \
|
||||
testDeepTiledBasic.cpp testDeepTiledBasic.h \
|
||||
testMultiPartFileMixingBasic.cpp testMultiPartFileMixingBasic.h \
|
||||
testMultiPartSharedAttributes.cpp testMultiPartSharedAttributes.h \
|
||||
testBackwardCompatibility.cpp testBackwardCompatibility.h \
|
||||
testCopyDeepScanLine.cpp testCopyDeepScanLine.h \
|
||||
testCopyDeepTiled.cpp testCopyDeepTiled.h \
|
||||
testCopyMultiPartFile.h testCopyMultiPartFile.cpp \
|
||||
testCompositeDeepScanLine.h testCompositeDeepScanLine.cpp \
|
||||
testInputPart.cpp testInputPart.h \
|
||||
testDeepScanLineMultipleRead.h testDeepScanLineMultipleRead.cpp \
|
||||
testPartHelper.h testPartHelper.cpp \
|
||||
testOptimized.cpp testOptimized.h \
|
||||
testOptimizedInterleavePatterns.cpp testOptimizedInterleavePatterns.h \
|
||||
testBadTypeAttributes.cpp testBadTypeAttributes.h \
|
||||
testFutureProofing.cpp testFutureProofing.h \
|
||||
compareDwa.cpp compareDwa.h \
|
||||
testDwaCompressorSimd.cpp testDwaCompressorSimd.h \
|
||||
testRle.cpp testRle.h
|
||||
|
||||
AM_CPPFLAGS = -DILM_IMF_TEST_IMAGEDIR=\"$(srcdir)/\"
|
||||
|
||||
if BUILD_IMFHUGETEST
|
||||
IlmImfTest_SOURCES += testDeepScanLineHuge.cpp testDeepScanLineHuge.h
|
||||
AM_CPPFLAGS += -DENABLE_IMFHUGETEST
|
||||
endif
|
||||
|
||||
|
||||
INCLUDES = -I$(top_builddir) \
|
||||
-I$(top_srcdir)/IlmImf \
|
||||
-I$(top_srcdir)/config \
|
||||
@ILMBASE_CXXFLAGS@
|
||||
|
||||
LDADD = -L$(top_builddir)/IlmImf \
|
||||
@ILMBASE_LDFLAGS@ @ILMBASE_LIBS@ \
|
||||
-lIlmImf -lz
|
||||
|
||||
TESTS = IlmImfTest
|
||||
|
||||
EXTRA_DIST = comp_none.exr comp_piz.exr comp_rle.exr comp_zip.exr \
|
||||
comp_zips.exr lineOrder_decreasing.exr lineOrder_increasing.exr \
|
||||
test_native1.exr test_native2.exr invalid.exr \
|
||||
tiled.exr comp_b44.exr comp_b44_piz.exr \
|
||||
comp_dwaa_piz.exr comp_dwaa_v1.exr comp_dwaa_v2.exr \
|
||||
comp_dwab_piz.exr comp_dwab_v1.exr comp_dwab_v2.exr \
|
||||
v1.7.test.planar.exr v1.7.test.tiled.exr v1.7.test.1.exr v1.7.test.interleaved.exr \
|
||||
invalid_shared_attrs_multipart.exr \
|
||||
tiled_with_scanlineimage_type.exr scanline_with_tiledimage_type.exr \
|
||||
tiled_with_deepscanline_type.exr tiled_with_deeptile_type.exr \
|
||||
scanline_with_deepscanline_type.exr scanline_with_deeptiled_type.exr \
|
||||
CMakeLists.txt
|
||||
BIN
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/comp_b44.exr
Normal file
BIN
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/comp_b44.exr
Normal file
Binary file not shown.
BIN
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/comp_b44_piz.exr
Normal file
BIN
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/comp_b44_piz.exr
Normal file
Binary file not shown.
BIN
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/comp_dwaa_piz.exr
Normal file
BIN
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/comp_dwaa_piz.exr
Normal file
Binary file not shown.
BIN
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/comp_dwaa_v1.exr
Normal file
BIN
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/comp_dwaa_v1.exr
Normal file
Binary file not shown.
BIN
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/comp_dwaa_v2.exr
Normal file
BIN
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/comp_dwaa_v2.exr
Normal file
Binary file not shown.
BIN
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/comp_dwab_piz.exr
Normal file
BIN
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/comp_dwab_piz.exr
Normal file
Binary file not shown.
BIN
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/comp_dwab_v1.exr
Normal file
BIN
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/comp_dwab_v1.exr
Normal file
Binary file not shown.
BIN
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/comp_dwab_v2.exr
Normal file
BIN
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/comp_dwab_v2.exr
Normal file
Binary file not shown.
BIN
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/comp_none.exr
Normal file
BIN
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/comp_none.exr
Normal file
Binary file not shown.
BIN
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/comp_piz.exr
Normal file
BIN
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/comp_piz.exr
Normal file
Binary file not shown.
BIN
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/comp_rle.exr
Normal file
BIN
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/comp_rle.exr
Normal file
Binary file not shown.
BIN
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/comp_zip.exr
Normal file
BIN
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/comp_zip.exr
Normal file
Binary file not shown.
BIN
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/comp_zips.exr
Normal file
BIN
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/comp_zips.exr
Normal file
Binary file not shown.
374
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/compareB44.cpp
Normal file
374
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/compareB44.cpp
Normal file
@@ -0,0 +1,374 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2006, Industrial Light & Magic, a division of Lucasfilm
|
||||
// Entertainment Company Ltd. Portions contributed and copyright held by
|
||||
// others as indicated. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer.
|
||||
//
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided with
|
||||
// the distribution.
|
||||
//
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// any other contributors to this software may be used to endorse or
|
||||
// promote products derived from this software without specific prior
|
||||
// written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "compareB44.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
|
||||
|
||||
using namespace OPENEXR_IMF_NAMESPACE;
|
||||
using namespace std;
|
||||
|
||||
|
||||
int
|
||||
shiftAndRound (int x, int shift)
|
||||
{
|
||||
x <<= 1;
|
||||
int a = (1 << shift) - 1;
|
||||
shift += 1;
|
||||
int b = (x >> shift) & 1;
|
||||
return (x + a + b) >> shift;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
withinB44ErrorBounds (const half A[4][4], const half B[4][4])
|
||||
{
|
||||
//
|
||||
// Assuming that a 4x4 pixel block, B, was generated by
|
||||
// compressing and uncompressing another pixel block, A,
|
||||
// using OpenEXR's B44 compression method, check whether
|
||||
// the differences between A and B are what we would
|
||||
// expect from the compressor.
|
||||
//
|
||||
|
||||
//
|
||||
// The block may not have been compressed at all if it
|
||||
// was part of a very small tile.
|
||||
//
|
||||
|
||||
bool equal = true;
|
||||
|
||||
for (int i = 0; i < 4; ++i)
|
||||
for (int j = 0; j < 4; ++j)
|
||||
if (A[i][j] != B[i][j])
|
||||
equal = false;
|
||||
|
||||
if (equal)
|
||||
return true;
|
||||
|
||||
//
|
||||
// The block was compressed.
|
||||
//
|
||||
// Perform a "light" version of the B44 compression on A
|
||||
// (see the pack() function in ImfB44Compressor.cpp).
|
||||
//
|
||||
|
||||
unsigned short t[16];
|
||||
|
||||
for (int i = 0; i < 16; ++i)
|
||||
{
|
||||
unsigned short Abits = A[i / 4][i % 4].bits();
|
||||
|
||||
if ((Abits & 0x7c00) == 0x7c00)
|
||||
t[i] = 0x8000;
|
||||
else if (Abits & 0x8000)
|
||||
t[i] = ~Abits;
|
||||
else
|
||||
t[i] = Abits | 0x8000;
|
||||
}
|
||||
|
||||
unsigned short tMax = 0;
|
||||
|
||||
for (int i = 0; i < 16; ++i)
|
||||
if (tMax < t[i])
|
||||
tMax = t[i];
|
||||
|
||||
int shift = -1;
|
||||
int d[16];
|
||||
int r[15];
|
||||
int rMin;
|
||||
int rMax;
|
||||
|
||||
do
|
||||
{
|
||||
shift += 1;
|
||||
|
||||
for (int i = 0; i < 16; ++i)
|
||||
d[i] = shiftAndRound (tMax - t[i], shift);
|
||||
|
||||
const int bias = 0x20;
|
||||
|
||||
r[ 0] = d[ 0] - d[ 4] + bias;
|
||||
r[ 1] = d[ 4] - d[ 8] + bias;
|
||||
r[ 2] = d[ 8] - d[12] + bias;
|
||||
|
||||
r[ 3] = d[ 0] - d[ 1] + bias;
|
||||
r[ 4] = d[ 4] - d[ 5] + bias;
|
||||
r[ 5] = d[ 8] - d[ 9] + bias;
|
||||
r[ 6] = d[12] - d[13] + bias;
|
||||
|
||||
r[ 7] = d[ 1] - d[ 2] + bias;
|
||||
r[ 8] = d[ 5] - d[ 6] + bias;
|
||||
r[ 9] = d[ 9] - d[10] + bias;
|
||||
r[10] = d[13] - d[14] + bias;
|
||||
|
||||
r[11] = d[ 2] - d[ 3] + bias;
|
||||
r[12] = d[ 6] - d[ 7] + bias;
|
||||
r[13] = d[10] - d[11] + bias;
|
||||
r[14] = d[14] - d[15] + bias;
|
||||
|
||||
rMin = r[0];
|
||||
rMax = r[0];
|
||||
|
||||
for (int i = 1; i < 15; ++i)
|
||||
{
|
||||
if (rMin > r[i])
|
||||
rMin = r[i];
|
||||
|
||||
if (rMax < r[i])
|
||||
rMax = r[i];
|
||||
}
|
||||
}
|
||||
while (rMin < 0 || rMax > 0x3f);
|
||||
|
||||
t[0] = tMax - (d[0] << shift);
|
||||
|
||||
//
|
||||
// Now perform a "light" version of the decompression method.
|
||||
// (see the unpack() function in ImfB44Compressor.cpp).
|
||||
//
|
||||
|
||||
unsigned short A1[16];
|
||||
const int bias = 0x20 << shift;
|
||||
|
||||
A1[ 0] = t[ 0];
|
||||
A1[ 4] = A1[ 0] + (r[ 0] << shift) - bias;
|
||||
A1[ 8] = A1[ 4] + (r[ 1] << shift) - bias;
|
||||
A1[12] = A1[ 8] + (r[ 2] << shift) - bias;
|
||||
|
||||
A1[ 1] = A1[ 0] + (r[ 3] << shift) - bias;
|
||||
A1[ 5] = A1[ 4] + (r[ 4] << shift) - bias;
|
||||
A1[ 9] = A1[ 8] + (r[ 5] << shift) - bias;
|
||||
A1[13] = A1[12] + (r[ 6] << shift) - bias;
|
||||
|
||||
A1[ 2] = A1[ 1] + (r[ 7] << shift) - bias;
|
||||
A1[ 6] = A1[ 5] + (r[ 8] << shift) - bias;
|
||||
A1[10] = A1[ 9] + (r[ 9] << shift) - bias;
|
||||
A1[14] = A1[13] + (r[10] << shift) - bias;
|
||||
|
||||
A1[ 3] = A1[ 2] + (r[11] << shift) - bias;
|
||||
A1[ 7] = A1[ 6] + (r[12] << shift) - bias;
|
||||
A1[11] = A1[10] + (r[13] << shift) - bias;
|
||||
A1[15] = A1[14] + (r[14] << shift) - bias;
|
||||
|
||||
//
|
||||
// Compare the result with B, allowing for an difference
|
||||
// of a couple of units in the last place.
|
||||
//
|
||||
|
||||
for (int i = 0; i < 16; ++i)
|
||||
{
|
||||
unsigned short A1bits = A1[i];
|
||||
unsigned short Bbits = B[i / 4][i % 4].bits();
|
||||
|
||||
if (Bbits & 0x8000)
|
||||
Bbits = ~Bbits;
|
||||
else
|
||||
Bbits = Bbits | 0x8000;
|
||||
|
||||
if (Bbits > A1bits + 5 || Bbits < A1bits - 5)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
compareB44 (int width,
|
||||
int height,
|
||||
const Array2D<half> &p1,
|
||||
const Array2D<half> &p2)
|
||||
{
|
||||
for (int y = 0; y < height; y += 4)
|
||||
{
|
||||
for (int x = 0; x < width; x += 4)
|
||||
{
|
||||
half A[4][4];
|
||||
half B[4][4];
|
||||
|
||||
for (int y1 = 0; y1 < 4; ++y1)
|
||||
{
|
||||
for (int x1 = 0; x1 < 4; ++x1)
|
||||
{
|
||||
int y2 = min (y + y1, height - 1);
|
||||
int x2 = min (x + x1, width - 1);
|
||||
A[y1][x1] = p1[y2][x2];
|
||||
B[y1][x1] = p2[y2][x2];
|
||||
}
|
||||
}
|
||||
|
||||
assert (withinB44ErrorBounds (A, B));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
compareB44 (int width,
|
||||
int height,
|
||||
const Array2D<Rgba> &p1,
|
||||
const Array2D<Rgba> &p2,
|
||||
RgbaChannels channels)
|
||||
{
|
||||
if (channels & WRITE_R)
|
||||
{
|
||||
for (int y = 0; y < height; y += 4)
|
||||
{
|
||||
for (int x = 0; x < width; x += 4)
|
||||
{
|
||||
half A[4][4];
|
||||
half B[4][4];
|
||||
|
||||
for (int y1 = 0; y1 < 4; ++y1)
|
||||
{
|
||||
for (int x1 = 0; x1 < 4; ++x1)
|
||||
{
|
||||
int y2 = min (y + y1, height - 1);
|
||||
int x2 = min (x + x1, width - 1);
|
||||
A[y1][x1] = p1[y2][x2].r;
|
||||
B[y1][x1] = p2[y2][x2].r;
|
||||
}
|
||||
}
|
||||
|
||||
assert (withinB44ErrorBounds (A, B));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int y = 0; y < height; y += 1)
|
||||
for (int x = 0; x < width; x += 1)
|
||||
assert (p2[y][x].r == 0);
|
||||
}
|
||||
|
||||
if (channels & WRITE_G)
|
||||
{
|
||||
for (int y = 0; y < height; y += 4)
|
||||
{
|
||||
for (int x = 0; x < width; x += 4)
|
||||
{
|
||||
half A[4][4];
|
||||
half B[4][4];
|
||||
|
||||
for (int y1 = 0; y1 < 4; ++y1)
|
||||
{
|
||||
for (int x1 = 0; x1 < 4; ++x1)
|
||||
{
|
||||
int y2 = min (y + y1, height - 1);
|
||||
int x2 = min (x + x1, width - 1);
|
||||
A[y1][x1] = p1[y2][x2].g;
|
||||
B[y1][x1] = p2[y2][x2].g;
|
||||
}
|
||||
}
|
||||
|
||||
assert (withinB44ErrorBounds (A, B));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int y = 0; y < height; y += 1)
|
||||
for (int x = 0; x < width; x += 1)
|
||||
assert (p2[y][x].g == 0);
|
||||
}
|
||||
|
||||
if (channels & WRITE_B)
|
||||
{
|
||||
for (int y = 0; y < height; y += 4)
|
||||
{
|
||||
for (int x = 0; x < width; x += 4)
|
||||
{
|
||||
half A[4][4];
|
||||
half B[4][4];
|
||||
|
||||
for (int y1 = 0; y1 < 4; ++y1)
|
||||
{
|
||||
for (int x1 = 0; x1 < 4; ++x1)
|
||||
{
|
||||
int y2 = min (y + y1, height - 1);
|
||||
int x2 = min (x + x1, width - 1);
|
||||
A[y1][x1] = p1[y2][x2].b;
|
||||
B[y1][x1] = p2[y2][x2].b;
|
||||
}
|
||||
}
|
||||
|
||||
assert (withinB44ErrorBounds (A, B));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int y = 0; y < height; y += 1)
|
||||
for (int x = 0; x < width; x += 1)
|
||||
assert (p2[y][x].b == 0);
|
||||
}
|
||||
|
||||
if (channels & WRITE_A)
|
||||
{
|
||||
for (int y = 0; y < height; y += 4)
|
||||
{
|
||||
for (int x = 0; x < width; x += 4)
|
||||
{
|
||||
half A[4][4];
|
||||
half B[4][4];
|
||||
|
||||
for (int y1 = 0; y1 < 4; ++y1)
|
||||
{
|
||||
for (int x1 = 0; x1 < 4; ++x1)
|
||||
{
|
||||
int y2 = min (y + y1, height - 1);
|
||||
int x2 = min (x + x1, width - 1);
|
||||
A[y1][x1] = p1[y2][x2].a;
|
||||
B[y1][x1] = p2[y2][x2].a;
|
||||
}
|
||||
}
|
||||
|
||||
assert (withinB44ErrorBounds (A, B));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int y = 0; y < height; y += 1)
|
||||
for (int x = 0; x < width; x += 1)
|
||||
assert (p2[y][x].a == 1);
|
||||
}
|
||||
}
|
||||
54
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/compareB44.h
Normal file
54
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/compareB44.h
Normal file
@@ -0,0 +1,54 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2006, Industrial Light & Magic, a division of Lucasfilm
|
||||
// Entertainment Company Ltd. Portions contributed and copyright held by
|
||||
// others as indicated. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer.
|
||||
//
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided with
|
||||
// the distribution.
|
||||
//
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// any other contributors to this software may be used to endorse or
|
||||
// promote products derived from this software without specific prior
|
||||
// written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#include "ImfNamespace.h"
|
||||
|
||||
#include <ImfRgba.h>
|
||||
#include <ImfArray.h>
|
||||
|
||||
bool withinB44ErrorBounds (const half A[4][4], const half B[4][4]);
|
||||
|
||||
void compareB44 (int width,
|
||||
int height,
|
||||
const OPENEXR_IMF_NAMESPACE::Array2D<half> &p1,
|
||||
const OPENEXR_IMF_NAMESPACE::Array2D<half> &p2);
|
||||
|
||||
void compareB44 (int width,
|
||||
int height,
|
||||
const OPENEXR_IMF_NAMESPACE::Array2D<OPENEXR_IMF_NAMESPACE::Rgba> &p1,
|
||||
const OPENEXR_IMF_NAMESPACE::Array2D<OPENEXR_IMF_NAMESPACE::Rgba> &p2,
|
||||
OPENEXR_IMF_NAMESPACE::RgbaChannels channels);
|
||||
144
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/compareDwa.cpp
Normal file
144
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/compareDwa.cpp
Normal file
@@ -0,0 +1,144 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2009-2014 DreamWorks Animation LLC.
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of DreamWorks Animation nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <math.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "half.h"
|
||||
#include "compareDwa.h"
|
||||
|
||||
using namespace OPENEXR_IMF_NAMESPACE;
|
||||
using namespace std;
|
||||
|
||||
//
|
||||
// Convert from linear to a nonlinear representation,
|
||||
//
|
||||
|
||||
half
|
||||
toNonlinear(half linear)
|
||||
{
|
||||
float sign = 1;
|
||||
float logBase = pow(2.7182818, 2.2);
|
||||
|
||||
if ((float)linear < 0) {
|
||||
sign = -1;
|
||||
}
|
||||
|
||||
if ((linear.bits() & 0x7c00) == 0x7c00) {
|
||||
return (half)0.0;
|
||||
}
|
||||
|
||||
if ( fabs( (float)linear ) <= 1.0f) {
|
||||
return (half)(sign * pow(fabs((float)linear), 1.f/2.2f));
|
||||
} else {
|
||||
return (half)(sign * ( log(fabs((float)linear)) / log(logBase) + 1.0f) );
|
||||
}
|
||||
|
||||
return (half)0.0f;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
compareDwa(int width,
|
||||
int height,
|
||||
const Array2D<Rgba> &src,
|
||||
const Array2D<Rgba> &test,
|
||||
RgbaChannels channels)
|
||||
{
|
||||
half srcNonlin, testNonlin;
|
||||
float relError;
|
||||
|
||||
for (int y=0; y<height; ++y) {
|
||||
for (int x=0; x<width; ++x) {
|
||||
|
||||
for (int comp=0; comp<3; ++comp) {
|
||||
switch (comp) {
|
||||
case 0:
|
||||
if (!(channels & WRITE_R)) continue;
|
||||
|
||||
srcNonlin = toNonlinear(src[y][x].r);
|
||||
testNonlin = toNonlinear(test[y][x].r);
|
||||
break;
|
||||
case 1:
|
||||
if (!(channels & WRITE_G)) continue;
|
||||
|
||||
srcNonlin = toNonlinear(src[y][x].g);
|
||||
testNonlin = toNonlinear(test[y][x].g);
|
||||
break;
|
||||
case 2:
|
||||
if (!(channels & WRITE_B)) continue;
|
||||
|
||||
srcNonlin = toNonlinear(src[y][x].b);
|
||||
testNonlin = toNonlinear(test[y][x].b);
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// Try to compare with relative error. This breaks down
|
||||
// for small numbers, which could be quantiezed to 0
|
||||
// giving 100% error.
|
||||
//
|
||||
if (srcNonlin.bits() != 0x00) {
|
||||
|
||||
relError = fabs( (float)srcNonlin - (float)testNonlin ) /
|
||||
fabs((float)srcNonlin);
|
||||
|
||||
|
||||
if (fabs(srcNonlin) < .1) continue;
|
||||
|
||||
if (fabs(srcNonlin) < .25) {
|
||||
assert( relError < .25);
|
||||
} else {
|
||||
assert( relError < .1);
|
||||
}
|
||||
|
||||
} else {
|
||||
assert( srcNonlin != testNonlin );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Test alpha, if necessary
|
||||
//
|
||||
if (channels & WRITE_A) {
|
||||
for (int y=0; y<height; ++y) {
|
||||
for (int x=0; x<width; ++x) {
|
||||
assert( src[y][x].a == test[y][x].a );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
47
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/compareDwa.h
Normal file
47
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/compareDwa.h
Normal file
@@ -0,0 +1,47 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2009-2014 DreamWorks Animation LLC.
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of DreamWorks Animation nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef COMPARE_DWA_H_INCLUDED
|
||||
#define COMPARE_DWA_H_INCLUDED
|
||||
|
||||
#include "ImfRgba.h"
|
||||
#include "ImfArray.h"
|
||||
#include "ImfNamespace.h"
|
||||
|
||||
void compareDwa(int width,
|
||||
int height,
|
||||
const OPENEXR_IMF_NAMESPACE::Array2D<Imf::Rgba> &src,
|
||||
const OPENEXR_IMF_NAMESPACE::Array2D<Imf::Rgba> &test,
|
||||
OPENEXR_IMF_NAMESPACE::RgbaChannels channels);
|
||||
|
||||
#endif
|
||||
68
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/compareFloat.cpp
Normal file
68
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/compareFloat.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2004, Industrial Light & Magic, a division of Lucasfilm
|
||||
// Entertainment Company Ltd. Portions contributed and copyright held by
|
||||
// others as indicated. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer.
|
||||
//
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided with
|
||||
// the distribution.
|
||||
//
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// any other contributors to this software may be used to endorse or
|
||||
// promote products derived from this software without specific prior
|
||||
// written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "compareFloat.h"
|
||||
|
||||
using namespace OPENEXR_IMF_NAMESPACE;
|
||||
|
||||
bool
|
||||
equivalent (float f1, float f2, Compression comp)
|
||||
{
|
||||
//
|
||||
// Test if a float, f1, is "equivalent" to another float, f2,
|
||||
// which results from storing f1 in an image file, and reading
|
||||
// it back:
|
||||
// If the file was compressed with PXR24_COMPRESSION, then f1
|
||||
// and f2 must the same as f1 rounded to 24 bits (see class
|
||||
// ImfPxr24Compressor); otherwise f1 and f2 must be the same.
|
||||
//
|
||||
|
||||
union
|
||||
{
|
||||
float f;
|
||||
unsigned int i;
|
||||
} u1, u2;
|
||||
|
||||
u1.f = f1;
|
||||
u2.f = f2;
|
||||
|
||||
if (comp == PXR24_COMPRESSION)
|
||||
return (u2.i >> 8) - (u1.i >> 8) < 2;
|
||||
else
|
||||
return u2.i == u1.i;
|
||||
}
|
||||
42
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/compareFloat.h
Normal file
42
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/compareFloat.h
Normal file
@@ -0,0 +1,42 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2004, Industrial Light & Magic, a division of Lucasfilm
|
||||
// Entertainment Company Ltd. Portions contributed and copyright held by
|
||||
// others as indicated. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer.
|
||||
//
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided with
|
||||
// the distribution.
|
||||
//
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// any other contributors to this software may be used to endorse or
|
||||
// promote products derived from this software without specific prior
|
||||
// written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#include "ImfNamespace.h"
|
||||
#include "ImfCompression.h"
|
||||
|
||||
bool equivalent (float f1, float f2, OPENEXR_IMF_NAMESPACE::Compression comp);
|
||||
|
||||
2
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/invalid.exr
Normal file
2
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/invalid.exr
Normal file
@@ -0,0 +1,2 @@
|
||||
this is not a valid EXR file
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
236
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/main.cpp
Normal file
236
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/main.cpp
Normal file
@@ -0,0 +1,236 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2004-2013, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "ImfNamespace.h"
|
||||
|
||||
#include "testXdr.h"
|
||||
#include "testMagic.h"
|
||||
#include "testHuf.h"
|
||||
#include "testWav.h"
|
||||
#include "testChannels.h"
|
||||
#include "testAttributes.h"
|
||||
#include "testCustomAttributes.h"
|
||||
#include "testLineOrder.h"
|
||||
#include "testCompression.h"
|
||||
#include "testCopyPixels.h"
|
||||
#include "testRgba.h"
|
||||
#include "testRgbaThreading.h"
|
||||
#include "testLut.h"
|
||||
#include "testSampleImages.h"
|
||||
#include "testPreviewImage.h"
|
||||
#include "testConversion.h"
|
||||
#include "testStandardAttributes.h"
|
||||
#include "testNativeFormat.h"
|
||||
#include "testTiledRgba.h"
|
||||
#include "testTiledCompression.h"
|
||||
#include "testTiledCopyPixels.h"
|
||||
#include "testTiledLineOrder.h"
|
||||
#include "testScanLineApi.h"
|
||||
#include "testExistingStreams.h"
|
||||
#include "testYca.h"
|
||||
#include "testTiledYa.h"
|
||||
#include "testIsComplete.h"
|
||||
#include "testSharedFrameBuffer.h"
|
||||
#include "testMultiView.h"
|
||||
#include "testMultiPartApi.h"
|
||||
#include "testMultiPartSharedAttributes.h"
|
||||
#include "testMultiPartThreading.h"
|
||||
#include "testMultiScanlinePartThreading.h"
|
||||
#include "testMultiTiledPartThreading.h"
|
||||
#include "testDeepScanLineBasic.h"
|
||||
#include "testCopyDeepScanLine.h"
|
||||
#include "testDeepScanLineMultipleRead.h"
|
||||
#include "testDeepScanLineHuge.h"
|
||||
#include "testDeepTiledBasic.h"
|
||||
#include "testCopyDeepTiled.h"
|
||||
#include "testCompositeDeepScanLine.h"
|
||||
#include "testMultiPartFileMixingBasic.h"
|
||||
#include "testInputPart.h"
|
||||
#include "testBackwardCompatibility.h"
|
||||
#include "testCopyMultiPartFile.h"
|
||||
#include "testPartHelper.h"
|
||||
#include "testOptimized.h"
|
||||
#include "testOptimizedInterleavePatterns.h"
|
||||
#include "testBadTypeAttributes.h"
|
||||
#include "testFutureProofing.h"
|
||||
#include "testPartHelper.h"
|
||||
#include "testDwaCompressorSimd.h"
|
||||
#include "testRle.h"
|
||||
|
||||
#include "tmpDir.h"
|
||||
#include "ImathRandom.h"
|
||||
|
||||
// system includes
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <iostream>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#if defined(OPENEXR_IMF_HAVE_LINUX_PROCFS) || defined(OPENEXR_IMF_HAVE_DARWIN)
|
||||
#include <unistd.h>
|
||||
#include <sstream>
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
|
||||
#define TEST(x,y) \
|
||||
if (argc < 2 || (!strcmp (argv[1], #x) || !strcmp (argv[1], y))) \
|
||||
{ \
|
||||
cout << "\n=======\nRunning " << #x <<endl; \
|
||||
x(tempDir); \
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
// Create temporary files in a uniquely named private temporary
|
||||
// subdirectory of IMF_TMP_DIR to avoid colliding with other
|
||||
// running instances of this program.
|
||||
|
||||
IMATH_NAMESPACE::Rand48 rand48 (time ((time_t*)0) );
|
||||
std::string tempDir;
|
||||
|
||||
while (true)
|
||||
{
|
||||
tempDir = IMF_TMP_DIR "IlmImfTest_";
|
||||
|
||||
for (int i = 0; i < 8; ++i)
|
||||
tempDir += ('A' + rand48.nexti() % 26);
|
||||
|
||||
std::cout << "tempDir = " << tempDir << std::endl;
|
||||
|
||||
int status = mkdir(tempDir.c_str(), 0777);
|
||||
|
||||
if (status == 0)
|
||||
{
|
||||
tempDir += IMF_PATH_SEPARATOR;
|
||||
break; // success
|
||||
}
|
||||
|
||||
if (errno != EEXIST)
|
||||
{
|
||||
std::cerr << "ERROR -- mkdir(" << tempDir << ") failed: "
|
||||
"errno = " << errno << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
TEST (testMagic, "core");
|
||||
TEST (testXdr, "core");
|
||||
TEST (testHuf, "core");
|
||||
TEST (testWav, "core");
|
||||
TEST (testRgba, "basic");
|
||||
TEST (testSharedFrameBuffer, "basic");
|
||||
TEST (testRgbaThreading, "basic");
|
||||
TEST (testChannels, "basic");
|
||||
TEST (testAttributes, "core");
|
||||
TEST (testCustomAttributes, "core");
|
||||
TEST (testLineOrder, "basic");
|
||||
TEST (testCompression, "basic");
|
||||
TEST (testCopyPixels, "basic");
|
||||
TEST (testLut, "basic");
|
||||
TEST (testSampleImages, "basic");
|
||||
TEST (testPreviewImage, "basic");
|
||||
TEST (testConversion, "basic");
|
||||
TEST (testTiledRgba, "basic");
|
||||
TEST (testTiledCopyPixels, "basic");
|
||||
TEST (testTiledCompression, "basic");
|
||||
TEST (testTiledLineOrder, "basic");
|
||||
TEST (testScanLineApi, "basic");
|
||||
TEST (testExistingStreams, "core");
|
||||
TEST (testStandardAttributes, "core");
|
||||
TEST (testOptimized, "basic");
|
||||
TEST (testOptimizedInterleavePatterns, "basic");
|
||||
TEST (testYca, "basic");
|
||||
TEST (testTiledYa, "basic");
|
||||
TEST (testNativeFormat, "basic");
|
||||
TEST (testMultiView, "basic");
|
||||
TEST (testIsComplete, "basic");
|
||||
TEST (testDeepScanLineBasic, "deep");
|
||||
TEST (testCopyDeepScanLine, "deep");
|
||||
TEST (testDeepScanLineMultipleRead, "deep");
|
||||
TEST (testDeepTiledBasic, "deep");
|
||||
TEST (testCopyDeepTiled, "deep");
|
||||
TEST (testCompositeDeepScanLine, "deep");
|
||||
TEST (testMultiPartFileMixingBasic, "multi");
|
||||
TEST (testInputPart, "multi");
|
||||
TEST (testPartHelper, "multi");
|
||||
TEST (testBadTypeAttributes, "multi");
|
||||
TEST (testMultiScanlinePartThreading, "multi");
|
||||
TEST (testMultiTiledPartThreading, "multi");
|
||||
TEST (testMultiPartThreading, "multi");
|
||||
TEST (testMultiPartApi, "multi");
|
||||
TEST (testMultiPartSharedAttributes, "multi");
|
||||
TEST (testCopyMultiPartFile, "multi");
|
||||
TEST (testBackwardCompatibility, "core");
|
||||
TEST (testFutureProofing, "core");
|
||||
TEST (testDwaCompressorSimd, "basic");
|
||||
TEST (testRle, "core");
|
||||
|
||||
|
||||
//#ifdef ENABLE_IMFHUGETEST
|
||||
// defined via configure with --enable-imfhugetest=yes/no
|
||||
#if 0
|
||||
TEST (testDeepScanLineHuge, "deep");
|
||||
#endif
|
||||
|
||||
|
||||
std::cout << "removing temp dir " << tempDir << std::endl;
|
||||
rmdir (tempDir.c_str());
|
||||
|
||||
#ifdef OPENEXR_IMF_HAVE_LINUX_PROCFS
|
||||
|
||||
//
|
||||
// Allow the user to check for file descriptor leaks
|
||||
//
|
||||
|
||||
std::cout << "open file descriptors:" << std::endl;
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "ls -lG /proc/" << getpid() << "/fd";
|
||||
|
||||
if (system (ss.str().c_str()) == -1)
|
||||
{
|
||||
std::cout << "failed to run ls\n";
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
537
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testAttributes.cpp
Normal file
537
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testAttributes.cpp
Normal file
@@ -0,0 +1,537 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2004-2012, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#include <tmpDir.h>
|
||||
|
||||
#include <ImfOutputFile.h>
|
||||
#include <ImfInputFile.h>
|
||||
#include <ImfChannelList.h>
|
||||
#include <ImfArray.h>
|
||||
#include <ImfVersion.h>
|
||||
#include <half.h>
|
||||
|
||||
#include <ImfBoxAttribute.h>
|
||||
#include <ImfChannelListAttribute.h>
|
||||
#include <ImfCompressionAttribute.h>
|
||||
#include <ImfChromaticitiesAttribute.h>
|
||||
#include <ImfFloatAttribute.h>
|
||||
#include <ImfFloatVectorAttribute.h>
|
||||
#include <ImfEnvmapAttribute.h>
|
||||
#include <ImfDeepImageStateAttribute.h>
|
||||
#include <ImfDoubleAttribute.h>
|
||||
#include <ImfIntAttribute.h>
|
||||
#include <ImfLineOrderAttribute.h>
|
||||
#include <ImfMatrixAttribute.h>
|
||||
#include <ImfOpaqueAttribute.h>
|
||||
#include <ImfStringAttribute.h>
|
||||
#include <ImfStringVectorAttribute.h>
|
||||
#include <ImfVecAttribute.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
namespace IMF = OPENEXR_IMF_NAMESPACE;
|
||||
using namespace IMF;
|
||||
|
||||
using namespace std;
|
||||
using namespace IMATH_NAMESPACE;
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
void
|
||||
fillPixels (Array2D<float> &pf, int width, int height)
|
||||
{
|
||||
for (int y = 0; y < height; ++y)
|
||||
for (int x = 0; x < width; ++x)
|
||||
pf[y][x] = x % 10 + 10 * (y % 17);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
writeReadAttr (const Array2D<float> &pf1,
|
||||
const char fileName[],
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
//
|
||||
// We don't test ChannelList, LineOrder, Compression and opaque
|
||||
// attributes here; those types are covered by other tests.
|
||||
//
|
||||
|
||||
Box2i a1 (V2i (1, 2), V2i (3, 4));
|
||||
Box2f a2 (V2f (1.5, 2.5), V2f (3.5, 4.5));
|
||||
float a3 (3.14159);
|
||||
int a4 (17);
|
||||
M33f a5 (11, 12, 13, 14, 15, 16, 17, 18, 19);
|
||||
M44f a6 (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
|
||||
string a7 ("extensive rebuilding by Nebuchadrezzar has left");
|
||||
V2i a8 (27, 28);
|
||||
V2f a9 (27.5, 28.5);
|
||||
V3i a10 (37, 38, 39);
|
||||
V3f a11 (37.5, 38.5, 39.5);
|
||||
double a12 (7.12342341419);
|
||||
Chromaticities a13 (V2f (1, 2), V2f (3, 4), V2f (5, 6), V2f (7, 8));
|
||||
Envmap a14 (ENVMAP_CUBE);
|
||||
|
||||
StringVector a15;
|
||||
a15.push_back ("who can spin");
|
||||
a15.push_back ("");
|
||||
a15.push_back ("straw into");
|
||||
a15.push_back ("gold");
|
||||
M33d a16 (12, 13, 14, 15, 16, 17, 18, 19, 20);
|
||||
M44d a17 (2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17);
|
||||
V2d a18 (27.51, 28.51);
|
||||
V3d a19 (37.51, 38.51, 39.51);
|
||||
|
||||
StringVector a20;
|
||||
|
||||
DeepImageState a21 (DIS_TIDY);
|
||||
|
||||
FloatVector a22;
|
||||
FloatVector a23;
|
||||
a23.push_back (1.5f);
|
||||
a23.push_back (-1.5f);
|
||||
a23.push_back (15.0f);
|
||||
a23.push_back (150.0f);
|
||||
|
||||
//
|
||||
// Write an image file with extra attributes in the header
|
||||
//
|
||||
|
||||
{
|
||||
Header hdr (width, height);
|
||||
|
||||
hdr.insert ("a1", Box2iAttribute (a1));
|
||||
hdr.insert ("a2", Box2fAttribute (a2));
|
||||
hdr.insert ("a3", FloatAttribute (a3));
|
||||
hdr.insert ("a4", IntAttribute (a4));
|
||||
hdr.insert ("a5", M33fAttribute (a5));
|
||||
hdr.insert ("a6", M44fAttribute (a6));
|
||||
hdr.insert ("a7", StringAttribute (a7));
|
||||
hdr.insert ("a8", V2iAttribute (a8));
|
||||
hdr.insert ("a9", V2fAttribute (a9));
|
||||
hdr.insert ("a10", V3iAttribute (a10));
|
||||
hdr.insert ("a11", V3fAttribute (a11));
|
||||
hdr.insert ("a12", DoubleAttribute (a12));
|
||||
hdr.insert ("a13", ChromaticitiesAttribute (a13));
|
||||
hdr.insert ("a14", EnvmapAttribute (a14));
|
||||
hdr.insert ("a15", StringVectorAttribute (a15));
|
||||
hdr.insert ("a16", M33dAttribute (a16));
|
||||
hdr.insert ("a17", M44dAttribute (a17));
|
||||
hdr.insert ("a18", V2dAttribute (a18));
|
||||
hdr.insert ("a19", V3dAttribute (a19));
|
||||
hdr.insert ("a20", StringVectorAttribute (a20));
|
||||
hdr.insert ("a21", DeepImageStateAttribute (a21));
|
||||
hdr.insert ("a22", FloatVectorAttribute (a22));
|
||||
hdr.insert ("a23", FloatVectorAttribute (a23));
|
||||
|
||||
hdr.channels().insert ("F", // name
|
||||
Channel (IMF::FLOAT, // type
|
||||
1, // xSampling
|
||||
1) // ySampling
|
||||
);
|
||||
|
||||
FrameBuffer fb;
|
||||
|
||||
fb.insert ("F", // name
|
||||
Slice (IMF::FLOAT, // type
|
||||
(char *) &pf1[0][0], // base
|
||||
sizeof (pf1[0][0]), // xStride
|
||||
sizeof (pf1[0][0]) * width, // yStride
|
||||
1, // xSampling
|
||||
1) // ySampling
|
||||
);
|
||||
|
||||
cout << "writing" << flush;
|
||||
|
||||
remove (fileName);
|
||||
OutputFile out (fileName, hdr);
|
||||
out.setFrameBuffer (fb);
|
||||
out.writePixels (height);
|
||||
}
|
||||
|
||||
//
|
||||
// Read the header back from the file, and see if the
|
||||
// values of the extra attributes come back correctly.
|
||||
//
|
||||
|
||||
{
|
||||
cout << " reading" << flush;
|
||||
|
||||
InputFile in (fileName);
|
||||
|
||||
cout << " (version " << in.version() << ")" << flush;
|
||||
|
||||
const Header &hdr = in.header();
|
||||
|
||||
assert (hdr.typedAttribute <Box2iAttribute> ("a1").value() == a1);
|
||||
assert (hdr.typedAttribute <Box2fAttribute> ("a2").value() == a2);
|
||||
assert (hdr.typedAttribute <FloatAttribute> ("a3").value() == a3);
|
||||
assert (hdr.typedAttribute <IntAttribute> ("a4").value() == a4);
|
||||
assert (hdr.typedAttribute <M33fAttribute> ("a5").value() == a5);
|
||||
assert (hdr.typedAttribute <M44fAttribute> ("a6").value() == a6);
|
||||
assert (hdr.typedAttribute <StringAttribute> ("a7").value() == a7);
|
||||
assert (hdr.typedAttribute <V2iAttribute> ("a8").value() == a8);
|
||||
assert (hdr.typedAttribute <V2fAttribute> ("a9").value() == a9);
|
||||
assert (hdr.typedAttribute <V3iAttribute> ("a10").value() == a10);
|
||||
assert (hdr.typedAttribute <V3fAttribute> ("a11").value() == a11);
|
||||
assert (hdr.typedAttribute <DoubleAttribute> ("a12").value() == a12);
|
||||
|
||||
assert (hdr.typedAttribute <ChromaticitiesAttribute>
|
||||
("a13").value().red == a13.red);
|
||||
|
||||
assert (hdr.typedAttribute <ChromaticitiesAttribute>
|
||||
("a13").value().green == a13.green);
|
||||
|
||||
assert (hdr.typedAttribute <ChromaticitiesAttribute>
|
||||
("a13").value().blue == a13.blue);
|
||||
|
||||
assert (hdr.typedAttribute <ChromaticitiesAttribute>
|
||||
("a13").value().white == a13.white);
|
||||
|
||||
assert (hdr.typedAttribute <EnvmapAttribute> ("a14").value() == a14);
|
||||
|
||||
assert (hdr.typedAttribute <StringVectorAttribute>
|
||||
("a15").value().size() == 4);
|
||||
|
||||
assert (hdr.typedAttribute <StringVectorAttribute>
|
||||
("a15").value()[0] == "who can spin");
|
||||
|
||||
assert (hdr.typedAttribute <StringVectorAttribute>
|
||||
("a15").value()[1] == "");
|
||||
|
||||
assert (hdr.typedAttribute <StringVectorAttribute>
|
||||
("a15").value()[2] == "straw into");
|
||||
|
||||
assert (hdr.typedAttribute <StringVectorAttribute>
|
||||
("a15").value()[3] == "gold");
|
||||
|
||||
assert (hdr.typedAttribute <M33dAttribute> ("a16").value() == a16);
|
||||
assert (hdr.typedAttribute <M44dAttribute> ("a17").value() == a17);
|
||||
assert (hdr.typedAttribute <V2dAttribute> ("a18").value() == a18);
|
||||
assert (hdr.typedAttribute <V3dAttribute> ("a19").value() == a19);
|
||||
|
||||
assert (hdr.typedAttribute <StringVectorAttribute>
|
||||
("a20").value() == a20);
|
||||
|
||||
assert (hdr.typedAttribute <DeepImageStateAttribute>
|
||||
("a21").value() == a21);
|
||||
|
||||
assert (hdr.typedAttribute <FloatVectorAttribute>
|
||||
("a22").value() == a22);
|
||||
|
||||
assert (hdr.typedAttribute <FloatVectorAttribute>
|
||||
("a23").value() == a23);
|
||||
}
|
||||
|
||||
remove (fileName);
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
channelList ()
|
||||
{
|
||||
cout << "channel list" << endl;
|
||||
|
||||
{
|
||||
// test channelsWithPrefix()
|
||||
|
||||
ChannelList channels;
|
||||
|
||||
channels.insert ("b0", Channel (IMF::HALF, 1, 1));
|
||||
channels.insert ("b1", Channel (IMF::HALF, 1, 1));
|
||||
channels.insert ("b2", Channel (IMF::HALF, 1, 1));
|
||||
channels.insert ("d3", Channel (IMF::HALF, 1, 1));
|
||||
channels.insert ("e4", Channel (IMF::HALF, 1, 1));
|
||||
|
||||
ChannelList::Iterator first;
|
||||
ChannelList::Iterator last;
|
||||
|
||||
channels.channelsWithPrefix ("a", first, last);
|
||||
assert (first != channels.end());
|
||||
assert (first == last);
|
||||
|
||||
channels.channelsWithPrefix ("b", first, last);
|
||||
assert (first != channels.end());
|
||||
assert (first != last);
|
||||
assert (first++.name() == Name ("b0"));
|
||||
assert (first++.name() == Name ("b1"));
|
||||
assert (first++.name() == Name ("b2"));
|
||||
assert (first == last);
|
||||
|
||||
channels.channelsWithPrefix ("b1", first, last);
|
||||
assert (first != channels.end());
|
||||
assert (first != last);
|
||||
assert (first++.name() == Name ("b1"));
|
||||
assert (first == last);
|
||||
|
||||
channels.channelsWithPrefix ("b11", first, last);
|
||||
assert (first != channels.end());
|
||||
assert (first == last);
|
||||
|
||||
channels.channelsWithPrefix ("c", first, last);
|
||||
assert (first != channels.end());
|
||||
assert (first == last);
|
||||
|
||||
channels.channelsWithPrefix ("d", first, last);
|
||||
assert (first != channels.end());
|
||||
assert (first != last);
|
||||
assert (first++.name() == Name ("d3"));
|
||||
assert (first == last);
|
||||
|
||||
channels.channelsWithPrefix ("e", first, last);
|
||||
assert (first != channels.end());
|
||||
assert (first != last);
|
||||
assert (first++.name() == Name ("e4"));
|
||||
assert (first == last);
|
||||
|
||||
channels.channelsWithPrefix ("f", first, last);
|
||||
assert (first == channels.end());
|
||||
assert (first == last);
|
||||
}
|
||||
|
||||
{
|
||||
// Test support for layers
|
||||
|
||||
ChannelList channels;
|
||||
|
||||
channels.insert ("a", Channel (IMF::HALF, 1, 1));
|
||||
channels.insert (".a", Channel (IMF::HALF, 1, 1));
|
||||
channels.insert ("a.", Channel (IMF::HALF, 1, 1));
|
||||
|
||||
channels.insert ("layer1.R", Channel (IMF::HALF, 1, 1));
|
||||
channels.insert ("layer1.G", Channel (IMF::HALF, 1, 1));
|
||||
channels.insert ("layer1.B", Channel (IMF::HALF, 1, 1));
|
||||
|
||||
channels.insert ("layer1.sublayer1.AA", Channel (IMF::HALF, 1, 1));
|
||||
channels.insert ("layer1.sublayer1.R", Channel (IMF::HALF, 1, 1));
|
||||
channels.insert ("layer1.sublayer1.G", Channel (IMF::HALF, 1, 1));
|
||||
channels.insert ("layer1.sublayer1.B", Channel (IMF::HALF, 1, 1));
|
||||
|
||||
channels.insert ("layer1.sublayer2.R", Channel (IMF::HALF, 1, 1));
|
||||
|
||||
channels.insert ("layer2.R", Channel (IMF::HALF, 1, 1));
|
||||
channels.insert ("layer2.G", Channel (IMF::HALF, 1, 1));
|
||||
channels.insert ("layer2.B", Channel (IMF::HALF, 1, 1));
|
||||
|
||||
set <string> layerNames;
|
||||
channels.layers (layerNames);
|
||||
|
||||
set<string>::iterator i = layerNames.begin();
|
||||
assert (*i++ == "layer1");
|
||||
assert (*i++ == "layer1.sublayer1");
|
||||
assert (*i++ == "layer1.sublayer2");
|
||||
assert (*i++ == "layer2");
|
||||
assert (i == layerNames.end());
|
||||
|
||||
ChannelList::ConstIterator first, last;
|
||||
|
||||
channels.channelsInLayer ("layer1.sublayer1", first, last);
|
||||
assert (first != channels.end());
|
||||
assert (first != last);
|
||||
assert (first++.name() == Name ("layer1.sublayer1.AA"));
|
||||
assert (first++.name() == Name ("layer1.sublayer1.B"));
|
||||
assert (first++.name() == Name ("layer1.sublayer1.G"));
|
||||
assert (first++.name() == Name ("layer1.sublayer1.R"));
|
||||
assert (first == last);
|
||||
|
||||
channels.channelsInLayer ("layer2", first, last);
|
||||
assert (first != channels.end());
|
||||
assert (first != last);
|
||||
assert (first++.name() == Name ("layer2.B"));
|
||||
assert (first++.name() == Name ("layer2.G"));
|
||||
assert (first++.name() == Name ("layer2.R"));
|
||||
assert (first == last);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
longNames (const Array2D<float> &pf1,
|
||||
const char fileName[],
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
//
|
||||
// Verify that long attibute or channel names in the header
|
||||
// set the LONG_NAMES_FLAG in the file version number.
|
||||
//
|
||||
|
||||
FrameBuffer fb;
|
||||
|
||||
fb.insert ("F", // name
|
||||
Slice (IMF::FLOAT, // type
|
||||
(char *) &pf1[0][0], // base
|
||||
sizeof (pf1[0][0]), // xStride
|
||||
sizeof (pf1[0][0]) * width, // yStride
|
||||
1, // xSampling
|
||||
1) // ySampling
|
||||
);
|
||||
|
||||
cout << "only short names" << endl;
|
||||
|
||||
{
|
||||
Header hdr (width, height);
|
||||
|
||||
hdr.channels().insert ("F", // name
|
||||
Channel (IMF::FLOAT, // type
|
||||
1, // xSampling
|
||||
1) // ySampling
|
||||
);
|
||||
|
||||
|
||||
cout << "writing" << flush;
|
||||
|
||||
remove (fileName);
|
||||
OutputFile out (fileName, hdr);
|
||||
out.setFrameBuffer (fb);
|
||||
out.writePixels (height);
|
||||
}
|
||||
|
||||
{
|
||||
cout << " reading" << endl;
|
||||
|
||||
InputFile in (fileName);
|
||||
assert (!(in.version() & LONG_NAMES_FLAG));
|
||||
}
|
||||
|
||||
static const char longName[] = "x2345678901234567890123456789012";
|
||||
|
||||
cout << "long attribute name" << endl;
|
||||
|
||||
{
|
||||
Header hdr (width, height);
|
||||
hdr.insert (longName, StringAttribute ("y"));
|
||||
|
||||
hdr.channels().insert ("F", // name
|
||||
Channel (IMF::FLOAT, // type
|
||||
1, // xSampling
|
||||
1) // ySampling
|
||||
);
|
||||
|
||||
cout << "writing" << flush;
|
||||
|
||||
remove (fileName);
|
||||
OutputFile out (fileName, hdr);
|
||||
out.setFrameBuffer (fb);
|
||||
out.writePixels (height);
|
||||
}
|
||||
|
||||
{
|
||||
cout << " reading" << endl;
|
||||
|
||||
InputFile in (fileName);
|
||||
assert (in.version() & LONG_NAMES_FLAG);
|
||||
|
||||
const Header &hdr = in.header();
|
||||
assert (hdr.typedAttribute <StringAttribute> (longName).value() == "y");
|
||||
}
|
||||
|
||||
cout << "long channel name" << endl;
|
||||
|
||||
{
|
||||
Header hdr (width, height);
|
||||
|
||||
hdr.channels().insert (longName, // name
|
||||
Channel (IMF::FLOAT, // type
|
||||
1, // xSampling
|
||||
1) // ySampling
|
||||
);
|
||||
|
||||
cout << "writing" << flush;
|
||||
|
||||
remove (fileName);
|
||||
OutputFile out (fileName, hdr);
|
||||
out.setFrameBuffer (fb);
|
||||
out.writePixels (height);
|
||||
}
|
||||
|
||||
{
|
||||
cout << " reading" << endl;
|
||||
|
||||
InputFile in (fileName);
|
||||
assert (in.version() & LONG_NAMES_FLAG);
|
||||
|
||||
const Header &hdr = in.header();
|
||||
assert (hdr.channels().findChannel (longName));
|
||||
}
|
||||
|
||||
remove (fileName);
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
template<class T> void
|
||||
print_type(const OPENEXR_IMF_NAMESPACE::TypedAttribute<T> & object)
|
||||
{
|
||||
cout << object.typeName() << endl;
|
||||
}
|
||||
|
||||
void
|
||||
testAttributes (const std::string &tempDir)
|
||||
{
|
||||
try
|
||||
{
|
||||
cout << "Testing built-in attributes" << endl;
|
||||
|
||||
const int W = 217;
|
||||
const int H = 197;
|
||||
|
||||
Array2D<float> pf (H, W);
|
||||
fillPixels (pf, W, H);
|
||||
|
||||
std::string filename = tempDir + "imf_test_attr.exr";
|
||||
|
||||
writeReadAttr (pf, filename.c_str(), W, H);
|
||||
channelList();
|
||||
longNames(pf, filename.c_str(), W, H);
|
||||
|
||||
print_type(OPENEXR_IMF_NAMESPACE::TypedAttribute<int>());
|
||||
|
||||
cout << "ok\n" << endl;
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
cerr << "ERROR -- caught exception: " << e.what() << endl;
|
||||
assert (false);
|
||||
}
|
||||
}
|
||||
41
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testAttributes.h
Normal file
41
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testAttributes.h
Normal file
@@ -0,0 +1,41 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
#include <string>
|
||||
|
||||
void testAttributes (const std::string &tempDir);
|
||||
|
||||
@@ -0,0 +1,393 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2012, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "testBackwardCompatibility.h"
|
||||
|
||||
#include <ImfArray.h>
|
||||
#include <ImfHeader.h>
|
||||
#include <IlmThreadPool.h>
|
||||
#include <ImfFrameBuffer.h>
|
||||
#include <ImfOutputFile.h>
|
||||
#include <ImfPreviewImage.h>
|
||||
#include <ImfTiledOutputFile.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <tmpDir.h>
|
||||
#include <ImathBox.h>
|
||||
#include <ImfChannelList.h>
|
||||
#include <IexMacros.h>
|
||||
|
||||
#include <ImfBoxAttribute.h>
|
||||
#include <ImfChannelListAttribute.h>
|
||||
#include <ImfCompressionAttribute.h>
|
||||
#include <ImfChromaticitiesAttribute.h>
|
||||
#include <ImfFloatAttribute.h>
|
||||
#include <ImfEnvmapAttribute.h>
|
||||
#include <ImfDoubleAttribute.h>
|
||||
#include <ImfIntAttribute.h>
|
||||
#include <ImfLineOrderAttribute.h>
|
||||
#include <ImfMatrixAttribute.h>
|
||||
#include <ImfOpaqueAttribute.h>
|
||||
#include <ImfStringAttribute.h>
|
||||
#include <ImfStringVectorAttribute.h>
|
||||
#include <ImfVecAttribute.h>
|
||||
|
||||
#include <half.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <assert.h>
|
||||
#include <time.h>
|
||||
#ifndef WIN32
|
||||
#include <sys/times.h>
|
||||
#endif // WIN32
|
||||
|
||||
#ifndef ILM_IMF_TEST_IMAGEDIR
|
||||
#define ILM_IMF_TEST_IMAGEDIR
|
||||
#endif
|
||||
|
||||
|
||||
namespace IMF = OPENEXR_IMF_NAMESPACE;
|
||||
using namespace IMF;
|
||||
using namespace IMATH_NAMESPACE;
|
||||
using namespace ILMTHREAD_NAMESPACE;
|
||||
using namespace std;
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
//
|
||||
// Make this true if you wish to generate images when building
|
||||
// the v1.7 code base.
|
||||
//
|
||||
const int generateImagesOnly = false;
|
||||
|
||||
|
||||
const int W = 217;
|
||||
const int H = 197;
|
||||
|
||||
|
||||
|
||||
|
||||
void
|
||||
diffImageFiles (const char * fn1, const char * fn2)
|
||||
{
|
||||
ifstream i1 (fn1, ios::binary);
|
||||
ifstream i2 (fn2, ios::binary);
|
||||
|
||||
if(!i1.good()){THROW (IEX_NAMESPACE::BaseExc, string("cannot open ") + string(fn1));}
|
||||
if(!i2.good()){THROW (IEX_NAMESPACE::BaseExc, string("cannot open ") + string(fn2));}
|
||||
|
||||
while (!i1.eof() && !i2.eof())
|
||||
{
|
||||
if (i1.get() != i2.get())
|
||||
{
|
||||
string e = string ("v1.7 and current differences between '") +
|
||||
string (fn1) + string ("' & '") + string (fn2) +
|
||||
string ("'");
|
||||
THROW (IEX_NAMESPACE::BaseExc, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
addPreviewImageToHeader (OPENEXR_IMF_NAMESPACE::Header & hdr)
|
||||
{
|
||||
size_t pW = 32;
|
||||
size_t pH = 32;
|
||||
|
||||
OPENEXR_IMF_NAMESPACE::Array2D <OPENEXR_IMF_NAMESPACE::PreviewRgba> previewPixels (pW, pH);
|
||||
for (size_t h=0; h<pH; h++)
|
||||
{
|
||||
for (size_t w=0; w<pW; w++)
|
||||
{
|
||||
previewPixels[w][h] = (w*h) % 255;
|
||||
}
|
||||
}
|
||||
hdr.setPreviewImage (OPENEXR_IMF_NAMESPACE::PreviewImage (pW, pH, &previewPixels[0][0]));
|
||||
}
|
||||
|
||||
void
|
||||
addUserAttributesToHeader (OPENEXR_IMF_NAMESPACE::Header & hdr)
|
||||
{
|
||||
Box2i a1 (V2i (1, 2), V2i (3, 4));
|
||||
Box2f a2 (V2f (1.5, 2.5), V2f (3.5, 4.5));
|
||||
float a3 (3.14159);
|
||||
int a4 (17);
|
||||
M33f a5 (11, 12, 13, 14, 15, 16, 17, 18, 19);
|
||||
M44f a6 (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
|
||||
string a7 ("extensive rebuilding by Nebuchadrezzar has left");
|
||||
V2i a8 (27, 28);
|
||||
V2f a9 (27.5, 28.5);
|
||||
V3i a10 (37, 38, 39);
|
||||
V3f a11 (37.5, 38.5, 39.5);
|
||||
double a12 (7.12342341419);
|
||||
Chromaticities a13 (V2f (1, 2), V2f (3, 4), V2f (5, 6), V2f (7, 8));
|
||||
// Envmap a14 (ENVMAP_CUBE);
|
||||
StringVector a15;
|
||||
a15.push_back ("who can spin");
|
||||
a15.push_back ("");
|
||||
a15.push_back ("straw into");
|
||||
a15.push_back ("gold");
|
||||
|
||||
M33d a16 (12, 13, 14, 15, 16, 17, 18, 19, 20);
|
||||
M44d a17 (2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17);
|
||||
V2d a18 (27.51, 28.51);
|
||||
V3d a19 (37.51, 38.51, 39.51);
|
||||
|
||||
hdr.insert ("a1", Box2iAttribute (a1));
|
||||
hdr.insert ("a2", Box2fAttribute (a2));
|
||||
hdr.insert ("a3", FloatAttribute (a3));
|
||||
hdr.insert ("a4", IntAttribute (a4));
|
||||
hdr.insert ("a5", M33fAttribute (a5));
|
||||
hdr.insert ("a6", M44fAttribute (a6));
|
||||
hdr.insert ("a7", StringAttribute (a7));
|
||||
hdr.insert ("a8", V2iAttribute (a8));
|
||||
hdr.insert ("a9", V2fAttribute (a9));
|
||||
hdr.insert ("a10", V3iAttribute (a10));
|
||||
hdr.insert ("a11", V3fAttribute (a11));
|
||||
hdr.insert ("a12", DoubleAttribute (a12));
|
||||
hdr.insert ("a13", ChromaticitiesAttribute (a13));
|
||||
// hdr.insert ("a14", EnvmapAttribute (a14));
|
||||
hdr.insert ("a15", StringVectorAttribute (a15));
|
||||
hdr.insert ("a16", M33dAttribute (a16));
|
||||
hdr.insert ("a17", M44dAttribute (a17));
|
||||
hdr.insert ("a18", V2dAttribute (a18));
|
||||
hdr.insert ("a19", V3dAttribute (a19));
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
generateScanlinePlanarImage (const char * fn)
|
||||
{
|
||||
// generate a v 1.7 image and check against ground truth on disk
|
||||
Array2D<float> pf (H, W); pf.resizeErase(H, W);
|
||||
Array2D<half> ph (H, W); ph.resizeErase(H, W);
|
||||
|
||||
for (int i = 0; i < H; i++)
|
||||
{
|
||||
for (int j = 0; j < W; j++)
|
||||
{
|
||||
pf[i][j] = (float)((i * W + j) / (float(W*H)));
|
||||
ph[i][j] = (half)(pf[i][j]);
|
||||
}
|
||||
}
|
||||
|
||||
IMATH_NAMESPACE::Box2i dod (IMATH_NAMESPACE::V2f(20), IMATH_NAMESPACE::V2f(W-20, H-23));
|
||||
OPENEXR_IMF_NAMESPACE::Header header = Header (W, H, dod);
|
||||
header.channels().insert("Z", Channel(IMF::FLOAT));
|
||||
header.channels().insert("R", Channel(IMF::HALF));
|
||||
header.channels().insert("G", Channel(IMF::HALF));
|
||||
header.channels().insert("B", Channel(IMF::HALF));
|
||||
addUserAttributesToHeader (header);
|
||||
|
||||
FrameBuffer fb;
|
||||
|
||||
fb.insert ("Z",
|
||||
Slice (IMF::FLOAT,
|
||||
(char *) &pf[0][0],
|
||||
sizeof (pf[0][0]),
|
||||
sizeof (pf[0][0]) * W));
|
||||
|
||||
fb.insert ("R",
|
||||
Slice (IMF::HALF,
|
||||
(char *) &ph[0][0],
|
||||
sizeof (ph[0][0]),
|
||||
sizeof (ph[0][0]) * W));
|
||||
fb.insert ("G",
|
||||
Slice (IMF::HALF,
|
||||
(char *) &ph[0][0],
|
||||
sizeof (ph[0][0]),
|
||||
sizeof (ph[0][0]) * W));
|
||||
fb.insert ("B",
|
||||
Slice (IMF::HALF,
|
||||
(char *) &ph[0][0],
|
||||
sizeof (ph[0][0]),
|
||||
sizeof (ph[0][0]) * W));
|
||||
|
||||
OutputFile file (fn, header);
|
||||
file.setFrameBuffer (fb);
|
||||
file.writePixels (H-40);
|
||||
}
|
||||
|
||||
struct RZ
|
||||
{
|
||||
float z;
|
||||
half g;
|
||||
};
|
||||
|
||||
void
|
||||
generateScanlineInterleavedImage (const char * fn)
|
||||
{
|
||||
// generate a v 1.7 image and check against ground truth on disk
|
||||
Array2D<RZ> rz (H, W); rz.resizeErase(H, W);
|
||||
|
||||
for (int i = 0; i < H; i++)
|
||||
{
|
||||
for (int j = 0; j < W; j++)
|
||||
{
|
||||
rz[i][j].z = (float)((i * W + j) / (float(W*H)));
|
||||
rz[i][j].g = (half)(rz[i][j].z);
|
||||
}
|
||||
}
|
||||
|
||||
IMATH_NAMESPACE::Box2i dod (IMATH_NAMESPACE::V2f(20), IMATH_NAMESPACE::V2f(W-20, H-23));
|
||||
OPENEXR_IMF_NAMESPACE::Header header = Header (W, H, dod);
|
||||
header.channels().insert("Z", Channel(IMF::FLOAT));
|
||||
header.channels().insert("R", Channel(IMF::HALF));
|
||||
addUserAttributesToHeader (header);
|
||||
|
||||
FrameBuffer fb;
|
||||
|
||||
fb.insert ("Z",
|
||||
Slice (IMF::FLOAT,
|
||||
(char *) &(rz[0][0].z),
|
||||
sizeof (rz[0][0]),
|
||||
sizeof (rz[0][0]) * W));
|
||||
|
||||
fb.insert ("G",
|
||||
Slice (IMF::HALF,
|
||||
(char *) &(rz[0][0].g),
|
||||
sizeof (rz[0][0]),
|
||||
sizeof (rz[0][0]) * W));
|
||||
|
||||
OutputFile file (fn, header);
|
||||
file.setFrameBuffer (fb);
|
||||
file.writePixels (H-40);
|
||||
}
|
||||
|
||||
void
|
||||
diffScanlineImages (const std::string & planarScanlineName,
|
||||
const std::string & interleavedScanlineName)
|
||||
{
|
||||
// Planar Images
|
||||
generateScanlinePlanarImage (planarScanlineName.c_str());
|
||||
diffImageFiles (planarScanlineName.c_str(),
|
||||
ILM_IMF_TEST_IMAGEDIR "v1.7.test.planar.exr");
|
||||
|
||||
// Interleaved Images
|
||||
generateScanlineInterleavedImage (interleavedScanlineName.c_str());
|
||||
diffImageFiles (interleavedScanlineName.c_str(),
|
||||
ILM_IMF_TEST_IMAGEDIR "v1.7.test.interleaved.exr");
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
generateTiledImage (const char * fn)
|
||||
{
|
||||
Array2D<RZ> rz (H, W); rz.resizeErase(H, W);
|
||||
|
||||
for (int i = 0; i < H; i++)
|
||||
{
|
||||
for (int j = 0; j < W; j++)
|
||||
{
|
||||
rz[i][j].z = (float)((i * W + j) / (float(W*H)));
|
||||
rz[i][j].g = (half)(rz[i][j].z);
|
||||
}
|
||||
}
|
||||
|
||||
Header header (W, H);
|
||||
header.channels().insert ("G", Channel (IMF::HALF));
|
||||
header.channels().insert ("Z", Channel (IMF::FLOAT));
|
||||
|
||||
int tileW = 12;
|
||||
int tileH = 24;
|
||||
header.setTileDescription (TileDescription (tileW, tileH, ONE_LEVEL));
|
||||
|
||||
OPENEXR_IMF_NAMESPACE::TiledOutputFile out (fn, header);
|
||||
OPENEXR_IMF_NAMESPACE::FrameBuffer frameBuffer; // 6
|
||||
frameBuffer.insert ("G",
|
||||
Slice (IMF::HALF,
|
||||
(char *) &rz[0][0].g,
|
||||
sizeof (rz[0][0]) * 1,
|
||||
sizeof (rz[0][0]) * W));
|
||||
|
||||
frameBuffer.insert ("Z",
|
||||
Slice (IMF::FLOAT,
|
||||
(char *) &rz[0][0].z,
|
||||
sizeof (rz[0][0]) * 1,
|
||||
sizeof (rz[0][0]) * W));
|
||||
|
||||
out.setFrameBuffer (frameBuffer);
|
||||
out.writeTiles (0, out.numXTiles() - 1, 0, out.numYTiles() - 1);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
diffTiledImages (const std::string & fn)
|
||||
{
|
||||
// Planar Images
|
||||
generateTiledImage (fn.c_str());
|
||||
diffImageFiles (fn.c_str(), ILM_IMF_TEST_IMAGEDIR "v1.7.test.tiled.exr");
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
void
|
||||
testBackwardCompatibility (const std::string & tempDir)
|
||||
{
|
||||
try
|
||||
{
|
||||
cout << "Testing backward compatibility" << endl;
|
||||
|
||||
|
||||
// Run this code with the 1.7 code base to generate the
|
||||
// images used in the test.
|
||||
if (generateImagesOnly)
|
||||
{
|
||||
generateScanlinePlanarImage ("v1.7.test.planar.exr");
|
||||
generateScanlineInterleavedImage ("v1.7.test.interleaved.exr");
|
||||
generateTiledImage ("v1.7.test.tiled.exr");
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string planarFn = tempDir + "v1.7.test.planar.exr";
|
||||
std::string interleavedFn = tempDir + "v1.7.test.interleaved.exr";
|
||||
diffScanlineImages (planarFn, interleavedFn);
|
||||
|
||||
std::string fn = tempDir + "v1.7.test.tiled.exr";
|
||||
diffTiledImages (fn);
|
||||
}
|
||||
|
||||
cout << "ok\n" << endl;
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
cerr << "ERROR -- caught exception: " << e.what() << endl;
|
||||
assert (false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2012, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef TESTBACKWARDCOMPATIBILITY_H_
|
||||
#define TESTBACKWARDCOMPATIBILITY_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
void testBackwardCompatibility (const std::string & tempDir);
|
||||
|
||||
#endif /* TESTBACKWARDCOMPATIBILITY_H_ */
|
||||
@@ -0,0 +1,373 @@
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2013, Weta Digital Ltd
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "ImfInputFile.h"
|
||||
#include "ImfInputPart.h"
|
||||
#include "ImfTiledInputFile.h"
|
||||
#include "ImfTiledInputPart.h"
|
||||
|
||||
#include "ImfDeepScanLineInputFile.h"
|
||||
#include "ImfDeepScanLineInputPart.h"
|
||||
#include "ImfDeepTiledInputFile.h"
|
||||
#include "ImfDeepTiledInputPart.h"
|
||||
|
||||
#include "ImfChannelList.h"
|
||||
#include "ImfMultiPartInputFile.h"
|
||||
#include "ImfPartType.h"
|
||||
#include <half.h>
|
||||
#include <vector>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "tmpDir.h"
|
||||
|
||||
namespace IMF = OPENEXR_IMF_NAMESPACE;
|
||||
using namespace IMF;
|
||||
using namespace std;
|
||||
using namespace IMATH_NAMESPACE;
|
||||
|
||||
#ifndef ILM_IMF_TEST_IMAGEDIR
|
||||
#define ILM_IMF_TEST_IMAGEDIR
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
|
||||
void doFrameBuffer(vector<half>& storage, const Header & hdr,FrameBuffer& dummy)
|
||||
{
|
||||
|
||||
int chans=0;
|
||||
for( ChannelList::ConstIterator q =hdr.channels().begin() ; q!=hdr.channels().end() ; q++)
|
||||
{
|
||||
chans++;
|
||||
}
|
||||
|
||||
Box2i dw= hdr.dataWindow();
|
||||
|
||||
storage.resize( (dw.size().x+1)*(dw.size().y+1)*chans);
|
||||
|
||||
int xstride = chans*sizeof(half);
|
||||
int ystride = xstride*(dw.size().x+1);
|
||||
int offset = ystride*dw.min.y + dw.min.x*xstride;
|
||||
|
||||
int chan=0;
|
||||
for( ChannelList::ConstIterator q = hdr.channels().begin() ; q!=hdr.channels().end() ; q++)
|
||||
{
|
||||
dummy.insert(q.name(),Slice(HALF,((char*) &storage[chan])-offset,xstride,ystride));
|
||||
chan++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<class T> void readTiledThing(T & input,bool test)
|
||||
{
|
||||
vector<half> value;
|
||||
FrameBuffer dummy;
|
||||
doFrameBuffer(value,input.header(),dummy);
|
||||
input.setFrameBuffer(dummy);
|
||||
int x_levels;
|
||||
int y_levels;
|
||||
|
||||
if(test && input.header().hasType())
|
||||
{
|
||||
if(input.header().type()!=TILEDIMAGE)
|
||||
{
|
||||
std::cerr << "tiled image/part didn't have tiledimage type\n";
|
||||
//assert(input.type()==TILEDIMAGE);
|
||||
}
|
||||
}
|
||||
|
||||
TileDescription t = input.header().tileDescription();
|
||||
switch(t.mode)
|
||||
{
|
||||
case ONE_LEVEL :
|
||||
x_levels = 1;
|
||||
y_levels = 1;
|
||||
break;
|
||||
case MIPMAP_LEVELS :
|
||||
x_levels = input.numXLevels();
|
||||
y_levels = 1;
|
||||
break;
|
||||
case RIPMAP_LEVELS :
|
||||
x_levels = input.numXLevels();
|
||||
y_levels = input.numYLevels();
|
||||
}
|
||||
|
||||
for(int x_level = 0 ; x_level < x_levels ; x_level++)
|
||||
{
|
||||
for(int y_level = 0 ; y_level < y_levels ;y_level++)
|
||||
{
|
||||
// unless we are RIPMapped, the y_level=x_level, not 0
|
||||
int actual_y_level = t.mode==RIPMAP_LEVELS ? y_level : x_level;
|
||||
|
||||
input.readTiles(0,input.numXTiles(x_level)-1,0,input.numYTiles(actual_y_level)-1,x_level,actual_y_level);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class T> void readScanlineThing(T& input,bool test)
|
||||
{
|
||||
|
||||
|
||||
if(test && input.header().hasType())
|
||||
{
|
||||
if(input.header().type()!=SCANLINEIMAGE)
|
||||
{
|
||||
std::cerr << "tiled image/part didn't have tiledimage type\n";
|
||||
//assert(input.type()==TILEDIMAGE);
|
||||
}
|
||||
}
|
||||
|
||||
vector<half> value;
|
||||
FrameBuffer dummy;
|
||||
doFrameBuffer(value,input.header(),dummy);
|
||||
input.setFrameBuffer(dummy);
|
||||
input.readPixels(input.header().dataWindow().min.x,input.header().dataWindow().max.x);
|
||||
}
|
||||
|
||||
void checkDeepTypesFailToLoad(const char * file)
|
||||
{
|
||||
|
||||
// trying to open it as a deep tiled file should fail
|
||||
try{
|
||||
DeepTiledInputFile f(file);
|
||||
assert(false);
|
||||
}catch(...)
|
||||
{
|
||||
}
|
||||
// trying to open it as a deep tiled part of a multipart file should fail
|
||||
try{
|
||||
MultiPartInputFile multiin(file);
|
||||
DeepTiledInputPart p(multiin,0);
|
||||
assert(false);
|
||||
}catch(...)
|
||||
{
|
||||
}
|
||||
|
||||
// trying to open it as a deep scanline file should fail
|
||||
try{
|
||||
DeepScanLineInputFile f(file);
|
||||
assert(false);
|
||||
}catch(...)
|
||||
{
|
||||
|
||||
}
|
||||
// trying to open it as a deep scanline part of a multipart file should fail
|
||||
try{
|
||||
MultiPartInputFile multiin(file);
|
||||
DeepScanLineInputPart p(multiin,0);
|
||||
assert(false);
|
||||
}catch(...)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void testTiledWithBadAttribute(const char* file)
|
||||
{
|
||||
// it's a tiled file, so it should read as a file
|
||||
TiledInputFile in(file);
|
||||
readTiledThing(in,false);
|
||||
|
||||
{
|
||||
// it should also read using the multipart API (and have its attribute fixed)
|
||||
MultiPartInputFile multiin(file);
|
||||
TiledInputPart tip(multiin,0);
|
||||
readTiledThing(tip,true);
|
||||
|
||||
// it should also read using the regular file API as a scanline file
|
||||
InputFile sin(file);
|
||||
readScanlineThing(sin,false);
|
||||
|
||||
}
|
||||
{
|
||||
// it should also read using the multipart API as a scanline file
|
||||
MultiPartInputFile multiin(file);
|
||||
|
||||
InputPart ip(multiin,0);
|
||||
readScanlineThing(ip,false);
|
||||
}
|
||||
|
||||
checkDeepTypesFailToLoad(file);
|
||||
|
||||
}
|
||||
|
||||
void testScanLineWithBadAttribute(const char * file)
|
||||
{
|
||||
InputFile in(file);
|
||||
readScanlineThing(in,false);
|
||||
|
||||
MultiPartInputFile multiin(file);
|
||||
InputPart ip(multiin,0);
|
||||
readScanlineThing(ip,false);
|
||||
|
||||
|
||||
checkDeepTypesFailToLoad(file);
|
||||
|
||||
// trying to open it as a tiled file should also fail
|
||||
try{
|
||||
TiledInputFile f(file);
|
||||
assert(false);
|
||||
}catch(...)
|
||||
{
|
||||
}
|
||||
// trying to open it as a tiled part of a multipart file should fail
|
||||
try{
|
||||
MultiPartInputFile multiin(file);
|
||||
TiledInputPart p(multiin,0);
|
||||
assert(false);
|
||||
}catch(...)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
const std::string & NOTYPEATTR="";
|
||||
|
||||
template<class IN,class OUT> void check(const char* filename,const string& inputtype,const string &outputtype,bool add_tiledesc)
|
||||
{
|
||||
Header f;
|
||||
|
||||
if(inputtype!=NOTYPEATTR)
|
||||
{
|
||||
f.setType(inputtype);
|
||||
}
|
||||
f.compression()=ZIPS_COMPRESSION;
|
||||
if(add_tiledesc)
|
||||
{
|
||||
f.setTileDescription(TileDescription());
|
||||
}
|
||||
|
||||
remove(filename);
|
||||
{
|
||||
OUT file(filename,f);
|
||||
}
|
||||
|
||||
{
|
||||
IMF::MultiPartInputFile file(filename);
|
||||
|
||||
if(outputtype!=NOTYPEATTR && file.header(0).type()!=outputtype)
|
||||
{
|
||||
cerr << "Error: expected type in header to be " << outputtype << " but got " << file.header(0).type() << " from multipart when input type was " << (inputtype==NOTYPEATTR ? "unset" : inputtype )<< std::endl;
|
||||
}
|
||||
|
||||
assert(outputtype==NOTYPEATTR || file.header(0).type()==outputtype);
|
||||
}
|
||||
|
||||
{
|
||||
IN file(filename);
|
||||
if(outputtype==NOTYPEATTR)
|
||||
{
|
||||
if(file.header().hasType())
|
||||
{
|
||||
cerr << " type attribute got inserted when it shouldn't have been\n";
|
||||
}
|
||||
|
||||
assert( !file.header().hasType() );
|
||||
|
||||
}else if(file.header().type()!=outputtype)
|
||||
{
|
||||
cerr << "Error: expected type in header to be " << outputtype << " but got " << file.header().type() << " when input type was " << (inputtype==NOTYPEATTR ? "unset" : inputtype )<< std::endl;
|
||||
}
|
||||
|
||||
}
|
||||
remove(filename);
|
||||
}
|
||||
|
||||
void testWriteBadTypes()
|
||||
{
|
||||
static const char* tmpfile = IMF_TMP_DIR "badfile.exr";
|
||||
|
||||
// attributes should be added automatically for deep files
|
||||
check<DeepScanLineInputFile,DeepScanLineOutputFile>(tmpfile,NOTYPEATTR,DEEPSCANLINE,false);
|
||||
check<DeepTiledInputFile,DeepTiledOutputFile>(tmpfile,NOTYPEATTR,DEEPTILE,true);
|
||||
|
||||
// attributes should NOT be added automatically for normal images
|
||||
check<InputFile,OutputFile>(tmpfile,NOTYPEATTR,NOTYPEATTR,false);
|
||||
check<InputFile,TiledOutputFile>(tmpfile,NOTYPEATTR,NOTYPEATTR,true);
|
||||
check<TiledInputFile,TiledOutputFile>(tmpfile,NOTYPEATTR,NOTYPEATTR,true);
|
||||
|
||||
|
||||
// if an attribute is provided, it should get changed to the correct one
|
||||
check<InputFile,OutputFile>(tmpfile,SCANLINEIMAGE,SCANLINEIMAGE,false);
|
||||
check<InputFile,TiledOutputFile>(tmpfile,SCANLINEIMAGE,TILEDIMAGE,true);
|
||||
check<TiledInputFile,TiledOutputFile>(tmpfile,SCANLINEIMAGE,TILEDIMAGE,true);
|
||||
check<DeepScanLineInputFile,DeepScanLineOutputFile>(tmpfile,SCANLINEIMAGE,DEEPSCANLINE,false);
|
||||
check<DeepTiledInputFile,DeepTiledOutputFile>(tmpfile,SCANLINEIMAGE,DEEPTILE,true);
|
||||
|
||||
check<InputFile,OutputFile>(tmpfile,TILEDIMAGE,SCANLINEIMAGE,false);
|
||||
check<InputFile,TiledOutputFile>(tmpfile,TILEDIMAGE,TILEDIMAGE,true);
|
||||
check<TiledInputFile,TiledOutputFile>(tmpfile,TILEDIMAGE,TILEDIMAGE,true);
|
||||
check<DeepScanLineInputFile, DeepScanLineOutputFile>(tmpfile,TILEDIMAGE,DEEPSCANLINE,false);
|
||||
check<DeepTiledInputFile,DeepTiledOutputFile>(tmpfile,TILEDIMAGE,DEEPTILE,true);
|
||||
|
||||
check<InputFile,OutputFile>(tmpfile,DEEPSCANLINE,SCANLINEIMAGE,false);
|
||||
check<InputFile,TiledOutputFile>(tmpfile,DEEPSCANLINE,TILEDIMAGE,true);
|
||||
check<TiledInputFile,TiledOutputFile>(tmpfile,DEEPSCANLINE,TILEDIMAGE,true);
|
||||
check<DeepScanLineInputFile, DeepScanLineOutputFile>(tmpfile,DEEPSCANLINE,DEEPSCANLINE,false);
|
||||
check<DeepTiledInputFile,DeepTiledOutputFile>(tmpfile,DEEPSCANLINE,DEEPTILE,true);
|
||||
|
||||
check<InputFile,OutputFile>(tmpfile,DEEPTILE,SCANLINEIMAGE,false);
|
||||
check<InputFile,TiledOutputFile>(tmpfile,DEEPTILE,TILEDIMAGE,true);
|
||||
check<TiledInputFile,TiledOutputFile>(tmpfile,DEEPTILE,TILEDIMAGE,true);
|
||||
check<DeepScanLineInputFile,DeepScanLineOutputFile>(tmpfile,DEEPTILE,DEEPSCANLINE,false);
|
||||
check<DeepTiledInputFile,DeepTiledOutputFile>(tmpfile,DEEPTILE,DEEPTILE,true);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void testBadTypeAttributes(const std::string & tempDir)
|
||||
{
|
||||
cout << "Testing whether bad type attributes are fixed on read... " << endl;
|
||||
|
||||
testTiledWithBadAttribute (ILM_IMF_TEST_IMAGEDIR "tiled_with_scanlineimage_type.exr");
|
||||
testTiledWithBadAttribute (ILM_IMF_TEST_IMAGEDIR "tiled_with_deepscanline_type.exr");
|
||||
testTiledWithBadAttribute (ILM_IMF_TEST_IMAGEDIR "tiled_with_deeptile_type.exr");
|
||||
|
||||
testScanLineWithBadAttribute (ILM_IMF_TEST_IMAGEDIR "scanline_with_tiledimage_type.exr");
|
||||
testScanLineWithBadAttribute (ILM_IMF_TEST_IMAGEDIR "scanline_with_deeptiled_type.exr");
|
||||
testScanLineWithBadAttribute (ILM_IMF_TEST_IMAGEDIR "scanline_with_deepscanline_type.exr");
|
||||
|
||||
cout << "Testing whether bad type attributes are fixed on write... " << endl;
|
||||
|
||||
testWriteBadTypes();
|
||||
|
||||
cout << "ok\n" << endl;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2013, Weta Digital Ltd
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef TEST_BAD_TYPE_ATTRIBUTES
|
||||
#define TEST_BAD_TYPE_ATTRIBUTES
|
||||
|
||||
#include <string>
|
||||
|
||||
void testBadTypeAttributes (const std::string & tempDir);
|
||||
|
||||
#endif
|
||||
260
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testChannels.cpp
Normal file
260
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testChannels.cpp
Normal file
@@ -0,0 +1,260 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#include <ImfOutputFile.h>
|
||||
#include <ImfInputFile.h>
|
||||
#include <ImfChannelList.h>
|
||||
#include <ImfArray.h>
|
||||
#include "half.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
using namespace OPENEXR_IMF_NAMESPACE;
|
||||
using namespace std;
|
||||
using namespace IMATH_NAMESPACE;
|
||||
|
||||
namespace {
|
||||
|
||||
void
|
||||
fillPixels (Array2D<half> &ph1,
|
||||
Array2D<half> &ph2,
|
||||
int width, int height)
|
||||
{
|
||||
for (int y = 0; y < height; ++y)
|
||||
{
|
||||
for (int x = 0; x < width; ++x)
|
||||
{
|
||||
ph1[y][x] = x % 10 + 10 * (y % 17);
|
||||
ph2[y][x] = x % 11 + 11 * (y % 15);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
writeRead (const Array2D<half> &h1out,
|
||||
const Array2D<half> &h2out,
|
||||
const char fileName[],
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
//
|
||||
// Write an image file with three channels, H1, H2 and H3.
|
||||
// Our frame buffer contains pixel data only for H1 and H2;
|
||||
// the file's H3 channel should be filled with zeroes.
|
||||
//
|
||||
|
||||
Header hdr (width, height);
|
||||
|
||||
hdr.channels().insert ("H1", // name
|
||||
Channel (HALF, // type
|
||||
1, // xSampling
|
||||
1) // ySampling
|
||||
);
|
||||
|
||||
hdr.channels().insert ("H2", // name
|
||||
Channel (HALF, // type
|
||||
1, // xSampling
|
||||
1) // ySampling
|
||||
);
|
||||
|
||||
hdr.channels().insert ("H3", // name
|
||||
Channel (HALF, // type
|
||||
1, // xSampling
|
||||
1) // ySampling
|
||||
);
|
||||
|
||||
{
|
||||
FrameBuffer fb;
|
||||
|
||||
fb.insert ("H1", // name
|
||||
Slice (HALF, // type
|
||||
(char *) &h1out[0][0], // base
|
||||
sizeof (h1out[0][0]), // xStride
|
||||
sizeof (h1out[0][0]) * width, // yStride
|
||||
1, // xSampling
|
||||
1) // ySampling
|
||||
);
|
||||
|
||||
fb.insert ("H2", // name
|
||||
Slice (HALF, // type
|
||||
(char *) &h2out[0][0], // base
|
||||
sizeof (h2out[0][0]), // xStride
|
||||
sizeof (h2out[0][0]) * width, // yStride
|
||||
1, // xSampling
|
||||
1) // ySampling
|
||||
);
|
||||
|
||||
cout << "writing" << flush;
|
||||
|
||||
remove (fileName);
|
||||
OutputFile out (fileName, hdr);
|
||||
out.setFrameBuffer (fb);
|
||||
out.writePixels (height);
|
||||
}
|
||||
|
||||
//
|
||||
// Read the image back from the file. Our frame buffer now
|
||||
// contains space for the three channels, H1, H3 and H4.
|
||||
// H1 and H3 should be read back from the file (but H3
|
||||
// should contain only zeroes), and H4 should be filled
|
||||
// with a default value, 3.0, because the file contains
|
||||
// no data for it. The file's H2 channel should be ignored.
|
||||
//
|
||||
|
||||
{
|
||||
cout << " reading" << flush;
|
||||
|
||||
InputFile in (fileName);
|
||||
|
||||
const Box2i &dw = in.header().dataWindow();
|
||||
int w = dw.max.x - dw.min.x + 1;
|
||||
int h = dw.max.y - dw.min.y + 1;
|
||||
int dx = dw.min.x;
|
||||
int dy = dw.min.y;
|
||||
|
||||
Array2D<half> h1in (h, w);
|
||||
Array2D<half> h3in (h, w);
|
||||
Array2D<half> h4in (h, w);
|
||||
|
||||
FrameBuffer fb;
|
||||
|
||||
fb.insert ("H1", // name
|
||||
Slice (HALF, // type
|
||||
(char *) &h1in[-dy][-dx], // base
|
||||
sizeof (h1in[0][0]), // xStride
|
||||
sizeof (h1in[0][0]) * w, // yStride
|
||||
1, // xSampling
|
||||
1, // ySampling
|
||||
3.0) // fillValue
|
||||
);
|
||||
|
||||
fb.insert ("H3", // name
|
||||
Slice (HALF, // type
|
||||
(char *) &h3in[-dy][-dx], // base
|
||||
sizeof (h3in[0][0]), // xStride
|
||||
sizeof (h3in[0][0]) * w, // yStride
|
||||
1, // xSampling
|
||||
1, // ySampling
|
||||
3.0) // fillValue
|
||||
);
|
||||
|
||||
fb.insert ("H4", // name
|
||||
Slice (HALF, // type
|
||||
(char *) &h4in[-dy][-dx], // base
|
||||
sizeof (h4in[0][0]), // xStride
|
||||
sizeof (h4in[0][0]) * w, // yStride
|
||||
1, // xSampling
|
||||
1, // ySampling
|
||||
3.0) // fillValue
|
||||
);
|
||||
|
||||
in.setFrameBuffer (fb);
|
||||
in.readPixels (dw.min.y, dw.max.y);
|
||||
|
||||
cout << " comparing" << flush;
|
||||
|
||||
assert (in.header().displayWindow() == hdr.displayWindow());
|
||||
assert (in.header().dataWindow() == hdr.dataWindow());
|
||||
assert (in.header().pixelAspectRatio() == hdr.pixelAspectRatio());
|
||||
assert (in.header().screenWindowCenter() == hdr.screenWindowCenter());
|
||||
assert (in.header().screenWindowWidth() == hdr.screenWindowWidth());
|
||||
assert (in.header().lineOrder() == hdr.lineOrder());
|
||||
assert (in.header().compression() == hdr.compression());
|
||||
|
||||
ChannelList::ConstIterator hi = hdr.channels().begin();
|
||||
ChannelList::ConstIterator ii = in.header().channels().begin();
|
||||
|
||||
while (hi != hdr.channels().end())
|
||||
{
|
||||
assert (!strcmp (hi.name(), ii.name()));
|
||||
assert (hi.channel().type == ii.channel().type);
|
||||
assert (hi.channel().xSampling == ii.channel().xSampling);
|
||||
assert (hi.channel().ySampling == ii.channel().ySampling);
|
||||
|
||||
++hi;
|
||||
++ii;
|
||||
}
|
||||
|
||||
assert (ii == in.header().channels().end());
|
||||
|
||||
for (int y = 0; y < h; ++y)
|
||||
{
|
||||
for (int x = 0; x < w; ++x)
|
||||
{
|
||||
assert (h1in[y][x] == h1out[y][x]);
|
||||
assert (h3in[y][x] == 0.0);
|
||||
assert (h4in[y][x] == 3.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
remove (fileName);
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
void
|
||||
testChannels (const std::string &tempDir)
|
||||
{
|
||||
try
|
||||
{
|
||||
cout << "Testing filling of missing channels" << endl;
|
||||
|
||||
const int W = 117;
|
||||
const int H = 97;
|
||||
|
||||
Array2D<half> ph1 (H, W);
|
||||
Array2D<half> ph2 (H, W);
|
||||
fillPixels (ph1, ph2, W, H);
|
||||
|
||||
std::string filename = tempDir + "imf_test_channels.exr";
|
||||
|
||||
writeRead (ph1, ph2, filename.c_str(), W, H);
|
||||
|
||||
cout << "ok\n" << endl;
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
cerr << "ERROR -- caught exception: " << e.what() << endl;
|
||||
assert (false);
|
||||
}
|
||||
}
|
||||
41
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testChannels.h
Normal file
41
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testChannels.h
Normal file
@@ -0,0 +1,41 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
#include <string>
|
||||
|
||||
void testChannels (const std::string &tempDir);
|
||||
|
||||
@@ -0,0 +1,719 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2012, Weta Digital Ltd
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Weta Digital nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "testCompositeDeepScanLine.h"
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <Iex.h>
|
||||
#include <ostream>
|
||||
#include <iostream>
|
||||
#include <typeinfo>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <sstream>
|
||||
|
||||
#include <ImfMultiPartOutputFile.h>
|
||||
#include <ImfMultiPartInputFile.h>
|
||||
#include <ImfDeepScanLineOutputPart.h>
|
||||
#include <ImfDeepScanLineInputPart.h>
|
||||
#include <ImfChannelList.h>
|
||||
#include <ImfHeader.h>
|
||||
#include <ImfDeepFrameBuffer.h>
|
||||
#include <ImfFrameBuffer.h>
|
||||
#include <ImfPartType.h>
|
||||
#include <ImfCompression.h>
|
||||
#include <ImfInputFile.h>
|
||||
#include <ImfCompositeDeepScanLine.h>
|
||||
#include <ImfThreading.h>
|
||||
#include <IlmThread.h>
|
||||
#include <ImfNamespace.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
|
||||
using std::vector;
|
||||
using std::string;
|
||||
using std::ostream;
|
||||
using std::endl;
|
||||
using std::cout;
|
||||
using std::ostringstream;
|
||||
|
||||
|
||||
using OPENEXR_IMF_NAMESPACE::DeepScanLineOutputFile;
|
||||
using OPENEXR_IMF_NAMESPACE::MultiPartInputFile;
|
||||
using OPENEXR_IMF_NAMESPACE::DeepScanLineOutputPart;
|
||||
using OPENEXR_IMF_NAMESPACE::DeepScanLineInputPart;
|
||||
|
||||
using OPENEXR_IMF_NAMESPACE::Header;
|
||||
using OPENEXR_IMF_NAMESPACE::PixelType;
|
||||
using OPENEXR_IMF_NAMESPACE::DeepFrameBuffer;
|
||||
using OPENEXR_IMF_NAMESPACE::FrameBuffer;
|
||||
using OPENEXR_IMF_NAMESPACE::FLOAT;
|
||||
using OPENEXR_IMF_NAMESPACE::HALF;
|
||||
using OPENEXR_IMF_NAMESPACE::UINT;
|
||||
using OPENEXR_IMF_NAMESPACE::Slice;
|
||||
using OPENEXR_IMF_NAMESPACE::DeepSlice;
|
||||
using OPENEXR_IMF_NAMESPACE::MultiPartOutputFile;
|
||||
using IMATH_NAMESPACE::Box2i;
|
||||
using OPENEXR_IMF_NAMESPACE::DEEPSCANLINE;
|
||||
using OPENEXR_IMF_NAMESPACE::ZIPS_COMPRESSION;
|
||||
using OPENEXR_IMF_NAMESPACE::InputFile;
|
||||
using OPENEXR_IMF_NAMESPACE::setGlobalThreadCount;
|
||||
using OPENEXR_IMF_NAMESPACE::CompositeDeepScanLine;
|
||||
|
||||
// a marker to say we've done inserting values into a sample: do mydata << end()
|
||||
struct end{};
|
||||
|
||||
// a marker to say we're about to send the final result, not another sample: do mydata << result()
|
||||
struct result{};
|
||||
|
||||
|
||||
//
|
||||
// support class that generates deep data, along with the 'ground truth'
|
||||
// result
|
||||
//
|
||||
template<class T>
|
||||
class data
|
||||
{
|
||||
public:
|
||||
vector<string> _channels; // channel names - same size and order as in all other arrays,
|
||||
vector<T> _current_result; // one value per channel: the ground truth value for the given pixel
|
||||
vector<vector <T> >_results; // a list of result pixels
|
||||
|
||||
|
||||
bool _inserting_result;
|
||||
bool _started; // we've started to assemble the values - no more channels permitted
|
||||
vector<T> _current_sample; // one value per channel for the sample currently being inserted
|
||||
vector< vector <T> > _current_pixel; // a list of results for the current pixwel
|
||||
vector< vector< vector<T> > > _samples; // a list of pixels
|
||||
PixelType _type;
|
||||
|
||||
data() : _inserting_result(false),_started(false)
|
||||
{
|
||||
if(typeid(T)==typeid(half))
|
||||
{
|
||||
_type = OPENEXR_IMF_NAMESPACE::HALF;
|
||||
}
|
||||
else
|
||||
{
|
||||
_type = OPENEXR_IMF_NAMESPACE::FLOAT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// add a value to the current sample
|
||||
data & operator << (float value)
|
||||
{
|
||||
if(_inserting_result)
|
||||
{
|
||||
_current_result.push_back(value);
|
||||
}else{
|
||||
_current_sample.push_back(T(value));
|
||||
}
|
||||
_started=true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// switch between writing samples and the result
|
||||
data & operator << (const result &)
|
||||
{
|
||||
if(_current_sample.size()!=0)
|
||||
{
|
||||
throw IEX_NAMESPACE::ArgExc("bug in test code: can't switch to inserting result: values written without 'end' statement");
|
||||
}
|
||||
if(_current_result.size()!=0)
|
||||
{
|
||||
throw IEX_NAMESPACE::ArgExc("bug in test suite: already inserting result");
|
||||
}
|
||||
_inserting_result=true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// finalise the current sample/results
|
||||
|
||||
data & operator << (const end &)
|
||||
{
|
||||
if(_inserting_result)
|
||||
{
|
||||
if(_current_result.size()!=_channels.size())
|
||||
{
|
||||
throw IEX_NAMESPACE::ArgExc("bug in test suite: cannot end result: wrong number of values written");
|
||||
}
|
||||
_results.push_back(_current_result);
|
||||
_current_result.resize(0);
|
||||
|
||||
//
|
||||
// also cause the current_samples to be written as the given number of pixels
|
||||
//
|
||||
_samples.push_back(_current_pixel);
|
||||
_current_pixel.resize(0);
|
||||
_inserting_result=false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(_current_sample.size()!=_channels.size())
|
||||
{
|
||||
throw IEX_NAMESPACE::ArgExc("bug in test suite: cannot end sample: wrong number of values written");
|
||||
}
|
||||
_current_pixel.push_back(_current_sample);
|
||||
_current_sample.resize(0);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// add a new channel
|
||||
|
||||
data & operator << (const string & s)
|
||||
{
|
||||
if(_started)
|
||||
{
|
||||
throw IEX_NAMESPACE::ArgExc("bug in test suite: cannot insert new channels here");
|
||||
}
|
||||
_channels.push_back(s);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
// total number of samples - storage for one copy of everything is sizeof(T)*channels.size()*totalSamples
|
||||
size_t totalSamples() const
|
||||
{
|
||||
size_t answer=0;
|
||||
for(size_t i=0;i<_samples.size();i++)
|
||||
{
|
||||
answer+=_samples[i].size();
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
//copy the channels into the header list
|
||||
void
|
||||
setHeader(Header & hdr) const
|
||||
{
|
||||
for(size_t i=0;i<_channels.size();i++)
|
||||
{
|
||||
hdr.channels().insert(_channels[i],_type);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void frak(vector< data<T> > & parts) const
|
||||
{
|
||||
for(size_t i=0;i<parts.size();i++)
|
||||
{
|
||||
parts[i]._channels = _channels;
|
||||
parts[i]._results = _results;
|
||||
parts[i]._type = _type;
|
||||
parts[i]._samples.resize(_samples.size());
|
||||
}
|
||||
|
||||
//
|
||||
// loop over each pixel, pushing its values to a random part
|
||||
//
|
||||
for(size_t i=0;i<_samples.size();i++)
|
||||
{
|
||||
// copy sample to a random part
|
||||
|
||||
for(int s=0;s<_samples[i].size();s++)
|
||||
{
|
||||
int part = rand()% parts.size();
|
||||
parts[part]._samples[i].push_back(_samples[i][s]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
writeData(DeepScanLineOutputPart & part) const
|
||||
{
|
||||
Box2i dw=part.header().dataWindow();
|
||||
size_t output_pixels = (dw.size().x+1)*(dw.size().y+1);
|
||||
|
||||
// how many times we'll write the same pattern
|
||||
size_t repeats = 1+(output_pixels/_results.size());
|
||||
|
||||
size_t sample_buffer_size = totalSamples()*repeats;
|
||||
|
||||
// buffer for sample counts
|
||||
vector<unsigned int> counts(output_pixels);
|
||||
|
||||
// buffers for sample pointers
|
||||
vector< vector<T *> > sample_pointers(_channels.size());
|
||||
|
||||
// buffer for actual sample data
|
||||
vector< vector<T> > sample_buffers(_channels.size());
|
||||
|
||||
for(size_t i=0;i<sample_buffers.size();i++)
|
||||
{
|
||||
sample_pointers[i].resize(output_pixels);
|
||||
sample_buffers[i].resize(sample_buffer_size);
|
||||
}
|
||||
|
||||
|
||||
size_t pixel=0; // which pixel we are currently writing
|
||||
size_t sample=0; // which sample we are currently writing into
|
||||
|
||||
for(size_t p=0;p<output_pixels;p++)
|
||||
{
|
||||
size_t count = _samples[pixel].size();
|
||||
counts[p]=count;
|
||||
if( count>0 )
|
||||
{
|
||||
for(size_t c=0 ; c<_channels.size() ; c++)
|
||||
{
|
||||
for(size_t s=0 ; s < count ; s++ )
|
||||
{
|
||||
sample_buffers[c][sample+s]=_samples[pixel][s][c];
|
||||
}
|
||||
sample_pointers[c][p]=&sample_buffers[c][sample];
|
||||
}
|
||||
sample+=count;
|
||||
}
|
||||
pixel++;
|
||||
if(pixel==_samples.size()) pixel=0;
|
||||
}
|
||||
cout << " wrote " << sample << " samples into " << output_pixels << " pixels\n";
|
||||
|
||||
DeepFrameBuffer fb;
|
||||
fb.insertSampleCountSlice(Slice(UINT,
|
||||
(char *)(&counts[0]-dw.min.x-(dw.size().x+1)*dw.min.y),
|
||||
sizeof(unsigned int),
|
||||
sizeof(unsigned int)*(dw.size().x+1)
|
||||
)
|
||||
);
|
||||
for(size_t c=0;c<_channels.size();c++)
|
||||
{
|
||||
fb.insert(_channels[c],
|
||||
DeepSlice(_type,(char *)(&sample_pointers[c][0]-dw.min.x-(dw.size().x+1)*dw.min.y),
|
||||
sizeof(T *),
|
||||
sizeof(T *)*(dw.size().x+1),
|
||||
sizeof(T)
|
||||
)
|
||||
);
|
||||
}
|
||||
part.setFrameBuffer(fb);
|
||||
part.writePixels(dw.size().y+1);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
setUpFrameBuffer(vector<T> & data,FrameBuffer & framebuf,const Box2i & dw,bool dontbotherloadingdepth) const
|
||||
{
|
||||
|
||||
// allocate enough space for all channels (even the depth channel)
|
||||
data.resize(_channels.size()*(dw.size().x+1)*(dw.size().y+1));
|
||||
for(size_t i=0;i<_channels.size();i++)
|
||||
{
|
||||
if(!dontbotherloadingdepth || (_channels[i]!="Z" && _channels[i]!="ZBack") )
|
||||
{
|
||||
framebuf.insert(_channels[i].c_str(),
|
||||
Slice(_type,(char *) (&data[i] - (dw.min.x + dw.min.y*(dw.size().x+1))*_channels.size() ),
|
||||
sizeof(T)*_channels.size(),
|
||||
sizeof(T)*(dw.size().x+1)*_channels.size())
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// check values are within a suitable tolerance of the expected value (expect some errors due to half float storage etc)
|
||||
//
|
||||
void
|
||||
checkValues(const vector<T> & data,const Box2i & dw,bool dontbothercheckingdepth)
|
||||
{
|
||||
size_t size = _channels.size()+(dw.size().x+1)*(dw.size().y+1);
|
||||
size_t pel=0;
|
||||
size_t channel=0;
|
||||
if(dontbothercheckingdepth)
|
||||
{
|
||||
for(size_t i=0;i<size;i++)
|
||||
{
|
||||
if(_channels[channel]!="Z" && _channels[channel]!="ZBack")
|
||||
{
|
||||
if(fabs(_results[pel][channel] - data[i])>0.005)
|
||||
{
|
||||
cout << "sample " << i << " (channel " << _channels[channel] << " of pixel " << i % _channels.size() << ") ";
|
||||
cout << "doesn't match expected value (channel " << channel << " of pixel " << pel << ") : ";
|
||||
cout << "got " << data[i] << " expected " << _results[pel][channel] << endl;
|
||||
}
|
||||
assert(fabs(_results[pel][channel]- data[i])<=0.005);
|
||||
}
|
||||
channel++;
|
||||
if(channel==_channels.size())
|
||||
{
|
||||
channel=0;
|
||||
pel++;
|
||||
if(pel==_results.size())
|
||||
{
|
||||
pel=0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}else{
|
||||
for(size_t i=0;i<size;i++)
|
||||
{
|
||||
if(fabs(_results[pel][channel] - data[i])>0.005)
|
||||
{
|
||||
cout << "sample " << i << " (channel " << _channels[channel] << " of pixel " << i % _channels.size() << ") ";
|
||||
cout << "doesn't match expected value (channel " << channel << " of pixel " << pel << ") : ";
|
||||
cout << "got " << data[i] << " expected " << _results[pel][channel] << endl;
|
||||
}
|
||||
assert(fabs(_results[pel][channel] - data[i])<=0.005);
|
||||
channel++;
|
||||
if(channel==_channels.size())
|
||||
{
|
||||
channel=0;
|
||||
pel++;
|
||||
if(pel==_results.size())
|
||||
{
|
||||
pel=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template<class T>
|
||||
ostream & operator << (ostream & o,data<T> & d)
|
||||
{
|
||||
o << "channels: [ ";
|
||||
for(size_t i=0;i<d._channels.size();i++)
|
||||
{
|
||||
o << d._channels[i] << " ";
|
||||
}
|
||||
o << "]" << endl;
|
||||
|
||||
for(size_t i=0;i<d._samples.size();i++)
|
||||
{
|
||||
o << "pixel: " << d._samples[i].size() << " samples" << endl;
|
||||
|
||||
for(size_t j=0;j<d._samples[i].size();j++)
|
||||
{
|
||||
o << " " << j << ": [ ";
|
||||
for(size_t k = 0; k < d._samples[i][j].size();k++)
|
||||
{
|
||||
o << d._samples[i][j][k] << ' ';
|
||||
}
|
||||
o << "]" << endl;
|
||||
}
|
||||
o << "result: [ ";
|
||||
for(size_t k=0;k<d._results[i].size();k++)
|
||||
{
|
||||
o << d._results[i][k] << ' ' ;
|
||||
}
|
||||
o << "]\n" << endl;
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
template<class DATA>
|
||||
void
|
||||
make_pattern(data<DATA> & bob,int pattern_number)
|
||||
{
|
||||
|
||||
if (pattern_number==0)
|
||||
{
|
||||
// set channels
|
||||
|
||||
bob << string("Z") << string("ZBack") << string("A") << string("R");
|
||||
PixelType t;
|
||||
|
||||
// regular two-pixel composite
|
||||
bob << 1.0 << 2.0 << 0.0 << 1.0 << end();
|
||||
bob << 2.1 << 2.3 << 0.5 << 0.4 << end();
|
||||
bob << result();
|
||||
bob << 3.1 << 4.3 << 0.5 << 1.4 << end();
|
||||
|
||||
bob << 10 << 20 << 1.0 << 1.0 << end();
|
||||
bob << 20 << 30 << 1.0 << 2.0 << end();
|
||||
bob << result();
|
||||
bob << 10 << 20 << 1.0 << 1.0 << end();
|
||||
|
||||
bob << result();
|
||||
bob << 0.0 << 0.0 << 0.0 << 0.0 << end();
|
||||
}
|
||||
else if (pattern_number==1)
|
||||
{
|
||||
//
|
||||
// out of order channels, no zback - should-re-order them for us
|
||||
//
|
||||
bob << string("Z") << string("R") << string("G") << string("B") << string("A");
|
||||
|
||||
|
||||
// write this four times, so we get various patterns for splitting the blocks
|
||||
for(int pass=0;pass<4;pass++)
|
||||
{
|
||||
// regular four-pixel composite
|
||||
bob << 1.0 << 0.4 << 1.25 << -0.1 << 0.7 << end();
|
||||
bob << 2.2 << 0.2 << -0.1 << 0.0 << 0.24 << end();
|
||||
bob << 2.3 << 0.9 << 0.56 << 2.26 << 0.9 << end();
|
||||
bob << 5.0 << 1.0 << 0.5 << 0.60 << 0.2 << end();
|
||||
bob << result();
|
||||
|
||||
// eight-pixel composite
|
||||
bob << 2.2984 << 0.68800 << 1.35908 << 0.42896 << 0.9817 << end();
|
||||
bob << 1.0 << 0.4 << 1.25 << -0.1 << 0.7 << end();
|
||||
bob << 2.2 << 0.2 << -0.1 << 0.0 << 0.24 << end();
|
||||
bob << 2.3 << 0.9 << 0.56 << 2.26 << 0.9 << end();
|
||||
bob << 5.0 << 1.0 << 0.5 << 0.60 << 0.2 << end();
|
||||
bob << 11.0 << 0.4 << 1.25 << -0.1 << 0.7 << end();
|
||||
bob << 12.2 << 0.2 << -0.1 << 0.0 << 0.24 << end();
|
||||
bob << 12.3 << 0.9 << 0.56 << 2.26 << 0.9 << end();
|
||||
bob << 15.0 << 1.0 << 0.5 << 0.60 << 0.2 << end();
|
||||
bob << result();
|
||||
bob << 2.62319 << 0.7005 << 1.38387 << 0.43678 << 0.99967 << end();
|
||||
|
||||
// one-pixel composite
|
||||
|
||||
bob << 27.0 << 1.0 << -1.0 << 42.0 << 14 << end(); // alpha>1 should still work
|
||||
bob << result();
|
||||
bob << 27.0 << 1.0 << -1.0 << 42.0 << 14 << end();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void
|
||||
write_file(const char * filename, const data<T> & master, int number_of_parts)
|
||||
{
|
||||
vector<Header> headers(number_of_parts);
|
||||
|
||||
// all headers are the same in this test
|
||||
headers[0].displayWindow().max.x=164;
|
||||
headers[0].displayWindow().max.y=216;
|
||||
headers[0].dataWindow().min.x=rand()%400 - 200;
|
||||
headers[0].dataWindow().max.x=headers[0].dataWindow().min.x+40+rand()%400;
|
||||
headers[0].dataWindow().min.y=rand()%400 - 200;
|
||||
headers[0].dataWindow().max.y=headers[0].dataWindow().min.y+40+rand()%400;
|
||||
cout << "data window: " << headers[0].dataWindow().min.x << ',' << headers[0].dataWindow().min.y << ' ' <<
|
||||
headers[0].dataWindow().max.x << ',' << headers[0].dataWindow().max.y << endl;
|
||||
headers[0].setType(DEEPSCANLINE);
|
||||
headers[0].compression()=ZIPS_COMPRESSION;
|
||||
headers[0].setName("Part0");
|
||||
|
||||
for(int i=1;i<number_of_parts;i++)
|
||||
{
|
||||
headers[i]=headers[0];
|
||||
ostringstream s;
|
||||
s << "Part" << i;
|
||||
headers[i].setName(s.str());
|
||||
}
|
||||
|
||||
vector< data<T> > sub_parts(number_of_parts);
|
||||
|
||||
if(number_of_parts>1)
|
||||
{
|
||||
master.frak(sub_parts);
|
||||
}
|
||||
|
||||
if(number_of_parts==1)
|
||||
{
|
||||
master.setHeader(headers[0]);
|
||||
}else{
|
||||
|
||||
for(int i=0;i<number_of_parts;i++)
|
||||
{
|
||||
sub_parts[i].setHeader(headers[i]);
|
||||
}
|
||||
}
|
||||
|
||||
MultiPartOutputFile f(filename,&headers[0],headers.size());
|
||||
for(int i=0;i<number_of_parts;i++)
|
||||
{
|
||||
DeepScanLineOutputPart p(f,i);
|
||||
if(number_of_parts==1)
|
||||
{
|
||||
master.writeData(p);
|
||||
}else{
|
||||
sub_parts[i].writeData(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void
|
||||
test_parts (int pattern_number,
|
||||
int number_of_parts,
|
||||
bool load_depths,
|
||||
bool entire_buffer,
|
||||
const std::string &tempDir)
|
||||
{
|
||||
std::string fn = tempDir + "imf_test_composite_deep_scanline_source.exr";
|
||||
|
||||
data<T> master;
|
||||
make_pattern (master, pattern_number);
|
||||
write_file (fn.c_str(), master,number_of_parts);
|
||||
|
||||
|
||||
{
|
||||
vector<T> data;
|
||||
CompositeDeepScanLine comp;
|
||||
FrameBuffer testbuf;
|
||||
MultiPartInputFile input(fn.c_str());
|
||||
vector<DeepScanLineInputPart *> parts(number_of_parts);
|
||||
|
||||
|
||||
// use 'part' interface TODO test file interface too
|
||||
for(int i=0;i<number_of_parts;i++)
|
||||
{
|
||||
parts[i] = new DeepScanLineInputPart(input,i);
|
||||
comp.addSource(parts[i]);
|
||||
}
|
||||
|
||||
|
||||
master.setUpFrameBuffer(data,testbuf,comp.dataWindow(),load_depths);
|
||||
|
||||
comp.setFrameBuffer(testbuf);
|
||||
|
||||
//
|
||||
// try loading the whole buffer
|
||||
//
|
||||
if(entire_buffer)
|
||||
{
|
||||
comp.readPixels(comp.dataWindow().min.y,comp.dataWindow().max.y);
|
||||
}else{
|
||||
int low = comp.dataWindow().min.y;
|
||||
while(low<comp.dataWindow().max.y)
|
||||
{
|
||||
int high = low + rand()%64;
|
||||
if(high>comp.dataWindow().max.y)
|
||||
high = comp.dataWindow().max.y;
|
||||
comp.readPixels(low,high);
|
||||
low = high;
|
||||
}
|
||||
}
|
||||
|
||||
master.checkValues(data,comp.dataWindow(),load_depths);
|
||||
|
||||
for(int i=0;i<number_of_parts;i++)
|
||||
{
|
||||
delete parts[i];
|
||||
}
|
||||
}
|
||||
if(number_of_parts==1)
|
||||
{
|
||||
// also test InputFile interface
|
||||
InputFile file(fn.c_str());
|
||||
vector<T> data;
|
||||
FrameBuffer testbuf;
|
||||
const Box2i & dataWindow = file.header().dataWindow();
|
||||
master.setUpFrameBuffer(data,testbuf,dataWindow,load_depths);
|
||||
file.setFrameBuffer(testbuf);
|
||||
if(entire_buffer)
|
||||
{
|
||||
file.readPixels(dataWindow.min.y,dataWindow.max.y);
|
||||
}else{
|
||||
int low = dataWindow.min.y;
|
||||
while(low<dataWindow.max.y)
|
||||
{
|
||||
int high = low + rand()%64;
|
||||
if(high>dataWindow.max.y)
|
||||
high = dataWindow.max.y;
|
||||
file.readPixels(low,high);
|
||||
low = high;
|
||||
}
|
||||
}
|
||||
|
||||
master.checkValues (data, dataWindow, load_depths);
|
||||
|
||||
}
|
||||
remove (fn.c_str());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void testCompositeDeepScanLine (const std::string & tempDir)
|
||||
{
|
||||
|
||||
cout << "\n\nTesting deep compositing interface basic functionality:\n" << endl;
|
||||
|
||||
int passes=2;
|
||||
if (!ILMTHREAD_NAMESPACE::supportsThreads ())
|
||||
{
|
||||
passes=1;
|
||||
}
|
||||
|
||||
|
||||
srand(1);
|
||||
|
||||
for(int pass=0;pass<2;pass++)
|
||||
{
|
||||
|
||||
test_parts<float>(0, 1, true, true, tempDir);
|
||||
test_parts<float>(0, 1, false, false, tempDir);
|
||||
test_parts<half> (0, 1, true, false, tempDir);
|
||||
test_parts<half> (0, 1, false, true, tempDir);
|
||||
|
||||
//
|
||||
// test pattern 1: tested by confirming data is written correctly and
|
||||
// then reading correct results in Nuke
|
||||
//
|
||||
test_parts<float>(1, 1, true, false, tempDir);
|
||||
test_parts<float>(1, 1, false, true, tempDir);
|
||||
test_parts<half> (1, 1, true, true, tempDir);
|
||||
test_parts<half> (1, 1, false, false, tempDir);
|
||||
|
||||
|
||||
cout << "Testing deep compositing across multiple parts:\n" << endl;
|
||||
|
||||
test_parts<float>(0, 5, true, false, tempDir);
|
||||
test_parts<float>(0, 5, false, true, tempDir);
|
||||
test_parts<half> (0, 5, true, false, tempDir);
|
||||
test_parts<half> (0, 5, false, true, tempDir);
|
||||
|
||||
test_parts<float>(1, 3, true, true, tempDir);
|
||||
test_parts<float>(1, 3, false, false, tempDir);
|
||||
test_parts<half> (1, 3, true, true, tempDir);
|
||||
test_parts<half> (1, 3, false, false, tempDir);
|
||||
|
||||
test_parts<float>(1, 4, true, true, tempDir);
|
||||
test_parts<float>(1, 4, false, false, tempDir);
|
||||
test_parts<half> (1, 4, true, false, tempDir);
|
||||
test_parts<half> (1, 4, false, true, tempDir);
|
||||
|
||||
if(passes==2 && pass==0)
|
||||
{
|
||||
cout << " testing with multithreading...\n";
|
||||
setGlobalThreadCount(64);
|
||||
}
|
||||
}
|
||||
cout << " ok\n" << endl;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2012, Weta Digital Ltd
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Weta Digital nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef TESTCOMPOSITEDEEPSCANLINE_H_
|
||||
#define TESTCOMPOSITEDEEPSCANLINE_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
void testCompositeDeepScanLine (const std::string & tempDir);
|
||||
|
||||
#endif /* TESTCOMPOSITEDEEPSCANLINE_H_ */
|
||||
435
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testCompression.cpp
Normal file
435
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testCompression.cpp
Normal file
@@ -0,0 +1,435 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2004-2012, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "compareB44.h"
|
||||
|
||||
#include <ImfOutputFile.h>
|
||||
#include <ImfInputFile.h>
|
||||
#include <ImfChannelList.h>
|
||||
#include <ImfArray.h>
|
||||
#include <ImathRandom.h>
|
||||
#include <half.h>
|
||||
#include "compareFloat.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
namespace IMF = OPENEXR_IMF_NAMESPACE;
|
||||
using namespace IMF;
|
||||
using namespace std;
|
||||
using namespace IMATH_NAMESPACE;
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
void
|
||||
fillPixels1 (Array2D<unsigned int> &pi,
|
||||
Array2D<half> &ph,
|
||||
Array2D<float> &pf,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
cout << "only zeroes" << endl;
|
||||
|
||||
for (int y = 0; y < height; ++y)
|
||||
for (int x = 0; x < width; ++x)
|
||||
{
|
||||
pi[y][x] = 0;
|
||||
ph[y][x] = 0;
|
||||
pf[y][x] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
fillPixels2 (Array2D<unsigned int> &pi,
|
||||
Array2D<half> &ph,
|
||||
Array2D<float> &pf,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
cout << "pattern 1" << endl;
|
||||
|
||||
for (int y = 0; y < height; ++y)
|
||||
for (int x = 0; x < width; ++x)
|
||||
{
|
||||
pi[y][x] = (x + y) & 1;
|
||||
ph[y][x] = pi[y][x];
|
||||
pf[y][x] = pi[y][x];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
fillPixels3 (Array2D<unsigned int> &pi,
|
||||
Array2D<half> &ph,
|
||||
Array2D<float> &pf,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
cout << "pattern 2" << endl;
|
||||
|
||||
for (int y = 0; y < height; ++y)
|
||||
for (int x = 0; x < width; ++x)
|
||||
{
|
||||
pi[y][x] = x % 100 + 100 * (y % 100);
|
||||
ph[y][x] = sin (double (x)) + sin (y * 0.5);
|
||||
pf[y][x] = sin (double (y)) + sin (x * 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
fillPixels4 (Array2D<unsigned int> &pi,
|
||||
Array2D<half> &ph,
|
||||
Array2D<float> &pf,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
cout << "random bits" << endl;
|
||||
|
||||
//
|
||||
// Use of a union to extract the bit pattern from a float, as is
|
||||
// done below, works only if int and float have the same size.
|
||||
//
|
||||
|
||||
assert (sizeof (int) == sizeof (float));
|
||||
|
||||
Rand48 rand;
|
||||
|
||||
for (int y = 0; y < height; ++y)
|
||||
for (int x = 0; x < width; ++x)
|
||||
{
|
||||
pi[y][x] = rand.nexti();
|
||||
|
||||
ph[y][x].setBits (rand.nexti());
|
||||
|
||||
union {int i; float f;} u;
|
||||
u.i = rand.nexti();
|
||||
|
||||
pf[y][x] = u.f;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
writeRead (const Array2D<unsigned int> &pi1,
|
||||
const Array2D<half> &ph1,
|
||||
const Array2D<float> &pf1,
|
||||
const char fileName[],
|
||||
int width,
|
||||
int height,
|
||||
int xOffset,
|
||||
int yOffset,
|
||||
Compression comp,
|
||||
int xs,
|
||||
int ys)
|
||||
{
|
||||
//
|
||||
// Write the pixel data in pi1, ph1 and ph2 to an
|
||||
// image file using the specified compression type
|
||||
// and subsampling rates. Read the pixel data back
|
||||
// from the file and verify that the data did not
|
||||
// change.
|
||||
//
|
||||
|
||||
cout << "compression " << comp <<
|
||||
", x sampling " << xs <<
|
||||
", y sampling " << ys <<
|
||||
":" << flush;
|
||||
|
||||
|
||||
Header hdr ((Box2i (V2i (0, 0), // display window
|
||||
V2i (width - 1, height -1))),
|
||||
(Box2i (V2i (xOffset, yOffset), // data window
|
||||
V2i (xOffset + width - 1, yOffset + height - 1))));
|
||||
|
||||
hdr.compression() = comp;
|
||||
|
||||
hdr.channels().insert ("I", // name
|
||||
Channel (IMF::UINT, // type
|
||||
xs, // xSampling
|
||||
ys) // ySampling
|
||||
);
|
||||
|
||||
hdr.channels().insert ("H", // name
|
||||
Channel (IMF::HALF, // type
|
||||
xs, // xSampling
|
||||
ys) // ySampling
|
||||
);
|
||||
|
||||
hdr.channels().insert ("F", // name
|
||||
Channel (IMF::FLOAT, // type
|
||||
xs, // xSampling
|
||||
ys) // ySampling
|
||||
);
|
||||
|
||||
{
|
||||
FrameBuffer fb;
|
||||
|
||||
fb.insert ("I", // name
|
||||
Slice (IMF::UINT, // type
|
||||
(char *) &pi1[-yOffset / ys][-xOffset / xs], // base
|
||||
sizeof (pi1[0][0]), // xStride
|
||||
sizeof (pi1[0][0]) * (width / xs), // yStride
|
||||
xs, // xSampling
|
||||
ys) // ySampling
|
||||
);
|
||||
|
||||
fb.insert ("H", // name
|
||||
Slice (IMF::HALF, // type
|
||||
(char *) &ph1[-yOffset / ys][-xOffset / xs], // base
|
||||
sizeof (ph1[0][0]), // xStride
|
||||
sizeof (ph1[0][0]) * (width / xs), // yStride
|
||||
xs, // xSampling
|
||||
ys) // ySampling
|
||||
);
|
||||
|
||||
fb.insert ("F", // name
|
||||
Slice (IMF::FLOAT, // type
|
||||
(char *) &pf1[-yOffset / ys][-xOffset / xs], // base
|
||||
sizeof (pf1[0][0]), // xStride
|
||||
sizeof (pf1[0][0]) * (width / xs), // yStride
|
||||
xs, // xSampling
|
||||
ys) // ySampling
|
||||
);
|
||||
|
||||
cout << " writing" << flush;
|
||||
|
||||
remove (fileName);
|
||||
OutputFile out (fileName, hdr);
|
||||
out.setFrameBuffer (fb);
|
||||
out.writePixels (height);
|
||||
}
|
||||
|
||||
{
|
||||
cout << " reading" << flush;
|
||||
|
||||
InputFile in (fileName);
|
||||
|
||||
const Box2i &dw = in.header().dataWindow();
|
||||
int w = dw.max.x - dw.min.x + 1;
|
||||
int h = dw.max.y - dw.min.y + 1;
|
||||
int dx = dw.min.x;
|
||||
int dy = dw.min.y;
|
||||
|
||||
Array2D<unsigned int> pi2 (h / ys, w / xs);
|
||||
Array2D<half> ph2 (h / ys, w / xs);
|
||||
Array2D<float> pf2 (h / ys, w / xs);
|
||||
|
||||
FrameBuffer fb;
|
||||
|
||||
{
|
||||
int xs = in.header().channels()["I"].xSampling;
|
||||
int ys = in.header().channels()["I"].ySampling;
|
||||
|
||||
fb.insert ("I", // name
|
||||
Slice (IMF::UINT, // type
|
||||
(char *) &pi2[-dy / ys][-dx / xs], // base
|
||||
sizeof (pi2[0][0]), // xStride
|
||||
sizeof (pi2[0][0]) * (w / xs), // yStride
|
||||
xs, // xSampling
|
||||
ys) // ySampling
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
int xs = in.header().channels()["H"].xSampling;
|
||||
int ys = in.header().channels()["H"].ySampling;
|
||||
|
||||
fb.insert ("H", // name
|
||||
Slice (IMF::HALF, // type
|
||||
(char *) &ph2[-dy / ys][-dx / xs], // base
|
||||
sizeof (ph2[0][0]), // xStride
|
||||
sizeof (ph2[0][0]) * (w / xs), // yStride
|
||||
xs, // xSampling
|
||||
ys) // ySampling
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
int xs = in.header().channels()["F"].xSampling;
|
||||
int ys = in.header().channels()["F"].ySampling;
|
||||
|
||||
fb.insert ("F", // name
|
||||
Slice (IMF::FLOAT, // type
|
||||
(char *) &pf2[-dy / ys][-dx / xs], // base
|
||||
sizeof (pf2[0][0]), // xStride
|
||||
sizeof (pf2[0][0]) * (w / xs), // yStride
|
||||
xs, // xSampling
|
||||
ys) // ySampling
|
||||
);
|
||||
}
|
||||
|
||||
in.setFrameBuffer (fb);
|
||||
in.readPixels (dw.min.y, dw.max.y);
|
||||
|
||||
cout << " comparing" << flush;
|
||||
|
||||
assert (in.header().displayWindow() == hdr.displayWindow());
|
||||
assert (in.header().dataWindow() == hdr.dataWindow());
|
||||
assert (in.header().pixelAspectRatio() == hdr.pixelAspectRatio());
|
||||
assert (in.header().screenWindowCenter() == hdr.screenWindowCenter());
|
||||
assert (in.header().screenWindowWidth() == hdr.screenWindowWidth());
|
||||
assert (in.header().lineOrder() == hdr.lineOrder());
|
||||
assert (in.header().compression() == hdr.compression());
|
||||
|
||||
ChannelList::ConstIterator hi = hdr.channels().begin();
|
||||
ChannelList::ConstIterator ii = in.header().channels().begin();
|
||||
|
||||
while (hi != hdr.channels().end())
|
||||
{
|
||||
assert (!strcmp (hi.name(), ii.name()));
|
||||
assert (hi.channel().type == ii.channel().type);
|
||||
assert (hi.channel().xSampling == ii.channel().xSampling);
|
||||
assert (hi.channel().ySampling == ii.channel().ySampling);
|
||||
|
||||
++hi;
|
||||
++ii;
|
||||
}
|
||||
|
||||
assert (ii == in.header().channels().end());
|
||||
|
||||
for (int y = 0; y < h / ys; ++y)
|
||||
{
|
||||
for (int x = 0; x < w / xs; ++x)
|
||||
{
|
||||
assert (pi1[y][x] == pi2[y][x]);
|
||||
assert (equivalent (pf1[y][x], pf2[y][x], comp));
|
||||
|
||||
if (comp != B44_COMPRESSION &&
|
||||
comp != B44A_COMPRESSION)
|
||||
{
|
||||
assert (ph1[y][x].bits() == ph2[y][x].bits());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (comp == B44_COMPRESSION ||
|
||||
comp == B44A_COMPRESSION)
|
||||
{
|
||||
Array2D<half> ph3 (h / ys, w / xs);
|
||||
|
||||
for (int y = 0; y < h / ys; ++y)
|
||||
for (int x = 0; x < w / xs; ++x)
|
||||
ph3[y][x] = ph1[y][x];
|
||||
|
||||
compareB44 (w / xs, h / ys, ph3, ph2);
|
||||
}
|
||||
}
|
||||
|
||||
remove (fileName);
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
writeRead (const std::string &tempDir,
|
||||
const Array2D<unsigned int> &pi,
|
||||
const Array2D<half> &ph,
|
||||
const Array2D<float> &pf,
|
||||
int w,
|
||||
int h,
|
||||
int dx,
|
||||
int dy)
|
||||
{
|
||||
std::string filename = tempDir + "imf_test_comp.exr";
|
||||
|
||||
for (int xs = 1; xs <= 2; ++xs)
|
||||
{
|
||||
for (int ys = 1; ys <= 2; ++ys)
|
||||
{
|
||||
for (int comp = 0; comp < NUM_COMPRESSION_METHODS; ++comp)
|
||||
{
|
||||
writeRead (pi, ph, pf,
|
||||
filename.c_str(),
|
||||
w * xs, h * ys,
|
||||
dx * xs, dy * ys,
|
||||
Compression (comp),
|
||||
xs, ys);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
void
|
||||
testCompression (const std::string &tempDir)
|
||||
{
|
||||
try
|
||||
{
|
||||
cout << "Testing pixel data types, "
|
||||
"subsampling and "
|
||||
"compression schemes" << endl;
|
||||
|
||||
const int W = 1371;
|
||||
const int H = 159;
|
||||
const int DX = 17;
|
||||
const int DY = 29;
|
||||
|
||||
Array2D<unsigned int> pi (H, W);
|
||||
Array2D<half> ph (H, W);
|
||||
Array2D<float> pf (H, W);
|
||||
|
||||
//
|
||||
// If the following assertion fails, new pixel types have
|
||||
// been added to the Imf library; testing code for the new
|
||||
// pixel types should be added to this file.
|
||||
//
|
||||
|
||||
assert (NUM_PIXELTYPES == 3);
|
||||
|
||||
fillPixels1 (pi, ph, pf, W, H);
|
||||
writeRead (tempDir, pi, ph, pf, W, H, DX, DY);
|
||||
|
||||
fillPixels2 (pi, ph, pf, W, H);
|
||||
writeRead (tempDir, pi, ph, pf, W, H, DX, DY);
|
||||
|
||||
fillPixels3 (pi, ph, pf, W, H);
|
||||
writeRead (tempDir, pi, ph, pf, W, H, DX, DY);
|
||||
|
||||
fillPixels4 (pi, ph, pf, W, H);
|
||||
writeRead (tempDir, pi, ph, pf, W, H, DX, DY);
|
||||
|
||||
cout << "ok\n" << endl;
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
cerr << "ERROR -- caught exception: " << e.what() << endl;
|
||||
assert (false);
|
||||
}
|
||||
}
|
||||
41
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testCompression.h
Normal file
41
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testCompression.h
Normal file
@@ -0,0 +1,41 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
#include <string>
|
||||
|
||||
void testCompression (const std::string &tempDir);
|
||||
|
||||
413
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testConversion.cpp
Normal file
413
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testConversion.cpp
Normal file
@@ -0,0 +1,413 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2003-2012, Industrial Light & Magic, a division of Lucasfilm
|
||||
// Entertainment Company Ltd. Portions contributed and copyright held by
|
||||
// others as indicated. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer.
|
||||
//
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided with
|
||||
// the distribution.
|
||||
//
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// any other contributors to this software may be used to endorse or
|
||||
// promote products derived from this software without specific prior
|
||||
// written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include <ImfOutputFile.h>
|
||||
#include <ImfInputFile.h>
|
||||
#include <ImfTiledOutputFile.h>
|
||||
#include <ImfTiledInputFile.h>
|
||||
#include <ImfChannelList.h>
|
||||
#include <ImfArray.h>
|
||||
#include <ImfConvert.h>
|
||||
#include <half.h>
|
||||
#include "compareFloat.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
namespace IMF = OPENEXR_IMF_NAMESPACE;
|
||||
using namespace IMF;
|
||||
using namespace std;
|
||||
using namespace IMATH_NAMESPACE;
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
//
|
||||
// Functions to test conversion of individual numbers
|
||||
//
|
||||
|
||||
void
|
||||
testFloatToUint (unsigned int floatVal, unsigned int uintVal)
|
||||
{
|
||||
union {unsigned int ui; float f;} u;
|
||||
u.ui = floatVal;
|
||||
cout << "floatToUint (" << u.f << ") == " << floatToUint(u.f) << endl;
|
||||
assert (floatToUint (u.f) == uintVal);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
testHalfToUint (unsigned int halfVal, unsigned int uintVal)
|
||||
{
|
||||
half h;
|
||||
h.setBits (halfVal);
|
||||
cout << "halfToUint (" << h << ") == " << halfToUint(h) << endl;
|
||||
assert (halfToUint (h) == uintVal);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
testFloatToHalf (unsigned int floatVal, unsigned int halfVal)
|
||||
{
|
||||
union {unsigned int ui; float f;} u;
|
||||
u.ui = floatVal;
|
||||
cout << "floatToHalf (" << u.f << ") == " << floatToHalf(u.f) << endl;
|
||||
assert (floatToHalf(u.f).bits() == halfVal);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
testUintToHalf (unsigned int uintVal, unsigned int halfVal)
|
||||
{
|
||||
cout << "uintToHalf (" << uintVal << ") == " << uintToHalf(uintVal) << endl;
|
||||
assert (uintToHalf(uintVal).bits() == halfVal);
|
||||
}
|
||||
|
||||
void
|
||||
testNumbers ()
|
||||
{
|
||||
testFloatToUint (0x00000000, 0); // 0.0
|
||||
testFloatToUint (0x3f000000, 0); // +0.5
|
||||
testFloatToUint (0xbf000000, 0); // -0.5
|
||||
testFloatToUint (0x42f82000, 124); // +124.0625
|
||||
testFloatToUint (0xc2f82000, 0); // -124.0625
|
||||
testFloatToUint (0x58635fa9, 0xffffffff); // +1.0e15
|
||||
testFloatToUint (0xd8635fa9, 0); // -1.0e15
|
||||
testFloatToUint (0x7f800000, 0xffffffff); // +infinity
|
||||
testFloatToUint (0xff800000, 0); // -infinity
|
||||
testFloatToUint (0x7fffffff, 0); // NaN
|
||||
testFloatToUint (0xffffffff, 0); // NaN
|
||||
|
||||
testHalfToUint (0x0000, 0); // 0.0
|
||||
testHalfToUint (0x3800, 0); // +0.5
|
||||
testHalfToUint (0xb800, 0); // -0.5
|
||||
testHalfToUint (0x57c1, 124); // +124.0625
|
||||
testHalfToUint (0xd7c1, 0); // -124.0625
|
||||
testHalfToUint (0x7c00, 0xffffffff); // +infinity
|
||||
testHalfToUint (0xfc00, 0); // -infinity
|
||||
testHalfToUint (0x7fff, 0); // NaN
|
||||
testHalfToUint (0xffff, 0); // NaN
|
||||
|
||||
testFloatToHalf (0x00000000, 0x0000); // 0.0
|
||||
testFloatToHalf (0x3f000000, 0x3800); // +0.5
|
||||
testFloatToHalf (0xbf000000, 0xb800); // -0.5
|
||||
testFloatToHalf (0x42f82000, 0x57c1); // +124.0625
|
||||
testFloatToHalf (0xc2f82000, 0xd7c1); // -124.0625
|
||||
testFloatToHalf (0x58635fa9, 0x7c00); // +1.0e15
|
||||
testFloatToHalf (0xd8635fa9, 0xfc00); // -1.0e15
|
||||
testFloatToHalf (0x7f800000, 0x7c00); // +infinity
|
||||
testFloatToHalf (0xff800000, 0xfc00); // -infinity
|
||||
testFloatToHalf (0x7fffffff, 0x7fff); // NaN
|
||||
testFloatToHalf (0xffffffff, 0xffff); // NaN
|
||||
|
||||
testUintToHalf (0, 0x0000);
|
||||
testUintToHalf (1, 0x3c00);
|
||||
testUintToHalf (124, 0x57c0);
|
||||
testUintToHalf (1000000, 0x7c00);
|
||||
testUintToHalf (0xffffffff, 0x7c00);
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
bool
|
||||
isEquivalent (T t1, T t2, Compression compression)
|
||||
{
|
||||
return t1 == t2;
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
bool
|
||||
isEquivalent (float t1, float t2, Compression compression)
|
||||
{
|
||||
return equivalent (t1, t2, compression);
|
||||
}
|
||||
|
||||
|
||||
template <class OutType, PixelType OutTypeTag,
|
||||
class InType, PixelType InTypeTag>
|
||||
void
|
||||
testScanLineImageChannel (const char fileName[],
|
||||
int width, int height,
|
||||
Compression compression)
|
||||
{
|
||||
cout << "scan lines, "
|
||||
"compression " << compression << ", " <<
|
||||
"output type " << OutTypeTag << ", " <<
|
||||
"input type " << InTypeTag << ":\n " << flush;
|
||||
|
||||
Array2D<OutType> outPixels (height, width);
|
||||
|
||||
for (int y = 0; y < height; ++y)
|
||||
for (int x = 0; x < width; ++x)
|
||||
outPixels[y][x] = x * 10 + y;
|
||||
|
||||
{
|
||||
Header hdr (width, height);
|
||||
|
||||
hdr.compression() = compression;
|
||||
|
||||
hdr.channels().insert ("X", // name
|
||||
Channel (OutTypeTag)); // type
|
||||
|
||||
FrameBuffer fb;
|
||||
|
||||
fb.insert ("X", // name
|
||||
Slice (OutTypeTag, // type
|
||||
(char *) &outPixels[0][0], // base
|
||||
sizeof (outPixels[0][0]), // xStride
|
||||
sizeof (outPixels[0][0]) * width)); // yStride
|
||||
|
||||
cout << "writing " << flush;
|
||||
|
||||
OutputFile out (fileName, hdr);
|
||||
out.setFrameBuffer (fb);
|
||||
out.writePixels (height);
|
||||
}
|
||||
|
||||
Array2D<InType> inPixels (height, width);
|
||||
|
||||
{
|
||||
cout << "reading " << flush;
|
||||
|
||||
FrameBuffer fb;
|
||||
|
||||
fb.insert ("X", // name
|
||||
Slice (InTypeTag, // type
|
||||
(char *) &inPixels[0][0], // base
|
||||
sizeof (inPixels[0][0]), // xStride
|
||||
sizeof (inPixels[0][0]) * width)); // yStride
|
||||
|
||||
InputFile in (fileName);
|
||||
in.setFrameBuffer (fb);
|
||||
in.readPixels (0, height - 1);
|
||||
}
|
||||
|
||||
cout << "comparing" << flush;
|
||||
|
||||
for (int y = 0; y < height; ++y)
|
||||
{
|
||||
for (int x = 0; x < width; ++x)
|
||||
{
|
||||
assert (isEquivalent (inPixels[y][x],
|
||||
InType (outPixels[y][x]),
|
||||
compression));
|
||||
}
|
||||
}
|
||||
|
||||
cout << endl;
|
||||
|
||||
remove (fileName);
|
||||
}
|
||||
|
||||
|
||||
template <class OutType, PixelType OutTypeTag,
|
||||
class InType, PixelType InTypeTag>
|
||||
void
|
||||
testTiledImageChannel (const char fileName[],
|
||||
int width, int height,
|
||||
Compression compression)
|
||||
{
|
||||
cout << "tiles, "
|
||||
"compression " << compression << ", " <<
|
||||
"output type " << OutTypeTag << ", " <<
|
||||
"input type " << InTypeTag << ":\n " << flush;
|
||||
|
||||
Array2D<OutType> outPixels (height, width);
|
||||
|
||||
for (int y = 0; y < height; ++y)
|
||||
for (int x = 0; x < width; ++x)
|
||||
outPixels[y][x] = x * 10 + y;
|
||||
|
||||
{
|
||||
Header hdr (width, height);
|
||||
|
||||
hdr.setTileDescription (TileDescription (67, 67, ONE_LEVEL));
|
||||
|
||||
hdr.compression() = compression;
|
||||
|
||||
hdr.channels().insert ("X", // name
|
||||
Channel (OutTypeTag)); // type
|
||||
|
||||
FrameBuffer fb;
|
||||
|
||||
fb.insert ("X", // name
|
||||
Slice (OutTypeTag, // type
|
||||
(char *) &outPixels[0][0], // base
|
||||
sizeof (outPixels[0][0]), // xStride
|
||||
sizeof (outPixels[0][0]) * width)); // yStride
|
||||
|
||||
cout << "writing " << flush;
|
||||
|
||||
TiledOutputFile out (fileName, hdr);
|
||||
out.setFrameBuffer (fb);
|
||||
out.writeTiles (0, out.numXTiles() - 1, 0, out.numYTiles() - 1);
|
||||
}
|
||||
|
||||
Array2D<InType> inPixels (height, width);
|
||||
|
||||
{
|
||||
cout << "reading " << flush;
|
||||
|
||||
FrameBuffer fb;
|
||||
|
||||
fb.insert ("X", // name
|
||||
Slice (InTypeTag, // type
|
||||
(char *) &inPixels[0][0], // base
|
||||
sizeof (inPixels[0][0]), // xStride
|
||||
sizeof (inPixels[0][0]) * width)); // yStride
|
||||
|
||||
TiledInputFile in (fileName);
|
||||
in.setFrameBuffer (fb);
|
||||
in.readTiles (0, in.numXTiles() - 1, 0, in.numYTiles() - 1);
|
||||
}
|
||||
|
||||
cout << "comparing" << flush;
|
||||
|
||||
for (int y = 0; y < height; ++y)
|
||||
{
|
||||
for (int x = 0; x < width; ++x)
|
||||
{
|
||||
assert (isEquivalent (inPixels[y][x],
|
||||
InType (outPixels[y][x]),
|
||||
compression));
|
||||
}
|
||||
}
|
||||
|
||||
cout << endl;
|
||||
|
||||
remove (fileName);
|
||||
}
|
||||
|
||||
|
||||
template <class OutType, PixelType OutTypeTag,
|
||||
class InType, PixelType InTypeTag>
|
||||
void
|
||||
testImageChannel (const std::string &fileName,
|
||||
int width, int height,
|
||||
Compression compression)
|
||||
{
|
||||
testScanLineImageChannel <OutType, OutTypeTag, InType, InTypeTag>
|
||||
(fileName.c_str(), width, height, compression);
|
||||
|
||||
testTiledImageChannel <OutType, OutTypeTag, InType, InTypeTag>
|
||||
(fileName.c_str(), width, height, compression);
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
void
|
||||
testConversion (const std::string &tempDir)
|
||||
{
|
||||
try
|
||||
{
|
||||
cout << "Testing conversion between pixel data types" << endl;
|
||||
|
||||
cout << "individual numbers" << endl;
|
||||
|
||||
testNumbers();
|
||||
|
||||
cout << "conversion of image channels while reading a file " << endl;
|
||||
|
||||
for (int comp = 0; comp < NUM_COMPRESSION_METHODS; ++comp)
|
||||
{
|
||||
if (comp == B44_COMPRESSION ||
|
||||
comp == B44A_COMPRESSION)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
testImageChannel <unsigned int, IMF::UINT, unsigned int, IMF::UINT>
|
||||
(tempDir + "imf_test_conv.exr",
|
||||
317, 539,
|
||||
Compression (comp));
|
||||
|
||||
testImageChannel <unsigned int, IMF::UINT, half, IMF::HALF>
|
||||
(tempDir + "imf_test_conv.exr",
|
||||
317, 539,
|
||||
Compression (comp));
|
||||
|
||||
testImageChannel <unsigned int, IMF::UINT, float, IMF::FLOAT>
|
||||
(tempDir + "imf_test_conv.exr",
|
||||
317, 539,
|
||||
Compression (comp));
|
||||
|
||||
testImageChannel <half, IMF::HALF, unsigned int, IMF::UINT>
|
||||
(tempDir + "imf_test_conv.exr",
|
||||
317, 539,
|
||||
Compression (comp));
|
||||
|
||||
testImageChannel <half, IMF::HALF, half, IMF::HALF>
|
||||
(tempDir + "imf_test_conv.exr",
|
||||
317, 539,
|
||||
Compression (comp));
|
||||
|
||||
testImageChannel <half, IMF::HALF, float, IMF::FLOAT>
|
||||
(tempDir + "imf_test_conv.exr",
|
||||
317, 539,
|
||||
Compression (comp));
|
||||
|
||||
testImageChannel <float, IMF::FLOAT, unsigned int, IMF::UINT>
|
||||
(tempDir + "imf_test_conv.exr",
|
||||
317, 539,
|
||||
Compression (comp));
|
||||
|
||||
testImageChannel <float, IMF::FLOAT, half, IMF::HALF>
|
||||
(tempDir + "imf_test_conv.exr",
|
||||
317, 539,
|
||||
Compression (comp));
|
||||
|
||||
testImageChannel <float, IMF::FLOAT, float, IMF::FLOAT>
|
||||
(tempDir + "imf_test_conv.exr",
|
||||
317, 539,
|
||||
Compression (comp));
|
||||
|
||||
}
|
||||
cout << "ok\n" << endl;
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
cerr << "ERROR -- caught exception: " << e.what() << endl;
|
||||
assert (false);
|
||||
}
|
||||
}
|
||||
40
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testConversion.h
Normal file
40
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testConversion.h
Normal file
@@ -0,0 +1,40 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2003-2012, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include <string>
|
||||
|
||||
void testConversion (const std::string &tempDir);
|
||||
|
||||
|
||||
@@ -0,0 +1,441 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// Portions (c) 2012, Weta Digital Ltd
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "testCopyDeepScanLine.h"
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <ImfDeepScanLineInputFile.h>
|
||||
#include <ImfDeepScanLineOutputFile.h>
|
||||
#include <ImfPartType.h>
|
||||
#include <ImfChannelList.h>
|
||||
#include <ImfDeepFrameBuffer.h>
|
||||
#include <ImfArray.h>
|
||||
#include <IlmThreadPool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <vector>
|
||||
|
||||
#include "tmpDir.h"
|
||||
|
||||
namespace IMF = OPENEXR_IMF_NAMESPACE;
|
||||
using namespace IMF;
|
||||
using namespace std;
|
||||
using namespace IMATH_NAMESPACE;
|
||||
using namespace ILMTHREAD_NAMESPACE;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
const int width = 538;
|
||||
const int height = 234;
|
||||
const int minX = 42;
|
||||
const int minY = 51;
|
||||
const Box2i dataWindow(V2i(minX, minY), V2i(minX + width - 1, minY + height - 1));
|
||||
const Box2i displayWindow(V2i(0, 0), V2i(minX + width * 2, minY + height * 2));
|
||||
const char source_filename[] = IMF_TMP_DIR "imf_test_copy_deep_scanline_source.exr";
|
||||
const char copy_filename[] = IMF_TMP_DIR "imf_test_copy_deep_scanline_copy.exr";
|
||||
|
||||
vector<int> channelTypes;
|
||||
Array2D<unsigned int> sampleCount;
|
||||
Header header;
|
||||
|
||||
void generateRandomFile (const std::string & source_filename,
|
||||
int channelCount,
|
||||
Compression compression)
|
||||
{
|
||||
cout << "generating " << flush;
|
||||
header = Header(displayWindow, dataWindow,
|
||||
1,
|
||||
IMATH_NAMESPACE::V2f (0, 0),
|
||||
1,
|
||||
INCREASING_Y,
|
||||
compression);
|
||||
|
||||
cout << "compression " << compression << " " << flush;
|
||||
|
||||
//
|
||||
// Add channels.
|
||||
//
|
||||
|
||||
channelTypes.clear();
|
||||
|
||||
for (int i = 0; i < channelCount; i++)
|
||||
{
|
||||
int type = rand() % 3;
|
||||
stringstream ss;
|
||||
ss << i;
|
||||
string str = ss.str();
|
||||
if (type == 0)
|
||||
header.channels().insert(str, Channel(IMF::UINT));
|
||||
if (type == 1)
|
||||
header.channels().insert(str, Channel(IMF::HALF));
|
||||
if (type == 2)
|
||||
header.channels().insert(str, Channel(IMF::FLOAT));
|
||||
channelTypes.push_back(type);
|
||||
}
|
||||
|
||||
header.setType(DEEPSCANLINE);
|
||||
|
||||
Array<Array2D< void* > > data(channelCount);
|
||||
for (int i = 0; i < channelCount; i++)
|
||||
data[i].resizeErase(height, width);
|
||||
|
||||
sampleCount.resizeErase(height, width);
|
||||
|
||||
remove (source_filename.c_str());
|
||||
DeepScanLineOutputFile file(source_filename.c_str(), header, 8);
|
||||
|
||||
DeepFrameBuffer frameBuffer;
|
||||
|
||||
frameBuffer.insertSampleCountSlice (Slice (IMF::UINT, // type // 7
|
||||
(char *) (&sampleCount[0][0]
|
||||
- dataWindow.min.x
|
||||
- dataWindow.min.y * width), // base // 8
|
||||
sizeof (unsigned int) * 1, // xStride// 9
|
||||
sizeof (unsigned int) * width)); // yStride// 10
|
||||
|
||||
for (int i = 0; i < channelCount; i++)
|
||||
{
|
||||
PixelType type;
|
||||
if (channelTypes[i] == 0)
|
||||
type = IMF::UINT;
|
||||
if (channelTypes[i] == 1)
|
||||
type = IMF::HALF;
|
||||
if (channelTypes[i] == 2)
|
||||
type = IMF::FLOAT;
|
||||
|
||||
stringstream ss;
|
||||
ss << i;
|
||||
string str = ss.str();
|
||||
|
||||
int sampleSize;
|
||||
if (channelTypes[i] == 0) sampleSize = sizeof (unsigned int);
|
||||
if (channelTypes[i] == 1) sampleSize = sizeof (half);
|
||||
if (channelTypes[i] == 2) sampleSize = sizeof (float);
|
||||
|
||||
int pointerSize = sizeof(char *);
|
||||
|
||||
frameBuffer.insert (str, // name // 6
|
||||
DeepSlice (type, // type // 7
|
||||
(char *) (&data[i][0][0]
|
||||
- dataWindow.min.x
|
||||
- dataWindow.min.y * width), // base // 8
|
||||
pointerSize * 1, // xStride// 9
|
||||
pointerSize * width, // yStride// 10
|
||||
sampleSize)); // sampleStride
|
||||
}
|
||||
|
||||
file.setFrameBuffer(frameBuffer);
|
||||
|
||||
cout << "writing " << flush;
|
||||
for (int i = 0; i < height; i++)
|
||||
{
|
||||
//
|
||||
// Fill in data at the last minute.
|
||||
//
|
||||
|
||||
for (int j = 0; j < width; j++)
|
||||
{
|
||||
sampleCount[i][j] = rand() % 10 + 1;
|
||||
for (int k = 0; k < channelCount; k++)
|
||||
{
|
||||
if (channelTypes[k] == 0)
|
||||
data[k][i][j] = new unsigned int[sampleCount[i][j]];
|
||||
if (channelTypes[k] == 1)
|
||||
data[k][i][j] = new half[sampleCount[i][j]];
|
||||
if (channelTypes[k] == 2)
|
||||
data[k][i][j] = new float[sampleCount[i][j]];
|
||||
for (int l = 0; l < sampleCount[i][j]; l++)
|
||||
{
|
||||
if (channelTypes[k] == 0)
|
||||
((unsigned int*)data[k][i][j])[l] = (i * width + j) % 2049;
|
||||
if (channelTypes[k] == 1)
|
||||
((half*)data[k][i][j])[l] = (i * width + j) % 2049;
|
||||
if (channelTypes[k] == 2)
|
||||
((float*)data[k][i][j])[l] = (i * width + j) % 2049;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
file.writePixels(height);
|
||||
|
||||
|
||||
for (int i = 0; i < height; i++)
|
||||
for (int j = 0; j < width; j++)
|
||||
for (int k = 0; k < channelCount; k++)
|
||||
{
|
||||
if (channelTypes[k] == 0)
|
||||
delete[] (unsigned int*) data[k][i][j];
|
||||
if (channelTypes[k] == 1)
|
||||
delete[] (half*) data[k][i][j];
|
||||
if (channelTypes[k] == 2)
|
||||
delete[] (float*) data[k][i][j];
|
||||
}
|
||||
}
|
||||
|
||||
void copyFile (const std::string & source_filename,
|
||||
const std::string & copy_filename)
|
||||
{
|
||||
cout << "copying " ;
|
||||
cout.flush();
|
||||
{
|
||||
DeepScanLineInputFile in_file(source_filename.c_str(), 8);
|
||||
remove (copy_filename.c_str());
|
||||
DeepScanLineOutputFile out_file (copy_filename.c_str(),
|
||||
in_file.header(),
|
||||
8);
|
||||
out_file.copyPixels(in_file);
|
||||
}
|
||||
// remove the source file here to prevent accidentally reading it
|
||||
// remove (source_filename);
|
||||
|
||||
}
|
||||
|
||||
void readFile (const std::string & copy_filename, int channelCount)
|
||||
{
|
||||
cout << "reading " ;
|
||||
cout.flush();
|
||||
DeepScanLineInputFile file(copy_filename.c_str(), 8);
|
||||
|
||||
const Header& fileHeader = file.header();
|
||||
assert (fileHeader.displayWindow() == header.displayWindow());
|
||||
assert (fileHeader.dataWindow() == header.dataWindow());
|
||||
assert (fileHeader.pixelAspectRatio() == header.pixelAspectRatio());
|
||||
assert (fileHeader.screenWindowCenter() == header.screenWindowCenter());
|
||||
assert (fileHeader.screenWindowWidth() == header.screenWindowWidth());
|
||||
assert (fileHeader.lineOrder() == header.lineOrder());
|
||||
assert (fileHeader.compression() == header.compression());
|
||||
assert (fileHeader.channels() == header.channels());
|
||||
assert (fileHeader.type() == header.type());
|
||||
|
||||
Array2D<unsigned int> localSampleCount;
|
||||
localSampleCount.resizeErase(height, width);
|
||||
Array<Array2D< void* > > data(channelCount);
|
||||
for (int i = 0; i < channelCount; i++)
|
||||
data[i].resizeErase(height, width);
|
||||
|
||||
DeepFrameBuffer frameBuffer;
|
||||
|
||||
frameBuffer.insertSampleCountSlice (Slice (IMF::UINT, // type // 7
|
||||
(char *) (&localSampleCount[0][0]
|
||||
- dataWindow.min.x
|
||||
- dataWindow.min.y * width), // base // 8)
|
||||
sizeof (unsigned int) * 1, // xStride// 9
|
||||
sizeof (unsigned int) * width)); // yStride// 10
|
||||
|
||||
|
||||
|
||||
|
||||
for (int i = 0; i < channelCount; i++)
|
||||
{
|
||||
PixelType type;
|
||||
if (channelTypes[i] == 0)
|
||||
type = IMF::UINT;
|
||||
if (channelTypes[i] == 1)
|
||||
type = IMF::HALF;
|
||||
if (channelTypes[i] == 2)
|
||||
type = IMF::FLOAT;
|
||||
|
||||
stringstream ss;
|
||||
ss << i;
|
||||
string str = ss.str();
|
||||
|
||||
int sampleSize;
|
||||
if (channelTypes[i] == 0) sampleSize = sizeof (unsigned int);
|
||||
if (channelTypes[i] == 1) sampleSize = sizeof (half);
|
||||
if (channelTypes[i] == 2) sampleSize = sizeof (float);
|
||||
|
||||
int pointerSize = sizeof (char *);
|
||||
|
||||
frameBuffer.insert (str, // name // 6
|
||||
DeepSlice (type, // type // 7
|
||||
(char *) (&data[i][0][0]
|
||||
- dataWindow.min.x
|
||||
- dataWindow.min.y * width), // base // 8)
|
||||
pointerSize * 1, // xStride// 9
|
||||
pointerSize * width, // yStride// 10
|
||||
sampleSize)); // sampleStride
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
file.setFrameBuffer(frameBuffer);
|
||||
|
||||
file.readPixelSampleCounts(dataWindow.min.y, dataWindow.max.y);
|
||||
for (int i = 0; i < dataWindow.max.y - dataWindow.min.y + 1; i++)
|
||||
{
|
||||
int y = i + dataWindow.min.y;
|
||||
|
||||
for (int j = 0; j < width; j++)
|
||||
assert(localSampleCount[i][j] == sampleCount[i][j]);
|
||||
|
||||
for (int j = 0; j < width; j++)
|
||||
{
|
||||
for (int k = 0; k < channelCount; k++)
|
||||
{
|
||||
if (channelTypes[k] == 0)
|
||||
data[k][i][j] = new unsigned int[localSampleCount[i][j]];
|
||||
if (channelTypes[k] == 1)
|
||||
data[k][i][j] = new half[localSampleCount[i][j]];
|
||||
if (channelTypes[k] == 2)
|
||||
data[k][i][j] = new float[localSampleCount[i][j]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
file.readPixels(dataWindow.min.y, dataWindow.max.y);
|
||||
|
||||
|
||||
for (int i = 0; i < height; i++)
|
||||
for (int j = 0; j < width; j++)
|
||||
for (int k = 0; k < channelCount; k++)
|
||||
{
|
||||
for (int l = 0; l < sampleCount[i][j]; l++)
|
||||
{
|
||||
if (channelTypes[k] == 0)
|
||||
{
|
||||
unsigned int* value = (unsigned int*)(data[k][i][j]);
|
||||
if (value[l] != (i * width + j) % 2049)
|
||||
cout << j << ", " << i << " error, should be "
|
||||
<< (i * width + j) % 2049 << ", is " << value[l]
|
||||
<< endl << flush;
|
||||
assert (value[l] == (i * width + j) % 2049);
|
||||
}
|
||||
if (channelTypes[k] == 1)
|
||||
{
|
||||
half* value = (half*)(data[k][i][j]);
|
||||
if (value[l] != (i * width + j) % 2049)
|
||||
cout << j << ", " << i << " error, should be "
|
||||
<< (i * width + j) % 2049 << ", is " << value[l]
|
||||
<< endl << flush;
|
||||
assert (((half*)(data[k][i][j]))[l] == (i * width + j) % 2049);
|
||||
}
|
||||
if (channelTypes[k] == 2)
|
||||
{
|
||||
float* value = (float*)(data[k][i][j]);
|
||||
if (value[l] != (i * width + j) % 2049)
|
||||
cout << j << ", " << i << " error, should be "
|
||||
<< (i * width + j) % 2049 << ", is " << value[l]
|
||||
<< endl << flush;
|
||||
assert (((float*)(data[k][i][j]))[l] == (i * width + j) % 2049);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < height; i++)
|
||||
for (int j = 0; j < width; j++)
|
||||
for (int k = 0; k < channelCount; k++)
|
||||
{
|
||||
if (channelTypes[k] == 0)
|
||||
delete[] (unsigned int*) data[k][i][j];
|
||||
if (channelTypes[k] == 1)
|
||||
delete[] (half*) data[k][i][j];
|
||||
if (channelTypes[k] == 2)
|
||||
delete[] (float*) data[k][i][j];
|
||||
}
|
||||
}
|
||||
|
||||
void readCopyWriteTest (const std::string & tempDir,
|
||||
int channelCount,
|
||||
int testTimes)
|
||||
{
|
||||
cout << "Testing files with " << channelCount << " channels " << testTimes << " times."
|
||||
<< endl << flush;
|
||||
|
||||
std::string source_filename = tempDir + "imf_test_copy_deep_scanline_source.exr";
|
||||
std::string copy_filename = tempDir + "imf_test_copy_deep_scanline_copy.exr";
|
||||
|
||||
for (int i = 0; i < testTimes; i++)
|
||||
{
|
||||
int compressionIndex = i % 3;
|
||||
Compression compression;
|
||||
switch (compressionIndex)
|
||||
{
|
||||
case 0:
|
||||
compression = NO_COMPRESSION;
|
||||
break;
|
||||
case 1:
|
||||
compression = RLE_COMPRESSION;
|
||||
break;
|
||||
case 2:
|
||||
compression = ZIPS_COMPRESSION;
|
||||
break;
|
||||
}
|
||||
|
||||
generateRandomFile (source_filename, channelCount, compression);
|
||||
copyFile (source_filename, copy_filename);
|
||||
readFile (copy_filename, channelCount );
|
||||
remove (source_filename.c_str());
|
||||
remove (copy_filename.c_str());
|
||||
cout << endl << flush;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}; // namespace
|
||||
|
||||
void testCopyDeepScanLine (const std::string &tempDir)
|
||||
{
|
||||
try
|
||||
{
|
||||
cout << "\n\nTesting raw data copy in DeepScanLineInput/OutputFile:\n" << endl;
|
||||
|
||||
srand(1);
|
||||
|
||||
int numThreads = ThreadPool::globalThreadPool().numThreads();
|
||||
ThreadPool::globalThreadPool().setNumThreads(4);
|
||||
|
||||
|
||||
readCopyWriteTest (tempDir, 1, 100);
|
||||
readCopyWriteTest (tempDir, 3, 50);
|
||||
readCopyWriteTest (tempDir, 10, 10);
|
||||
|
||||
ThreadPool::globalThreadPool().setNumThreads(numThreads);
|
||||
|
||||
cout << "ok\n" << endl;
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
cerr << "ERROR -- caught exception: " << e.what() << endl;
|
||||
assert (false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// Portions (c) 2012, Weta Digital Ltd
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef TESTCOPYDEEPSCANLINE_H_
|
||||
#define TESTCOPYDEEPSCANLINE_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
void testCopyDeepScanLine (const std::string &tempDir);
|
||||
|
||||
#endif /* TESTCOPYDEEPSCANLINE_H_ */
|
||||
519
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testCopyDeepTiled.cpp
Normal file
519
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testCopyDeepTiled.cpp
Normal file
@@ -0,0 +1,519 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "testCopyDeepTiled.h"
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <ImfDeepTiledInputFile.h>
|
||||
#include <ImfDeepTiledOutputFile.h>
|
||||
#include <ImfChannelList.h>
|
||||
#include <ImfArray.h>
|
||||
#include <ImfPartType.h>
|
||||
#include <ImfNamespace.h>
|
||||
#include <IlmThreadPool.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <vector>
|
||||
|
||||
#include "tmpDir.h"
|
||||
|
||||
namespace IMF = OPENEXR_IMF_NAMESPACE;
|
||||
using namespace IMF;
|
||||
using namespace IMATH_NAMESPACE;
|
||||
using namespace ILMTHREAD_NAMESPACE;
|
||||
using namespace std;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
const int width = 199;
|
||||
const int height = 369;
|
||||
const int minX = 23;
|
||||
const int minY = 59;
|
||||
const Box2i dataWindow(V2i(minX, minY), V2i(minX + width - 1, minY + height - 1));
|
||||
const Box2i displayWindow(V2i(0, 0), V2i(minX + width * 2, minY + height * 2));
|
||||
|
||||
|
||||
vector<int> channelTypes;
|
||||
Array2D< Array2D<unsigned int> > sampleCountWhole;
|
||||
Header header;
|
||||
|
||||
void
|
||||
generateRandomFile (int channelCount,
|
||||
Compression compression,
|
||||
const std::string & srcFn)
|
||||
{
|
||||
|
||||
cout << "generating " << flush;
|
||||
header = Header(displayWindow, dataWindow,
|
||||
1,
|
||||
IMATH_NAMESPACE::V2f (0, 0),
|
||||
1,
|
||||
INCREASING_Y,
|
||||
compression);
|
||||
cout << "compression " << compression << " " << flush;
|
||||
|
||||
//
|
||||
// Add channels.
|
||||
//
|
||||
|
||||
channelTypes.clear();
|
||||
|
||||
for (int i = 0; i < channelCount; i++)
|
||||
{
|
||||
int type = rand() % 3;
|
||||
stringstream ss;
|
||||
ss << i;
|
||||
string str = ss.str();
|
||||
if (type == 0)
|
||||
header.channels().insert(str, Channel(IMF::UINT));
|
||||
if (type == 1)
|
||||
header.channels().insert(str, Channel(IMF::HALF));
|
||||
if (type == 2)
|
||||
header.channels().insert(str, Channel(IMF::FLOAT));
|
||||
channelTypes.push_back(type);
|
||||
}
|
||||
|
||||
header.setType(DEEPTILE);
|
||||
header.setTileDescription(
|
||||
TileDescription(rand() % width + 1, rand() % height + 1, RIPMAP_LEVELS));
|
||||
|
||||
Array<Array2D< void* > > data(channelCount);
|
||||
for (int i = 0; i < channelCount; i++)
|
||||
data[i].resizeErase(height, width);
|
||||
|
||||
Array2D<unsigned int> sampleCount;
|
||||
sampleCount.resizeErase(height, width);
|
||||
|
||||
remove (srcFn.c_str());
|
||||
DeepTiledOutputFile file(srcFn.c_str(), header, 8);
|
||||
|
||||
cout << "tileSizeX " << file.tileXSize() << " tileSizeY " << file.tileYSize() << " ";
|
||||
|
||||
sampleCountWhole.resizeErase(file.numYLevels(), file.numXLevels());
|
||||
for (int i = 0; i < sampleCountWhole.height(); i++)
|
||||
for (int j = 0; j < sampleCountWhole.width(); j++)
|
||||
sampleCountWhole[i][j].resizeErase(height, width);
|
||||
|
||||
DeepFrameBuffer frameBuffer;
|
||||
|
||||
int memOffset = dataWindow.min.x + dataWindow.min.y * width;
|
||||
|
||||
frameBuffer.insertSampleCountSlice (Slice (IMF::UINT,
|
||||
(char *) (&sampleCount[0][0] - memOffset),
|
||||
sizeof (unsigned int) * 1,
|
||||
sizeof (unsigned int) * width,
|
||||
1, 1,
|
||||
0,
|
||||
false,
|
||||
false));
|
||||
|
||||
for (int i = 0; i < channelCount; i++)
|
||||
{
|
||||
PixelType type;
|
||||
if (channelTypes[i] == 0)
|
||||
type = IMF::UINT;
|
||||
if (channelTypes[i] == 1)
|
||||
type = IMF::HALF;
|
||||
if (channelTypes[i] == 2)
|
||||
type = IMF::FLOAT;
|
||||
|
||||
stringstream ss;
|
||||
ss << i;
|
||||
string str = ss.str();
|
||||
|
||||
int sampleSize;
|
||||
if (channelTypes[i] == 0) sampleSize = sizeof (unsigned int);
|
||||
if (channelTypes[i] == 1) sampleSize = sizeof (half);
|
||||
if (channelTypes[i] == 2) sampleSize = sizeof (float);
|
||||
|
||||
int pointerSize = sizeof (char *);
|
||||
|
||||
frameBuffer.insert (str,
|
||||
DeepSlice (type,
|
||||
(char *) (&data[i][0][0] - memOffset),
|
||||
pointerSize * 1,
|
||||
pointerSize * width,
|
||||
sampleSize,
|
||||
1, 1,
|
||||
0,
|
||||
false,
|
||||
false));
|
||||
}
|
||||
|
||||
file.setFrameBuffer(frameBuffer);
|
||||
|
||||
cout << "writing " << flush;
|
||||
|
||||
for (int ly = 0; ly < file.numYLevels(); ly++)
|
||||
for (int lx = 0; lx < file.numXLevels(); lx++)
|
||||
{
|
||||
Box2i dataWindowL = file.dataWindowForLevel(lx, ly);
|
||||
|
||||
//
|
||||
// Bulk write (without relative coordinates).
|
||||
//
|
||||
|
||||
for (int j = 0; j < file.numYTiles(ly); j++)
|
||||
{
|
||||
for (int i = 0; i < file.numXTiles(lx); i++)
|
||||
{
|
||||
Box2i box = file.dataWindowForTile(i, j, lx, ly);
|
||||
for (int y = box.min.y; y <= box.max.y; y++)
|
||||
for (int x = box.min.x; x <= box.max.x; x++)
|
||||
{
|
||||
int dwy = y - dataWindowL.min.y;
|
||||
int dwx = x - dataWindowL.min.x;
|
||||
sampleCount[dwy][dwx] = rand() % 10 + 1;
|
||||
sampleCountWhole[ly][lx][dwy][dwx] = sampleCount[dwy][dwx];
|
||||
for (int k = 0; k < channelCount; k++)
|
||||
{
|
||||
if (channelTypes[k] == 0)
|
||||
data[k][dwy][dwx] = new unsigned int[sampleCount[dwy][dwx]];
|
||||
if (channelTypes[k] == 1)
|
||||
data[k][dwy][dwx] = new half[sampleCount[dwy][dwx]];
|
||||
if (channelTypes[k] == 2)
|
||||
data[k][dwy][dwx] = new float[sampleCount[dwy][dwx]];
|
||||
for (int l = 0; l < sampleCount[dwy][dwx]; l++)
|
||||
{
|
||||
if (channelTypes[k] == 0)
|
||||
((unsigned int*)data[k][dwy][dwx])[l] = (dwy * width + dwx) % 2049;
|
||||
if (channelTypes[k] == 1)
|
||||
((half*)data[k][dwy][dwx])[l] = (dwy* width + dwx) % 2049;
|
||||
if (channelTypes[k] == 2)
|
||||
((float*)data[k][dwy][dwx])[l] = (dwy * width + dwx) % 2049;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
file.writeTiles(0, file.numXTiles(lx) - 1, 0, file.numYTiles(ly) - 1, lx, ly);
|
||||
|
||||
|
||||
for (int i = 0; i < file.levelHeight(ly); i++)
|
||||
for (int j = 0; j < file.levelWidth(lx); j++)
|
||||
for (int k = 0; k < channelCount; k++)
|
||||
{
|
||||
if (channelTypes[k] == 0)
|
||||
delete[] (unsigned int*) data[k][i][j];
|
||||
if (channelTypes[k] == 1)
|
||||
delete[] (half*) data[k][i][j];
|
||||
if (channelTypes[k] == 2)
|
||||
delete[] (float*) data[k][i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
checkValue (void* sampleRawData, int sampleCount, int channelType, int dwx, int dwy)
|
||||
{
|
||||
for (int l = 0; l < sampleCount; l++)
|
||||
{
|
||||
if (channelType == 0)
|
||||
{
|
||||
unsigned int* value = (unsigned int*)(sampleRawData);
|
||||
if (value[l] != (dwy * width + dwx) % 2049)
|
||||
cout << dwx << ", " << dwy << " error, should be "
|
||||
<< (dwy * width + dwx) % 2049 << ", is " << value[l]
|
||||
<< endl << flush;
|
||||
assert (value[l] == (dwy * width + dwx) % 2049);
|
||||
}
|
||||
if (channelType == 1)
|
||||
{
|
||||
half* value = (half*)(sampleRawData);
|
||||
if (value[l] != (dwy * width + dwx) % 2049)
|
||||
cout << dwx << ", " << dwy << " error, should be "
|
||||
<< (dwy * width + dwx) % 2049 << ", is " << value[l]
|
||||
<< endl << flush;
|
||||
assert (value[l] == (dwy * width + dwx) % 2049);
|
||||
}
|
||||
if (channelType == 2)
|
||||
{
|
||||
float* value = (float*)(sampleRawData);
|
||||
if (value[l] != (dwy * width + dwx) % 2049)
|
||||
cout << dwx << ", " << dwy << " error, should be "
|
||||
<< (dwy * width + dwx) % 2049 << ", is " << value[l]
|
||||
<< endl << flush;
|
||||
assert (value[l] == (dwy * width + dwx) % 2049);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
readFile (int channelCount, const std::string & cpyFn)
|
||||
{
|
||||
|
||||
cout << "reading " << flush;
|
||||
|
||||
DeepTiledInputFile file (cpyFn.c_str(), 4);
|
||||
|
||||
const Header& fileHeader = file.header();
|
||||
assert (fileHeader.displayWindow() == header.displayWindow());
|
||||
assert (fileHeader.dataWindow() == header.dataWindow());
|
||||
assert (fileHeader.pixelAspectRatio() == header.pixelAspectRatio());
|
||||
assert (fileHeader.screenWindowCenter() == header.screenWindowCenter());
|
||||
assert (fileHeader.screenWindowWidth() == header.screenWindowWidth());
|
||||
assert (fileHeader.lineOrder() == header.lineOrder());
|
||||
assert (fileHeader.compression() == header.compression());
|
||||
assert (fileHeader.channels() == header.channels());
|
||||
assert (fileHeader.type() == header.type());
|
||||
assert (fileHeader.tileDescription() == header.tileDescription());
|
||||
|
||||
Array2D<unsigned int> localSampleCount;
|
||||
localSampleCount.resizeErase(height, width);
|
||||
Array<Array2D< void* > > data(channelCount);
|
||||
for (int i = 0; i < channelCount; i++)
|
||||
data[i].resizeErase(height, width);
|
||||
|
||||
DeepFrameBuffer frameBuffer;
|
||||
|
||||
int memOffset = dataWindow.min.x + dataWindow.min.y * width;
|
||||
frameBuffer.insertSampleCountSlice (Slice (IMF::UINT,
|
||||
(char *) (&localSampleCount[0][0] - memOffset),
|
||||
sizeof (unsigned int) * 1,
|
||||
sizeof (unsigned int) * width,
|
||||
1, 1,
|
||||
0,
|
||||
false,
|
||||
false));
|
||||
|
||||
for (int i = 0; i < channelCount; i++)
|
||||
{
|
||||
PixelType type;
|
||||
if (channelTypes[i] == 0)
|
||||
type = IMF::UINT;
|
||||
if (channelTypes[i] == 1)
|
||||
type = IMF::HALF;
|
||||
if (channelTypes[i] == 2)
|
||||
type = IMF::FLOAT;
|
||||
|
||||
stringstream ss;
|
||||
ss << i;
|
||||
string str = ss.str();
|
||||
|
||||
int sampleSize;
|
||||
if (channelTypes[i] == 0) sampleSize = sizeof (unsigned int);
|
||||
if (channelTypes[i] == 1) sampleSize = sizeof (half);
|
||||
if (channelTypes[i] == 2) sampleSize = sizeof (float);
|
||||
|
||||
int pointerSize = sizeof (char *);
|
||||
|
||||
frameBuffer.insert (str,
|
||||
DeepSlice (type,
|
||||
(char *) (&data[i][0][0] - memOffset),
|
||||
pointerSize * 1,
|
||||
pointerSize * width,
|
||||
sampleSize,
|
||||
1, 1,
|
||||
0,
|
||||
false,
|
||||
false));
|
||||
}
|
||||
|
||||
file.setFrameBuffer(frameBuffer);
|
||||
|
||||
|
||||
for (int ly = 0; ly < file.numYLevels(); ly++)
|
||||
for (int lx = 0; lx < file.numXLevels(); lx++)
|
||||
{
|
||||
Box2i dataWindowL = file.dataWindowForLevel(lx, ly);
|
||||
|
||||
//
|
||||
// Testing bulk read (without relative coordinates).
|
||||
//
|
||||
|
||||
file.readPixelSampleCounts(0, file.numXTiles(lx) - 1, 0, file.numYTiles(ly) - 1, lx, ly);
|
||||
|
||||
for (int i = 0; i < file.numYTiles(ly); i++)
|
||||
{
|
||||
for (int j = 0; j < file.numXTiles(lx); j++)
|
||||
{
|
||||
Box2i box = file.dataWindowForTile(j, i, lx, ly);
|
||||
for (int y = box.min.y; y <= box.max.y; y++)
|
||||
for (int x = box.min.x; x <= box.max.x; x++)
|
||||
{
|
||||
int dwy = y - dataWindowL.min.y;
|
||||
int dwx = x - dataWindowL.min.x;
|
||||
assert(localSampleCount[dwy][dwx] == sampleCountWhole[ly][lx][dwy][dwx]);
|
||||
|
||||
for (int k = 0; k < channelTypes.size(); k++)
|
||||
{
|
||||
if (channelTypes[k] == 0)
|
||||
data[k][dwy][dwx] = new unsigned int[localSampleCount[dwy][dwx]];
|
||||
if (channelTypes[k] == 1)
|
||||
data[k][dwy][dwx] = new half[localSampleCount[dwy][dwx]];
|
||||
if (channelTypes[k] == 2)
|
||||
data[k][dwy][dwx] = new float[localSampleCount[dwy][dwx]];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
file.readTiles(0, file.numXTiles(lx) - 1, 0, file.numYTiles(ly) - 1, lx, ly);
|
||||
|
||||
|
||||
for (int i = 0; i < file.levelHeight(ly); i++)
|
||||
for (int j = 0; j < file.levelWidth(lx); j++)
|
||||
for (int k = 0; k < channelCount; k++)
|
||||
{
|
||||
for (int l = 0; l < localSampleCount[i][j]; l++)
|
||||
{
|
||||
if (channelTypes[k] == 0)
|
||||
{
|
||||
unsigned int* value = (unsigned int*)(data[k][i][j]);
|
||||
if (value[l] != (i * width + j) % 2049)
|
||||
cout << j << ", " << i << " error, should be "
|
||||
<< (i * width + j) % 2049 << ", is " << value[l]
|
||||
<< endl << flush;
|
||||
assert (value[l] == (i * width + j) % 2049);
|
||||
}
|
||||
if (channelTypes[k] == 1)
|
||||
{
|
||||
half* value = (half*)(data[k][i][j]);
|
||||
if (value[l] != (i * width + j) % 2049)
|
||||
cout << j << ", " << i << " error, should be "
|
||||
<< (i * width + j) % 2049 << ", is " << value[l]
|
||||
<< endl << flush;
|
||||
assert (((half*)(data[k][i][j]))[l] == (i * width + j) % 2049);
|
||||
}
|
||||
if (channelTypes[k] == 2)
|
||||
{
|
||||
float* value = (float*)(data[k][i][j]);
|
||||
if (value[l] != (i * width + j) % 2049)
|
||||
cout << j << ", " << i << " error, should be "
|
||||
<< (i * width + j) % 2049 << ", is " << value[l]
|
||||
<< endl << flush;
|
||||
assert (((float*)(data[k][i][j]))[l] == (i * width + j) % 2049);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (int i = 0; i < file.levelHeight(ly); i++)
|
||||
for (int j = 0; j < file.levelWidth(lx); j++)
|
||||
for (int k = 0; k < channelCount; k++)
|
||||
{
|
||||
if (channelTypes[k] == 0)
|
||||
delete[] (unsigned int*) data[k][i][j];
|
||||
if (channelTypes[k] == 1)
|
||||
delete[] (half*) data[k][i][j];
|
||||
if (channelTypes[k] == 2)
|
||||
delete[] (float*) data[k][i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
copyFile (const std::string & srcFn, const std::string & cpyFn)
|
||||
{
|
||||
cout << "copying " ;
|
||||
cout.flush();
|
||||
{
|
||||
DeepTiledInputFile in_file (srcFn.c_str(),8);
|
||||
remove (cpyFn.c_str());
|
||||
DeepTiledOutputFile out_file (cpyFn.c_str(), in_file.header());
|
||||
out_file.copyPixels (in_file);
|
||||
}
|
||||
// prevent accidentally reading souce instead of copy
|
||||
remove (srcFn.c_str());
|
||||
}
|
||||
|
||||
void
|
||||
readCopyWriteTest (int channelCount, int testTimes, const std::string & tempDir)
|
||||
{
|
||||
cout << "Testing files with " << channelCount << " channels, using absolute coordinates "
|
||||
<< testTimes << " times."
|
||||
<< endl << flush;
|
||||
|
||||
std::string cpyFn = tempDir + "imf_test_copy_deep_tiled_copy.exr";
|
||||
std::string srcFn = tempDir + "imf_test_copy_deep_tiled_source.exr";
|
||||
|
||||
for (int i = 0; i < testTimes; i++)
|
||||
{
|
||||
int compressionIndex = i % 3;
|
||||
Compression compression;
|
||||
switch (compressionIndex)
|
||||
{
|
||||
case 0:
|
||||
compression = NO_COMPRESSION;
|
||||
break;
|
||||
case 1:
|
||||
compression = RLE_COMPRESSION;
|
||||
break;
|
||||
case 2:
|
||||
compression = ZIPS_COMPRESSION;
|
||||
break;
|
||||
}
|
||||
|
||||
generateRandomFile (channelCount, compression, srcFn);
|
||||
copyFile (srcFn, cpyFn);
|
||||
readFile (channelCount, cpyFn);
|
||||
remove (cpyFn.c_str());
|
||||
cout << endl << flush;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void testCopyDeepTiled (const std::string & tempDir)
|
||||
{
|
||||
try
|
||||
{
|
||||
cout << "Testing raw copy in DeepTiledInput/OutputFile " << endl;
|
||||
|
||||
srand(1);
|
||||
|
||||
int numThreads = ThreadPool::globalThreadPool().numThreads();
|
||||
ThreadPool::globalThreadPool().setNumThreads(2);
|
||||
|
||||
readCopyWriteTest ( 3, 1, tempDir);
|
||||
readCopyWriteTest ( 5, 2, tempDir);
|
||||
readCopyWriteTest (11, 3, tempDir);
|
||||
|
||||
ThreadPool::globalThreadPool().setNumThreads (numThreads);
|
||||
|
||||
cout << "ok\n" << endl;
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
cerr << "ERROR -- caught exception: " << e.what() << endl;
|
||||
assert (false);
|
||||
}
|
||||
}
|
||||
42
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testCopyDeepTiled.h
Normal file
42
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testCopyDeepTiled.h
Normal file
@@ -0,0 +1,42 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef TESTCOPYDEEPTILED_H_
|
||||
#define TESTCOPYDEEPTILED_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
void testCopyDeepTiled (const std::string & tempDir);
|
||||
|
||||
#endif /* TESTCOPYDEEPTILED_H_ */
|
||||
@@ -0,0 +1,980 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// Portions (c) 2012, Weta Digital Ltd
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// Weta Digital nor any other ontributors may be used to endorse
|
||||
// or promote products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "tmpDir.h"
|
||||
#include "testCopyMultiPartFile.h"
|
||||
|
||||
#include <IlmThreadPool.h>
|
||||
#include <ImfMultiPartInputFile.h>
|
||||
#include <ImfMultiPartOutputFile.h>
|
||||
#include <ImfArray.h>
|
||||
#include <ImfChannelList.h>
|
||||
#include <ImfOutputPart.h>
|
||||
#include <ImfInputPart.h>
|
||||
#include <ImfTiledOutputPart.h>
|
||||
#include <ImfTiledInputPart.h>
|
||||
#include <ImfDeepTiledOutputPart.h>
|
||||
#include <ImfDeepScanLineOutputPart.h>
|
||||
#include <ImfDeepTiledInputPart.h>
|
||||
#include <ImfDeepScanLineInputPart.h>
|
||||
#include <ImfPartType.h>
|
||||
#include <ImfNamespace.h>
|
||||
|
||||
|
||||
namespace IMF = OPENEXR_IMF_NAMESPACE;
|
||||
using namespace IMF;
|
||||
using namespace std;
|
||||
using namespace IMATH_NAMESPACE;
|
||||
using namespace ILMTHREAD_NAMESPACE;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
const int height = 247;
|
||||
const int width = 233;
|
||||
|
||||
vector<Header> headers;
|
||||
vector<int> pixelTypes;
|
||||
vector<int> partTypes;
|
||||
vector<int> levelModes;
|
||||
|
||||
template <class T>
|
||||
void fillPixels (Array2D<T> &ph, int width, int height)
|
||||
{
|
||||
ph.resizeErase(height, width);
|
||||
for (int y = 0; y < height; ++y)
|
||||
for (int x = 0; x < width; ++x)
|
||||
{
|
||||
//
|
||||
// We do this because half cannot store number bigger than 2048 exactly.
|
||||
//
|
||||
ph[y][x] = (y * width + x) % 2049;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void fillPixels (Array2D<unsigned int>& sampleCount, Array2D<T*> &ph, int width, int height)
|
||||
{
|
||||
ph.resizeErase(height, width);
|
||||
for (int y = 0; y < height; ++y)
|
||||
for (int x = 0; x < width; ++x)
|
||||
{
|
||||
ph[y][x] = new T[sampleCount[y][x]];
|
||||
for (int i = 0; i < sampleCount[y][x]; i++)
|
||||
{
|
||||
//
|
||||
// We do this because half cannot store number bigger than 2048 exactly.
|
||||
//
|
||||
ph[y][x][i] = (y * width + x) % 2049;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void allocatePixels(int type, Array2D<unsigned int>& sampleCount,
|
||||
Array2D<unsigned int*>& uintData, Array2D<float*>& floatData,
|
||||
Array2D<half*>& halfData, int x1, int x2, int y1, int y2)
|
||||
{
|
||||
for (int y = y1; y <= y2; y++)
|
||||
for (int x = x1; x <= x2; x++)
|
||||
{
|
||||
if (type == 0)
|
||||
uintData[y][x] = new unsigned int[sampleCount[y][x]];
|
||||
if (type == 1)
|
||||
floatData[y][x] = new float[sampleCount[y][x]];
|
||||
if (type == 2)
|
||||
halfData[y][x] = new half[sampleCount[y][x]];
|
||||
}
|
||||
}
|
||||
|
||||
void allocatePixels(int type, Array2D<unsigned int>& sampleCount,
|
||||
Array2D<unsigned int*>& uintData, Array2D<float*>& floatData,
|
||||
Array2D<half*>& halfData, int width, int height)
|
||||
{
|
||||
allocatePixels(type, sampleCount, uintData, floatData, halfData, 0, width - 1, 0, height - 1);
|
||||
}
|
||||
|
||||
void releasePixels(int type, Array2D<unsigned int*>& uintData, Array2D<float*>& floatData,
|
||||
Array2D<half*>& halfData, int x1, int x2, int y1, int y2)
|
||||
{
|
||||
for (int y = y1; y <= y2; y++)
|
||||
for (int x = x1; x <= x2; x++)
|
||||
{
|
||||
if (type == 0)
|
||||
delete[] uintData[y][x];
|
||||
if (type == 1)
|
||||
delete[] floatData[y][x];
|
||||
if (type == 2)
|
||||
delete[] halfData[y][x];
|
||||
}
|
||||
}
|
||||
|
||||
void releasePixels(int type, Array2D<unsigned int*>& uintData, Array2D<float*>& floatData,
|
||||
Array2D<half*>& halfData, int width, int height)
|
||||
{
|
||||
releasePixels(type, uintData, floatData, halfData, 0, width - 1, 0, height - 1);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool checkPixels (Array2D<T> &ph, int lx, int rx, int ly, int ry, int width)
|
||||
{
|
||||
for (int y = ly; y <= ry; ++y)
|
||||
for (int x = lx; x <= rx; ++x)
|
||||
if (ph[y][x] != (y * width + x) % 2049)
|
||||
{
|
||||
cout << "value at " << x << ", " << y << ": " << ph[y][x]
|
||||
<< ", should be " << (y * width + x) % 2049 << endl << flush;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool checkPixels (Array2D<T> &ph, int width, int height)
|
||||
{
|
||||
return checkPixels<T> (ph, 0, width - 1, 0, height - 1, width);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool checkPixels (Array2D<unsigned int>& sampleCount, Array2D<T*> &ph,
|
||||
int lx, int rx, int ly, int ry, int width)
|
||||
{
|
||||
for (int y = ly; y <= ry; ++y)
|
||||
for (int x = lx; x <= rx; ++x)
|
||||
{
|
||||
for (int i = 0; i < sampleCount[y][x]; i++)
|
||||
{
|
||||
if (ph[y][x][i] != (y * width + x) % 2049)
|
||||
{
|
||||
cout << "value at " << x << ", " << y << ", sample " << i << ": " << ph[y][x][i]
|
||||
<< ", should be " << (y * width + x) % 2049 << endl << flush;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool checkPixels (Array2D<unsigned int>& sampleCount, Array2D<T*> &ph, int width, int height)
|
||||
{
|
||||
return checkPixels<T> (sampleCount, ph, 0, width - 1, 0, height - 1, width);
|
||||
}
|
||||
|
||||
bool checkSampleCount(Array2D<unsigned int>& sampleCount, int x1, int x2, int y1, int y2, int width)
|
||||
{
|
||||
for (int i = y1; i <= y2; i++)
|
||||
for (int j = x1; j <= x2; j++)
|
||||
{
|
||||
if (sampleCount[i][j] != ((i * width) + j) % 10 + 1)
|
||||
{
|
||||
cout << "sample count at " << j << ", " << i << ": " << sampleCount[i][j]
|
||||
<< ", should be " << (i * width + j) % 10 + 1 << endl << flush;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool checkSampleCount(Array2D<unsigned int>& sampleCount, int width, int height)
|
||||
{
|
||||
return checkSampleCount(sampleCount, 0, width - 1, 0, height - 1, width);
|
||||
}
|
||||
|
||||
void generateRandomHeaders(int partCount, vector<Header>& headers)
|
||||
{
|
||||
cout << "Generating headers and data" << endl << flush;
|
||||
|
||||
headers.clear();
|
||||
for (int i = 0; i < partCount; i++)
|
||||
{
|
||||
Header header (width,
|
||||
height,
|
||||
1.f,
|
||||
IMATH_NAMESPACE::V2f (0, 0),
|
||||
1.f,
|
||||
INCREASING_Y,
|
||||
ZIPS_COMPRESSION);
|
||||
|
||||
int pixelType = rand() % 3;
|
||||
int partType = rand() % 4;
|
||||
|
||||
pixelTypes[i] = pixelType;
|
||||
partTypes[i] = partType;
|
||||
|
||||
stringstream ss;
|
||||
ss << i;
|
||||
header.setName(ss.str());
|
||||
|
||||
switch (pixelType)
|
||||
{
|
||||
case 0:
|
||||
header.channels().insert("UINT", Channel(IMF::UINT));
|
||||
break;
|
||||
case 1:
|
||||
header.channels().insert("FLOAT", Channel(IMF::FLOAT));
|
||||
break;
|
||||
case 2:
|
||||
header.channels().insert("HALF", Channel(IMF::HALF));
|
||||
break;
|
||||
}
|
||||
|
||||
switch (partType)
|
||||
{
|
||||
case 0:
|
||||
header.setType(SCANLINEIMAGE);
|
||||
break;
|
||||
case 1:
|
||||
header.setType(TILEDIMAGE);
|
||||
break;
|
||||
case 2:
|
||||
header.setType(DEEPSCANLINE);
|
||||
break;
|
||||
case 3:
|
||||
header.setType(DEEPTILE);
|
||||
break;
|
||||
}
|
||||
|
||||
int tileX;
|
||||
int tileY;
|
||||
int levelMode;
|
||||
if (partType == 1 || partType == 3)
|
||||
{
|
||||
tileX = rand() % width + 1;
|
||||
tileY = rand() % height + 1;
|
||||
levelMode = rand() % 3;
|
||||
levelModes[i] = levelMode;
|
||||
LevelMode lm;
|
||||
switch (levelMode)
|
||||
{
|
||||
case 0:
|
||||
lm = ONE_LEVEL;
|
||||
break;
|
||||
case 1:
|
||||
lm = MIPMAP_LEVELS;
|
||||
break;
|
||||
case 2:
|
||||
lm = RIPMAP_LEVELS;
|
||||
break;
|
||||
}
|
||||
header.setTileDescription(TileDescription(tileX, tileY, lm));
|
||||
}
|
||||
|
||||
|
||||
int order = rand() % NUM_LINEORDERS;
|
||||
if(partType==0 || partType ==2)
|
||||
{
|
||||
// can't write random scanlines
|
||||
order = rand() % (NUM_LINEORDERS-1);
|
||||
}
|
||||
LineOrder l;
|
||||
switch(order)
|
||||
{
|
||||
case 0 :
|
||||
l = INCREASING_Y;
|
||||
break;
|
||||
case 1 :
|
||||
l = DECREASING_Y;
|
||||
break;
|
||||
case 2 :
|
||||
l = RANDOM_Y;
|
||||
break;
|
||||
}
|
||||
|
||||
header.lineOrder()=l;
|
||||
|
||||
|
||||
if (partType == 0 || partType == 2)
|
||||
{
|
||||
cout << "pixelType = " << pixelType << " partType = " << partType
|
||||
<< " line order =" << header.lineOrder() << endl << flush;
|
||||
}
|
||||
else
|
||||
{
|
||||
cout << "pixelType = " << pixelType << " partType = " << partType
|
||||
<< " tile order =" << header.lineOrder()
|
||||
<< " levelMode = " << levelModes[i] << endl << flush;
|
||||
}
|
||||
|
||||
headers.push_back(header);
|
||||
}
|
||||
}
|
||||
|
||||
void setOutputFrameBuffer(FrameBuffer& frameBuffer, int pixelType,
|
||||
Array2D<unsigned int>& uData, Array2D<float>& fData,
|
||||
Array2D<half>& hData, int width)
|
||||
{
|
||||
switch (pixelType)
|
||||
{
|
||||
case 0:
|
||||
frameBuffer.insert ("UINT",
|
||||
Slice (IMF::UINT,
|
||||
(char *) (&uData[0][0]),
|
||||
sizeof (uData[0][0]) * 1,
|
||||
sizeof (uData[0][0]) * width));
|
||||
break;
|
||||
case 1:
|
||||
frameBuffer.insert ("FLOAT",
|
||||
Slice (IMF::FLOAT,
|
||||
(char *) (&fData[0][0]),
|
||||
sizeof (fData[0][0]) * 1,
|
||||
sizeof (fData[0][0]) * width));
|
||||
break;
|
||||
case 2:
|
||||
frameBuffer.insert ("HALF",
|
||||
Slice (IMF::HALF,
|
||||
(char *) (&hData[0][0]),
|
||||
sizeof (hData[0][0]) * 1,
|
||||
sizeof (hData[0][0]) * width));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void setOutputDeepFrameBuffer(DeepFrameBuffer& frameBuffer, int pixelType,
|
||||
Array2D<unsigned int*>& uData, Array2D<float*>& fData,
|
||||
Array2D<half*>& hData, int width)
|
||||
{
|
||||
switch (pixelType)
|
||||
{
|
||||
case 0:
|
||||
frameBuffer.insert ("UINT",
|
||||
DeepSlice (IMF::UINT,
|
||||
(char *) (&uData[0][0]),
|
||||
sizeof (uData[0][0]) * 1,
|
||||
sizeof (uData[0][0]) * width,
|
||||
sizeof (unsigned int)));
|
||||
break;
|
||||
case 1:
|
||||
frameBuffer.insert ("FLOAT",
|
||||
DeepSlice (IMF::FLOAT,
|
||||
(char *) (&fData[0][0]),
|
||||
sizeof (fData[0][0]) * 1,
|
||||
sizeof (fData[0][0]) * width,
|
||||
sizeof (float)));
|
||||
break;
|
||||
case 2:
|
||||
frameBuffer.insert ("HALF",
|
||||
DeepSlice (IMF::HALF,
|
||||
(char *) (&hData[0][0]),
|
||||
sizeof (hData[0][0]) * 1,
|
||||
sizeof (hData[0][0]) * width,
|
||||
sizeof (half)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void setInputFrameBuffer(FrameBuffer& frameBuffer, int pixelType,
|
||||
Array2D<unsigned int>& uData, Array2D<float>& fData,
|
||||
Array2D<half>& hData, int width, int height)
|
||||
{
|
||||
switch (pixelType)
|
||||
{
|
||||
case 0:
|
||||
uData.resizeErase(height, width);
|
||||
frameBuffer.insert ("UINT",
|
||||
Slice (IMF::UINT,
|
||||
(char *) (&uData[0][0]),
|
||||
sizeof (uData[0][0]) * 1,
|
||||
sizeof (uData[0][0]) * width,
|
||||
1, 1,
|
||||
0));
|
||||
break;
|
||||
case 1:
|
||||
fData.resizeErase(height, width);
|
||||
frameBuffer.insert ("FLOAT",
|
||||
Slice (IMF::FLOAT,
|
||||
(char *) (&fData[0][0]),
|
||||
sizeof (fData[0][0]) * 1,
|
||||
sizeof (fData[0][0]) * width,
|
||||
1, 1,
|
||||
0));
|
||||
break;
|
||||
case 2:
|
||||
hData.resizeErase(height, width);
|
||||
frameBuffer.insert ("HALF",
|
||||
Slice (IMF::HALF,
|
||||
(char *) (&hData[0][0]),
|
||||
sizeof (hData[0][0]) * 1,
|
||||
sizeof (hData[0][0]) * width,
|
||||
1, 1,
|
||||
0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void setInputDeepFrameBuffer(DeepFrameBuffer& frameBuffer, int pixelType,
|
||||
Array2D<unsigned int*>& uData, Array2D<float*>& fData,
|
||||
Array2D<half*>& hData, int width, int height)
|
||||
{
|
||||
switch (pixelType)
|
||||
{
|
||||
case 0:
|
||||
uData.resizeErase(height, width);
|
||||
frameBuffer.insert ("UINT",
|
||||
DeepSlice (IMF::UINT,
|
||||
(char *) (&uData[0][0]),
|
||||
sizeof (uData[0][0]) * 1,
|
||||
sizeof (uData[0][0]) * width,
|
||||
sizeof (unsigned int)));
|
||||
break;
|
||||
case 1:
|
||||
fData.resizeErase(height, width);
|
||||
frameBuffer.insert ("FLOAT",
|
||||
DeepSlice (IMF::FLOAT,
|
||||
(char *) (&fData[0][0]),
|
||||
sizeof (fData[0][0]) * 1,
|
||||
sizeof (fData[0][0]) * width,
|
||||
sizeof (float)));
|
||||
break;
|
||||
case 2:
|
||||
hData.resizeErase(height, width);
|
||||
frameBuffer.insert ("HALF",
|
||||
DeepSlice (IMF::HALF,
|
||||
(char *) (&hData[0][0]),
|
||||
sizeof (hData[0][0]) * 1,
|
||||
sizeof (hData[0][0]) * width,
|
||||
sizeof (half)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
generateRandomFile (int partCount, const std::string & srcFn)
|
||||
{
|
||||
//
|
||||
// Init data.
|
||||
//
|
||||
Array2D<half> halfData;
|
||||
Array2D<float> floatData;
|
||||
Array2D<unsigned int> uintData;
|
||||
|
||||
Array2D<unsigned int> sampleCount;
|
||||
Array2D<half*> deepHalfData;
|
||||
Array2D<float*> deepFloatData;
|
||||
Array2D<unsigned int*> deepUintData;
|
||||
|
||||
vector<GenericOutputFile*> outputfiles;
|
||||
|
||||
pixelTypes.resize(partCount);
|
||||
partTypes.resize(partCount);
|
||||
levelModes.resize(partCount);
|
||||
|
||||
//
|
||||
// Generate headers and data.
|
||||
//
|
||||
generateRandomHeaders(partCount, headers);
|
||||
|
||||
remove(srcFn.c_str());
|
||||
MultiPartOutputFile file(srcFn.c_str(), &headers[0],headers.size());
|
||||
|
||||
//
|
||||
// Writing files.
|
||||
//
|
||||
cout << "Writing files " << flush;
|
||||
|
||||
//
|
||||
// Pre-generating frameBuffers.
|
||||
//
|
||||
for (int i = 0; i < partCount; i++)
|
||||
{
|
||||
switch (partTypes[i])
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
OutputPart part(file, i);
|
||||
|
||||
FrameBuffer frameBuffer;
|
||||
|
||||
fillPixels <unsigned int> (uintData, width, height);
|
||||
fillPixels <float> (floatData, width, height);
|
||||
fillPixels <half> (halfData, width, height);
|
||||
|
||||
setOutputFrameBuffer(frameBuffer, pixelTypes[i], uintData, floatData, halfData, width);
|
||||
|
||||
part.setFrameBuffer(frameBuffer);
|
||||
|
||||
part.writePixels(height);
|
||||
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
TiledOutputPart part(file, i);
|
||||
|
||||
int numXLevels = part.numXLevels();
|
||||
int numYLevels = part.numYLevels();
|
||||
|
||||
for (int xLevel = 0; xLevel < numXLevels; xLevel++)
|
||||
for (int yLevel = 0; yLevel < numYLevels; yLevel++)
|
||||
{
|
||||
if (!part.isValidLevel(xLevel, yLevel))
|
||||
continue;
|
||||
|
||||
int w = part.levelWidth(xLevel);
|
||||
int h = part.levelHeight(yLevel);
|
||||
|
||||
FrameBuffer frameBuffer;
|
||||
|
||||
fillPixels <unsigned int> (uintData, w, h);
|
||||
fillPixels <float> (floatData, w, h);
|
||||
fillPixels <half> (halfData, w, h);
|
||||
setOutputFrameBuffer(frameBuffer, pixelTypes[i],
|
||||
uintData, floatData, halfData,
|
||||
w);
|
||||
|
||||
part.setFrameBuffer(frameBuffer);
|
||||
|
||||
part.writeTiles(0, part.numXTiles(xLevel) - 1,
|
||||
0, part.numYTiles(yLevel) - 1,
|
||||
xLevel, yLevel);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
DeepScanLineOutputPart part(file, i);
|
||||
|
||||
DeepFrameBuffer frameBuffer;
|
||||
|
||||
sampleCount.resizeErase(height, width);
|
||||
for (int j = 0; j < height; j++)
|
||||
for (int k = 0; k < width; k++)
|
||||
sampleCount[j][k] = (j * width + k) % 10 + 1;
|
||||
|
||||
frameBuffer.insertSampleCountSlice (Slice (IMF::UINT,
|
||||
(char *) (&sampleCount[0][0]),
|
||||
sizeof (unsigned int) * 1,
|
||||
sizeof (unsigned int) * width));
|
||||
|
||||
if (pixelTypes[i] == 0)
|
||||
fillPixels <unsigned int> (sampleCount, deepUintData, width, height);
|
||||
if (pixelTypes[i] == 1)
|
||||
fillPixels <float> (sampleCount, deepFloatData, width, height);
|
||||
if (pixelTypes[i] == 2)
|
||||
fillPixels <half> (sampleCount, deepHalfData, width, height);
|
||||
setOutputDeepFrameBuffer(frameBuffer, pixelTypes[i],
|
||||
deepUintData, deepFloatData, deepHalfData,
|
||||
width);
|
||||
|
||||
part.setFrameBuffer(frameBuffer);
|
||||
|
||||
part.writePixels(height);
|
||||
|
||||
releasePixels(pixelTypes[i], deepUintData, deepFloatData, deepHalfData, width, height);
|
||||
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
DeepTiledOutputPart part(file, i);
|
||||
|
||||
int numXLevels = part.numXLevels();
|
||||
int numYLevels = part.numYLevels();
|
||||
|
||||
for (int xLevel = 0; xLevel < numXLevels; xLevel++)
|
||||
for (int yLevel = 0; yLevel < numYLevels; yLevel++)
|
||||
{
|
||||
if (!part.isValidLevel(xLevel, yLevel))
|
||||
continue;
|
||||
|
||||
int w = part.levelWidth(xLevel);
|
||||
int h = part.levelHeight(yLevel);
|
||||
|
||||
DeepFrameBuffer frameBuffer;
|
||||
|
||||
sampleCount.resizeErase(h, w);
|
||||
for (int j = 0; j < h; j++)
|
||||
for (int k = 0; k < w; k++)
|
||||
sampleCount[j][k] = (j * w + k) % 10 + 1;
|
||||
|
||||
frameBuffer.insertSampleCountSlice (Slice (IMF::UINT,
|
||||
(char *) (&sampleCount[0][0]),
|
||||
sizeof (unsigned int) * 1,
|
||||
sizeof (unsigned int) * w));
|
||||
|
||||
if (pixelTypes[i] == 0)
|
||||
fillPixels <unsigned int> (sampleCount, deepUintData, w, h);
|
||||
if (pixelTypes[i] == 1)
|
||||
fillPixels <float> (sampleCount, deepFloatData, w, h);
|
||||
if (pixelTypes[i] == 2)
|
||||
fillPixels <half> (sampleCount, deepHalfData, w, h);
|
||||
setOutputDeepFrameBuffer(frameBuffer, pixelTypes[i],
|
||||
deepUintData, deepFloatData, deepHalfData,
|
||||
w);
|
||||
|
||||
part.setFrameBuffer(frameBuffer);
|
||||
|
||||
part.writeTiles(0, part.numXTiles(xLevel) - 1,
|
||||
0, part.numYTiles(yLevel) - 1,
|
||||
xLevel, yLevel);
|
||||
|
||||
releasePixels(pixelTypes[i], deepUintData, deepFloatData, deepHalfData, w, h);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
readWholeFiles (const std::string & cpyFn)
|
||||
{
|
||||
Array2D<unsigned int> uData;
|
||||
Array2D<float> fData;
|
||||
Array2D<half> hData;
|
||||
|
||||
Array2D<unsigned int*> deepUData;
|
||||
Array2D<float*> deepFData;
|
||||
Array2D<half*> deepHData;
|
||||
|
||||
Array2D<unsigned int> sampleCount;
|
||||
|
||||
MultiPartInputFile file(cpyFn.c_str());
|
||||
for (size_t i = 0; i < file.parts(); i++)
|
||||
{
|
||||
const Header& header = file.header(i);
|
||||
assert (header.displayWindow() == headers[i].displayWindow());
|
||||
assert (header.dataWindow() == headers[i].dataWindow());
|
||||
assert (header.pixelAspectRatio() == headers[i].pixelAspectRatio());
|
||||
assert (header.screenWindowCenter() == headers[i].screenWindowCenter());
|
||||
assert (header.screenWindowWidth() == headers[i].screenWindowWidth());
|
||||
assert (header.lineOrder() == headers[i].lineOrder());
|
||||
assert (header.compression() == headers[i].compression());
|
||||
assert (header.channels() == headers[i].channels());
|
||||
assert (header.name() == headers[i].name());
|
||||
assert (header.type() == headers[i].type());
|
||||
}
|
||||
|
||||
cout << "Reading whole files " << flush;
|
||||
|
||||
//
|
||||
// Shuffle part numbers.
|
||||
//
|
||||
vector<int> shuffledPartNumber;
|
||||
for (int i = 0; i < headers.size(); i++)
|
||||
shuffledPartNumber.push_back(i);
|
||||
for (int i = 0; i < headers.size(); i++)
|
||||
{
|
||||
int a = rand() % headers.size();
|
||||
int b = rand() % headers.size();
|
||||
swap (shuffledPartNumber[a], shuffledPartNumber[b]);
|
||||
}
|
||||
|
||||
//
|
||||
// Start reading whole files.
|
||||
//
|
||||
int i;
|
||||
int partNumber;
|
||||
try
|
||||
{
|
||||
for (i = 0; i < headers.size(); i++)
|
||||
{
|
||||
partNumber = shuffledPartNumber[i];
|
||||
switch (partTypes[partNumber])
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
FrameBuffer frameBuffer;
|
||||
setInputFrameBuffer(frameBuffer, pixelTypes[partNumber],
|
||||
uData, fData, hData, width, height);
|
||||
|
||||
InputPart part(file, partNumber);
|
||||
part.setFrameBuffer(frameBuffer);
|
||||
part.readPixels(0, height - 1);
|
||||
switch (pixelTypes[partNumber])
|
||||
{
|
||||
case 0:
|
||||
assert(checkPixels<unsigned int>(uData, width, height));
|
||||
break;
|
||||
case 1:
|
||||
assert(checkPixels<float>(fData, width, height));
|
||||
break;
|
||||
case 2:
|
||||
assert(checkPixels<half>(hData, width, height));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
TiledInputPart part(file, partNumber);
|
||||
int numXLevels = part.numXLevels();
|
||||
int numYLevels = part.numYLevels();
|
||||
for (int xLevel = 0; xLevel < numXLevels; xLevel++)
|
||||
for (int yLevel = 0; yLevel < numYLevels; yLevel++)
|
||||
{
|
||||
if (!part.isValidLevel(xLevel, yLevel))
|
||||
continue;
|
||||
|
||||
int w = part.levelWidth(xLevel);
|
||||
int h = part.levelHeight(yLevel);
|
||||
|
||||
FrameBuffer frameBuffer;
|
||||
setInputFrameBuffer(frameBuffer, pixelTypes[partNumber],
|
||||
uData, fData, hData, w, h);
|
||||
|
||||
part.setFrameBuffer(frameBuffer);
|
||||
int numXTiles = part.numXTiles(xLevel);
|
||||
int numYTiles = part.numYTiles(yLevel);
|
||||
part.readTiles(0, numXTiles - 1, 0, numYTiles - 1, xLevel, yLevel);
|
||||
switch (pixelTypes[partNumber])
|
||||
{
|
||||
case 0:
|
||||
assert(checkPixels<unsigned int>(uData, w, h));
|
||||
break;
|
||||
case 1:
|
||||
assert(checkPixels<float>(fData, w, h));
|
||||
break;
|
||||
case 2:
|
||||
assert(checkPixels<half>(hData, w, h));
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
DeepScanLineInputPart part(file, partNumber);
|
||||
|
||||
DeepFrameBuffer frameBuffer;
|
||||
|
||||
sampleCount.resizeErase(height, width);
|
||||
frameBuffer.insertSampleCountSlice (Slice (IMF::UINT,
|
||||
(char *) (&sampleCount[0][0]),
|
||||
sizeof (unsigned int) * 1,
|
||||
sizeof (unsigned int) * width));
|
||||
|
||||
setInputDeepFrameBuffer(frameBuffer, pixelTypes[partNumber],
|
||||
deepUData, deepFData, deepHData, width, height);
|
||||
|
||||
part.setFrameBuffer(frameBuffer);
|
||||
|
||||
part.readPixelSampleCounts(0, height - 1);
|
||||
|
||||
allocatePixels(pixelTypes[partNumber], sampleCount,
|
||||
deepUData, deepFData, deepHData, width, height);
|
||||
|
||||
part.readPixels(0, height - 1);
|
||||
switch (pixelTypes[partNumber])
|
||||
{
|
||||
case 0:
|
||||
assert(checkPixels<unsigned int>(sampleCount, deepUData, width, height));
|
||||
break;
|
||||
case 1:
|
||||
assert(checkPixels<float>(sampleCount, deepFData, width, height));
|
||||
break;
|
||||
case 2:
|
||||
assert(checkPixels<half>(sampleCount, deepHData, width, height));
|
||||
break;
|
||||
}
|
||||
|
||||
releasePixels(pixelTypes[partNumber],
|
||||
deepUData, deepFData, deepHData, width, height);
|
||||
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
DeepTiledInputPart part(file, partNumber);
|
||||
int numXLevels = part.numXLevels();
|
||||
int numYLevels = part.numYLevels();
|
||||
for (int xLevel = 0; xLevel < numXLevels; xLevel++)
|
||||
for (int yLevel = 0; yLevel < numYLevels; yLevel++)
|
||||
{
|
||||
if (!part.isValidLevel(xLevel, yLevel))
|
||||
continue;
|
||||
|
||||
int w = part.levelWidth(xLevel);
|
||||
int h = part.levelHeight(yLevel);
|
||||
|
||||
DeepFrameBuffer frameBuffer;
|
||||
|
||||
sampleCount.resizeErase(h, w);
|
||||
frameBuffer.insertSampleCountSlice (Slice (IMF::UINT,
|
||||
(char *) (&sampleCount[0][0]),
|
||||
sizeof (unsigned int) * 1,
|
||||
sizeof (unsigned int) * w));
|
||||
|
||||
setInputDeepFrameBuffer(frameBuffer, pixelTypes[partNumber],
|
||||
deepUData, deepFData, deepHData, w, h);
|
||||
|
||||
part.setFrameBuffer(frameBuffer);
|
||||
|
||||
int numXTiles = part.numXTiles(xLevel);
|
||||
int numYTiles = part.numYTiles(yLevel);
|
||||
|
||||
part.readPixelSampleCounts(0, numXTiles - 1, 0, numYTiles - 1,
|
||||
xLevel, yLevel);
|
||||
|
||||
allocatePixels(pixelTypes[partNumber], sampleCount,
|
||||
deepUData, deepFData, deepHData, w, h);
|
||||
|
||||
part.readTiles(0, numXTiles - 1, 0, numYTiles - 1, xLevel, yLevel);
|
||||
switch (pixelTypes[partNumber])
|
||||
{
|
||||
case 0:
|
||||
assert(checkPixels<unsigned int>(sampleCount, deepUData, w, h));
|
||||
break;
|
||||
case 1:
|
||||
assert(checkPixels<float>(sampleCount, deepFData, w, h));
|
||||
break;
|
||||
case 2:
|
||||
assert(checkPixels<half>(sampleCount, deepHData, w, h));
|
||||
break;
|
||||
}
|
||||
|
||||
releasePixels(pixelTypes[partNumber],
|
||||
deepUData, deepFData, deepHData, w, h);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
cout << "Error while reading part " << partNumber << endl << flush;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
copyFile (const std::string & srcFn, const std::string & cpyFn)
|
||||
{
|
||||
cout << "copying ";
|
||||
cout.flush();
|
||||
|
||||
MultiPartInputFile in(srcFn.c_str());
|
||||
|
||||
|
||||
vector<Header> in_hdr(in.parts());
|
||||
for(int i=0;i<in.parts();i++)
|
||||
{
|
||||
in_hdr[i]=in.header(i);
|
||||
}
|
||||
|
||||
MultiPartOutputFile out(cpyFn.c_str(),&in_hdr[0],in.parts());
|
||||
for(size_t i=0;i<in.parts();i++)
|
||||
{
|
||||
std::string part_type = in.header(i).type();
|
||||
if(part_type == DEEPSCANLINE)
|
||||
{
|
||||
DeepScanLineInputPart partin(in,i);
|
||||
DeepScanLineOutputPart partout(out,i);
|
||||
partout.copyPixels(partin);
|
||||
}
|
||||
else if(part_type == DEEPTILE)
|
||||
{
|
||||
DeepTiledInputPart partin(in,i);
|
||||
DeepTiledOutputPart partout(out,i);
|
||||
partout.copyPixels(partin);
|
||||
}else if(part_type== SCANLINEIMAGE)
|
||||
{
|
||||
InputPart partin(in,i);
|
||||
OutputPart partout(out,i);
|
||||
partout.copyPixels(partin);
|
||||
}
|
||||
else if(part_type==TILEDIMAGE)
|
||||
{
|
||||
TiledInputPart partin(in,i);
|
||||
TiledOutputPart partout(out,i);
|
||||
partout.copyPixels(partin);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
testWriteCopyRead (int partNumber,
|
||||
int runCount,
|
||||
int randomReadCount,
|
||||
const std::string & tempDir)
|
||||
{
|
||||
cout << "Testing file with " << partNumber << " part(s)." << endl << flush;
|
||||
|
||||
std::string srcFn = tempDir + "imf_test_copy_multipart_source.exr";
|
||||
std::string cpyFn = tempDir + "imf_test_copy_multipart_copy.exr";
|
||||
|
||||
for (int i = 0; i < runCount; i++)
|
||||
{
|
||||
generateRandomFile (partNumber, srcFn);
|
||||
copyFile (srcFn, cpyFn);
|
||||
remove (srcFn.c_str());
|
||||
readWholeFiles (cpyFn);
|
||||
remove (cpyFn.c_str());
|
||||
|
||||
cout << endl << flush;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void testCopyMultiPartFile (const std::string & tempDir)
|
||||
{
|
||||
try
|
||||
{
|
||||
cout << "Testing copying multi-part files" << endl;
|
||||
|
||||
srand(1);
|
||||
|
||||
int numThreads = ThreadPool::globalThreadPool().numThreads();
|
||||
ThreadPool::globalThreadPool().setNumThreads(4);
|
||||
|
||||
testWriteCopyRead ( 2, 20, 10, tempDir);
|
||||
testWriteCopyRead ( 1, 10, 5, tempDir);
|
||||
testWriteCopyRead ( 5, 4, 25, tempDir);
|
||||
testWriteCopyRead (50, 1, 250, tempDir);
|
||||
|
||||
ThreadPool::globalThreadPool().setNumThreads(numThreads);
|
||||
|
||||
cout << "ok\n" << endl;
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
cerr << "ERROR -- caught exception: " << e.what() << endl;
|
||||
assert (false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// Portions (c) 2012, Weta Digital Ltd
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef TESTCOPYMULTIPARTFILE_H_
|
||||
#define TESTCOPYMULTIPARTFILE_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
void testCopyMultiPartFile (const std::string & tempDir);
|
||||
|
||||
#endif /* TESTCOPYMULTIPARTFILE_H_ */
|
||||
229
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testCopyPixels.cpp
Normal file
229
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testCopyPixels.cpp
Normal file
@@ -0,0 +1,229 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include <ImfOutputFile.h>
|
||||
#include <ImfInputFile.h>
|
||||
#include <ImfChannelList.h>
|
||||
#include <ImfArray.h>
|
||||
#include <half.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
using namespace OPENEXR_IMF_NAMESPACE;
|
||||
using namespace std;
|
||||
using namespace IMATH_NAMESPACE;
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
void
|
||||
fillPixels (Array2D<half> &ph, int width, int height)
|
||||
{
|
||||
for (int y = 0; y < height; ++y)
|
||||
for (int x = 0; x < width; ++x)
|
||||
ph[y][x] = sin (double (x)) + sin (y * 0.5);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
writeCopyRead (const Array2D<half> &ph1,
|
||||
const char fileName1[],
|
||||
const char fileName2[],
|
||||
int width,
|
||||
int height,
|
||||
int xOffset,
|
||||
int yOffset,
|
||||
Compression comp)
|
||||
{
|
||||
//
|
||||
// Write the pixel data in ph1 to an image file using the
|
||||
// specified compression type and subsampling rates.
|
||||
// Then copy the image file using OutputFile::copyPixels()
|
||||
// Read the pixel data back from the copied file verify
|
||||
// that the data are the same as those in ph1.
|
||||
//
|
||||
|
||||
cout << "compression " << comp << ":" << flush;
|
||||
|
||||
Header hdr ((Box2i (V2i (0, 0), // display window
|
||||
V2i (width - 1, height -1))),
|
||||
(Box2i (V2i (xOffset, yOffset), // data window
|
||||
V2i (xOffset + width - 1, yOffset + height - 1))));
|
||||
|
||||
hdr.compression() = comp;
|
||||
hdr.channels().insert ("H", Channel (HALF, 1, 1));
|
||||
|
||||
{
|
||||
FrameBuffer fb;
|
||||
|
||||
fb.insert ("H", // name
|
||||
Slice (HALF, // type
|
||||
(char *) &ph1[-yOffset][-xOffset], // base
|
||||
sizeof (ph1[0][0]), // xStride
|
||||
sizeof (ph1[0][0]) * width, // yStride
|
||||
1, // xSampling
|
||||
1) // ySampling
|
||||
);
|
||||
|
||||
cout << " writing" << flush;
|
||||
|
||||
remove (fileName1);
|
||||
OutputFile out (fileName1, hdr);
|
||||
out.setFrameBuffer (fb);
|
||||
out.writePixels (height);
|
||||
}
|
||||
|
||||
{
|
||||
cout << " copying" << flush;
|
||||
|
||||
remove (fileName2);
|
||||
InputFile in (fileName1);
|
||||
OutputFile out (fileName2, in.header());
|
||||
out.copyPixels (in);
|
||||
}
|
||||
|
||||
{
|
||||
cout << " reading" << flush;
|
||||
|
||||
InputFile in1 (fileName1);
|
||||
InputFile in2 (fileName2);
|
||||
|
||||
const Box2i &dw = in2.header().dataWindow();
|
||||
int w = dw.max.x - dw.min.x + 1;
|
||||
int h = dw.max.y - dw.min.y + 1;
|
||||
int dx = dw.min.x;
|
||||
int dy = dw.min.y;
|
||||
|
||||
Array2D<half> ph1 (h, w);
|
||||
Array2D<half> ph2 (h, w);
|
||||
|
||||
FrameBuffer fb1;
|
||||
FrameBuffer fb2;
|
||||
|
||||
fb1.insert ("H", // name
|
||||
Slice (HALF, // type
|
||||
(char *) &ph1[-dy][-dx], // base
|
||||
sizeof (ph1[0][0]), // xStride
|
||||
sizeof (ph1[0][0]) * w, // yStride
|
||||
1, // xSampling
|
||||
1) // ySampling
|
||||
);
|
||||
|
||||
fb2.insert ("H", // name
|
||||
Slice (HALF, // type
|
||||
(char *) &ph2[-dy][-dx], // base
|
||||
sizeof (ph2[0][0]), // xStride
|
||||
sizeof (ph2[0][0]) * w, // yStride
|
||||
1, // xSampling
|
||||
1) // ySampling
|
||||
);
|
||||
|
||||
in1.setFrameBuffer (fb1);
|
||||
in1.readPixels (dw.min.y, dw.max.y);
|
||||
in2.setFrameBuffer (fb2);
|
||||
in2.readPixels (dw.min.y, dw.max.y);
|
||||
|
||||
cout << " comparing" << flush;
|
||||
|
||||
assert (in2.header().displayWindow() == hdr.displayWindow());
|
||||
assert (in2.header().dataWindow() == hdr.dataWindow());
|
||||
assert (in2.header().pixelAspectRatio() == hdr.pixelAspectRatio());
|
||||
assert (in2.header().screenWindowCenter() == hdr.screenWindowCenter());
|
||||
assert (in2.header().screenWindowWidth() == hdr.screenWindowWidth());
|
||||
assert (in2.header().lineOrder() == hdr.lineOrder());
|
||||
assert (in2.header().compression() == hdr.compression());
|
||||
assert (in2.header().channels() == hdr.channels());
|
||||
|
||||
for (int y = 0; y < h; ++y)
|
||||
for (int x = 0; x < w; ++x)
|
||||
assert (ph1[y][x] == ph2[y][x]);
|
||||
}
|
||||
|
||||
remove (fileName1);
|
||||
remove (fileName2);
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
writeCopyRead (const std::string &tempDir, const Array2D<half> &ph, int w, int h, int dx, int dy)
|
||||
{
|
||||
std::string filename1 = tempDir + "imf_test_copy1.exr";
|
||||
std::string filename2 = tempDir + "imf_test_copy2.exr";
|
||||
|
||||
for (int comp = 0; comp < NUM_COMPRESSION_METHODS; ++comp)
|
||||
{
|
||||
writeCopyRead (ph,
|
||||
filename1.c_str(),
|
||||
filename2.c_str(),
|
||||
w, h,
|
||||
dx, dy,
|
||||
Compression (comp));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
void
|
||||
testCopyPixels (const std::string &tempDir)
|
||||
{
|
||||
try
|
||||
{
|
||||
cout << "Testing fast pixel copying" << endl;
|
||||
|
||||
const int W = 371;
|
||||
const int H = 559;
|
||||
const int DX = 17;
|
||||
const int DY = 29;
|
||||
|
||||
Array2D<half> ph (H, W);
|
||||
|
||||
fillPixels (ph, W, H);
|
||||
writeCopyRead (tempDir, ph, W, H, 0, 0);
|
||||
writeCopyRead (tempDir, ph, W, H, 0, DY);
|
||||
writeCopyRead (tempDir, ph, W, H, DX, 0);
|
||||
writeCopyRead (tempDir, ph, W, H, DX, DY);
|
||||
|
||||
cout << "ok\n" << endl;
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
cerr << "ERROR -- caught exception: " << e.what() << endl;
|
||||
assert (false);
|
||||
}
|
||||
}
|
||||
41
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testCopyPixels.h
Normal file
41
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testCopyPixels.h
Normal file
@@ -0,0 +1,41 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
#include <string>
|
||||
|
||||
void testCopyPixels (const std::string &tempDir);
|
||||
|
||||
@@ -0,0 +1,279 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2004-2012, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include <ImfOutputFile.h>
|
||||
#include <ImfInputFile.h>
|
||||
#include <ImfChannelList.h>
|
||||
#include <ImfAttribute.h>
|
||||
#include <ImfIntAttribute.h>
|
||||
#include <ImfOpaqueAttribute.h>
|
||||
#include <ImfArray.h>
|
||||
#include <half.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
namespace IMF = OPENEXR_IMF_NAMESPACE;
|
||||
using namespace IMF;
|
||||
using namespace std;
|
||||
using namespace IMATH_NAMESPACE;
|
||||
|
||||
|
||||
//
|
||||
// Definition of the custom GlorpAttribute type.
|
||||
// Note that this must be in the same namespace as the definition
|
||||
//
|
||||
|
||||
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER
|
||||
|
||||
struct Glorp
|
||||
{
|
||||
int a, b;
|
||||
Glorp (int a = 0, int b = 0): a(a), b(b) {}
|
||||
};
|
||||
|
||||
|
||||
typedef TypedAttribute<Glorp> GlorpAttribute;
|
||||
template <> const char *GlorpAttribute::staticTypeName ();
|
||||
template <> void GlorpAttribute::writeValueTo (OStream &, int) const;
|
||||
template <> void GlorpAttribute::readValueFrom (IStream &, int, int);
|
||||
|
||||
template <>
|
||||
const char *
|
||||
GlorpAttribute::staticTypeName ()
|
||||
{
|
||||
return "glorp";
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
void
|
||||
GlorpAttribute::writeValueTo (OStream &os, int version) const
|
||||
{
|
||||
Xdr::write <StreamIO> (os, _value.a);
|
||||
Xdr::write <StreamIO> (os, _value.b);
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
void
|
||||
GlorpAttribute::readValueFrom (IStream &is, int size, int version)
|
||||
{
|
||||
Xdr::read <StreamIO> (is, _value.a);
|
||||
Xdr::read <StreamIO> (is, _value.b);
|
||||
}
|
||||
|
||||
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
void
|
||||
fillPixels (Array2D<float> &pf, int width, int height)
|
||||
{
|
||||
for (int y = 0; y < height; ++y)
|
||||
for (int x = 0; x < width; ++x)
|
||||
pf[y][x] = x % 10 + 10 * (y % 17);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
writeReadCustomAttr (const Array2D<float> &pf1,
|
||||
const char fileName[],
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
//
|
||||
// Tell the image file library about the custom GlorpAttribute type.
|
||||
//
|
||||
|
||||
GlorpAttribute::registerAttributeType();
|
||||
|
||||
//
|
||||
// Write an image file with two custom attributes:
|
||||
// "custom1", of type IntAttribute, and
|
||||
// "custom2", of type GlorpAttribute.
|
||||
//
|
||||
|
||||
{
|
||||
Header hdr (width, height);
|
||||
|
||||
hdr.insert ("custom1", IntAttribute (25));
|
||||
hdr.insert ("custom2", GlorpAttribute (Glorp (4, 9)));
|
||||
|
||||
hdr.channels().insert ("F", // name
|
||||
Channel (IMF::FLOAT, // type
|
||||
1, // xSampling
|
||||
1) // ySampling
|
||||
);
|
||||
|
||||
FrameBuffer fb;
|
||||
|
||||
fb.insert ("F", // name
|
||||
Slice (IMF::FLOAT, // type
|
||||
(char *) &pf1[0][0], // base
|
||||
sizeof (pf1[0][0]), // xStride
|
||||
sizeof (pf1[0][0]) * width, // yStride
|
||||
1, // xSampling
|
||||
1) // ySampling
|
||||
);
|
||||
|
||||
cout << "writing" << flush;
|
||||
|
||||
remove (fileName);
|
||||
OutputFile out (fileName, hdr);
|
||||
out.setFrameBuffer (fb);
|
||||
out.writePixels (height);
|
||||
}
|
||||
|
||||
//
|
||||
// Tell the image file library to forget the GlorpAttribute type.
|
||||
//
|
||||
|
||||
GlorpAttribute::unRegisterAttributeType();
|
||||
|
||||
//
|
||||
// Read the header back from the file:
|
||||
// "custom1" should come back as an IntAttribute, and
|
||||
// "custom2" should come back as an OpaqueAttribute.
|
||||
//
|
||||
|
||||
Header hdr;
|
||||
|
||||
{
|
||||
cout << " reading" << flush;
|
||||
|
||||
InputFile in (fileName);
|
||||
|
||||
const IntAttribute *c1;
|
||||
const OpaqueAttribute *c2;
|
||||
|
||||
c1 = in.header().findTypedAttribute <IntAttribute> ("custom1");
|
||||
c2 = in.header().findTypedAttribute <OpaqueAttribute> ("custom2");
|
||||
|
||||
assert (c1 != 0 && c1->value() == 25);
|
||||
assert (c2 != 0);
|
||||
|
||||
hdr = in.header();
|
||||
}
|
||||
|
||||
//
|
||||
// Tell the image file library to remember the custom GlorpAttribute type.
|
||||
//
|
||||
|
||||
GlorpAttribute::registerAttributeType();
|
||||
|
||||
//
|
||||
// Write a new image file using the header read back from
|
||||
// the previous file file. The two custom attributes should
|
||||
// be stored in the new file.
|
||||
//
|
||||
|
||||
{
|
||||
FrameBuffer fb;
|
||||
|
||||
fb.insert ("F", // name
|
||||
Slice (IMF::FLOAT, // type
|
||||
(char *) &pf1[0][0], // base
|
||||
sizeof (pf1[0][0]), // xStride
|
||||
sizeof (pf1[0][0]) * width, // yStride
|
||||
1, // xSampling
|
||||
1) // ySampling
|
||||
);
|
||||
|
||||
cout << " writing" << flush;
|
||||
|
||||
remove (fileName);
|
||||
OutputFile out (fileName, hdr);
|
||||
out.setFrameBuffer (fb);
|
||||
out.writePixels (height);
|
||||
}
|
||||
|
||||
//
|
||||
// Read the header of the new image file:
|
||||
// "custom1" should come back as an IntAttribute, and
|
||||
// "custom2" should come back as a GlorpAttribute.
|
||||
//
|
||||
|
||||
{
|
||||
cout << " reading" << flush;
|
||||
|
||||
InputFile in (fileName);
|
||||
|
||||
const IntAttribute *c1;
|
||||
const GlorpAttribute *c2;
|
||||
|
||||
c1 = in.header().findTypedAttribute <IntAttribute> ("custom1");
|
||||
c2 = in.header().findTypedAttribute <GlorpAttribute> ("custom2");
|
||||
|
||||
assert (c1 != 0 && c1->value() == 25);
|
||||
assert (c2 != 0 && c2->value().a == 4 && c2->value().b == 9);
|
||||
}
|
||||
|
||||
remove (fileName);
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
void
|
||||
testCustomAttributes (const std::string &tempDir)
|
||||
{
|
||||
try
|
||||
{
|
||||
cout << "Testing custom attributes" << endl;
|
||||
|
||||
const int W = 217;
|
||||
const int H = 197;
|
||||
|
||||
Array2D<float> pf (H, W);
|
||||
fillPixels (pf, W, H);
|
||||
|
||||
std::string filename = tempDir + "imf_test_custom_attr.exr";
|
||||
|
||||
writeReadCustomAttr (pf, filename.c_str(), W, H);
|
||||
|
||||
cout << "ok\n" << endl;
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
cerr << "ERROR -- caught exception: " << e.what() << endl;
|
||||
assert (false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
#include <string>
|
||||
|
||||
void testCustomAttributes (const std::string &tempDir);
|
||||
|
||||
@@ -0,0 +1,576 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "testDeepScanLineBasic.h"
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <ImfDeepScanLineInputFile.h>
|
||||
#include <ImfDeepScanLineOutputFile.h>
|
||||
#include <ImfDeepFrameBuffer.h>
|
||||
#include <ImfPartType.h>
|
||||
#include <ImfChannelList.h>
|
||||
#include <ImfArray.h>
|
||||
#include <IlmThreadPool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <vector>
|
||||
|
||||
namespace IMF = OPENEXR_IMF_NAMESPACE;
|
||||
using namespace IMF;
|
||||
using namespace std;
|
||||
using namespace IMATH_NAMESPACE;
|
||||
using namespace ILMTHREAD_NAMESPACE;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
const int width = 273;
|
||||
const int height = 173;
|
||||
const int minX = 10;
|
||||
const int minY = 11;
|
||||
const Box2i dataWindow(V2i(minX, minY), V2i(minX + width - 1, minY + height - 1));
|
||||
const Box2i displayWindow(V2i(0, 0), V2i(minX + width * 2, minY + height * 2));
|
||||
|
||||
vector<int> channelTypes;
|
||||
Array2D<unsigned int> sampleCount;
|
||||
Header header;
|
||||
|
||||
void generateRandomFile (const std::string filename,
|
||||
int channelCount,
|
||||
Compression compression,
|
||||
bool bulkWrite)
|
||||
{
|
||||
cout << "generating " << flush;
|
||||
header = Header(displayWindow, dataWindow,
|
||||
1,
|
||||
IMATH_NAMESPACE::V2f (0, 0),
|
||||
1,
|
||||
INCREASING_Y,
|
||||
compression);
|
||||
|
||||
cout << "compression " << compression << " " << flush;
|
||||
|
||||
//
|
||||
// Add channels.
|
||||
//
|
||||
|
||||
channelTypes.clear();
|
||||
|
||||
for (int i = 0; i < channelCount; i++)
|
||||
{
|
||||
int type = rand() % 3;
|
||||
stringstream ss;
|
||||
ss << i;
|
||||
string str = ss.str();
|
||||
if (type == 0)
|
||||
header.channels().insert(str, Channel(IMF::UINT));
|
||||
if (type == 1)
|
||||
header.channels().insert(str, Channel(IMF::HALF));
|
||||
if (type == 2)
|
||||
header.channels().insert(str, Channel(IMF::FLOAT));
|
||||
channelTypes.push_back(type);
|
||||
}
|
||||
|
||||
header.setType(DEEPSCANLINE);
|
||||
|
||||
Array<Array2D< void* > > data(channelCount);
|
||||
for (int i = 0; i < channelCount; i++)
|
||||
data[i].resizeErase(height, width);
|
||||
|
||||
sampleCount.resizeErase(height, width);
|
||||
|
||||
remove (filename.c_str());
|
||||
DeepScanLineOutputFile file(filename.c_str(), header, 8);
|
||||
|
||||
DeepFrameBuffer frameBuffer;
|
||||
|
||||
frameBuffer.insertSampleCountSlice (Slice (IMF::UINT, // type // 7
|
||||
(char *) (&sampleCount[0][0]
|
||||
- dataWindow.min.x
|
||||
- dataWindow.min.y * width), // base
|
||||
sizeof (unsigned int) * 1, // xStride
|
||||
sizeof (unsigned int) * width)); // yStride
|
||||
|
||||
for (int i = 0; i < channelCount; i++)
|
||||
{
|
||||
PixelType type;
|
||||
if (channelTypes[i] == 0)
|
||||
type = IMF::UINT;
|
||||
if (channelTypes[i] == 1)
|
||||
type = IMF::HALF;
|
||||
if (channelTypes[i] == 2)
|
||||
type = IMF::FLOAT;
|
||||
|
||||
stringstream ss;
|
||||
ss << i;
|
||||
string str = ss.str();
|
||||
|
||||
int sampleSize;
|
||||
if (channelTypes[i] == 0) sampleSize = sizeof (unsigned int);
|
||||
if (channelTypes[i] == 1) sampleSize = sizeof (half);
|
||||
if (channelTypes[i] == 2) sampleSize = sizeof (float);
|
||||
|
||||
int pointerSize = sizeof(char *);
|
||||
|
||||
frameBuffer.insert (str, // name // 6
|
||||
DeepSlice (type, // type // 7
|
||||
(char *) (&data[i][0][0]
|
||||
- dataWindow.min.x
|
||||
- dataWindow.min.y * width), // base // 8
|
||||
pointerSize * 1, // xStride// 9
|
||||
pointerSize * width, // yStride// 10
|
||||
sampleSize)); // sampleStride
|
||||
}
|
||||
|
||||
file.setFrameBuffer(frameBuffer);
|
||||
|
||||
cout << "writing " << flush;
|
||||
if (bulkWrite)
|
||||
{
|
||||
cout << "bulk " << flush;
|
||||
for (int i = 0; i < height; i++)
|
||||
{
|
||||
//
|
||||
// Fill in data at the last minute.
|
||||
//
|
||||
|
||||
for (int j = 0; j < width; j++)
|
||||
{
|
||||
sampleCount[i][j] = rand() % 10 + 1;
|
||||
for (int k = 0; k < channelCount; k++)
|
||||
{
|
||||
if (channelTypes[k] == 0)
|
||||
data[k][i][j] = new unsigned int[sampleCount[i][j]];
|
||||
if (channelTypes[k] == 1)
|
||||
data[k][i][j] = new half[sampleCount[i][j]];
|
||||
if (channelTypes[k] == 2)
|
||||
data[k][i][j] = new float[sampleCount[i][j]];
|
||||
for (int l = 0; l < sampleCount[i][j]; l++)
|
||||
{
|
||||
if (channelTypes[k] == 0)
|
||||
((unsigned int*)data[k][i][j])[l] = (i * width + j) % 2049;
|
||||
if (channelTypes[k] == 1)
|
||||
((half*)data[k][i][j])[l] = (i * width + j) % 2049;
|
||||
if (channelTypes[k] == 2)
|
||||
((float*)data[k][i][j])[l] = (i * width + j) % 2049;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
file.writePixels(height);
|
||||
}
|
||||
else
|
||||
{
|
||||
cout << "per-line " << flush;
|
||||
for (int i = 0; i < height; i++)
|
||||
{
|
||||
//
|
||||
// Fill in data at the last minute.
|
||||
//
|
||||
|
||||
for (int j = 0; j < width; j++)
|
||||
{
|
||||
sampleCount[i][j] = rand() % 10 + 1;
|
||||
for (int k = 0; k < channelCount; k++)
|
||||
{
|
||||
if (channelTypes[k] == 0)
|
||||
data[k][i][j] = new unsigned int[sampleCount[i][j]];
|
||||
if (channelTypes[k] == 1)
|
||||
data[k][i][j] = new half[sampleCount[i][j]];
|
||||
if (channelTypes[k] == 2)
|
||||
data[k][i][j] = new float[sampleCount[i][j]];
|
||||
for (int l = 0; l < sampleCount[i][j]; l++)
|
||||
{
|
||||
if (channelTypes[k] == 0)
|
||||
((unsigned int*)data[k][i][j])[l] = (i * width + j) % 2049;
|
||||
if (channelTypes[k] == 1)
|
||||
((half*)data[k][i][j])[l] = (i * width + j) % 2049;
|
||||
if (channelTypes[k] == 2)
|
||||
((float*)data[k][i][j])[l] = (i * width + j) % 2049;
|
||||
}
|
||||
}
|
||||
}
|
||||
file.writePixels(1);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < height; i++)
|
||||
for (int j = 0; j < width; j++)
|
||||
for (int k = 0; k < channelCount; k++)
|
||||
{
|
||||
if (channelTypes[k] == 0)
|
||||
delete[] (unsigned int*) data[k][i][j];
|
||||
if (channelTypes[k] == 1)
|
||||
delete[] (half*) data[k][i][j];
|
||||
if (channelTypes[k] == 2)
|
||||
delete[] (float*) data[k][i][j];
|
||||
}
|
||||
}
|
||||
|
||||
void readFile (const std::string & filename,
|
||||
int channelCount,
|
||||
bool bulkRead,
|
||||
bool randomChannels)
|
||||
{
|
||||
if(randomChannels)
|
||||
{
|
||||
cout << " reading random channels " << flush;
|
||||
}
|
||||
else
|
||||
{
|
||||
cout << " reading all channels " << flush;
|
||||
}
|
||||
|
||||
DeepScanLineInputFile file(filename.c_str(), 8);
|
||||
|
||||
const Header& fileHeader = file.header();
|
||||
assert (fileHeader.displayWindow() == header.displayWindow());
|
||||
assert (fileHeader.dataWindow() == header.dataWindow());
|
||||
assert (fileHeader.pixelAspectRatio() == header.pixelAspectRatio());
|
||||
assert (fileHeader.screenWindowCenter() == header.screenWindowCenter());
|
||||
assert (fileHeader.screenWindowWidth() == header.screenWindowWidth());
|
||||
assert (fileHeader.lineOrder() == header.lineOrder());
|
||||
assert (fileHeader.compression() == header.compression());
|
||||
assert (fileHeader.channels() == header.channels());
|
||||
assert (fileHeader.type() == header.type());
|
||||
|
||||
Array2D<unsigned int> localSampleCount;
|
||||
localSampleCount.resizeErase(height, width);
|
||||
Array<Array2D< void* > > data(channelCount);
|
||||
for (int i = 0; i < channelCount; i++)
|
||||
data[i].resizeErase(height, width);
|
||||
|
||||
DeepFrameBuffer frameBuffer;
|
||||
|
||||
frameBuffer.insertSampleCountSlice (Slice (IMF::UINT, // type // 7
|
||||
(char *) (&localSampleCount[0][0]
|
||||
- dataWindow.min.x
|
||||
- dataWindow.min.y * width), // base // 8)
|
||||
sizeof (unsigned int) * 1, // xStride// 9
|
||||
sizeof (unsigned int) * width)); // yStride// 10
|
||||
|
||||
vector<int> read_channel(channelCount);
|
||||
|
||||
|
||||
int channels_added=0;
|
||||
|
||||
for (int i = 0; i < channelCount; i++)
|
||||
{
|
||||
if(randomChannels)
|
||||
{
|
||||
read_channel[i] = rand() % 2;
|
||||
|
||||
}
|
||||
if(!randomChannels || read_channel[i]==1)
|
||||
{
|
||||
PixelType type;
|
||||
if (channelTypes[i] == 0)
|
||||
type = IMF::UINT;
|
||||
if (channelTypes[i] == 1)
|
||||
type = IMF::HALF;
|
||||
if (channelTypes[i] == 2)
|
||||
type = IMF::FLOAT;
|
||||
|
||||
stringstream ss;
|
||||
ss << i;
|
||||
string str = ss.str();
|
||||
|
||||
int sampleSize;
|
||||
if (channelTypes[i] == 0) sampleSize = sizeof (unsigned int);
|
||||
if (channelTypes[i] == 1) sampleSize = sizeof (half);
|
||||
if (channelTypes[i] == 2) sampleSize = sizeof (float);
|
||||
|
||||
int pointerSize = sizeof (char *);
|
||||
|
||||
frameBuffer.insert (str, // name // 6
|
||||
DeepSlice (type, // type // 7
|
||||
(char *) (&data[i][0][0]
|
||||
- dataWindow.min.x
|
||||
- dataWindow.min.y * width), // base // 8)
|
||||
pointerSize * 1, // xStride// 9
|
||||
pointerSize * width, // yStride// 10
|
||||
sampleSize)); // sampleStride
|
||||
channels_added++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(channels_added==0)
|
||||
{
|
||||
cout << "skipping " <<flush;
|
||||
return;
|
||||
}
|
||||
|
||||
file.setFrameBuffer(frameBuffer);
|
||||
|
||||
if (bulkRead)
|
||||
{
|
||||
cout << "bulk " << flush;
|
||||
file.readPixelSampleCounts(dataWindow.min.y, dataWindow.max.y);
|
||||
for (int i = 0; i < dataWindow.max.y - dataWindow.min.y + 1; i++)
|
||||
{
|
||||
int y = i + dataWindow.min.y;
|
||||
|
||||
for (int j = 0; j < width; j++)
|
||||
assert(localSampleCount[i][j] == sampleCount[i][j]);
|
||||
|
||||
for (int j = 0; j < width; j++)
|
||||
{
|
||||
for (int k = 0; k < channelCount; k++)
|
||||
{
|
||||
if(!randomChannels || read_channel[k]==1)
|
||||
{
|
||||
if (channelTypes[k] == 0)
|
||||
data[k][i][j] = new unsigned int[localSampleCount[i][j]];
|
||||
if (channelTypes[k] == 1)
|
||||
data[k][i][j] = new half[localSampleCount[i][j]];
|
||||
if (channelTypes[k] == 2)
|
||||
data[k][i][j] = new float[localSampleCount[i][j]];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
file.readPixels(dataWindow.min.y, dataWindow.max.y);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
cout << "per-line " << flush;
|
||||
for (int i = 0; i < dataWindow.max.y - dataWindow.min.y + 1; i++)
|
||||
{
|
||||
int y = i + dataWindow.min.y;
|
||||
file.readPixelSampleCounts(y);
|
||||
|
||||
for (int j = 0; j < width; j++)
|
||||
assert(localSampleCount[i][j] == sampleCount[i][j]);
|
||||
|
||||
for (int j = 0; j < width; j++)
|
||||
{
|
||||
for (int k = 0; k < channelCount; k++)
|
||||
{
|
||||
if( !randomChannels || read_channel[k]==1)
|
||||
{
|
||||
if (channelTypes[k] == 0)
|
||||
data[k][i][j] = new unsigned int[localSampleCount[i][j]];
|
||||
if (channelTypes[k] == 1)
|
||||
data[k][i][j] = new half[localSampleCount[i][j]];
|
||||
if (channelTypes[k] == 2)
|
||||
data[k][i][j] = new float[localSampleCount[i][j]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
file.readPixels(y);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < height; i++)
|
||||
for (int j = 0; j < width; j++)
|
||||
for (int k = 0; k < channelCount; k++)
|
||||
{
|
||||
if( !randomChannels || read_channel[k]==1 )
|
||||
{
|
||||
for (int l = 0; l < sampleCount[i][j]; l++)
|
||||
{
|
||||
if (channelTypes[k] == 0)
|
||||
{
|
||||
unsigned int* value = (unsigned int*)(data[k][i][j]);
|
||||
if (value[l] != (i * width + j) % 2049)
|
||||
cout << j << ", " << i << " error, should be "
|
||||
<< (i * width + j) % 2049 << ", is " << value[l]
|
||||
<< endl << flush;
|
||||
assert (value[l] == (i * width + j) % 2049);
|
||||
}
|
||||
if (channelTypes[k] == 1)
|
||||
{
|
||||
half* value = (half*)(data[k][i][j]);
|
||||
if (value[l] != (i * width + j) % 2049)
|
||||
cout << j << ", " << i << " error, should be "
|
||||
<< (i * width + j) % 2049 << ", is " << value[l]
|
||||
<< endl << flush;
|
||||
assert (((half*)(data[k][i][j]))[l] == (i * width + j) % 2049);
|
||||
}
|
||||
if (channelTypes[k] == 2)
|
||||
{
|
||||
float* value = (float*)(data[k][i][j]);
|
||||
if (value[l] != (i * width + j) % 2049)
|
||||
cout << j << ", " << i << " error, should be "
|
||||
<< (i * width + j) % 2049 << ", is " << value[l]
|
||||
<< endl << flush;
|
||||
assert (((float*)(data[k][i][j]))[l] == (i * width + j) % 2049);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < height; i++)
|
||||
for (int j = 0; j < width; j++)
|
||||
for (int k = 0; k < channelCount; k++)
|
||||
{
|
||||
if( !randomChannels || read_channel[k]==1 )
|
||||
{
|
||||
if (channelTypes[k] == 0)
|
||||
delete[] (unsigned int*) data[k][i][j];
|
||||
if (channelTypes[k] == 1)
|
||||
delete[] (half*) data[k][i][j];
|
||||
if (channelTypes[k] == 2)
|
||||
delete[] (float*) data[k][i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void readWriteTest(const std::string & tempDir, int channelCount, int testTimes)
|
||||
{
|
||||
cout << "Testing files with " << channelCount << " channels " << testTimes << " times."
|
||||
<< endl << flush;
|
||||
|
||||
std::string filename = tempDir + "imf_test_deep_scanline_basic.exr";
|
||||
|
||||
for (int i = 0; i < testTimes; i++)
|
||||
{
|
||||
int compressionIndex = i % 3;
|
||||
Compression compression;
|
||||
switch (compressionIndex)
|
||||
{
|
||||
case 0:
|
||||
compression = NO_COMPRESSION;
|
||||
break;
|
||||
case 1:
|
||||
compression = RLE_COMPRESSION;
|
||||
break;
|
||||
case 2:
|
||||
compression = ZIPS_COMPRESSION;
|
||||
break;
|
||||
}
|
||||
|
||||
generateRandomFile (filename, channelCount, compression, false);
|
||||
readFile (filename, channelCount, false , false );
|
||||
if (channelCount>1)
|
||||
readFile (filename, channelCount, false , true );
|
||||
remove (filename.c_str());
|
||||
cout << endl << flush;
|
||||
|
||||
generateRandomFile (filename, channelCount, compression, true);
|
||||
readFile (filename, channelCount, true , false );
|
||||
if (channelCount>1)
|
||||
readFile (filename, channelCount, true , true );
|
||||
remove (filename.c_str());
|
||||
cout << endl << flush;
|
||||
}
|
||||
}
|
||||
|
||||
void testCompressionTypeChecks()
|
||||
{
|
||||
Header h;
|
||||
h.setType(DEEPTILE);
|
||||
h.compression()=NO_COMPRESSION;
|
||||
h.sanityCheck();
|
||||
h.compression()=ZIPS_COMPRESSION;
|
||||
h.sanityCheck();
|
||||
h.compression()=RLE_COMPRESSION;
|
||||
h.sanityCheck();
|
||||
|
||||
cout << "accepted valid compression types\n";
|
||||
//
|
||||
// these should fail
|
||||
//
|
||||
try{
|
||||
h.compression()=ZIP_COMPRESSION;
|
||||
h.sanityCheck();
|
||||
assert(false);
|
||||
}catch(...){
|
||||
cout << "correctly identified bad compression setting (zip)\n";
|
||||
}
|
||||
try{
|
||||
h.compression()=B44_COMPRESSION;
|
||||
h.sanityCheck();
|
||||
assert(false);
|
||||
}catch(...){
|
||||
cout << "correctly identified bad compression setting (b44)\n";
|
||||
}
|
||||
try{
|
||||
h.compression()=B44A_COMPRESSION;
|
||||
h.sanityCheck();
|
||||
assert(false);
|
||||
}catch(...) {
|
||||
cout << "correctly identified bad compression setting (b44a)\n";
|
||||
}
|
||||
try{
|
||||
h.compression()=PXR24_COMPRESSION;
|
||||
h.sanityCheck();
|
||||
assert(false);
|
||||
}catch(...) {
|
||||
cout << "correctly identified bad compression setting (pxr24)\n";
|
||||
}
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
}; // namespace
|
||||
|
||||
void testDeepScanLineBasic (const std::string &tempDir)
|
||||
{
|
||||
try
|
||||
{
|
||||
cout << "\n\nTesting the DeepScanLineInput/OutputFile for basic use:\n" << endl;
|
||||
|
||||
srand(1);
|
||||
|
||||
int numThreads = ThreadPool::globalThreadPool().numThreads();
|
||||
ThreadPool::globalThreadPool().setNumThreads(4);
|
||||
|
||||
|
||||
testCompressionTypeChecks();
|
||||
|
||||
readWriteTest (tempDir, 1, 100);
|
||||
readWriteTest (tempDir, 3, 50);
|
||||
readWriteTest (tempDir,10, 10);
|
||||
|
||||
ThreadPool::globalThreadPool().setNumThreads(numThreads);
|
||||
|
||||
cout << "ok\n" << endl;
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
cerr << "ERROR -- caught exception: " << e.what() << endl;
|
||||
assert (false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef TESTDEEPSCANLINEBASIC_H_
|
||||
#define TESTDEEPSCANLINEBASIC_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
void testDeepScanLineBasic (const std::string &tempDir);
|
||||
|
||||
#endif /* TESTDEEPSCANLINEBASIC_H_ */
|
||||
@@ -0,0 +1,438 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "testDeepScanLineBasic.h"
|
||||
|
||||
#include "ImfDeepScanLineInputFile.h"
|
||||
#include "ImfDeepScanLineOutputFile.h"
|
||||
#include "ImfDeepFrameBuffer.h"
|
||||
#include "ImfPartType.h"
|
||||
#include "ImfChannelList.h"
|
||||
#include "ImfArray.h"
|
||||
#include "IlmThreadPool.h"
|
||||
|
||||
#include "tmpDir.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace IMF = OPENEXR_IMF_NAMESPACE;
|
||||
using namespace IMF;
|
||||
using namespace std;
|
||||
using namespace IMATH_NAMESPACE;
|
||||
using namespace ILMTHREAD_NAMESPACE;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
const int width = 8193;
|
||||
const int height = 1;
|
||||
const int minX = 0;
|
||||
const int minY = 0;
|
||||
const long numGib = 1; // number of GiB to allocate for huge test
|
||||
const Box2i dataWindow(V2i(minX, minY), V2i(minX + width - 1, minY + height - 1));
|
||||
const Box2i displayWindow(V2i(0, 0), V2i(minX + width * 2, minY + height * 2));
|
||||
|
||||
vector<int> channelTypes;
|
||||
Array2D<unsigned int> sampleCount;
|
||||
vector<unsigned char> storage; // actual pixel storage for entire image (effectively)
|
||||
|
||||
Header header;
|
||||
|
||||
void
|
||||
generateRandomFile (int channelCount,
|
||||
Compression compression,
|
||||
bool random_channel_data,
|
||||
const std::string & fn)
|
||||
{
|
||||
cout << "generating ... " << flush;
|
||||
header = Header(displayWindow, dataWindow,
|
||||
1,
|
||||
IMATH_NAMESPACE::V2f (0, 0),
|
||||
1,
|
||||
INCREASING_Y,
|
||||
compression);
|
||||
|
||||
cout << "compression " << compression << " " << flush;
|
||||
|
||||
//
|
||||
// Add channels.
|
||||
//
|
||||
|
||||
channelTypes.clear();
|
||||
|
||||
for (int i = 0; i < channelCount; i++)
|
||||
{
|
||||
int type = rand() % 3;
|
||||
stringstream ss;
|
||||
ss << i;
|
||||
string str = ss.str();
|
||||
if (type == 0)
|
||||
header.channels().insert(str, Channel(IMF::UINT));
|
||||
if (type == 1)
|
||||
header.channels().insert(str, Channel(IMF::HALF));
|
||||
if (type == 2)
|
||||
header.channels().insert(str, Channel(IMF::FLOAT));
|
||||
channelTypes.push_back(type);
|
||||
}
|
||||
|
||||
header.setType(DEEPSCANLINE);
|
||||
|
||||
Array<Array2D< void* > > data(channelCount);
|
||||
for (int i = 0; i < channelCount; i++)
|
||||
data[i].resizeErase(height, width);
|
||||
|
||||
sampleCount.resizeErase(height, width);
|
||||
|
||||
remove (fn.c_str());
|
||||
DeepScanLineOutputFile file (fn.c_str(), header, 8);
|
||||
|
||||
DeepFrameBuffer frameBuffer;
|
||||
|
||||
frameBuffer.insertSampleCountSlice (Slice (IMF::UINT, // type // 7
|
||||
(char *) (&sampleCount[0][0]
|
||||
- dataWindow.min.x
|
||||
- dataWindow.min.y * width), // base // 8
|
||||
sizeof (unsigned int) * 1, // xStride// 9
|
||||
sizeof (unsigned int) * width)); // yStride// 10
|
||||
|
||||
|
||||
// count total size of all pixels
|
||||
Int64 bytes_per_sample = 0;
|
||||
for (int i = 0; i < channelCount; i++)
|
||||
{
|
||||
PixelType type;
|
||||
if (channelTypes[i] == 0)
|
||||
type = IMF::UINT;
|
||||
if (channelTypes[i] == 1)
|
||||
type = IMF::HALF;
|
||||
if (channelTypes[i] == 2)
|
||||
type = IMF::FLOAT;
|
||||
|
||||
stringstream ss;
|
||||
ss << i;
|
||||
string str = ss.str();
|
||||
|
||||
int sampleSize;
|
||||
if (channelTypes[i] == 0) sampleSize = sizeof (unsigned int);
|
||||
if (channelTypes[i] == 1) sampleSize = sizeof (half);
|
||||
if (channelTypes[i] == 2) sampleSize = sizeof (float);
|
||||
|
||||
int pointerSize = sizeof(char *);
|
||||
|
||||
bytes_per_sample+=sampleSize;
|
||||
|
||||
frameBuffer.insert (str, // name // 6
|
||||
DeepSlice (type, // type // 7
|
||||
(char *) (&data[i][0][0]
|
||||
- dataWindow.min.x
|
||||
- dataWindow.min.y * width), // base // 8
|
||||
pointerSize * 1, // xStride// 9
|
||||
pointerSize * width, // yStride// 10
|
||||
sampleSize)); // sampleStride
|
||||
}
|
||||
|
||||
file.setFrameBuffer(frameBuffer);
|
||||
|
||||
cout << "writing file " << endl;
|
||||
|
||||
Int64 total_number_of_samples = 0;
|
||||
|
||||
// compute ideal number of samples per pixel assuming we want abotut 5GiB of data
|
||||
// int samples_per_pixel = int(5l*1024l*1024l*1024l/Int64(width*height)) / bytes_per_sample;
|
||||
|
||||
// compute ideal number of samples per pixel assuming we want abotut 15GiB of data
|
||||
int samples_per_pixel = int(numGib*1024l*1024l*1024l/Int64(width*height)) / bytes_per_sample;
|
||||
|
||||
cout << " generating approx. " << samples_per_pixel << " samples per pixel\n";
|
||||
|
||||
for (int i = 0; i < height; i++)
|
||||
{
|
||||
for (int j = 0; j < width; j++)
|
||||
{
|
||||
sampleCount[i][j] = (rand() % 4000) + (samples_per_pixel-2000);
|
||||
total_number_of_samples += sampleCount[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
cout << " total number of samples: " << total_number_of_samples << std::endl;
|
||||
cout << " storage required: " << total_number_of_samples*bytes_per_sample << " bytes (" <<
|
||||
((total_number_of_samples*bytes_per_sample)>>30) << "GiB)" << std::endl;
|
||||
|
||||
|
||||
//
|
||||
// storage layout scheme:
|
||||
// [Pixel1: [Channel1: [Sample1 Sample2 Sample...] ] [Channel2: [Sample1 Sample2...] ] [Channnel...] ]
|
||||
// [Pixel2: [Channel1: [Sample1 Sample2 Sample...] ] [Channel2: [Sample1 Sample2...] ] [Channnel...] ]
|
||||
// [Pixel...]
|
||||
//
|
||||
storage.resize(total_number_of_samples*bytes_per_sample);
|
||||
|
||||
|
||||
|
||||
Int64 write_pointer=0;
|
||||
|
||||
for (int i = 0; i < height; i++)
|
||||
{
|
||||
//
|
||||
// Fill in data at the last minute.
|
||||
//
|
||||
|
||||
|
||||
for (int j = 0; j < width; j++)
|
||||
{
|
||||
for (int k = 0; k < channelCount; k++)
|
||||
{
|
||||
data[k][i][j]=&storage[write_pointer];
|
||||
if (channelTypes[k] == 0)
|
||||
write_pointer+=sizeof(int)*sampleCount[i][j];
|
||||
if (channelTypes[k] == 1)
|
||||
write_pointer+=sizeof(half)*sampleCount[i][j];
|
||||
if (channelTypes[k] == 2)
|
||||
write_pointer+=sizeof(float)*sampleCount[i][j];
|
||||
|
||||
if(random_channel_data)
|
||||
{
|
||||
for (int l = 0; l < sampleCount[i][j]; l++)
|
||||
{
|
||||
if (channelTypes[k] == 0)
|
||||
((unsigned int*)data[k][i][j])[l] = rand();
|
||||
if (channelTypes[k] == 1)
|
||||
((half*)data[k][i][j])[l] = rand()/RAND_MAX;
|
||||
if (channelTypes[k] == 2)
|
||||
((float*)data[k][i][j])[l] = rand()/RAND_MAX;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int l = 0; l < sampleCount[i][j]; l++)
|
||||
{
|
||||
if (channelTypes[k] == 0)
|
||||
((unsigned int*)data[k][i][j])[l] = (i * width + j) % 2049;
|
||||
if (channelTypes[k] == 1)
|
||||
((half*)data[k][i][j])[l] = (i * width + j) % 2049;
|
||||
if (channelTypes[k] == 2)
|
||||
((float*)data[k][i][j])[l] = (i * width + j) % 2049;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
cout << " data prepared, writing ...";
|
||||
|
||||
file.writePixels(height);
|
||||
cout << " data written\n";
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
readFile (int channelCount, bool bulkRead, const std::string & fn)
|
||||
{
|
||||
cout << "reading \n" << flush;
|
||||
|
||||
DeepScanLineInputFile file (fn.c_str(), 8);
|
||||
|
||||
const Header& fileHeader = file.header();
|
||||
assert (fileHeader.displayWindow() == header.displayWindow());
|
||||
assert (fileHeader.dataWindow() == header.dataWindow());
|
||||
assert (fileHeader.pixelAspectRatio() == header.pixelAspectRatio());
|
||||
assert (fileHeader.screenWindowCenter() == header.screenWindowCenter());
|
||||
assert (fileHeader.screenWindowWidth() == header.screenWindowWidth());
|
||||
assert (fileHeader.lineOrder() == header.lineOrder());
|
||||
assert (fileHeader.compression() == header.compression());
|
||||
assert (fileHeader.channels() == header.channels());
|
||||
assert (fileHeader.type() == header.type());
|
||||
|
||||
Array2D<unsigned int> localSampleCount;
|
||||
localSampleCount.resizeErase(height, width);
|
||||
Array<Array2D< void* > > data(channelCount);
|
||||
for (int i = 0; i < channelCount; i++)
|
||||
data[i].resizeErase(height, width);
|
||||
|
||||
DeepFrameBuffer frameBuffer;
|
||||
|
||||
frameBuffer.insertSampleCountSlice (Slice (IMF::UINT, // type // 7
|
||||
(char *) (&localSampleCount[0][0]
|
||||
- dataWindow.min.x
|
||||
- dataWindow.min.y * width), // base // 8)
|
||||
sizeof (unsigned int) * 1, // xStride// 9
|
||||
sizeof (unsigned int) * width)); // yStride// 10
|
||||
|
||||
Int64 bytes_per_sample=0;
|
||||
|
||||
for (int i = 0; i < channelCount; i++)
|
||||
{
|
||||
PixelType type;
|
||||
if (channelTypes[i] == 0)
|
||||
type = IMF::UINT;
|
||||
if (channelTypes[i] == 1)
|
||||
type = IMF::HALF;
|
||||
if (channelTypes[i] == 2)
|
||||
type = IMF::FLOAT;
|
||||
|
||||
stringstream ss;
|
||||
ss << i;
|
||||
string str = ss.str();
|
||||
|
||||
int sampleSize;
|
||||
if (channelTypes[i] == 0) sampleSize = sizeof (unsigned int);
|
||||
if (channelTypes[i] == 1) sampleSize = sizeof (half);
|
||||
if (channelTypes[i] == 2) sampleSize = sizeof (float);
|
||||
|
||||
int pointerSize = sizeof (char *);
|
||||
|
||||
bytes_per_sample+=sampleSize;
|
||||
|
||||
frameBuffer.insert (str, // name // 6
|
||||
DeepSlice (type, // type // 7
|
||||
(char *) (&data[i][0][0]
|
||||
- dataWindow.min.x
|
||||
- dataWindow.min.y * width), // base // 8)
|
||||
pointerSize * 1, // xStride// 9
|
||||
pointerSize * width, // yStride// 10
|
||||
sampleSize)); // sampleStride
|
||||
}
|
||||
|
||||
file.setFrameBuffer(frameBuffer);
|
||||
|
||||
file.readPixelSampleCounts(dataWindow.min.y, dataWindow.max.y);
|
||||
Int64 total_pixel_count = 0;
|
||||
|
||||
for (int i = 0; i < dataWindow.max.y - dataWindow.min.y + 1; i++)
|
||||
{
|
||||
int y = i + dataWindow.min.y;
|
||||
|
||||
|
||||
for (int j = 0; j < width; j++)
|
||||
{
|
||||
assert(localSampleCount[i][j] == sampleCount[i][j]);
|
||||
total_pixel_count += localSampleCount[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
vector<char> localstorage(total_pixel_count*bytes_per_sample);
|
||||
|
||||
Int64 write_pointer=0;
|
||||
|
||||
for (int i = 0; i < height; i++)
|
||||
{
|
||||
//
|
||||
// Fill in data at the last minute.
|
||||
//
|
||||
|
||||
|
||||
for (int j = 0; j < width; j++)
|
||||
{
|
||||
for (int k = 0; k < channelCount; k++)
|
||||
{
|
||||
data[k][i][j]=&localstorage[write_pointer];
|
||||
if (channelTypes[k] == 0)
|
||||
write_pointer+=sizeof(int)*sampleCount[i][j];
|
||||
if (channelTypes[k] == 1)
|
||||
write_pointer+=sizeof(half)*sampleCount[i][j];
|
||||
if (channelTypes[k] == 2)
|
||||
write_pointer+=sizeof(float)*sampleCount[i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cout << "reading image data ... " << flush;
|
||||
|
||||
file.readPixels(dataWindow.min.y, dataWindow.max.y);
|
||||
|
||||
cout << " image read \n" << flush;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
readWriteTest (int channelCount,
|
||||
int testTimes,
|
||||
bool random_channel_data,
|
||||
const std::string & fn)
|
||||
{
|
||||
cout << "Testing files with " << channelCount << " channels " << testTimes << " times."
|
||||
<< endl << flush;
|
||||
for (int i = 0; i < testTimes; i++)
|
||||
{
|
||||
int compressionIndex = i % 3;
|
||||
Compression compression;
|
||||
switch (compressionIndex)
|
||||
{
|
||||
case 0:
|
||||
compression = NO_COMPRESSION;
|
||||
break;
|
||||
case 1:
|
||||
compression = RLE_COMPRESSION;
|
||||
break;
|
||||
case 2:
|
||||
compression = ZIPS_COMPRESSION;
|
||||
break;
|
||||
}
|
||||
|
||||
generateRandomFile (channelCount, compression, random_channel_data, fn);
|
||||
readFile (channelCount, false, fn);
|
||||
remove (fn.c_str());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}; // namespace
|
||||
|
||||
void testDeepScanLineHuge (const std::string & tempDir)
|
||||
{
|
||||
try
|
||||
{
|
||||
cout << "\n\nTesting the DeepScanLineInput/OutputFile for huge scanlines:\n" << endl;
|
||||
|
||||
srand(1);
|
||||
std::string fn = tempDir + "imf_test_deep_scanline_huge.exr";
|
||||
|
||||
readWriteTest (10, 5 , false, fn);
|
||||
readWriteTest (10, 5 , true, fn);
|
||||
cout << "ok\n" << endl;
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
cerr << "ERROR -- caught exception: " << e.what() << endl;
|
||||
assert (false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef TESTDEEPSCANLINEHUGE_H_
|
||||
#define TESTDEEPSCANLINEHUGE_H_
|
||||
|
||||
void testDeepScanLineHuge (const std::string & tempDir);
|
||||
|
||||
#endif /* TESTDEEPSCANLINEHUGE_H_ */
|
||||
@@ -0,0 +1,229 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2012, Weta Digital Ltd
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Weta Digital nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "testCompositeDeepScanLine.h"
|
||||
|
||||
#include <ImfDeepScanLineOutputFile.h>
|
||||
#include <ImfDeepScanLineInputFile.h>
|
||||
#include <ImfChannelList.h>
|
||||
#include <ImfPartType.h>
|
||||
#include <ImfDeepFrameBuffer.h>
|
||||
#include <ImfHeader.h>
|
||||
#include <ImfNamespace.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "tmpDir.h"
|
||||
|
||||
namespace{
|
||||
|
||||
const char source_filename[] = IMF_TMP_DIR "imf_test_multiple_read.exr";
|
||||
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
using std::flush;
|
||||
using std::vector;
|
||||
|
||||
using OPENEXR_IMF_NAMESPACE::Header;
|
||||
using OPENEXR_IMF_NAMESPACE::Channel;
|
||||
using OPENEXR_IMF_NAMESPACE::UINT;
|
||||
using OPENEXR_IMF_NAMESPACE::FLOAT;
|
||||
using OPENEXR_IMF_NAMESPACE::DEEPSCANLINE;
|
||||
using OPENEXR_IMF_NAMESPACE::ZIPS_COMPRESSION;
|
||||
using OPENEXR_IMF_NAMESPACE::DeepScanLineOutputFile;
|
||||
using OPENEXR_IMF_NAMESPACE::DeepScanLineInputFile;
|
||||
using OPENEXR_IMF_NAMESPACE::DeepFrameBuffer;
|
||||
using OPENEXR_IMF_NAMESPACE::Slice;
|
||||
using OPENEXR_IMF_NAMESPACE::DeepSlice;
|
||||
using IMATH_NAMESPACE::Box2i;
|
||||
|
||||
namespace IMF = OPENEXR_IMF_NAMESPACE;
|
||||
|
||||
static void
|
||||
make_file(const char * filename)
|
||||
{
|
||||
|
||||
int width=4;
|
||||
int height=48;
|
||||
|
||||
//
|
||||
// create a deep output file of widthxheight, where each pixel has 'y' samples,
|
||||
// each with value 'x'
|
||||
//
|
||||
|
||||
Header header( width,height);
|
||||
header.channels().insert("Z", Channel(IMF::FLOAT));
|
||||
header.compression()=ZIPS_COMPRESSION;
|
||||
header.setType(DEEPSCANLINE);
|
||||
|
||||
remove (filename);
|
||||
DeepScanLineOutputFile file(filename, header);
|
||||
|
||||
unsigned int sample_count;
|
||||
float sample;
|
||||
float * sample_ptr = &sample;
|
||||
|
||||
DeepFrameBuffer fb;
|
||||
|
||||
fb.insertSampleCountSlice(Slice(IMF::UINT,(char *)&sample_count));
|
||||
fb.insert("Z",DeepSlice(IMF::FLOAT,(char *) &sample_ptr));
|
||||
|
||||
|
||||
file.setFrameBuffer(fb);
|
||||
|
||||
for( int y=0 ; y < height ; y++ )
|
||||
{
|
||||
//
|
||||
// ensure each scanline contains a different number of samples,
|
||||
// with different values. We don't care that each sample has the same
|
||||
// value, or that each pixel on the scanline is identical
|
||||
//
|
||||
sample_count = y;
|
||||
sample = y+100.0;
|
||||
|
||||
file.writePixels(1);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void read_file(const char * filename)
|
||||
{
|
||||
DeepScanLineInputFile file(filename);
|
||||
|
||||
Box2i datawin = file.header().dataWindow();
|
||||
int width = datawin.size().x+1;
|
||||
int height = datawin.size().y+1;
|
||||
int x_offset = datawin.min.x;
|
||||
int y_offset = datawin.min.y;
|
||||
const char * channel = file.header().channels().begin().name();
|
||||
|
||||
vector<unsigned int> samplecounts(width);
|
||||
vector<float *> sample_pointers(width);
|
||||
vector<float> samples;
|
||||
|
||||
DeepFrameBuffer fb;
|
||||
|
||||
fb.insertSampleCountSlice(Slice(IMF::UINT,(char *) (&samplecounts[0]-x_offset) , sizeof(unsigned int)));
|
||||
|
||||
fb.insert( channel, DeepSlice(IMF::FLOAT,(char *) (&sample_pointers[0]-x_offset) , sizeof(float *),0,sizeof(float)) );
|
||||
|
||||
file.setFrameBuffer(fb);
|
||||
|
||||
for(int count=0;count<4000;count++)
|
||||
{
|
||||
int row = rand() % height + y_offset;
|
||||
|
||||
//
|
||||
// read row y (at random)
|
||||
//
|
||||
|
||||
file.readPixelSampleCounts(row,row);
|
||||
//
|
||||
// check that's correct, and also resize samples array
|
||||
//
|
||||
|
||||
int total_samples = 0;
|
||||
for(int i=0;i<width;i++)
|
||||
{
|
||||
|
||||
if( samplecounts[i]!= row)
|
||||
{
|
||||
cout << i << ", " << row << " error, sample counts hould be "
|
||||
<< row << ", is " << samplecounts[i]
|
||||
<< endl << flush;
|
||||
}
|
||||
|
||||
assert (samplecounts[i]== row);
|
||||
|
||||
total_samples+=samplecounts[i];
|
||||
}
|
||||
|
||||
samples.resize(total_samples);
|
||||
//
|
||||
// set pointers to point to the correct place
|
||||
//
|
||||
int total=0;
|
||||
for(int i=0 ; i<width && total < total_samples ; i++)
|
||||
{
|
||||
sample_pointers[i] = &samples[total];
|
||||
total+=samplecounts[i];
|
||||
}
|
||||
|
||||
//
|
||||
// read channel
|
||||
//
|
||||
|
||||
file.readPixels(row,row);
|
||||
|
||||
//
|
||||
// check
|
||||
//
|
||||
|
||||
for(int i=0;i<total_samples;i++)
|
||||
{
|
||||
if(samples[i]!=row+100.f)
|
||||
{
|
||||
cout << " sample " << i << " on row " << row << " error, shuold be "
|
||||
<< 100.f+row << " got " << samples[i] << endl;
|
||||
cout << flush;
|
||||
}
|
||||
assert(samples[i]==row+100.f);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testDeepScanLineMultipleRead(const std::string & tempDir)
|
||||
{
|
||||
|
||||
cout << "\n\nTesting random re-reads from deep scanline file:\n" << endl;
|
||||
|
||||
std::string source_filename = tempDir + "imf_test_multiple_read";
|
||||
srand(1);
|
||||
|
||||
make_file(source_filename.c_str());
|
||||
read_file(source_filename.c_str());
|
||||
remove(source_filename.c_str());
|
||||
|
||||
cout << " ok\n" << endl;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2012, Weta Digital Ltd
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Weta Digital nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef TESTDEEPSCANLINEMULTIPLEREAD_H_
|
||||
#define TESTDEEPSCANLINEMULTIPLEREAD_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
void testDeepScanLineMultipleRead(const std::string & tempDir);
|
||||
|
||||
#endif /* DEEPSCANLINEMULTIPLEREAD_H_ */
|
||||
761
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testDeepTiledBasic.cpp
Normal file
761
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testDeepTiledBasic.cpp
Normal file
@@ -0,0 +1,761 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "testDeepTiledBasic.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <ImfDeepTiledInputFile.h>
|
||||
#include <ImfDeepTiledOutputFile.h>
|
||||
#include <ImfChannelList.h>
|
||||
#include <ImfArray.h>
|
||||
#include <ImfPartType.h>
|
||||
#include <IlmThreadPool.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <vector>
|
||||
|
||||
namespace IMF = OPENEXR_IMF_NAMESPACE;
|
||||
using namespace IMF;
|
||||
using namespace IMATH_NAMESPACE;
|
||||
using namespace ILMTHREAD_NAMESPACE;
|
||||
using namespace std;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
const int width = 273;
|
||||
const int height = 169;
|
||||
const int minX = 10;
|
||||
const int minY = 11;
|
||||
const Box2i dataWindow(V2i(minX, minY), V2i(minX + width - 1, minY + height - 1));
|
||||
const Box2i displayWindow(V2i(0, 0), V2i(minX + width * 2, minY + height * 2));
|
||||
|
||||
vector<int> channelTypes;
|
||||
Array2D< Array2D<unsigned int> > sampleCountWhole;
|
||||
Header header;
|
||||
|
||||
void generateRandomFile (int channelCount,
|
||||
Compression compression,
|
||||
bool bulkWrite,
|
||||
bool relativeCoords,
|
||||
const std::string & filename)
|
||||
{
|
||||
if (relativeCoords)
|
||||
assert(bulkWrite == false);
|
||||
|
||||
cout << "generating " << flush;
|
||||
header = Header(displayWindow, dataWindow,
|
||||
1,
|
||||
IMATH_NAMESPACE::V2f (0, 0),
|
||||
1,
|
||||
INCREASING_Y,
|
||||
compression);
|
||||
cout << "compression " << compression << " " << flush;
|
||||
|
||||
//
|
||||
// Add channels.
|
||||
//
|
||||
|
||||
channelTypes.clear();
|
||||
|
||||
for (int i = 0; i < channelCount; i++)
|
||||
{
|
||||
int type = rand() % 3;
|
||||
stringstream ss;
|
||||
ss << i;
|
||||
string str = ss.str();
|
||||
if (type == 0)
|
||||
header.channels().insert(str, Channel(IMF::UINT));
|
||||
if (type == 1)
|
||||
header.channels().insert(str, Channel(IMF::HALF));
|
||||
if (type == 2)
|
||||
header.channels().insert(str, Channel(IMF::FLOAT));
|
||||
channelTypes.push_back(type);
|
||||
}
|
||||
|
||||
header.setType(DEEPTILE);
|
||||
header.setTileDescription(
|
||||
TileDescription(rand() % width + 1, rand() % height + 1, RIPMAP_LEVELS));
|
||||
|
||||
|
||||
//
|
||||
// Set up the output file
|
||||
//
|
||||
remove (filename.c_str());
|
||||
DeepTiledOutputFile file(filename.c_str(), header, 8);
|
||||
|
||||
DeepFrameBuffer frameBuffer;
|
||||
|
||||
Array<Array2D< void* > > data(channelCount);
|
||||
for (int i = 0; i < channelCount; i++)
|
||||
data[i].resizeErase(height, width);
|
||||
|
||||
Array2D<unsigned int> sampleCount;
|
||||
sampleCount.resizeErase(height, width);
|
||||
|
||||
cout << " tileSizeX " << file.tileXSize()
|
||||
<< " tileSizeY " << file.tileYSize() << " ";
|
||||
|
||||
sampleCountWhole.resizeErase(file.numYLevels(), file.numXLevels());
|
||||
for (int i = 0; i < sampleCountWhole.height(); i++)
|
||||
for (int j = 0; j < sampleCountWhole.width(); j++)
|
||||
sampleCountWhole[i][j].resizeErase(height, width);
|
||||
|
||||
int memOffset;
|
||||
if (relativeCoords)
|
||||
memOffset = 0;
|
||||
else
|
||||
memOffset = dataWindow.min.x + dataWindow.min.y * width;
|
||||
|
||||
frameBuffer.insertSampleCountSlice (Slice (IMF::UINT,
|
||||
(char *) (&sampleCount[0][0] - memOffset),
|
||||
sizeof (unsigned int) * 1,
|
||||
sizeof (unsigned int) * width,
|
||||
1, 1,
|
||||
0,
|
||||
relativeCoords,
|
||||
relativeCoords));
|
||||
|
||||
for (int i = 0; i < channelCount; i++)
|
||||
{
|
||||
PixelType type;
|
||||
if (channelTypes[i] == 0)
|
||||
type = IMF::UINT;
|
||||
if (channelTypes[i] == 1)
|
||||
type = IMF::HALF;
|
||||
if (channelTypes[i] == 2)
|
||||
type = IMF::FLOAT;
|
||||
|
||||
stringstream ss;
|
||||
ss << i;
|
||||
string str = ss.str();
|
||||
|
||||
int sampleSize;
|
||||
if (channelTypes[i] == 0) sampleSize = sizeof (unsigned int);
|
||||
if (channelTypes[i] == 1) sampleSize = sizeof (half);
|
||||
if (channelTypes[i] == 2) sampleSize = sizeof (float);
|
||||
|
||||
int pointerSize = sizeof (char *);
|
||||
|
||||
frameBuffer.insert (str,
|
||||
DeepSlice (type,
|
||||
(char *) (&data[i][0][0] - memOffset),
|
||||
pointerSize * 1,
|
||||
pointerSize * width,
|
||||
sampleSize,
|
||||
1, 1,
|
||||
0,
|
||||
relativeCoords,
|
||||
relativeCoords));
|
||||
}
|
||||
|
||||
file.setFrameBuffer(frameBuffer);
|
||||
|
||||
cout << "writing " << flush;
|
||||
|
||||
if (bulkWrite)
|
||||
cout << "bulk " << flush;
|
||||
else
|
||||
{
|
||||
if (relativeCoords == false)
|
||||
cout << "per-tile " << flush;
|
||||
else
|
||||
cout << "per-tile with relative coordinates " << flush;
|
||||
}
|
||||
|
||||
for (int ly = 0; ly < file.numYLevels(); ly++)
|
||||
for (int lx = 0; lx < file.numXLevels(); lx++)
|
||||
{
|
||||
Box2i dataWindowL = file.dataWindowForLevel(lx, ly);
|
||||
|
||||
if (bulkWrite)
|
||||
{
|
||||
//
|
||||
// Bulk write (without relative coordinates).
|
||||
//
|
||||
|
||||
for (int j = 0; j < file.numYTiles(ly); j++)
|
||||
{
|
||||
for (int i = 0; i < file.numXTiles(lx); i++)
|
||||
{
|
||||
Box2i box = file.dataWindowForTile(i, j, lx, ly);
|
||||
for (int y = box.min.y; y <= box.max.y; y++)
|
||||
for (int x = box.min.x; x <= box.max.x; x++)
|
||||
{
|
||||
int dwy = y - dataWindowL.min.y;
|
||||
int dwx = x - dataWindowL.min.x;
|
||||
sampleCount[dwy][dwx] = rand() % 10 + 1;
|
||||
sampleCountWhole[ly][lx][dwy][dwx] = sampleCount[dwy][dwx];
|
||||
for (int k = 0; k < channelCount; k++)
|
||||
{
|
||||
if (channelTypes[k] == 0)
|
||||
data[k][dwy][dwx] = new unsigned int[sampleCount[dwy][dwx]];
|
||||
if (channelTypes[k] == 1)
|
||||
data[k][dwy][dwx] = new half[sampleCount[dwy][dwx]];
|
||||
if (channelTypes[k] == 2)
|
||||
data[k][dwy][dwx] = new float[sampleCount[dwy][dwx]];
|
||||
for (int l = 0; l < sampleCount[dwy][dwx]; l++)
|
||||
{
|
||||
if (channelTypes[k] == 0)
|
||||
((unsigned int*)data[k][dwy][dwx])[l] = (dwy * width + dwx) % 2049;
|
||||
if (channelTypes[k] == 1)
|
||||
((half*)data[k][dwy][dwx])[l] = (dwy* width + dwx) % 2049;
|
||||
if (channelTypes[k] == 2)
|
||||
((float*)data[k][dwy][dwx])[l] = (dwy * width + dwx) % 2049;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
file.writeTiles(0, file.numXTiles(lx) - 1, 0, file.numYTiles(ly) - 1, lx, ly);
|
||||
}
|
||||
else if (bulkWrite == false)
|
||||
{
|
||||
if (relativeCoords == false)
|
||||
{
|
||||
//
|
||||
// Per-tile write without relative coordinates.
|
||||
//
|
||||
|
||||
for (int j = 0; j < file.numYTiles(ly); j++)
|
||||
{
|
||||
for (int i = 0; i < file.numXTiles(lx); i++)
|
||||
{
|
||||
Box2i box = file.dataWindowForTile(i, j, lx, ly);
|
||||
for (int y = box.min.y; y <= box.max.y; y++)
|
||||
for (int x = box.min.x; x <= box.max.x; x++)
|
||||
{
|
||||
int dwy = y - dataWindowL.min.y;
|
||||
int dwx = x - dataWindowL.min.x;
|
||||
sampleCount[dwy][dwx] = rand() % 10 + 1;
|
||||
sampleCountWhole[ly][lx][dwy][dwx] = sampleCount[dwy][dwx];
|
||||
for (int k = 0; k < channelCount; k++)
|
||||
{
|
||||
if (channelTypes[k] == 0)
|
||||
data[k][dwy][dwx] = new unsigned int[sampleCount[dwy][dwx]];
|
||||
if (channelTypes[k] == 1)
|
||||
data[k][dwy][dwx] = new half[sampleCount[dwy][dwx]];
|
||||
if (channelTypes[k] == 2)
|
||||
data[k][dwy][dwx] = new float[sampleCount[dwy][dwx]];
|
||||
for (int l = 0; l < sampleCount[dwy][dwx]; l++)
|
||||
{
|
||||
if (channelTypes[k] == 0)
|
||||
((unsigned int*)data[k][dwy][dwx])[l] = (dwy * width + dwx) % 2049;
|
||||
if (channelTypes[k] == 1)
|
||||
((half*)data[k][dwy][dwx])[l] = (dwy* width + dwx) % 2049;
|
||||
if (channelTypes[k] == 2)
|
||||
((float*)data[k][dwy][dwx])[l] = (dwy * width + dwx) % 2049;
|
||||
}
|
||||
}
|
||||
}
|
||||
file.writeTile(i, j, lx, ly);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (relativeCoords)
|
||||
{
|
||||
//
|
||||
// Per-tile write with relative coordinates.
|
||||
//
|
||||
|
||||
for (int j = 0; j < file.numYTiles(ly); j++)
|
||||
{
|
||||
for (int i = 0; i < file.numXTiles(lx); i++)
|
||||
{
|
||||
Box2i box = file.dataWindowForTile(i, j, lx, ly);
|
||||
for (int y = box.min.y; y <= box.max.y; y++)
|
||||
for (int x = box.min.x; x <= box.max.x; x++)
|
||||
{
|
||||
int dwy = y - dataWindowL.min.y;
|
||||
int dwx = x - dataWindowL.min.x;
|
||||
int ty = y - box.min.y;
|
||||
int tx = x - box.min.x;
|
||||
sampleCount[ty][tx] = rand() % 10 + 1;
|
||||
sampleCountWhole[ly][lx][dwy][dwx] = sampleCount[ty][tx];
|
||||
for (int k = 0; k < channelCount; k++)
|
||||
{
|
||||
if (channelTypes[k] == 0)
|
||||
data[k][ty][tx] = new unsigned int[sampleCount[ty][tx]];
|
||||
if (channelTypes[k] == 1)
|
||||
data[k][ty][tx] = new half[sampleCount[ty][tx]];
|
||||
if (channelTypes[k] == 2)
|
||||
data[k][ty][tx] = new float[sampleCount[ty][tx]];
|
||||
for (int l = 0; l < sampleCount[ty][tx]; l++)
|
||||
{
|
||||
if (channelTypes[k] == 0)
|
||||
((unsigned int*)data[k][ty][tx])[l] =
|
||||
(dwy * width + dwx) % 2049;
|
||||
if (channelTypes[k] == 1)
|
||||
((half*)data[k][ty][tx])[l] =
|
||||
(dwy * width + dwx) % 2049;
|
||||
if (channelTypes[k] == 2)
|
||||
((float*)data[k][ty][tx])[l] =
|
||||
(dwy * width + dwx) % 2049;
|
||||
}
|
||||
}
|
||||
}
|
||||
file.writeTile(i, j, lx, ly);
|
||||
|
||||
for (int y = box.min.y; y <= box.max.y; y++)
|
||||
for (int x = box.min.x; x <= box.max.x; x++)
|
||||
for (int k = 0; k < channelCount; k++)
|
||||
{
|
||||
int ty = y - box.min.y;
|
||||
int tx = x - box.min.x;
|
||||
if (channelTypes[k] == 0)
|
||||
delete[] (unsigned int*) data[k][ty][tx];
|
||||
if (channelTypes[k] == 1)
|
||||
delete[] (half*) data[k][ty][tx];
|
||||
if (channelTypes[k] == 2)
|
||||
delete[] (float*) data[k][ty][tx];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (relativeCoords == false)
|
||||
{
|
||||
for (int i = 0; i < file.levelHeight(ly); i++)
|
||||
for (int j = 0; j < file.levelWidth(lx); j++)
|
||||
for (int k = 0; k < channelCount; k++)
|
||||
{
|
||||
if (channelTypes[k] == 0)
|
||||
delete[] (unsigned int*) data[k][i][j];
|
||||
if (channelTypes[k] == 1)
|
||||
delete[] (half*) data[k][i][j];
|
||||
if (channelTypes[k] == 2)
|
||||
delete[] (float*) data[k][i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void checkValue (void* sampleRawData,
|
||||
int sampleCount,
|
||||
int channelType,
|
||||
int dwx,
|
||||
int dwy)
|
||||
{
|
||||
for (int l = 0; l < sampleCount; l++)
|
||||
{
|
||||
if (channelType == 0)
|
||||
{
|
||||
unsigned int* value = (unsigned int*)(sampleRawData);
|
||||
if (value[l] != (dwy * width + dwx) % 2049)
|
||||
cout << dwx << ", " << dwy << " error, should be "
|
||||
<< (dwy * width + dwx) % 2049 << ", is " << value[l]
|
||||
<< endl << flush;
|
||||
assert (value[l] == (dwy * width + dwx) % 2049);
|
||||
}
|
||||
if (channelType == 1)
|
||||
{
|
||||
half* value = (half*)(sampleRawData);
|
||||
if (value[l] != (dwy * width + dwx) % 2049)
|
||||
cout << dwx << ", " << dwy << " error, should be "
|
||||
<< (dwy * width + dwx) % 2049 << ", is " << value[l]
|
||||
<< endl << flush;
|
||||
assert (value[l] == (dwy * width + dwx) % 2049);
|
||||
}
|
||||
if (channelType == 2)
|
||||
{
|
||||
float* value = (float*)(sampleRawData);
|
||||
if (value[l] != (dwy * width + dwx) % 2049)
|
||||
cout << dwx << ", " << dwy << " error, should be "
|
||||
<< (dwy * width + dwx) % 2049 << ", is " << value[l]
|
||||
<< endl << flush;
|
||||
assert (value[l] == (dwy * width + dwx) % 2049);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void readFile (int channelCount,
|
||||
bool bulkRead,
|
||||
bool relativeCoords,
|
||||
const std::string & filename)
|
||||
{
|
||||
if (relativeCoords)
|
||||
assert(bulkRead == false);
|
||||
|
||||
cout << "reading " << flush;
|
||||
|
||||
DeepTiledInputFile file (filename.c_str(), 4);
|
||||
|
||||
const Header& fileHeader = file.header();
|
||||
assert (fileHeader.displayWindow() == header.displayWindow());
|
||||
assert (fileHeader.dataWindow() == header.dataWindow());
|
||||
assert (fileHeader.pixelAspectRatio() == header.pixelAspectRatio());
|
||||
assert (fileHeader.screenWindowCenter() == header.screenWindowCenter());
|
||||
assert (fileHeader.screenWindowWidth() == header.screenWindowWidth());
|
||||
assert (fileHeader.lineOrder() == header.lineOrder());
|
||||
assert (fileHeader.compression() == header.compression());
|
||||
assert (fileHeader.channels() == header.channels());
|
||||
assert (fileHeader.type() == header.type());
|
||||
assert (fileHeader.tileDescription() == header.tileDescription());
|
||||
|
||||
Array2D<unsigned int> localSampleCount;
|
||||
localSampleCount.resizeErase(height, width);
|
||||
Array<Array2D< void* > > data(channelCount);
|
||||
for (int i = 0; i < channelCount; i++)
|
||||
data[i].resizeErase(height, width);
|
||||
|
||||
DeepFrameBuffer frameBuffer;
|
||||
|
||||
int memOffset;
|
||||
if (relativeCoords)
|
||||
memOffset = 0;
|
||||
else
|
||||
memOffset = dataWindow.min.x + dataWindow.min.y * width;
|
||||
frameBuffer.insertSampleCountSlice (Slice (IMF::UINT,
|
||||
(char *) (&localSampleCount[0][0] - memOffset),
|
||||
sizeof (unsigned int) * 1,
|
||||
sizeof (unsigned int) * width,
|
||||
1, 1,
|
||||
0,
|
||||
relativeCoords,
|
||||
relativeCoords));
|
||||
|
||||
for (int i = 0; i < channelCount; i++)
|
||||
{
|
||||
PixelType type;
|
||||
if (channelTypes[i] == 0)
|
||||
type = IMF::UINT;
|
||||
if (channelTypes[i] == 1)
|
||||
type = IMF::HALF;
|
||||
if (channelTypes[i] == 2)
|
||||
type = IMF::FLOAT;
|
||||
|
||||
stringstream ss;
|
||||
ss << i;
|
||||
string str = ss.str();
|
||||
|
||||
int sampleSize;
|
||||
if (channelTypes[i] == 0) sampleSize = sizeof (unsigned int);
|
||||
if (channelTypes[i] == 1) sampleSize = sizeof (half);
|
||||
if (channelTypes[i] == 2) sampleSize = sizeof (float);
|
||||
|
||||
int pointerSize = sizeof (char *);
|
||||
|
||||
frameBuffer.insert (str,
|
||||
DeepSlice (type,
|
||||
(char *) (&data[i][0][0] - memOffset),
|
||||
pointerSize * 1,
|
||||
pointerSize * width,
|
||||
sampleSize,
|
||||
1, 1,
|
||||
0,
|
||||
relativeCoords,
|
||||
relativeCoords));
|
||||
}
|
||||
|
||||
file.setFrameBuffer(frameBuffer);
|
||||
|
||||
if (bulkRead)
|
||||
cout << "bulk " << flush;
|
||||
else
|
||||
{
|
||||
if (relativeCoords == false)
|
||||
cout << "per-tile " << flush;
|
||||
else
|
||||
cout << "per-tile with relative coordinates " << flush;
|
||||
}
|
||||
|
||||
for (int ly = 0; ly < file.numYLevels(); ly++)
|
||||
for (int lx = 0; lx < file.numXLevels(); lx++)
|
||||
{
|
||||
Box2i dataWindowL = file.dataWindowForLevel(lx, ly);
|
||||
|
||||
if (bulkRead)
|
||||
{
|
||||
//
|
||||
// Testing bulk read (without relative coordinates).
|
||||
//
|
||||
|
||||
file.readPixelSampleCounts(0, file.numXTiles(lx) - 1, 0, file.numYTiles(ly) - 1, lx, ly);
|
||||
|
||||
for (int i = 0; i < file.numYTiles(ly); i++)
|
||||
{
|
||||
for (int j = 0; j < file.numXTiles(lx); j++)
|
||||
{
|
||||
Box2i box = file.dataWindowForTile(j, i, lx, ly);
|
||||
for (int y = box.min.y; y <= box.max.y; y++)
|
||||
for (int x = box.min.x; x <= box.max.x; x++)
|
||||
{
|
||||
int dwy = y - dataWindowL.min.y;
|
||||
int dwx = x - dataWindowL.min.x;
|
||||
assert(localSampleCount[dwy][dwx] == sampleCountWhole[ly][lx][dwy][dwx]);
|
||||
|
||||
for (int k = 0; k < channelTypes.size(); k++)
|
||||
{
|
||||
if (channelTypes[k] == 0)
|
||||
data[k][dwy][dwx] = new unsigned int[localSampleCount[dwy][dwx]];
|
||||
if (channelTypes[k] == 1)
|
||||
data[k][dwy][dwx] = new half[localSampleCount[dwy][dwx]];
|
||||
if (channelTypes[k] == 2)
|
||||
data[k][dwy][dwx] = new float[localSampleCount[dwy][dwx]];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
file.readTiles(0, file.numXTiles(lx) - 1, 0, file.numYTiles(ly) - 1, lx, ly);
|
||||
}
|
||||
else if (bulkRead == false)
|
||||
{
|
||||
if (relativeCoords == false)
|
||||
{
|
||||
//
|
||||
// Testing per-tile read without relative coordinates.
|
||||
//
|
||||
|
||||
for (int i = 0; i < file.numYTiles(ly); i++)
|
||||
{
|
||||
for (int j = 0; j < file.numXTiles(lx); j++)
|
||||
{
|
||||
file.readPixelSampleCount(j, i, lx, ly);
|
||||
|
||||
Box2i box = file.dataWindowForTile(j, i, lx, ly);
|
||||
for (int y = box.min.y; y <= box.max.y; y++)
|
||||
for (int x = box.min.x; x <= box.max.x; x++)
|
||||
{
|
||||
int dwy = y - dataWindowL.min.y;
|
||||
int dwx = x - dataWindowL.min.x;
|
||||
assert(localSampleCount[dwy][dwx] == sampleCountWhole[ly][lx][dwy][dwx]);
|
||||
|
||||
for (int k = 0; k < channelTypes.size(); k++)
|
||||
{
|
||||
if (channelTypes[k] == 0)
|
||||
data[k][dwy][dwx] = new unsigned int[localSampleCount[dwy][dwx]];
|
||||
if (channelTypes[k] == 1)
|
||||
data[k][dwy][dwx] = new half[localSampleCount[dwy][dwx]];
|
||||
if (channelTypes[k] == 2)
|
||||
data[k][dwy][dwx] = new float[localSampleCount[dwy][dwx]];
|
||||
}
|
||||
}
|
||||
|
||||
file.readTile(j, i, lx, ly);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (relativeCoords)
|
||||
{
|
||||
//
|
||||
// Testing per-tile read with relative coordinates.
|
||||
//
|
||||
|
||||
for (int i = 0; i < file.numYTiles(ly); i++)
|
||||
{
|
||||
for (int j = 0; j < file.numXTiles(lx); j++)
|
||||
{
|
||||
file.readPixelSampleCount(j, i, lx, ly);
|
||||
|
||||
Box2i box = file.dataWindowForTile(j, i, lx, ly);
|
||||
for (int y = box.min.y; y <= box.max.y; y++)
|
||||
for (int x = box.min.x; x <= box.max.x; x++)
|
||||
{
|
||||
int dwy = y - dataWindowL.min.y;
|
||||
int dwx = x - dataWindowL.min.x;
|
||||
int ty = y - box.min.y;
|
||||
int tx = x - box.min.x;
|
||||
assert(localSampleCount[ty][tx] == sampleCountWhole[ly][lx][dwy][dwx]);
|
||||
|
||||
for (int k = 0; k < channelTypes.size(); k++)
|
||||
{
|
||||
if (channelTypes[k] == 0)
|
||||
data[k][ty][tx] = new unsigned int[localSampleCount[ty][tx]];
|
||||
if (channelTypes[k] == 1)
|
||||
data[k][ty][tx] = new half[localSampleCount[ty][tx]];
|
||||
if (channelTypes[k] == 2)
|
||||
data[k][ty][tx] = new float[localSampleCount[ty][tx]];
|
||||
}
|
||||
}
|
||||
|
||||
file.readTile(j, i, lx, ly);
|
||||
|
||||
for (int y = box.min.y; y <= box.max.y; y++)
|
||||
for (int x = box.min.x; x <= box.max.x; x++)
|
||||
{
|
||||
int dwy = y - dataWindowL.min.y;
|
||||
int dwx = x - dataWindowL.min.x;
|
||||
int ty = y - box.min.y;
|
||||
int tx = x - box.min.x;
|
||||
|
||||
for (int k = 0; k < channelTypes.size(); k++)
|
||||
{
|
||||
checkValue(data[k][ty][tx],
|
||||
localSampleCount[ty][tx],
|
||||
channelTypes[k],
|
||||
dwx, dwy);
|
||||
if (channelTypes[k] == 0)
|
||||
delete[] (unsigned int*) data[k][ty][tx];
|
||||
if (channelTypes[k] == 1)
|
||||
delete[] (half*) data[k][ty][tx];
|
||||
if (channelTypes[k] == 2)
|
||||
delete[] (float*) data[k][ty][tx];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (relativeCoords == false)
|
||||
{
|
||||
for (int i = 0; i < file.levelHeight(ly); i++)
|
||||
for (int j = 0; j < file.levelWidth(lx); j++)
|
||||
for (int k = 0; k < channelCount; k++)
|
||||
{
|
||||
for (int l = 0; l < localSampleCount[i][j]; l++)
|
||||
{
|
||||
if (channelTypes[k] == 0)
|
||||
{
|
||||
unsigned int* value = (unsigned int*)(data[k][i][j]);
|
||||
if (value[l] != (i * width + j) % 2049)
|
||||
cout << j << ", " << i << " error, should be "
|
||||
<< (i * width + j) % 2049 << ", is " << value[l]
|
||||
<< endl << flush;
|
||||
assert (value[l] == (i * width + j) % 2049);
|
||||
}
|
||||
if (channelTypes[k] == 1)
|
||||
{
|
||||
half* value = (half*)(data[k][i][j]);
|
||||
if (value[l] != (i * width + j) % 2049)
|
||||
cout << j << ", " << i << " error, should be "
|
||||
<< (i * width + j) % 2049 << ", is " << value[l]
|
||||
<< endl << flush;
|
||||
assert (((half*)(data[k][i][j]))[l] == (i * width + j) % 2049);
|
||||
}
|
||||
if (channelTypes[k] == 2)
|
||||
{
|
||||
float* value = (float*)(data[k][i][j]);
|
||||
if (value[l] != (i * width + j) % 2049)
|
||||
cout << j << ", " << i << " error, should be "
|
||||
<< (i * width + j) % 2049 << ", is " << value[l]
|
||||
<< endl << flush;
|
||||
assert (((float*)(data[k][i][j]))[l] == (i * width + j) % 2049);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < file.levelHeight(ly); i++)
|
||||
for (int j = 0; j < file.levelWidth(lx); j++)
|
||||
for (int k = 0; k < channelCount; k++)
|
||||
{
|
||||
if (channelTypes[k] == 0)
|
||||
delete[] (unsigned int*) data[k][i][j];
|
||||
if (channelTypes[k] == 1)
|
||||
delete[] (half*) data[k][i][j];
|
||||
if (channelTypes[k] == 2)
|
||||
delete[] (float*) data[k][i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void readWriteTestWithAbsoluateCoordinates (int channelCount,
|
||||
int testTimes,
|
||||
const std::string & tempDir)
|
||||
{
|
||||
cout << "Testing files with " << channelCount
|
||||
<< " channels, using absolute coordinates "
|
||||
<< testTimes << " times."
|
||||
<< endl << flush;
|
||||
|
||||
std::string fn = tempDir + "imf_test_deep_tiled_basic.exr";
|
||||
|
||||
for (int i = 0; i < testTimes; i++)
|
||||
{
|
||||
int compressionIndex = i % 3;
|
||||
Compression compression;
|
||||
switch (compressionIndex)
|
||||
{
|
||||
case 0:
|
||||
compression = NO_COMPRESSION;
|
||||
break;
|
||||
case 1:
|
||||
compression = RLE_COMPRESSION;
|
||||
break;
|
||||
case 2:
|
||||
compression = ZIPS_COMPRESSION;
|
||||
break;
|
||||
}
|
||||
|
||||
generateRandomFile (channelCount, compression, false, false, fn);
|
||||
readFile (channelCount, false, false, fn);
|
||||
remove (fn.c_str());
|
||||
cout << endl << flush;
|
||||
|
||||
generateRandomFile (channelCount, compression, true, false, fn);
|
||||
readFile (channelCount, true, false, fn);
|
||||
remove (fn.c_str());
|
||||
cout << endl << flush;
|
||||
|
||||
generateRandomFile (channelCount, compression, false, true, fn);
|
||||
readFile (channelCount, false, true, fn);
|
||||
remove (fn.c_str());
|
||||
cout << endl << flush;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void testDeepTiledBasic (const std::string & tempDir)
|
||||
{
|
||||
try
|
||||
{
|
||||
cout << "Testing the DeepTiledInput/OutputFile for basic use" << endl;
|
||||
|
||||
srand(1);
|
||||
|
||||
int numThreads = ThreadPool::globalThreadPool().numThreads();
|
||||
ThreadPool::globalThreadPool().setNumThreads(2);
|
||||
|
||||
readWriteTestWithAbsoluateCoordinates ( 1, 2, tempDir);
|
||||
readWriteTestWithAbsoluateCoordinates ( 3, 2, tempDir);
|
||||
readWriteTestWithAbsoluateCoordinates (10, 2, tempDir);
|
||||
|
||||
ThreadPool::globalThreadPool().setNumThreads(numThreads);
|
||||
|
||||
cout << "ok\n" << endl;
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
cerr << "ERROR -- caught exception: " << e.what() << endl;
|
||||
assert (false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef TESTDEEPTILEDBASIC_H_
|
||||
#define TESTDEEPTILEDBASIC_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
void testDeepTiledBasic (const std::string & tempDir);
|
||||
|
||||
#endif /* TESTDEEPTILEDBASIC_H_ */
|
||||
@@ -0,0 +1,543 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2009-2014 DreamWorks Animation LLC.
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of DreamWorks Animation nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <half.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <ImfDwaCompressorSimd.h>
|
||||
#include <ImfSystemSpecific.h>
|
||||
#include <ImathRandom.h>
|
||||
#include <iostream>
|
||||
#include <assert.h>
|
||||
|
||||
using namespace OPENEXR_IMF_NAMESPACE;
|
||||
using namespace IMATH_NAMESPACE;
|
||||
using namespace std;
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
void
|
||||
dumpBuffer (const SimdAlignedBuffer64f &buffer)
|
||||
{
|
||||
for (int i=0; i<8; ++i)
|
||||
{
|
||||
for (int j=0; j<8; ++j)
|
||||
{
|
||||
cout << buffer._buffer[i*8+j] << " ";
|
||||
}
|
||||
cout << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
compareBuffer (const SimdAlignedBuffer64f &src,
|
||||
const SimdAlignedBuffer64f &dst,
|
||||
const float errThresh)
|
||||
{
|
||||
for (int i=0; i<64; ++i)
|
||||
{
|
||||
double diff = fabs(src._buffer[i] - dst._buffer[i]);
|
||||
|
||||
if (diff > errThresh)
|
||||
{
|
||||
cout << scientific;
|
||||
cout << "Error exceeded threshold on element " << i << endl;
|
||||
cout << " diff: " << diff << endl;
|
||||
cout << "Goal (src): " << scientific << endl;
|
||||
dumpBuffer(src);
|
||||
cout << "Test (dst): " << endl;
|
||||
dumpBuffer(dst);
|
||||
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
compareBufferRelative (const SimdAlignedBuffer64f &src,
|
||||
const SimdAlignedBuffer64f &dst,
|
||||
const float relErrThresh,
|
||||
const float absErrThresh)
|
||||
{
|
||||
for (int i=0; i<64; ++i)
|
||||
{
|
||||
double diff = fabs(src._buffer[i] - dst._buffer[i]);
|
||||
double relDiff = diff / fabs(src._buffer[i]);
|
||||
|
||||
if (relDiff > relErrThresh && diff > absErrThresh)
|
||||
{
|
||||
cout << scientific;
|
||||
cout << "Error exceeded threshold on element " << i << endl;
|
||||
cout << " diff: " << diff << " relErr: " << fixed << 100.0*relDiff << " %" << endl;
|
||||
cout << "Goal (src): " << scientific << endl;
|
||||
dumpBuffer(src);
|
||||
cout << "Test (dst): " << endl;
|
||||
dumpBuffer(dst);
|
||||
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Test that we can round trip CSC data with reasonable precision
|
||||
//
|
||||
void
|
||||
testCsc()
|
||||
{
|
||||
const int numIter = 1000000;
|
||||
Rand48 rand48(0);
|
||||
SimdAlignedBuffer64f orig[3];
|
||||
SimdAlignedBuffer64f test[3];
|
||||
|
||||
cout << " Color Space Conversion Round Trip " << endl;
|
||||
cout << " csc709Forward64() - 64 x csc709Inverse()" << endl;
|
||||
for (int iter=0; iter<numIter; ++iter)
|
||||
{
|
||||
for (int i=0; i<64; ++i)
|
||||
{
|
||||
test[0]._buffer[i] = orig[0]._buffer[i] = rand48.nextf();
|
||||
test[1]._buffer[i] = orig[1]._buffer[i] = rand48.nextf();
|
||||
test[2]._buffer[i] = orig[2]._buffer[i] = rand48.nextf();
|
||||
}
|
||||
|
||||
csc709Forward64(test[0]._buffer, test[1]._buffer, test[2]._buffer);
|
||||
for (int i=0; i<64; ++i)
|
||||
{
|
||||
csc709Inverse(test[0]._buffer[i], test[1]._buffer[i], test[2]._buffer[i]);
|
||||
}
|
||||
|
||||
compareBuffer(orig[0], test[0], 1e-3);
|
||||
compareBuffer(orig[1], test[1], 1e-3);
|
||||
compareBuffer(orig[2], test[2], 1e-3);
|
||||
|
||||
} // iter
|
||||
|
||||
cout << " csc709Forward64() - csc709Inverse64()" << endl;
|
||||
for (int iter=0; iter<numIter; ++iter)
|
||||
{
|
||||
for (int i=0; i<64; ++i)
|
||||
{
|
||||
test[0]._buffer[i] = orig[0]._buffer[i] = rand48.nextf();
|
||||
test[1]._buffer[i] = orig[1]._buffer[i] = rand48.nextf();
|
||||
test[2]._buffer[i] = orig[2]._buffer[i] = rand48.nextf();
|
||||
}
|
||||
|
||||
csc709Forward64(test[0]._buffer, test[1]._buffer, test[2]._buffer);
|
||||
csc709Inverse64(test[0]._buffer, test[1]._buffer, test[2]._buffer);
|
||||
|
||||
compareBuffer(orig[0], test[0], 1e-3);
|
||||
compareBuffer(orig[1], test[1], 1e-3);
|
||||
compareBuffer(orig[2], test[2], 1e-3);
|
||||
|
||||
} // iter
|
||||
}
|
||||
|
||||
//
|
||||
// Test interleaving two byte arrays
|
||||
//
|
||||
void
|
||||
testInterleave()
|
||||
{
|
||||
const int bufferLen = 100000;
|
||||
const int randomNumIter = 10000;
|
||||
const int lengthNumIter = 128;
|
||||
Rand48 rand48(0);
|
||||
char *srcA = new char[bufferLen];
|
||||
char *srcB = new char[bufferLen];
|
||||
char *dst = new char[2*bufferLen];
|
||||
char *test = new char[2*bufferLen];
|
||||
|
||||
cout << " Byte Interleaving " << endl;
|
||||
|
||||
for (int i=0; i<bufferLen; ++i)
|
||||
{
|
||||
srcA[i] = (char)rand48.nextf(0.0, 255.0);
|
||||
srcB[i] = (char)rand48.nextf(0.0, 255.0);
|
||||
dst[2*i] = srcA[i];
|
||||
dst[2*i+1] = srcB[i];
|
||||
}
|
||||
|
||||
for (int iter=0; iter<randomNumIter; ++iter)
|
||||
{
|
||||
memset(test, 0, 2*bufferLen);
|
||||
|
||||
int offset = (int)rand48.nextf(0.0, bufferLen/2);
|
||||
int len = (int)rand48.nextf(1.0, bufferLen - 1 - offset);
|
||||
|
||||
interleaveByte2( test+2*offset, srcA+offset, srcB+offset, len);
|
||||
for (int i=0; i<len; ++i) {
|
||||
assert( test[2*offset + 2*i] == dst[2*offset + 2*i]);
|
||||
assert( test[2*offset + 2*i + 1] == dst[2*offset + 2*i + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Test increasing length buffers, with varying alignment
|
||||
// on all the buffers.
|
||||
//
|
||||
for (int len=1; len<lengthNumIter; ++len)
|
||||
{
|
||||
for (int offset=0; offset<16*16*16; ++offset)
|
||||
{
|
||||
int offsetA = offset % 16;
|
||||
int offsetB = (offset / 16) % 16;
|
||||
int offsetTest = (offset / 256) % 16;
|
||||
|
||||
memset(srcA, 255, bufferLen);
|
||||
memset(srcB, 255, bufferLen);
|
||||
memset(dst, 0, 2*bufferLen);
|
||||
memset(test, 0, 2*bufferLen);
|
||||
|
||||
char *a = srcA + offsetA;
|
||||
char *b = srcB + offsetB;
|
||||
char *out = test + offsetTest;
|
||||
|
||||
for (int i=0; i<len; ++i)
|
||||
{
|
||||
a[i] = (char)rand48.nextf(0.0, 255.0);
|
||||
b[i] = (char)rand48.nextf(0.0, 255.0);
|
||||
|
||||
dst[2*i] = a[i];
|
||||
dst[2*i+1] = b[i];
|
||||
}
|
||||
|
||||
interleaveByte2(out, a, b, len);
|
||||
|
||||
for (int i=0; i<2*len+8; ++i)
|
||||
{
|
||||
assert( dst[2*i] == out[2*i] );
|
||||
assert( dst[2*i+1] == out[2*i+1] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete[] srcA;
|
||||
delete[] srcB;
|
||||
delete[] dst;
|
||||
delete[] test;
|
||||
}
|
||||
|
||||
//
|
||||
// Test that we can route trip DCT data with reasonable precision
|
||||
//
|
||||
void
|
||||
testDct()
|
||||
{
|
||||
const int numIter = 1000000;
|
||||
Rand48 rand48(0);
|
||||
SimdAlignedBuffer64f orig;
|
||||
SimdAlignedBuffer64f test;
|
||||
|
||||
cout << " DCT Round Trip " << endl;
|
||||
for (int iter=0; iter<numIter; ++iter)
|
||||
{
|
||||
for (int i=0; i<64; ++i)
|
||||
{
|
||||
orig._buffer[i] = test._buffer[i] = rand48.nextf();
|
||||
}
|
||||
|
||||
dctForward8x8(test._buffer);
|
||||
dctInverse8x8_scalar<0>(test._buffer);
|
||||
|
||||
compareBufferRelative(orig, test, .02, 1e-3);
|
||||
}
|
||||
|
||||
cout << " Inverse, DC Only" << endl;
|
||||
for (int iter=0; iter<numIter; ++iter)
|
||||
{
|
||||
orig._buffer[0] = test._buffer[0] = rand48.nextf();
|
||||
for (int i=1; i<64; ++i)
|
||||
{
|
||||
orig._buffer[i] = test._buffer[i] = 0;
|
||||
}
|
||||
|
||||
dctInverse8x8_scalar<0>(orig._buffer);
|
||||
dctInverse8x8DcOnly(test._buffer);
|
||||
|
||||
compareBufferRelative(orig, test, .01, 1e-6);
|
||||
}
|
||||
|
||||
|
||||
#define INVERSE_DCT_SCALAR_TEST_N(_func, _n, _desc) \
|
||||
cout << " " << _desc << endl; \
|
||||
for (int iter=0; iter<numIter; ++iter) \
|
||||
{ \
|
||||
for (int i=0; i<64; ++i) \
|
||||
{ \
|
||||
if (i < 8*(8-_n)) \
|
||||
{ \
|
||||
orig._buffer[i] = test._buffer[i] = rand48.nextf(); \
|
||||
} else { \
|
||||
orig._buffer[i] = test._buffer[i] = 0; \
|
||||
} \
|
||||
} \
|
||||
dctInverse8x8_scalar<0>(orig._buffer); \
|
||||
_func<_n>(test._buffer); \
|
||||
compareBufferRelative(orig, test, .01, 1e-6); \
|
||||
}
|
||||
|
||||
cout << " Inverse, Scalar: " << endl;
|
||||
INVERSE_DCT_SCALAR_TEST_N(dctInverse8x8_scalar, 0, "8x8")
|
||||
INVERSE_DCT_SCALAR_TEST_N(dctInverse8x8_scalar, 1, "7x8")
|
||||
INVERSE_DCT_SCALAR_TEST_N(dctInverse8x8_scalar, 2, "6x8")
|
||||
INVERSE_DCT_SCALAR_TEST_N(dctInverse8x8_scalar, 3, "5x8")
|
||||
INVERSE_DCT_SCALAR_TEST_N(dctInverse8x8_scalar, 4, "4x8")
|
||||
INVERSE_DCT_SCALAR_TEST_N(dctInverse8x8_scalar, 5, "3x8")
|
||||
INVERSE_DCT_SCALAR_TEST_N(dctInverse8x8_scalar, 6, "2x8")
|
||||
INVERSE_DCT_SCALAR_TEST_N(dctInverse8x8_scalar, 7, "1x8")
|
||||
|
||||
CpuId cpuid;
|
||||
if (cpuid.sse2)
|
||||
{
|
||||
cout << " Inverse, SSE2: " << endl;
|
||||
INVERSE_DCT_SCALAR_TEST_N(dctInverse8x8_sse2, 0, "8x8")
|
||||
INVERSE_DCT_SCALAR_TEST_N(dctInverse8x8_sse2, 1, "7x8")
|
||||
INVERSE_DCT_SCALAR_TEST_N(dctInverse8x8_sse2, 2, "6x8")
|
||||
INVERSE_DCT_SCALAR_TEST_N(dctInverse8x8_sse2, 3, "5x8")
|
||||
INVERSE_DCT_SCALAR_TEST_N(dctInverse8x8_sse2, 4, "4x8")
|
||||
INVERSE_DCT_SCALAR_TEST_N(dctInverse8x8_sse2, 5, "3x8")
|
||||
INVERSE_DCT_SCALAR_TEST_N(dctInverse8x8_sse2, 6, "2x8")
|
||||
INVERSE_DCT_SCALAR_TEST_N(dctInverse8x8_sse2, 7, "1x8")
|
||||
}
|
||||
|
||||
if (cpuid.avx)
|
||||
{
|
||||
cout << " Inverse, AVX: " << endl;
|
||||
INVERSE_DCT_SCALAR_TEST_N(dctInverse8x8_avx, 0, "8x8")
|
||||
INVERSE_DCT_SCALAR_TEST_N(dctInverse8x8_avx, 1, "7x8")
|
||||
INVERSE_DCT_SCALAR_TEST_N(dctInverse8x8_avx, 2, "6x8")
|
||||
INVERSE_DCT_SCALAR_TEST_N(dctInverse8x8_avx, 3, "5x8")
|
||||
INVERSE_DCT_SCALAR_TEST_N(dctInverse8x8_avx, 4, "4x8")
|
||||
INVERSE_DCT_SCALAR_TEST_N(dctInverse8x8_avx, 5, "3x8")
|
||||
INVERSE_DCT_SCALAR_TEST_N(dctInverse8x8_avx, 6, "2x8")
|
||||
INVERSE_DCT_SCALAR_TEST_N(dctInverse8x8_avx, 7, "1x8")
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Test FLOAT -> HALF conversion, mostly for F16C enabled processors
|
||||
//
|
||||
void
|
||||
testFloatToHalf()
|
||||
{
|
||||
cout << " FLOAT -> HALF conversion" << endl;
|
||||
|
||||
const int numIter = 1000000;
|
||||
Rand48 rand48(0);
|
||||
SimdAlignedBuffer64f src;
|
||||
SimdAlignedBuffer64us dst;
|
||||
|
||||
cout << " convertFloatToHalf64_scalar()" << endl;
|
||||
for (int iter=0; iter<numIter; ++iter)
|
||||
{
|
||||
for (int i=0; i<64; ++i)
|
||||
{
|
||||
if (i < 32)
|
||||
{
|
||||
src._buffer[i] = (float)140000*(rand48.nextf()-.5);
|
||||
} else
|
||||
{
|
||||
src._buffer[i] = (float)(rand48.nextf()-.5);
|
||||
}
|
||||
dst._buffer[i] = 0;
|
||||
}
|
||||
|
||||
convertFloatToHalf64_scalar(dst._buffer, src._buffer);
|
||||
|
||||
for (int i=0; i<64; ++i)
|
||||
{
|
||||
half value = (half)src._buffer[i];
|
||||
if (value.bits() != dst._buffer[i])
|
||||
{
|
||||
cout << src._buffer[i] << " -> " << dst._buffer[i]
|
||||
<< " expected " << value.bits() << endl;
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CpuId cpuid;
|
||||
if (cpuid.avx && cpuid.f16c)
|
||||
{
|
||||
cout << " convertFloatToHalf64_f16c()" << endl;
|
||||
for (int iter=0; iter<numIter; ++iter)
|
||||
{
|
||||
for (int i=0; i<64; ++i)
|
||||
{
|
||||
if (i < 32)
|
||||
{
|
||||
src._buffer[i] = (float)140000*(rand48.nextf()-.5);
|
||||
}
|
||||
else
|
||||
{
|
||||
src._buffer[i] = (float)(rand48.nextf()-.5);
|
||||
}
|
||||
dst._buffer[i] = 0;
|
||||
}
|
||||
|
||||
convertFloatToHalf64_f16c(dst._buffer, src._buffer);
|
||||
|
||||
for (int i=0; i<64; ++i)
|
||||
{
|
||||
half value = (half)src._buffer[i];
|
||||
if (value.bits() != dst._buffer[i])
|
||||
{
|
||||
cout << src._buffer[i] << " -> " << dst._buffer[i]
|
||||
<< " expected " << value.bits() << endl;
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Test ZigZag reordering + HALF -> FLOAT conversion
|
||||
//
|
||||
void
|
||||
testFromHalfZigZag()
|
||||
{
|
||||
SimdAlignedBuffer64us src;
|
||||
SimdAlignedBuffer64f dst;
|
||||
|
||||
cout << " ZigZag re-ordering with HALF -> FLOAT conversion" << endl;
|
||||
|
||||
// First off, simple check to see that the reordering is working
|
||||
// This pattern, when converted, should give 0.0 - 63.0 as floats
|
||||
// in order.
|
||||
unsigned short pattern[] = {
|
||||
0x0000, 0x3c00, 0x4800, 0x4c00, 0x4880, 0x4000, 0x4200, 0x4900,
|
||||
0x4c40, 0x4e00, 0x5000, 0x4e40, 0x4c80, 0x4980, 0x4400, 0x4500,
|
||||
0x4a00, 0x4cc0, 0x4e80, 0x5020, 0x5100, 0x5200, 0x5120, 0x5040,
|
||||
0x4ec0, 0x4d00, 0x4a80, 0x4600, 0x4700, 0x4b00, 0x4d40, 0x4f00,
|
||||
0x5060, 0x5140, 0x5220, 0x5300, 0x5320, 0x5240, 0x5160, 0x5080,
|
||||
0x4f40, 0x4d80, 0x4b80, 0x4dc0, 0x4f80, 0x50a0, 0x5180, 0x5260,
|
||||
0x5340, 0x5360, 0x5280, 0x51a0, 0x50c0, 0x4fc0, 0x50e0, 0x51c0,
|
||||
0x52a0, 0x5380, 0x53a0, 0x52c0, 0x51e0, 0x52e0, 0x53c0, 0x53e0
|
||||
};
|
||||
|
||||
cout << " fromHalfZigZag_scaler()" << endl;
|
||||
for (int i=0; i<64; ++i)
|
||||
{
|
||||
src._buffer[i] = pattern[i];
|
||||
}
|
||||
fromHalfZigZag_scalar(src._buffer, dst._buffer);
|
||||
for (int i=0; i<64; ++i)
|
||||
{
|
||||
if ( fabsf(dst._buffer[i] - (float)i) > 1e-5 )
|
||||
{
|
||||
cout << "At index " << i << ": ";
|
||||
cout << "expecting " << (float)i << "; got " << dst._buffer[i] << endl;
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
// Then compare the two implementations, if supported
|
||||
CpuId cpuid;
|
||||
if (cpuid.avx && cpuid.f16c)
|
||||
{
|
||||
const int numIter = 1000000;
|
||||
Rand48 rand48(0);
|
||||
half h;
|
||||
SimdAlignedBuffer64f dstF16c;
|
||||
|
||||
cout << " fromHalfZigZag_f16c()" << endl;
|
||||
|
||||
for (int iter=0; iter<numIter; ++iter)
|
||||
{
|
||||
for (int i=0; i<64; ++i)
|
||||
{
|
||||
if (i < 32)
|
||||
{
|
||||
h = (half)(140000.*(rand48.nextf() - .5));
|
||||
}
|
||||
else
|
||||
{
|
||||
h = (half)(rand48.nextf() - .5);
|
||||
}
|
||||
src._buffer[i] = h.bits();
|
||||
}
|
||||
|
||||
fromHalfZigZag_scalar(src._buffer, dst._buffer);
|
||||
fromHalfZigZag_f16c(src._buffer, dstF16c._buffer);
|
||||
|
||||
for (int i=0; i<64; ++i)
|
||||
{
|
||||
if ( fabsf(dst._buffer[i] - dstF16c._buffer[i]) > 1e-5 )
|
||||
{
|
||||
cout << "At index " << i << ": ";
|
||||
cout << "expecting " << dst._buffer[i] << "; got "
|
||||
<< dstF16c._buffer[i] << endl;
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
} // iter
|
||||
} // f16c
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
void
|
||||
testDwaCompressorSimd (const string&)
|
||||
{
|
||||
cout << "SIMD helper functions for DwaCompressor:" << endl;
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
testCsc();
|
||||
testInterleave();
|
||||
testFloatToHalf();
|
||||
testFromHalfZigZag();
|
||||
|
||||
testDct();
|
||||
|
||||
}
|
||||
catch (const exception &e)
|
||||
{
|
||||
cout << "unexpected exception: " << e.what() << endl;
|
||||
assert (false);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
cout << "unexpected exception" << endl;
|
||||
assert (false);
|
||||
}
|
||||
|
||||
cout << "ok\n" << endl;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2009-2014 DreamWorks Animation LLC.
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of DreamWorks Animation nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef TESTDWACOMPRESSORSIMD_H_
|
||||
#define TESTDWACOMPRESSORSIMD_H_
|
||||
|
||||
#include <string>
|
||||
void testDwaCompressorSimd(const std::string&);
|
||||
|
||||
#endif /* TESTDWACOMPRESSORSIMD_H_ */
|
||||
|
||||
566
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testExistingStreams.cpp
Normal file
566
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testExistingStreams.cpp
Normal file
@@ -0,0 +1,566 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2004-2012, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include <ImfRgbaFile.h>
|
||||
#include <ImfTiledRgbaFile.h>
|
||||
#include <ImfMultiPartInputFile.h>
|
||||
#include <ImfMultiPartOutputFile.h>
|
||||
#include <ImfPartType.h>
|
||||
#include <ImfInputPart.h>
|
||||
#include <ImfOutputPart.h>
|
||||
#include <ImfStdIO.h>
|
||||
#include <ImfArray.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include "Iex.h"
|
||||
#include <errno.h>
|
||||
|
||||
#include <vector>
|
||||
#include <ImfChannelList.h>
|
||||
|
||||
|
||||
using namespace OPENEXR_IMF_NAMESPACE;
|
||||
using namespace std;
|
||||
using namespace IMATH_NAMESPACE;
|
||||
|
||||
namespace {
|
||||
|
||||
void
|
||||
fillPixels1 (Array2D<Rgba> &pixels, int w, int h)
|
||||
{
|
||||
for (int y = 0; y < h; ++y)
|
||||
{
|
||||
for (int x = 0; x < w; ++x)
|
||||
{
|
||||
Rgba &p = pixels[y][x];
|
||||
|
||||
p.r = (x & 1);
|
||||
p.g = ((x + y) & 1);
|
||||
p.b = (y & 1);
|
||||
p.a = (p.r + p.b + p.g) / 3.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
fillPixels2 (Array2D<Rgba> &pixels, int w, int h)
|
||||
{
|
||||
for (int y = 0; y < h; ++y)
|
||||
{
|
||||
for (int x = 0; x < w; ++x)
|
||||
{
|
||||
Rgba &p = pixels[y][x];
|
||||
|
||||
p.r = (x & 2);
|
||||
p.g = ((x + y) & 2);
|
||||
p.b = (y & 2);
|
||||
p.a = (p.r + p.b + p.g) / 3.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// class MMIFStream -- a memory-mapped implementation of
|
||||
// class IStream based on class std::ifstream
|
||||
//
|
||||
|
||||
class MMIFStream: public OPENEXR_IMF_NAMESPACE::IStream
|
||||
{
|
||||
public:
|
||||
|
||||
//-------------------------------------------------------
|
||||
// A constructor that opens the file with the given name.
|
||||
// It reads the whole file into an internal buffer and
|
||||
// then immediately closes the file.
|
||||
//-------------------------------------------------------
|
||||
|
||||
MMIFStream (const char fileName[]);
|
||||
|
||||
virtual ~MMIFStream ();
|
||||
|
||||
virtual bool isMemoryMapped () const {return true;}
|
||||
|
||||
virtual bool read (char c[/*n*/], int n);
|
||||
virtual char* readMemoryMapped (int n);
|
||||
virtual Int64 tellg () {return _pos;}
|
||||
virtual void seekg (Int64 pos) {_pos = pos;}
|
||||
virtual void clear () {}
|
||||
|
||||
private:
|
||||
|
||||
char* _buffer;
|
||||
Int64 _length;
|
||||
Int64 _pos;
|
||||
};
|
||||
|
||||
|
||||
|
||||
MMIFStream::MMIFStream (const char fileName[]):
|
||||
OPENEXR_IMF_NAMESPACE::IStream (fileName),
|
||||
_buffer (0),
|
||||
_length (0),
|
||||
_pos (0)
|
||||
{
|
||||
std::ifstream ifs (fileName, ios_base::binary);
|
||||
|
||||
//
|
||||
// Get length of file
|
||||
//
|
||||
|
||||
ifs.seekg (0, ios::end);
|
||||
_length = ifs.tellg();
|
||||
ifs.seekg (0, ios::beg);
|
||||
|
||||
//
|
||||
// Allocate memory
|
||||
//
|
||||
|
||||
_buffer = new char [_length];
|
||||
|
||||
//
|
||||
// Read the entire file
|
||||
//
|
||||
|
||||
ifs.read (_buffer, _length);
|
||||
ifs.close();
|
||||
}
|
||||
|
||||
|
||||
MMIFStream::~MMIFStream ()
|
||||
{
|
||||
delete [] _buffer;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
MMIFStream::read (char c[/*n*/], int n)
|
||||
{
|
||||
if ((_pos < 0 || _pos >= _length) && n != 0)
|
||||
throw IEX_NAMESPACE::InputExc ("Unexpected end of file.");
|
||||
|
||||
Int64 n2 = n;
|
||||
bool retVal = true;
|
||||
|
||||
if (_length - _pos <= n2)
|
||||
{
|
||||
n2 = _length - _pos;
|
||||
retVal = false;
|
||||
}
|
||||
|
||||
memcpy (c, &(_buffer[_pos]), n2);
|
||||
_pos += n2;
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
char*
|
||||
MMIFStream::readMemoryMapped (int n)
|
||||
{
|
||||
if (_pos < 0 || _pos >= _length)
|
||||
throw IEX_NAMESPACE::InputExc ("Unexpected end of file.");
|
||||
|
||||
if (_pos + n > _length)
|
||||
throw IEX_NAMESPACE::InputExc ("Reading past end of file.");
|
||||
|
||||
char* retVal = &(_buffer[_pos]);
|
||||
_pos += n;
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
writeReadScanLines (const char fileName[],
|
||||
int width,
|
||||
int height,
|
||||
const Array2D<Rgba> &p1)
|
||||
{
|
||||
//
|
||||
// Save a scanline-based RGBA image, but instead of
|
||||
// letting the RgbaOutputFile object open the file,
|
||||
// make the RgbaOutputFile object use an existing
|
||||
// StdOFStream. Read the image back, using an
|
||||
// existing StdIFStream, and compare the pixels
|
||||
// with the original data. Then read the image
|
||||
// back a second time using a memory-mapped
|
||||
// MMIFStream (see above).
|
||||
//
|
||||
|
||||
cout << "scan-line based file:" << endl;
|
||||
|
||||
Header header (width, height);
|
||||
|
||||
{
|
||||
cout << "writing";
|
||||
remove (fileName);
|
||||
std::ofstream os (fileName, ios_base::binary);
|
||||
StdOFStream ofs (os, fileName);
|
||||
RgbaOutputFile out (ofs, header, WRITE_RGBA);
|
||||
out.setFrameBuffer (&p1[0][0], 1, width);
|
||||
out.writePixels (height);
|
||||
}
|
||||
|
||||
{
|
||||
cout << ", reading";
|
||||
std::ifstream is (fileName, ios_base::binary);
|
||||
StdIFStream ifs (is, fileName);
|
||||
RgbaInputFile in (ifs);
|
||||
|
||||
const Box2i &dw = in.dataWindow();
|
||||
int w = dw.max.x - dw.min.x + 1;
|
||||
int h = dw.max.y - dw.min.y + 1;
|
||||
int dx = dw.min.x;
|
||||
int dy = dw.min.y;
|
||||
|
||||
Array2D<Rgba> p2 (h, w);
|
||||
in.setFrameBuffer (&p2[-dy][-dx], 1, w);
|
||||
in.readPixels (dw.min.y, dw.max.y);
|
||||
|
||||
cout << ", comparing";
|
||||
for (int y = 0; y < h; ++y)
|
||||
{
|
||||
for (int x = 0; x < w; ++x)
|
||||
{
|
||||
assert (p2[y][x].r == p1[y][x].r);
|
||||
assert (p2[y][x].g == p1[y][x].g);
|
||||
assert (p2[y][x].b == p1[y][x].b);
|
||||
assert (p2[y][x].a == p1[y][x].a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
cout << ", reading (memory-mapped)";
|
||||
MMIFStream ifs (fileName);
|
||||
RgbaInputFile in (ifs);
|
||||
|
||||
const Box2i &dw = in.dataWindow();
|
||||
int w = dw.max.x - dw.min.x + 1;
|
||||
int h = dw.max.y - dw.min.y + 1;
|
||||
int dx = dw.min.x;
|
||||
int dy = dw.min.y;
|
||||
|
||||
Array2D<Rgba> p2 (h, w);
|
||||
in.setFrameBuffer (&p2[-dy][-dx], 1, w);
|
||||
in.readPixels (dw.min.y, dw.max.y);
|
||||
|
||||
cout << ", comparing";
|
||||
for (int y = 0; y < h; ++y)
|
||||
{
|
||||
for (int x = 0; x < w; ++x)
|
||||
{
|
||||
assert (p2[y][x].r == p1[y][x].r);
|
||||
assert (p2[y][x].g == p1[y][x].g);
|
||||
assert (p2[y][x].b == p1[y][x].b);
|
||||
assert (p2[y][x].a == p1[y][x].a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cout << endl;
|
||||
|
||||
remove (fileName);
|
||||
}
|
||||
void
|
||||
writeReadMultiPart (const char fileName[],
|
||||
int width,
|
||||
int height,
|
||||
const Array2D<Rgba> &p1)
|
||||
{
|
||||
//
|
||||
// Save a two scanline parts in an image, but instead of
|
||||
// letting the MultiPartOutputFile object open the file,
|
||||
// make the MultiPartOutputFile object use an existing
|
||||
// StdOFStream. Read the image back, using an
|
||||
// existing StdIFStream, and compare the pixels
|
||||
// with the original data. Then read the image
|
||||
// back a second time using a memory-mapped
|
||||
// MMIFStream (see above).
|
||||
//
|
||||
|
||||
cout << "scan-line based mulitpart file:" << endl;
|
||||
|
||||
vector<Header> headers(2);
|
||||
headers[0] = Header(width, height);
|
||||
headers[0].setName("part1");
|
||||
headers[0].channels().insert("R",Channel());
|
||||
headers[0].channels().insert("G",Channel());
|
||||
headers[0].channels().insert("B",Channel());
|
||||
headers[0].channels().insert("A",Channel());
|
||||
headers[0].setType(SCANLINEIMAGE);
|
||||
|
||||
headers[1]=headers[0];
|
||||
headers[1].setName("part2");
|
||||
|
||||
|
||||
{
|
||||
cout << "writing";
|
||||
remove (fileName);
|
||||
std::ofstream os (fileName, ios_base::binary);
|
||||
StdOFStream ofs (os, fileName);
|
||||
MultiPartOutputFile out (ofs, &headers[0],2);
|
||||
FrameBuffer f;
|
||||
f.insert("R",Slice(HALF,(char *) &p1[0][0].r,sizeof(Rgba),width*sizeof(Rgba)));
|
||||
f.insert("G",Slice(HALF,(char *) &p1[0][0].g,sizeof(Rgba),width*sizeof(Rgba)));
|
||||
f.insert("B",Slice(HALF,(char *) &p1[0][0].b,sizeof(Rgba),width*sizeof(Rgba)));
|
||||
f.insert("A",Slice(HALF,(char *) &p1[0][0].a,sizeof(Rgba),width*sizeof(Rgba)));
|
||||
|
||||
for(int i=0;i<2;i++)
|
||||
{
|
||||
OutputPart p(out,i);
|
||||
p.setFrameBuffer (f);
|
||||
p.writePixels (height);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
cout << ", reading";
|
||||
std::ifstream is (fileName, ios_base::binary);
|
||||
StdIFStream ifs (is, fileName);
|
||||
MultiPartInputFile in (ifs);
|
||||
|
||||
assert(in.parts() == 2);
|
||||
|
||||
assert(in.header(0).dataWindow()==in.header(1).dataWindow());
|
||||
|
||||
const Box2i &dw = in.header(0).dataWindow();
|
||||
int w = dw.max.x - dw.min.x + 1;
|
||||
int h = dw.max.y - dw.min.y + 1;
|
||||
int dx = dw.min.x;
|
||||
int dy = dw.min.y;
|
||||
|
||||
Array2D<Rgba> p2 (h, w);
|
||||
FrameBuffer f;
|
||||
f.insert("R",Slice(HALF,(char *) &p2[-dy][-dx].r,sizeof(Rgba),w*sizeof(Rgba)));
|
||||
f.insert("G",Slice(HALF,(char *) &p2[-dy][-dx].g,sizeof(Rgba),w*sizeof(Rgba)));
|
||||
f.insert("B",Slice(HALF,(char *) &p2[-dy][-dx].b,sizeof(Rgba),w*sizeof(Rgba)));
|
||||
f.insert("A",Slice(HALF,(char *) &p2[-dy][-dx].a,sizeof(Rgba),w*sizeof(Rgba)));
|
||||
|
||||
for(int part=0;part<2;part++)
|
||||
{
|
||||
InputPart p(in,part);
|
||||
p.setFrameBuffer(f);
|
||||
p.readPixels (dw.min.y, dw.max.y);
|
||||
|
||||
cout << ", comparing pt " << part;
|
||||
for (int y = 0; y < h; ++y)
|
||||
{
|
||||
for (int x = 0; x < w; ++x)
|
||||
{
|
||||
assert (p2[y][x].r == p1[y][x].r);
|
||||
assert (p2[y][x].g == p1[y][x].g);
|
||||
assert (p2[y][x].b == p1[y][x].b);
|
||||
assert (p2[y][x].a == p1[y][x].a);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
cout << ", reading (memory-mapped)";
|
||||
MMIFStream ifs (fileName);
|
||||
MultiPartInputFile in (ifs);
|
||||
|
||||
assert(in.parts() == 2);
|
||||
|
||||
assert(in.header(0).dataWindow()==in.header(1).dataWindow());
|
||||
|
||||
|
||||
const Box2i &dw = in.header(0).dataWindow();
|
||||
int w = dw.max.x - dw.min.x + 1;
|
||||
int h = dw.max.y - dw.min.y + 1;
|
||||
int dx = dw.min.x;
|
||||
int dy = dw.min.y;
|
||||
|
||||
Array2D<Rgba> p2 (h, w);
|
||||
FrameBuffer f;
|
||||
f.insert("R",Slice(HALF,(char *) &p2[-dy][-dx].r,sizeof(Rgba),w*sizeof(Rgba)));
|
||||
f.insert("G",Slice(HALF,(char *) &p2[-dy][-dx].g,sizeof(Rgba),w*sizeof(Rgba)));
|
||||
f.insert("B",Slice(HALF,(char *) &p2[-dy][-dx].b,sizeof(Rgba),w*sizeof(Rgba)));
|
||||
f.insert("A",Slice(HALF,(char *) &p2[-dy][-dx].a,sizeof(Rgba),w*sizeof(Rgba)));
|
||||
|
||||
for(int part=0;part<2;part++)
|
||||
{
|
||||
InputPart p(in,part);
|
||||
p.setFrameBuffer(f);
|
||||
p.readPixels (dw.min.y, dw.max.y);
|
||||
|
||||
cout << ", comparing pt " << part;
|
||||
for (int y = 0; y < h; ++y)
|
||||
{
|
||||
for (int x = 0; x < w; ++x)
|
||||
{
|
||||
assert (p2[y][x].r == p1[y][x].r);
|
||||
assert (p2[y][x].g == p1[y][x].g);
|
||||
assert (p2[y][x].b == p1[y][x].b);
|
||||
assert (p2[y][x].a == p1[y][x].a);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cout << endl;
|
||||
|
||||
remove (fileName);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
writeReadTiles (const char fileName[],
|
||||
int width,
|
||||
int height,
|
||||
const Array2D<Rgba> &p1)
|
||||
{
|
||||
//
|
||||
// Save a tiled RGBA image, but instead of letting
|
||||
// the TiledRgbaOutputFile object open the file, make
|
||||
// it use an existing StdOFStream. Read the image back,
|
||||
// using an existing StdIFStream, and compare the pixels
|
||||
// with the original data. Then read the image back a
|
||||
// second time using a memory-mapped MMIFStream (see above).
|
||||
//
|
||||
|
||||
cout << "tiled file:" << endl;
|
||||
|
||||
Header header (width, height);
|
||||
|
||||
{
|
||||
cout << "writing";
|
||||
remove (fileName);
|
||||
std::ofstream os (fileName, ios_base::binary);
|
||||
StdOFStream ofs (os, fileName);
|
||||
TiledRgbaOutputFile out (ofs, header, WRITE_RGBA, 20, 20, ONE_LEVEL);
|
||||
out.setFrameBuffer (&p1[0][0], 1, width);
|
||||
out.writeTiles (0, out.numXTiles() - 1, 0, out.numYTiles() - 1);
|
||||
}
|
||||
|
||||
{
|
||||
cout << ", reading";
|
||||
std::ifstream is (fileName, ios_base::binary);
|
||||
StdIFStream ifs (is, fileName);
|
||||
TiledRgbaInputFile in (ifs);
|
||||
|
||||
const Box2i &dw = in.dataWindow();
|
||||
int w = dw.max.x - dw.min.x + 1;
|
||||
int h = dw.max.y - dw.min.y + 1;
|
||||
int dx = dw.min.x;
|
||||
int dy = dw.min.y;
|
||||
|
||||
Array2D<Rgba> p2 (h, w);
|
||||
in.setFrameBuffer (&p2[-dy][-dx], 1, w);
|
||||
in.readTiles (0, in.numXTiles() - 1, 0, in.numYTiles() - 1);
|
||||
|
||||
cout << ", comparing";
|
||||
for (int y = 0; y < h; ++y)
|
||||
{
|
||||
for (int x = 0; x < w; ++x)
|
||||
{
|
||||
assert (p2[y][x].r == p1[y][x].r);
|
||||
assert (p2[y][x].g == p1[y][x].g);
|
||||
assert (p2[y][x].b == p1[y][x].b);
|
||||
assert (p2[y][x].a == p1[y][x].a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
cout << ", reading (memory-mapped)";
|
||||
MMIFStream ifs (fileName);
|
||||
TiledRgbaInputFile in (ifs);
|
||||
|
||||
const Box2i &dw = in.dataWindow();
|
||||
int w = dw.max.x - dw.min.x + 1;
|
||||
int h = dw.max.y - dw.min.y + 1;
|
||||
int dx = dw.min.x;
|
||||
int dy = dw.min.y;
|
||||
|
||||
Array2D<Rgba> p2 (h, w);
|
||||
in.setFrameBuffer (&p2[-dy][-dx], 1, w);
|
||||
in.readTiles (0, in.numXTiles() - 1, 0, in.numYTiles() - 1);
|
||||
|
||||
cout << ", comparing";
|
||||
for (int y = 0; y < h; ++y)
|
||||
{
|
||||
for (int x = 0; x < w; ++x)
|
||||
{
|
||||
assert (p2[y][x].r == p1[y][x].r);
|
||||
assert (p2[y][x].g == p1[y][x].g);
|
||||
assert (p2[y][x].b == p1[y][x].b);
|
||||
assert (p2[y][x].a == p1[y][x].a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cout << endl;
|
||||
|
||||
remove (fileName);
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
void
|
||||
testExistingStreams (const std::string &tempDir)
|
||||
{
|
||||
try
|
||||
{
|
||||
cout << "Testing reading and writing using existing streams" << endl;
|
||||
|
||||
const int W = 119;
|
||||
const int H = 237;
|
||||
|
||||
Array2D<Rgba> p1 (H, W);
|
||||
|
||||
fillPixels1 (p1, W, H);
|
||||
writeReadScanLines ((tempDir + "imf_test_streams.exr").c_str(), W, H, p1);
|
||||
|
||||
fillPixels2 (p1, W, H);
|
||||
writeReadTiles ((tempDir + "imf_test_streams2.exr").c_str(), W, H, p1);
|
||||
|
||||
fillPixels1 (p1, W, H);
|
||||
writeReadMultiPart ((tempDir + "imf_test_streams3.exr").c_str(), W, H, p1);
|
||||
|
||||
cout << "ok\n" << endl;
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
cerr << "ERROR -- caught exception: " << e.what() << endl;
|
||||
assert (false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2004-2012, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include <string>
|
||||
|
||||
void testExistingStreams (const std::string &tempDir);
|
||||
|
||||
1384
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testFutureProofing.cpp
Normal file
1384
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testFutureProofing.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,40 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2013, Weta Digital Ltd
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef TESTFUTUREPROOFING_H_
|
||||
#define TESTFUTUREPROOFING_H_
|
||||
|
||||
#include <string>
|
||||
void testFutureProofing (const std::string & tempDir);
|
||||
|
||||
#endif
|
||||
252
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testHuf.cpp
Normal file
252
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testHuf.cpp
Normal file
@@ -0,0 +1,252 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#include <ImfHuf.h>
|
||||
#include "ImathRandom.h"
|
||||
#include <ImfArray.h>
|
||||
#include <iostream>
|
||||
#include <exception>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
using namespace OPENEXR_IMF_NAMESPACE;
|
||||
using namespace std;
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
void
|
||||
fill1 (unsigned short data[/*n*/], int n, float bias, IMATH_NAMESPACE::Rand48 & rand48)
|
||||
{
|
||||
for (int i = 0; i < n; ++i)
|
||||
data[i] = (unsigned short)
|
||||
(pow (rand48.nextf(), double(bias)) * (USHRT_MAX + 1));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
fill2 (unsigned short data[/*n*/], int n, int m, IMATH_NAMESPACE::Rand48 & rand48)
|
||||
{
|
||||
for (int i = 0; i < n; ++i)
|
||||
data[i] = 0;
|
||||
|
||||
for (int i = 0; i < m; ++i)
|
||||
data[rand48.nexti() % n] = (unsigned short) (rand48.nextf() * (USHRT_MAX + 1));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
fill3 (unsigned short data[/*n*/], int n, int m)
|
||||
{
|
||||
for (int i = 0; i < n; ++i)
|
||||
data[i] = m;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
fill4 (unsigned short data[/*n*/], int n)
|
||||
{
|
||||
for (int i = 0; i < n; ++i)
|
||||
data[i] = i & USHRT_MAX;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
fill5 (unsigned short data[/*n*/], int n)
|
||||
{
|
||||
for (int i = 0; i < n; ++i)
|
||||
data[i] = 0;
|
||||
|
||||
int j = 0, k = 0;
|
||||
|
||||
for (int i = 0; i < n; ++i)
|
||||
{
|
||||
data[i] = j;
|
||||
j = j + k;
|
||||
k = k + 1;
|
||||
|
||||
if (j > USHRT_MAX)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
compressUncompress (const unsigned short raw[], int n)
|
||||
{
|
||||
Array <char> compressed (3 * n + 4 * 65536);
|
||||
Array <unsigned short> uncompressed (n);
|
||||
|
||||
cout << "compressing " << flush;
|
||||
|
||||
int nCompressed = hufCompress (raw, n, compressed);
|
||||
|
||||
cout << "uncompressing " << flush;
|
||||
|
||||
hufUncompress (compressed, nCompressed, uncompressed, n);
|
||||
|
||||
cout << "comparing: " << flush;
|
||||
|
||||
for (int i = 0; i < n; ++i)
|
||||
assert (uncompressed[i] == raw[i]);
|
||||
|
||||
cout << sizeof (raw[0]) * n << " bytes, compressed " <<
|
||||
nCompressed << " bytes" << endl;
|
||||
}
|
||||
|
||||
void
|
||||
compressUncompressSubset(const unsigned short raw[], int n)
|
||||
{
|
||||
// Test various subsets of the data set
|
||||
|
||||
Array <char> compressed (3 * n + 4 * 65536);
|
||||
Array <unsigned short> uncompressed (n);
|
||||
|
||||
int maxOffset = 16;
|
||||
if (n <= maxOffset) {
|
||||
maxOffset = n-1;
|
||||
}
|
||||
|
||||
for (int offset=1; offset<maxOffset; ++offset) {
|
||||
|
||||
int maxLength = n - offset;
|
||||
int minLength = maxLength - 16;
|
||||
if (minLength < 1) minLength = 1;
|
||||
|
||||
for (int length=minLength; length<=maxLength; ++length) {
|
||||
cout << "compressing " << flush;
|
||||
|
||||
int nCompressed = hufCompress (raw + offset, length, compressed + offset);
|
||||
|
||||
cout << "uncompressing " << flush;
|
||||
|
||||
hufUncompress (compressed + offset, nCompressed, uncompressed + offset, length);
|
||||
|
||||
for (int i = 0; i < length; ++i)
|
||||
assert (uncompressed[offset+i] == raw[offset+i]);
|
||||
|
||||
cout << sizeof (raw[0]) * length << " bytes, compressed " << nCompressed << " bytes ";
|
||||
cout << "(+" << offset << ",-" << n-offset-length << ")" << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
void
|
||||
testHuf (const std::string&)
|
||||
{
|
||||
try
|
||||
{
|
||||
cout << "Testing Huffman encoder" << endl;
|
||||
|
||||
IMATH_NAMESPACE::Rand48 rand48 (0);
|
||||
|
||||
const int N = 1000000;
|
||||
Array <unsigned short> raw (N);
|
||||
|
||||
fill1 (raw, N, 1, rand48); // test various symbol distributions
|
||||
compressUncompress (raw, N);
|
||||
compressUncompressSubset (raw, N);
|
||||
fill1 (raw, N, 10, rand48);
|
||||
compressUncompress (raw, N);
|
||||
compressUncompressSubset (raw, N);
|
||||
fill1 (raw, N, 100, rand48);
|
||||
compressUncompress (raw, N);
|
||||
compressUncompressSubset (raw, N);
|
||||
fill1 (raw, N, 1000, rand48);
|
||||
compressUncompress (raw, N);
|
||||
compressUncompressSubset (raw, N);
|
||||
|
||||
fill2 (raw, N, 1, rand48);
|
||||
compressUncompress (raw, N);
|
||||
compressUncompressSubset (raw, N);
|
||||
fill2 (raw, N, 10, rand48);
|
||||
compressUncompress (raw, N);
|
||||
compressUncompressSubset (raw, N);
|
||||
fill2 (raw, N, 100, rand48);
|
||||
compressUncompress (raw, N);
|
||||
compressUncompressSubset (raw, N);
|
||||
fill2 (raw, N, 1000, rand48);
|
||||
compressUncompress (raw, N);
|
||||
compressUncompressSubset (raw, N);
|
||||
|
||||
fill3 (raw, N, 0);
|
||||
compressUncompress (raw, N);
|
||||
compressUncompressSubset (raw, N);
|
||||
fill3 (raw, N, 1);
|
||||
compressUncompress (raw, N);
|
||||
compressUncompressSubset (raw, N);
|
||||
fill3 (raw, N, USHRT_MAX - 1);
|
||||
compressUncompress (raw, N);
|
||||
compressUncompressSubset (raw, N);
|
||||
fill3 (raw, N, USHRT_MAX);
|
||||
compressUncompress (raw, N);
|
||||
compressUncompressSubset (raw, N);
|
||||
|
||||
fill4 (raw, USHRT_MAX + 1);
|
||||
compressUncompress (raw, USHRT_MAX + 1);
|
||||
compressUncompressSubset (raw, USHRT_MAX + 1);
|
||||
fill4 (raw, N);
|
||||
compressUncompress (raw, N);
|
||||
compressUncompressSubset (raw, N);
|
||||
|
||||
fill4 (raw, 0);
|
||||
compressUncompress (raw, 0); // test small input data sets
|
||||
fill4 (raw, 1);
|
||||
compressUncompress (raw, 1);
|
||||
fill4 (raw, 2);
|
||||
compressUncompress (raw, 2);
|
||||
fill4 (raw, 3);
|
||||
compressUncompress (raw, 3);
|
||||
|
||||
fill5 (raw, N); // test run-length coding of code table
|
||||
compressUncompress (raw, N);
|
||||
compressUncompressSubset (raw, N);
|
||||
|
||||
cout << "ok\n" << endl;
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
cerr << "ERROR -- caught exception: " << e.what() << endl;
|
||||
assert (false);
|
||||
}
|
||||
}
|
||||
41
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testHuf.h
Normal file
41
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testHuf.h
Normal file
@@ -0,0 +1,41 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
#include <string>
|
||||
|
||||
void testHuf (const std::string &tempDir);
|
||||
|
||||
729
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testInputPart.cpp
Normal file
729
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testInputPart.cpp
Normal file
@@ -0,0 +1,729 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// Portions (c) 2012, Weta Digital Ltd
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// Weta Digital nor any other ontributors may be used to endorse
|
||||
// or promote products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "tmpDir.h"
|
||||
#include "testInputPart.h"
|
||||
|
||||
#include <IlmThreadPool.h>
|
||||
#include <ImfMultiPartInputFile.h>
|
||||
#include <ImfMultiPartOutputFile.h>
|
||||
#include <ImfArray.h>
|
||||
#include <ImfChannelList.h>
|
||||
#include <ImfOutputPart.h>
|
||||
#include <ImfInputPart.h>
|
||||
#include <ImfTiledOutputPart.h>
|
||||
#include <ImfPartType.h>
|
||||
#include <ImfMisc.h>
|
||||
|
||||
namespace IMF = OPENEXR_IMF_NAMESPACE;
|
||||
using namespace IMF;
|
||||
using namespace std;
|
||||
using namespace IMATH_NAMESPACE;
|
||||
using namespace ILMTHREAD_NAMESPACE;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
const int height = 267;
|
||||
const int width = 193;
|
||||
|
||||
vector<Header> headers;
|
||||
vector<int> pixelTypes;
|
||||
vector<int> partTypes;
|
||||
vector<int> levelModes;
|
||||
|
||||
template <class T>
|
||||
void fillPixels (Array2D<T> &ph, int width, int height)
|
||||
{
|
||||
ph.resizeErase(height, width);
|
||||
for (int y = 0; y < height; ++y)
|
||||
for (int x = 0; x < width; ++x)
|
||||
{
|
||||
//
|
||||
// We do this because half cannot store number bigger than 2048 exactly.
|
||||
//
|
||||
ph[y][x] = (y * width + x) % 2049;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void fillPixels (Array2D<unsigned int>& sampleCount, Array2D<T*> &ph, int width, int height)
|
||||
{
|
||||
ph.resizeErase(height, width);
|
||||
for (int y = 0; y < height; ++y)
|
||||
for (int x = 0; x < width; ++x)
|
||||
{
|
||||
ph[y][x] = new T[sampleCount[y][x]];
|
||||
for (int i = 0; i < sampleCount[y][x]; i++)
|
||||
{
|
||||
//
|
||||
// We do this because half cannot store number bigger than 2048 exactly.
|
||||
//
|
||||
ph[y][x][i] = (y * width + x) % 2049;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void allocatePixels(int type, Array2D<unsigned int>& sampleCount,
|
||||
Array2D<unsigned int*>& uintData, Array2D<float*>& floatData,
|
||||
Array2D<half*>& halfData, int x1, int x2, int y1, int y2)
|
||||
{
|
||||
for (int y = y1; y <= y2; y++)
|
||||
for (int x = x1; x <= x2; x++)
|
||||
{
|
||||
if (type == 0)
|
||||
uintData[y][x] = new unsigned int[sampleCount[y][x]];
|
||||
if (type == 1)
|
||||
floatData[y][x] = new float[sampleCount[y][x]];
|
||||
if (type == 2)
|
||||
halfData[y][x] = new half[sampleCount[y][x]];
|
||||
}
|
||||
}
|
||||
|
||||
void allocatePixels(int type, Array2D<unsigned int>& sampleCount,
|
||||
Array2D<unsigned int*>& uintData, Array2D<float*>& floatData,
|
||||
Array2D<half*>& halfData, int width, int height)
|
||||
{
|
||||
allocatePixels(type, sampleCount, uintData, floatData, halfData, 0, width - 1, 0, height - 1);
|
||||
}
|
||||
|
||||
void releasePixels(int type, Array2D<unsigned int*>& uintData, Array2D<float*>& floatData,
|
||||
Array2D<half*>& halfData, int x1, int x2, int y1, int y2)
|
||||
{
|
||||
for (int y = y1; y <= y2; y++)
|
||||
for (int x = x1; x <= x2; x++)
|
||||
{
|
||||
if (type == 0)
|
||||
delete[] uintData[y][x];
|
||||
if (type == 1)
|
||||
delete[] floatData[y][x];
|
||||
if (type == 2)
|
||||
delete[] halfData[y][x];
|
||||
}
|
||||
}
|
||||
|
||||
void releasePixels(int type, Array2D<unsigned int*>& uintData, Array2D<float*>& floatData,
|
||||
Array2D<half*>& halfData, int width, int height)
|
||||
{
|
||||
releasePixels(type, uintData, floatData, halfData, 0, width - 1, 0, height - 1);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool checkPixels (Array2D<T> &ph, int lx, int rx, int ly, int ry, int width)
|
||||
{
|
||||
for (int y = ly; y <= ry; ++y)
|
||||
for (int x = lx; x <= rx; ++x)
|
||||
if (ph[y][x] != (y * width + x) % 2049)
|
||||
{
|
||||
cout << "value at " << x << ", " << y << ": " << ph[y][x]
|
||||
<< ", should be " << (y * width + x) % 2049 << endl << flush;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool checkPixels (Array2D<T> &ph, int width, int height)
|
||||
{
|
||||
return checkPixels<T> (ph, 0, width - 1, 0, height - 1, width);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool checkPixels (Array2D<unsigned int>& sampleCount, Array2D<T*> &ph,
|
||||
int lx, int rx, int ly, int ry, int width)
|
||||
{
|
||||
for (int y = ly; y <= ry; ++y)
|
||||
for (int x = lx; x <= rx; ++x)
|
||||
{
|
||||
for (int i = 0; i < sampleCount[y][x]; i++)
|
||||
{
|
||||
if (ph[y][x][i] != (y * width + x) % 2049)
|
||||
{
|
||||
cout << "value at " << x << ", " << y << ", sample " << i << ": " << ph[y][x][i]
|
||||
<< ", should be " << (y * width + x) % 2049 << endl << flush;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool checkPixels (Array2D<unsigned int>& sampleCount, Array2D<T*> &ph, int width, int height)
|
||||
{
|
||||
return checkPixels<T> (sampleCount, ph, 0, width - 1, 0, height - 1, width);
|
||||
}
|
||||
|
||||
bool checkSampleCount(Array2D<unsigned int>& sampleCount, int x1, int x2, int y1, int y2, int width)
|
||||
{
|
||||
for (int i = y1; i <= y2; i++)
|
||||
for (int j = x1; j <= x2; j++)
|
||||
{
|
||||
if (sampleCount[i][j] != ((i * width) + j) % 10 + 1)
|
||||
{
|
||||
cout << "sample count at " << j << ", " << i << ": " << sampleCount[i][j]
|
||||
<< ", should be " << (i * width + j) % 10 + 1 << endl << flush;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool checkSampleCount(Array2D<unsigned int>& sampleCount, int width, int height)
|
||||
{
|
||||
return checkSampleCount(sampleCount, 0, width - 1, 0, height - 1, width);
|
||||
}
|
||||
|
||||
void generateRandomHeaders(int partCount, vector<Header>& headers)
|
||||
{
|
||||
cout << "Generating headers and data" << endl << flush;
|
||||
|
||||
headers.clear();
|
||||
for (int i = 0; i < partCount; i++)
|
||||
{
|
||||
Header header (width,
|
||||
height,
|
||||
1.f,
|
||||
IMATH_NAMESPACE::V2f (0, 0),
|
||||
1.f,
|
||||
INCREASING_Y,
|
||||
ZIPS_COMPRESSION);
|
||||
|
||||
int pixelType = rand() % 3;
|
||||
int partType = rand() % 2;
|
||||
|
||||
pixelTypes[i] = pixelType;
|
||||
partTypes[i] = partType;
|
||||
|
||||
stringstream ss;
|
||||
ss << i;
|
||||
header.setName(ss.str());
|
||||
|
||||
switch (pixelType)
|
||||
{
|
||||
case 0:
|
||||
header.channels().insert("UINT", Channel(IMF::UINT));
|
||||
break;
|
||||
case 1:
|
||||
header.channels().insert("FLOAT", Channel(IMF::FLOAT));
|
||||
break;
|
||||
case 2:
|
||||
header.channels().insert("HALF", Channel(IMF::HALF));
|
||||
break;
|
||||
}
|
||||
|
||||
switch (partType)
|
||||
{
|
||||
case 0:
|
||||
header.setType(SCANLINEIMAGE);
|
||||
break;
|
||||
case 1:
|
||||
header.setType(TILEDIMAGE);
|
||||
break;
|
||||
}
|
||||
|
||||
int tileX;
|
||||
int tileY;
|
||||
int levelMode;
|
||||
if (partType == 1)
|
||||
{
|
||||
tileX = rand() % width + 1;
|
||||
tileY = rand() % height + 1;
|
||||
levelMode = rand() % 3;
|
||||
levelModes[i] = levelMode;
|
||||
LevelMode lm;
|
||||
switch (levelMode)
|
||||
{
|
||||
case 0:
|
||||
lm = ONE_LEVEL;
|
||||
break;
|
||||
case 1:
|
||||
lm = MIPMAP_LEVELS;
|
||||
break;
|
||||
case 2:
|
||||
lm = RIPMAP_LEVELS;
|
||||
break;
|
||||
}
|
||||
header.setTileDescription(TileDescription(tileX, tileY, lm));
|
||||
}
|
||||
|
||||
|
||||
int order = rand() % NUM_LINEORDERS;
|
||||
if(partType==0 || partType ==2)
|
||||
{
|
||||
// can't write random scanlines
|
||||
order = rand() % (NUM_LINEORDERS-1);
|
||||
}
|
||||
LineOrder l;
|
||||
switch(order)
|
||||
{
|
||||
case 0 :
|
||||
l = INCREASING_Y;
|
||||
break;
|
||||
case 1 :
|
||||
l = DECREASING_Y;
|
||||
break;
|
||||
case 2 :
|
||||
l = RANDOM_Y;
|
||||
break;
|
||||
}
|
||||
|
||||
header.lineOrder()=l;
|
||||
|
||||
|
||||
if (partType == 0)
|
||||
{
|
||||
cout << "pixelType = " << pixelType << " partType = " << partType
|
||||
<< " line order =" << header.lineOrder() << endl << flush;
|
||||
}
|
||||
else
|
||||
{
|
||||
cout << "pixelType = " << pixelType << " partType = " << partType
|
||||
<< " tile order =" << header.lineOrder()
|
||||
<< " levelMode = " << levelModes[i] << endl << flush;
|
||||
}
|
||||
|
||||
headers.push_back(header);
|
||||
}
|
||||
}
|
||||
|
||||
void setOutputFrameBuffer(FrameBuffer& frameBuffer, int pixelType,
|
||||
Array2D<unsigned int>& uData, Array2D<float>& fData,
|
||||
Array2D<half>& hData, int width)
|
||||
{
|
||||
switch (pixelType)
|
||||
{
|
||||
case 0:
|
||||
frameBuffer.insert ("UINT",
|
||||
Slice (IMF::UINT,
|
||||
(char *) (&uData[0][0]),
|
||||
sizeof (uData[0][0]) * 1,
|
||||
sizeof (uData[0][0]) * width));
|
||||
break;
|
||||
case 1:
|
||||
frameBuffer.insert ("FLOAT",
|
||||
Slice (IMF::FLOAT,
|
||||
(char *) (&fData[0][0]),
|
||||
sizeof (fData[0][0]) * 1,
|
||||
sizeof (fData[0][0]) * width));
|
||||
break;
|
||||
case 2:
|
||||
frameBuffer.insert ("HALF",
|
||||
Slice (IMF::HALF,
|
||||
(char *) (&hData[0][0]),
|
||||
sizeof (hData[0][0]) * 1,
|
||||
sizeof (hData[0][0]) * width));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void setInputFrameBuffer(FrameBuffer& frameBuffer, int pixelType,
|
||||
Array2D<unsigned int>& uData, Array2D<float>& fData,
|
||||
Array2D<half>& hData, int width, int height)
|
||||
{
|
||||
switch (pixelType)
|
||||
{
|
||||
case 0:
|
||||
uData.resizeErase(height, width);
|
||||
frameBuffer.insert ("UINT",
|
||||
Slice (IMF::UINT,
|
||||
(char *) (&uData[0][0]),
|
||||
sizeof (uData[0][0]) * 1,
|
||||
sizeof (uData[0][0]) * width,
|
||||
1, 1,
|
||||
0));
|
||||
break;
|
||||
case 1:
|
||||
fData.resizeErase(height, width);
|
||||
frameBuffer.insert ("FLOAT",
|
||||
Slice (IMF::FLOAT,
|
||||
(char *) (&fData[0][0]),
|
||||
sizeof (fData[0][0]) * 1,
|
||||
sizeof (fData[0][0]) * width,
|
||||
1, 1,
|
||||
0));
|
||||
break;
|
||||
case 2:
|
||||
hData.resizeErase(height, width);
|
||||
frameBuffer.insert ("HALF",
|
||||
Slice (IMF::HALF,
|
||||
(char *) (&hData[0][0]),
|
||||
sizeof (hData[0][0]) * 1,
|
||||
sizeof (hData[0][0]) * width,
|
||||
1, 1,
|
||||
0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
generateRandomFile (int partCount, const std::string & fn)
|
||||
{
|
||||
//
|
||||
// Init data.
|
||||
//
|
||||
Array2D<half> halfData;
|
||||
Array2D<float> floatData;
|
||||
Array2D<unsigned int> uintData;
|
||||
|
||||
Array2D<unsigned int> sampleCount;
|
||||
Array2D<half*> deepHalfData;
|
||||
Array2D<float*> deepFloatData;
|
||||
Array2D<unsigned int*> deepUintData;
|
||||
|
||||
vector<GenericOutputFile*> outputfiles;
|
||||
|
||||
pixelTypes.resize(partCount);
|
||||
partTypes.resize(partCount);
|
||||
levelModes.resize(partCount);
|
||||
|
||||
//
|
||||
// Generate headers and data.
|
||||
//
|
||||
generateRandomHeaders(partCount, headers);
|
||||
|
||||
remove(fn.c_str());
|
||||
MultiPartOutputFile file(fn.c_str(), &headers[0],headers.size());
|
||||
|
||||
//
|
||||
// Writing files.
|
||||
//
|
||||
cout << "Writing files " << flush;
|
||||
|
||||
//
|
||||
// Pre-generating frameBuffers.
|
||||
//
|
||||
for (int i = 0; i < partCount; i++)
|
||||
{
|
||||
switch (partTypes[i])
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
OutputPart part(file, i);
|
||||
|
||||
FrameBuffer frameBuffer;
|
||||
|
||||
fillPixels <unsigned int> (uintData, width, height);
|
||||
fillPixels <float> (floatData, width, height);
|
||||
fillPixels <half> (halfData, width, height);
|
||||
|
||||
setOutputFrameBuffer(frameBuffer, pixelTypes[i], uintData, floatData, halfData, width);
|
||||
|
||||
part.setFrameBuffer(frameBuffer);
|
||||
|
||||
part.writePixels(height);
|
||||
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
TiledOutputPart part(file, i);
|
||||
|
||||
int numXLevels = part.numXLevels();
|
||||
int numYLevels = part.numYLevels();
|
||||
|
||||
for (int xLevel = 0; xLevel < numXLevels; xLevel++)
|
||||
for (int yLevel = 0; yLevel < numYLevels; yLevel++)
|
||||
{
|
||||
if (!part.isValidLevel(xLevel, yLevel))
|
||||
continue;
|
||||
|
||||
int w = part.levelWidth(xLevel);
|
||||
int h = part.levelHeight(yLevel);
|
||||
|
||||
FrameBuffer frameBuffer;
|
||||
|
||||
fillPixels <unsigned int> (uintData, w, h);
|
||||
fillPixels <float> (floatData, w, h);
|
||||
fillPixels <half> (halfData, w, h);
|
||||
setOutputFrameBuffer(frameBuffer, pixelTypes[i],
|
||||
uintData, floatData, halfData,
|
||||
w);
|
||||
|
||||
part.setFrameBuffer(frameBuffer);
|
||||
|
||||
part.writeTiles(0, part.numXTiles(xLevel) - 1,
|
||||
0, part.numYTiles(yLevel) - 1,
|
||||
xLevel, yLevel);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
readWholeFiles (const std::string & fn)
|
||||
{
|
||||
Array2D<unsigned int> uData;
|
||||
Array2D<float> fData;
|
||||
Array2D<half> hData;
|
||||
|
||||
Array2D<unsigned int*> deepUData;
|
||||
Array2D<float*> deepFData;
|
||||
Array2D<half*> deepHData;
|
||||
|
||||
Array2D<unsigned int> sampleCount;
|
||||
|
||||
MultiPartInputFile file(fn.c_str());
|
||||
for (size_t i = 0; i < file.parts(); i++)
|
||||
{
|
||||
const Header& header = file.header(i);
|
||||
assert (header.displayWindow() == headers[i].displayWindow());
|
||||
assert (header.dataWindow() == headers[i].dataWindow());
|
||||
assert (header.pixelAspectRatio() == headers[i].pixelAspectRatio());
|
||||
assert (header.screenWindowCenter() == headers[i].screenWindowCenter());
|
||||
assert (header.screenWindowWidth() == headers[i].screenWindowWidth());
|
||||
assert (header.lineOrder() == headers[i].lineOrder());
|
||||
assert (header.compression() == headers[i].compression());
|
||||
assert (header.channels() == headers[i].channels());
|
||||
assert (header.name() == headers[i].name());
|
||||
assert (header.type() == headers[i].type());
|
||||
}
|
||||
|
||||
cout << "Reading whole files " << flush;
|
||||
|
||||
//
|
||||
// Shuffle part numbers.
|
||||
//
|
||||
vector<int> shuffledPartNumber;
|
||||
for (int i = 0; i < headers.size(); i++)
|
||||
shuffledPartNumber.push_back(i);
|
||||
for (int i = 0; i < headers.size(); i++)
|
||||
{
|
||||
int a = rand() % headers.size();
|
||||
int b = rand() % headers.size();
|
||||
swap (shuffledPartNumber[a], shuffledPartNumber[b]);
|
||||
}
|
||||
|
||||
//
|
||||
// Start reading whole files.
|
||||
//
|
||||
int i;
|
||||
int partNumber;
|
||||
try
|
||||
{
|
||||
for (i = 0; i < headers.size(); i++)
|
||||
{
|
||||
partNumber = shuffledPartNumber[i];
|
||||
FrameBuffer frameBuffer;
|
||||
setInputFrameBuffer(frameBuffer, pixelTypes[partNumber],
|
||||
uData, fData, hData, width, height);
|
||||
|
||||
InputPart part(file, partNumber);
|
||||
part.setFrameBuffer(frameBuffer);
|
||||
part.readPixels(0, height - 1);
|
||||
switch (pixelTypes[partNumber])
|
||||
{
|
||||
case 0:
|
||||
assert(checkPixels<unsigned int>(uData, width, height));
|
||||
break;
|
||||
case 1:
|
||||
assert(checkPixels<float>(fData, width, height));
|
||||
break;
|
||||
case 2:
|
||||
assert(checkPixels<half>(hData, width, height));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
cout << "Error while reading part " << partNumber << endl << flush;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
readFirstPart (const std::string & fn)
|
||||
{
|
||||
Array2D<unsigned int> uData;
|
||||
Array2D<float> fData;
|
||||
Array2D<half> hData;
|
||||
|
||||
Array2D<unsigned int*> deepUData;
|
||||
Array2D<float*> deepFData;
|
||||
Array2D<half*> deepHData;
|
||||
|
||||
Array2D<unsigned int> sampleCount;
|
||||
|
||||
cout << "Reading first part " << flush;
|
||||
int pixelType = pixelTypes[0];
|
||||
int levelMode = levelModes[0];
|
||||
|
||||
int l1, l2;
|
||||
l1 = rand() % height;
|
||||
l2 = rand() % height;
|
||||
if (l1 > l2) swap(l1, l2);
|
||||
|
||||
InputFile part(fn.c_str());
|
||||
|
||||
FrameBuffer frameBuffer;
|
||||
setInputFrameBuffer(frameBuffer, pixelType,
|
||||
uData, fData, hData, width, height);
|
||||
|
||||
part.setFrameBuffer(frameBuffer);
|
||||
part.readPixels(l1, l2);
|
||||
|
||||
switch (pixelType)
|
||||
{
|
||||
case 0:
|
||||
assert(checkPixels<unsigned int>(uData, 0, width - 1, l1, l2, width));
|
||||
break;
|
||||
case 1:
|
||||
assert(checkPixels<float>(fData, 0, width - 1, l1, l2, width));
|
||||
break;
|
||||
case 2:
|
||||
assert(checkPixels<half>(hData, 0, width - 1, l1, l2, width));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
readPartialFiles (int randomReadCount, const std::string & fn)
|
||||
{
|
||||
Array2D<unsigned int> uData;
|
||||
Array2D<float> fData;
|
||||
Array2D<half> hData;
|
||||
|
||||
Array2D<unsigned int*> deepUData;
|
||||
Array2D<float*> deepFData;
|
||||
Array2D<half*> deepHData;
|
||||
|
||||
Array2D<unsigned int> sampleCount;
|
||||
|
||||
cout << "Reading partial files " << flush;
|
||||
MultiPartInputFile file(fn.c_str());
|
||||
|
||||
for (int i = 0; i < randomReadCount; i++)
|
||||
{
|
||||
int partNumber = rand() % file.parts();
|
||||
int partType = partTypes[partNumber];
|
||||
int pixelType = pixelTypes[partNumber];
|
||||
int levelMode = levelModes[partNumber];
|
||||
|
||||
int l1, l2;
|
||||
l1 = rand() % height;
|
||||
l2 = rand() % height;
|
||||
|
||||
if (l1 > l2) swap(l1, l2);
|
||||
|
||||
InputPart part(file, partNumber);
|
||||
|
||||
FrameBuffer frameBuffer;
|
||||
setInputFrameBuffer(frameBuffer, pixelType,
|
||||
uData, fData, hData, width, height);
|
||||
|
||||
part.setFrameBuffer(frameBuffer);
|
||||
part.readPixels(l1, l2);
|
||||
|
||||
switch (pixelType)
|
||||
{
|
||||
case 0:
|
||||
assert(checkPixels<unsigned int>(uData, 0, width - 1, l1, l2, width));
|
||||
break;
|
||||
case 1:
|
||||
assert(checkPixels<float>(fData, 0, width - 1, l1, l2, width));
|
||||
break;
|
||||
case 2:
|
||||
assert(checkPixels<half>(hData, 0, width - 1, l1, l2, width));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
testWriteRead (int partNumber,
|
||||
int runCount,
|
||||
int randomReadCount,
|
||||
const std::string & tempDir)
|
||||
{
|
||||
cout << "Testing file with " << partNumber << " part(s)." << endl << flush;
|
||||
|
||||
const std::string fn = tempDir + "imf_test_input_part.exr";
|
||||
|
||||
for (int i = 0; i < runCount; i++)
|
||||
{
|
||||
generateRandomFile (partNumber, fn);
|
||||
readWholeFiles (fn);
|
||||
readFirstPart (fn);
|
||||
readPartialFiles (randomReadCount, fn);
|
||||
|
||||
remove (fn.c_str());
|
||||
|
||||
cout << endl << flush;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
void testInputPart (const std::string & tempDir)
|
||||
{
|
||||
try
|
||||
{
|
||||
cout << "Testing reading multipart tiles and scanlines with InputPart" << endl;
|
||||
|
||||
srand(1);
|
||||
|
||||
int numThreads = ThreadPool::globalThreadPool().numThreads();
|
||||
ThreadPool::globalThreadPool().setNumThreads(4);
|
||||
|
||||
testWriteRead ( 1, 1, 5, tempDir);
|
||||
testWriteRead ( 2, 2, 1, tempDir);
|
||||
testWriteRead ( 8, 4, 2, tempDir);
|
||||
testWriteRead (50, 3, 11, tempDir);
|
||||
|
||||
ThreadPool::globalThreadPool().setNumThreads(numThreads);
|
||||
|
||||
cout << "ok\n" << endl;
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
cerr << "ERROR -- caught exception: " << e.what() << endl;
|
||||
assert (false);
|
||||
}
|
||||
}
|
||||
42
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testInputPart.h
Normal file
42
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testInputPart.h
Normal file
@@ -0,0 +1,42 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef TESTINPUTPART_H_
|
||||
#define TESTINPUTPART_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
void testInputPart (const std::string & tempDir);
|
||||
|
||||
#endif /* TESTINPUTPART_H_ */
|
||||
166
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testIsComplete.cpp
Normal file
166
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testIsComplete.cpp
Normal file
@@ -0,0 +1,166 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2005-2012, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include <ImfRgbaFile.h>
|
||||
#include <ImfTiledRgbaFile.h>
|
||||
#include <ImfArray.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
using namespace OPENEXR_IMF_NAMESPACE;
|
||||
using namespace std;
|
||||
using namespace IMATH_NAMESPACE;
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
void
|
||||
writeFiles (const char completeScanLinesName[],
|
||||
const char incompleteScanLinesName[],
|
||||
const char completeTilesName[],
|
||||
const char incompleteTilesName[],
|
||||
int width,
|
||||
int height,
|
||||
int tileXSize,
|
||||
int tileYSize)
|
||||
{
|
||||
Array2D <Rgba> pixels (height, width);
|
||||
|
||||
for (int y = 0; y < height; ++y)
|
||||
for (int x = 0; x < width; ++x)
|
||||
pixels[y][x] = Rgba (x, y, 0.0, 1.0);
|
||||
|
||||
{
|
||||
RgbaOutputFile out (completeScanLinesName, width, height);
|
||||
out.setFrameBuffer (&pixels[0][0], 1, width);
|
||||
out.writePixels (height);
|
||||
}
|
||||
|
||||
{
|
||||
RgbaOutputFile out (incompleteScanLinesName, width, height);
|
||||
out.setFrameBuffer (&pixels[0][0], 1, width);
|
||||
out.writePixels (height - 1);
|
||||
}
|
||||
|
||||
{
|
||||
TiledRgbaOutputFile out (completeTilesName,
|
||||
width, height,
|
||||
tileXSize, tileYSize,
|
||||
ONE_LEVEL);
|
||||
|
||||
out.setFrameBuffer (&pixels[0][0], 1, width);
|
||||
out.writeTiles (0, out.numXTiles() - 1, 0, out.numYTiles() - 1);
|
||||
}
|
||||
|
||||
{
|
||||
TiledRgbaOutputFile out (incompleteTilesName,
|
||||
width, height,
|
||||
tileXSize, tileYSize,
|
||||
ONE_LEVEL);
|
||||
|
||||
out.setFrameBuffer (&pixels[0][0], 1, width);
|
||||
out.writeTiles (0, out.numXTiles() - 1, 0, out.numYTiles() - 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
checkFiles (const char completeScanLinesName[],
|
||||
const char incompleteScanLinesName[],
|
||||
const char completeTilesName[],
|
||||
const char incompleteTilesName[])
|
||||
{
|
||||
{
|
||||
RgbaInputFile in (completeScanLinesName);
|
||||
assert (in.isComplete());
|
||||
}
|
||||
|
||||
{
|
||||
RgbaInputFile in (incompleteScanLinesName);
|
||||
assert (!in.isComplete());
|
||||
}
|
||||
|
||||
{
|
||||
RgbaInputFile in (completeTilesName);
|
||||
assert (in.isComplete());
|
||||
}
|
||||
|
||||
{
|
||||
RgbaInputFile in (incompleteTilesName);
|
||||
assert (!in.isComplete());
|
||||
}
|
||||
|
||||
{
|
||||
TiledRgbaInputFile in (completeTilesName);
|
||||
assert (in.isComplete());
|
||||
}
|
||||
|
||||
{
|
||||
TiledRgbaInputFile in (incompleteTilesName);
|
||||
assert (!in.isComplete());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
void
|
||||
testIsComplete (const std::string &tempDir)
|
||||
{
|
||||
try
|
||||
{
|
||||
cout << "Testing isComplete() function" << endl;
|
||||
|
||||
std::string csl = tempDir + "imf_test_complete_sl.exr";
|
||||
std::string icsl = tempDir + "imf_test_incomplete_sl.exr";
|
||||
std::string ct = tempDir + "imf_test_complete_t.exr";
|
||||
std::string ict = tempDir + "imf_test_incomplete_t.exr";
|
||||
|
||||
writeFiles (csl.c_str(), icsl.c_str(), ct.c_str(), ict.c_str(), 327, 289, 17, 17);
|
||||
checkFiles (csl.c_str(), icsl.c_str(), ct.c_str(), ict.c_str());
|
||||
|
||||
remove (csl.c_str());
|
||||
remove (icsl.c_str());
|
||||
remove (ct.c_str());
|
||||
remove (ict.c_str());
|
||||
|
||||
cout << "ok\n" << endl;
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
cerr << "ERROR -- caught exception: " << e.what() << endl;
|
||||
assert (false);
|
||||
}
|
||||
}
|
||||
42
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testIsComplete.h
Normal file
42
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testIsComplete.h
Normal file
@@ -0,0 +1,42 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2005-2012, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
#include <string>
|
||||
|
||||
void testIsComplete (const std::string &tempDir);
|
||||
|
||||
|
||||
227
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testLineOrder.cpp
Normal file
227
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testLineOrder.cpp
Normal file
@@ -0,0 +1,227 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include <ImfOutputFile.h>
|
||||
#include <ImfInputFile.h>
|
||||
#include <ImfChannelList.h>
|
||||
#include <ImfArray.h>
|
||||
#include <ImfThreading.h>
|
||||
#include "IlmThread.h"
|
||||
#include "half.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
using namespace OPENEXR_IMF_NAMESPACE;
|
||||
using namespace std;
|
||||
using namespace IMATH_NAMESPACE;
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
void
|
||||
fillPixels (Array2D<half> &ph, int width, int height)
|
||||
{
|
||||
for (int y = 0; y < height; ++y)
|
||||
for (int x = 0; x < width; ++x)
|
||||
ph[y][x] = x % 10 + 10 * (y % 17);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
writeRead (const Array2D<half> &ph1,
|
||||
const char fileName[],
|
||||
int width,
|
||||
int height,
|
||||
LineOrder lorder)
|
||||
{
|
||||
//
|
||||
// Write the pixel data in ph1 to an image file using
|
||||
// the specified line order. Read the pixel data back
|
||||
// from the file in pseudo-random order and verify that
|
||||
// the data did not change.
|
||||
//
|
||||
|
||||
cout << "line order " << lorder <<
|
||||
":" << flush;
|
||||
|
||||
Header hdr (width, height);
|
||||
hdr.lineOrder() = lorder;
|
||||
|
||||
hdr.channels().insert ("H", // name
|
||||
Channel (HALF, // type
|
||||
1, // xSampling
|
||||
1) // ySampling
|
||||
);
|
||||
|
||||
{
|
||||
FrameBuffer fb;
|
||||
|
||||
fb.insert ("H", // name
|
||||
Slice (HALF, // type
|
||||
(char *) &ph1[0][0], // base
|
||||
sizeof (ph1[0][0]), // xStride
|
||||
sizeof (ph1[0][0]) * width, // yStride
|
||||
1, // xSampling
|
||||
1) // ySampling
|
||||
);
|
||||
|
||||
cout << " writing" << flush;
|
||||
|
||||
remove (fileName);
|
||||
OutputFile out (fileName, hdr);
|
||||
out.setFrameBuffer (fb);
|
||||
out.writePixels (height);
|
||||
}
|
||||
|
||||
{
|
||||
cout << " reading" << flush;
|
||||
|
||||
InputFile in (fileName);
|
||||
|
||||
const Box2i &dw = in.header().dataWindow();
|
||||
int w = dw.max.x - dw.min.x + 1;
|
||||
int h = dw.max.y - dw.min.y + 1;
|
||||
int dx = dw.min.x;
|
||||
int dy = dw.min.y;
|
||||
|
||||
Array2D<half> ph2 (h, w);
|
||||
|
||||
FrameBuffer fb;
|
||||
|
||||
fb.insert ("H", // name
|
||||
Slice (HALF, // type
|
||||
(char *) &ph2[-dy][-dx], // base
|
||||
sizeof (ph2[0][0]), // xStride
|
||||
sizeof (ph2[0][0]) * w, // yStride
|
||||
1, // xSampling
|
||||
1) // ySampling
|
||||
);
|
||||
|
||||
in.setFrameBuffer (fb);
|
||||
|
||||
//
|
||||
// Read the scan lines in this order:
|
||||
// 0, N, 2N, 3N, ... 1, N+1, 2N+1, ... 2, N+2, 2N+2, ...
|
||||
//
|
||||
|
||||
const int N = 7;
|
||||
|
||||
for (int i = 0; i < N; ++i)
|
||||
for (int y = dw.min.y + i; y <= dw.max.y; y += N)
|
||||
in.readPixels (y);
|
||||
|
||||
cout << " comparing" << flush;
|
||||
|
||||
assert (in.header().displayWindow() == hdr.displayWindow());
|
||||
assert (in.header().dataWindow() == hdr.dataWindow());
|
||||
assert (in.header().pixelAspectRatio() == hdr.pixelAspectRatio());
|
||||
assert (in.header().screenWindowCenter() == hdr.screenWindowCenter());
|
||||
assert (in.header().screenWindowWidth() == hdr.screenWindowWidth());
|
||||
assert (in.header().lineOrder() == hdr.lineOrder());
|
||||
assert (in.header().compression() == hdr.compression());
|
||||
|
||||
ChannelList::ConstIterator hi = hdr.channels().begin();
|
||||
ChannelList::ConstIterator ii = in.header().channels().begin();
|
||||
|
||||
while (hi != hdr.channels().end())
|
||||
{
|
||||
assert (!strcmp (hi.name(), ii.name()));
|
||||
assert (hi.channel().type == ii.channel().type);
|
||||
assert (hi.channel().xSampling == ii.channel().xSampling);
|
||||
assert (hi.channel().ySampling == ii.channel().ySampling);
|
||||
|
||||
++hi;
|
||||
++ii;
|
||||
}
|
||||
|
||||
assert (ii == in.header().channels().end());
|
||||
|
||||
for (int y = 0; y < h; ++y)
|
||||
for (int x = 0; x < w; ++x)
|
||||
assert (ph1[y][x] == ph2[y][x]);
|
||||
}
|
||||
|
||||
remove (fileName);
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
void
|
||||
testLineOrder (const std::string &tempDir)
|
||||
{
|
||||
try
|
||||
{
|
||||
cout << "Testing line order and random access to scan lines" << endl;
|
||||
|
||||
const int W = 117;
|
||||
const int H = 97;
|
||||
|
||||
Array2D<half> ph (H, W);
|
||||
fillPixels (ph, W, H);
|
||||
|
||||
int maxThreads = ILMTHREAD_NAMESPACE::supportsThreads()? 3: 0;
|
||||
|
||||
for (int n = 0; n <= maxThreads; ++n)
|
||||
{
|
||||
if (ILMTHREAD_NAMESPACE::supportsThreads())
|
||||
{
|
||||
setGlobalThreadCount (n);
|
||||
cout << "\nnumber of threads: " << globalThreadCount() << endl;
|
||||
}
|
||||
|
||||
std::string filename = tempDir + "imf_test_lorder.exr";
|
||||
|
||||
for (int lorder = 0; lorder < RANDOM_Y; ++lorder)
|
||||
{
|
||||
writeRead (ph,
|
||||
filename.c_str(),
|
||||
W, H,
|
||||
LineOrder (lorder));
|
||||
}
|
||||
}
|
||||
|
||||
cout << "ok\n" << endl;
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
cerr << "ERROR -- caught exception: " << e.what() << endl;
|
||||
assert (false);
|
||||
}
|
||||
}
|
||||
41
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testLineOrder.h
Normal file
41
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testLineOrder.h
Normal file
@@ -0,0 +1,41 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
#include <string>
|
||||
|
||||
void testLineOrder (const std::string &tempDir);
|
||||
|
||||
256
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testLut.cpp
Normal file
256
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testLut.cpp
Normal file
@@ -0,0 +1,256 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#include <ImfLut.h>
|
||||
#include <ImfArray.h>
|
||||
#include "ImathRandom.h"
|
||||
#include <iostream>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
using namespace OPENEXR_IMF_NAMESPACE;
|
||||
using namespace std;
|
||||
using namespace IMATH_NAMESPACE;
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
half
|
||||
one (half)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
testHalfLut ()
|
||||
{
|
||||
const int NX = 67;
|
||||
const int NY = 31;
|
||||
|
||||
Array2D<half> h (NY, NX);
|
||||
HalfLut lut (one);
|
||||
|
||||
//
|
||||
// apply (data, nData, stride);
|
||||
//
|
||||
|
||||
for (int y = 0; y < NY; ++y)
|
||||
for (int x = 0; x < NX; ++x)
|
||||
h[y][x] = 0;
|
||||
|
||||
lut.apply (&h[0][0], NX * NY, 1);
|
||||
|
||||
for (int y = 0; y < NY; ++y)
|
||||
for (int x = 0; x < NX; ++x)
|
||||
assert (h[y][x] == 1);
|
||||
|
||||
//
|
||||
// apply (slice, dataWindow);
|
||||
//
|
||||
|
||||
for (int y = 0; y < NY; ++y)
|
||||
for (int x = 0; x < NX; ++x)
|
||||
h[y][x] = 0;
|
||||
|
||||
Slice s (HALF, // type
|
||||
(char *) &h[0][0], // base
|
||||
sizeof (h[0][0]), // xStride
|
||||
sizeof (h[0][0]) * NX, // yStride
|
||||
1, 1); // xSampling, ySampling
|
||||
|
||||
Box2i dw (V2i (3, 5), V2i (45, 27));
|
||||
|
||||
lut.apply (s, dw);
|
||||
|
||||
for (int y = 0; y < NY; ++y)
|
||||
for (int x = 0; x < NX; ++x)
|
||||
if (dw.intersects (V2i (x, y)))
|
||||
assert (h[y][x] == 1);
|
||||
else
|
||||
assert (h[y][x] == 0);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
testRgbaLut ()
|
||||
{
|
||||
const int NX = 67;
|
||||
const int NY = 31;
|
||||
|
||||
Array2D<Rgba> rgba (NY, NX);
|
||||
RgbaLut lut (one, WRITE_RGB);
|
||||
|
||||
//
|
||||
// apply (data, nData, stride);
|
||||
//
|
||||
|
||||
for (int y = 0; y < NY; ++y)
|
||||
{
|
||||
for (int x = 0; x < NX; ++x)
|
||||
{
|
||||
rgba[y][x].r = 0;
|
||||
rgba[y][x].g = 0;
|
||||
rgba[y][x].b = 0;
|
||||
rgba[y][x].a = 0;
|
||||
}
|
||||
}
|
||||
|
||||
lut.apply (&rgba[0][0], NX * NY, 1);
|
||||
|
||||
for (int y = 0; y < NY; ++y)
|
||||
{
|
||||
for (int x = 0; x < NX; ++x)
|
||||
{
|
||||
assert (rgba[y][x].r == 1);
|
||||
assert (rgba[y][x].g == 1);
|
||||
assert (rgba[y][x].b == 1);
|
||||
assert (rgba[y][x].a == 0);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// apply (base, xStride, yStride, dataWindow);
|
||||
//
|
||||
|
||||
for (int y = 0; y < NY; ++y)
|
||||
{
|
||||
for (int x = 0; x < NX; ++x)
|
||||
{
|
||||
rgba[y][x].r = 0;
|
||||
rgba[y][x].g = 0;
|
||||
rgba[y][x].b = 0;
|
||||
rgba[y][x].a = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Box2i dw (V2i (3, 5), V2i (45, 27));
|
||||
|
||||
lut.apply (&rgba[0][0], 1, NX, dw);
|
||||
|
||||
for (int y = 0; y < NY; ++y)
|
||||
{
|
||||
for (int x = 0; x < NX; ++x)
|
||||
{
|
||||
if (dw.intersects (V2i (x, y)))
|
||||
{
|
||||
assert (rgba[y][x].r == 1);
|
||||
assert (rgba[y][x].g == 1);
|
||||
assert (rgba[y][x].b == 1);
|
||||
assert (rgba[y][x].a == 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert (rgba[y][x].r == 0);
|
||||
assert (rgba[y][x].g == 0);
|
||||
assert (rgba[y][x].b == 0);
|
||||
assert (rgba[y][x].a == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
testRounding ()
|
||||
{
|
||||
//
|
||||
// For each rounding function, f,
|
||||
// f(f(x)) == f(x) must be true.
|
||||
//
|
||||
|
||||
Rand32 rand;
|
||||
|
||||
for (int i = 0; i < 10000; ++i)
|
||||
{
|
||||
half h = rand.nextf (HALF_MIN, HALF_MAX);
|
||||
assert (round12log (h) == round12log (round12log (h)));
|
||||
}
|
||||
|
||||
for (int n = 0; n <= 10; ++n)
|
||||
{
|
||||
roundNBit rn (n);
|
||||
|
||||
for (int i = 0; i < 10000; ++i)
|
||||
{
|
||||
half h = rand.nextf (HALF_MIN, HALF_MAX);
|
||||
assert (rn (h) == rn (rn (h)));
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Special cases:
|
||||
//
|
||||
|
||||
assert (round12log (-1) == 0);
|
||||
assert (round12log (0) == 0);
|
||||
assert (round12log (0.5) == 0.5);
|
||||
assert (round12log (1) == 1);
|
||||
assert (round12log (2) == 2);
|
||||
|
||||
roundNBit r3 (3);
|
||||
|
||||
assert (r3 (-1) == -1);
|
||||
assert (r3 (0) == 0);
|
||||
assert (r3 (0.5) == 0.5);
|
||||
assert (r3 (1) == 1);
|
||||
assert (r3 (2) == 2);
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
void
|
||||
testLut (const std::string&)
|
||||
{
|
||||
try
|
||||
{
|
||||
cout << "Testing lookup tables" << endl;
|
||||
|
||||
testHalfLut();
|
||||
testRgbaLut();
|
||||
testRounding();
|
||||
|
||||
cout << "ok\n" << endl;
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
cerr << "ERROR -- caught exception: " << e.what() << endl;
|
||||
assert (false);
|
||||
}
|
||||
}
|
||||
41
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testLut.h
Normal file
41
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testLut.h
Normal file
@@ -0,0 +1,41 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
#include <string>
|
||||
|
||||
void testLut (const std::string &tempDir);
|
||||
|
||||
140
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testMagic.cpp
Normal file
140
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testMagic.cpp
Normal file
@@ -0,0 +1,140 @@
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2003-2012, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <ImfVersion.h>
|
||||
#include <ImfTestFile.h>
|
||||
#include <ImfStdIO.h>
|
||||
#include <iostream>
|
||||
#include <exception>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifndef ILM_IMF_TEST_IMAGEDIR
|
||||
#define ILM_IMF_TEST_IMAGEDIR
|
||||
#endif
|
||||
|
||||
|
||||
using namespace OPENEXR_IMF_NAMESPACE;
|
||||
using namespace std;
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
void
|
||||
testFile1 (const char fileName[], bool isImfFile)
|
||||
{
|
||||
cout << fileName << " " << flush;
|
||||
|
||||
ifstream f (fileName, ios_base::binary);
|
||||
assert (!!f);
|
||||
|
||||
char bytes[4];
|
||||
f.read (bytes, sizeof (bytes));
|
||||
|
||||
assert (!!f && isImfFile == isImfMagic (bytes));
|
||||
|
||||
cout << "is " << (isImfMagic (bytes)? "": "not ") << "an OpenEXR file\n";
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
testFile2 (const char fileName[], bool exists, bool exrFile, bool tiledFile)
|
||||
{
|
||||
cout << fileName << " " << flush;
|
||||
|
||||
bool exr, tiled;
|
||||
|
||||
exr = isOpenExrFile (fileName, tiled);
|
||||
assert (exr == exrFile && tiled == tiledFile);
|
||||
|
||||
exr = isOpenExrFile (fileName);
|
||||
assert (exr == exrFile);
|
||||
|
||||
tiled = isTiledOpenExrFile (fileName);
|
||||
assert (tiled == tiledFile);
|
||||
|
||||
if (exists)
|
||||
{
|
||||
StdIFStream is (fileName);
|
||||
|
||||
exr = isOpenExrFile (is, tiled);
|
||||
assert (exr == exrFile && tiled == tiledFile);
|
||||
|
||||
if (exr)
|
||||
assert (is.tellg() == 0);
|
||||
|
||||
exr = isOpenExrFile (is);
|
||||
assert (exr == exrFile);
|
||||
|
||||
if (exr)
|
||||
assert (is.tellg() == 0);
|
||||
|
||||
tiled = isTiledOpenExrFile (is);
|
||||
assert (tiled == tiledFile);
|
||||
|
||||
if (tiled)
|
||||
assert (is.tellg() == 0);
|
||||
}
|
||||
|
||||
cout << (exists? "exists": "does not exist") << ", " <<
|
||||
(exrFile? "is an OpenEXR file": "is not an OpenEXR file") << ", " <<
|
||||
(tiledFile? "is tiled": "is not tiled") << endl;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
void
|
||||
testMagic (const std::string &)
|
||||
{
|
||||
try
|
||||
{
|
||||
cout << "Testing magic number" << endl;
|
||||
|
||||
testFile1 (ILM_IMF_TEST_IMAGEDIR "comp_none.exr", true);
|
||||
testFile1 (ILM_IMF_TEST_IMAGEDIR "invalid.exr", false);
|
||||
|
||||
testFile2 (ILM_IMF_TEST_IMAGEDIR "tiled.exr", true, true, true);
|
||||
testFile2 (ILM_IMF_TEST_IMAGEDIR "comp_none.exr", true, true, false);
|
||||
testFile2 (ILM_IMF_TEST_IMAGEDIR "invalid.exr", true, false, false);
|
||||
testFile2 (ILM_IMF_TEST_IMAGEDIR "does_not_exist.exr", false, false, false);
|
||||
|
||||
cout << "ok\n" << endl;
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
cerr << "ERROR -- caught exception: " << e.what() << endl;
|
||||
assert (false);
|
||||
}
|
||||
}
|
||||
38
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testMagic.h
Normal file
38
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testMagic.h
Normal file
@@ -0,0 +1,38 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2003-2012, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include <string>
|
||||
|
||||
void testMagic(const std::string &tempDir);
|
||||
744
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testMultiPartApi.cpp
Normal file
744
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testMultiPartApi.cpp
Normal file
@@ -0,0 +1,744 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "tmpDir.h"
|
||||
#include "testMultiPartApi.h"
|
||||
|
||||
#include <ImfPartType.h>
|
||||
#include <ImfMultiPartInputFile.h>
|
||||
#include <ImfMultiPartOutputFile.h>
|
||||
#include <ImfOutputFile.h>
|
||||
#include <ImfTiledOutputFile.h>
|
||||
#include <ImfGenericOutputFile.h>
|
||||
#include <ImfArray.h>
|
||||
#include <ImfChannelList.h>
|
||||
#include <ImfOutputPart.h>
|
||||
#include <ImfInputPart.h>
|
||||
#include <ImfTiledOutputPart.h>
|
||||
#include <ImfTiledInputPart.h>
|
||||
#include <ImfTiledMisc.h>
|
||||
|
||||
namespace IMF = OPENEXR_IMF_NAMESPACE;
|
||||
using namespace IMF;
|
||||
using namespace std;
|
||||
using namespace IMATH_NAMESPACE;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
const int height = 263;
|
||||
const int width = 197;
|
||||
|
||||
struct Task
|
||||
{
|
||||
int partNumber;
|
||||
int tx, ty, lx, ly;
|
||||
|
||||
Task(int partNumber):
|
||||
partNumber(partNumber)
|
||||
{}
|
||||
|
||||
Task(int partNumber, int tx, int ty, int lx, int ly):
|
||||
partNumber(partNumber),
|
||||
tx(tx),
|
||||
ty(ty),
|
||||
lx(lx),
|
||||
ly(ly)
|
||||
{}
|
||||
};
|
||||
|
||||
vector<Header> headers;
|
||||
vector<int> pixelTypes;
|
||||
vector<int> partTypes;
|
||||
vector<int> levelModes;
|
||||
|
||||
template <class T>
|
||||
void fillPixels (Array2D<T> &ph, int width, int height)
|
||||
{
|
||||
ph.resizeErase(height, width);
|
||||
for (int y = 0; y < height; ++y)
|
||||
for (int x = 0; x < width; ++x)
|
||||
{
|
||||
//
|
||||
// We do this because half cannot store number bigger than 2048 exactly.
|
||||
//
|
||||
ph[y][x] = (y * width + x) % 2049;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool checkPixels (Array2D<T> &ph, int lx, int rx, int ly, int ry, int width)
|
||||
{
|
||||
for (int y = ly; y <= ry; ++y)
|
||||
for (int x = lx; x <= rx; ++x)
|
||||
if (ph[y][x] != (y * width + x) % 2049)
|
||||
{
|
||||
cout << "value at " << x << ", " << y << ": " << ph[y][x]
|
||||
<< ", should be " << (y * width + x) % 2049 << endl << flush;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool checkPixels (Array2D<T> &ph, int width, int height)
|
||||
{
|
||||
return checkPixels<T> (ph, 0, width - 1, 0, height - 1, width);
|
||||
}
|
||||
|
||||
void generateRandomHeaders(int partCount, vector<Header>& headers, vector<Task>& taskList)
|
||||
{
|
||||
headers.clear();
|
||||
for (int i = 0; i < partCount; i++)
|
||||
{
|
||||
Header header(width, height);
|
||||
int pixelType = rand() % 3;
|
||||
int partType = rand() % 2;
|
||||
pixelTypes[i] = pixelType;
|
||||
partTypes[i] = partType;
|
||||
|
||||
stringstream ss;
|
||||
ss << i;
|
||||
header.setName(ss.str());
|
||||
|
||||
switch (pixelType)
|
||||
{
|
||||
case 0:
|
||||
header.channels().insert("UINT", Channel(IMF::UINT));
|
||||
break;
|
||||
case 1:
|
||||
header.channels().insert("FLOAT", Channel(IMF::FLOAT));
|
||||
break;
|
||||
case 2:
|
||||
header.channels().insert("HALF", Channel(IMF::HALF));
|
||||
break;
|
||||
}
|
||||
|
||||
switch (partType)
|
||||
{
|
||||
case 0:
|
||||
header.setType(SCANLINEIMAGE);
|
||||
break;
|
||||
case 1:
|
||||
header.setType(TILEDIMAGE);
|
||||
break;
|
||||
}
|
||||
|
||||
int tileX;
|
||||
int tileY;
|
||||
int levelMode;
|
||||
if (partType == 1)
|
||||
{
|
||||
tileX = rand() % width + 1;
|
||||
tileY = rand() % height + 1;
|
||||
levelMode = rand() % 3;
|
||||
levelModes[i] = levelMode;
|
||||
LevelMode lm;
|
||||
switch (levelMode)
|
||||
{
|
||||
case 0:
|
||||
lm = ONE_LEVEL;
|
||||
break;
|
||||
case 1:
|
||||
lm = MIPMAP_LEVELS;
|
||||
break;
|
||||
case 2:
|
||||
lm = RIPMAP_LEVELS;
|
||||
break;
|
||||
}
|
||||
header.setTileDescription(TileDescription(tileX, tileY, lm));
|
||||
}
|
||||
|
||||
//
|
||||
// Add lines or tiles to task list.
|
||||
//
|
||||
if (partType == 0)
|
||||
{
|
||||
for (int j = 0; j < height; j++)
|
||||
taskList.push_back(Task(i));
|
||||
}
|
||||
else
|
||||
{
|
||||
int numXLevel;
|
||||
int numYLevel;
|
||||
int* numXTiles;
|
||||
int* numYTiles;
|
||||
precalculateTileInfo (header.tileDescription(),
|
||||
0, width - 1,
|
||||
0, height - 1,
|
||||
numXTiles, numYTiles,
|
||||
numXLevel, numYLevel);
|
||||
|
||||
for (int lx = 0; lx < numXLevel; lx++)
|
||||
for (int ly = 0; ly < numYLevel; ly++)
|
||||
{
|
||||
if (levelMode == 1)
|
||||
if (lx != ly) continue;
|
||||
|
||||
// Get all tasks for this level.
|
||||
for (int tx = 0; tx < numXTiles[lx]; tx++)
|
||||
for (int ty = 0; ty < numYTiles[ly]; ty++)
|
||||
taskList.push_back(Task(i, tx, ty, lx, ly));
|
||||
}
|
||||
|
||||
delete[] numXTiles;
|
||||
delete[] numYTiles;
|
||||
}
|
||||
|
||||
// if (partType == 0)
|
||||
// {
|
||||
// cout << "pixelType = " << pixelType << " partType = " << partType
|
||||
// << endl << flush;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// cout << "pixelType = " << pixelType << " partType = " << partType
|
||||
// << " levelMode = " << levelModes[i] << endl << flush;
|
||||
// }
|
||||
|
||||
headers.push_back(header);
|
||||
}
|
||||
}
|
||||
|
||||
void setOutputFrameBuffer(FrameBuffer& frameBuffer, int pixelType,
|
||||
Array2D<unsigned int>& uData, Array2D<float>& fData,
|
||||
Array2D<half>& hData, int width)
|
||||
{
|
||||
switch (pixelType)
|
||||
{
|
||||
case 0:
|
||||
frameBuffer.insert ("UINT",
|
||||
Slice (IMF::UINT,
|
||||
(char *) (&uData[0][0]),
|
||||
sizeof (uData[0][0]) * 1,
|
||||
sizeof (uData[0][0]) * width));
|
||||
break;
|
||||
case 1:
|
||||
frameBuffer.insert ("FLOAT",
|
||||
Slice (IMF::FLOAT,
|
||||
(char *) (&fData[0][0]),
|
||||
sizeof (fData[0][0]) * 1,
|
||||
sizeof (fData[0][0]) * width));
|
||||
break;
|
||||
case 2:
|
||||
frameBuffer.insert ("HALF",
|
||||
Slice (IMF::HALF,
|
||||
(char *) (&hData[0][0]),
|
||||
sizeof (hData[0][0]) * 1,
|
||||
sizeof (hData[0][0]) * width));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void setInputFrameBuffer(FrameBuffer& frameBuffer, int pixelType,
|
||||
Array2D<unsigned int>& uData, Array2D<float>& fData,
|
||||
Array2D<half>& hData, int width, int height)
|
||||
{
|
||||
switch (pixelType)
|
||||
{
|
||||
case 0:
|
||||
uData.resizeErase(height, width);
|
||||
frameBuffer.insert ("UINT",
|
||||
Slice (IMF::UINT,
|
||||
(char *) (&uData[0][0]),
|
||||
sizeof (uData[0][0]) * 1,
|
||||
sizeof (uData[0][0]) * width,
|
||||
1, 1,
|
||||
0));
|
||||
break;
|
||||
case 1:
|
||||
fData.resizeErase(height, width);
|
||||
frameBuffer.insert ("FLOAT",
|
||||
Slice (IMF::FLOAT,
|
||||
(char *) (&fData[0][0]),
|
||||
sizeof (fData[0][0]) * 1,
|
||||
sizeof (fData[0][0]) * width,
|
||||
1, 1,
|
||||
0));
|
||||
break;
|
||||
case 2:
|
||||
hData.resizeErase(height, width);
|
||||
frameBuffer.insert ("HALF",
|
||||
Slice (IMF::HALF,
|
||||
(char *) (&hData[0][0]),
|
||||
sizeof (hData[0][0]) * 1,
|
||||
sizeof (hData[0][0]) * width,
|
||||
1, 1,
|
||||
0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
generateRandomFile (int partCount, const std::string & fn)
|
||||
{
|
||||
//
|
||||
// Init data.
|
||||
//
|
||||
Array2D<half> halfData;
|
||||
Array2D<float> floatData;
|
||||
Array2D<unsigned int> uintData;
|
||||
fillPixels<unsigned int>(uintData, width, height);
|
||||
fillPixels<half>(halfData, width, height);
|
||||
fillPixels<float>(floatData, width, height);
|
||||
|
||||
Array2D< Array2D< half > >* tiledHalfData = new Array2D< Array2D< half > >[partCount];
|
||||
Array2D< Array2D< float > >* tiledFloatData = new Array2D< Array2D< float > >[partCount];
|
||||
Array2D< Array2D< unsigned int > >* tiledUintData = new Array2D< Array2D< unsigned int > >[partCount];
|
||||
|
||||
vector<GenericOutputFile*> outputfiles;
|
||||
vector<Task> taskList;
|
||||
|
||||
pixelTypes.resize(partCount);
|
||||
partTypes.resize(partCount);
|
||||
levelModes.resize(partCount);
|
||||
|
||||
//
|
||||
// Generate headers and data.
|
||||
//
|
||||
cout << "Generating headers and data " << flush;
|
||||
generateRandomHeaders(partCount, headers, taskList);
|
||||
|
||||
//
|
||||
// Shuffle tasks.
|
||||
//
|
||||
cout << "Shuffling " << taskList.size() << " tasks " << flush;
|
||||
int taskListSize = taskList.size();
|
||||
for (int i = 0; i < taskListSize; i++)
|
||||
{
|
||||
int a, b;
|
||||
a = rand() % taskListSize;
|
||||
b = rand() % taskListSize;
|
||||
swap(taskList[a], taskList[b]);
|
||||
}
|
||||
|
||||
remove(fn.c_str());
|
||||
MultiPartOutputFile file(fn.c_str(), &headers[0],headers.size());
|
||||
|
||||
//
|
||||
// Writing tasks.
|
||||
//
|
||||
cout << "Writing tasks " << flush;
|
||||
|
||||
//
|
||||
// Pre-generating frameBuffers.
|
||||
//
|
||||
vector<void *> parts;
|
||||
vector<FrameBuffer> frameBuffers(partCount);
|
||||
Array<Array2D<FrameBuffer> > tiledFrameBuffers(partCount);
|
||||
for (int i = 0; i < partCount; i++)
|
||||
{
|
||||
if (partTypes[i] == 0)
|
||||
{
|
||||
OutputPart* part = new OutputPart(file, i);
|
||||
parts.push_back((void*) part);
|
||||
|
||||
FrameBuffer& frameBuffer = frameBuffers[i];
|
||||
|
||||
setOutputFrameBuffer(frameBuffer, pixelTypes[i], uintData, floatData, halfData, width);
|
||||
|
||||
part->setFrameBuffer(frameBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
TiledOutputPart* part = new TiledOutputPart(file, i);
|
||||
parts.push_back((void*) part);
|
||||
|
||||
int numXLevels = part->numXLevels();
|
||||
int numYLevels = part->numYLevels();
|
||||
|
||||
// Allocating space.
|
||||
switch (pixelTypes[i])
|
||||
{
|
||||
case 0:
|
||||
tiledUintData[i].resizeErase(numYLevels, numXLevels);
|
||||
break;
|
||||
case 1:
|
||||
tiledFloatData[i].resizeErase(numYLevels, numXLevels);
|
||||
break;
|
||||
case 2:
|
||||
tiledHalfData[i].resizeErase(numYLevels, numXLevels);
|
||||
break;
|
||||
}
|
||||
|
||||
tiledFrameBuffers[i].resizeErase(numYLevels, numXLevels);
|
||||
|
||||
for (int xLevel = 0; xLevel < numXLevels; xLevel++)
|
||||
for (int yLevel = 0; yLevel < numYLevels; yLevel++)
|
||||
{
|
||||
if (!part->isValidLevel(xLevel, yLevel))
|
||||
continue;
|
||||
|
||||
int w = part->levelWidth(xLevel);
|
||||
int h = part->levelHeight(yLevel);
|
||||
|
||||
FrameBuffer& frameBuffer = tiledFrameBuffers[i][yLevel][xLevel];
|
||||
|
||||
switch (pixelTypes[i])
|
||||
{
|
||||
case 0:
|
||||
fillPixels<unsigned int>(tiledUintData[i][yLevel][xLevel], w, h);
|
||||
break;
|
||||
case 1:
|
||||
fillPixels<float>(tiledFloatData[i][yLevel][xLevel], w, h);
|
||||
break;
|
||||
case 2:
|
||||
fillPixels<half>(tiledHalfData[i][yLevel][xLevel], w, h);
|
||||
break;
|
||||
}
|
||||
setOutputFrameBuffer(frameBuffer, pixelTypes[i],
|
||||
tiledUintData[i][yLevel][xLevel],
|
||||
tiledFloatData[i][yLevel][xLevel],
|
||||
tiledHalfData[i][yLevel][xLevel],
|
||||
w);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Writing tasks.
|
||||
//
|
||||
for (int i = 0; i < taskListSize; i++)
|
||||
{
|
||||
int partNumber = taskList[i].partNumber;
|
||||
int partType = partTypes[partNumber];
|
||||
int pixelType = pixelTypes[partNumber];
|
||||
int levelMode = levelModes[partNumber];
|
||||
if (partType == 0)
|
||||
{
|
||||
OutputPart* part = (OutputPart*) parts[partNumber];
|
||||
part->writePixels();
|
||||
}
|
||||
else
|
||||
{
|
||||
int tx = taskList[i].tx;
|
||||
int ty = taskList[i].ty;
|
||||
int lx = taskList[i].lx;
|
||||
int ly = taskList[i].ly;
|
||||
TiledOutputPart* part = (TiledOutputPart*) parts[partNumber];
|
||||
part->setFrameBuffer(tiledFrameBuffers[partNumber][ly][lx]);
|
||||
part->writeTile(tx, ty, lx, ly);
|
||||
}
|
||||
}
|
||||
|
||||
delete[] tiledHalfData;
|
||||
delete[] tiledUintData;
|
||||
delete[] tiledFloatData;
|
||||
}
|
||||
|
||||
void
|
||||
readWholeFiles (const std::string & fn)
|
||||
{
|
||||
Array2D<unsigned int> uData;
|
||||
Array2D<float> fData;
|
||||
Array2D<half> hData;
|
||||
|
||||
MultiPartInputFile file(fn.c_str());
|
||||
for (size_t i = 0; i < file.parts(); i++)
|
||||
{
|
||||
const Header& header = file.header(i);
|
||||
assert (header.displayWindow() == headers[i].displayWindow());
|
||||
assert (header.dataWindow() == headers[i].dataWindow());
|
||||
assert (header.pixelAspectRatio() == headers[i].pixelAspectRatio());
|
||||
assert (header.screenWindowCenter() == headers[i].screenWindowCenter());
|
||||
assert (header.screenWindowWidth() == headers[i].screenWindowWidth());
|
||||
assert (header.lineOrder() == headers[i].lineOrder());
|
||||
assert (header.compression() == headers[i].compression());
|
||||
|
||||
//
|
||||
// It rarely fails here. Added code to see what's wrong when it happens.
|
||||
//
|
||||
ChannelList::ConstIterator i1 = header.channels().begin();
|
||||
ChannelList::ConstIterator i2 = headers[i].channels().begin();
|
||||
Channel c1 = i1.channel();
|
||||
Channel c2 = i2.channel();
|
||||
if (!(c1 == c2))
|
||||
{
|
||||
cout << " type is " << c1.type << ", should be " << c2.type
|
||||
<< " xSampling is " << c1.xSampling << ", should be " << c2.xSampling
|
||||
<< " ySampling is " << c1.ySampling << ", should be " << c2.ySampling
|
||||
<< " pLinear is " << c1.pLinear << ", should be " << c2.pLinear << flush;
|
||||
}
|
||||
|
||||
assert (header.channels() == headers[i].channels());
|
||||
assert (header.name() == headers[i].name());
|
||||
assert (header.type() == headers[i].type());
|
||||
}
|
||||
|
||||
cout << "Reading whole files " << flush;
|
||||
|
||||
//
|
||||
// Shuffle part numbers.
|
||||
//
|
||||
vector<int> shuffledPartNumber;
|
||||
for (int i = 0; i < headers.size(); i++)
|
||||
shuffledPartNumber.push_back(i);
|
||||
for (int i = 0; i < headers.size(); i++)
|
||||
{
|
||||
int a = rand() % headers.size();
|
||||
int b = rand() % headers.size();
|
||||
swap (shuffledPartNumber[a], shuffledPartNumber[b]);
|
||||
}
|
||||
|
||||
//
|
||||
// Start reading whole files.
|
||||
//
|
||||
int i;
|
||||
int partNumber;
|
||||
try
|
||||
{
|
||||
for (i = 0; i < headers.size(); i++)
|
||||
{
|
||||
partNumber = shuffledPartNumber[i];
|
||||
if (partTypes[partNumber] == 0)
|
||||
{
|
||||
FrameBuffer frameBuffer;
|
||||
setInputFrameBuffer(frameBuffer, pixelTypes[partNumber],
|
||||
uData, fData, hData, width, height);
|
||||
|
||||
InputPart part(file, partNumber);
|
||||
part.setFrameBuffer(frameBuffer);
|
||||
part.readPixels(0, height - 1);
|
||||
switch (pixelTypes[partNumber])
|
||||
{
|
||||
case 0:
|
||||
assert(checkPixels<unsigned int>(uData, width, height));
|
||||
break;
|
||||
case 1:
|
||||
assert(checkPixels<float>(fData, width, height));
|
||||
break;
|
||||
case 2:
|
||||
assert(checkPixels<half>(hData, width, height));
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FrameBuffer frameBuffer;
|
||||
TiledInputPart part(file, partNumber);
|
||||
int numXLevels = part.numXLevels();
|
||||
int numYLevels = part.numYLevels();
|
||||
for (int xLevel = 0; xLevel < numXLevels; xLevel++)
|
||||
for (int yLevel = 0; yLevel < numYLevels; yLevel++)
|
||||
{
|
||||
if (!part.isValidLevel(xLevel, yLevel))
|
||||
continue;
|
||||
|
||||
int w = part.levelWidth(xLevel);
|
||||
int h = part.levelHeight(yLevel);
|
||||
|
||||
setInputFrameBuffer(frameBuffer, pixelTypes[partNumber],
|
||||
uData, fData, hData, width, height);
|
||||
|
||||
part.setFrameBuffer(frameBuffer);
|
||||
int numXTiles = part.numXTiles(xLevel);
|
||||
int numYTiles = part.numYTiles(yLevel);
|
||||
part.readTiles(0, numXTiles - 1, 0, numYTiles - 1, xLevel, yLevel);
|
||||
switch (pixelTypes[partNumber])
|
||||
{
|
||||
case 0:
|
||||
assert(checkPixels<unsigned int>(uData, w, h));
|
||||
break;
|
||||
case 1:
|
||||
assert(checkPixels<float>(fData, w, h));
|
||||
break;
|
||||
case 2:
|
||||
assert(checkPixels<half>(hData, w, h));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
cout << "Error while reading part " << partNumber << endl << flush;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
readPartialFiles (int randomReadCount, const std::string & fn)
|
||||
{
|
||||
Array2D<unsigned int> uData;
|
||||
Array2D<float> fData;
|
||||
Array2D<half> hData;
|
||||
|
||||
cout << "Reading partial files " << flush;
|
||||
MultiPartInputFile file(fn.c_str());
|
||||
//const vector<Header>& headers = file.parts();
|
||||
for (int i = 0; i < randomReadCount; i++)
|
||||
{
|
||||
int partNumber = rand() % headers.size();
|
||||
int partType = partTypes[partNumber];
|
||||
int pixelType = pixelTypes[partNumber];
|
||||
int levelMode = levelModes[partNumber];
|
||||
|
||||
if (partType == 0)
|
||||
{
|
||||
int l1, l2;
|
||||
l1 = rand() % height;
|
||||
l2 = rand() % height;
|
||||
if (l1 > l2) swap(l1, l2);
|
||||
|
||||
InputPart part(file, partNumber);
|
||||
|
||||
FrameBuffer frameBuffer;
|
||||
setInputFrameBuffer(frameBuffer, pixelType,
|
||||
uData, fData, hData, width, height);
|
||||
|
||||
part.setFrameBuffer(frameBuffer);
|
||||
part.readPixels(l1, l2);
|
||||
|
||||
switch (pixelType)
|
||||
{
|
||||
case 0:
|
||||
assert(checkPixels<unsigned int>(uData, 0, width - 1, l1, l2, width));
|
||||
break;
|
||||
case 1:
|
||||
assert(checkPixels<float>(fData, 0, width - 1, l1, l2, width));
|
||||
break;
|
||||
case 2:
|
||||
assert(checkPixels<half>(hData, 0, width - 1, l1, l2, width));
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int tx1, tx2, ty1, ty2;
|
||||
int lx, ly;
|
||||
|
||||
TiledInputPart part(file, partNumber);
|
||||
|
||||
int numXLevels = part.numXLevels();
|
||||
int numYLevels = part.numYLevels();
|
||||
|
||||
lx = rand() % numXLevels;
|
||||
ly = rand() % numYLevels;
|
||||
if (levelMode == 1) ly = lx;
|
||||
|
||||
int w = part.levelWidth(lx);
|
||||
int h = part.levelHeight(ly);
|
||||
|
||||
int numXTiles = part.numXTiles(lx);
|
||||
int numYTiles = part.numYTiles(ly);
|
||||
tx1 = rand() % numXTiles;
|
||||
tx2 = rand() % numXTiles;
|
||||
ty1 = rand() % numYTiles;
|
||||
ty2 = rand() % numYTiles;
|
||||
if (tx1 > tx2) swap(tx1, tx2);
|
||||
if (ty1 > ty2) swap(ty1, ty2);
|
||||
|
||||
FrameBuffer frameBuffer;
|
||||
setInputFrameBuffer(frameBuffer, pixelType,
|
||||
uData, fData, hData, w, h);
|
||||
|
||||
part.setFrameBuffer(frameBuffer);
|
||||
part.readTiles(tx1, tx2, ty1, ty2, lx, ly);
|
||||
|
||||
Box2i b1 = part.dataWindowForTile(tx1, ty1, lx, ly);
|
||||
Box2i b2 = part.dataWindowForTile(tx2, ty2, lx, ly);
|
||||
|
||||
switch (pixelType)
|
||||
{
|
||||
case 0:
|
||||
assert(checkPixels<unsigned int>(uData, b1.min.x, b2.max.x, b1.min.y, b2.max.y,
|
||||
w));
|
||||
break;
|
||||
case 1:
|
||||
assert(checkPixels<float>(fData, b1.min.x, b2.max.x, b1.min.y, b2.max.y,
|
||||
w));
|
||||
break;
|
||||
case 2:
|
||||
assert(checkPixels<half>(hData, b1.min.x, b2.max.x, b1.min.y, b2.max.y,
|
||||
w));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testWriteRead (int partNumber,
|
||||
int runCount,
|
||||
int randomReadCount,
|
||||
const std::string & tempDir)
|
||||
{
|
||||
cout << "Testing file with " << partNumber << " part(s)." << endl << flush;
|
||||
|
||||
std::string fn = tempDir + "imf_test_multipart_api.exr";
|
||||
|
||||
for (int i = 0; i < runCount; i++)
|
||||
{
|
||||
generateRandomFile (partNumber, fn);
|
||||
readWholeFiles (fn);
|
||||
readPartialFiles (randomReadCount, fn);
|
||||
|
||||
remove (fn.c_str());
|
||||
|
||||
cout << endl << flush;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
void testMultiPartApi (const std::string & tempDir)
|
||||
{
|
||||
try
|
||||
{
|
||||
cout << "Testing the multi part APIs for normal use" << endl;
|
||||
|
||||
srand(1);
|
||||
|
||||
testWriteRead ( 1, 2, 5, tempDir);
|
||||
testWriteRead ( 2, 5, 10, tempDir);
|
||||
testWriteRead ( 5, 1, 25, tempDir);
|
||||
testWriteRead (50, 2, 100, tempDir);
|
||||
|
||||
cout << "ok\n" << endl;
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
cerr << "ERROR -- caught exception: " << e.what() << endl;
|
||||
assert (false);
|
||||
}
|
||||
}
|
||||
42
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testMultiPartApi.h
Normal file
42
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testMultiPartApi.h
Normal file
@@ -0,0 +1,42 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef TESTMULTIPARTAPI_H_
|
||||
#define TESTMULTIPARTAPI_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
void testMultiPartApi (const std::string & tempDir);
|
||||
|
||||
#endif /* TESTMULTIPARTAPI_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,42 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef TESTMULTIPARTFILEMIXINGBASIC_H_
|
||||
#define TESTMULTIPARTFILEMIXINGBASIC_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
void testMultiPartFileMixingBasic (const std::string & tempDir);
|
||||
|
||||
#endif /* TESTMULTIPARTFILEMIXINGBASIC_H_ */
|
||||
@@ -0,0 +1,527 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2012, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "testMultiPartSharedAttributes.h"
|
||||
|
||||
#include <ImfMultiPartInputFile.h>
|
||||
#include <ImfMultiPartOutputFile.h>
|
||||
#include <ImfOutputFile.h>
|
||||
#include <ImfTiledOutputFile.h>
|
||||
#include <ImfGenericOutputFile.h>
|
||||
#include <ImfArray.h>
|
||||
#include <ImfChannelList.h>
|
||||
#include <ImfOutputPart.h>
|
||||
#include <ImfInputPart.h>
|
||||
#include <ImfTiledOutputPart.h>
|
||||
#include <ImfTiledInputPart.h>
|
||||
#include <ImfBoxAttribute.h>
|
||||
#include <ImfChromaticitiesAttribute.h>
|
||||
#include <ImfTimeCodeAttribute.h>
|
||||
#include <ImfIntAttribute.h>
|
||||
#include <ImfPartType.h>
|
||||
#include <IexBaseExc.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
namespace IMF = OPENEXR_IMF_NAMESPACE;
|
||||
using namespace IMF;
|
||||
using namespace std;
|
||||
using namespace IMATH_NAMESPACE;
|
||||
|
||||
#ifndef ILM_IMF_TEST_IMAGEDIR
|
||||
#define ILM_IMF_TEST_IMAGEDIR
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
const int height = 263;
|
||||
const int width = 197;
|
||||
|
||||
|
||||
void
|
||||
generateRandomHeaders (int partCount, vector<Header> & headers)
|
||||
{
|
||||
headers.clear();
|
||||
|
||||
for (int i = 0; i < partCount; i++)
|
||||
{
|
||||
Header header(width, height);
|
||||
int pixelType = rand() % 3;
|
||||
int partType = rand() % 2;
|
||||
|
||||
stringstream ss;
|
||||
ss << i;
|
||||
header.setName(ss.str());
|
||||
|
||||
switch (pixelType)
|
||||
{
|
||||
case 0:
|
||||
header.channels().insert("UINT", Channel(IMF::UINT));
|
||||
break;
|
||||
case 1:
|
||||
header.channels().insert("FLOAT", Channel(IMF::FLOAT));
|
||||
break;
|
||||
case 2:
|
||||
header.channels().insert("HALF", Channel(IMF::HALF));
|
||||
break;
|
||||
}
|
||||
|
||||
switch (partType)
|
||||
{
|
||||
case 0:
|
||||
header.setType(IMF::SCANLINEIMAGE);
|
||||
break;
|
||||
case 1:
|
||||
header.setType(IMF::TILEDIMAGE);
|
||||
break;
|
||||
}
|
||||
|
||||
int tileX;
|
||||
int tileY;
|
||||
int levelMode;
|
||||
if (partType == 1)
|
||||
{
|
||||
tileX = rand() % width + 1;
|
||||
tileY = rand() % height + 1;
|
||||
levelMode = rand() % 3;
|
||||
LevelMode lm;
|
||||
switch (levelMode)
|
||||
{
|
||||
case 0:
|
||||
lm = ONE_LEVEL;
|
||||
break;
|
||||
case 1:
|
||||
lm = MIPMAP_LEVELS;
|
||||
break;
|
||||
case 2:
|
||||
lm = RIPMAP_LEVELS;
|
||||
break;
|
||||
}
|
||||
header.setTileDescription(TileDescription(tileX, tileY, lm));
|
||||
}
|
||||
|
||||
headers.push_back(header);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testMultiPartOutputFileForExpectedFailure (const vector<Header> & headers,
|
||||
const std::string & fn,
|
||||
const string & failMessage="")
|
||||
{
|
||||
try
|
||||
{
|
||||
remove(fn.c_str());
|
||||
MultiPartOutputFile file(fn.c_str(), &headers[0],headers.size());
|
||||
cerr << "ERROR -- " << failMessage << endl;
|
||||
assert (false);
|
||||
}
|
||||
catch (const IEX_NAMESPACE::ArgExc & e)
|
||||
{
|
||||
// expected behaviour
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
testDisplayWindow (const vector<Header> & hs, const std::string & fn)
|
||||
{
|
||||
vector<Header> headers(hs);
|
||||
IMATH_NAMESPACE::Box2i newDisplayWindow = headers[0].displayWindow();
|
||||
Header newHeader (newDisplayWindow.size().x+10, newDisplayWindow.size().y+10);
|
||||
newHeader.setType (headers[0].type());
|
||||
newHeader.setName (headers[0].name() + string("_newHeader"));
|
||||
headers.push_back (newHeader);
|
||||
testMultiPartOutputFileForExpectedFailure (headers,
|
||||
fn,
|
||||
"Shared Attributes : displayWindow : should fail for !=values");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
testPixelAspectRatio (const vector<Header> & hs, const std::string & fn)
|
||||
{
|
||||
vector<Header> headers(hs);
|
||||
|
||||
IMATH_NAMESPACE::Box2i newDisplayWindow = headers[0].displayWindow();
|
||||
Header newHeader (headers[0].displayWindow().size().x+1,
|
||||
headers[0].displayWindow().size().y+1,
|
||||
headers[0].pixelAspectRatio() + 1.f);
|
||||
newHeader.setType (headers[0].type());
|
||||
newHeader.setName (headers[0].name() + string("_newHeader"));
|
||||
headers.push_back (newHeader);
|
||||
testMultiPartOutputFileForExpectedFailure (headers,
|
||||
fn,
|
||||
"Shared Attributes : pixelAspecRatio : should fail for !=values");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
testTimeCode (const vector<Header> & hs, const std::string & fn)
|
||||
{
|
||||
vector<Header> headers(hs);
|
||||
|
||||
Header newHeader (headers[0]);
|
||||
newHeader.setName (headers[0].name() + string("_newHeader"));
|
||||
|
||||
|
||||
//
|
||||
// Test against a vector of headers that has no attributes of this type
|
||||
//
|
||||
TimeCode t(1234567);
|
||||
TimeCodeAttribute ta(t);
|
||||
newHeader.insert(TimeCodeAttribute::staticTypeName(), ta);
|
||||
headers.push_back (newHeader);
|
||||
testMultiPartOutputFileForExpectedFailure (headers,
|
||||
fn,
|
||||
"Shared Attributes : timecode : should fail for !presence");
|
||||
|
||||
|
||||
//
|
||||
// Test against a vector of headers that has chromaticities attribute
|
||||
// but of differing value
|
||||
//
|
||||
for (int i=0; i<headers.size(); i++)
|
||||
headers[i].insert (TimeCodeAttribute::staticTypeName(), ta);
|
||||
|
||||
t.setTimeAndFlags (t.timeAndFlags()+1);
|
||||
TimeCodeAttribute tta(t);
|
||||
newHeader.insert (TimeCodeAttribute::staticTypeName(), tta);
|
||||
newHeader.setName (newHeader.name() + string("_+1"));
|
||||
headers.push_back (newHeader);
|
||||
testMultiPartOutputFileForExpectedFailure (headers,
|
||||
fn,
|
||||
"Shared Attributes : timecode : should fail for != values");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
testChromaticities (const vector<Header> & hs, const std::string & fn)
|
||||
{
|
||||
vector<Header> headers(hs);
|
||||
|
||||
Header newHeader (headers[0]);
|
||||
newHeader.setName (headers[0].name() + string("_newHeader"));
|
||||
|
||||
Chromaticities c;
|
||||
ChromaticitiesAttribute ca(c);
|
||||
newHeader.insert (ChromaticitiesAttribute::staticTypeName(), ca);
|
||||
|
||||
//
|
||||
// Test against a vector of headers that has no attributes of this type
|
||||
//
|
||||
headers.push_back (newHeader);
|
||||
testMultiPartOutputFileForExpectedFailure (headers,
|
||||
fn,
|
||||
"Shared Attributes : chromaticities : should fail for !present");
|
||||
|
||||
|
||||
//
|
||||
// Test against a vector of headers that has chromaticities attribute
|
||||
// but of differing value
|
||||
//
|
||||
for (int i=0; i<headers.size(); i++)
|
||||
headers[i].insert (ChromaticitiesAttribute::staticTypeName(), ca);
|
||||
|
||||
c.red += IMATH_NAMESPACE::V2f (1.0f, 1.0f);
|
||||
ChromaticitiesAttribute cca(c);
|
||||
newHeader.insert (ChromaticitiesAttribute::staticTypeName(), cca);
|
||||
headers.push_back (newHeader);
|
||||
testMultiPartOutputFileForExpectedFailure (headers,
|
||||
fn,
|
||||
"Shared Attributes : chromaticities : should fail for != values");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
testSharedAttributes (const std::string & fn)
|
||||
{
|
||||
//
|
||||
// The Shared Attributes are currently:
|
||||
// Display Window
|
||||
// Pixel Aspect Ratio
|
||||
// TimeCode
|
||||
// Chromaticities
|
||||
//
|
||||
|
||||
int partCount = 3;
|
||||
vector<Header> headers;
|
||||
|
||||
|
||||
// This will generate headers that are valid for all parts
|
||||
generateRandomHeaders (partCount, headers);
|
||||
|
||||
// expect this to be successful
|
||||
{
|
||||
remove(fn.c_str());
|
||||
MultiPartOutputFile file(fn.c_str(), &headers[0],headers.size());
|
||||
}
|
||||
|
||||
// Adding a header a that has non-complient standard attributes will throw
|
||||
// an exception.
|
||||
|
||||
// Run the tests
|
||||
testDisplayWindow (headers, fn);
|
||||
testPixelAspectRatio (headers, fn);
|
||||
testTimeCode (headers, fn);
|
||||
testChromaticities (headers, fn);
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
void
|
||||
testDiskAttrValue (const Header & diskHeader, const T & testAttribute)
|
||||
{
|
||||
const string & attrName = testAttribute.typeName();
|
||||
const T & diskAttr = dynamic_cast <const T &> (diskHeader[attrName]);
|
||||
if (diskAttr.value() != testAttribute.value())
|
||||
{
|
||||
throw IEX_NAMESPACE::InputExc ("incorrect value from disk");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
testHeaders (const std::string & fn)
|
||||
{
|
||||
//
|
||||
// In a multipart context the headers must be subject to the following
|
||||
// constraints
|
||||
// * type must be set and valid
|
||||
// * unique names
|
||||
//
|
||||
|
||||
|
||||
vector<Header> headers;
|
||||
|
||||
//
|
||||
// expect this to fail - empty header list
|
||||
//
|
||||
testMultiPartOutputFileForExpectedFailure (headers,
|
||||
fn,
|
||||
"Header : empty header list passed");
|
||||
|
||||
|
||||
//
|
||||
// expect this to fail - header has no image attribute type
|
||||
//
|
||||
Header h;
|
||||
headers.push_back (h);
|
||||
testMultiPartOutputFileForExpectedFailure (headers,
|
||||
fn,
|
||||
"Header : empty image type passed");
|
||||
|
||||
|
||||
//
|
||||
// expect this to fail - header name duplication
|
||||
//
|
||||
headers[0].setType (IMF::SCANLINEIMAGE);
|
||||
Header hh(headers[0]);
|
||||
headers.push_back(hh);
|
||||
testMultiPartOutputFileForExpectedFailure (headers,
|
||||
fn,
|
||||
"Header: duplicate header names passed");
|
||||
|
||||
|
||||
//
|
||||
// expect this to fail - header has incorrect image attribute type
|
||||
//
|
||||
try
|
||||
{
|
||||
headers[0].setType ("invalid image type");
|
||||
cerr << "Header : unsupported image type passed" << endl;
|
||||
assert (false);
|
||||
}
|
||||
catch (const IEX_NAMESPACE::ArgExc & e)
|
||||
{
|
||||
// expected behaviour
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Write and Read the data off disk and check values
|
||||
//
|
||||
TimeCode t(1234567);
|
||||
TimeCodeAttribute ta(t);
|
||||
Chromaticities c;
|
||||
ChromaticitiesAttribute ca(c);
|
||||
vector<IntAttribute> ia;
|
||||
for (int i=0; i<headers.size(); i++)
|
||||
{
|
||||
stringstream ss;
|
||||
ss << i;
|
||||
headers[i].setName (ss.str());
|
||||
headers[i].setType (IMF::SCANLINEIMAGE);
|
||||
headers[i].insert(TimeCodeAttribute::staticTypeName(), ta);
|
||||
headers[i].insert(ChromaticitiesAttribute::staticTypeName(), ca);
|
||||
|
||||
IntAttribute ta(i);
|
||||
ia.push_back(ta);
|
||||
headers[i].insert(IntAttribute::staticTypeName(), ta);
|
||||
}
|
||||
|
||||
|
||||
// write out the file
|
||||
remove(fn.c_str());
|
||||
{
|
||||
MultiPartOutputFile file(fn.c_str(), &headers[0],headers.size());
|
||||
}
|
||||
|
||||
|
||||
// read in the file and look at the attribute data
|
||||
MultiPartInputFile file (fn.c_str());
|
||||
|
||||
assert (file.parts() == 2);
|
||||
|
||||
for (int i=0; i<file.parts(); i++)
|
||||
{
|
||||
const Header & diskHeader = file.header(i);
|
||||
//
|
||||
// Test Display Window
|
||||
//
|
||||
const IMATH_NAMESPACE::Box2i & diskDispWin = diskHeader.displayWindow();
|
||||
const IMATH_NAMESPACE::Box2i & testDispWin = headers[i].displayWindow();
|
||||
assert (diskDispWin == testDispWin);
|
||||
|
||||
//
|
||||
// Test Pixel Aspect Ratio
|
||||
//
|
||||
float diskPAR = diskHeader.pixelAspectRatio();
|
||||
float testPAR = headers[i].pixelAspectRatio();
|
||||
assert (diskPAR == testPAR);
|
||||
|
||||
//
|
||||
// Test TimeCode
|
||||
//
|
||||
try
|
||||
{
|
||||
testDiskAttrValue<TimeCodeAttribute> (diskHeader, ta);
|
||||
}
|
||||
catch (const IEX_NAMESPACE::InputExc &e)
|
||||
{
|
||||
cerr << "Shared Attributes : TimeCode : " << e.what() << endl;
|
||||
assert (false);
|
||||
}
|
||||
|
||||
//
|
||||
// Test Chromaticities
|
||||
//
|
||||
try
|
||||
{
|
||||
testDiskAttrValue<ChromaticitiesAttribute> (diskHeader, ca);
|
||||
}
|
||||
catch (const IEX_NAMESPACE::InputExc &e)
|
||||
{
|
||||
cerr << "Shared Attributes : Chromaticities : " << e.what() << endl;
|
||||
assert (false);
|
||||
}
|
||||
|
||||
//
|
||||
// Test for non-shared attribute that can have differing values across
|
||||
// multiple parts
|
||||
//
|
||||
try
|
||||
{
|
||||
testDiskAttrValue<IntAttribute> (diskHeader, ia[i]);
|
||||
}
|
||||
catch (const IEX_NAMESPACE::InputExc &e)
|
||||
{
|
||||
cerr << "Shared Attributes : IntAttribute : " << e.what() << endl;
|
||||
assert (false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Test the code against an incorrectly constructed file
|
||||
//
|
||||
try
|
||||
{
|
||||
MultiPartInputFile file (ILM_IMF_TEST_IMAGEDIR "invalid_shared_attrs_multipart.exr");
|
||||
cerr << "Shared Attributes : InputFile : incorrect input file passed\n";
|
||||
assert (false);
|
||||
}
|
||||
catch (const IEX_NAMESPACE::InputExc &e)
|
||||
{
|
||||
// expectected behaviour
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
void
|
||||
testMultiPartSharedAttributes (const std::string & tempDir)
|
||||
{
|
||||
try
|
||||
{
|
||||
cout << "Testing multi part APIs : shared attributes, header... " << endl;
|
||||
|
||||
std::string fn = tempDir + "imf_test_multipart_shared_attrs.exr";
|
||||
|
||||
testSharedAttributes (fn);
|
||||
testHeaders (fn);
|
||||
|
||||
cout << " ... ok\n" << endl;
|
||||
}
|
||||
catch (const IEX_NAMESPACE::BaseExc & e)
|
||||
{
|
||||
cerr << "ERROR -- caught IEX_NAMESPACE::BaseExc exception: " << e.what() << endl;
|
||||
assert (false);
|
||||
}
|
||||
catch (const std::exception & e)
|
||||
{
|
||||
cerr << "ERROR -- caught std::exception exception: " << e.what() << endl;
|
||||
assert (false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2012, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef TESTMULTIPARTSHAREDATTRIBUTES_H_
|
||||
#define TESTMULTIPARTSHAREDATTRIBUTES_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
void testMultiPartSharedAttributes (const std::string & tempDir);
|
||||
|
||||
#endif /* TESTMULTIPARTSHAREDATTRIBUTES_H_ */
|
||||
@@ -0,0 +1,829 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "tmpDir.h"
|
||||
#include "testMultiPartThreading.h"
|
||||
|
||||
#include <ImfPartType.h>
|
||||
#include <ImfMultiPartInputFile.h>
|
||||
#include <ImfMultiPartOutputFile.h>
|
||||
#include <ImfOutputFile.h>
|
||||
#include <ImfTiledOutputFile.h>
|
||||
#include <ImfGenericOutputFile.h>
|
||||
#include <ImfArray.h>
|
||||
#include <ImfChannelList.h>
|
||||
#include <ImfOutputPart.h>
|
||||
#include <ImfInputPart.h>
|
||||
#include <ImfTiledOutputPart.h>
|
||||
#include <ImfTiledInputPart.h>
|
||||
#include <IlmThreadPool.h>
|
||||
#include <IlmThreadMutex.h>
|
||||
#include <ImfTiledMisc.h>
|
||||
|
||||
namespace IMF = OPENEXR_IMF_NAMESPACE;
|
||||
using namespace IMF;
|
||||
using namespace std;
|
||||
using namespace IMATH_NAMESPACE;
|
||||
using namespace ILMTHREAD_NAMESPACE;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
const int height = 263;
|
||||
const int width = 197;
|
||||
|
||||
vector<Header> headers;
|
||||
vector<int> pixelTypes;
|
||||
vector<int> partTypes;
|
||||
vector<int> levelModes;
|
||||
|
||||
Mutex mutexes[200];
|
||||
|
||||
template <class T>
|
||||
void fillPixels (Array2D<T> &ph, int width, int height)
|
||||
{
|
||||
ph.resizeErase(height, width);
|
||||
for (int y = 0; y < height; ++y)
|
||||
for (int x = 0; x < width; ++x)
|
||||
{
|
||||
//
|
||||
// We do this because half cannot store number bigger than 2048 exactly.
|
||||
//
|
||||
ph[y][x] = (y * width + x) % 2049;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool checkPixels (Array2D<T> &ph, int lx, int rx, int ly, int ry, int width)
|
||||
{
|
||||
for (int y = ly; y <= ry; ++y)
|
||||
for (int x = lx; x <= rx; ++x)
|
||||
if (ph[y][x] != (y * width + x) % 2049)
|
||||
{
|
||||
cout << "value at " << x << ", " << y << ": " << ph[y][x]
|
||||
<< ", should be " << (y * width + x) % 2049 << endl << flush;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool checkPixels (Array2D<T> &ph, int width, int height)
|
||||
{
|
||||
return checkPixels<T> (ph, 0, width - 1, 0, height - 1, width);
|
||||
}
|
||||
|
||||
void setOutputFrameBuffer(FrameBuffer& frameBuffer, int pixelType,
|
||||
Array2D<unsigned int>& uData, Array2D<float>& fData,
|
||||
Array2D<half>& hData, int width)
|
||||
{
|
||||
switch (pixelType)
|
||||
{
|
||||
case 0:
|
||||
frameBuffer.insert ("UINT",
|
||||
Slice (IMF::UINT,
|
||||
(char *) (&uData[0][0]),
|
||||
sizeof (uData[0][0]) * 1,
|
||||
sizeof (uData[0][0]) * width));
|
||||
break;
|
||||
case 1:
|
||||
frameBuffer.insert ("FLOAT",
|
||||
Slice (IMF::FLOAT,
|
||||
(char *) (&fData[0][0]),
|
||||
sizeof (fData[0][0]) * 1,
|
||||
sizeof (fData[0][0]) * width));
|
||||
break;
|
||||
case 2:
|
||||
frameBuffer.insert ("HALF",
|
||||
Slice (IMF::HALF,
|
||||
(char *) (&hData[0][0]),
|
||||
sizeof (hData[0][0]) * 1,
|
||||
sizeof (hData[0][0]) * width));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void setInputFrameBuffer(FrameBuffer& frameBuffer, int pixelType,
|
||||
Array2D<unsigned int>& uData, Array2D<float>& fData,
|
||||
Array2D<half>& hData, int width, int height)
|
||||
{
|
||||
switch (pixelType)
|
||||
{
|
||||
case 0:
|
||||
uData.resizeErase(height, width);
|
||||
frameBuffer.insert ("UINT",
|
||||
Slice (IMF::UINT,
|
||||
(char *) (&uData[0][0]),
|
||||
sizeof (uData[0][0]) * 1,
|
||||
sizeof (uData[0][0]) * width,
|
||||
1, 1,
|
||||
0));
|
||||
break;
|
||||
case 1:
|
||||
fData.resizeErase(height, width);
|
||||
frameBuffer.insert ("FLOAT",
|
||||
Slice (IMF::FLOAT,
|
||||
(char *) (&fData[0][0]),
|
||||
sizeof (fData[0][0]) * 1,
|
||||
sizeof (fData[0][0]) * width,
|
||||
1, 1,
|
||||
0));
|
||||
break;
|
||||
case 2:
|
||||
hData.resizeErase(height, width);
|
||||
frameBuffer.insert ("HALF",
|
||||
Slice (IMF::HALF,
|
||||
(char *) (&hData[0][0]),
|
||||
sizeof (hData[0][0]) * 1,
|
||||
sizeof (hData[0][0]) * width,
|
||||
1, 1,
|
||||
0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct WritingTaskData
|
||||
{
|
||||
int partNumber;
|
||||
int tx, ty, lx, ly;
|
||||
|
||||
WritingTaskData(int partNumber):
|
||||
partNumber(partNumber)
|
||||
{}
|
||||
|
||||
WritingTaskData(int partNumber, int tx, int ty, int lx, int ly):
|
||||
partNumber(partNumber),
|
||||
tx(tx),
|
||||
ty(ty),
|
||||
lx(lx),
|
||||
ly(ly)
|
||||
{}
|
||||
};
|
||||
|
||||
class WritingTask: public Task
|
||||
{
|
||||
public:
|
||||
WritingTask (TaskGroup *group, MultiPartOutputFile* file, vector<WritingTaskData*> data,
|
||||
Array2D<FrameBuffer>* tiledFrameBuffers):
|
||||
Task(group),
|
||||
file(file),
|
||||
data(data),
|
||||
tiledFrameBuffers(tiledFrameBuffers)
|
||||
{}
|
||||
|
||||
void execute()
|
||||
{
|
||||
for (int i = 0; i < data.size(); i++)
|
||||
{
|
||||
int partNumber = data[i]->partNumber;
|
||||
int partType = partTypes[partNumber];
|
||||
int pixelType = pixelTypes[partNumber];
|
||||
int levelMode = levelModes[partNumber];
|
||||
|
||||
if (partType == 0)
|
||||
{
|
||||
OutputPart part(*file, partNumber);
|
||||
part.writePixels();
|
||||
}
|
||||
else
|
||||
{
|
||||
int tx = data[i]->tx;
|
||||
int ty = data[i]->ty;
|
||||
int lx = data[i]->lx;
|
||||
int ly = data[i]->ly;
|
||||
TiledOutputPart part(*file, partNumber);
|
||||
|
||||
//
|
||||
// We add lock here to assure that two threads that accessing
|
||||
// the same part won't mess things up.
|
||||
//
|
||||
|
||||
Lock lock(mutexes[partNumber]);
|
||||
|
||||
part.setFrameBuffer(tiledFrameBuffers[partNumber][ly][lx]);
|
||||
part.writeTile(tx, ty, lx, ly);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
MultiPartOutputFile* file;
|
||||
vector<WritingTaskData*> data;
|
||||
Array2D<FrameBuffer>* tiledFrameBuffers;
|
||||
};
|
||||
|
||||
class RandomReadingTask : public Task
|
||||
{
|
||||
public:
|
||||
RandomReadingTask (TaskGroup *group, MultiPartInputFile* file):
|
||||
Task(group),
|
||||
file(file)
|
||||
{}
|
||||
|
||||
void execute()
|
||||
{
|
||||
int partNumber = rand() % headers.size();
|
||||
int partType = partTypes[partNumber];
|
||||
int pixelType = pixelTypes[partNumber];
|
||||
int levelMode = levelModes[partNumber];
|
||||
|
||||
Array2D<unsigned int> uData;
|
||||
Array2D<float> fData;
|
||||
Array2D<half> hData;
|
||||
if (partType == 0)
|
||||
{
|
||||
int l1, l2;
|
||||
l1 = rand() % height;
|
||||
l2 = rand() % height;
|
||||
if (l1 > l2) swap(l1, l2);
|
||||
|
||||
InputPart part(*file, partNumber);
|
||||
//
|
||||
// We add lock here to assure that two threads that accessing
|
||||
// the same part won't mess things up.
|
||||
//
|
||||
Lock lock(mutexes[partNumber]);
|
||||
|
||||
FrameBuffer frameBuffer;
|
||||
setInputFrameBuffer(frameBuffer, pixelType,
|
||||
uData, fData, hData, width, height);
|
||||
|
||||
part.setFrameBuffer(frameBuffer);
|
||||
part.readPixels(l1, l2);
|
||||
|
||||
switch (pixelType)
|
||||
{
|
||||
case 0:
|
||||
assert(checkPixels<unsigned int>(uData, 0, width - 1, l1, l2, width));
|
||||
break;
|
||||
case 1:
|
||||
assert(checkPixels<float>(fData, 0, width - 1, l1, l2, width));
|
||||
break;
|
||||
case 2:
|
||||
assert(checkPixels<half>(hData, 0, width - 1, l1, l2, width));
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int tx1, tx2, ty1, ty2;
|
||||
int lx, ly;
|
||||
|
||||
TiledInputPart part(*file, partNumber);
|
||||
//
|
||||
// We add lock here to assure that two threads that accessing
|
||||
// the same part won't mess things up.
|
||||
//
|
||||
Lock lock(mutexes[partNumber]);
|
||||
|
||||
int numXLevels = part.numXLevels();
|
||||
int numYLevels = part.numYLevels();
|
||||
|
||||
lx = rand() % numXLevels;
|
||||
ly = rand() % numYLevels;
|
||||
if (levelMode == 1) ly = lx;
|
||||
|
||||
int w = part.levelWidth(lx);
|
||||
int h = part.levelHeight(ly);
|
||||
|
||||
int numXTiles = part.numXTiles(lx);
|
||||
int numYTiles = part.numYTiles(ly);
|
||||
tx1 = rand() % numXTiles;
|
||||
tx2 = rand() % numXTiles;
|
||||
ty1 = rand() % numYTiles;
|
||||
ty2 = rand() % numYTiles;
|
||||
if (tx1 > tx2) swap(tx1, tx2);
|
||||
if (ty1 > ty2) swap(ty1, ty2);
|
||||
|
||||
FrameBuffer frameBuffer;
|
||||
setInputFrameBuffer(frameBuffer, pixelType,
|
||||
uData, fData, hData, w, h);
|
||||
|
||||
part.setFrameBuffer(frameBuffer);
|
||||
part.readTiles(tx1, tx2, ty1, ty2, lx, ly);
|
||||
|
||||
Box2i b1 = part.dataWindowForTile(tx1, ty1, lx, ly);
|
||||
Box2i b2 = part.dataWindowForTile(tx2, ty2, lx, ly);
|
||||
|
||||
switch (pixelType)
|
||||
{
|
||||
case 0:
|
||||
assert(checkPixels<unsigned int>(uData, b1.min.x, b2.max.x, b1.min.y, b2.max.y,
|
||||
w));
|
||||
break;
|
||||
case 1:
|
||||
assert(checkPixels<float>(fData, b1.min.x, b2.max.x, b1.min.y, b2.max.y,
|
||||
w));
|
||||
break;
|
||||
case 2:
|
||||
assert(checkPixels<half>(hData, b1.min.x, b2.max.x, b1.min.y, b2.max.y,
|
||||
w));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
MultiPartInputFile* file;
|
||||
};
|
||||
|
||||
void generateRandomHeaders(int partCount, vector<Header>& headers, vector<WritingTaskData>& taskList)
|
||||
{
|
||||
headers.clear();
|
||||
for (int i = 0; i < partCount; i++)
|
||||
{
|
||||
Header header(width, height);
|
||||
int pixelType = rand() % 3;
|
||||
int partType = rand() % 2;
|
||||
pixelTypes[i] = pixelType;
|
||||
partTypes[i] = partType;
|
||||
|
||||
stringstream ss;
|
||||
ss << i;
|
||||
header.setName(ss.str());
|
||||
|
||||
switch (pixelType)
|
||||
{
|
||||
case 0:
|
||||
header.channels().insert("UINT", Channel(IMF::UINT));
|
||||
break;
|
||||
case 1:
|
||||
header.channels().insert("FLOAT", Channel(IMF::FLOAT));
|
||||
break;
|
||||
case 2:
|
||||
header.channels().insert("HALF", Channel(IMF::HALF));
|
||||
break;
|
||||
}
|
||||
|
||||
switch (partType)
|
||||
{
|
||||
case 0:
|
||||
header.setType(SCANLINEIMAGE);
|
||||
break;
|
||||
case 1:
|
||||
header.setType(TILEDIMAGE);
|
||||
break;
|
||||
}
|
||||
|
||||
int tileX;
|
||||
int tileY;
|
||||
int levelMode;
|
||||
if (partType == 1)
|
||||
{
|
||||
tileX = rand() % width + 1;
|
||||
tileY = rand() % height + 1;
|
||||
levelMode = rand() % 3;
|
||||
levelModes[i] = levelMode;
|
||||
LevelMode lm;
|
||||
switch (levelMode)
|
||||
{
|
||||
case 0:
|
||||
lm = ONE_LEVEL;
|
||||
break;
|
||||
case 1:
|
||||
lm = MIPMAP_LEVELS;
|
||||
break;
|
||||
case 2:
|
||||
lm = RIPMAP_LEVELS;
|
||||
break;
|
||||
}
|
||||
header.setTileDescription(TileDescription(tileX, tileY, lm));
|
||||
}
|
||||
|
||||
//
|
||||
// Add lines or tiles to task list.
|
||||
//
|
||||
if (partType == 0)
|
||||
{
|
||||
for (int j = 0; j < height; j++)
|
||||
taskList.push_back(WritingTaskData(i));
|
||||
}
|
||||
else
|
||||
{
|
||||
int numXLevel;
|
||||
int numYLevel;
|
||||
int* numXTiles;
|
||||
int* numYTiles;
|
||||
precalculateTileInfo (header.tileDescription(),
|
||||
0, width - 1,
|
||||
0, height - 1,
|
||||
numXTiles, numYTiles,
|
||||
numXLevel, numYLevel);
|
||||
|
||||
for (int lx = 0; lx < numXLevel; lx++)
|
||||
for (int ly = 0; ly < numYLevel; ly++)
|
||||
{
|
||||
if (levelMode == 1)
|
||||
if (lx != ly) continue;
|
||||
|
||||
// Get all tasks for this level.
|
||||
for (int tx = 0; tx < numXTiles[lx]; tx++)
|
||||
for (int ty = 0; ty < numYTiles[ly]; ty++)
|
||||
taskList.push_back(WritingTaskData(i, tx, ty, lx, ly));
|
||||
}
|
||||
|
||||
delete[] numXTiles;
|
||||
delete[] numYTiles;
|
||||
}
|
||||
|
||||
// if (partType == 0)
|
||||
// {
|
||||
// cout << "pixelType = " << pixelType << " partType = " << partType
|
||||
// << endl << flush;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// cout << "pixelType = " << pixelType << " partType = " << partType
|
||||
// << " levelMode = " << levelModes[i] << endl << flush;
|
||||
// }
|
||||
|
||||
headers.push_back(header);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
generateRandomFile (int partCount, const std::string & fn)
|
||||
{
|
||||
//
|
||||
// Init data.
|
||||
//
|
||||
Array2D<half> halfData;
|
||||
Array2D<float> floatData;
|
||||
Array2D<unsigned int> uintData;
|
||||
fillPixels<unsigned int>(uintData, width, height);
|
||||
fillPixels<half>(halfData, width, height);
|
||||
fillPixels<float>(floatData, width, height);
|
||||
|
||||
Array2D< Array2D< half > >* tiledHalfData = new Array2D< Array2D< half > >[partCount];
|
||||
Array2D< Array2D< float > >* tiledFloatData = new Array2D< Array2D< float > >[partCount];
|
||||
Array2D< Array2D< unsigned int > >* tiledUintData = new Array2D< Array2D< unsigned int > >[partCount];
|
||||
|
||||
vector<GenericOutputFile*> outputfiles;
|
||||
vector<WritingTaskData> taskList;
|
||||
|
||||
pixelTypes.resize(partCount);
|
||||
partTypes.resize(partCount);
|
||||
levelModes.resize(partCount);
|
||||
|
||||
//
|
||||
// Generate headers and data.
|
||||
//
|
||||
cout << "Generating headers and data " << flush;
|
||||
generateRandomHeaders(partCount, headers, taskList);
|
||||
|
||||
//
|
||||
// Shuffle tasks.
|
||||
//
|
||||
cout << "Shuffling " << taskList.size() << " tasks " << flush;
|
||||
int taskListSize = taskList.size();
|
||||
for (int i = 0; i < taskListSize; i++)
|
||||
{
|
||||
int a, b;
|
||||
a = rand() % taskListSize;
|
||||
b = rand() % taskListSize;
|
||||
swap(taskList[a], taskList[b]);
|
||||
}
|
||||
|
||||
remove(fn.c_str());
|
||||
MultiPartOutputFile file(fn.c_str(), &headers[0],headers.size());
|
||||
|
||||
//
|
||||
// Writing tasks.
|
||||
//
|
||||
cout << "Writing tasks " << flush;
|
||||
|
||||
//
|
||||
// Pre-generating frameBuffers.
|
||||
//
|
||||
vector<void *> parts;
|
||||
vector<FrameBuffer> frameBuffers(partCount);
|
||||
Array<Array2D<FrameBuffer> >tiledFrameBuffers(partCount);
|
||||
for (int i = 0; i < partCount; i++)
|
||||
{
|
||||
if (partTypes[i] == 0)
|
||||
{
|
||||
OutputPart* part = new OutputPart(file, i);
|
||||
parts.push_back((void*) part);
|
||||
|
||||
FrameBuffer& frameBuffer = frameBuffers[i];
|
||||
|
||||
setOutputFrameBuffer(frameBuffer, pixelTypes[i], uintData, floatData, halfData, width);
|
||||
|
||||
part->setFrameBuffer(frameBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
TiledOutputPart* part = new TiledOutputPart(file, i);
|
||||
parts.push_back((void*) part);
|
||||
|
||||
int numXLevels = part->numXLevels();
|
||||
int numYLevels = part->numYLevels();
|
||||
|
||||
// Allocating space.
|
||||
switch (pixelTypes[i])
|
||||
{
|
||||
case 0:
|
||||
tiledUintData[i].resizeErase(numYLevels, numXLevels);
|
||||
break;
|
||||
case 1:
|
||||
tiledFloatData[i].resizeErase(numYLevels, numXLevels);
|
||||
break;
|
||||
case 2:
|
||||
tiledHalfData[i].resizeErase(numYLevels, numXLevels);
|
||||
break;
|
||||
}
|
||||
|
||||
tiledFrameBuffers[i].resizeErase(numYLevels, numXLevels);
|
||||
|
||||
for (int xLevel = 0; xLevel < numXLevels; xLevel++)
|
||||
for (int yLevel = 0; yLevel < numYLevels; yLevel++)
|
||||
{
|
||||
if (!part->isValidLevel(xLevel, yLevel))
|
||||
continue;
|
||||
|
||||
int w = part->levelWidth(xLevel);
|
||||
int h = part->levelHeight(yLevel);
|
||||
|
||||
FrameBuffer& frameBuffer = tiledFrameBuffers[i][yLevel][xLevel];
|
||||
|
||||
switch (pixelTypes[i])
|
||||
{
|
||||
case 0:
|
||||
fillPixels<unsigned int>(tiledUintData[i][yLevel][xLevel], w, h);
|
||||
break;
|
||||
case 1:
|
||||
fillPixels<float>(tiledFloatData[i][yLevel][xLevel], w, h);
|
||||
break;
|
||||
case 2:
|
||||
fillPixels<half>(tiledHalfData[i][yLevel][xLevel], w, h);
|
||||
break;
|
||||
}
|
||||
setOutputFrameBuffer(frameBuffer, pixelTypes[i],
|
||||
tiledUintData[i][yLevel][xLevel],
|
||||
tiledFloatData[i][yLevel][xLevel],
|
||||
tiledHalfData[i][yLevel][xLevel],
|
||||
w);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Writing tasks.
|
||||
//
|
||||
TaskGroup taskGroup;
|
||||
ThreadPool* threadPool = new ThreadPool(32);
|
||||
vector<WritingTaskData*> list;
|
||||
for (int i = 0; i < taskListSize; i++)
|
||||
{
|
||||
list.push_back(&taskList[i]);
|
||||
if (i % 10 == 0 || i == taskListSize - 1)
|
||||
{
|
||||
threadPool->addTask(
|
||||
(new WritingTask (&taskGroup, &file, list, tiledFrameBuffers)));
|
||||
list.clear();
|
||||
}
|
||||
}
|
||||
|
||||
delete threadPool;
|
||||
|
||||
delete[] tiledHalfData;
|
||||
delete[] tiledUintData;
|
||||
delete[] tiledFloatData;
|
||||
}
|
||||
|
||||
void
|
||||
readWholeFiles (const std::string & fn)
|
||||
{
|
||||
Array2D<unsigned int> uData;
|
||||
Array2D<float> fData;
|
||||
Array2D<half> hData;
|
||||
|
||||
MultiPartInputFile file(fn.c_str());
|
||||
for (size_t i = 0; i < file.parts(); i++)
|
||||
{
|
||||
const Header& header = file.header(i);
|
||||
assert (header.displayWindow() == headers[i].displayWindow());
|
||||
assert (header.dataWindow() == headers[i].dataWindow());
|
||||
assert (header.pixelAspectRatio() == headers[i].pixelAspectRatio());
|
||||
assert (header.screenWindowCenter() == headers[i].screenWindowCenter());
|
||||
assert (header.screenWindowWidth() == headers[i].screenWindowWidth());
|
||||
assert (header.lineOrder() == headers[i].lineOrder());
|
||||
assert (header.compression() == headers[i].compression());
|
||||
|
||||
//
|
||||
// It rarely fails here. Added code to see what's wrong when it happens.
|
||||
//
|
||||
ChannelList::ConstIterator i1 = header.channels().begin();
|
||||
ChannelList::ConstIterator i2 = headers[i].channels().begin();
|
||||
Channel c1 = i1.channel();
|
||||
Channel c2 = i2.channel();
|
||||
if (!(c1 == c2))
|
||||
{
|
||||
cout << " type " << c1.type << ", " << c2.type
|
||||
<< " xSampling " << c1.xSampling << ", " << c2.xSampling
|
||||
<< " ySampling " << c1.ySampling << ", " << c2.ySampling
|
||||
<< " pLinear " << c1.pLinear << ", " << c2.pLinear << flush;
|
||||
}
|
||||
|
||||
assert (header.channels() == headers[i].channels());
|
||||
assert (header.name() == headers[i].name());
|
||||
assert (header.type() == headers[i].type());
|
||||
}
|
||||
|
||||
cout << "Reading whole files " << flush;
|
||||
|
||||
//
|
||||
// Shuffle part numbers.
|
||||
//
|
||||
vector<int> shuffledPartNumber;
|
||||
for (int i = 0; i < headers.size(); i++)
|
||||
shuffledPartNumber.push_back(i);
|
||||
for (int i = 0; i < headers.size(); i++)
|
||||
{
|
||||
int a = rand() % headers.size();
|
||||
int b = rand() % headers.size();
|
||||
swap (shuffledPartNumber[a], shuffledPartNumber[b]);
|
||||
}
|
||||
|
||||
//
|
||||
// Start reading whole files.
|
||||
//
|
||||
int i;
|
||||
int partNumber;
|
||||
try
|
||||
{
|
||||
for (i = 0; i < headers.size(); i++)
|
||||
{
|
||||
partNumber = shuffledPartNumber[i];
|
||||
if (partTypes[partNumber] == 0)
|
||||
{
|
||||
FrameBuffer frameBuffer;
|
||||
setInputFrameBuffer(frameBuffer, pixelTypes[partNumber],
|
||||
uData, fData, hData, width, height);
|
||||
|
||||
InputPart part(file, partNumber);
|
||||
part.setFrameBuffer(frameBuffer);
|
||||
part.readPixels(0, height - 1);
|
||||
switch (pixelTypes[partNumber])
|
||||
{
|
||||
case 0:
|
||||
assert(checkPixels<unsigned int>(uData, width, height));
|
||||
break;
|
||||
case 1:
|
||||
assert(checkPixels<float>(fData, width, height));
|
||||
break;
|
||||
case 2:
|
||||
assert(checkPixels<half>(hData, width, height));
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FrameBuffer frameBuffer;
|
||||
TiledInputPart part(file, partNumber);
|
||||
int numXLevels = part.numXLevels();
|
||||
int numYLevels = part.numYLevels();
|
||||
for (int xLevel = 0; xLevel < numXLevels; xLevel++)
|
||||
for (int yLevel = 0; yLevel < numYLevels; yLevel++)
|
||||
{
|
||||
if (!part.isValidLevel(xLevel, yLevel))
|
||||
continue;
|
||||
|
||||
int w = part.levelWidth(xLevel);
|
||||
int h = part.levelHeight(yLevel);
|
||||
|
||||
setInputFrameBuffer(frameBuffer, pixelTypes[partNumber],
|
||||
uData, fData, hData, width, height);
|
||||
|
||||
part.setFrameBuffer(frameBuffer);
|
||||
int numXTiles = part.numXTiles(xLevel);
|
||||
int numYTiles = part.numYTiles(yLevel);
|
||||
part.readTiles(0, numXTiles - 1, 0, numYTiles - 1, xLevel, yLevel);
|
||||
switch (pixelTypes[partNumber])
|
||||
{
|
||||
case 0:
|
||||
assert(checkPixels<unsigned int>(uData, w, h));
|
||||
break;
|
||||
case 1:
|
||||
assert(checkPixels<float>(fData, w, h));
|
||||
break;
|
||||
case 2:
|
||||
assert(checkPixels<half>(hData, w, h));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
cout << "Error while reading part " << partNumber << endl << flush;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
readPartialFiles (int randomReadCount, const std::string & fn)
|
||||
{
|
||||
cout << "Reading partial files " << flush;
|
||||
MultiPartInputFile file(fn.c_str());
|
||||
|
||||
TaskGroup taskGroup;
|
||||
ThreadPool* threadPool = new ThreadPool(32);
|
||||
|
||||
for (int i = 0; i < randomReadCount; i++)
|
||||
{
|
||||
threadPool->addTask(
|
||||
(new RandomReadingTask (&taskGroup, &file)));
|
||||
}
|
||||
|
||||
delete threadPool;
|
||||
}
|
||||
|
||||
void
|
||||
testWriteRead (int partNumber,
|
||||
int runCount,
|
||||
int randomReadCount,
|
||||
const std::string & tempDir)
|
||||
{
|
||||
cout << "Testing file with " << partNumber << " part(s)." << endl << flush;
|
||||
std::string fn = tempDir + "imf_test_multipart_threading.exr";
|
||||
|
||||
for (int i = 0; i < runCount; i++)
|
||||
{
|
||||
generateRandomFile (partNumber, fn);
|
||||
readWholeFiles (fn);
|
||||
readPartialFiles (randomReadCount, fn);
|
||||
|
||||
remove (fn.c_str());
|
||||
|
||||
cout << endl << flush;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void testMultiPartThreading (const std::string & tempDir)
|
||||
{
|
||||
try
|
||||
{
|
||||
cout << "Testing the multi part APIs for multi-thread use" << endl;
|
||||
|
||||
srand(1);
|
||||
|
||||
int numThreads = ThreadPool::globalThreadPool().numThreads();
|
||||
ThreadPool::globalThreadPool().setNumThreads(32);
|
||||
|
||||
testWriteRead ( 1, 1, 5, tempDir);
|
||||
testWriteRead ( 2, 2, 10, tempDir);
|
||||
testWriteRead ( 5, 5, 25, tempDir);
|
||||
testWriteRead (50, 2, 250, tempDir);
|
||||
|
||||
ThreadPool::globalThreadPool().setNumThreads(numThreads);
|
||||
|
||||
cout << "ok\n" << endl;
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
cerr << "ERROR -- caught exception: " << e.what() << endl;
|
||||
assert (false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef TESTMULTIPARTTHREADING_H_
|
||||
#define TESTMULTIPARTTHREADING_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
void testMultiPartThreading (const std::string & tempDir);
|
||||
|
||||
#endif /* TESTMULTIPARTTHREADING_H_ */
|
||||
@@ -0,0 +1,438 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "tmpDir.h"
|
||||
|
||||
#include "testMultiScanlinePartThreading.h"
|
||||
|
||||
#include <ImfPartType.h>
|
||||
#include <ImfMultiPartInputFile.h>
|
||||
#include <ImfMultiPartOutputFile.h>
|
||||
#include <ImfOutputFile.h>
|
||||
#include <ImfTiledOutputFile.h>
|
||||
#include <ImfGenericOutputFile.h>
|
||||
#include <ImfArray.h>
|
||||
#include <ImfChannelList.h>
|
||||
#include <ImfOutputPart.h>
|
||||
#include <ImfInputPart.h>
|
||||
#include <ImfTiledOutputPart.h>
|
||||
#include <ImfTiledInputPart.h>
|
||||
#include <IlmThreadPool.h>
|
||||
#include <IlmThreadMutex.h>
|
||||
|
||||
namespace IMF = OPENEXR_IMF_NAMESPACE;
|
||||
using namespace IMF;
|
||||
using namespace std;
|
||||
using namespace IMATH_NAMESPACE;
|
||||
using namespace ILMTHREAD_NAMESPACE;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
const int height = 263;
|
||||
const int width = 197;
|
||||
|
||||
vector<Header> headers;
|
||||
|
||||
template <class T>
|
||||
void fillPixels (Array2D<T> &ph, int width, int height)
|
||||
{
|
||||
ph.resizeErase(height, width);
|
||||
for (int y = 0; y < height; ++y)
|
||||
for (int x = 0; x < width; ++x)
|
||||
{
|
||||
//
|
||||
// We do this because half cannot store number bigger than 2048 exactly.
|
||||
//
|
||||
ph[y][x] = (y * width + x) % 2049;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool checkPixels (Array2D<T> &ph, int lx, int rx, int ly, int ry, int width)
|
||||
{
|
||||
for (int y = ly; y <= ry; ++y)
|
||||
for (int x = lx; x <= rx; ++x)
|
||||
if (ph[y][x] != (y * width + x) % 2049)
|
||||
{
|
||||
cout << "value at " << x << ", " << y << ": " << ph[y][x]
|
||||
<< ", should be " << (y * width + x) % 2049 << endl << flush;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool checkPixels (Array2D<T> &ph, int width, int height)
|
||||
{
|
||||
return checkPixels<T> (ph, 0, width - 1, 0, height - 1, width);
|
||||
}
|
||||
|
||||
class WritingTask: public Task
|
||||
{
|
||||
public:
|
||||
WritingTask (TaskGroup *group, OutputPart& part, int outputLines):
|
||||
Task(group),
|
||||
part(part),
|
||||
outputLines(outputLines)
|
||||
{}
|
||||
|
||||
void execute()
|
||||
{
|
||||
for (int i = 0; i < outputLines; i++)
|
||||
part.writePixels();
|
||||
}
|
||||
|
||||
private:
|
||||
OutputPart& part;
|
||||
int outputLines;
|
||||
};
|
||||
|
||||
class ReadingTask: public Task
|
||||
{
|
||||
public:
|
||||
ReadingTask (TaskGroup *group, InputPart& part, int startPos):
|
||||
Task(group),
|
||||
part(part),
|
||||
startPos(startPos)
|
||||
{}
|
||||
|
||||
void execute()
|
||||
{
|
||||
int endPos = startPos + 9;
|
||||
if (endPos >= height) endPos = height - 1;
|
||||
part.readPixels(startPos, endPos);
|
||||
}
|
||||
|
||||
private:
|
||||
InputPart& part;
|
||||
int startPos;
|
||||
};
|
||||
|
||||
void setOutputFrameBuffer(FrameBuffer& frameBuffer, int pixelType,
|
||||
Array2D<unsigned int>& uData, Array2D<float>& fData,
|
||||
Array2D<half>& hData, int width)
|
||||
{
|
||||
switch (pixelType)
|
||||
{
|
||||
case 0:
|
||||
frameBuffer.insert ("UINT",
|
||||
Slice (IMF::UINT,
|
||||
(char *) (&uData[0][0]),
|
||||
sizeof (uData[0][0]) * 1,
|
||||
sizeof (uData[0][0]) * width));
|
||||
break;
|
||||
case 1:
|
||||
frameBuffer.insert ("FLOAT",
|
||||
Slice (IMF::FLOAT,
|
||||
(char *) (&fData[0][0]),
|
||||
sizeof (fData[0][0]) * 1,
|
||||
sizeof (fData[0][0]) * width));
|
||||
break;
|
||||
case 2:
|
||||
frameBuffer.insert ("HALF",
|
||||
Slice (IMF::HALF,
|
||||
(char *) (&hData[0][0]),
|
||||
sizeof (hData[0][0]) * 1,
|
||||
sizeof (hData[0][0]) * width));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void setInputFrameBuffer(FrameBuffer& frameBuffer, int pixelType,
|
||||
Array2D<unsigned int>& uData, Array2D<float>& fData,
|
||||
Array2D<half>& hData, int width, int height)
|
||||
{
|
||||
switch (pixelType)
|
||||
{
|
||||
case 0:
|
||||
uData.resizeErase(height, width);
|
||||
frameBuffer.insert ("UINT",
|
||||
Slice (IMF::UINT,
|
||||
(char *) (&uData[0][0]),
|
||||
sizeof (uData[0][0]) * 1,
|
||||
sizeof (uData[0][0]) * width,
|
||||
1, 1,
|
||||
0));
|
||||
break;
|
||||
case 1:
|
||||
fData.resizeErase(height, width);
|
||||
frameBuffer.insert ("FLOAT",
|
||||
Slice (IMF::FLOAT,
|
||||
(char *) (&fData[0][0]),
|
||||
sizeof (fData[0][0]) * 1,
|
||||
sizeof (fData[0][0]) * width,
|
||||
1, 1,
|
||||
0));
|
||||
break;
|
||||
case 2:
|
||||
hData.resizeErase(height, width);
|
||||
frameBuffer.insert ("HALF",
|
||||
Slice (IMF::HALF,
|
||||
(char *) (&hData[0][0]),
|
||||
sizeof (hData[0][0]) * 1,
|
||||
sizeof (hData[0][0]) * width,
|
||||
1, 1,
|
||||
0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
generateFiles (int pixelTypes[], const std::string & fn)
|
||||
{
|
||||
//
|
||||
// Generate headers.
|
||||
//
|
||||
|
||||
cout << "Generating headers " << flush;
|
||||
headers.clear();
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
Header header(width, height);
|
||||
int pixelType = pixelTypes[i];
|
||||
|
||||
stringstream ss;
|
||||
ss << i;
|
||||
header.setName(ss.str());
|
||||
|
||||
switch (pixelType)
|
||||
{
|
||||
case 0:
|
||||
header.channels().insert("UINT", Channel(IMF::UINT));
|
||||
break;
|
||||
case 1:
|
||||
header.channels().insert("FLOAT", Channel(IMF::FLOAT));
|
||||
break;
|
||||
case 2:
|
||||
header.channels().insert("HALF", Channel(IMF::HALF));
|
||||
break;
|
||||
}
|
||||
|
||||
header.setType(SCANLINEIMAGE);
|
||||
|
||||
headers.push_back(header);
|
||||
}
|
||||
|
||||
//
|
||||
// Preparing.
|
||||
//
|
||||
|
||||
cout << "Writing files " << flush;
|
||||
Array2D<half> halfData;
|
||||
Array2D<float> floatData;
|
||||
Array2D<unsigned int> uintData;
|
||||
fillPixels<unsigned int>(uintData, width, height);
|
||||
fillPixels<half>(halfData, width, height);
|
||||
fillPixels<float>(floatData, width, height);
|
||||
|
||||
remove(fn.c_str());
|
||||
MultiPartOutputFile file(fn.c_str(), &headers[0],headers.size() );
|
||||
|
||||
vector<OutputPart> parts;
|
||||
FrameBuffer frameBuffers[2];
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
OutputPart part(file, i);
|
||||
|
||||
FrameBuffer& frameBuffer = frameBuffers[i];
|
||||
setOutputFrameBuffer(frameBuffer, pixelTypes[i], uintData, floatData, halfData, width);
|
||||
part.setFrameBuffer(frameBuffer);
|
||||
|
||||
parts.push_back(part);
|
||||
}
|
||||
|
||||
//
|
||||
// Writing tasks.
|
||||
//
|
||||
|
||||
TaskGroup taskGroup;
|
||||
ThreadPool* threadPool = new ThreadPool(2);
|
||||
for (int i = 0; i < height / 10; i++)
|
||||
{
|
||||
threadPool->addTask((new WritingTask (&taskGroup, parts[0], 10)));
|
||||
threadPool->addTask((new WritingTask (&taskGroup, parts[1], 10)));
|
||||
}
|
||||
threadPool->addTask((new WritingTask (&taskGroup, parts[0], height % 10)));
|
||||
threadPool->addTask((new WritingTask (&taskGroup, parts[1], height % 10)));
|
||||
delete threadPool;
|
||||
}
|
||||
|
||||
void
|
||||
readFiles (int pixelTypes[], const std::string & fn)
|
||||
{
|
||||
cout << "Checking headers " << flush;
|
||||
MultiPartInputFile file(fn.c_str());
|
||||
assert (file.parts() == 2);
|
||||
for (size_t i = 0; i < 2; i++)
|
||||
{
|
||||
const Header& header = file.header(i);
|
||||
assert (header.displayWindow() == headers[i].displayWindow());
|
||||
assert (header.dataWindow() == headers[i].dataWindow());
|
||||
assert (header.pixelAspectRatio() == headers[i].pixelAspectRatio());
|
||||
assert (header.screenWindowCenter() == headers[i].screenWindowCenter());
|
||||
assert (header.screenWindowWidth() == headers[i].screenWindowWidth());
|
||||
assert (header.lineOrder() == headers[i].lineOrder());
|
||||
assert (header.compression() == headers[i].compression());
|
||||
assert (header.channels() == headers[i].channels());
|
||||
assert (header.name() == headers[i].name());
|
||||
assert (header.type() == headers[i].type());
|
||||
}
|
||||
|
||||
//
|
||||
// Preparing.
|
||||
//
|
||||
|
||||
Array2D<unsigned int> uData[2];
|
||||
Array2D<float> fData[2];
|
||||
Array2D<half> hData[2];
|
||||
vector<InputPart> parts;
|
||||
FrameBuffer frameBuffers[2];
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
InputPart part(file, i);
|
||||
|
||||
FrameBuffer& frameBuffer = frameBuffers[i];
|
||||
setInputFrameBuffer(frameBuffer, pixelTypes[i], uData[i], fData[i], hData[i], width, height);
|
||||
part.setFrameBuffer(frameBuffer);
|
||||
|
||||
parts.push_back(part);
|
||||
}
|
||||
|
||||
//
|
||||
// Reading files.
|
||||
//
|
||||
|
||||
cout << "Reading files " << flush;
|
||||
TaskGroup taskGroup;
|
||||
ThreadPool* threadPool = new ThreadPool(2);
|
||||
for (int i = 0; i <= height / 10; i++)
|
||||
{
|
||||
threadPool->addTask((new ReadingTask (&taskGroup, parts[0], i * 10)));
|
||||
threadPool->addTask((new ReadingTask (&taskGroup, parts[1], i * 10)));
|
||||
}
|
||||
delete threadPool;
|
||||
|
||||
//
|
||||
// Checking data.
|
||||
//
|
||||
|
||||
cout << "Comparing" << endl << flush;
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
switch (pixelTypes[i])
|
||||
{
|
||||
case 0:
|
||||
assert(checkPixels<unsigned int>(uData[i], width, height));
|
||||
break;
|
||||
case 1:
|
||||
assert(checkPixels<float>(fData[i], width, height));
|
||||
break;
|
||||
case 2:
|
||||
assert(checkPixels<half>(hData[i], width, height));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testWriteRead (int pixelTypes[], const std::string & tempDir)
|
||||
{
|
||||
std::string fn = tempDir + "imf_test_multi_scanline_part_threading.exr";
|
||||
|
||||
string typeNames[2];
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
switch (pixelTypes[i])
|
||||
{
|
||||
case 0:
|
||||
typeNames[i] = "unsigned int";
|
||||
break;
|
||||
case 1:
|
||||
typeNames[i] = "float";
|
||||
break;
|
||||
case 2:
|
||||
typeNames[i] = "half";
|
||||
break;
|
||||
}
|
||||
}
|
||||
cout << "part 1: " << typeNames[0] << " scanline part, "
|
||||
<< "part 2: " << typeNames[1] << " scanline part. " << endl << flush;
|
||||
|
||||
generateFiles (pixelTypes, fn);
|
||||
readFiles (pixelTypes, fn);
|
||||
|
||||
remove (fn.c_str());
|
||||
|
||||
cout << endl << flush;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void testMultiScanlinePartThreading (const std::string & tempDir)
|
||||
{
|
||||
try
|
||||
{
|
||||
cout << "Testing the two threads reading/writing on two-scanline-part file" << endl;
|
||||
|
||||
int numThreads = ThreadPool::globalThreadPool().numThreads();
|
||||
ThreadPool::globalThreadPool().setNumThreads(2);
|
||||
|
||||
int pixelTypes[2];
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
for (int j = 0; j < 3; j++)
|
||||
{
|
||||
pixelTypes[0] = i;
|
||||
pixelTypes[1] = j;
|
||||
testWriteRead (pixelTypes, tempDir);
|
||||
}
|
||||
|
||||
ThreadPool::globalThreadPool().setNumThreads(numThreads);
|
||||
|
||||
cout << "ok\n" << endl;
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
cerr << "ERROR -- caught exception: " << e.what() << endl;
|
||||
assert (false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef TESTMULTISCANLINEPARTTHREADING_H_
|
||||
#define TESTMULTISCANLINEPARTTHREADING_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
void testMultiScanlinePartThreading (const std::string & tempDir);
|
||||
|
||||
#endif /* TESTMULTISCANLINEPARTTHREADING_H_ */
|
||||
@@ -0,0 +1,550 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <algorithm>
|
||||
|
||||
#include "tmpDir.h"
|
||||
|
||||
#include "testMultiTiledPartThreading.h"
|
||||
|
||||
#include <ImfPartType.h>
|
||||
#include <ImfMultiPartInputFile.h>
|
||||
#include <ImfMultiPartOutputFile.h>
|
||||
#include <ImfOutputFile.h>
|
||||
#include <ImfTiledOutputFile.h>
|
||||
#include <ImfGenericOutputFile.h>
|
||||
#include <ImfArray.h>
|
||||
#include <ImfChannelList.h>
|
||||
#include <ImfOutputPart.h>
|
||||
#include <ImfInputPart.h>
|
||||
#include <ImfTiledOutputPart.h>
|
||||
#include <ImfTiledInputPart.h>
|
||||
#include <IlmThreadPool.h>
|
||||
#include <IlmThreadMutex.h>
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
namespace IMF = OPENEXR_IMF_NAMESPACE;
|
||||
using namespace IMF;
|
||||
using namespace std;
|
||||
using namespace IMATH_NAMESPACE;
|
||||
using namespace ILMTHREAD_NAMESPACE;
|
||||
|
||||
const int height = 263;
|
||||
const int width = 197;
|
||||
|
||||
vector<Header> headers;
|
||||
int pixelTypes[2];
|
||||
int levelMode;
|
||||
int tileSize;
|
||||
|
||||
template <class T>
|
||||
void fillPixels (Array2D<T> &ph, int width, int height)
|
||||
{
|
||||
ph.resizeErase(height, width);
|
||||
for (int y = 0; y < height; ++y)
|
||||
for (int x = 0; x < width; ++x)
|
||||
{
|
||||
//
|
||||
// We do this because half cannot store number bigger than 2048 exactly.
|
||||
//
|
||||
ph[y][x] = (y * width + x) % 2049;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool checkPixels (Array2D<T> &ph, int lx, int rx, int ly, int ry, int width)
|
||||
{
|
||||
for (int y = ly; y <= ry; ++y)
|
||||
for (int x = lx; x <= rx; ++x)
|
||||
if (ph[y][x] != (y * width + x) % 2049)
|
||||
{
|
||||
cout << "value at " << x << ", " << y << ": " << ph[y][x]
|
||||
<< ", should be " << (y * width + x) % 2049 << endl << flush;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool checkPixels (Array2D<T> &ph, int width, int height)
|
||||
{
|
||||
return checkPixels<T> (ph, 0, width - 1, 0, height - 1, width);
|
||||
}
|
||||
|
||||
void setOutputFrameBuffer(FrameBuffer& frameBuffer, int pixelType,
|
||||
Array2D<unsigned int>& uData, Array2D<float>& fData,
|
||||
Array2D<half>& hData, int width)
|
||||
{
|
||||
switch (pixelType)
|
||||
{
|
||||
case 0:
|
||||
frameBuffer.insert ("UINT",
|
||||
Slice (IMF::UINT,
|
||||
(char *) (&uData[0][0]),
|
||||
sizeof (uData[0][0]) * 1,
|
||||
sizeof (uData[0][0]) * width));
|
||||
break;
|
||||
case 1:
|
||||
frameBuffer.insert ("FLOAT",
|
||||
Slice (IMF::FLOAT,
|
||||
(char *) (&fData[0][0]),
|
||||
sizeof (fData[0][0]) * 1,
|
||||
sizeof (fData[0][0]) * width));
|
||||
break;
|
||||
case 2:
|
||||
frameBuffer.insert ("HALF",
|
||||
Slice (IMF::HALF,
|
||||
(char *) (&hData[0][0]),
|
||||
sizeof (hData[0][0]) * 1,
|
||||
sizeof (hData[0][0]) * width));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void setInputFrameBuffer(FrameBuffer& frameBuffer, int pixelType,
|
||||
Array2D<unsigned int>& uData, Array2D<float>& fData,
|
||||
Array2D<half>& hData, int width, int height)
|
||||
{
|
||||
switch (pixelType)
|
||||
{
|
||||
case 0:
|
||||
uData.resizeErase(height, width);
|
||||
frameBuffer.insert ("UINT",
|
||||
Slice (IMF::UINT,
|
||||
(char *) (&uData[0][0]),
|
||||
sizeof (uData[0][0]) * 1,
|
||||
sizeof (uData[0][0]) * width,
|
||||
1, 1,
|
||||
0));
|
||||
break;
|
||||
case 1:
|
||||
fData.resizeErase(height, width);
|
||||
frameBuffer.insert ("FLOAT",
|
||||
Slice (IMF::FLOAT,
|
||||
(char *) (&fData[0][0]),
|
||||
sizeof (fData[0][0]) * 1,
|
||||
sizeof (fData[0][0]) * width,
|
||||
1, 1,
|
||||
0));
|
||||
break;
|
||||
case 2:
|
||||
hData.resizeErase(height, width);
|
||||
frameBuffer.insert ("HALF",
|
||||
Slice (IMF::HALF,
|
||||
(char *) (&hData[0][0]),
|
||||
sizeof (hData[0][0]) * 1,
|
||||
sizeof (hData[0][0]) * width,
|
||||
1, 1,
|
||||
0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
class WritingTask: public Task
|
||||
{
|
||||
public:
|
||||
WritingTask (TaskGroup *group, TiledOutputPart& part,
|
||||
int lx, int ly, int startY, int numXTiles):
|
||||
Task(group),
|
||||
part(part),
|
||||
lx(lx),
|
||||
ly(ly),
|
||||
startY(startY),
|
||||
numXTiles(numXTiles)
|
||||
{}
|
||||
|
||||
void execute()
|
||||
{
|
||||
part.writeTiles(0, numXTiles - 1, startY, startY, lx, ly);
|
||||
}
|
||||
|
||||
private:
|
||||
TiledOutputPart& part;
|
||||
int lx, ly;
|
||||
int startY;
|
||||
int numXTiles;
|
||||
};
|
||||
|
||||
class ReadingTask: public Task
|
||||
{
|
||||
public:
|
||||
ReadingTask (TaskGroup *group, TiledInputPart& part,
|
||||
int lx, int ly, int startY, int numXTiles):
|
||||
Task(group),
|
||||
part(part),
|
||||
lx(lx),
|
||||
ly(ly),
|
||||
startY(startY),
|
||||
numXTiles(numXTiles)
|
||||
{}
|
||||
|
||||
void execute()
|
||||
{
|
||||
part.readTiles(0, numXTiles - 1, startY, startY, lx, ly);
|
||||
}
|
||||
|
||||
private:
|
||||
TiledInputPart& part;
|
||||
int lx, ly;
|
||||
int startY;
|
||||
int numXTiles;
|
||||
};
|
||||
|
||||
void
|
||||
generateFiles (const std::string & fn)
|
||||
{
|
||||
//
|
||||
// Generating headers.
|
||||
//
|
||||
|
||||
cout << "Generating headers " << flush;
|
||||
headers.clear();
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
Header header(width, height);
|
||||
int pixelType = pixelTypes[i];
|
||||
|
||||
stringstream ss;
|
||||
ss << i;
|
||||
header.setName(ss.str());
|
||||
|
||||
switch (pixelType)
|
||||
{
|
||||
case 0:
|
||||
header.channels().insert("UINT", Channel(IMF::UINT));
|
||||
break;
|
||||
case 1:
|
||||
header.channels().insert("FLOAT", Channel(IMF::FLOAT));
|
||||
break;
|
||||
case 2:
|
||||
header.channels().insert("HALF", Channel(IMF::HALF));
|
||||
break;
|
||||
}
|
||||
|
||||
header.setType(TILEDIMAGE);
|
||||
|
||||
int tileX = tileSize;
|
||||
int tileY = tileSize;
|
||||
LevelMode lm;
|
||||
switch (levelMode)
|
||||
{
|
||||
case 0:
|
||||
lm = ONE_LEVEL;
|
||||
break;
|
||||
case 1:
|
||||
lm = MIPMAP_LEVELS;
|
||||
break;
|
||||
case 2:
|
||||
lm = RIPMAP_LEVELS;
|
||||
break;
|
||||
}
|
||||
header.setTileDescription(TileDescription(tileX, tileY, lm));
|
||||
|
||||
headers.push_back(header);
|
||||
}
|
||||
|
||||
//
|
||||
// Preparing.
|
||||
//
|
||||
remove (fn.c_str());
|
||||
MultiPartOutputFile file(fn.c_str(), &headers[0],headers.size());
|
||||
vector<TiledOutputPart> parts;
|
||||
Array2D<half> halfData[2];
|
||||
Array2D<float> floatData[2];
|
||||
Array2D<unsigned int> uintData[2];
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
TiledOutputPart part(file, i);
|
||||
parts.push_back(part);
|
||||
}
|
||||
|
||||
//
|
||||
// Writing files.
|
||||
//
|
||||
cout << "Writing files " << flush;
|
||||
|
||||
//
|
||||
// Two parts are the same, and we pick parts[0].
|
||||
//
|
||||
TiledOutputPart& part = parts[0];
|
||||
|
||||
int numXLevels = part.numXLevels();
|
||||
int numYLevels = part.numYLevels();
|
||||
|
||||
for (int xLevel = 0; xLevel < numXLevels; xLevel++)
|
||||
for (int yLevel = 0; yLevel < numYLevels; yLevel++)
|
||||
{
|
||||
if (!part.isValidLevel(xLevel, yLevel))
|
||||
continue;
|
||||
|
||||
int w = part.levelWidth(xLevel);
|
||||
int h = part.levelHeight(yLevel);
|
||||
|
||||
FrameBuffer frameBuffers[2];
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
FrameBuffer& frameBuffer = frameBuffers[i];
|
||||
|
||||
switch (pixelTypes[i])
|
||||
{
|
||||
case 0:
|
||||
fillPixels<unsigned int>(uintData[i], w, h);
|
||||
break;
|
||||
case 1:
|
||||
fillPixels<float>(floatData[i], w, h);
|
||||
break;
|
||||
case 2:
|
||||
fillPixels<half>(halfData[i], w, h);
|
||||
break;
|
||||
}
|
||||
setOutputFrameBuffer(frameBuffer, pixelTypes[i],
|
||||
uintData[i],
|
||||
floatData[i],
|
||||
halfData[i],
|
||||
w);
|
||||
parts[i].setFrameBuffer(frameBuffer);
|
||||
}
|
||||
|
||||
TaskGroup taskGroup;
|
||||
ThreadPool* threadPool = new ThreadPool(2);
|
||||
int numXTiles = part.numXTiles(xLevel);
|
||||
int numYTiles = part.numYTiles(yLevel);
|
||||
for (int i = 0; i < numYTiles; i++)
|
||||
{
|
||||
threadPool->addTask(
|
||||
(new WritingTask (&taskGroup, parts[0],
|
||||
xLevel, yLevel, i, numXTiles)));
|
||||
threadPool->addTask(
|
||||
(new WritingTask (&taskGroup, parts[1],
|
||||
xLevel, yLevel, i, numXTiles)));
|
||||
}
|
||||
delete threadPool;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
readFiles (const std::string & fn)
|
||||
{
|
||||
|
||||
cout << "Checking headers " << flush;
|
||||
MultiPartInputFile file(fn.c_str());
|
||||
assert (file.parts() == 2);
|
||||
for (size_t i = 0; i < 2; i++)
|
||||
{
|
||||
const Header& header = file.header(i);
|
||||
assert (header.displayWindow() == headers[i].displayWindow());
|
||||
assert (header.dataWindow() == headers[i].dataWindow());
|
||||
assert (header.pixelAspectRatio() == headers[i].pixelAspectRatio());
|
||||
assert (header.screenWindowCenter() == headers[i].screenWindowCenter());
|
||||
assert (header.screenWindowWidth() == headers[i].screenWindowWidth());
|
||||
assert (header.lineOrder() == headers[i].lineOrder());
|
||||
assert (header.compression() == headers[i].compression());
|
||||
assert (header.channels() == headers[i].channels());
|
||||
assert (header.name() == headers[i].name());
|
||||
assert (header.type() == headers[i].type());
|
||||
}
|
||||
|
||||
//
|
||||
// Preparing.
|
||||
//
|
||||
|
||||
Array2D<unsigned int> uData[2];
|
||||
Array2D<float> fData[2];
|
||||
Array2D<half> hData[2];
|
||||
vector<TiledInputPart> parts;
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
TiledInputPart part(file, i);
|
||||
parts.push_back(part);
|
||||
}
|
||||
|
||||
//
|
||||
// Reading files.
|
||||
//
|
||||
|
||||
cout << "Reading and comparing files " << flush;
|
||||
TiledInputPart& part = parts[0];
|
||||
|
||||
int numXLevels = part.numXLevels();
|
||||
int numYLevels = part.numYLevels();
|
||||
|
||||
for (int xLevel = 0; xLevel < numXLevels; xLevel++)
|
||||
for (int yLevel = 0; yLevel < numYLevels; yLevel++)
|
||||
{
|
||||
if (!part.isValidLevel(xLevel, yLevel))
|
||||
continue;
|
||||
|
||||
int w = part.levelWidth(xLevel);
|
||||
int h = part.levelHeight(yLevel);
|
||||
|
||||
FrameBuffer frameBuffers[2];
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
FrameBuffer& frameBuffer = frameBuffers[i];
|
||||
|
||||
setInputFrameBuffer(frameBuffer, pixelTypes[i],
|
||||
uData[i],
|
||||
fData[i],
|
||||
hData[i],
|
||||
w, h);
|
||||
parts[i].setFrameBuffer(frameBuffer);
|
||||
}
|
||||
|
||||
TaskGroup taskGroup;
|
||||
ThreadPool* threadPool = new ThreadPool(2);
|
||||
int numXTiles = part.numXTiles(xLevel);
|
||||
int numYTiles = part.numYTiles(yLevel);
|
||||
for (int i = 0; i < numYTiles; i++)
|
||||
{
|
||||
threadPool->addTask(
|
||||
(new ReadingTask (&taskGroup, parts[0],
|
||||
xLevel, yLevel, i, numXTiles)));
|
||||
threadPool->addTask(
|
||||
(new ReadingTask (&taskGroup, parts[1],
|
||||
xLevel, yLevel, i, numXTiles)));
|
||||
}
|
||||
delete threadPool;
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
switch (pixelTypes[i])
|
||||
{
|
||||
case 0:
|
||||
assert(checkPixels<unsigned int>(uData[i], w, h));
|
||||
break;
|
||||
case 1:
|
||||
assert(checkPixels<float>(fData[i], w, h));
|
||||
break;
|
||||
case 2:
|
||||
assert(checkPixels<half>(hData[i], w, h));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testWriteRead (const std::string & tempDir)
|
||||
{
|
||||
std::string fn = tempDir + "imf_test_multi_tiled_part_threading.exr";
|
||||
string typeNames[2];
|
||||
string levelModeName;
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
switch (pixelTypes[i])
|
||||
{
|
||||
case 0:
|
||||
typeNames[i] = "unsigned int";
|
||||
break;
|
||||
case 1:
|
||||
typeNames[i] = "float";
|
||||
break;
|
||||
case 2:
|
||||
typeNames[i] = "half";
|
||||
break;
|
||||
}
|
||||
|
||||
switch (levelMode)
|
||||
{
|
||||
case 0:
|
||||
levelModeName = "ONE_LEVEL";
|
||||
break;
|
||||
case 1:
|
||||
levelModeName = "MIPMAP";
|
||||
break;
|
||||
case 2:
|
||||
levelModeName = "RIPMAP";
|
||||
break;
|
||||
}
|
||||
}
|
||||
cout << "part 1: type " << typeNames[0]
|
||||
<< " tiled part, "
|
||||
<< "part 2: type " << typeNames[1]
|
||||
<< " tiled part, "
|
||||
<< "level mode " << levelModeName
|
||||
<< " tile size " << tileSize << "x" << tileSize
|
||||
<< endl << flush;
|
||||
|
||||
generateFiles (fn);
|
||||
readFiles (fn);
|
||||
|
||||
remove (fn.c_str());
|
||||
|
||||
cout << endl << flush;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void testMultiTiledPartThreading (const std::string & tempDir)
|
||||
{
|
||||
try
|
||||
{
|
||||
cout << "Testing the two threads reading/writing on two-tiled-part file" << endl;
|
||||
|
||||
int numThreads = ThreadPool::globalThreadPool().numThreads();
|
||||
ThreadPool::globalThreadPool().setNumThreads(2);
|
||||
|
||||
for (int pt1 = 0; pt1 < 3; pt1++)
|
||||
for (int pt2 = 0; pt2 < 3; pt2++)
|
||||
for (int lm = 0; lm < 3; lm++)
|
||||
for (int size = 1; size < min(width, height); size += 50)
|
||||
{
|
||||
pixelTypes[0] = pt1;
|
||||
pixelTypes[1] = pt2;
|
||||
levelMode = lm;
|
||||
tileSize = size;
|
||||
testWriteRead (tempDir);
|
||||
}
|
||||
|
||||
ThreadPool::globalThreadPool().setNumThreads(numThreads);
|
||||
|
||||
cout << "ok\n" << endl;
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
cerr << "ERROR -- caught exception: " << e.what() << endl;
|
||||
assert (false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef TESTMULTITILEDPARTTHREADING_H_
|
||||
#define TESTMULTITILEDPARTTHREADING_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
void testMultiTiledPartThreading (const std::string & tempDir);
|
||||
|
||||
#endif /* TESTMULTITILEDPARTTHREADING_H_ */
|
||||
510
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testMultiView.cpp
Normal file
510
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testMultiView.cpp
Normal file
@@ -0,0 +1,510 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2007 Weta Digital Ltd
|
||||
// Copyright (c) 2012 Industrial Light & Magic, a division of Lucasfilm
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Weta Digital nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#include <ImfMultiView.h>
|
||||
|
||||
#include <typeinfo>
|
||||
#include <sstream>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
|
||||
using namespace OPENEXR_IMF_NAMESPACE;
|
||||
using namespace std;
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
ChannelList
|
||||
buildList (const char *name, ...)
|
||||
{
|
||||
//
|
||||
// nice function to build channel lists
|
||||
//
|
||||
|
||||
ChannelList list;
|
||||
const char *channelName = name;
|
||||
|
||||
va_list ap;
|
||||
va_start (ap, name);
|
||||
|
||||
while (channelName != 0)
|
||||
{
|
||||
list.insert (channelName, Channel());
|
||||
channelName = va_arg (ap, char *);
|
||||
}
|
||||
|
||||
va_end (ap);
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
testMultiViewFunctions ()
|
||||
{
|
||||
StringVector multiView;
|
||||
|
||||
multiView.push_back ("right");
|
||||
multiView.push_back ("left");
|
||||
multiView.push_back ("centre");
|
||||
|
||||
//
|
||||
// Test viewFromChannelName()
|
||||
//
|
||||
|
||||
// default view
|
||||
|
||||
assert (viewFromChannelName ("R", multiView) == "right");
|
||||
|
||||
// explicitly specified default view
|
||||
|
||||
assert (viewFromChannelName ("right.balween", multiView) == "right");
|
||||
|
||||
// non-default view: two sections
|
||||
|
||||
assert (viewFromChannelName ("left.gritstone", multiView) == "left");
|
||||
|
||||
// non-default view: two sections
|
||||
|
||||
assert (viewFromChannelName ("centre.ronaldsay", multiView) == "centre");
|
||||
|
||||
// non-default view: three sections
|
||||
|
||||
assert (viewFromChannelName ("swaledale.left.lonk", multiView) == "left");
|
||||
|
||||
// explicitly specified default view: four sections
|
||||
|
||||
assert (viewFromChannelName ("manx.loghtan.right.shetland",
|
||||
multiView) == "right");
|
||||
|
||||
// non-default view: five sections
|
||||
|
||||
assert (viewFromChannelName ("dorset.down.hebridean.centre.r",
|
||||
multiView) == "centre");
|
||||
|
||||
// shouldn't happen that we have null channel names
|
||||
|
||||
assert (viewFromChannelName ("", multiView) == "");
|
||||
|
||||
// single section with no view name: default view
|
||||
|
||||
assert (viewFromChannelName ("dartmoor", multiView) == "right");
|
||||
|
||||
// two sections with no view name: no view
|
||||
|
||||
assert (viewFromChannelName ("scottish.blackface", multiView) == "");
|
||||
|
||||
// three sections with no view name: no view
|
||||
|
||||
assert (viewFromChannelName ("beulah.speckled.face", multiView) == "");
|
||||
|
||||
// four sections with no view name: no view
|
||||
|
||||
assert (viewFromChannelName ("devon.and.cornwall.longwool",
|
||||
multiView) == "");
|
||||
|
||||
//
|
||||
// Test areCounterparts()
|
||||
//
|
||||
|
||||
// two non default channel names in list
|
||||
|
||||
assert (areCounterparts ("right.R",
|
||||
"centre.R",
|
||||
multiView) == true);
|
||||
|
||||
// two channel names, both explicit and in list,
|
||||
// even though one is default channel
|
||||
|
||||
assert (areCounterparts ("left.R",
|
||||
"right.R",
|
||||
multiView) == true);
|
||||
|
||||
// default view with non-default view
|
||||
|
||||
assert (areCounterparts ("R",
|
||||
"left.R",
|
||||
multiView) == true);
|
||||
|
||||
// as above, but other way round
|
||||
|
||||
assert (areCounterparts ("left.R",
|
||||
"R",
|
||||
multiView) == true);
|
||||
|
||||
// same channel name specified in two different ways
|
||||
|
||||
assert (areCounterparts ("right.R",
|
||||
"R",
|
||||
multiView) == false);
|
||||
|
||||
// as above, but other way round
|
||||
|
||||
assert (areCounterparts ("R",
|
||||
"right.R",
|
||||
multiView) == false);
|
||||
|
||||
// none.R is not in a view
|
||||
|
||||
assert (areCounterparts ("none.R",
|
||||
"left.R",
|
||||
multiView) == false);
|
||||
|
||||
// as above, but other way round
|
||||
|
||||
assert (areCounterparts ("left.R",
|
||||
"none.R",
|
||||
multiView) == false);
|
||||
|
||||
// as above, but with default channel
|
||||
|
||||
assert (areCounterparts ("X",
|
||||
"none.X",
|
||||
multiView) == false);
|
||||
|
||||
// as above, but other way round
|
||||
|
||||
assert (areCounterparts ("none.B",
|
||||
"B",
|
||||
multiView) == false);
|
||||
|
||||
// both not in a view
|
||||
|
||||
assert (areCounterparts ("southdown.none.G",
|
||||
"wiltshire.horn.G",
|
||||
multiView) == false);
|
||||
|
||||
// as above, but different lengths of names
|
||||
|
||||
assert (areCounterparts ("wiltshire.horn.G",
|
||||
"cotswold.G",
|
||||
multiView) == false);
|
||||
|
||||
// three section pairs
|
||||
|
||||
assert (areCounterparts ("wensleydale.left.baa",
|
||||
"wensleydale.right.baa",
|
||||
multiView) == true);
|
||||
|
||||
// different in first section
|
||||
|
||||
assert (areCounterparts ("wensleydal.left.baa",
|
||||
"wensleydale.right.baa",
|
||||
multiView) == false);
|
||||
|
||||
// different in last section
|
||||
|
||||
assert (areCounterparts ("wensleydale.left.bah",
|
||||
"wensleydale.right.baa",
|
||||
multiView) == false);
|
||||
|
||||
// same channel
|
||||
|
||||
assert (areCounterparts ("wensleydale.left.baa",
|
||||
"wensleydale.left.baa",
|
||||
multiView) == false);
|
||||
|
||||
// second is in no view
|
||||
|
||||
assert (areCounterparts ("wensleydale.right.fell",
|
||||
"wensleydale.rough.fell",
|
||||
multiView) == false);
|
||||
|
||||
// first is in no view
|
||||
|
||||
assert (areCounterparts ("wensleydale.rough.fell",
|
||||
"wensleydale.left.fell",
|
||||
multiView) == false);
|
||||
|
||||
// four sectons
|
||||
|
||||
assert (areCounterparts ("lincoln.longwool.right.A",
|
||||
"lincoln.longwool.left.A",
|
||||
multiView) == true);
|
||||
|
||||
// different in final section
|
||||
|
||||
assert (areCounterparts ("lincoln.longwool.right.B",
|
||||
"lincoln.longwool.left.A",
|
||||
multiView) == false);
|
||||
|
||||
// different in second section
|
||||
|
||||
assert (areCounterparts ("lincoln.shortwool.right.A",
|
||||
"lincoln.longwool.left.A",
|
||||
multiView) == false);
|
||||
|
||||
// different in first section
|
||||
|
||||
assert (areCounterparts ("cumbria.longwool.right.A",
|
||||
"lincoln.longwool.left.A",
|
||||
multiView) == false);
|
||||
|
||||
// enough said
|
||||
|
||||
assert (areCounterparts ("baa.baa.black.sheep",
|
||||
"lincoln.longwool.left.A",
|
||||
multiView) == false);
|
||||
|
||||
|
||||
// three sections with default - only last is same
|
||||
|
||||
assert (areCounterparts ("portland.left.baa",
|
||||
"baa",
|
||||
multiView) == false);
|
||||
|
||||
// four sections with default
|
||||
|
||||
assert (areCounterparts ("dorset.down.left.baa",
|
||||
"baa",
|
||||
multiView) == false);
|
||||
|
||||
//
|
||||
// Channel list tests
|
||||
//
|
||||
|
||||
// list of channels in some multiview image
|
||||
|
||||
ChannelList a = buildList
|
||||
("A",
|
||||
"B",
|
||||
"C",
|
||||
"right.jacob",
|
||||
"shropshire.right.D",
|
||||
"castlemilk.moorit.right.A",
|
||||
"black.welsh.mountain.right.A",
|
||||
"left.A",
|
||||
"left.B",
|
||||
"left.C",
|
||||
"left.jacob",
|
||||
"shropshire.left.D",
|
||||
"castlemilk.moorit.left.A",
|
||||
"black.welsh.mountain.left.A",
|
||||
"centre.A",
|
||||
"centre.B",
|
||||
"centre.C",
|
||||
"shropshire.centre.D",
|
||||
"castlemilk.moorit.centre.A",
|
||||
"none.A",
|
||||
"none.B",
|
||||
"none.C",
|
||||
"none.D",
|
||||
"none.jacob",
|
||||
"shropshire.none.D",
|
||||
"rough.fell",
|
||||
(char *) 0);
|
||||
|
||||
//
|
||||
// List of channels in each view
|
||||
//
|
||||
|
||||
// all left channels
|
||||
|
||||
ChannelList realLeft = buildList
|
||||
("left.A",
|
||||
"left.B",
|
||||
"left.C",
|
||||
"left.jacob",
|
||||
"shropshire.left.D",
|
||||
"castlemilk.moorit.left.A",
|
||||
"black.welsh.mountain.left.A",
|
||||
(char *) 0);
|
||||
|
||||
ChannelList realRight = buildList
|
||||
("A",
|
||||
"B",
|
||||
"C",
|
||||
"right.jacob",
|
||||
"shropshire.right.D",
|
||||
"castlemilk.moorit.right.A",
|
||||
"black.welsh.mountain.right.A",
|
||||
(char *) 0);
|
||||
|
||||
// all the right channels including the default channels
|
||||
|
||||
ChannelList realCentre = buildList
|
||||
("centre.A",
|
||||
"centre.B",
|
||||
"centre.C",
|
||||
"shropshire.centre.D",
|
||||
"castlemilk.moorit.centre.A",
|
||||
(char *) 0);
|
||||
|
||||
// no jacob channel
|
||||
// there IS a jacob channel but it has no counterparts because
|
||||
// this is in "no view"
|
||||
|
||||
ChannelList realNone = buildList
|
||||
("none.A",
|
||||
"none.B",
|
||||
"none.D",
|
||||
"none.C",
|
||||
"none.jacob",
|
||||
"shropshire.none.D",
|
||||
"rough.fell",
|
||||
(char *) 0);
|
||||
|
||||
// have a dummy name just to throw a wolf amongst the sheep
|
||||
|
||||
multiView.push_back ("wolf");
|
||||
|
||||
// no channels
|
||||
|
||||
ChannelList realNull = buildList ((char *) 0);
|
||||
|
||||
//
|
||||
// Test channelsInView()
|
||||
//
|
||||
|
||||
// default view channel extraction
|
||||
|
||||
assert (channelsInView ("right", a, multiView) == realRight);
|
||||
|
||||
// non-default view channel extraction
|
||||
|
||||
assert (channelsInView ("left", a, multiView) == realLeft);
|
||||
|
||||
// missing 'centre.jacob'
|
||||
|
||||
assert (channelsInView ("centre", a, multiView) == realCentre);
|
||||
|
||||
// "none" isn't a view name, no channels returned
|
||||
|
||||
assert (channelsInView ("none", a, multiView) == realNull);
|
||||
|
||||
// "wolf" has no channels, no channels returned
|
||||
|
||||
assert (channelsInView ("wolf", a, multiView) == realNull);
|
||||
|
||||
// all no view channels
|
||||
|
||||
assert (channelsInNoView (a, multiView) == realNone);
|
||||
|
||||
|
||||
//
|
||||
// Test channelInAllViews()
|
||||
//
|
||||
|
||||
ChannelList realA = buildList
|
||||
("left.A",
|
||||
"A",
|
||||
"centre.A",
|
||||
(char *) 0);
|
||||
|
||||
ChannelList realB = buildList
|
||||
("left.B",
|
||||
"B",
|
||||
"centre.B",
|
||||
(char *) 0);
|
||||
|
||||
ChannelList realJacob = buildList
|
||||
("left.jacob",
|
||||
"right.jacob",
|
||||
(char *) 0);
|
||||
|
||||
ChannelList realCm = buildList
|
||||
("castlemilk.moorit.left.A",
|
||||
"castlemillk.moorit.right.A",
|
||||
"castlemilk.moorit.centre.A",
|
||||
(char *) 0);
|
||||
|
||||
ChannelList realBwm = buildList
|
||||
("black.welsh.mountain.left.A",
|
||||
"black.welsh.mountain.right.A",
|
||||
(char *) 0);
|
||||
|
||||
assert (channelInAllViews ("left.A", a, multiView) == realA);
|
||||
|
||||
assert (channelInAllViews ("A", a, multiView) == realA);
|
||||
|
||||
assert (channelInAllViews ("centre.B", a, multiView) == realB);
|
||||
|
||||
assert (channelInAllViews ("right.jacob", a, multiView) == realJacob);
|
||||
|
||||
assert (channelInAllViews ("castlemilk.moorit.centre.A",
|
||||
a, multiView) == realCm);
|
||||
|
||||
assert (channelInAllViews ("black.welsh.mountain.right.A",
|
||||
a, multiView) == realBwm);
|
||||
|
||||
//
|
||||
// Test insertViewName()
|
||||
//
|
||||
|
||||
assert (insertViewName ("A", multiView, 0) ==
|
||||
"A");
|
||||
|
||||
assert (insertViewName ("mountain.A", multiView, 0) ==
|
||||
"mountain.right.A");
|
||||
|
||||
assert (insertViewName ("welsh.mountain.A", multiView, 0) ==
|
||||
"welsh.mountain.right.A");
|
||||
|
||||
assert (insertViewName ("black.welsh.mountain.A", multiView, 0) ==
|
||||
"black.welsh.mountain.right.A");
|
||||
|
||||
assert (insertViewName ("A", multiView, 1) ==
|
||||
"left.A");
|
||||
|
||||
assert (insertViewName ("mountain.A", multiView, 1) ==
|
||||
"mountain.left.A");
|
||||
|
||||
assert (insertViewName ("welsh.mountain.A", multiView, 1) ==
|
||||
"welsh.mountain.left.A");
|
||||
|
||||
assert (insertViewName ("black.welsh.mountain.A", multiView, 1) ==
|
||||
"black.welsh.mountain.left.A");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
void
|
||||
testMultiView (const std::string&)
|
||||
{
|
||||
try
|
||||
{
|
||||
cout << "Testing multi-view channel list functions" << endl;
|
||||
testMultiViewFunctions();
|
||||
cout << "ok\n" << endl;
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
cerr << "ERROR -- caught exception: " << e.what() << endl;
|
||||
assert (false);
|
||||
}
|
||||
}
|
||||
41
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testMultiView.h
Normal file
41
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testMultiView.h
Normal file
@@ -0,0 +1,41 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2007 Weta Digital Ltd
|
||||
// Copyright (c) 2012 Industrial Light & Magic, a division of Lucasfilm
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Weta Digital nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
#include <string>
|
||||
|
||||
void testMultiView (const std::string &tempDir);
|
||||
|
||||
294
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testNativeFormat.cpp
Normal file
294
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testNativeFormat.cpp
Normal file
@@ -0,0 +1,294 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2003-2012, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include <ImfOutputFile.h>
|
||||
#include <ImfInputFile.h>
|
||||
#include <ImfChannelList.h>
|
||||
#include <ImfRgbaFile.h>
|
||||
#include <ImfArray.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifndef ILM_IMF_TEST_IMAGEDIR
|
||||
#define ILM_IMF_TEST_IMAGEDIR
|
||||
#endif
|
||||
|
||||
|
||||
using namespace OPENEXR_IMF_NAMESPACE;
|
||||
using namespace std;
|
||||
using namespace IMATH_NAMESPACE;
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
void
|
||||
readImage (const char fileName[],
|
||||
Array2D<Rgba>& pixels,
|
||||
int& w,
|
||||
int& h,
|
||||
unsigned int correctChecksum)
|
||||
{
|
||||
RgbaInputFile in (fileName);
|
||||
|
||||
const Box2i &dw = in.dataWindow();
|
||||
|
||||
w = dw.max.x - dw.min.x + 1;
|
||||
h = dw.max.y - dw.min.y + 1;
|
||||
int dx = dw.min.x;
|
||||
int dy = dw.min.y;
|
||||
|
||||
pixels.resizeErase (h, w);
|
||||
in.setFrameBuffer (&pixels[0][0] - dx - dy * w, 1, w);
|
||||
in.readPixels (in.dataWindow().min.y, in.dataWindow().max.y);
|
||||
|
||||
unsigned int checksum = 0;
|
||||
|
||||
for (int y = 0; y < h; ++y)
|
||||
for (int x = 0; x < w; ++x)
|
||||
{
|
||||
checksum ^= pixels[y][x].r.bits();
|
||||
checksum ^= pixels[y][x].g.bits();
|
||||
checksum ^= pixels[y][x].b.bits();
|
||||
checksum ^= pixels[y][x].a.bits();
|
||||
}
|
||||
|
||||
cout << "checksum = " << checksum << flush;
|
||||
|
||||
assert (checksum == correctChecksum);
|
||||
|
||||
cout << ", ok" << flush;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
readBackImage (const char fileName[],
|
||||
Array2D<Rgba>& pixels,
|
||||
const Array2D<Rgba>& pixels2,
|
||||
int& w,
|
||||
int& h,
|
||||
const int& xs,
|
||||
const int& ys)
|
||||
{
|
||||
InputFile file (fileName);
|
||||
|
||||
Box2i dw = file.header().dataWindow();
|
||||
w = dw.max.x - dw.min.x + 1;
|
||||
h = dw.max.y - dw.min.y + 1;
|
||||
|
||||
pixels.resizeErase (h, w);
|
||||
|
||||
FrameBuffer frameBuffer;
|
||||
|
||||
Rgba *base = &pixels[0][0] - dw.min.x - dw.min.y * w;
|
||||
int xStride = sizeof (pixels[0][0]) * xs;
|
||||
int yStride = sizeof (pixels[0][0]) * w * ys;
|
||||
|
||||
frameBuffer.insert ("R", // name
|
||||
Slice (HALF, // type
|
||||
(char *) &base[0].r, // base
|
||||
xStride, // xStride
|
||||
yStride, // yStride
|
||||
xs, ys, // x/y sampling
|
||||
0.0)); // fillValue
|
||||
|
||||
frameBuffer.insert ("G", // name
|
||||
Slice (HALF, // type
|
||||
(char *) &base[0].g, // base
|
||||
xStride, // xStride
|
||||
yStride, // yStride
|
||||
xs, ys, // x/y sampling
|
||||
0.0)); // fillValue
|
||||
|
||||
frameBuffer.insert ("B", // name
|
||||
Slice (HALF, // type
|
||||
(char *) &base[0].b, // base
|
||||
xStride, // xStride
|
||||
yStride, // yStride
|
||||
xs, ys, // x/y sampling
|
||||
0.0)); // fillValue
|
||||
|
||||
frameBuffer.insert ("A", // name
|
||||
Slice (HALF, // type
|
||||
(char *) &base[0].a, // base
|
||||
xStride, // xStride
|
||||
yStride, // yStride
|
||||
xs, ys, // x/y sampling
|
||||
1.0)); // fillValue
|
||||
|
||||
file.setFrameBuffer (frameBuffer);
|
||||
file.readPixels (dw.min.y, dw.max.y);
|
||||
|
||||
cout << "comparing, " << flush;
|
||||
for (int y = 0; y < h; y+=ys)
|
||||
for (int x = 0; x < w; x+=xs)
|
||||
{
|
||||
assert(pixels2[y][x].r.bits() == pixels[y][x].r.bits());
|
||||
assert(pixels2[y][x].g.bits() == pixels[y][x].g.bits());
|
||||
assert(pixels2[y][x].b.bits() == pixels[y][x].b.bits());
|
||||
assert(pixels2[y][x].a.bits() == pixels[y][x].a.bits());
|
||||
}
|
||||
cout << "ok" << endl << flush;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
writeImage (const char fileName[],
|
||||
const Array2D<OPENEXR_IMF_NAMESPACE::Rgba>& pixels,
|
||||
const int& width,
|
||||
const int& height,
|
||||
const int& xs = 1,
|
||||
const int& ys = 1)
|
||||
{
|
||||
//
|
||||
// Write the image to fileName one scanline at a time
|
||||
//
|
||||
|
||||
Header header (width, height);
|
||||
header.compression() = PIZ_COMPRESSION;
|
||||
header.channels().insert ("R", Channel (HALF,xs,ys));
|
||||
header.channels().insert ("G", Channel (HALF,xs,ys));
|
||||
header.channels().insert ("B", Channel (HALF,xs,ys));
|
||||
header.channels().insert ("A", Channel (HALF,xs,ys));
|
||||
|
||||
OutputFile file (fileName, header);
|
||||
FrameBuffer frameBuffer;
|
||||
|
||||
const Rgba *base = &pixels[0][0];
|
||||
int xStride = sizeof (pixels[0][0]) * xs;
|
||||
int yStride = sizeof (pixels[0][0]) * 0;
|
||||
|
||||
frameBuffer.insert ("R", // name
|
||||
Slice (HALF, // type
|
||||
(char *) &base[0].r, // base
|
||||
xStride, // xStride
|
||||
yStride, // yStride
|
||||
xs, ys)); // x/y sampling
|
||||
|
||||
frameBuffer.insert ("G", // name
|
||||
Slice (HALF, // type
|
||||
(char *) &base[0].g, // base
|
||||
xStride, // xStride
|
||||
yStride, // yStride
|
||||
xs, ys)); // x/y sampling
|
||||
|
||||
frameBuffer.insert ("B", // name
|
||||
Slice (HALF, // type
|
||||
(char *) &base[0].b, // base
|
||||
xStride, // xStride
|
||||
yStride, // yStride
|
||||
xs, ys)); // x/y sampling
|
||||
|
||||
frameBuffer.insert ("A", // name
|
||||
Slice (HALF, // type
|
||||
(char *) &base[0].a, // base
|
||||
xStride, // xStride
|
||||
yStride, // yStride
|
||||
xs, ys)); // x/y sampling
|
||||
|
||||
// iterate over all scanlines, and write them out
|
||||
for (int y = 0; y < height; ++y)
|
||||
{
|
||||
// set the base address for this scanline
|
||||
base = &pixels[y][0];
|
||||
frameBuffer["R"].base = (char *) &base[0].r;
|
||||
frameBuffer["G"].base = (char *) &base[0].g;
|
||||
frameBuffer["B"].base = (char *) &base[0].b;
|
||||
frameBuffer["A"].base = (char *) &base[0].a;
|
||||
|
||||
// set the framebuffer and write the pixels
|
||||
file.setFrameBuffer (frameBuffer);
|
||||
file.writePixels (1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
readCopyRead (const std::string &tempDir,
|
||||
const char* infilename,
|
||||
unsigned int correctChecksum)
|
||||
{
|
||||
std::string outfilename = tempDir + "imf_test_native.exr";
|
||||
|
||||
int w, h;
|
||||
Array2D<OPENEXR_IMF_NAMESPACE::Rgba> pixels (1,1);
|
||||
|
||||
cout << " reading, " << flush;
|
||||
readImage(infilename, pixels, w, h, correctChecksum);
|
||||
cout << endl;
|
||||
|
||||
for (int xs = 1; xs <= 2; ++xs)
|
||||
{
|
||||
for (int ys = 1; ys <= 2; ++ys)
|
||||
{
|
||||
cout << " x sampling " << xs << ", y sampling " << ys <<
|
||||
": writing image, " << flush;
|
||||
writeImage(outfilename.c_str(), pixels, w, h, xs, ys);
|
||||
|
||||
Array2D<OPENEXR_IMF_NAMESPACE::Rgba> pixels2 (1,1);
|
||||
cout << "reading back, " << flush;
|
||||
readBackImage(outfilename.c_str(), pixels2, pixels, w, h, xs, ys);
|
||||
|
||||
remove(outfilename.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
void
|
||||
testNativeFormat (const std::string &tempDir)
|
||||
{
|
||||
try
|
||||
{
|
||||
cout << "Testing if uncompressible pixel data are written "
|
||||
"in Xdr, not native format" << endl;
|
||||
|
||||
cout << "image 1:" << endl;
|
||||
readCopyRead(tempDir, ILM_IMF_TEST_IMAGEDIR "test_native1.exr", 54435);
|
||||
|
||||
cout << "image 2:" << endl;
|
||||
readCopyRead(tempDir, ILM_IMF_TEST_IMAGEDIR "test_native2.exr", 37639);
|
||||
|
||||
cout << "ok\n" << endl;
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
cerr << "ERROR -- caught exception: " << e.what() << endl;
|
||||
assert (false);
|
||||
}
|
||||
}
|
||||
39
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testNativeFormat.h
Normal file
39
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testNativeFormat.h
Normal file
@@ -0,0 +1,39 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2003-2012, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include <string>
|
||||
|
||||
void testNativeFormat (const std::string &tempDir);
|
||||
|
||||
626
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testOptimized.cpp
Normal file
626
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testOptimized.cpp
Normal file
@@ -0,0 +1,626 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include <ImfOutputFile.h>
|
||||
#include <ImfInputFile.h>
|
||||
#include <ImfChannelList.h>
|
||||
#include <ImfArray.h>
|
||||
#include <ImfVersion.h>
|
||||
#include "half.h"
|
||||
|
||||
#include <ImfBoxAttribute.h>
|
||||
#include <ImfChannelListAttribute.h>
|
||||
#include <ImfCompressionAttribute.h>
|
||||
#include <ImfChromaticitiesAttribute.h>
|
||||
#include <ImfFloatAttribute.h>
|
||||
#include <ImfEnvmapAttribute.h>
|
||||
#include <ImfDoubleAttribute.h>
|
||||
#include <ImfIntAttribute.h>
|
||||
#include <ImfLineOrderAttribute.h>
|
||||
#include <ImfMatrixAttribute.h>
|
||||
#include <ImfOpaqueAttribute.h>
|
||||
#include <ImfStringAttribute.h>
|
||||
#include <ImfStringVectorAttribute.h>
|
||||
#include <ImfVecAttribute.h>
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
using namespace std;
|
||||
namespace IMF = OPENEXR_IMF_NAMESPACE;
|
||||
using namespace IMF;
|
||||
|
||||
namespace IMATH = IMATH_NAMESPACE;
|
||||
using namespace IMATH;
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
static const int IMAGE_2K_HEIGHT = 1152;
|
||||
static const int IMAGE_2K_WIDTH = 2048;
|
||||
|
||||
static const char* CHANNEL_NAMES[] = {"R", "G", "B", "A"};
|
||||
static const char* CHANNEL_NAMES_LEFT[] = {"left.R", "left.G", "left.B", "left.A"};
|
||||
|
||||
static const half ALPHA_DEFAULT_VALUE(1.0f);
|
||||
|
||||
#define RGB_FILENAME "imf_optimized_aces_rgb.exr"
|
||||
#define RGBA_FILENAME "imf_optimized_aces_rgba.exr"
|
||||
#define RGB_STEREO_FILENAME "imf_optimized_aces_rgb_stereo.exr"
|
||||
#define RGBA_STEREO_FILENAME "imf_optimized_aces_rgba_stereo.exr"
|
||||
|
||||
typedef enum EImageType
|
||||
{
|
||||
IMAGE_TYPE_RGB = 1,
|
||||
IMAGE_TYPE_RGBA = 2,
|
||||
IMAGE_TYPE_OTHER =3
|
||||
} EImageType;
|
||||
|
||||
int
|
||||
getNbChannels(EImageType pImageType)
|
||||
{
|
||||
int retVal = 0;
|
||||
|
||||
switch(pImageType)
|
||||
{
|
||||
case IMAGE_TYPE_RGB:
|
||||
retVal = 3;
|
||||
break;
|
||||
case IMAGE_TYPE_RGBA:
|
||||
retVal = 4;
|
||||
break;
|
||||
case IMAGE_TYPE_OTHER:
|
||||
retVal = 2;
|
||||
break;
|
||||
default:
|
||||
retVal = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
void
|
||||
generatePixel (int i, int j, half* rgbaValue, bool pIsLeft)
|
||||
{
|
||||
float redValue = 0.0f;
|
||||
float greenValue = 0.0f;
|
||||
float blueValue = 0.0f;
|
||||
float alphaValue = 0.0f;
|
||||
|
||||
// These formulas are arbitrary but generate results that vary
|
||||
// depending on pixel position. They are used to validate that
|
||||
// pixels are read/written correctly, because if we had only one
|
||||
// value for the whole image, the tests would still pass if we read
|
||||
// only one pixel and copied it all across the buffer.
|
||||
if(pIsLeft)
|
||||
{
|
||||
redValue = ((i + j) % 10 + 0.004f * j) / 10.0f;
|
||||
greenValue = ((j + j) % 10 + 0.006f * i) / 10.0f;
|
||||
blueValue = ((j * j + i) % 10 + 0.003f * j) / 10.0f;
|
||||
alphaValue = ALPHA_DEFAULT_VALUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
redValue = ((i * j) % 10 + 0.005f * j) / 10.0f;
|
||||
greenValue = ((i + i) % 10 + 0.007f * i) / 10.0f;
|
||||
blueValue = ((i * i + j) % 10 + 0.006f * j) / 10.0f;
|
||||
alphaValue = ALPHA_DEFAULT_VALUE;
|
||||
}
|
||||
|
||||
|
||||
rgbaValue[0] = redValue;
|
||||
rgbaValue[1] = greenValue;
|
||||
rgbaValue[2] = blueValue;
|
||||
rgbaValue[3] = alphaValue;
|
||||
}
|
||||
|
||||
//
|
||||
// Given a buffer, fill the pixels with arbitrary but deterministic values.
|
||||
// Used to fill the pixels in a buffer before writing them to a file.
|
||||
//
|
||||
void
|
||||
fillPixels (const int& pImageHeight,
|
||||
const int& pImageWidth,
|
||||
Array2D<half>& pPixels,
|
||||
int pNbChannels,
|
||||
bool pIsLeft)
|
||||
{
|
||||
for(int i = 0; i < pImageHeight; ++i)
|
||||
{
|
||||
for(int j = 0; j < pImageWidth; ++j)
|
||||
{
|
||||
half rgbaValue[4];
|
||||
|
||||
generatePixel(i, j, &rgbaValue[0], pIsLeft);
|
||||
memcpy( (void*)&pPixels[i][j * pNbChannels],
|
||||
&rgbaValue[0],
|
||||
pNbChannels * sizeof(half));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Validate that the pixels value are the same as what we used to fill them.
|
||||
// Used after reading the pixels from the file to validate that it was read
|
||||
// properly.
|
||||
//
|
||||
void
|
||||
validatePixels (const int& pImageHeight,
|
||||
const int& pImageWidth,
|
||||
Array2D<half>& pPixels,
|
||||
int pNbChannels,
|
||||
bool pIsLeft)
|
||||
{
|
||||
for(int i = 0; i < pImageHeight; ++i)
|
||||
{
|
||||
for(int j = 0; j < pImageWidth; ++j)
|
||||
{
|
||||
int retVal = -1;
|
||||
half rgbaValue[4];
|
||||
generatePixel(i, j, &rgbaValue[0], pIsLeft);
|
||||
|
||||
retVal = memcmp ((void*)&pPixels[i][j * pNbChannels],
|
||||
(void*)&rgbaValue[0],
|
||||
pNbChannels * sizeof(half));
|
||||
|
||||
if(retVal != 0)
|
||||
{
|
||||
cout << "ERROR at pixel [" << i << ";" << j << "]" << endl;
|
||||
cout << "\tExpected [" << rgbaValue[0] << ", "
|
||||
<< rgbaValue[1] << ", "
|
||||
<< rgbaValue[2] << "] " << endl;
|
||||
|
||||
cout << "\tReceived [" << pPixels[i][j * pNbChannels] << ", "
|
||||
<< pPixels[i][j * pNbChannels + 1] << ", "
|
||||
<< pPixels[i][j * pNbChannels + 2] << "]" << endl;
|
||||
assert(retVal == 0);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Write pixels to a file (mono version)
|
||||
//
|
||||
void
|
||||
writePixels (const char pFilename[],
|
||||
const int& pImageHeight,
|
||||
const int& pImageWidth,
|
||||
Array2D<half>& pPixels,
|
||||
int pNbChannels,
|
||||
Compression pCompression)
|
||||
{
|
||||
Header header (pImageWidth,
|
||||
pImageHeight,
|
||||
1.0f,
|
||||
V2f(0.0f,0.0f),
|
||||
1.0f,
|
||||
INCREASING_Y,
|
||||
pCompression);
|
||||
for(int i = 0; i < pNbChannels; ++i)
|
||||
{
|
||||
header.channels().insert (CHANNEL_NAMES[i], Channel(HALF));
|
||||
}
|
||||
|
||||
OutputFile lFile(pFilename, header);
|
||||
FrameBuffer lOutputFrameBuffer;
|
||||
|
||||
for(int i = 0; i < pNbChannels; ++i)
|
||||
{
|
||||
lOutputFrameBuffer.insert (CHANNEL_NAMES[i],
|
||||
Slice (HALF,
|
||||
(char *) &pPixels[0][i],
|
||||
sizeof (pPixels[0][0]) * pNbChannels,
|
||||
sizeof (pPixels[0][0]) * pNbChannels * pImageWidth));
|
||||
}
|
||||
|
||||
lFile.setFrameBuffer (lOutputFrameBuffer);
|
||||
lFile.writePixels (pImageHeight);
|
||||
}
|
||||
|
||||
//
|
||||
// Write pixels to a file (stereo version)
|
||||
//
|
||||
void
|
||||
writePixels (const char pFilename[],
|
||||
const int& pImageHeight,
|
||||
const int& pImageWidth,
|
||||
Array2D<half>& pPixels,
|
||||
Array2D<half>& pPixelsLeft,
|
||||
int pNbChannels,
|
||||
Compression pCompression)
|
||||
{
|
||||
Header header (pImageWidth,
|
||||
pImageHeight,
|
||||
1.0f,
|
||||
V2f(0.0f,0.0f),
|
||||
1.0f,
|
||||
INCREASING_Y,
|
||||
pCompression);
|
||||
for(int i = 0; i < pNbChannels; ++i)
|
||||
{
|
||||
header.channels().insert (CHANNEL_NAMES[i], Channel(HALF));
|
||||
header.channels().insert (CHANNEL_NAMES_LEFT[i], Channel(HALF));
|
||||
}
|
||||
|
||||
StringVector multiView;
|
||||
multiView.push_back ("right");
|
||||
multiView.push_back ("left");
|
||||
header.insert("multiView", IMF::TypedAttribute<IMF::StringVector>(multiView));
|
||||
|
||||
OutputFile lFile(pFilename, header);
|
||||
FrameBuffer lOutputFrameBuffer;
|
||||
|
||||
for(int i = 0; i < pNbChannels; ++i)
|
||||
{
|
||||
lOutputFrameBuffer.insert (CHANNEL_NAMES[i],
|
||||
Slice (HALF,
|
||||
(char *) &pPixels[0][i],
|
||||
sizeof (pPixels[0][0]) * pNbChannels,
|
||||
sizeof (pPixels[0][0]) * pNbChannels * pImageWidth));
|
||||
|
||||
lOutputFrameBuffer.insert (CHANNEL_NAMES_LEFT[i],
|
||||
Slice (HALF,
|
||||
(char *) &pPixelsLeft[0][i],
|
||||
sizeof (pPixelsLeft[0][0]) * pNbChannels,
|
||||
sizeof (pPixelsLeft[0][0]) * pNbChannels * pImageWidth));
|
||||
}
|
||||
|
||||
lFile.setFrameBuffer (lOutputFrameBuffer);
|
||||
lFile.writePixels (pImageHeight);
|
||||
}
|
||||
|
||||
//
|
||||
// Read pixels from a file (mono version).
|
||||
//
|
||||
void
|
||||
readPixels (const char pFilename[], int pNbChannels, Array2D<half>& pPixels)
|
||||
{
|
||||
InputFile lFile(pFilename);
|
||||
IMATH::Box2i lDataWindow = lFile.header().dataWindow();
|
||||
|
||||
int lWidth = lDataWindow.max.x - lDataWindow.min.x + 1;
|
||||
int lHeight = lDataWindow.max.y - lDataWindow.min.y + 1;
|
||||
|
||||
FrameBuffer lInputFrameBuffer;
|
||||
|
||||
for(int i = 0; i < pNbChannels; ++i)
|
||||
{
|
||||
lInputFrameBuffer.insert (CHANNEL_NAMES[i],
|
||||
Slice (HALF,
|
||||
(char *) &pPixels[0][i],
|
||||
sizeof (pPixels[0][0]) * pNbChannels,
|
||||
sizeof (pPixels[0][0]) * pNbChannels * lWidth,
|
||||
1,
|
||||
1,
|
||||
ALPHA_DEFAULT_VALUE));
|
||||
}
|
||||
|
||||
lFile.setFrameBuffer (lInputFrameBuffer);
|
||||
|
||||
bool is_optimized = lFile.isOptimizationEnabled();
|
||||
if(is_optimized)
|
||||
{
|
||||
cout << " optimization enabled\n";
|
||||
|
||||
if(pNbChannels==2)
|
||||
{
|
||||
cerr << " error: isOptimizationEnabled returned TRUE, but "
|
||||
"optimization not known to work for two channel images\n";
|
||||
assert(pNbChannels!=2);
|
||||
}
|
||||
|
||||
}else{
|
||||
cout << " optimization disabled\n";
|
||||
#ifdef IMF_HAVE_SSE2
|
||||
if(pNbChannels!=2)
|
||||
{
|
||||
cerr << " error: isOptimizationEnabled returned FALSE, but "
|
||||
"should work for " << pNbChannels << "channel images\n";
|
||||
assert(pNbChannels==2);
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
lFile.readPixels (lDataWindow.min.y, lDataWindow.max.y);
|
||||
}
|
||||
|
||||
//
|
||||
// Read pixels from a file (stereo version).
|
||||
//
|
||||
void
|
||||
readPixels (const char pFilename[],
|
||||
int pNbChannels,
|
||||
Array2D<half>& pPixels,
|
||||
Array2D<half>& pPixelsLeft)
|
||||
{
|
||||
InputFile lFile(pFilename);
|
||||
IMATH::Box2i lDataWindow = lFile.header().dataWindow();
|
||||
|
||||
int lWidth = lDataWindow.max.x - lDataWindow.min.x + 1;
|
||||
int lHeight = lDataWindow.max.y - lDataWindow.min.y + 1;
|
||||
|
||||
FrameBuffer lInputFrameBuffer;
|
||||
|
||||
for(int i = 0; i < pNbChannels; ++i)
|
||||
{
|
||||
lInputFrameBuffer.insert (CHANNEL_NAMES[i],
|
||||
Slice (HALF,
|
||||
(char *) &pPixels[0][i],
|
||||
sizeof (pPixels[0][0]) * pNbChannels,
|
||||
sizeof (pPixels[0][0]) * pNbChannels * lWidth,
|
||||
1,
|
||||
1,
|
||||
ALPHA_DEFAULT_VALUE));
|
||||
|
||||
lInputFrameBuffer.insert (CHANNEL_NAMES_LEFT[i],
|
||||
Slice (HALF,
|
||||
(char *) &pPixelsLeft[0][i],
|
||||
sizeof (pPixelsLeft[0][0]) * pNbChannels,
|
||||
sizeof (pPixelsLeft[0][0]) * pNbChannels * lWidth,
|
||||
1,
|
||||
1,
|
||||
ALPHA_DEFAULT_VALUE));
|
||||
}
|
||||
|
||||
lFile.setFrameBuffer (lInputFrameBuffer);
|
||||
lFile.readPixels (lDataWindow.min.y, lDataWindow.max.y);
|
||||
}
|
||||
|
||||
//
|
||||
// Allocate an array of pixels, fill them with values and then write
|
||||
// them to a file.
|
||||
void
|
||||
writeFile (const char pFilename[],
|
||||
int pHeight,
|
||||
int pWidth,
|
||||
EImageType pImageType,
|
||||
bool pIsStereo,
|
||||
Compression pCompression)
|
||||
{
|
||||
const int lNbChannels = getNbChannels (pImageType);
|
||||
Array2D<half> lPixels;
|
||||
|
||||
lPixels.resizeErase (pHeight, pWidth * lNbChannels);
|
||||
fillPixels (pHeight, pWidth, lPixels, lNbChannels, false);
|
||||
|
||||
if(pIsStereo)
|
||||
{
|
||||
Array2D<half> lPixelsLeft;
|
||||
|
||||
lPixelsLeft.resizeErase (pHeight, pWidth * lNbChannels);
|
||||
fillPixels (pHeight,
|
||||
pWidth,
|
||||
lPixelsLeft,
|
||||
lNbChannels,
|
||||
true);
|
||||
|
||||
writePixels (pFilename,
|
||||
pHeight,
|
||||
pWidth,
|
||||
lPixels,
|
||||
lPixelsLeft,
|
||||
lNbChannels,
|
||||
pCompression);
|
||||
}
|
||||
else
|
||||
{
|
||||
writePixels (pFilename,
|
||||
pHeight,
|
||||
pWidth,
|
||||
lPixels,
|
||||
lNbChannels,
|
||||
pCompression);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Read pixels from a file and then validate that the values are the
|
||||
// same as what was used to fill them before writing.
|
||||
//
|
||||
void
|
||||
readValidateFile (const char pFilename[],
|
||||
int pHeight,
|
||||
int pWidth,
|
||||
EImageType
|
||||
pImageType,
|
||||
bool pIsStereo)
|
||||
{
|
||||
const int lNbChannels = getNbChannels(pImageType);
|
||||
|
||||
Array2D<half> lPixels;
|
||||
lPixels.resizeErase(pHeight, pWidth * lNbChannels);
|
||||
//readPixels(pFilename, lNbChannels, lPixels);
|
||||
//writePixels("pkTest.exr", pHeight, pWidth, lPixels, lNbChannels, NO_COMPRESSION);
|
||||
|
||||
|
||||
if(pIsStereo)
|
||||
{
|
||||
Array2D<half> lPixelsLeft;
|
||||
lPixelsLeft.resizeErase (pHeight, pWidth * lNbChannels);
|
||||
readPixels (pFilename, lNbChannels, lPixels, lPixelsLeft);
|
||||
validatePixels (pHeight, pWidth, lPixels, lNbChannels, false);
|
||||
validatePixels (pHeight, pWidth, lPixelsLeft, lNbChannels, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
readPixels (pFilename, lNbChannels, lPixels);
|
||||
validatePixels (pHeight, pWidth, lPixels, lNbChannels, false);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// confirm the optimization flag returns false for non-RGB files
|
||||
//
|
||||
void
|
||||
testNonOptimized (const std::string & tempDir)
|
||||
{
|
||||
const int pHeight = IMAGE_2K_HEIGHT - 1;
|
||||
const int pWidth = IMAGE_2K_WIDTH - 1;
|
||||
std::string fn = tempDir + RGB_FILENAME;
|
||||
const char* filename = fn.c_str();
|
||||
|
||||
remove(filename);
|
||||
writeFile (filename, pHeight, pWidth, IMAGE_TYPE_OTHER, false, NO_COMPRESSION);
|
||||
readValidateFile(filename,pHeight,pWidth,IMAGE_TYPE_OTHER,false);
|
||||
remove(filename);
|
||||
}
|
||||
|
||||
//
|
||||
// Test all combinations of file/framebuffer
|
||||
// RGB file to RGB framebuffer
|
||||
// RGB file to RGBA framebuffer
|
||||
// RGBA file to RGB framebuffer
|
||||
// RGBA file to RGBA framebuffer
|
||||
// Given a switch that determines whether the pixels will be SSE-aligned,
|
||||
// whether the file is mono or stereo, and the compression algorithm used
|
||||
// to write the file.
|
||||
//
|
||||
void
|
||||
testAllCombinations (bool isAligned,
|
||||
bool isStereo,
|
||||
Compression pCompression,
|
||||
const std::string & tempDir)
|
||||
{
|
||||
std::string pRgb = isStereo ? RGB_STEREO_FILENAME :
|
||||
RGB_FILENAME;
|
||||
pRgb = tempDir + pRgb;
|
||||
std::string pRgba = isStereo ? RGBA_STEREO_FILENAME :
|
||||
RGBA_FILENAME;
|
||||
pRgba = tempDir + pRgba;
|
||||
|
||||
const char * pRgbFilename = pRgb.c_str();
|
||||
const char * pRgbaFilename = pRgba.c_str();
|
||||
|
||||
const int pHeight = isAligned ? IMAGE_2K_HEIGHT : IMAGE_2K_HEIGHT - 1;
|
||||
const int pWidth = isAligned ? IMAGE_2K_WIDTH : IMAGE_2K_WIDTH - 1;
|
||||
|
||||
remove(pRgbFilename);
|
||||
remove(pRgbaFilename);
|
||||
|
||||
writeFile (pRgbFilename, pHeight, pWidth, IMAGE_TYPE_RGB, isStereo, pCompression);
|
||||
writeFile (pRgbaFilename, pHeight, pWidth, IMAGE_TYPE_RGBA, isStereo, pCompression);
|
||||
|
||||
cout << "\t\tRGB file to RGB framebuffer" << endl;
|
||||
readValidateFile (pRgbFilename, pHeight, pWidth, IMAGE_TYPE_RGB, isStereo);
|
||||
|
||||
|
||||
cout << "\t\tRGB file to RGB framebuffer" << endl;
|
||||
readValidateFile (pRgbFilename, pHeight, pWidth, IMAGE_TYPE_RGB, isStereo);
|
||||
|
||||
cout << "\t\tRGB file to RGBA framebuffer" << endl;
|
||||
readValidateFile (pRgbFilename, pHeight, pWidth, IMAGE_TYPE_RGBA, isStereo);
|
||||
|
||||
cout << "\t\tRGBA file to RGB framebuffer" << endl;
|
||||
readValidateFile (pRgbaFilename, pHeight, pWidth, IMAGE_TYPE_RGB, isStereo);
|
||||
|
||||
cout << "\t\tRGBA file to RGBA framebuffer" << endl;
|
||||
readValidateFile (pRgbaFilename, pHeight, pWidth, IMAGE_TYPE_RGBA, isStereo);
|
||||
|
||||
remove(pRgbFilename);
|
||||
remove(pRgbaFilename);
|
||||
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
void
|
||||
testOptimized (const std::string & tempDir)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Test all combinations
|
||||
// Aligned file with no compression
|
||||
// Unaligned file with no compression
|
||||
// Aligned file with zip compression
|
||||
// Unaligned file with zip compression
|
||||
//
|
||||
// Other algorithms are not necessary because we are not testing
|
||||
// compression but whetherthe optimized readPixels() code works
|
||||
// with a compressed file.
|
||||
// MONO
|
||||
cout << "\nTesting optimized code path for rgb(a) images-- "
|
||||
"2048x1152 (alignment respected) UNCOMPRESSED" << endl;
|
||||
|
||||
|
||||
cout << "\tNON-OPTIMIZABLE file" << endl;
|
||||
testNonOptimized(tempDir);
|
||||
|
||||
cout << "\tALIGNED -- MONO -- NO COMPRESSION" << endl;
|
||||
testAllCombinations (true, false, NO_COMPRESSION, tempDir);
|
||||
|
||||
cout << "\tUNALIGNED -- MONO -- NO COMPRESSION" << endl;
|
||||
testAllCombinations (false, false, NO_COMPRESSION, tempDir);
|
||||
|
||||
cout << "\tALIGNED -- MONO -- ZIP COMPRESSION" << endl;
|
||||
testAllCombinations (true, false, ZIP_COMPRESSION, tempDir);
|
||||
|
||||
cout << "\tUNALIGNED -- MONO -- ZIP COMPRESSION" << endl;
|
||||
testAllCombinations (false, false, ZIP_COMPRESSION, tempDir);
|
||||
|
||||
|
||||
//// STEREO
|
||||
cout << "\tALIGNED -- STEREO -- NO COMPRESSION" << endl;
|
||||
testAllCombinations (true, true, NO_COMPRESSION, tempDir);
|
||||
|
||||
cout << "\tUNALIGNED -- STEREO -- NO COMPRESSION" << endl;
|
||||
testAllCombinations (false, true, NO_COMPRESSION, tempDir);
|
||||
|
||||
cout << "\tALIGNED -- STEREO -- ZIP COMPRESSION" << endl;
|
||||
testAllCombinations (true, true, ZIP_COMPRESSION, tempDir);
|
||||
|
||||
cout << "\tUNALIGNED -- STEREO -- ZIP COMPRESSION" << endl;
|
||||
testAllCombinations (false, true, ZIP_COMPRESSION, tempDir);
|
||||
|
||||
cout << "RGB(A) files validation complete \n" << endl;
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
cerr << "ERROR -- caught exception: " << e.what() << endl;
|
||||
assert (false);
|
||||
}
|
||||
|
||||
}
|
||||
39
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testOptimized.h
Normal file
39
cs440-acg/ext/openexr/OpenEXR/IlmImfTest/testOptimized.h
Normal file
@@ -0,0 +1,39 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include <string>
|
||||
|
||||
void testOptimized (const std::string &tempDir);
|
||||
|
||||
@@ -0,0 +1,624 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2013, Weta Digital Ltd
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "ImfInputFile.h"
|
||||
#include <stdlib.h>
|
||||
#include <vector>
|
||||
#include "ImfChannelList.h"
|
||||
#include "ImfOutputFile.h"
|
||||
#include "ImfCompression.h"
|
||||
#include "ImfStandardAttributes.h"
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <assert.h>
|
||||
#include <IlmThread.h>
|
||||
#include <ImathBox.h>
|
||||
|
||||
#include "tmpDir.h"
|
||||
|
||||
namespace IMF = OPENEXR_IMF_NAMESPACE;
|
||||
using namespace IMF;
|
||||
using namespace std;
|
||||
using namespace IMATH_NAMESPACE;
|
||||
using namespace ILMTHREAD_NAMESPACE;
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
using OPENEXR_IMF_NAMESPACE::UINT;
|
||||
using OPENEXR_IMF_NAMESPACE::FLOAT;
|
||||
|
||||
std::string filename;
|
||||
|
||||
vector<char> writingBuffer; // buffer as file was written
|
||||
vector<char> readingBuffer; // buffer containing new image (and filled channels?)
|
||||
vector<char> preReadBuffer; // buffer as it was before reading - unread, unfilled channels should be unchanged
|
||||
|
||||
int gOptimisedReads = 0;
|
||||
int gSuccesses = 0;
|
||||
int gFailures = 0;
|
||||
|
||||
|
||||
//
|
||||
// @todo Needs a description of what this is used for.
|
||||
//
|
||||
//
|
||||
struct Schema
|
||||
{
|
||||
const char* _name; // name of this scheme
|
||||
const char* const* _active; // channels to be read
|
||||
const char* const * _passive; // channels to be ignored (keep in buffer passed to inputfile, should not be overwritten)
|
||||
int _banks;
|
||||
const char* const * _views; // list of views to write, or NULL
|
||||
const PixelType* _types; // NULL for all HALF, otherwise per-channel type
|
||||
|
||||
vector<string> views() const
|
||||
{
|
||||
const char * const* v = _views;
|
||||
vector<string> svec;
|
||||
while(*v!=NULL)
|
||||
{
|
||||
svec.push_back (*v);
|
||||
v++;
|
||||
}
|
||||
return svec;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const char * rgb[] = {"R","G","B",NULL};
|
||||
const char * rgba[] = {"R","G","B","A",NULL};
|
||||
const char * bgr[] = {"B","G","R",NULL};
|
||||
const char * abgr[] = {"A","B","G","R",NULL};
|
||||
const char * alpha[] = {"A",NULL};
|
||||
const char * redalpha[] = {"R","A",NULL};
|
||||
const char * rgbrightrgb[] = {"R","G","B","right.R","right.G","right.B",NULL};
|
||||
const char * rgbleftrgb[] = {"R","G","B","left.R","left.G","left.B",NULL};
|
||||
const char * rgbarightrgba[] = {"R","G","B","A","right.R","right.G","right.B","right.A",NULL};
|
||||
const char * rgbaleftrgba[] = {"R","G","B","A","left.R","left.G","left.B","left.A",NULL};
|
||||
const char * rgbrightrgba[] = {"R","G","B","right.R","right.G","right.B","right.A",NULL};
|
||||
const char * rgbleftrgba[] = {"R","G","B","left.R","left.G","left.B","left.A",NULL};
|
||||
const char * rgbarightrgb[] = {"R","G","B","A","right.R","right.G","right.B",NULL};
|
||||
const char * rgbaleftrgb[] = {"R","G","B","A","left.R","left.G","left.B",NULL};
|
||||
const char * rightrgba[] = {"right.R","right.G","right.B","right.A",NULL};
|
||||
const char * leftrgba[] = {"left.R","left.G","left.B","left.A",NULL};
|
||||
const char * rightrgb[] = {"right.R","right.G","right.B",NULL};
|
||||
const char * leftrgb[] = {"left.R","left.G","left.B",NULL};
|
||||
const char * threeview[] ={"R","G","B","A","left.R","left.G","left.B","left.A","right.R","right.G","right.B","right.A",NULL};
|
||||
const char * trees[] = {"rimu","pohutukawa","manuka","kauri",NULL};
|
||||
const char * treesandbirds[]= {"kiwi","rimu","pohutukawa","kakapu","kauri","manuka","moa","fantail",NULL};
|
||||
|
||||
const char * lefthero[] = {"left","right",NULL};
|
||||
const char * righthero[] = {"right","left",NULL};
|
||||
const char * centrehero[] = {"centre","left","right",NULL};
|
||||
|
||||
const PixelType four_floats[] = {IMF::FLOAT,IMF::FLOAT,IMF::FLOAT,IMF::FLOAT};
|
||||
const PixelType hhhfff[] = {IMF::HALF,IMF::HALF,IMF::HALF,IMF::FLOAT,IMF::FLOAT,IMF::FLOAT};
|
||||
const PixelType hhhhffff[] = {IMF::HALF,IMF::HALF,IMF::HALF,IMF::HALF,IMF::FLOAT,IMF::FLOAT,IMF::FLOAT,IMF::FLOAT};
|
||||
|
||||
Schema Schemes[] =
|
||||
{
|
||||
{"RGBHalf" ,rgb ,NULL ,1 ,NULL ,NULL },
|
||||
{"RGBAHalf" ,rgba ,NULL ,1 ,NULL ,NULL },
|
||||
{"ABGRHalf" ,abgr ,NULL ,1 ,NULL ,NULL },
|
||||
{"RGBFloat" ,rgb ,NULL ,1 ,NULL ,four_floats},
|
||||
{"BGRHalf" ,bgr ,NULL ,1 ,NULL ,NULL },
|
||||
{"RGBLeftRGB" ,rgbleftrgb ,NULL ,1 ,righthero ,NULL },
|
||||
{"RGBRightRGB" ,rgbrightrgb ,NULL ,1 ,lefthero ,NULL },
|
||||
{"RGBALeftRGBA" ,rgbaleftrgba ,NULL ,1 ,righthero ,NULL },
|
||||
{"RGBARightRGBA" ,rgbarightrgba ,NULL ,1 ,lefthero ,NULL },
|
||||
{"LeftRGB" ,leftrgb ,NULL ,1 ,NULL ,NULL },
|
||||
{"RightRGB" ,rightrgb ,NULL ,1 ,NULL ,NULL },
|
||||
{"LeftRGBA" ,leftrgba ,NULL ,1 ,NULL ,NULL },
|
||||
{"RightRGBA" ,rightrgba ,NULL ,1 ,NULL ,NULL },
|
||||
{"TripleView" ,threeview ,NULL ,1 ,centrehero ,NULL },
|
||||
{"Trees" ,trees ,NULL ,1 ,NULL ,NULL },
|
||||
{"TreesAndBirds" ,treesandbirds ,NULL ,1 ,NULL ,NULL },
|
||||
{"RGBLeftRGBA" ,rgbleftrgba ,NULL ,1 ,righthero ,NULL },
|
||||
{"RGBRightRGBA" ,rgbrightrgba ,NULL ,1 ,lefthero ,NULL },
|
||||
{"RGBALeftRGB" ,rgbaleftrgb ,NULL ,1 ,righthero ,NULL },
|
||||
{"RGBARightRGB" ,rgbarightrgb ,NULL ,1 ,lefthero ,NULL },
|
||||
{"TwinRGBLeftRGB" ,rgbleftrgb ,NULL ,2 ,righthero ,NULL },
|
||||
{"TwinRGBRightRGB" ,rgbrightrgb ,NULL ,2 ,lefthero ,NULL },
|
||||
{"TwinRGBALeftRGBA" ,rgbaleftrgba ,NULL ,2 ,righthero ,NULL },
|
||||
{"TwinRGBARightRGBA" ,rgbarightrgba ,NULL , 2 ,lefthero ,NULL },
|
||||
{"TripleTripleView" ,threeview ,NULL ,3 ,centrehero ,NULL },
|
||||
{"Alpha" ,alpha ,NULL ,1 ,NULL ,NULL },
|
||||
{"RedAlpha" ,redalpha ,NULL ,1 ,NULL ,NULL },
|
||||
{"RG+BA" ,rgba ,NULL ,2 ,NULL ,NULL },//interleave only RG, then BA
|
||||
{"RGBpassiveA" ,rgb ,alpha ,1 ,NULL ,NULL },//interleave only RG, then BA
|
||||
{"RGBpassiveleftRGB" ,rgb ,leftrgb ,1 ,NULL ,NULL },
|
||||
{"RGBFloatA" ,rgba ,NULL ,1 ,NULL ,hhhfff },
|
||||
{"RGBFloatLeftRGB" ,rgbleftrgb ,NULL ,1 ,righthero ,hhhfff },
|
||||
{"RGBAFloatLeftRGBA" ,rgbaleftrgba ,NULL ,1 ,righthero ,hhhhffff },
|
||||
{"RGBApassiverightRGBA" ,rgba ,rightrgba ,1 ,NULL ,NULL },
|
||||
{"BanksOfTreesAndBirds" ,treesandbirds ,NULL ,2 ,NULL ,NULL },
|
||||
{NULL,NULL,NULL,0,NULL,NULL}
|
||||
};
|
||||
|
||||
|
||||
|
||||
bool compare(const FrameBuffer& asRead,
|
||||
const FrameBuffer& asWritten,
|
||||
const Box2i& dataWindow,
|
||||
bool nonfatal
|
||||
)
|
||||
{
|
||||
for (FrameBuffer::ConstIterator i =asRead.begin();i!=asRead.end();i++)
|
||||
{
|
||||
FrameBuffer::ConstIterator p = asWritten.find(i.name());
|
||||
for (int y=dataWindow.min.y; y<= dataWindow.max.y; y++)
|
||||
{
|
||||
for (int x = dataWindow.min.x; x <= dataWindow.max.x; x++)
|
||||
|
||||
{
|
||||
char * ptr = (i.slice().base+i.slice().yStride*y +i.slice().xStride*x);
|
||||
half readHalf;
|
||||
switch (i.slice().type)
|
||||
{
|
||||
case IMF::FLOAT :
|
||||
readHalf = half(*(float*) ptr);
|
||||
break;
|
||||
case IMF::HALF :
|
||||
readHalf = half(*(half*) ptr);
|
||||
break;
|
||||
case IMF::UINT :
|
||||
continue; // can't very well check this
|
||||
default :
|
||||
cout << "don't know about that\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
half writtenHalf;
|
||||
|
||||
if (p!=asWritten.end())
|
||||
{
|
||||
char * ptr = p.slice().base+p.slice().yStride*y +
|
||||
p.slice().xStride*x;
|
||||
switch (p.slice().type)
|
||||
{
|
||||
case IMF::FLOAT :
|
||||
writtenHalf = half(*(float*) ptr);
|
||||
break;
|
||||
case IMF::HALF :
|
||||
writtenHalf = half(*(half*) ptr);
|
||||
break;
|
||||
case IMF::UINT :
|
||||
continue;
|
||||
default :
|
||||
cout << "don't know about that\n";
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
writtenHalf=half(i.slice().fillValue);
|
||||
}
|
||||
|
||||
if (writtenHalf.bits()!=readHalf.bits())
|
||||
{
|
||||
if (nonfatal)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
cout << "\n\nerror reading back channel " << i.name() << " pixel " << x << ',' << y << " got " << readHalf << " expected " << writtenHalf << endl;
|
||||
assert(writtenHalf.bits()==readHalf.bits());
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// allocate readingBuffer or writingBuffer, setting up a framebuffer to point to the right thing
|
||||
//
|
||||
ChannelList
|
||||
setupBuffer (const Header& hdr, // header to grab datawindow from
|
||||
const char * const *channels, // NULL terminated list of channels to write
|
||||
const char * const *passivechannels, // NULL terminated list of channels to write
|
||||
const PixelType* pt, // type of each channel, or NULL for all HALF
|
||||
FrameBuffer& buf, // buffer to fill with pointers to channel
|
||||
FrameBuffer& prereadbuf, // channels which aren't being read - indexes into the preread buffer
|
||||
FrameBuffer& postreadbuf, // channels which aren't being read - indexes into the postread buffer
|
||||
int banks, // number of banks - channels within each bank are interleaved, banks are scanline interleaved
|
||||
bool writing // true if should allocate
|
||||
)
|
||||
{
|
||||
Box2i dw = hdr.dataWindow();
|
||||
|
||||
//
|
||||
// how many channels in total
|
||||
//
|
||||
int activechans = 0;
|
||||
int bytes_per_pixel =0;
|
||||
|
||||
while (channels[activechans]!=NULL)
|
||||
{
|
||||
if (pt==NULL)
|
||||
{
|
||||
bytes_per_pixel+=2;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (pt[activechans])
|
||||
{
|
||||
case IMF::HALF : bytes_per_pixel+=2;break;
|
||||
case IMF::FLOAT : case IMF::UINT : bytes_per_pixel+=4;break;
|
||||
default :
|
||||
cout << "Unexpected PixelType?\n";
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
activechans++;
|
||||
}
|
||||
|
||||
|
||||
int passivechans=0;
|
||||
while (passivechannels!=NULL && passivechannels[passivechans]!=NULL)
|
||||
{
|
||||
if (pt==NULL)
|
||||
{
|
||||
bytes_per_pixel+=2;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (pt[passivechans+activechans])
|
||||
{
|
||||
case IMF::HALF : bytes_per_pixel+=2;break;
|
||||
case IMF::FLOAT : case IMF::UINT : bytes_per_pixel+=4;break;
|
||||
default :
|
||||
cout << "Unexpected PixelType?\n";
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
passivechans++;
|
||||
}
|
||||
|
||||
int chans = activechans+passivechans;
|
||||
|
||||
|
||||
int bytes_per_bank = bytes_per_pixel/banks;
|
||||
|
||||
int samples = (hdr.dataWindow().max.x+1-hdr.dataWindow().min.x)*
|
||||
(hdr.dataWindow().max.y+1-hdr.dataWindow().min.y)*chans;
|
||||
|
||||
int size = samples*bytes_per_pixel;
|
||||
|
||||
|
||||
if (writing)
|
||||
{
|
||||
writingBuffer.resize(size);
|
||||
}
|
||||
else
|
||||
{
|
||||
readingBuffer.resize(size);
|
||||
}
|
||||
|
||||
const char * write_ptr = writing ? &writingBuffer[0] : &readingBuffer[0];
|
||||
// fill with random halfs, casting to floats for float channels
|
||||
int chan=0;
|
||||
for (int i=0;i<samples;i++)
|
||||
{
|
||||
unsigned short int values = (unsigned short int) floor((double(rand())/double(RAND_MAX))*65535.0);
|
||||
half v;
|
||||
v.setBits(values);
|
||||
if (pt==NULL || pt[chan]==IMF::HALF)
|
||||
{
|
||||
*(half*)write_ptr = half(v);
|
||||
write_ptr+=2;
|
||||
}
|
||||
else
|
||||
{
|
||||
*(float*)write_ptr = float(v);
|
||||
write_ptr+=4;
|
||||
}
|
||||
chan++;
|
||||
if (chan==chans)
|
||||
{
|
||||
chan=0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!writing)
|
||||
{
|
||||
//take a copy of the buffer as it was before being read
|
||||
preReadBuffer = readingBuffer;
|
||||
}
|
||||
|
||||
char* offset=NULL;
|
||||
|
||||
ChannelList chanlist;
|
||||
|
||||
int bytes_per_row = bytes_per_pixel*(dw.max.x+1-dw.min.x);
|
||||
int bytes_per_bank_row = bytes_per_row/banks;
|
||||
|
||||
int first_pixel_index = bytes_per_row*dw.min.y+bytes_per_bank*dw.min.x;
|
||||
|
||||
for (int i=0;i<chans;i++)
|
||||
{
|
||||
PixelType type = pt==NULL ? IMF::HALF : pt[i];
|
||||
if (i<activechans && writing)
|
||||
{
|
||||
chanlist.insert(channels[i],type);
|
||||
}
|
||||
|
||||
|
||||
if (i % (chans/banks) ==0)
|
||||
{
|
||||
//
|
||||
// set offset pointer to beginning of bank
|
||||
//
|
||||
|
||||
int bank = i / (chans/banks);
|
||||
offset = (writing ? &writingBuffer[0] :
|
||||
&readingBuffer[0]) + bank*bytes_per_bank_row - first_pixel_index;
|
||||
}
|
||||
|
||||
if (i<activechans)
|
||||
{
|
||||
|
||||
buf.insert (channels[i],
|
||||
Slice (type,
|
||||
offset,
|
||||
bytes_per_bank,
|
||||
bytes_per_row,
|
||||
1,1,100+i));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!writing)
|
||||
{
|
||||
|
||||
postreadbuf.insert (passivechannels[i-activechans],
|
||||
Slice (type,
|
||||
offset,
|
||||
bytes_per_bank,
|
||||
bytes_per_row,
|
||||
1,1,0.4));
|
||||
|
||||
char * pre_offset = offset-&readingBuffer[0]+&preReadBuffer[0];
|
||||
prereadbuf.insert (passivechannels[i-activechans],
|
||||
Slice (type,
|
||||
pre_offset,
|
||||
bytes_per_bank,
|
||||
bytes_per_row,
|
||||
1,1,0.4));
|
||||
}
|
||||
}
|
||||
switch (type)
|
||||
{
|
||||
case IMF::HALF :
|
||||
offset+=2;
|
||||
break;
|
||||
case IMF::FLOAT :
|
||||
offset+=4;
|
||||
break;
|
||||
default :
|
||||
cout << "Unexpected Pixel Type\n";
|
||||
exit(1);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return chanlist;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Box2i writefile(Schema & scheme,FrameBuffer& buf,bool tiny)
|
||||
{
|
||||
const int height = 128;
|
||||
const int width = 128;
|
||||
|
||||
Header hdr(width,height,1);
|
||||
|
||||
|
||||
//min values in range (-100,100)
|
||||
hdr.dataWindow().min.x = int(200.0*double(rand())/double(RAND_MAX)-100.0);
|
||||
hdr.dataWindow().min.y = int(200.0*double(rand())/double(RAND_MAX)-100.0);
|
||||
|
||||
|
||||
// in tiny mode, make image up to 14*14 pixels (less than two SSE instructions)
|
||||
if (tiny)
|
||||
{
|
||||
hdr.dataWindow().max.x = hdr.dataWindow().min.x + 1+int(13*double(rand())/double(RAND_MAX));
|
||||
hdr.dataWindow().max.y = hdr.dataWindow().min.y + 1+int(13*double(rand())/double(RAND_MAX));
|
||||
}
|
||||
else
|
||||
{
|
||||
// in normal mode, make chunky images
|
||||
hdr.dataWindow().max.x = hdr.dataWindow().min.x + 64+int(400*double(rand())/double(RAND_MAX));
|
||||
hdr.dataWindow().max.y = hdr.dataWindow().min.y + 64+int(400*double(rand())/double(RAND_MAX));
|
||||
}
|
||||
|
||||
hdr.compression()=ZIPS_COMPRESSION;
|
||||
|
||||
FrameBuffer dummy1,dummy2;
|
||||
|
||||
hdr.channels() = setupBuffer (hdr,
|
||||
scheme._active,
|
||||
scheme._passive,
|
||||
scheme._types,
|
||||
buf,
|
||||
dummy1,
|
||||
dummy2,
|
||||
scheme._banks,
|
||||
true);
|
||||
|
||||
if (scheme._views)
|
||||
{
|
||||
addMultiView(hdr,scheme.views());
|
||||
}
|
||||
|
||||
remove (filename.c_str());
|
||||
OutputFile f(filename.c_str(), hdr);
|
||||
f.setFrameBuffer(buf);
|
||||
f.writePixels(hdr.dataWindow().max.y-hdr.dataWindow().min.y+1);
|
||||
|
||||
return hdr.dataWindow();
|
||||
}
|
||||
|
||||
bool
|
||||
readfile (Schema scheme,
|
||||
FrameBuffer & buf, ///< list of channels to read: index to readingBuffer
|
||||
FrameBuffer & preread, ///< list of channels to skip: index to preReadBuffer
|
||||
FrameBuffer & postread) ///< list of channels to skip: index to readingBuffer)
|
||||
{
|
||||
InputFile infile (filename.c_str());
|
||||
setupBuffer(infile.header(),
|
||||
scheme._active,
|
||||
scheme._passive,
|
||||
scheme._types,
|
||||
buf,
|
||||
preread,
|
||||
postread,
|
||||
scheme._banks,false);
|
||||
infile.setFrameBuffer(buf);
|
||||
|
||||
cout.flush();
|
||||
infile.readPixels (infile.header().dataWindow().min.y,
|
||||
infile.header().dataWindow().max.y);
|
||||
|
||||
return infile.isOptimizationEnabled();
|
||||
}
|
||||
|
||||
void
|
||||
test (Schema writeScheme, Schema readScheme, bool nonfatal, bool tiny)
|
||||
{
|
||||
ostringstream q;
|
||||
q << writeScheme._name << " read as " << readScheme._name << "...";
|
||||
cout << left << setw(53) << q.str();
|
||||
|
||||
FrameBuffer writeFrameBuf;
|
||||
Box2i dw = writefile(writeScheme,writeFrameBuf,tiny);
|
||||
FrameBuffer readFrameBuf;
|
||||
FrameBuffer preReadFrameBuf;
|
||||
FrameBuffer postReadFrameBuf;
|
||||
cout.flush();
|
||||
bool opt = readfile (readScheme,
|
||||
readFrameBuf,
|
||||
preReadFrameBuf,
|
||||
postReadFrameBuf);
|
||||
if (compare(readFrameBuf, writeFrameBuf, dw, nonfatal) &&
|
||||
compare(preReadFrameBuf, postReadFrameBuf, dw, nonfatal)
|
||||
)
|
||||
{
|
||||
cout << " OK ";
|
||||
if (opt)
|
||||
{
|
||||
cout << "OPTIMISED ";
|
||||
gOptimisedReads++;
|
||||
}
|
||||
cout << "\n";
|
||||
gSuccesses++;
|
||||
}
|
||||
else
|
||||
{
|
||||
cout << " FAIL" << endl;
|
||||
gFailures++;
|
||||
}
|
||||
remove (filename.c_str());
|
||||
}
|
||||
|
||||
|
||||
void runtests(bool nonfatal,bool tiny)
|
||||
{
|
||||
srand(1);
|
||||
int i=0;
|
||||
int skipped=0;
|
||||
|
||||
gFailures=0;
|
||||
gSuccesses=0;
|
||||
gOptimisedReads=0;
|
||||
|
||||
|
||||
while(Schemes[i]._name!=NULL)
|
||||
{
|
||||
int j=0;
|
||||
while(Schemes[j]._name!=NULL)
|
||||
{
|
||||
cout << right << setw(2) << i << ',' << right << setw(2) << j << ": ";
|
||||
cout.flush();
|
||||
|
||||
if (nonfatal)
|
||||
{
|
||||
cout << " skipping " << Schemes[i]._name << ',' << Schemes[j]._name << ": known to crash\n";
|
||||
skipped++;
|
||||
}
|
||||
else
|
||||
{
|
||||
test(Schemes[i],Schemes[j],nonfatal,tiny);
|
||||
}
|
||||
j++;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
cout << gFailures << '/' << (gSuccesses+gFailures) << " runs failed\n";
|
||||
cout << skipped << " tests skipped (assumed to be bad)\n";
|
||||
cout << gOptimisedReads << '/' << gSuccesses << " optimised\n";
|
||||
|
||||
if (gFailures>0 )
|
||||
{
|
||||
cout << " TESTS FAILED\n";
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace anon
|
||||
|
||||
|
||||
void
|
||||
testOptimizedInterleavePatterns (const std::string & tempDir)
|
||||
{
|
||||
filename = tempDir + "imf_test_interleave_patterns.exr";
|
||||
|
||||
|
||||
cout << "Testing SSE optimisation with different interleave patterns (large images) ... " << endl;
|
||||
runtests (false,false);
|
||||
|
||||
cout << "Testing SSE optimisation with different interleave patterns (tiny images) ... " << endl;
|
||||
runtests (false,true);
|
||||
|
||||
cout << "ok\n" << endl;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2013, Weta Digital Ltd
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _TEST_OPTIMIZED_INTERLEAVE_PATTERNS_
|
||||
#define _TEST_OPTIMIZED_INTERLEAVE_PATTERNS_
|
||||
|
||||
void testOptimizedInterleavePatterns (const std::string &tempDir);
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user