1/*
2 * Copyright 2008, Jérôme Duval. All rights reserved.
3 * Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
4 *   Digital Ltd. LLC
5 * Distributed under the terms of the MIT License.
6 */
7
8#include <Catalog.h>
9
10#include "ConfigView.h"
11#include "EXRGamma.h"
12#include "EXRTranslator.h"
13#include "ImfArray.h"
14#undef min
15#undef max
16#include "ImfRgbaFile.h"
17#include "IStreamWrapper.h"
18
19#undef B_TRANSLATION_CONTEXT
20#define B_TRANSLATION_CONTEXT "EXRTranslator"
21
22
23// The input formats that this translator supports.
24static const translation_format sInputFormats[] = {
25	{
26		EXR_IMAGE_FORMAT,
27		B_TRANSLATOR_BITMAP,
28		EXR_IN_QUALITY,
29		EXR_IN_CAPABILITY,
30		"image/exr",
31		"EXR"
32	},
33};
34
35// The output formats that this translator supports.
36static const translation_format sOutputFormats[] = {
37	{
38		B_TRANSLATOR_BITMAP,
39		B_TRANSLATOR_BITMAP,
40		BITS_OUT_QUALITY,
41		BITS_OUT_CAPABILITY,
42		"image/x-be-bitmap",
43		"Be Bitmap Format (EXRTranslator)"
44	},
45};
46
47// Default settings for the Translator
48static const TranSetting sDefaultSettings[] = {
49	{B_TRANSLATOR_EXT_HEADER_ONLY, TRAN_SETTING_BOOL, false},
50	{B_TRANSLATOR_EXT_DATA_ONLY, TRAN_SETTING_BOOL, false}
51};
52
53const uint32 kNumInputFormats = sizeof(sInputFormats) / sizeof(translation_format);
54const uint32 kNumOutputFormats = sizeof(sOutputFormats) / sizeof(translation_format);
55const uint32 kNumDefaultSettings = sizeof(sDefaultSettings) / sizeof(TranSetting);
56
57
58
59
60//	#pragma mark -
61
62
63EXRTranslator::EXRTranslator()
64	: BaseTranslator(B_TRANSLATE("EXR images"),
65		B_TRANSLATE("EXR image translator"),
66		EXR_TRANSLATOR_VERSION,
67		sInputFormats, kNumInputFormats,
68		sOutputFormats, kNumOutputFormats,
69		"EXRTranslator_Settings",
70		sDefaultSettings, kNumDefaultSettings,
71		B_TRANSLATOR_BITMAP, EXR_IMAGE_FORMAT)
72{
73}
74
75
76EXRTranslator::~EXRTranslator()
77{
78}
79
80
81status_t
82EXRTranslator::DerivedIdentify(BPositionIO *stream,
83	const translation_format *format, BMessage *settings,
84	translator_info *outInfo, uint32 outType)
85{
86	if (!outType)
87		outType = B_TRANSLATOR_BITMAP;
88	if (outType != B_TRANSLATOR_BITMAP)
89		return B_NO_TRANSLATOR;
90
91	try {
92		IStreamWrapper istream("filename", stream);
93		RgbaInputFile inputFile(istream);
94
95		if (outInfo) {
96			outInfo->type = EXR_IMAGE_FORMAT;
97			outInfo->group = B_TRANSLATOR_BITMAP;
98			outInfo->quality = EXR_IN_QUALITY;
99			outInfo->capability = EXR_IN_CAPABILITY;
100			strcpy(outInfo->MIME, "image/exr");
101			strlcpy(outInfo->name, B_TRANSLATE("EXR image"),
102				sizeof(outInfo->name));
103		}
104	} catch (...) {
105		return B_NO_TRANSLATOR;
106	}
107
108	return B_OK;
109}
110
111
112status_t
113EXRTranslator::DerivedTranslate(BPositionIO* source,
114	const translator_info* info, BMessage* settings,
115	uint32 outType, BPositionIO* target, int32 baseType)
116{
117	if (!outType)
118		outType = B_TRANSLATOR_BITMAP;
119	if (outType != B_TRANSLATOR_BITMAP || baseType != 0)
120		return B_NO_TRANSLATOR;
121
122	status_t err = B_NO_TRANSLATOR;
123	try {
124		IStreamWrapper istream("filename", source);
125		RgbaInputFile in(istream);
126
127		//Imath::Box2i dw = in.dataWindow();
128		const Imath::Box2i &displayWindow = in.displayWindow();
129		const Imath::Box2i &dataWindow = in.dataWindow();
130		//float a = in.pixelAspectRatio(); // TODO take into account the aspect ratio
131		int dataWidth = dataWindow.max.x - dataWindow.min.x + 1;
132		int dataHeight = dataWindow.max.y - dataWindow.min.y + 1;
133		int displayWidth = displayWindow.max.x - displayWindow.min.x + 1;
134		int displayHeight = displayWindow.max.y - displayWindow.min.y + 1;
135
136		// Write out the data to outDestination
137		// Construct and write Be bitmap header
138		TranslatorBitmap bitsHeader;
139		bitsHeader.magic = B_TRANSLATOR_BITMAP;
140		bitsHeader.bounds.left = 0;
141		bitsHeader.bounds.top = 0;
142		bitsHeader.bounds.right = displayWidth - 1;
143		bitsHeader.bounds.bottom = displayHeight - 1;
144		bitsHeader.rowBytes = 4 * displayWidth;
145		bitsHeader.colors = B_RGBA32;
146		bitsHeader.dataSize = bitsHeader.rowBytes * displayHeight;
147		if (swap_data(B_UINT32_TYPE, &bitsHeader,
148			sizeof(TranslatorBitmap), B_SWAP_HOST_TO_BENDIAN) != B_OK) {
149			return B_ERROR;
150		}
151		target->Write(&bitsHeader, sizeof(TranslatorBitmap));
152
153		Array2D <Rgba> pixels(dataHeight, dataWidth);
154		in.setFrameBuffer (&pixels[0][0] - dataWindow.min.y * dataWidth - dataWindow.min.x, 1, dataWidth);
155		in.readPixels (dataWindow.min.y, dataWindow.max.y);
156
157		float	_gamma = 0.4545f;
158		float	_exposure = 0.0f;
159		float	_defog = 0.0f;
160		float	_kneeLow = 0.0f;
161		float	_kneeHigh = 5.0f;
162
163		float	_fogR = 0.0f;
164		float	_fogG = 0.0f;
165		float	_fogB = 0.0f;
166
167		halfFunction<float>
168		rGamma (Gamma (_gamma,
169					_exposure,
170					_defog * _fogR,
171					_kneeLow,
172					_kneeHigh),
173			-HALF_MAX, HALF_MAX,
174			0.f, 255.f, 0.f, 0.f);
175
176		halfFunction<float>
177		gGamma (Gamma (_gamma,
178					_exposure,
179					_defog * _fogG,
180					_kneeLow,
181					_kneeHigh),
182			-HALF_MAX, HALF_MAX,
183			0.f, 255.f, 0.f, 0.f);
184
185		halfFunction<float>
186		bGamma (Gamma (_gamma,
187					_exposure,
188					_defog * _fogB,
189					_kneeLow,
190					_kneeHigh),
191			-HALF_MAX, HALF_MAX,
192			0.f, 255.f, 0.f, 0.f);
193
194		for (int y = displayWindow.min.y; y <= displayWindow.max.y; ++y) {
195			if (y < dataWindow.min.y
196				|| y > dataWindow.max.y) {
197				unsigned char sp[4];
198				sp[0] = 128;
199				sp[1] = 128;
200				sp[2] = 128;
201				sp[3] = 255;
202				for (int x = displayWindow.min.x; x <= displayWindow.max.x; ++x) {
203					target->Write(sp, 4);
204				}
205				continue;
206			}
207
208			for (int x = displayWindow.min.x; x <= displayWindow.max.x; ++x) {
209				unsigned char sp[4];
210				if (x < dataWindow.min.x
211					|| x > dataWindow.max.x) {
212					sp[0] = 128;
213					sp[1] = 128;
214					sp[2] = 128;
215					sp[3] = 255;
216				} else {
217					const Imf::Rgba &rp = pixels[y][x];
218
219					sp[0] = (unsigned char)bGamma(rp.b);
220					sp[1] = (unsigned char)gGamma(rp.g);
221					sp[2] = (unsigned char)rGamma(rp.r);
222					sp[3] = 255;
223				}
224				target->Write(sp, 4);
225			}
226		}
227
228		err = B_OK;
229//	} catch (const std::exception &e) {
230//		std::cerr << e.what() << std::endl;
231	} catch (...) {
232	}
233	return err;
234}
235
236
237BView *
238EXRTranslator::NewConfigView(TranslatorSettings *settings)
239{
240	return new ConfigView();
241}
242
243
244//	#pragma mark -
245
246
247BTranslator *
248make_nth_translator(int32 n, image_id you, uint32 flags, ...)
249{
250	if (n != 0)
251		return NULL;
252
253	return new EXRTranslator();
254}
255