// // SPDX-License-Identifier: BSD-3-Clause // Copyright (c) Contributors to the OpenEXR Project. // //----------------------------------------------------------------------------- // // Code examples that show how class DeepTiledInputFile and // class DeepTiledOutputFile can be used to read and write // OpenEXR image files with 16-bit floating-point green, // and 32-bit floating point depth channels. // //----------------------------------------------------------------------------- #include #include #include #include #include #include #include #include "drawImage.h" #include "namespaceAlias.h" using namespace IMF; using namespace std; using namespace IMATH_NAMESPACE; // defined in deepExamples.cpp extern Array2D testDataZ; extern Array2D testDataA; extern unsigned int getPixelSampleCount (int i, int j); extern void getPixelSampleData( int i, int j, Array2D& dataZ, Array2D& dataA); void readDeepTiledFile ( const char filename[], Box2i& displayWindow, Box2i& dataWindow, Array2D& dataZ, Array2D& dataA, Array2D& sampleCount) { // // Read a deep image using class DeepTiledInputFile. Try to read one // channel, A, of type HALF, and one channel, Z, // of type FLOAT. Store the A, and Z pixels in two // separate memory buffers. // // - open the file // - allocate memory for the pixels // - describe the layout of the A, and Z pixel buffers // - read the sample counts from the file // - allocate the memory requred to store the samples // - read the pixels from the file // DeepTiledInputFile file (filename); int width = dataWindow.max.x - dataWindow.min.x + 1; int height = dataWindow.max.y - dataWindow.min.y + 1; sampleCount.resizeErase (height, width); dataZ.resizeErase (height, width); dataA.resizeErase (height, width); DeepFrameBuffer frameBuffer; frameBuffer.insertSampleCountSlice (Slice ( UINT, (char*) (&sampleCount[0][0] - dataWindow.min.x - dataWindow.min.y * width), sizeof (unsigned int) * 1, // xStride sizeof (unsigned int) * width)); // yStride frameBuffer.insert ( "Z", DeepSlice ( FLOAT, (char*) (&dataZ[0][0] - dataWindow.min.x - dataWindow.min.y * width), sizeof (float*) * 1, // xStride for pointer array sizeof (float*) * width, // yStride for pointer array sizeof (float) * 1)); // stride for samples frameBuffer.insert ( "A", DeepSlice ( HALF, (char*) (&dataA[0][0] - dataWindow.min.x - dataWindow.min.y * width), sizeof (half*) * 1, // xStride for pointer array sizeof (half*) * width, // yStride for pointer array sizeof (half) * 1)); // stride for samples file.setFrameBuffer (frameBuffer); int numXTiles = file.numXTiles (0); int numYTiles = file.numYTiles (0); file.readPixelSampleCounts (0, numXTiles - 1, 0, numYTiles - 1); for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { dataZ[i][j] = new float[sampleCount[i][j]]; dataA[i][j] = new half[sampleCount[i][j]]; } } file.readTiles (0, numXTiles - 1, 0, numYTiles - 1); // (after read data is processed, data must be freed:) for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { delete[] dataZ[i][j]; delete[] dataA[i][j]; } } } void getSampleDataForTile ( int i, int j, int tileSizeX, int tileSizeY, Array2D& sampleCount, Array2D& dataZ, Array2D& dataA) { for (int k = 0; k < tileSizeY; k++) { int y = j * tileSizeY + k; if (y >= sampleCount.height()) break; for (int l = 0; l < tileSizeX; l++) { int x = i * tileSizeX + l; if (x >= sampleCount.width()) break; sampleCount[y][x] = getPixelSampleCount(y, x); dataZ[y][x] = new float[sampleCount[y][x]]; dataA[y][x] = new half [sampleCount[y][x]]; getPixelSampleData(y, x, dataZ, dataA); } } } void writeDeepTiledFile ( const char filename[], Box2i displayWindow, Box2i dataWindow, int tileSizeX, int tileSizeY) { // // Write a deep image with only a A (alpha) and a Z (depth) channel, // using class DeepTiledOutputFile. // // - create a file header // - add A and Z channels to the header // - open the file, and store the header in the file // - describe the memory layout of the A and Z pixels // - store the pixels in the file // int height = dataWindow.max.y - dataWindow.min.y + 1; int width = dataWindow.max.x - dataWindow.min.x + 1; Header header (displayWindow, dataWindow); header.channels ().insert ("Z", Channel (FLOAT)); header.channels ().insert ("A", Channel (HALF)); header.setType (DEEPTILE); header.compression () = ZIPS_COMPRESSION; header.setTileDescription ( TileDescription (tileSizeX, tileSizeY, ONE_LEVEL)); Array2D dataZ; dataZ.resizeErase (height, width); Array2D dataA; dataA.resizeErase (height, width); Array2D sampleCount; sampleCount.resizeErase (height, width); DeepTiledOutputFile file (filename, header); DeepFrameBuffer frameBuffer; frameBuffer.insertSampleCountSlice (Slice ( UINT, (char*) (&sampleCount[0][0] - dataWindow.min.x - dataWindow.min.y * width), sizeof (unsigned int) * 1, // xStride sizeof (unsigned int) * width)); // yStride frameBuffer.insert ( "Z", DeepSlice ( FLOAT, (char*) (&dataZ[0][0] - dataWindow.min.x - dataWindow.min.y * width), sizeof (float*) * 1, // xStride for pointer array sizeof (float*) * width, // yStride for pointer array sizeof (float) * 1)); // stride for samples frameBuffer.insert ( "A", DeepSlice ( HALF, (char*) (&dataA[0][0] - dataWindow.min.x - dataWindow.min.y * width), sizeof (half*) * 1, // xStride for pointer array sizeof (half*) * width, // yStride for pointer array sizeof (half) * 1)); // stride for samples file.setFrameBuffer (frameBuffer); for (int j = 0; j < file.numYTiles (0); j++) { for (int i = 0; i < file.numXTiles (0); i++) { // Generate data for sampleCount, dataZ and dataA. getSampleDataForTile (i, j, tileSizeX, tileSizeY, sampleCount, dataZ, dataA); file.writeTile (i, j, 0); } } for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { delete[] dataZ[i][j]; delete[] dataA[i][j]; } } } void deepTiledExamples() { int w = 800; int h = 600; int tileSizeX = 64; int tileSizeY = 64; Box2i window; window.min.setValue(0, 0); window.max.setValue(w - 1, h - 1); Array2D dataZ; dataZ.resizeErase(h, w); Array2D dataA; dataA.resizeErase(h, w); Array2D sampleCount; sampleCount.resizeErase(h, w); // Create an image to be used as a source for deep data testDataA.resizeErase(h, w); testDataZ.resizeErase(h, w); drawImage2(testDataA, testDataZ, w, h); writeDeepTiledFile("testTiled.deep.exr", window, window, tileSizeX, tileSizeY); readDeepTiledFile ("testTiled.deep.exr", window, window, dataZ, dataA, sampleCount); }