// note that this is not a standalone header, it is supposed
// to be included only in Main.cpp, from a specific place

#include <ImfRgbaFile.h>
#include <ImfTiledRgbaFile.h>
#include <ImfStandardAttributes.h>
#include <Iex.h>

using namespace Imf;
using namespace Imath;

#if defined(_MSC_VER) && !defined(__MWERKS__)
#pragma comment(lib, "Iex.lib")
#pragma comment(lib, "Half.lib")
#pragma comment(lib, "IlmImf.lib")
#pragma comment(lib, "IlmThread.lib")
#pragma comment(lib, "Imath.lib")
#pragma comment(lib, "zlibwapi.lib")
#endif // _MSC_VER) && !__MWERKS__

void EXRTest()
{
	Compression compression = RLE_COMPRESSION;
    LevelMode levelMode = ONE_LEVEL;
    LevelRoundingMode roundingMode = ROUND_DOWN;
	const char *outFileName = "test.exr";

	TBmp *p_image = CJpegCodec::p_Load_JPEG("test.jpg");
	int mapWidth = p_image->n_width;
	int mapHeight = p_image->n_height;
	std::vector<Rgba> pixels(mapWidth * mapHeight);
	for(int i = 0, n = pixels.size(); i < n; ++ i) {
		float r = uint8_t(p_image->p_buffer[i] >> 16) / 255.0f;
		float g = uint8_t(p_image->p_buffer[i] >> 8) / 255.0f;
		float b = uint8_t(p_image->p_buffer[i]) / 255.0f;
		pixels[i] = Rgba(r, g, b);
	}

	int tileWidth = 256, tileHeight = 256; // or less?
    try	{
        RgbaChannels channels = WRITE_RGB;

        Header header;
		header.dataWindow() = Box2i (V2i (0, 0), V2i (mapWidth - 1, mapHeight - 1));
		header.displayWindow() = header.dataWindow();
		header.compression() = compression;
		addEnvmap(header, ENVMAP_LATLONG);

		TiledRgbaOutputFile out(outFileName, header, channels,
			tileWidth, tileHeight, levelMode, roundingMode);
		int level = 0;
		Box2i dw = out.dataWindowForLevel(level);
		out.setFrameBuffer(&pixels[0], 1, mapWidth);
		for(int tileY = 0; tileY < out.numYTiles(level); ++ tileY) {
			for(int tileX = 0; tileX < out.numXTiles(level); ++ tileX)
				out.writeTile(tileX, tileY, level);
		}
	} catch(std::exception &e) {
		fprintf(stderr, "error: uncaught exception: %s\n", e.what());
    }
}

void EXRWrite(const char *outFileName, int mapWidth, int mapHeight, const float *p_rgb_pixels)
{
	Compression compression = RLE_COMPRESSION;
    LevelMode levelMode = ONE_LEVEL;
    LevelRoundingMode roundingMode = ROUND_DOWN;

	std::vector<Rgba> pixels(mapWidth * mapHeight);
	for(int i = 0, n = pixels.size(); i < n; ++ i) {
		float r = p_rgb_pixels[3 * i + 0];
		float g = p_rgb_pixels[3 * i + 1];
		float b = p_rgb_pixels[3 * i + 2];
		pixels[i] = Rgba(r, g, b);
	}
	// convert to half

	int tileWidth = 256, tileHeight = 256; // or less?
    try	{
        RgbaChannels channels = WRITE_RGB;

        Header header;
		header.dataWindow() = Box2i(V2i(0, 0), V2i(mapWidth - 1, mapHeight - 1));
		header.displayWindow() = header.dataWindow();
		header.compression() = compression;
		addEnvmap(header, ENVMAP_LATLONG);

		TiledRgbaOutputFile out(outFileName, header, channels,
			tileWidth, tileHeight, levelMode, roundingMode);
		int level = 0;
		Box2i dw = out.dataWindowForLevel(level);
		out.setFrameBuffer(&pixels[0], 1, mapWidth);
		for(int tileY = 0; tileY < out.numYTiles(level); ++ tileY) {
			for(int tileX = 0; tileX < out.numXTiles(level); ++ tileX)
				out.writeTile(tileX, tileY, level);
		}
	} catch(std::exception &e) {
		fprintf(stderr, "error: uncaught exception: %s\n", e.what());
    }
}
