xref: /haiku/src/add-ons/translators/jpeg/JPEGTranslator.cpp (revision 1da233a71fe159b71ce7437b9acb5252adff4754)
19949213aSStephan Aßmus /*
29949213aSStephan Aßmus 
39949213aSStephan Aßmus Copyright (c) 2002-2003, Marcin 'Shard' Konicki
49949213aSStephan Aßmus All rights reserved.
59949213aSStephan Aßmus 
69949213aSStephan Aßmus Redistribution and use in source and binary forms, with or without
79949213aSStephan Aßmus modification, are permitted provided that the following conditions are met:
89949213aSStephan Aßmus 
99949213aSStephan Aßmus     * Redistributions of source code must retain the above copyright notice,
109949213aSStephan Aßmus       this list of conditions and the following disclaimer.
119949213aSStephan Aßmus     * Redistributions in binary form must reproduce the above copyright notice,
129949213aSStephan Aßmus       this list of conditions and the following disclaimer in the documentation and/or
139949213aSStephan Aßmus       other materials provided with the distribution.
149949213aSStephan Aßmus     * Name "Marcin Konicki", "Shard" or any combination of them,
159949213aSStephan Aßmus       must not be used to endorse or promote products derived from this
169949213aSStephan Aßmus       software without specific prior written permission from Marcin Konicki.
179949213aSStephan Aßmus 
189949213aSStephan Aßmus THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
199949213aSStephan Aßmus ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
209949213aSStephan Aßmus THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
219949213aSStephan Aßmus ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
229949213aSStephan Aßmus BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
239949213aSStephan Aßmus OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
249949213aSStephan Aßmus PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
259949213aSStephan Aßmus OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
269949213aSStephan Aßmus WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
279949213aSStephan Aßmus OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
289949213aSStephan Aßmus EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
299949213aSStephan Aßmus 
309949213aSStephan Aßmus */
319949213aSStephan Aßmus 
329949213aSStephan Aßmus 
339949213aSStephan Aßmus #include "JPEGTranslator.h"
34b98ef4f9SStephan Aßmus #include "TranslatorWindow.h"
3552e8f46aSAxel Dörfler #include "exif_parser.h"
3652e8f46aSAxel Dörfler 
3770d59669SSiarzhuk Zharski #include <syslog.h>
3870d59669SSiarzhuk Zharski 
39b98ef4f9SStephan Aßmus #include <Alignment.h>
4003901b6cSJérôme Duval #include <Catalog.h>
41b98ef4f9SStephan Aßmus #include <GridLayoutBuilder.h>
42b98ef4f9SStephan Aßmus #include <GroupLayoutBuilder.h>
438687ff64SAxel Dörfler #include <TabView.h>
44b98ef4f9SStephan Aßmus #include <TextView.h>
458687ff64SAxel Dörfler 
4603901b6cSJérôme Duval #undef B_TRANSLATE_CONTEXT
4703901b6cSJérôme Duval #define B_TRANSLATE_CONTEXT "JPEGTranslator"
489949213aSStephan Aßmus 
4952e8f46aSAxel Dörfler #define MARKER_EXIF	0xe1
5052e8f46aSAxel Dörfler 
519949213aSStephan Aßmus // Set these accordingly
529949213aSStephan Aßmus #define JPEG_ACRONYM "JPEG"
539949213aSStephan Aßmus #define JPEG_FORMAT 'JPEG'
549949213aSStephan Aßmus #define JPEG_MIME_STRING "image/jpeg"
559949213aSStephan Aßmus #define JPEG_DESCRIPTION "JPEG image"
569949213aSStephan Aßmus 
579949213aSStephan Aßmus // The translation kit's native file type
589949213aSStephan Aßmus #define B_TRANSLATOR_BITMAP_MIME_STRING "image/x-be-bitmap"
59c095606eSRyan Leavengood #define B_TRANSLATOR_BITMAP_DESCRIPTION "Be Bitmap Format (JPEGTranslator)"
609949213aSStephan Aßmus 
61b98ef4f9SStephan Aßmus 
622e49ff35SSiarzhuk Zharski static const int32 sTranslatorVersion = B_TRANSLATION_MAKE_VERSION(1, 2, 0);
632e49ff35SSiarzhuk Zharski 
64*1da233a7SSiarzhuk Zharski static const char* sTranslatorName = B_TRANSLATE("JPEG images");
65*1da233a7SSiarzhuk Zharski static const char* sTranslatorInfo = B_TRANSLATE("©2002-2003, Marcin Konicki\n"
66f13b5de6SAxel Dörfler 	"©2005-2007, Haiku\n"
67758b1d0eSIngo Weinhold 	"\n"
687fd58091SJérôme Duval 	"Based on IJG library ©  1994-2009, Thomas G. Lane, Guido Vollbeding.\n"
692e49ff35SSiarzhuk Zharski 	"\thttp://www.ijg.org/files/\n"
70b98ef4f9SStephan Aßmus 	"\n"
71fcc3e627SStephan Aßmus 	"with \"lossless\" encoding support patch by Ken Murchison\n"
722e49ff35SSiarzhuk Zharski 	"\thttp://www.oceana.com/ftp/ljpeg/\n"
73758b1d0eSIngo Weinhold 	"\n"
74758b1d0eSIngo Weinhold 	"With some colorspace conversion routines by Magnus Hellman\n"
752e49ff35SSiarzhuk Zharski 	"\thttp://www.bebits.com/app/802\n");
769949213aSStephan Aßmus 
779949213aSStephan Aßmus // Define the formats we know how to read
78bf243977SPhilippe Houdoin static const translation_format sInputFormats[] = {
799949213aSStephan Aßmus 	{ JPEG_FORMAT, B_TRANSLATOR_BITMAP, 0.5, 0.5,
809949213aSStephan Aßmus 		JPEG_MIME_STRING, JPEG_DESCRIPTION },
819949213aSStephan Aßmus 	{ B_TRANSLATOR_BITMAP, B_TRANSLATOR_BITMAP, 0.5, 0.5,
827b5743baSPhilippe Houdoin 		B_TRANSLATOR_BITMAP_MIME_STRING, B_TRANSLATOR_BITMAP_DESCRIPTION }
839949213aSStephan Aßmus };
849949213aSStephan Aßmus 
859949213aSStephan Aßmus // Define the formats we know how to write
86bf243977SPhilippe Houdoin static const translation_format sOutputFormats[] = {
879949213aSStephan Aßmus 	{ JPEG_FORMAT, B_TRANSLATOR_BITMAP, 0.5, 0.5,
889949213aSStephan Aßmus 		JPEG_MIME_STRING, JPEG_DESCRIPTION },
899949213aSStephan Aßmus 	{ B_TRANSLATOR_BITMAP, B_TRANSLATOR_BITMAP, 0.5, 0.5,
907b5743baSPhilippe Houdoin 		B_TRANSLATOR_BITMAP_MIME_STRING, B_TRANSLATOR_BITMAP_DESCRIPTION }
919949213aSStephan Aßmus };
9252e8f46aSAxel Dörfler 
93d8e2fb50SAxel Dörfler 
94bf243977SPhilippe Houdoin static const TranSetting sDefaultSettings[] = {
95b98ef4f9SStephan Aßmus 	{JPEG_SET_SMOOTHING, TRAN_SETTING_INT32, 0},
96b98ef4f9SStephan Aßmus 	{JPEG_SET_QUALITY, TRAN_SETTING_INT32, 95},
97b98ef4f9SStephan Aßmus 	{JPEG_SET_PROGRESSIVE, TRAN_SETTING_BOOL, true},
98b98ef4f9SStephan Aßmus 	{JPEG_SET_OPT_COLORS, TRAN_SETTING_BOOL, true},
99b98ef4f9SStephan Aßmus 	{JPEG_SET_SMALL_FILES, TRAN_SETTING_BOOL, false},
100b98ef4f9SStephan Aßmus 	{JPEG_SET_GRAY1_AS_RGB24, TRAN_SETTING_BOOL, false},
101b98ef4f9SStephan Aßmus 	{JPEG_SET_ALWAYS_RGB32, TRAN_SETTING_BOOL, true},
102b98ef4f9SStephan Aßmus 	{JPEG_SET_PHOTOSHOP_CMYK, TRAN_SETTING_BOOL, true},
103b98ef4f9SStephan Aßmus 	{JPEG_SET_SHOWREADWARNING, TRAN_SETTING_BOOL, true}
104b98ef4f9SStephan Aßmus };
105bf243977SPhilippe Houdoin 
106bf243977SPhilippe Houdoin const uint32 kNumInputFormats = sizeof(sInputFormats) / sizeof(translation_format);
107bf243977SPhilippe Houdoin const uint32 kNumOutputFormats = sizeof(sOutputFormats) / sizeof(translation_format);
108bf243977SPhilippe Houdoin const uint32 kNumDefaultSettings = sizeof(sDefaultSettings) / sizeof(TranSetting);
1099949213aSStephan Aßmus 
110d8e2fb50SAxel Dörfler 
111b98ef4f9SStephan Aßmus namespace conversion {
112d8e2fb50SAxel Dörfler 
113d8e2fb50SAxel Dörfler 
1149e34f742SAxel Dörfler static bool
1159e34f742SAxel Dörfler x_flipped(int32 orientation)
1169e34f742SAxel Dörfler {
1179e34f742SAxel Dörfler 	return orientation == 2 || orientation == 3
1189e34f742SAxel Dörfler 		|| orientation == 6 || orientation == 7;
1199e34f742SAxel Dörfler }
1209e34f742SAxel Dörfler 
1219e34f742SAxel Dörfler 
1229e34f742SAxel Dörfler static bool
1239e34f742SAxel Dörfler y_flipped(int32 orientation)
1249e34f742SAxel Dörfler {
1259e34f742SAxel Dörfler 	return orientation == 3 || orientation == 4
1269e34f742SAxel Dörfler 		|| orientation == 7 || orientation == 8;
1279e34f742SAxel Dörfler }
1289e34f742SAxel Dörfler 
1299e34f742SAxel Dörfler 
1309e34f742SAxel Dörfler static int32
1319e34f742SAxel Dörfler dest_index(uint32 width, uint32 height, uint32 x, uint32 y, int32 orientation)
1329e34f742SAxel Dörfler {
1339e34f742SAxel Dörfler 	if (orientation > 4) {
1349e34f742SAxel Dörfler 		uint32 temp = x;
1359e34f742SAxel Dörfler 		x = y;
1369e34f742SAxel Dörfler 		y = temp;
1379e34f742SAxel Dörfler 	}
1389e34f742SAxel Dörfler 	if (y_flipped(orientation))
1399e34f742SAxel Dörfler 		y = height - 1 - y;
1409e34f742SAxel Dörfler 	if (x_flipped(orientation))
1419e34f742SAxel Dörfler 		x = width - 1 - x;
1429e34f742SAxel Dörfler 
1439e34f742SAxel Dörfler 	return y * width + x;
1449e34f742SAxel Dörfler }
1459e34f742SAxel Dörfler 
1469e34f742SAxel Dörfler 
1479e34f742SAxel Dörfler //	#pragma mark - conversion for compression
148d8e2fb50SAxel Dörfler 
149d8e2fb50SAxel Dörfler 
150d8e2fb50SAxel Dörfler inline void
1519e34f742SAxel Dörfler convert_from_gray1_to_gray8(uint8* in, uint8* out, int32 inRowBytes)
152d8e2fb50SAxel Dörfler {
153d8e2fb50SAxel Dörfler 	int32 index = 0;
154d8e2fb50SAxel Dörfler 	int32 index2 = 0;
1559e34f742SAxel Dörfler 	while (index < inRowBytes) {
156d8e2fb50SAxel Dörfler 		unsigned char c = in[index++];
157d8e2fb50SAxel Dörfler 		for (int b = 128; b; b = b>>1) {
158d8e2fb50SAxel Dörfler 			unsigned char color;
159d8e2fb50SAxel Dörfler 			if (c & b)
160d8e2fb50SAxel Dörfler 				color = 0;
161d8e2fb50SAxel Dörfler 			else
162d8e2fb50SAxel Dörfler 				color = 255;
163d8e2fb50SAxel Dörfler 			out[index2++] = color;
164d8e2fb50SAxel Dörfler 		}
165d8e2fb50SAxel Dörfler 	}
166d8e2fb50SAxel Dörfler }
167d8e2fb50SAxel Dörfler 
168d8e2fb50SAxel Dörfler 
169d8e2fb50SAxel Dörfler inline void
1709e34f742SAxel Dörfler convert_from_gray1_to_24(uint8* in, uint8* out, int32 inRowBytes)
171d8e2fb50SAxel Dörfler {
172d8e2fb50SAxel Dörfler 	int32 index = 0;
173d8e2fb50SAxel Dörfler 	int32 index2 = 0;
1749e34f742SAxel Dörfler 	while (index < inRowBytes) {
175d8e2fb50SAxel Dörfler 		unsigned char c = in[index++];
176d8e2fb50SAxel Dörfler 		for (int b = 128; b; b = b>>1) {
177d8e2fb50SAxel Dörfler 			unsigned char color;
178d8e2fb50SAxel Dörfler 			if (c & b)
179d8e2fb50SAxel Dörfler 				color = 0;
180d8e2fb50SAxel Dörfler 			else
181d8e2fb50SAxel Dörfler 				color = 255;
182d8e2fb50SAxel Dörfler 			out[index2++] = color;
183d8e2fb50SAxel Dörfler 			out[index2++] = color;
184d8e2fb50SAxel Dörfler 			out[index2++] = color;
185d8e2fb50SAxel Dörfler 		}
186d8e2fb50SAxel Dörfler 	}
187d8e2fb50SAxel Dörfler }
188d8e2fb50SAxel Dörfler 
189d8e2fb50SAxel Dörfler 
190d8e2fb50SAxel Dörfler inline void
1919e34f742SAxel Dörfler convert_from_cmap8_to_24(uint8* in, uint8* out, int32 inRowBytes)
192d8e2fb50SAxel Dörfler {
193d8e2fb50SAxel Dörfler 	const color_map * map = system_colors();
194d8e2fb50SAxel Dörfler 	int32 index = 0;
195d8e2fb50SAxel Dörfler 	int32 index2 = 0;
1969e34f742SAxel Dörfler 	while (index < inRowBytes) {
197d8e2fb50SAxel Dörfler 		rgb_color color = map->color_list[in[index++]];
198d8e2fb50SAxel Dörfler 
199d8e2fb50SAxel Dörfler 		out[index2++] = color.red;
200d8e2fb50SAxel Dörfler 		out[index2++] = color.green;
201d8e2fb50SAxel Dörfler 		out[index2++] = color.blue;
202d8e2fb50SAxel Dörfler 	}
203d8e2fb50SAxel Dörfler }
204d8e2fb50SAxel Dörfler 
205d8e2fb50SAxel Dörfler 
206d8e2fb50SAxel Dörfler inline void
2079e34f742SAxel Dörfler convert_from_15_to_24(uint8* in, uint8* out, int32 inRowBytes)
208d8e2fb50SAxel Dörfler {
209d8e2fb50SAxel Dörfler 	int32 index = 0;
210d8e2fb50SAxel Dörfler 	int32 index2 = 0;
211d8e2fb50SAxel Dörfler 	int16 in_pixel;
2129e34f742SAxel Dörfler 	while (index < inRowBytes) {
213d8e2fb50SAxel Dörfler 		in_pixel = in[index] | (in[index + 1] << 8);
214d8e2fb50SAxel Dörfler 		index += 2;
215d8e2fb50SAxel Dörfler 
216d8e2fb50SAxel Dörfler 		out[index2++] = (((in_pixel & 0x7c00)) >> 7) | (((in_pixel & 0x7c00)) >> 12);
217d8e2fb50SAxel Dörfler 		out[index2++] = (((in_pixel & 0x3e0)) >> 2) | (((in_pixel & 0x3e0)) >> 7);
218d8e2fb50SAxel Dörfler 		out[index2++] = (((in_pixel & 0x1f)) << 3) | (((in_pixel & 0x1f)) >> 2);
219d8e2fb50SAxel Dörfler 	}
220d8e2fb50SAxel Dörfler }
221d8e2fb50SAxel Dörfler 
222d8e2fb50SAxel Dörfler 
223d8e2fb50SAxel Dörfler inline void
2249e34f742SAxel Dörfler convert_from_15b_to_24(uint8* in, uint8* out, int32 inRowBytes)
225d8e2fb50SAxel Dörfler {
226d8e2fb50SAxel Dörfler 	int32 index = 0;
227d8e2fb50SAxel Dörfler 	int32 index2 = 0;
228d8e2fb50SAxel Dörfler 	int16 in_pixel;
2299e34f742SAxel Dörfler 	while (index < inRowBytes) {
230d8e2fb50SAxel Dörfler 		in_pixel = in[index + 1] | (in[index] << 8);
231d8e2fb50SAxel Dörfler 		index += 2;
232d8e2fb50SAxel Dörfler 
233d8e2fb50SAxel Dörfler 		out[index2++] = (((in_pixel & 0x7c00)) >> 7) | (((in_pixel & 0x7c00)) >> 12);
234d8e2fb50SAxel Dörfler 		out[index2++] = (((in_pixel & 0x3e0)) >> 2) | (((in_pixel & 0x3e0)) >> 7);
235d8e2fb50SAxel Dörfler 		out[index2++] = (((in_pixel & 0x1f)) << 3) | (((in_pixel & 0x1f)) >> 2);
236d8e2fb50SAxel Dörfler 	}
237d8e2fb50SAxel Dörfler }
238d8e2fb50SAxel Dörfler 
239d8e2fb50SAxel Dörfler 
240d8e2fb50SAxel Dörfler inline void
2419e34f742SAxel Dörfler convert_from_16_to_24(uint8* in, uint8* out, int32 inRowBytes)
242d8e2fb50SAxel Dörfler {
243d8e2fb50SAxel Dörfler 	int32 index = 0;
244d8e2fb50SAxel Dörfler 	int32 index2 = 0;
245d8e2fb50SAxel Dörfler 	int16 in_pixel;
2469e34f742SAxel Dörfler 	while (index < inRowBytes) {
247d8e2fb50SAxel Dörfler 		in_pixel = in[index] | (in[index + 1] << 8);
248d8e2fb50SAxel Dörfler 		index += 2;
249d8e2fb50SAxel Dörfler 
250d8e2fb50SAxel Dörfler 		out[index2++] = (((in_pixel & 0xf800)) >> 8) | (((in_pixel & 0xf800)) >> 13);
251d8e2fb50SAxel Dörfler 		out[index2++] = (((in_pixel & 0x7e0)) >> 3) | (((in_pixel & 0x7e0)) >> 9);
252d8e2fb50SAxel Dörfler 		out[index2++] = (((in_pixel & 0x1f)) << 3) | (((in_pixel & 0x1f)) >> 2);
253d8e2fb50SAxel Dörfler 	}
254d8e2fb50SAxel Dörfler }
255d8e2fb50SAxel Dörfler 
256d8e2fb50SAxel Dörfler 
257d8e2fb50SAxel Dörfler inline void
2589e34f742SAxel Dörfler convert_from_16b_to_24(uint8* in, uint8* out, int32 inRowBytes)
259d8e2fb50SAxel Dörfler {
260d8e2fb50SAxel Dörfler 	int32 index = 0;
261d8e2fb50SAxel Dörfler 	int32 index2 = 0;
262d8e2fb50SAxel Dörfler 	int16 in_pixel;
2639e34f742SAxel Dörfler 	while (index < inRowBytes) {
264d8e2fb50SAxel Dörfler 		in_pixel = in[index + 1] | (in[index] << 8);
265d8e2fb50SAxel Dörfler 		index += 2;
266d8e2fb50SAxel Dörfler 
267d8e2fb50SAxel Dörfler 		out[index2++] = (((in_pixel & 0xf800)) >> 8) | (((in_pixel & 0xf800)) >> 13);
268d8e2fb50SAxel Dörfler 		out[index2++] = (((in_pixel & 0x7e0)) >> 3) | (((in_pixel & 0x7e0)) >> 9);
269d8e2fb50SAxel Dörfler 		out[index2++] = (((in_pixel & 0x1f)) << 3) | (((in_pixel & 0x1f)) >> 2);
270d8e2fb50SAxel Dörfler 	}
271d8e2fb50SAxel Dörfler }
272d8e2fb50SAxel Dörfler 
273d8e2fb50SAxel Dörfler 
274d8e2fb50SAxel Dörfler inline void
2759e34f742SAxel Dörfler convert_from_24_to_24(uint8* in, uint8* out, int32 inRowBytes)
276d8e2fb50SAxel Dörfler {
277d8e2fb50SAxel Dörfler 	int32 index = 0;
278d8e2fb50SAxel Dörfler 	int32 index2 = 0;
2799e34f742SAxel Dörfler 	while (index < inRowBytes) {
280d8e2fb50SAxel Dörfler 		out[index2++] = in[index + 2];
281d8e2fb50SAxel Dörfler 		out[index2++] = in[index + 1];
282d8e2fb50SAxel Dörfler 		out[index2++] = in[index];
283d8e2fb50SAxel Dörfler 		index+=3;
284d8e2fb50SAxel Dörfler 	}
285d8e2fb50SAxel Dörfler }
286d8e2fb50SAxel Dörfler 
287d8e2fb50SAxel Dörfler 
288d8e2fb50SAxel Dörfler inline void
2899e34f742SAxel Dörfler convert_from_32_to_24(uint8* in, uint8* out, int32 inRowBytes)
290d8e2fb50SAxel Dörfler {
29151623681SAxel Dörfler 	inRowBytes /= 4;
29251623681SAxel Dörfler 
2939e34f742SAxel Dörfler 	for (int32 i = 0; i < inRowBytes; i++) {
2949e34f742SAxel Dörfler 		out[0] = in[2];
2959e34f742SAxel Dörfler 		out[1] = in[1];
2969e34f742SAxel Dörfler 		out[2] = in[0];
2979e34f742SAxel Dörfler 
2989e34f742SAxel Dörfler 		in += 4;
2999e34f742SAxel Dörfler 		out += 3;
300d8e2fb50SAxel Dörfler 	}
301d8e2fb50SAxel Dörfler }
302d8e2fb50SAxel Dörfler 
303d8e2fb50SAxel Dörfler 
304d8e2fb50SAxel Dörfler inline void
3059e34f742SAxel Dörfler convert_from_32b_to_24(uint8* in, uint8* out, int32 inRowBytes)
306d8e2fb50SAxel Dörfler {
30751623681SAxel Dörfler 	inRowBytes /= 4;
30851623681SAxel Dörfler 
3099e34f742SAxel Dörfler 	for (int32 i = 0; i < inRowBytes; i++) {
31051623681SAxel Dörfler 		out[0] = in[1];
31151623681SAxel Dörfler 		out[1] = in[2];
31251623681SAxel Dörfler 		out[2] = in[3];
3139e34f742SAxel Dörfler 
3149e34f742SAxel Dörfler 		in += 4;
3159e34f742SAxel Dörfler 		out += 3;
316d8e2fb50SAxel Dörfler 	}
317d8e2fb50SAxel Dörfler }
318d8e2fb50SAxel Dörfler 
319d8e2fb50SAxel Dörfler 
3209e34f742SAxel Dörfler //	#pragma mark - conversion for decompression
3219e34f742SAxel Dörfler 
3229e34f742SAxel Dörfler 
323d8e2fb50SAxel Dörfler inline void
3249e34f742SAxel Dörfler convert_from_CMYK_to_32_photoshop(uint8* in, uint8* out, int32 inRowBytes, int32 xStep)
325d8e2fb50SAxel Dörfler {
3269e34f742SAxel Dörfler 	for (int32 i = 0; i < inRowBytes; i += 4) {
3279e34f742SAxel Dörfler 		int32 black = in[3];
3289e34f742SAxel Dörfler 		out[0] = in[2] * black / 255;
3299e34f742SAxel Dörfler 		out[1] = in[1] * black / 255;
3309e34f742SAxel Dörfler 		out[2] = in[0] * black / 255;
3319e34f742SAxel Dörfler 		out[3] = 255;
3329e34f742SAxel Dörfler 
3339e34f742SAxel Dörfler 		in += 4;
3349e34f742SAxel Dörfler 		out += xStep;
335d8e2fb50SAxel Dörfler 	}
336d8e2fb50SAxel Dörfler }
337d8e2fb50SAxel Dörfler 
338d8e2fb50SAxel Dörfler 
339d8e2fb50SAxel Dörfler //!	!!! UNTESTED !!!
340d8e2fb50SAxel Dörfler inline void
3419e34f742SAxel Dörfler convert_from_CMYK_to_32(uint8* in, uint8* out, int32 inRowBytes, int32 xStep)
342d8e2fb50SAxel Dörfler {
3439e34f742SAxel Dörfler 	for (int32 i = 0; i < inRowBytes; i += 4) {
3449e34f742SAxel Dörfler 		int32 black = 255 - in[3];
3459e34f742SAxel Dörfler 		out[0] = ((255 - in[2]) * black) / 255;
3469e34f742SAxel Dörfler 		out[1] = ((255 - in[1]) * black) / 255;
3479e34f742SAxel Dörfler 		out[2] = ((255 - in[0]) * black) / 255;
3489e34f742SAxel Dörfler 		out[3] = 255;
3499e34f742SAxel Dörfler 
3509e34f742SAxel Dörfler 		in += 4;
3519e34f742SAxel Dörfler 		out += xStep;
352d8e2fb50SAxel Dörfler 	}
353d8e2fb50SAxel Dörfler }
354d8e2fb50SAxel Dörfler 
355d8e2fb50SAxel Dörfler 
356d8e2fb50SAxel Dörfler //!	RGB24 8:8:8 to xRGB 8:8:8:8
357d8e2fb50SAxel Dörfler inline void
3589e34f742SAxel Dörfler convert_from_24_to_32(uint8* in, uint8* out, int32 inRowBytes, int32 xStep)
359d8e2fb50SAxel Dörfler {
3609e34f742SAxel Dörfler 	for (int32 i = 0; i < inRowBytes; i += 3) {
3619e34f742SAxel Dörfler 		out[0] = in[2];
3629e34f742SAxel Dörfler 		out[1] = in[1];
3639e34f742SAxel Dörfler 		out[2] = in[0];
3649e34f742SAxel Dörfler 		out[3] = 255;
3659e34f742SAxel Dörfler 
3669e34f742SAxel Dörfler 		in += 3;
3679e34f742SAxel Dörfler 		out += xStep;
3689e34f742SAxel Dörfler 	}
3699e34f742SAxel Dörfler }
3709e34f742SAxel Dörfler 
3719e34f742SAxel Dörfler 
3729e34f742SAxel Dörfler //! 8-bit to 8-bit, only need when rotating the image
3739e34f742SAxel Dörfler void
3749e34f742SAxel Dörfler translate_8(uint8* in, uint8* out, int32 inRowBytes, int32 xStep)
3759e34f742SAxel Dörfler {
3769e34f742SAxel Dörfler 	for (int32 i = 0; i < inRowBytes; i++) {
3779e34f742SAxel Dörfler 		out[0] = in[0];
3789e34f742SAxel Dörfler 
3799e34f742SAxel Dörfler 		in++;
3809e34f742SAxel Dörfler 		out += xStep;
381d8e2fb50SAxel Dörfler 	}
382d8e2fb50SAxel Dörfler }
383d8e2fb50SAxel Dörfler 
384d8e2fb50SAxel Dörfler 
385b98ef4f9SStephan Aßmus } // namespace conversion
3868687ff64SAxel Dörfler 
3878687ff64SAxel Dörfler 
388d8e2fb50SAxel Dörfler //	#pragma mark -
389d8e2fb50SAxel Dörfler 
390d8e2fb50SAxel Dörfler 
391b98ef4f9SStephan Aßmus SSlider::SSlider(const char* name, const char* label,
392d8e2fb50SAxel Dörfler 		BMessage* message, int32 minValue, int32 maxValue, orientation posture,
393b98ef4f9SStephan Aßmus 		thumb_style thumbType, uint32 flags)
394b98ef4f9SStephan Aßmus 	: BSlider(name, label, message, minValue, maxValue,
395b98ef4f9SStephan Aßmus 		posture, thumbType, flags)
3969949213aSStephan Aßmus {
3978687ff64SAxel Dörfler 	rgb_color barColor = { 0, 0, 229, 255 };
3988687ff64SAxel Dörfler 	UseFillColor(true, &barColor);
3999949213aSStephan Aßmus }
4009949213aSStephan Aßmus 
4018687ff64SAxel Dörfler 
4028687ff64SAxel Dörfler //!	Update status string - show actual value
403b20d13f4SStefano Ceccherini const char*
4049949213aSStephan Aßmus SSlider::UpdateText() const
4059949213aSStephan Aßmus {
4068687ff64SAxel Dörfler 	snprintf(fStatusLabel, sizeof(fStatusLabel), "%ld", Value());
4078687ff64SAxel Dörfler 	return fStatusLabel;
4089949213aSStephan Aßmus }
4099949213aSStephan Aßmus 
4108687ff64SAxel Dörfler 
411d8e2fb50SAxel Dörfler //	#pragma mark -
4129949213aSStephan Aßmus 
413d8e2fb50SAxel Dörfler 
414b98ef4f9SStephan Aßmus TranslatorReadView::TranslatorReadView(const char* name,
415b98ef4f9SStephan Aßmus 	TranslatorSettings* settings)
416b98ef4f9SStephan Aßmus 	:
417b98ef4f9SStephan Aßmus 	BView(name, 0, new BGroupLayout(B_HORIZONTAL)),
418d8e2fb50SAxel Dörfler 	fSettings(settings)
419b98ef4f9SStephan Aßmus 		// settings should already be Acquired()
4209949213aSStephan Aßmus {
4212e49ff35SSiarzhuk Zharski 	fAlwaysRGB32 = new BCheckBox("alwaysrgb32",
4222e49ff35SSiarzhuk Zharski 		B_TRANSLATE("Read greyscale images as RGB32"),
423d8e2fb50SAxel Dörfler 		new BMessage(VIEW_MSG_SET_ALWAYSRGB32));
424b98ef4f9SStephan Aßmus 	if (fSettings->SetGetBool(JPEG_SET_ALWAYS_RGB32, NULL))
425b98ef4f9SStephan Aßmus 		fAlwaysRGB32->SetValue(B_CONTROL_ON);
4269949213aSStephan Aßmus 
4272e49ff35SSiarzhuk Zharski 	fPhotoshopCMYK = new BCheckBox("photoshopCMYK",
4282e49ff35SSiarzhuk Zharski 		B_TRANSLATE("Use CMYK code with 0 for 100% ink coverage"),
4298687ff64SAxel Dörfler 		new BMessage(VIEW_MSG_SET_PHOTOSHOPCMYK));
430b98ef4f9SStephan Aßmus 	if (fSettings->SetGetBool(JPEG_SET_PHOTOSHOP_CMYK, NULL))
431b98ef4f9SStephan Aßmus 		fPhotoshopCMYK->SetValue(B_CONTROL_ON);
4329949213aSStephan Aßmus 
4332e49ff35SSiarzhuk Zharski 	fShowErrorBox = new BCheckBox("error",
4342e49ff35SSiarzhuk Zharski 		B_TRANSLATE("Show warning messages"),
4358687ff64SAxel Dörfler 		new BMessage(VIEW_MSG_SET_SHOWREADERRORBOX));
436b98ef4f9SStephan Aßmus 	if (fSettings->SetGetBool(JPEG_SET_SHOWREADWARNING, NULL))
437b98ef4f9SStephan Aßmus 		fShowErrorBox->SetValue(B_CONTROL_ON);
4389949213aSStephan Aßmus 
439b98ef4f9SStephan Aßmus 	float padding = 5.0f;
440b98ef4f9SStephan Aßmus 	AddChild(BGroupLayoutBuilder(B_VERTICAL, padding)
441b98ef4f9SStephan Aßmus 		.Add(fAlwaysRGB32)
442b98ef4f9SStephan Aßmus 		.Add(fPhotoshopCMYK)
443b98ef4f9SStephan Aßmus 		.Add(fShowErrorBox)
444b98ef4f9SStephan Aßmus 		.AddGlue()
445b98ef4f9SStephan Aßmus 		.SetInsets(padding, padding, padding, padding)
446b98ef4f9SStephan Aßmus 	);
4479949213aSStephan Aßmus 
448b98ef4f9SStephan Aßmus }
449b98ef4f9SStephan Aßmus 
450b98ef4f9SStephan Aßmus 
451b98ef4f9SStephan Aßmus TranslatorReadView::~TranslatorReadView()
452b98ef4f9SStephan Aßmus {
453b98ef4f9SStephan Aßmus 	fSettings->Release();
4549949213aSStephan Aßmus }
4559949213aSStephan Aßmus 
4568687ff64SAxel Dörfler 
4579949213aSStephan Aßmus void
4589949213aSStephan Aßmus TranslatorReadView::AttachedToWindow()
4599949213aSStephan Aßmus {
460b98ef4f9SStephan Aßmus 	BView::AttachedToWindow();
461b20d13f4SStefano Ceccherini 
4628687ff64SAxel Dörfler 	fAlwaysRGB32->SetTarget(this);
4638687ff64SAxel Dörfler 	fPhotoshopCMYK->SetTarget(this);
4648687ff64SAxel Dörfler 	fShowErrorBox->SetTarget(this);
4659949213aSStephan Aßmus }
4669949213aSStephan Aßmus 
4678687ff64SAxel Dörfler 
4689949213aSStephan Aßmus void
4699949213aSStephan Aßmus TranslatorReadView::MessageReceived(BMessage* message)
4709949213aSStephan Aßmus {
4718687ff64SAxel Dörfler 	switch (message->what) {
4729949213aSStephan Aßmus 		case VIEW_MSG_SET_ALWAYSRGB32:
4739949213aSStephan Aßmus 		{
4749949213aSStephan Aßmus 			int32 value;
4759949213aSStephan Aßmus 			if (message->FindInt32("be:value", &value) == B_OK) {
476b98ef4f9SStephan Aßmus 				bool boolValue = value;
477b98ef4f9SStephan Aßmus 				fSettings->SetGetBool(JPEG_SET_ALWAYS_RGB32, &boolValue);
478b98ef4f9SStephan Aßmus 				fSettings->SaveSettings();
4799949213aSStephan Aßmus 			}
4809949213aSStephan Aßmus 			break;
4819949213aSStephan Aßmus 		}
4829949213aSStephan Aßmus 		case VIEW_MSG_SET_PHOTOSHOPCMYK:
4839949213aSStephan Aßmus 		{
4849949213aSStephan Aßmus 			int32 value;
4859949213aSStephan Aßmus 			if (message->FindInt32("be:value", &value) == B_OK) {
486b98ef4f9SStephan Aßmus 				bool boolValue = value;
487b98ef4f9SStephan Aßmus 				fSettings->SetGetBool(JPEG_SET_PHOTOSHOP_CMYK, &boolValue);
488b98ef4f9SStephan Aßmus 				fSettings->SaveSettings();
4899949213aSStephan Aßmus 			}
4909949213aSStephan Aßmus 			break;
4919949213aSStephan Aßmus 		}
4929949213aSStephan Aßmus 		case VIEW_MSG_SET_SHOWREADERRORBOX:
4939949213aSStephan Aßmus 		{
4949949213aSStephan Aßmus 			int32 value;
4959949213aSStephan Aßmus 			if (message->FindInt32("be:value", &value) == B_OK) {
496b98ef4f9SStephan Aßmus 				bool boolValue = value;
497b98ef4f9SStephan Aßmus 				fSettings->SetGetBool(JPEG_SET_SHOWREADWARNING, &boolValue);
498b98ef4f9SStephan Aßmus 				fSettings->SaveSettings();
4999949213aSStephan Aßmus 			}
5009949213aSStephan Aßmus 			break;
5019949213aSStephan Aßmus 		}
5029949213aSStephan Aßmus 		default:
5039949213aSStephan Aßmus 			BView::MessageReceived(message);
5049949213aSStephan Aßmus 			break;
5059949213aSStephan Aßmus 	}
5069949213aSStephan Aßmus }
5079949213aSStephan Aßmus 
5089949213aSStephan Aßmus 
5098687ff64SAxel Dörfler //	#pragma mark - TranslatorWriteView
5109949213aSStephan Aßmus 
5118687ff64SAxel Dörfler 
512b98ef4f9SStephan Aßmus TranslatorWriteView::TranslatorWriteView(const char* name,
513b98ef4f9SStephan Aßmus 	TranslatorSettings* settings)
514b98ef4f9SStephan Aßmus 	:
515b98ef4f9SStephan Aßmus 	BView(name, 0, new BGroupLayout(B_VERTICAL)),
516d8e2fb50SAxel Dörfler 	fSettings(settings)
517b98ef4f9SStephan Aßmus 		// settings should already be Acquired()
5189949213aSStephan Aßmus {
5192e49ff35SSiarzhuk Zharski 	fQualitySlider = new SSlider("quality", B_TRANSLATE("Output quality"),
5208687ff64SAxel Dörfler 		new BMessage(VIEW_MSG_SET_QUALITY), 0, 100);
5218687ff64SAxel Dörfler 	fQualitySlider->SetHashMarks(B_HASH_MARKS_BOTTOM);
5228687ff64SAxel Dörfler 	fQualitySlider->SetHashMarkCount(10);
52303901b6cSJérôme Duval 	fQualitySlider->SetLimitLabels(B_TRANSLATE("Low"), B_TRANSLATE("High"));
524b98ef4f9SStephan Aßmus 	fQualitySlider->SetValue(fSettings->SetGetInt32(JPEG_SET_QUALITY, NULL));
5259949213aSStephan Aßmus 
5262e49ff35SSiarzhuk Zharski 	fSmoothingSlider = new SSlider("smoothing",
5272e49ff35SSiarzhuk Zharski 		B_TRANSLATE("Output smoothing strength"),
5288687ff64SAxel Dörfler 		new BMessage(VIEW_MSG_SET_SMOOTHING), 0, 100);
5298687ff64SAxel Dörfler 	fSmoothingSlider->SetHashMarks(B_HASH_MARKS_BOTTOM);
5308687ff64SAxel Dörfler 	fSmoothingSlider->SetHashMarkCount(10);
53103901b6cSJérôme Duval 	fSmoothingSlider->SetLimitLabels(B_TRANSLATE("None"), B_TRANSLATE("High"));
532b98ef4f9SStephan Aßmus 	fSmoothingSlider->SetValue(
533b98ef4f9SStephan Aßmus 		fSettings->SetGetInt32(JPEG_SET_SMOOTHING, NULL));
5349949213aSStephan Aßmus 
5352e49ff35SSiarzhuk Zharski 	fProgress = new BCheckBox("progress",
5362e49ff35SSiarzhuk Zharski 		B_TRANSLATE("Use progressive compression"),
5378687ff64SAxel Dörfler 		new BMessage(VIEW_MSG_SET_PROGRESSIVE));
538b98ef4f9SStephan Aßmus 	if (fSettings->SetGetBool(JPEG_SET_PROGRESSIVE, NULL))
539b98ef4f9SStephan Aßmus 		fProgress->SetValue(B_CONTROL_ON);
5409949213aSStephan Aßmus 
5412e49ff35SSiarzhuk Zharski 	fSmallerFile = new BCheckBox("smallerfile",
5422e49ff35SSiarzhuk Zharski 		B_TRANSLATE("Make file smaller (sligthtly worse quality)"),
5438687ff64SAxel Dörfler 		new BMessage(VIEW_MSG_SET_SMALLERFILE));
544b98ef4f9SStephan Aßmus 	if (fSettings->SetGetBool(JPEG_SET_SMALL_FILES))
545b98ef4f9SStephan Aßmus 		fSmallerFile->SetValue(B_CONTROL_ON);
546b98ef4f9SStephan Aßmus 
5472e49ff35SSiarzhuk Zharski 	fOptimizeColors = new BCheckBox("optimizecolors",
5482e49ff35SSiarzhuk Zharski 		B_TRANSLATE("Prevent colors 'washing out'"),
549b98ef4f9SStephan Aßmus 		new BMessage(VIEW_MSG_SET_OPTIMIZECOLORS));
550b98ef4f9SStephan Aßmus 	if (fSettings->SetGetBool(JPEG_SET_OPT_COLORS, NULL))
551b98ef4f9SStephan Aßmus 		fOptimizeColors->SetValue(B_CONTROL_ON);
552b98ef4f9SStephan Aßmus 	else
5538687ff64SAxel Dörfler 		fSmallerFile->SetEnabled(false);
5549949213aSStephan Aßmus 
5552e49ff35SSiarzhuk Zharski 	fGrayAsRGB24 = new BCheckBox("gray1asrgb24",
5562e49ff35SSiarzhuk Zharski 		B_TRANSLATE("Write black-and-white images as RGB24"),
5578687ff64SAxel Dörfler 		new BMessage(VIEW_MSG_SET_GRAY1ASRGB24));
558b98ef4f9SStephan Aßmus 	if (fSettings->SetGetBool(JPEG_SET_GRAY1_AS_RGB24))
559b98ef4f9SStephan Aßmus 		fGrayAsRGB24->SetValue(B_CONTROL_ON);
5609949213aSStephan Aßmus 
561b98ef4f9SStephan Aßmus 	float padding = 5.0f;
562b98ef4f9SStephan Aßmus 	AddChild(BGroupLayoutBuilder(B_VERTICAL, padding)
563b98ef4f9SStephan Aßmus 		.Add(fQualitySlider)
564b98ef4f9SStephan Aßmus 		.Add(fSmoothingSlider)
565b98ef4f9SStephan Aßmus 		.Add(fProgress)
566b98ef4f9SStephan Aßmus 		.Add(fOptimizeColors)
567b98ef4f9SStephan Aßmus 		.Add(fSmallerFile)
568b98ef4f9SStephan Aßmus 		.Add(fGrayAsRGB24)
569b98ef4f9SStephan Aßmus 		.AddGlue()
570b98ef4f9SStephan Aßmus 		.SetInsets(padding, padding, padding, padding)
571b98ef4f9SStephan Aßmus 	);
572b98ef4f9SStephan Aßmus }
5739949213aSStephan Aßmus 
574b98ef4f9SStephan Aßmus 
575b98ef4f9SStephan Aßmus TranslatorWriteView::~TranslatorWriteView()
576b98ef4f9SStephan Aßmus {
577b98ef4f9SStephan Aßmus 	fSettings->Release();
5789949213aSStephan Aßmus }
5799949213aSStephan Aßmus 
5808687ff64SAxel Dörfler 
5819949213aSStephan Aßmus void
5829949213aSStephan Aßmus TranslatorWriteView::AttachedToWindow()
5839949213aSStephan Aßmus {
584b98ef4f9SStephan Aßmus 	BView::AttachedToWindow();
585b20d13f4SStefano Ceccherini 
5868687ff64SAxel Dörfler 	fQualitySlider->SetTarget(this);
5878687ff64SAxel Dörfler 	fSmoothingSlider->SetTarget(this);
5888687ff64SAxel Dörfler 	fProgress->SetTarget(this);
5898687ff64SAxel Dörfler 	fOptimizeColors->SetTarget(this);
5908687ff64SAxel Dörfler 	fSmallerFile->SetTarget(this);
5918687ff64SAxel Dörfler 	fGrayAsRGB24->SetTarget(this);
5929949213aSStephan Aßmus }
5939949213aSStephan Aßmus 
5948687ff64SAxel Dörfler 
5959949213aSStephan Aßmus void
5969949213aSStephan Aßmus TranslatorWriteView::MessageReceived(BMessage* message)
5979949213aSStephan Aßmus {
5988687ff64SAxel Dörfler 	switch (message->what) {
5999949213aSStephan Aßmus 		case VIEW_MSG_SET_QUALITY:
6009949213aSStephan Aßmus 		{
6019949213aSStephan Aßmus 			int32 value;
6029949213aSStephan Aßmus 			if (message->FindInt32("be:value", &value) == B_OK) {
603b98ef4f9SStephan Aßmus 				fSettings->SetGetInt32(JPEG_SET_QUALITY, &value);
604b98ef4f9SStephan Aßmus 				fSettings->SaveSettings();
6059949213aSStephan Aßmus 			}
6069949213aSStephan Aßmus 			break;
6079949213aSStephan Aßmus 		}
6089949213aSStephan Aßmus 		case VIEW_MSG_SET_SMOOTHING:
6099949213aSStephan Aßmus 		{
6109949213aSStephan Aßmus 			int32 value;
6119949213aSStephan Aßmus 			if (message->FindInt32("be:value", &value) == B_OK) {
612b98ef4f9SStephan Aßmus 				fSettings->SetGetInt32(JPEG_SET_SMOOTHING, &value);
613b98ef4f9SStephan Aßmus 				fSettings->SaveSettings();
6149949213aSStephan Aßmus 			}
6159949213aSStephan Aßmus 			break;
6169949213aSStephan Aßmus 		}
6179949213aSStephan Aßmus 		case VIEW_MSG_SET_PROGRESSIVE:
6189949213aSStephan Aßmus 		{
6199949213aSStephan Aßmus 			int32 value;
6209949213aSStephan Aßmus 			if (message->FindInt32("be:value", &value) == B_OK) {
621b98ef4f9SStephan Aßmus 				bool boolValue = value;
622b98ef4f9SStephan Aßmus 				fSettings->SetGetBool(JPEG_SET_PROGRESSIVE, &boolValue);
623b98ef4f9SStephan Aßmus 				fSettings->SaveSettings();
6249949213aSStephan Aßmus 			}
6259949213aSStephan Aßmus 			break;
6269949213aSStephan Aßmus 		}
6279949213aSStephan Aßmus 		case VIEW_MSG_SET_OPTIMIZECOLORS:
6289949213aSStephan Aßmus 		{
6299949213aSStephan Aßmus 			int32 value;
6309949213aSStephan Aßmus 			if (message->FindInt32("be:value", &value) == B_OK) {
631b98ef4f9SStephan Aßmus 				bool boolValue = value;
632b98ef4f9SStephan Aßmus 				fSettings->SetGetBool(JPEG_SET_OPT_COLORS, &boolValue);
633b98ef4f9SStephan Aßmus 				fSmallerFile->SetEnabled(value);
634b98ef4f9SStephan Aßmus 				fSettings->SaveSettings();
6359949213aSStephan Aßmus 			}
6369949213aSStephan Aßmus 			break;
6379949213aSStephan Aßmus 		}
6389949213aSStephan Aßmus 		case VIEW_MSG_SET_SMALLERFILE:
6399949213aSStephan Aßmus 		{
6409949213aSStephan Aßmus 			int32 value;
6419949213aSStephan Aßmus 			if (message->FindInt32("be:value", &value) == B_OK) {
642b98ef4f9SStephan Aßmus 				bool boolValue = value;
643b98ef4f9SStephan Aßmus 				fSettings->SetGetBool(JPEG_SET_SMALL_FILES, &boolValue);
644b98ef4f9SStephan Aßmus 				fSettings->SaveSettings();
6459949213aSStephan Aßmus 			}
6469949213aSStephan Aßmus 			break;
6479949213aSStephan Aßmus 		}
6489949213aSStephan Aßmus 		case VIEW_MSG_SET_GRAY1ASRGB24:
6499949213aSStephan Aßmus 		{
6509949213aSStephan Aßmus 			int32 value;
6519949213aSStephan Aßmus 			if (message->FindInt32("be:value", &value) == B_OK) {
652b98ef4f9SStephan Aßmus 				bool boolValue = value;
653b98ef4f9SStephan Aßmus 				fSettings->SetGetBool(JPEG_SET_GRAY1_AS_RGB24, &boolValue);
654b98ef4f9SStephan Aßmus 				fSettings->SaveSettings();
6559949213aSStephan Aßmus 			}
6569949213aSStephan Aßmus 			break;
6579949213aSStephan Aßmus 		}
6589949213aSStephan Aßmus 		default:
6599949213aSStephan Aßmus 			BView::MessageReceived(message);
6609949213aSStephan Aßmus 			break;
6619949213aSStephan Aßmus 	}
6629949213aSStephan Aßmus }
6639949213aSStephan Aßmus 
6649949213aSStephan Aßmus 
665d8e2fb50SAxel Dörfler //	#pragma mark -
6669949213aSStephan Aßmus 
667d8e2fb50SAxel Dörfler 
668b98ef4f9SStephan Aßmus TranslatorAboutView::TranslatorAboutView(const char* name)
669b98ef4f9SStephan Aßmus 	:
670b98ef4f9SStephan Aßmus 	BView(name, 0, new BGroupLayout(B_VERTICAL))
6719949213aSStephan Aßmus {
672b98ef4f9SStephan Aßmus 	BAlignment labelAlignment = BAlignment(B_ALIGN_LEFT, B_ALIGN_TOP);
673*1da233a7SSiarzhuk Zharski 	BStringView* title = new BStringView("Title", sTranslatorName);
6749949213aSStephan Aßmus 	title->SetFont(be_bold_font);
675b98ef4f9SStephan Aßmus 	title->SetExplicitAlignment(labelAlignment);
6769949213aSStephan Aßmus 
6779949213aSStephan Aßmus 	char versionString[16];
678bf243977SPhilippe Houdoin 	sprintf(versionString, "v%d.%d.%d", (int)(sTranslatorVersion >> 8),
679bf243977SPhilippe Houdoin 		(int)((sTranslatorVersion >> 4) & 0xf), (int)(sTranslatorVersion & 0xf));
6809949213aSStephan Aßmus 
681b98ef4f9SStephan Aßmus 	BStringView* version = new BStringView("Version", versionString);
682b98ef4f9SStephan Aßmus 	version->SetExplicitAlignment(labelAlignment);
6839949213aSStephan Aßmus 
684b98ef4f9SStephan Aßmus 	BTextView* infoView = new BTextView("info");
6852e49ff35SSiarzhuk Zharski 	infoView->SetText(sTranslatorInfo);
686b98ef4f9SStephan Aßmus 	infoView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
687b98ef4f9SStephan Aßmus 	infoView->MakeEditable(false);
6889949213aSStephan Aßmus 
689b98ef4f9SStephan Aßmus 	float padding = 5.0f;
690b98ef4f9SStephan Aßmus 	AddChild(BGroupLayoutBuilder(B_VERTICAL, padding)
691b98ef4f9SStephan Aßmus 		.Add(BGroupLayoutBuilder(B_HORIZONTAL, padding)
692b98ef4f9SStephan Aßmus 			.Add(title)
693b98ef4f9SStephan Aßmus 			.Add(version)
694b98ef4f9SStephan Aßmus 			.AddGlue()
695b98ef4f9SStephan Aßmus 		)
696b98ef4f9SStephan Aßmus 		.Add(infoView)
697b98ef4f9SStephan Aßmus 		.SetInsets(padding, padding, padding, padding)
698b98ef4f9SStephan Aßmus 	);
6999949213aSStephan Aßmus }
7009949213aSStephan Aßmus 
7019949213aSStephan Aßmus 
702b98ef4f9SStephan Aßmus TranslatorView::TranslatorView(const char* name, TranslatorSettings* settings)
703b98ef4f9SStephan Aßmus 	:
704b98ef4f9SStephan Aßmus 	BTabView(name)
7059949213aSStephan Aßmus {
70670d59669SSiarzhuk Zharski 	AddTab(new TranslatorWriteView(B_TRANSLATE("Write"), settings->Acquire()));
70770d59669SSiarzhuk Zharski 	AddTab(new TranslatorReadView(B_TRANSLATE("Read"), settings->Acquire()));
70870d59669SSiarzhuk Zharski 	AddTab(new TranslatorAboutView(B_TRANSLATE("About")));
7099949213aSStephan Aßmus 
710b98ef4f9SStephan Aßmus 	settings->Release();
7119949213aSStephan Aßmus 
712b98ef4f9SStephan Aßmus  	BFont font;
713b98ef4f9SStephan Aßmus  	GetFont(&font);
714b98ef4f9SStephan Aßmus  	SetExplicitPreferredSize(
715b98ef4f9SStephan Aßmus 		BSize((font.Size() * 380) / 12, (font.Size() * 250) / 12));
7169949213aSStephan Aßmus }
7179949213aSStephan Aßmus 
7189949213aSStephan Aßmus 
719d8e2fb50SAxel Dörfler //	#pragma mark - Translator Add-On
7209949213aSStephan Aßmus 
7219949213aSStephan Aßmus 
722b98ef4f9SStephan Aßmus BView*
723b98ef4f9SStephan Aßmus JPEGTranslator::NewConfigView(TranslatorSettings* settings)
7249949213aSStephan Aßmus {
725b98ef4f9SStephan Aßmus 	BView* configView = new TranslatorView("TranslatorView", settings);
726b98ef4f9SStephan Aßmus 	return configView;
7279949213aSStephan Aßmus }
7289949213aSStephan Aßmus 
729b98ef4f9SStephan Aßmus 
730d8e2fb50SAxel Dörfler /*! Determine whether or not we can handle this data */
7319949213aSStephan Aßmus status_t
732b98ef4f9SStephan Aßmus JPEGTranslator::DerivedIdentify(BPositionIO* inSource,
733b98ef4f9SStephan Aßmus 	const translation_format* inFormat, BMessage* ioExtension,
734b98ef4f9SStephan Aßmus 	translator_info* outInfo, uint32 outType)
7359949213aSStephan Aßmus {
736d8e2fb50SAxel Dörfler 	if (outType != 0 && outType != B_TRANSLATOR_BITMAP && outType != JPEG_FORMAT)
7379949213aSStephan Aßmus 		return B_NO_TRANSLATOR;
7389949213aSStephan Aßmus 
7399949213aSStephan Aßmus 	// !!! You might need to make this buffer bigger to test for your native format
7409949213aSStephan Aßmus 	off_t position = inSource->Position();
7419949213aSStephan Aßmus 	char header[sizeof(TranslatorBitmap)];
7429949213aSStephan Aßmus 	status_t err = inSource->Read(header, sizeof(TranslatorBitmap));
7439949213aSStephan Aßmus 	inSource->Seek(position, SEEK_SET);
744d8e2fb50SAxel Dörfler 	if (err < B_OK)
745d8e2fb50SAxel Dörfler 		return err;
7469949213aSStephan Aßmus 
7479949213aSStephan Aßmus 	if (B_BENDIAN_TO_HOST_INT32(((TranslatorBitmap *)header)->magic) == B_TRANSLATOR_BITMAP) {
748b98ef4f9SStephan Aßmus 		if (PopulateInfoFromFormat(outInfo, B_TRANSLATOR_BITMAP) != B_OK)
749b98ef4f9SStephan Aßmus 			return B_NO_TRANSLATOR;
7509949213aSStephan Aßmus 	} else {
7519949213aSStephan Aßmus 		// First 3 bytes in jpg files are always the same from what i've seen so far
7529949213aSStephan Aßmus 		// check them
7539949213aSStephan Aßmus 		if (header[0] == (char)0xff && header[1] == (char)0xd8 && header[2] == (char)0xff) {
754b98ef4f9SStephan Aßmus 			if (PopulateInfoFromFormat(outInfo, JPEG_FORMAT) != B_OK)
7559949213aSStephan Aßmus 				return B_NO_TRANSLATOR;
756b98ef4f9SStephan Aßmus 
7579949213aSStephan Aßmus 		} else
7589949213aSStephan Aßmus 			return B_NO_TRANSLATOR;
7599949213aSStephan Aßmus 	}
7609949213aSStephan Aßmus 
7619949213aSStephan Aßmus 	return B_OK;
7629949213aSStephan Aßmus }
7639949213aSStephan Aßmus 
764b98ef4f9SStephan Aßmus 
7659949213aSStephan Aßmus status_t
766b98ef4f9SStephan Aßmus JPEGTranslator::DerivedTranslate(BPositionIO* inSource,
767b98ef4f9SStephan Aßmus 	const translator_info* inInfo, BMessage* ioExtension, uint32 outType,
768b98ef4f9SStephan Aßmus 	BPositionIO* outDestination, int32 baseType)
7699949213aSStephan Aßmus {
7709949213aSStephan Aßmus 	// If no specific type was requested, convert to the interchange format
771dbc936acSStephan Aßmus 	if (outType == 0)
772dbc936acSStephan Aßmus 		outType = B_TRANSLATOR_BITMAP;
7739949213aSStephan Aßmus 
774dbc936acSStephan Aßmus 	// Setup a "breakpoint" since throwing exceptions does not seem to work
775dbc936acSStephan Aßmus 	// at all in an add-on. (?)
776dbc936acSStephan Aßmus 	// In the be_jerror.cpp we implement a handler for critical library errors
777dbc936acSStephan Aßmus 	// (be_error_exit()) and there we use the longjmp() function to return to
778dbc936acSStephan Aßmus 	// this place. If this happens, it is as if the setjmp() call is called
779dbc936acSStephan Aßmus 	// a second time, but this time the return value will be 1. The first
780dbc936acSStephan Aßmus 	// invokation will return 0.
781b91634cbSStephan Aßmus 	jmp_buf longJumpBuffer;
782b91634cbSStephan Aßmus 	int jmpRet = setjmp(longJumpBuffer);
783dbc936acSStephan Aßmus 	if (jmpRet == 1)
784dbc936acSStephan Aßmus 		return B_ERROR;
785dbc936acSStephan Aßmus 
786dbc936acSStephan Aßmus 	try {
7879949213aSStephan Aßmus 		// What action to take, based on the findings of Identify()
7889949213aSStephan Aßmus 		if (outType == inInfo->type) {
7899949213aSStephan Aßmus 			return Copy(inSource, outDestination);
790dbc936acSStephan Aßmus 		} else if (inInfo->type == B_TRANSLATOR_BITMAP
791dbc936acSStephan Aßmus 				&& outType == JPEG_FORMAT) {
792b91634cbSStephan Aßmus 			return Compress(inSource, outDestination, &longJumpBuffer);
793dbc936acSStephan Aßmus 		} else if (inInfo->type == JPEG_FORMAT
794dbc936acSStephan Aßmus 				&& outType == B_TRANSLATOR_BITMAP) {
795b91634cbSStephan Aßmus 			return Decompress(inSource, outDestination, ioExtension,
796b91634cbSStephan Aßmus 				&longJumpBuffer);
7979949213aSStephan Aßmus 		}
798dbc936acSStephan Aßmus 	} catch (...) {
79970d59669SSiarzhuk Zharski 		syslog(LOG_ERR, "libjpeg encountered a critical error (caught C++ "
80070d59669SSiarzhuk Zharski 			"exception).\n");
801dbc936acSStephan Aßmus 		return B_ERROR;
802dbc936acSStephan Aßmus 	}
8039949213aSStephan Aßmus 
8049949213aSStephan Aßmus 	return B_NO_TRANSLATOR;
8059949213aSStephan Aßmus }
8069949213aSStephan Aßmus 
807b98ef4f9SStephan Aßmus 
808d8e2fb50SAxel Dörfler /*!	The user has requested the same format for input and output, so just copy */
809b98ef4f9SStephan Aßmus status_t
810b98ef4f9SStephan Aßmus JPEGTranslator::Copy(BPositionIO* in, BPositionIO* out)
8119949213aSStephan Aßmus {
8129949213aSStephan Aßmus 	int block_size = 65536;
8139949213aSStephan Aßmus 	void* buffer = malloc(block_size);
8149949213aSStephan Aßmus 	char temp[1024];
8159949213aSStephan Aßmus 	if (buffer == NULL) {
8169949213aSStephan Aßmus 		buffer = temp;
8179949213aSStephan Aßmus 		block_size = 1024;
8189949213aSStephan Aßmus 	}
8199949213aSStephan Aßmus 	status_t err = B_OK;
8209949213aSStephan Aßmus 
8219949213aSStephan Aßmus 	// Read until end of file or error
8229949213aSStephan Aßmus 	while (1) {
8239949213aSStephan Aßmus 		ssize_t to_read = block_size;
8249949213aSStephan Aßmus 		err = in->Read(buffer, to_read);
8259949213aSStephan Aßmus 		// Explicit check for EOF
8269949213aSStephan Aßmus 		if (err == -1) {
8279949213aSStephan Aßmus 			if (buffer != temp) free(buffer);
8289949213aSStephan Aßmus 			return B_OK;
8299949213aSStephan Aßmus 		}
8309949213aSStephan Aßmus 		if (err <= B_OK) break;
8319949213aSStephan Aßmus 		to_read = err;
8329949213aSStephan Aßmus 		err = out->Write(buffer, to_read);
8339949213aSStephan Aßmus 		if (err != to_read) if (err >= 0) err = B_DEVICE_FULL;
8349949213aSStephan Aßmus 		if (err < B_OK) break;
8359949213aSStephan Aßmus 	}
8369949213aSStephan Aßmus 
8379949213aSStephan Aßmus 	if (buffer != temp) free(buffer);
8389949213aSStephan Aßmus 	return (err >= 0) ? B_OK : err;
8399949213aSStephan Aßmus }
8409949213aSStephan Aßmus 
841d8e2fb50SAxel Dörfler 
842d8e2fb50SAxel Dörfler /*!	Encode into the native format */
843b98ef4f9SStephan Aßmus status_t
844b98ef4f9SStephan Aßmus JPEGTranslator::Compress(BPositionIO* in, BPositionIO* out,
845b98ef4f9SStephan Aßmus 	const jmp_buf* longJumpBuffer)
8469949213aSStephan Aßmus {
847b98ef4f9SStephan Aßmus 	using namespace conversion;
8489949213aSStephan Aßmus 
8499949213aSStephan Aßmus 	// Read info about bitmap
8509949213aSStephan Aßmus 	TranslatorBitmap header;
8519949213aSStephan Aßmus 	status_t err = in->Read(&header, sizeof(TranslatorBitmap));
852d8e2fb50SAxel Dörfler 	if (err < B_OK)
853d8e2fb50SAxel Dörfler 		return err;
854d8e2fb50SAxel Dörfler 	else if (err < (int)sizeof(TranslatorBitmap))
855d8e2fb50SAxel Dörfler 		return B_ERROR;
8569949213aSStephan Aßmus 
8579949213aSStephan Aßmus 	// Grab dimension, color space, and size information from the stream
8589949213aSStephan Aßmus 	BRect bounds;
8599949213aSStephan Aßmus 	bounds.left = B_BENDIAN_TO_HOST_FLOAT(header.bounds.left);
8609949213aSStephan Aßmus 	bounds.top = B_BENDIAN_TO_HOST_FLOAT(header.bounds.top);
8619949213aSStephan Aßmus 	bounds.right = B_BENDIAN_TO_HOST_FLOAT(header.bounds.right);
8629949213aSStephan Aßmus 	bounds.bottom = B_BENDIAN_TO_HOST_FLOAT(header.bounds.bottom);
8639949213aSStephan Aßmus 
8649949213aSStephan Aßmus 	int32 in_row_bytes = B_BENDIAN_TO_HOST_INT32(header.rowBytes);
8659949213aSStephan Aßmus 
8669949213aSStephan Aßmus 	int width = bounds.IntegerWidth() + 1;
8679949213aSStephan Aßmus 	int height = bounds.IntegerHeight() + 1;
8689949213aSStephan Aßmus 
8699949213aSStephan Aßmus 	// Function pointer to convert function
8709949213aSStephan Aßmus 	// It will point to proper function if needed
8719e34f742SAxel Dörfler 	void (*converter)(uchar* inscanline, uchar* outscanline,
8729e34f742SAxel Dörfler 		int32 inRowBytes) = NULL;
8739949213aSStephan Aßmus 
8749949213aSStephan Aßmus 	// Default color info
8759949213aSStephan Aßmus 	J_COLOR_SPACE jpg_color_space = JCS_RGB;
8769949213aSStephan Aßmus 	int jpg_input_components = 3;
8779949213aSStephan Aßmus 	int32 out_row_bytes;
8789949213aSStephan Aßmus 	int padding = 0;
8799949213aSStephan Aßmus 
880d8e2fb50SAxel Dörfler 	switch ((color_space)B_BENDIAN_TO_HOST_INT32(header.colors)) {
8819949213aSStephan Aßmus 		case B_CMAP8:
8829949213aSStephan Aßmus 			converter = convert_from_cmap8_to_24;
8839949213aSStephan Aßmus 			padding = in_row_bytes - width;
8849949213aSStephan Aßmus 			break;
885d8e2fb50SAxel Dörfler 
8869949213aSStephan Aßmus 		case B_GRAY1:
887b98ef4f9SStephan Aßmus 			if (fSettings->SetGetBool(JPEG_SET_GRAY1_AS_RGB24, NULL)) {
8889949213aSStephan Aßmus 				converter = convert_from_gray1_to_24;
8899949213aSStephan Aßmus 			} else {
8909949213aSStephan Aßmus 				jpg_input_components = 1;
8919949213aSStephan Aßmus 				jpg_color_space = JCS_GRAYSCALE;
8929949213aSStephan Aßmus 				converter = convert_from_gray1_to_gray8;
8939949213aSStephan Aßmus 			}
8949949213aSStephan Aßmus 			padding = in_row_bytes - (width / 8);
8959949213aSStephan Aßmus 			break;
896d8e2fb50SAxel Dörfler 
8979949213aSStephan Aßmus 		case B_GRAY8:
8989949213aSStephan Aßmus 			jpg_input_components = 1;
8999949213aSStephan Aßmus 			jpg_color_space = JCS_GRAYSCALE;
9009949213aSStephan Aßmus 			padding = in_row_bytes - width;
9019949213aSStephan Aßmus 			break;
902d8e2fb50SAxel Dörfler 
9039949213aSStephan Aßmus 		case B_RGB15:
9049949213aSStephan Aßmus 		case B_RGBA15:
9059949213aSStephan Aßmus 			converter = convert_from_15_to_24;
9069949213aSStephan Aßmus 			padding = in_row_bytes - (width * 2);
9079949213aSStephan Aßmus 			break;
908d8e2fb50SAxel Dörfler 
9099949213aSStephan Aßmus 		case B_RGB15_BIG:
9109949213aSStephan Aßmus 		case B_RGBA15_BIG:
9119949213aSStephan Aßmus 			converter = convert_from_15b_to_24;
9129949213aSStephan Aßmus 			padding = in_row_bytes - (width * 2);
9139949213aSStephan Aßmus 			break;
914d8e2fb50SAxel Dörfler 
9159949213aSStephan Aßmus 		case B_RGB16:
9169949213aSStephan Aßmus 			converter = convert_from_16_to_24;
9179949213aSStephan Aßmus 			padding = in_row_bytes - (width * 2);
9189949213aSStephan Aßmus 			break;
919d8e2fb50SAxel Dörfler 
9209949213aSStephan Aßmus 		case B_RGB16_BIG:
9219949213aSStephan Aßmus 			converter = convert_from_16b_to_24;
9229949213aSStephan Aßmus 			padding = in_row_bytes - (width * 2);
9239949213aSStephan Aßmus 			break;
924d8e2fb50SAxel Dörfler 
9259949213aSStephan Aßmus 		case B_RGB24:
9269949213aSStephan Aßmus 			converter = convert_from_24_to_24;
9279949213aSStephan Aßmus 			padding = in_row_bytes - (width * 3);
9289949213aSStephan Aßmus 			break;
929d8e2fb50SAxel Dörfler 
9309949213aSStephan Aßmus 		case B_RGB24_BIG:
9319949213aSStephan Aßmus 			padding = in_row_bytes - (width * 3);
9329949213aSStephan Aßmus 			break;
933d8e2fb50SAxel Dörfler 
9349949213aSStephan Aßmus 		case B_RGB32:
9359949213aSStephan Aßmus 		case B_RGBA32:
9369949213aSStephan Aßmus 			converter = convert_from_32_to_24;
9379949213aSStephan Aßmus 			padding = in_row_bytes - (width * 4);
9389949213aSStephan Aßmus 			break;
939d8e2fb50SAxel Dörfler 
9409949213aSStephan Aßmus 		case B_RGB32_BIG:
9419949213aSStephan Aßmus 		case B_RGBA32_BIG:
9429949213aSStephan Aßmus 			converter = convert_from_32b_to_24;
9439949213aSStephan Aßmus 			padding = in_row_bytes - (width * 4);
9449949213aSStephan Aßmus 			break;
945d8e2fb50SAxel Dörfler 
9469949213aSStephan Aßmus 		case B_CMYK32:
9479949213aSStephan Aßmus 			jpg_color_space = JCS_CMYK;
9489949213aSStephan Aßmus 			jpg_input_components = 4;
9499949213aSStephan Aßmus 			padding = in_row_bytes - (width * 4);
9509949213aSStephan Aßmus 			break;
951d8e2fb50SAxel Dörfler 
9529949213aSStephan Aßmus 		default:
95370d59669SSiarzhuk Zharski 			syslog(LOG_ERR, "Wrong type: Color space not implemented.\n");
9549949213aSStephan Aßmus 			return B_ERROR;
9559949213aSStephan Aßmus 	}
9569949213aSStephan Aßmus 	out_row_bytes = jpg_input_components * width;
9579949213aSStephan Aßmus 
9589949213aSStephan Aßmus 	// Set basic things needed for jpeg writing
9599949213aSStephan Aßmus 	struct jpeg_compress_struct cinfo;
9609949213aSStephan Aßmus 	struct jpeg_error_mgr jerr;
961b98ef4f9SStephan Aßmus 	cinfo.err = be_jpeg_std_error(&jerr, fSettings, longJumpBuffer);
9629949213aSStephan Aßmus 	jpeg_create_compress(&cinfo);
9639949213aSStephan Aßmus 	be_jpeg_stdio_dest(&cinfo, out);
9649949213aSStephan Aßmus 
9659949213aSStephan Aßmus 	// Set basic values
9669949213aSStephan Aßmus 	cinfo.image_width = width;
9679949213aSStephan Aßmus 	cinfo.image_height = height;
9689949213aSStephan Aßmus 	cinfo.input_components = jpg_input_components;
9699949213aSStephan Aßmus 	cinfo.in_color_space = jpg_color_space;
9709949213aSStephan Aßmus 	jpeg_set_defaults(&cinfo);
9719949213aSStephan Aßmus 
9729949213aSStephan Aßmus 	// Set better accuracy
9739949213aSStephan Aßmus 	cinfo.dct_method = JDCT_ISLOW;
9749949213aSStephan Aßmus 
9759949213aSStephan Aßmus 	// This is needed to prevent some colors loss
9769949213aSStephan Aßmus 	// With it generated jpegs are as good as from Fireworks (at last! :D)
977b98ef4f9SStephan Aßmus 	if (fSettings->SetGetBool(JPEG_SET_OPT_COLORS, NULL)) {
9789949213aSStephan Aßmus 		int index = 0;
9799949213aSStephan Aßmus 		while (index < cinfo.num_components) {
9809949213aSStephan Aßmus 			cinfo.comp_info[index].h_samp_factor = 1;
9819949213aSStephan Aßmus 			cinfo.comp_info[index].v_samp_factor = 1;
9829949213aSStephan Aßmus 			// This will make file smaller, but with worse quality more or less
9839949213aSStephan Aßmus 			// like with 93%-94% (but it's subjective opinion) on tested images
9849949213aSStephan Aßmus 			// but with smaller size (between 92% and 93% on tested images)
985b98ef4f9SStephan Aßmus 			if (fSettings->SetGetBool(JPEG_SET_SMALL_FILES))
9869949213aSStephan Aßmus 				cinfo.comp_info[index].quant_tbl_no = 1;
9879949213aSStephan Aßmus 			// This will make bigger file, but also better quality ;]
9889949213aSStephan Aßmus 			// from my tests it seems like useless - better quality with smaller
9899949213aSStephan Aßmus 			// can be acheived without this
9909949213aSStephan Aßmus //			cinfo.comp_info[index].dc_tbl_no = 1;
9919949213aSStephan Aßmus //			cinfo.comp_info[index].ac_tbl_no = 1;
9929949213aSStephan Aßmus 			index++;
9939949213aSStephan Aßmus 		}
9949949213aSStephan Aßmus 	}
9959949213aSStephan Aßmus 
9969949213aSStephan Aßmus 	// Set quality
997b98ef4f9SStephan Aßmus 	jpeg_set_quality(&cinfo, fSettings->SetGetInt32(JPEG_SET_QUALITY, NULL), true);
9989949213aSStephan Aßmus 
9999949213aSStephan Aßmus 	// Set progressive compression if needed
10009949213aSStephan Aßmus 	// if not, turn on optimizing in libjpeg
1001b98ef4f9SStephan Aßmus 	if (fSettings->SetGetBool(JPEG_SET_PROGRESSIVE, NULL))
10029949213aSStephan Aßmus 		jpeg_simple_progression(&cinfo);
10039949213aSStephan Aßmus 	else
10049949213aSStephan Aßmus 		cinfo.optimize_coding = TRUE;
10059949213aSStephan Aßmus 
10069949213aSStephan Aßmus 	// Set smoothing (effect like Blur)
1007b98ef4f9SStephan Aßmus 	cinfo.smoothing_factor = fSettings->SetGetInt32(JPEG_SET_SMOOTHING, NULL);
10089949213aSStephan Aßmus 
10099949213aSStephan Aßmus 	// Initialize compression
10109949213aSStephan Aßmus 	jpeg_start_compress(&cinfo, TRUE);
10119949213aSStephan Aßmus 
10129949213aSStephan Aßmus 	// Declare scanlines
10139949213aSStephan Aßmus 	JSAMPROW in_scanline = NULL;
10149949213aSStephan Aßmus 	JSAMPROW out_scanline = NULL;
1015b98ef4f9SStephan Aßmus 	JSAMPROW writeline;
1016b98ef4f9SStephan Aßmus 		// Pointer to in_scanline (default) or out_scanline (if there will be conversion)
10179949213aSStephan Aßmus 
10189949213aSStephan Aßmus 	// Allocate scanline
10199949213aSStephan Aßmus 	// Use libjpeg memory allocation functions, so in case of error it will free them itself
1020d8e2fb50SAxel Dörfler 	in_scanline = (unsigned char *)(cinfo.mem->alloc_large)((j_common_ptr)&cinfo,
1021d8e2fb50SAxel Dörfler 		JPOOL_PERMANENT, in_row_bytes);
10229949213aSStephan Aßmus 
10239949213aSStephan Aßmus 	// We need 2nd scanline storage ony for conversion
10249949213aSStephan Aßmus 	if (converter != NULL) {
10259949213aSStephan Aßmus 		// There will be conversion, allocate second scanline...
10269949213aSStephan Aßmus 		// Use libjpeg memory allocation functions, so in case of error it will free them itself
1027d8e2fb50SAxel Dörfler 	    out_scanline = (unsigned char *)(cinfo.mem->alloc_large)((j_common_ptr)&cinfo,
1028d8e2fb50SAxel Dörfler 	    	JPOOL_PERMANENT, out_row_bytes);
10299949213aSStephan Aßmus 		// ... and make it the one to write to file
10309949213aSStephan Aßmus 		writeline = out_scanline;
10319949213aSStephan Aßmus 	} else
10329949213aSStephan Aßmus 		writeline = in_scanline;
10339949213aSStephan Aßmus 
10349949213aSStephan Aßmus 	while (cinfo.next_scanline < cinfo.image_height) {
10359949213aSStephan Aßmus 		// Read scanline
10369949213aSStephan Aßmus 		err = in->Read(in_scanline, in_row_bytes);
10379949213aSStephan Aßmus 		if (err < in_row_bytes)
1038d8e2fb50SAxel Dörfler 			return err < B_OK ? Error((j_common_ptr)&cinfo, err)
1039d8e2fb50SAxel Dörfler 				: Error((j_common_ptr)&cinfo, B_ERROR);
10409949213aSStephan Aßmus 
10419949213aSStephan Aßmus 		// Convert if needed
10429949213aSStephan Aßmus 		if (converter != NULL)
10439949213aSStephan Aßmus 			converter(in_scanline, out_scanline, in_row_bytes - padding);
10449949213aSStephan Aßmus 
10459949213aSStephan Aßmus 		// Write scanline
10469949213aSStephan Aßmus 	   	jpeg_write_scanlines(&cinfo, &writeline, 1);
10479949213aSStephan Aßmus 	}
10489949213aSStephan Aßmus 
10499949213aSStephan Aßmus 	jpeg_finish_compress(&cinfo);
10509949213aSStephan Aßmus 	jpeg_destroy_compress(&cinfo);
10519949213aSStephan Aßmus 	return B_OK;
10529949213aSStephan Aßmus }
10539949213aSStephan Aßmus 
1054d8e2fb50SAxel Dörfler 
1055d8e2fb50SAxel Dörfler /*!	Decode the native format */
1056b98ef4f9SStephan Aßmus status_t
1057b98ef4f9SStephan Aßmus JPEGTranslator::Decompress(BPositionIO* in, BPositionIO* out,
1058b98ef4f9SStephan Aßmus 	BMessage* ioExtension, const jmp_buf* longJumpBuffer)
10599949213aSStephan Aßmus {
1060b98ef4f9SStephan Aßmus 	using namespace conversion;
10619949213aSStephan Aßmus 
10629949213aSStephan Aßmus 	// Set basic things needed for jpeg reading
10639949213aSStephan Aßmus 	struct jpeg_decompress_struct cinfo;
10649949213aSStephan Aßmus 	struct jpeg_error_mgr jerr;
1065b98ef4f9SStephan Aßmus 	cinfo.err = be_jpeg_std_error(&jerr, fSettings, longJumpBuffer);
10669949213aSStephan Aßmus 	jpeg_create_decompress(&cinfo);
10679949213aSStephan Aßmus 	be_jpeg_stdio_src(&cinfo, in);
10689949213aSStephan Aßmus 
106952e8f46aSAxel Dörfler 	jpeg_save_markers(&cinfo, MARKER_EXIF, 131072);
107052e8f46aSAxel Dörfler 		// make sure the EXIF tag is stored
107152e8f46aSAxel Dörfler 
10729949213aSStephan Aßmus 	// Read info about image
10739949213aSStephan Aßmus 	jpeg_read_header(&cinfo, TRUE);
10749949213aSStephan Aßmus 
107552e8f46aSAxel Dörfler 	BMessage exif;
107652e8f46aSAxel Dörfler 
1077f13b5de6SAxel Dörfler 	// parse EXIF data and add it ioExtension, if any
107852e8f46aSAxel Dörfler 	jpeg_marker_struct* marker = cinfo.marker_list;
107952e8f46aSAxel Dörfler 	while (marker != NULL) {
108052e8f46aSAxel Dörfler 		if (marker->marker == MARKER_EXIF
108152e8f46aSAxel Dörfler 			&& !strncmp((char*)marker->data, "Exif", 4)) {
1082f13b5de6SAxel Dörfler 			if (ioExtension != NULL) {
108352e8f46aSAxel Dörfler 				// Strip EXIF header from TIFF data
108452e8f46aSAxel Dörfler 				ioExtension->AddData("exif", B_RAW_TYPE,
108552e8f46aSAxel Dörfler 					(uint8*)marker->data + 6, marker->data_length - 6);
1086f13b5de6SAxel Dörfler 			}
108752e8f46aSAxel Dörfler 
108852e8f46aSAxel Dörfler 			BMemoryIO io(marker->data + 6, marker->data_length - 6);
108952e8f46aSAxel Dörfler 			convert_exif_to_message(io, exif);
109052e8f46aSAxel Dörfler 		}
109152e8f46aSAxel Dörfler 		marker = marker->next;
109252e8f46aSAxel Dörfler 	}
109352e8f46aSAxel Dörfler 
10949949213aSStephan Aßmus 	// Default color info
109552e8f46aSAxel Dörfler 	color_space outColorSpace = B_RGB32;
109652e8f46aSAxel Dörfler 	int outColorComponents = 4;
10979949213aSStephan Aßmus 
10989949213aSStephan Aßmus 	// Function pointer to convert function
10999949213aSStephan Aßmus 	// It will point to proper function if needed
110052e8f46aSAxel Dörfler 	void (*converter)(uchar* inScanLine, uchar* outScanLine,
11019e34f742SAxel Dörfler 		int32 inRowBytes, int32 xStep) = convert_from_24_to_32;
11029949213aSStephan Aßmus 
11039949213aSStephan Aßmus 	// If color space isn't rgb
11049949213aSStephan Aßmus 	if (cinfo.out_color_space != JCS_RGB) {
1105d8e2fb50SAxel Dörfler 		switch (cinfo.out_color_space) {
11069949213aSStephan Aßmus 			case JCS_UNKNOWN:		/* error/unspecified */
110770d59669SSiarzhuk Zharski 				syslog(LOG_ERR, "From Type: Jpeg uses unknown color type\n");
11089949213aSStephan Aßmus 				break;
11099949213aSStephan Aßmus 			case JCS_GRAYSCALE:		/* monochrome */
11109949213aSStephan Aßmus 				// Check if user wants to read only as RGB32 or not
1111b98ef4f9SStephan Aßmus 				if (!fSettings->SetGetBool(JPEG_SET_ALWAYS_RGB32, NULL)) {
11129949213aSStephan Aßmus 					// Grayscale
111352e8f46aSAxel Dörfler 					outColorSpace = B_GRAY8;
111452e8f46aSAxel Dörfler 					outColorComponents = 1;
11159e34f742SAxel Dörfler 					converter = translate_8;
11169949213aSStephan Aßmus 				} else {
11179949213aSStephan Aßmus 					// RGB
11189949213aSStephan Aßmus 					cinfo.out_color_space = JCS_RGB;
11199949213aSStephan Aßmus 					cinfo.output_components = 3;
11209949213aSStephan Aßmus 					converter = convert_from_24_to_32;
11219949213aSStephan Aßmus 				}
11229949213aSStephan Aßmus 				break;
11239949213aSStephan Aßmus 			case JCS_YCbCr:		/* Y/Cb/Cr (also known as YUV) */
11249949213aSStephan Aßmus 				cinfo.out_color_space = JCS_RGB;
11259949213aSStephan Aßmus 				converter = convert_from_24_to_32;
11269949213aSStephan Aßmus 				break;
11279949213aSStephan Aßmus 			case JCS_YCCK:		/* Y/Cb/Cr/K */
11289949213aSStephan Aßmus 				// Let libjpeg convert it to CMYK
11299949213aSStephan Aßmus 				cinfo.out_color_space = JCS_CMYK;
11309949213aSStephan Aßmus 				// Fall through to CMYK since we need the same settings
11319949213aSStephan Aßmus 			case JCS_CMYK:		/* C/M/Y/K */
11329949213aSStephan Aßmus 				// Use proper converter
1133b98ef4f9SStephan Aßmus 				if (fSettings->SetGetBool(JPEG_SET_PHOTOSHOP_CMYK))
11349949213aSStephan Aßmus 					converter = convert_from_CMYK_to_32_photoshop;
11359949213aSStephan Aßmus 				else
11369949213aSStephan Aßmus 					converter = convert_from_CMYK_to_32;
11379949213aSStephan Aßmus 				break;
11389949213aSStephan Aßmus 			default:
113970d59669SSiarzhuk Zharski 				syslog(LOG_ERR,
114070d59669SSiarzhuk Zharski 						"From Type: Jpeg uses hmm... i don't know really :(\n");
11419949213aSStephan Aßmus 				break;
11429949213aSStephan Aßmus 		}
11439949213aSStephan Aßmus 	}
11449949213aSStephan Aßmus 
11459949213aSStephan Aßmus 	// Initialize decompression
11469949213aSStephan Aßmus 	jpeg_start_decompress(&cinfo);
11479949213aSStephan Aßmus 
11489e34f742SAxel Dörfler 	// retrieve orientation from settings/EXIF
114952e8f46aSAxel Dörfler 	int32 orientation;
11509e34f742SAxel Dörfler 	if (ioExtension == NULL
11519e34f742SAxel Dörfler 		|| ioExtension->FindInt32("exif:orientation", &orientation) != B_OK) {
115252e8f46aSAxel Dörfler 		if (exif.FindInt32("Orientation", &orientation) != B_OK)
115352e8f46aSAxel Dörfler 			orientation = 1;
115452e8f46aSAxel Dörfler 	}
11559949213aSStephan Aßmus 
11569e34f742SAxel Dörfler 	if (orientation != 1 && converter == NULL)
11579e34f742SAxel Dörfler 		converter = translate_8;
11589e34f742SAxel Dörfler 
11599e34f742SAxel Dörfler 	int32 outputWidth = orientation > 4 ? cinfo.output_height : cinfo.output_width;
11609e34f742SAxel Dörfler 	int32 outputHeight = orientation > 4 ? cinfo.output_width : cinfo.output_height;
11619e34f742SAxel Dörfler 
11629e34f742SAxel Dörfler 	int32 destOffset = dest_index(outputWidth, outputHeight,
11639e34f742SAxel Dörfler 		0, 0, orientation) * outColorComponents;
11649e34f742SAxel Dörfler 	int32 xStep = dest_index(outputWidth, outputHeight,
11659e34f742SAxel Dörfler 		1, 0, orientation) * outColorComponents - destOffset;
11669e34f742SAxel Dörfler 	int32 yStep = dest_index(outputWidth, outputHeight,
11679e34f742SAxel Dörfler 		0, 1, orientation) * outColorComponents - destOffset;
11689e34f742SAxel Dörfler 	bool needAll = orientation != 1;
11699e34f742SAxel Dörfler 
11709e34f742SAxel Dörfler 	// Initialize this bounds rect to the size of your image
11719e34f742SAxel Dörfler 	BRect bounds(0, 0, outputWidth - 1, outputHeight - 1);
11729e34f742SAxel Dörfler 
11739e34f742SAxel Dörfler #if 0
11749e34f742SAxel Dörfler printf("destOffset = %ld, xStep = %ld, yStep = %ld, input: %ld x %ld, output: %ld x %ld, orientation %ld\n",
11759e34f742SAxel Dörfler 	destOffset, xStep, yStep, (int32)cinfo.output_width, (int32)cinfo.output_height,
11769e34f742SAxel Dörfler 	bounds.IntegerWidth() + 1, bounds.IntegerHeight() + 1, orientation);
11779e34f742SAxel Dörfler #endif
11789e34f742SAxel Dörfler 
11799949213aSStephan Aßmus 	// Bytes count in one line of image (scanline)
11809e34f742SAxel Dörfler 	int32 inRowBytes = cinfo.output_width * cinfo.output_components;
11819e34f742SAxel Dörfler 	int32 rowBytes = (bounds.IntegerWidth() + 1) * outColorComponents;
11829e34f742SAxel Dörfler 	int32 dataSize = cinfo.output_width * cinfo.output_height
11839e34f742SAxel Dörfler 		* outColorComponents;
11849949213aSStephan Aßmus 
11859949213aSStephan Aßmus 	// Fill out the B_TRANSLATOR_BITMAP's header
11869949213aSStephan Aßmus 	TranslatorBitmap header;
11879949213aSStephan Aßmus 	header.magic = B_HOST_TO_BENDIAN_INT32(B_TRANSLATOR_BITMAP);
11889949213aSStephan Aßmus 	header.bounds.left = B_HOST_TO_BENDIAN_FLOAT(bounds.left);
11899949213aSStephan Aßmus 	header.bounds.top = B_HOST_TO_BENDIAN_FLOAT(bounds.top);
11909949213aSStephan Aßmus 	header.bounds.right = B_HOST_TO_BENDIAN_FLOAT(bounds.right);
11919949213aSStephan Aßmus 	header.bounds.bottom = B_HOST_TO_BENDIAN_FLOAT(bounds.bottom);
119252e8f46aSAxel Dörfler 	header.colors = (color_space)B_HOST_TO_BENDIAN_INT32(outColorSpace);
119352e8f46aSAxel Dörfler 	header.rowBytes = B_HOST_TO_BENDIAN_INT32(rowBytes);
11949e34f742SAxel Dörfler 	header.dataSize = B_HOST_TO_BENDIAN_INT32(dataSize);
11959949213aSStephan Aßmus 
11969949213aSStephan Aßmus 	// Write out the header
11979949213aSStephan Aßmus 	status_t err = out->Write(&header, sizeof(TranslatorBitmap));
1198d8e2fb50SAxel Dörfler 	if (err < B_OK)
1199d8e2fb50SAxel Dörfler 		return Error((j_common_ptr)&cinfo, err);
1200d8e2fb50SAxel Dörfler 	else if (err < (int)sizeof(TranslatorBitmap))
1201d8e2fb50SAxel Dörfler 		return Error((j_common_ptr)&cinfo, B_ERROR);
12029949213aSStephan Aßmus 
12039949213aSStephan Aßmus 	// Declare scanlines
12049e34f742SAxel Dörfler 	JSAMPROW inScanLine = NULL;
12059e34f742SAxel Dörfler 	uint8* dest = NULL;
12069e34f742SAxel Dörfler 	uint8* destLine = NULL;
12079949213aSStephan Aßmus 
12089949213aSStephan Aßmus 	// Allocate scanline
12099949213aSStephan Aßmus 	// Use libjpeg memory allocation functions, so in case of error it will free them itself
12109e34f742SAxel Dörfler     inScanLine = (unsigned char *)(cinfo.mem->alloc_large)((j_common_ptr)&cinfo,
12119e34f742SAxel Dörfler     	JPOOL_PERMANENT, inRowBytes);
12129949213aSStephan Aßmus 
12139949213aSStephan Aßmus 	// We need 2nd scanline storage only for conversion
12149949213aSStephan Aßmus 	if (converter != NULL) {
12159949213aSStephan Aßmus 		// There will be conversion, allocate second scanline...
1216b98ef4f9SStephan Aßmus 		// Use libjpeg memory allocation functions, so in case of error it will
1217b98ef4f9SStephan Aßmus 		// free them itself
12189e34f742SAxel Dörfler 	    dest = (uint8*)(cinfo.mem->alloc_large)((j_common_ptr)&cinfo,
12199e34f742SAxel Dörfler 	    	JPOOL_PERMANENT, needAll ? dataSize : rowBytes);
12209e34f742SAxel Dörfler 	    destLine = dest + destOffset;
12219949213aSStephan Aßmus 	} else
12229e34f742SAxel Dörfler 		destLine = inScanLine;
12239949213aSStephan Aßmus 
12249949213aSStephan Aßmus 	while (cinfo.output_scanline < cinfo.output_height) {
12259949213aSStephan Aßmus 		// Read scanline
12269e34f742SAxel Dörfler 		jpeg_read_scanlines(&cinfo, &inScanLine, 1);
12279949213aSStephan Aßmus 
12289949213aSStephan Aßmus 		// Convert if needed
12299949213aSStephan Aßmus 		if (converter != NULL)
12309e34f742SAxel Dörfler 			converter(inScanLine, destLine, inRowBytes, xStep);
12319949213aSStephan Aßmus 
12329e34f742SAxel Dörfler 		if (!needAll) {
12339949213aSStephan Aßmus 	  		// Write the scanline buffer to the output stream
12349e34f742SAxel Dörfler 			ssize_t bytesWritten = out->Write(destLine, rowBytes);
12359e34f742SAxel Dörfler 			if (bytesWritten < rowBytes) {
12369e34f742SAxel Dörfler 				return bytesWritten < B_OK
12379e34f742SAxel Dörfler 					? Error((j_common_ptr)&cinfo, bytesWritten)
1238d8e2fb50SAxel Dörfler 					: Error((j_common_ptr)&cinfo, B_ERROR);
12399949213aSStephan Aßmus 			}
12409e34f742SAxel Dörfler 		} else
12419e34f742SAxel Dörfler 			destLine += yStep;
12429e34f742SAxel Dörfler 	}
12439e34f742SAxel Dörfler 
12449e34f742SAxel Dörfler 	if (needAll) {
12459e34f742SAxel Dörfler 		ssize_t bytesWritten = out->Write(dest, dataSize);
12469e34f742SAxel Dörfler 		if (bytesWritten < dataSize) {
12479e34f742SAxel Dörfler 			return bytesWritten < B_OK
12489e34f742SAxel Dörfler 				? Error((j_common_ptr)&cinfo, bytesWritten)
12499e34f742SAxel Dörfler 				: Error((j_common_ptr)&cinfo, B_ERROR);
12509e34f742SAxel Dörfler 		}
12519e34f742SAxel Dörfler 	}
12529949213aSStephan Aßmus 
12539949213aSStephan Aßmus 	jpeg_finish_decompress(&cinfo);
12549949213aSStephan Aßmus 	jpeg_destroy_decompress(&cinfo);
12559949213aSStephan Aßmus 	return B_OK;
12569949213aSStephan Aßmus }
12579949213aSStephan Aßmus 
1258b98ef4f9SStephan Aßmus /*! have the other PopulateInfoFromFormat() check both inputFormats & outputFormats */
1259b98ef4f9SStephan Aßmus status_t
1260b98ef4f9SStephan Aßmus JPEGTranslator::PopulateInfoFromFormat(translator_info* info,
1261b98ef4f9SStephan Aßmus 	uint32 formatType, translator_id id)
1262b98ef4f9SStephan Aßmus {
1263b98ef4f9SStephan Aßmus 	int32 formatCount;
1264b98ef4f9SStephan Aßmus 	const translation_format* formats = OutputFormats(&formatCount);
1265b98ef4f9SStephan Aßmus 	for (int i = 0; i <= 1 ;formats = InputFormats(&formatCount), i++) {
1266b98ef4f9SStephan Aßmus 		if (PopulateInfoFromFormat(info, formatType,
1267b98ef4f9SStephan Aßmus 			formats, formatCount) == B_OK) {
1268b98ef4f9SStephan Aßmus 			info->translator = id;
1269b98ef4f9SStephan Aßmus 			return B_OK;
1270b98ef4f9SStephan Aßmus 		}
1271b98ef4f9SStephan Aßmus 	}
1272b98ef4f9SStephan Aßmus 
1273b98ef4f9SStephan Aßmus 	return B_ERROR;
1274b98ef4f9SStephan Aßmus }
1275b98ef4f9SStephan Aßmus 
1276b98ef4f9SStephan Aßmus 
1277b98ef4f9SStephan Aßmus status_t
1278b98ef4f9SStephan Aßmus JPEGTranslator::PopulateInfoFromFormat(translator_info* info,
1279b98ef4f9SStephan Aßmus 	uint32 formatType, const translation_format* formats, int32 formatCount)
1280b98ef4f9SStephan Aßmus {
1281b98ef4f9SStephan Aßmus 	for (int i = 0; i < formatCount; i++) {
1282b98ef4f9SStephan Aßmus 		if (formats[i].type == formatType) {
1283b98ef4f9SStephan Aßmus 			info->type = formatType;
1284b98ef4f9SStephan Aßmus 			info->group = formats[i].group;
1285b98ef4f9SStephan Aßmus 			info->quality = formats[i].quality;
1286b98ef4f9SStephan Aßmus 			info->capability = formats[i].capability;
128770d59669SSiarzhuk Zharski 			BString str1(formats[i].name);
128870d59669SSiarzhuk Zharski 			str1.ReplaceFirst("Be Bitmap Format (JPEGTranslator)",
128970d59669SSiarzhuk Zharski 				B_TRANSLATE("Be Bitmap Format (JPEGTranslator)"));
129070d59669SSiarzhuk Zharski 			strncpy(info->name, str1.String(), sizeof(info->name));
1291b98ef4f9SStephan Aßmus 			strcpy(info->MIME,  formats[i].MIME);
1292b98ef4f9SStephan Aßmus 			return B_OK;
1293b98ef4f9SStephan Aßmus 		}
1294b98ef4f9SStephan Aßmus 	}
1295b98ef4f9SStephan Aßmus 
1296b98ef4f9SStephan Aßmus 	return B_ERROR;
1297b98ef4f9SStephan Aßmus }
1298b98ef4f9SStephan Aßmus 
1299d8e2fb50SAxel Dörfler /*!
1300d8e2fb50SAxel Dörfler 	Frees jpeg alocated memory
1301d8e2fb50SAxel Dörfler 	Returns given error (B_ERROR by default)
1302d8e2fb50SAxel Dörfler */
1303b98ef4f9SStephan Aßmus status_t
1304b98ef4f9SStephan Aßmus JPEGTranslator::Error(j_common_ptr cinfo, status_t error)
13059949213aSStephan Aßmus {
13069949213aSStephan Aßmus 	jpeg_destroy(cinfo);
13079949213aSStephan Aßmus 	return error;
13089949213aSStephan Aßmus }
1309d8e2fb50SAxel Dörfler 
1310d8e2fb50SAxel Dörfler 
1311b98ef4f9SStephan Aßmus JPEGTranslator::JPEGTranslator()
1312bf243977SPhilippe Houdoin 	: BaseTranslator(sTranslatorName, sTranslatorInfo, sTranslatorVersion,
1313bf243977SPhilippe Houdoin 		sInputFormats,  kNumInputFormats,
1314bf243977SPhilippe Houdoin 		sOutputFormats, kNumOutputFormats,
1315bf243977SPhilippe Houdoin 		SETTINGS_FILE,
1316bf243977SPhilippe Houdoin 		sDefaultSettings, kNumDefaultSettings,
1317b98ef4f9SStephan Aßmus 		B_TRANSLATOR_BITMAP, JPEG_FORMAT)
1318b98ef4f9SStephan Aßmus {}
1319b98ef4f9SStephan Aßmus 
1320b98ef4f9SStephan Aßmus 
1321b98ef4f9SStephan Aßmus BTranslator*
1322b98ef4f9SStephan Aßmus make_nth_translator(int32 n, image_id you, uint32 flags, ...)
1323b98ef4f9SStephan Aßmus {
1324b98ef4f9SStephan Aßmus 	if (n == 0)
1325b98ef4f9SStephan Aßmus 		return new JPEGTranslator();
1326b98ef4f9SStephan Aßmus 
1327b98ef4f9SStephan Aßmus 	return NULL;
1328b98ef4f9SStephan Aßmus }
1329d8e2fb50SAxel Dörfler 
1330d8e2fb50SAxel Dörfler 
1331d8e2fb50SAxel Dörfler int
1332117da2d7SAxel Dörfler main(int, char**)
1333117da2d7SAxel Dörfler {
1334117da2d7SAxel Dörfler 	BApplication app("application/x-vnd.Haiku-JPEGTranslator");
1335b98ef4f9SStephan Aßmus 	JPEGTranslator* translator = new JPEGTranslator();
1336bf243977SPhilippe Houdoin 	if (LaunchTranslatorWindow(translator, sTranslatorName) == B_OK)
1337d8e2fb50SAxel Dörfler 		app.Run();
1338b98ef4f9SStephan Aßmus 
1339d8e2fb50SAxel Dörfler 	return 0;
1340d8e2fb50SAxel Dörfler }
1341d8e2fb50SAxel Dörfler 
1342