xref: /haiku/src/add-ons/translators/jpeg/JPEGTranslator.cpp (revision 2710b4f5d4251c5cf88c82b0114ea99b0ef46d22)
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"
3452e8f46aSAxel Dörfler 
3570d59669SSiarzhuk Zharski #include <syslog.h>
3670d59669SSiarzhuk Zharski 
37b98ef4f9SStephan Aßmus #include <Alignment.h>
3803901b6cSJérôme Duval #include <Catalog.h>
397d48219bSHannah Boneß #include <LayoutBuilder.h>
408687ff64SAxel Dörfler #include <TabView.h>
41b98ef4f9SStephan Aßmus #include <TextView.h>
428687ff64SAxel Dörfler 
43e4bd005dSIngo Weinhold #include "be_jerror.h"
44e4bd005dSIngo Weinhold #include "exif_parser.h"
45e4bd005dSIngo Weinhold #include "TranslatorWindow.h"
46e4bd005dSIngo Weinhold 
47e4bd005dSIngo Weinhold 
48546208a5SOliver Tappe #undef B_TRANSLATION_CONTEXT
49546208a5SOliver Tappe #define B_TRANSLATION_CONTEXT "JPEGTranslator"
509949213aSStephan Aßmus 
5152e8f46aSAxel Dörfler #define MARKER_EXIF	0xe1
5252e8f46aSAxel Dörfler 
539949213aSStephan Aßmus // Set these accordingly
549949213aSStephan Aßmus #define JPEG_ACRONYM "JPEG"
559949213aSStephan Aßmus #define JPEG_FORMAT 'JPEG'
569949213aSStephan Aßmus #define JPEG_MIME_STRING "image/jpeg"
579949213aSStephan Aßmus #define JPEG_DESCRIPTION "JPEG image"
589949213aSStephan Aßmus 
599949213aSStephan Aßmus // The translation kit's native file type
609949213aSStephan Aßmus #define B_TRANSLATOR_BITMAP_MIME_STRING "image/x-be-bitmap"
61c095606eSRyan Leavengood #define B_TRANSLATOR_BITMAP_DESCRIPTION "Be Bitmap Format (JPEGTranslator)"
629949213aSStephan Aßmus 
63b98ef4f9SStephan Aßmus 
642e49ff35SSiarzhuk Zharski static const int32 sTranslatorVersion = B_TRANSLATION_MAKE_VERSION(1, 2, 0);
652e49ff35SSiarzhuk Zharski 
661da233a7SSiarzhuk Zharski static const char* sTranslatorName = B_TRANSLATE("JPEG images");
671da233a7SSiarzhuk Zharski static const char* sTranslatorInfo = B_TRANSLATE("©2002-2003, Marcin Konicki\n"
68f13b5de6SAxel Dörfler 	"©2005-2007, Haiku\n"
69758b1d0eSIngo Weinhold 	"\n"
707fd58091SJérôme Duval 	"Based on IJG library ©  1994-2009, Thomas G. Lane, Guido Vollbeding.\n"
712e49ff35SSiarzhuk Zharski 	"\thttp://www.ijg.org/files/\n"
72b98ef4f9SStephan Aßmus 	"\n"
73fcc3e627SStephan Aßmus 	"with \"lossless\" encoding support patch by Ken Murchison\n"
742e49ff35SSiarzhuk Zharski 	"\thttp://www.oceana.com/ftp/ljpeg/\n"
75758b1d0eSIngo Weinhold 	"\n"
76758b1d0eSIngo Weinhold 	"With some colorspace conversion routines by Magnus Hellman\n"
772e49ff35SSiarzhuk Zharski 	"\thttp://www.bebits.com/app/802\n");
789949213aSStephan Aßmus 
799949213aSStephan Aßmus // Define the formats we know how to read
80bf243977SPhilippe Houdoin static const translation_format sInputFormats[] = {
819949213aSStephan Aßmus 	{ JPEG_FORMAT, B_TRANSLATOR_BITMAP, 0.5, 0.5,
829949213aSStephan Aßmus 		JPEG_MIME_STRING, JPEG_DESCRIPTION },
839949213aSStephan Aßmus 	{ B_TRANSLATOR_BITMAP, B_TRANSLATOR_BITMAP, 0.5, 0.5,
847b5743baSPhilippe Houdoin 		B_TRANSLATOR_BITMAP_MIME_STRING, B_TRANSLATOR_BITMAP_DESCRIPTION }
859949213aSStephan Aßmus };
869949213aSStephan Aßmus 
879949213aSStephan Aßmus // Define the formats we know how to write
88bf243977SPhilippe Houdoin static const translation_format sOutputFormats[] = {
899949213aSStephan Aßmus 	{ JPEG_FORMAT, B_TRANSLATOR_BITMAP, 0.5, 0.5,
909949213aSStephan Aßmus 		JPEG_MIME_STRING, JPEG_DESCRIPTION },
919949213aSStephan Aßmus 	{ B_TRANSLATOR_BITMAP, B_TRANSLATOR_BITMAP, 0.5, 0.5,
927b5743baSPhilippe Houdoin 		B_TRANSLATOR_BITMAP_MIME_STRING, B_TRANSLATOR_BITMAP_DESCRIPTION }
939949213aSStephan Aßmus };
9452e8f46aSAxel Dörfler 
95d8e2fb50SAxel Dörfler 
96bf243977SPhilippe Houdoin static const TranSetting sDefaultSettings[] = {
97b98ef4f9SStephan Aßmus 	{JPEG_SET_SMOOTHING, TRAN_SETTING_INT32, 0},
98b98ef4f9SStephan Aßmus 	{JPEG_SET_QUALITY, TRAN_SETTING_INT32, 95},
99b98ef4f9SStephan Aßmus 	{JPEG_SET_PROGRESSIVE, TRAN_SETTING_BOOL, true},
100b98ef4f9SStephan Aßmus 	{JPEG_SET_OPT_COLORS, TRAN_SETTING_BOOL, true},
101b98ef4f9SStephan Aßmus 	{JPEG_SET_SMALL_FILES, TRAN_SETTING_BOOL, false},
102b98ef4f9SStephan Aßmus 	{JPEG_SET_GRAY1_AS_RGB24, TRAN_SETTING_BOOL, false},
103b98ef4f9SStephan Aßmus 	{JPEG_SET_ALWAYS_RGB32, TRAN_SETTING_BOOL, true},
104b98ef4f9SStephan Aßmus 	{JPEG_SET_PHOTOSHOP_CMYK, TRAN_SETTING_BOOL, true},
105b98ef4f9SStephan Aßmus 	{JPEG_SET_SHOWREADWARNING, TRAN_SETTING_BOOL, true}
106b98ef4f9SStephan Aßmus };
107bf243977SPhilippe Houdoin 
108bf243977SPhilippe Houdoin const uint32 kNumInputFormats = sizeof(sInputFormats) / sizeof(translation_format);
109bf243977SPhilippe Houdoin const uint32 kNumOutputFormats = sizeof(sOutputFormats) / sizeof(translation_format);
110bf243977SPhilippe Houdoin const uint32 kNumDefaultSettings = sizeof(sDefaultSettings) / sizeof(TranSetting);
1119949213aSStephan Aßmus 
112d8e2fb50SAxel Dörfler 
113b98ef4f9SStephan Aßmus namespace conversion {
114d8e2fb50SAxel Dörfler 
115d8e2fb50SAxel Dörfler 
1169e34f742SAxel Dörfler static bool
x_flipped(int32 orientation)1179e34f742SAxel Dörfler x_flipped(int32 orientation)
1189e34f742SAxel Dörfler {
1199e34f742SAxel Dörfler 	return orientation == 2 || orientation == 3
1209e34f742SAxel Dörfler 		|| orientation == 6 || orientation == 7;
1219e34f742SAxel Dörfler }
1229e34f742SAxel Dörfler 
1239e34f742SAxel Dörfler 
1249e34f742SAxel Dörfler static bool
y_flipped(int32 orientation)1259e34f742SAxel Dörfler y_flipped(int32 orientation)
1269e34f742SAxel Dörfler {
1279e34f742SAxel Dörfler 	return orientation == 3 || orientation == 4
1289e34f742SAxel Dörfler 		|| orientation == 7 || orientation == 8;
1299e34f742SAxel Dörfler }
1309e34f742SAxel Dörfler 
1319e34f742SAxel Dörfler 
1329e34f742SAxel Dörfler static int32
dest_index(uint32 width,uint32 height,uint32 x,uint32 y,int32 orientation)1339e34f742SAxel Dörfler dest_index(uint32 width, uint32 height, uint32 x, uint32 y, int32 orientation)
1349e34f742SAxel Dörfler {
1359e34f742SAxel Dörfler 	if (orientation > 4) {
1369e34f742SAxel Dörfler 		uint32 temp = x;
1379e34f742SAxel Dörfler 		x = y;
1389e34f742SAxel Dörfler 		y = temp;
1399e34f742SAxel Dörfler 	}
1409e34f742SAxel Dörfler 	if (y_flipped(orientation))
1419e34f742SAxel Dörfler 		y = height - 1 - y;
1429e34f742SAxel Dörfler 	if (x_flipped(orientation))
1439e34f742SAxel Dörfler 		x = width - 1 - x;
1449e34f742SAxel Dörfler 
1459e34f742SAxel Dörfler 	return y * width + x;
1469e34f742SAxel Dörfler }
1479e34f742SAxel Dörfler 
1489e34f742SAxel Dörfler 
1499e34f742SAxel Dörfler //	#pragma mark - conversion for compression
150d8e2fb50SAxel Dörfler 
151d8e2fb50SAxel Dörfler 
152d8e2fb50SAxel Dörfler inline void
convert_from_gray1_to_gray8(uint8 * in,uint8 * out,int32 inRowBytes)1539e34f742SAxel Dörfler convert_from_gray1_to_gray8(uint8* in, uint8* out, int32 inRowBytes)
154d8e2fb50SAxel Dörfler {
155d8e2fb50SAxel Dörfler 	int32 index = 0;
156d8e2fb50SAxel Dörfler 	int32 index2 = 0;
1579e34f742SAxel Dörfler 	while (index < inRowBytes) {
158d8e2fb50SAxel Dörfler 		unsigned char c = in[index++];
159d8e2fb50SAxel Dörfler 		for (int b = 128; b; b = b>>1) {
160d8e2fb50SAxel Dörfler 			unsigned char color;
161d8e2fb50SAxel Dörfler 			if (c & b)
162d8e2fb50SAxel Dörfler 				color = 0;
163d8e2fb50SAxel Dörfler 			else
164d8e2fb50SAxel Dörfler 				color = 255;
165d8e2fb50SAxel Dörfler 			out[index2++] = color;
166d8e2fb50SAxel Dörfler 		}
167d8e2fb50SAxel Dörfler 	}
168d8e2fb50SAxel Dörfler }
169d8e2fb50SAxel Dörfler 
170d8e2fb50SAxel Dörfler 
171d8e2fb50SAxel Dörfler inline void
convert_from_gray1_to_24(uint8 * in,uint8 * out,int32 inRowBytes)1729e34f742SAxel Dörfler convert_from_gray1_to_24(uint8* in, uint8* out, int32 inRowBytes)
173d8e2fb50SAxel Dörfler {
174d8e2fb50SAxel Dörfler 	int32 index = 0;
175d8e2fb50SAxel Dörfler 	int32 index2 = 0;
1769e34f742SAxel Dörfler 	while (index < inRowBytes) {
177d8e2fb50SAxel Dörfler 		unsigned char c = in[index++];
178d8e2fb50SAxel Dörfler 		for (int b = 128; b; b = b>>1) {
179d8e2fb50SAxel Dörfler 			unsigned char color;
180d8e2fb50SAxel Dörfler 			if (c & b)
181d8e2fb50SAxel Dörfler 				color = 0;
182d8e2fb50SAxel Dörfler 			else
183d8e2fb50SAxel Dörfler 				color = 255;
184d8e2fb50SAxel Dörfler 			out[index2++] = color;
185d8e2fb50SAxel Dörfler 			out[index2++] = color;
186d8e2fb50SAxel Dörfler 			out[index2++] = color;
187d8e2fb50SAxel Dörfler 		}
188d8e2fb50SAxel Dörfler 	}
189d8e2fb50SAxel Dörfler }
190d8e2fb50SAxel Dörfler 
191d8e2fb50SAxel Dörfler 
192d8e2fb50SAxel Dörfler inline void
convert_from_cmap8_to_24(uint8 * in,uint8 * out,int32 inRowBytes)1939e34f742SAxel Dörfler convert_from_cmap8_to_24(uint8* in, uint8* out, int32 inRowBytes)
194d8e2fb50SAxel Dörfler {
195d8e2fb50SAxel Dörfler 	const color_map * map = system_colors();
196d8e2fb50SAxel Dörfler 	int32 index = 0;
197d8e2fb50SAxel Dörfler 	int32 index2 = 0;
1989e34f742SAxel Dörfler 	while (index < inRowBytes) {
199d8e2fb50SAxel Dörfler 		rgb_color color = map->color_list[in[index++]];
200d8e2fb50SAxel Dörfler 
201d8e2fb50SAxel Dörfler 		out[index2++] = color.red;
202d8e2fb50SAxel Dörfler 		out[index2++] = color.green;
203d8e2fb50SAxel Dörfler 		out[index2++] = color.blue;
204d8e2fb50SAxel Dörfler 	}
205d8e2fb50SAxel Dörfler }
206d8e2fb50SAxel Dörfler 
207d8e2fb50SAxel Dörfler 
208d8e2fb50SAxel Dörfler inline void
convert_from_15_to_24(uint8 * in,uint8 * out,int32 inRowBytes)2099e34f742SAxel Dörfler convert_from_15_to_24(uint8* in, uint8* out, int32 inRowBytes)
210d8e2fb50SAxel Dörfler {
211d8e2fb50SAxel Dörfler 	int32 index = 0;
212d8e2fb50SAxel Dörfler 	int32 index2 = 0;
213d8e2fb50SAxel Dörfler 	int16 in_pixel;
2149e34f742SAxel Dörfler 	while (index < inRowBytes) {
215d8e2fb50SAxel Dörfler 		in_pixel = in[index] | (in[index + 1] << 8);
216d8e2fb50SAxel Dörfler 		index += 2;
217d8e2fb50SAxel Dörfler 
218d8e2fb50SAxel Dörfler 		out[index2++] = (((in_pixel & 0x7c00)) >> 7) | (((in_pixel & 0x7c00)) >> 12);
219d8e2fb50SAxel Dörfler 		out[index2++] = (((in_pixel & 0x3e0)) >> 2) | (((in_pixel & 0x3e0)) >> 7);
220d8e2fb50SAxel Dörfler 		out[index2++] = (((in_pixel & 0x1f)) << 3) | (((in_pixel & 0x1f)) >> 2);
221d8e2fb50SAxel Dörfler 	}
222d8e2fb50SAxel Dörfler }
223d8e2fb50SAxel Dörfler 
224d8e2fb50SAxel Dörfler 
225d8e2fb50SAxel Dörfler inline void
convert_from_15b_to_24(uint8 * in,uint8 * out,int32 inRowBytes)2269e34f742SAxel Dörfler convert_from_15b_to_24(uint8* in, uint8* out, int32 inRowBytes)
227d8e2fb50SAxel Dörfler {
228d8e2fb50SAxel Dörfler 	int32 index = 0;
229d8e2fb50SAxel Dörfler 	int32 index2 = 0;
230d8e2fb50SAxel Dörfler 	int16 in_pixel;
2319e34f742SAxel Dörfler 	while (index < inRowBytes) {
232d8e2fb50SAxel Dörfler 		in_pixel = in[index + 1] | (in[index] << 8);
233d8e2fb50SAxel Dörfler 		index += 2;
234d8e2fb50SAxel Dörfler 
235d8e2fb50SAxel Dörfler 		out[index2++] = (((in_pixel & 0x7c00)) >> 7) | (((in_pixel & 0x7c00)) >> 12);
236d8e2fb50SAxel Dörfler 		out[index2++] = (((in_pixel & 0x3e0)) >> 2) | (((in_pixel & 0x3e0)) >> 7);
237d8e2fb50SAxel Dörfler 		out[index2++] = (((in_pixel & 0x1f)) << 3) | (((in_pixel & 0x1f)) >> 2);
238d8e2fb50SAxel Dörfler 	}
239d8e2fb50SAxel Dörfler }
240d8e2fb50SAxel Dörfler 
241d8e2fb50SAxel Dörfler 
242d8e2fb50SAxel Dörfler inline void
convert_from_16_to_24(uint8 * in,uint8 * out,int32 inRowBytes)2439e34f742SAxel Dörfler convert_from_16_to_24(uint8* in, uint8* out, int32 inRowBytes)
244d8e2fb50SAxel Dörfler {
245d8e2fb50SAxel Dörfler 	int32 index = 0;
246d8e2fb50SAxel Dörfler 	int32 index2 = 0;
247d8e2fb50SAxel Dörfler 	int16 in_pixel;
2489e34f742SAxel Dörfler 	while (index < inRowBytes) {
249d8e2fb50SAxel Dörfler 		in_pixel = in[index] | (in[index + 1] << 8);
250d8e2fb50SAxel Dörfler 		index += 2;
251d8e2fb50SAxel Dörfler 
252d8e2fb50SAxel Dörfler 		out[index2++] = (((in_pixel & 0xf800)) >> 8) | (((in_pixel & 0xf800)) >> 13);
253d8e2fb50SAxel Dörfler 		out[index2++] = (((in_pixel & 0x7e0)) >> 3) | (((in_pixel & 0x7e0)) >> 9);
254d8e2fb50SAxel Dörfler 		out[index2++] = (((in_pixel & 0x1f)) << 3) | (((in_pixel & 0x1f)) >> 2);
255d8e2fb50SAxel Dörfler 	}
256d8e2fb50SAxel Dörfler }
257d8e2fb50SAxel Dörfler 
258d8e2fb50SAxel Dörfler 
259d8e2fb50SAxel Dörfler inline void
convert_from_16b_to_24(uint8 * in,uint8 * out,int32 inRowBytes)2609e34f742SAxel Dörfler convert_from_16b_to_24(uint8* in, uint8* out, int32 inRowBytes)
261d8e2fb50SAxel Dörfler {
262d8e2fb50SAxel Dörfler 	int32 index = 0;
263d8e2fb50SAxel Dörfler 	int32 index2 = 0;
264d8e2fb50SAxel Dörfler 	int16 in_pixel;
2659e34f742SAxel Dörfler 	while (index < inRowBytes) {
266d8e2fb50SAxel Dörfler 		in_pixel = in[index + 1] | (in[index] << 8);
267d8e2fb50SAxel Dörfler 		index += 2;
268d8e2fb50SAxel Dörfler 
269d8e2fb50SAxel Dörfler 		out[index2++] = (((in_pixel & 0xf800)) >> 8) | (((in_pixel & 0xf800)) >> 13);
270d8e2fb50SAxel Dörfler 		out[index2++] = (((in_pixel & 0x7e0)) >> 3) | (((in_pixel & 0x7e0)) >> 9);
271d8e2fb50SAxel Dörfler 		out[index2++] = (((in_pixel & 0x1f)) << 3) | (((in_pixel & 0x1f)) >> 2);
272d8e2fb50SAxel Dörfler 	}
273d8e2fb50SAxel Dörfler }
274d8e2fb50SAxel Dörfler 
275d8e2fb50SAxel Dörfler 
276d8e2fb50SAxel Dörfler inline void
convert_from_24_to_24(uint8 * in,uint8 * out,int32 inRowBytes)2779e34f742SAxel Dörfler convert_from_24_to_24(uint8* in, uint8* out, int32 inRowBytes)
278d8e2fb50SAxel Dörfler {
279d8e2fb50SAxel Dörfler 	int32 index = 0;
280d8e2fb50SAxel Dörfler 	int32 index2 = 0;
2819e34f742SAxel Dörfler 	while (index < inRowBytes) {
282d8e2fb50SAxel Dörfler 		out[index2++] = in[index + 2];
283d8e2fb50SAxel Dörfler 		out[index2++] = in[index + 1];
284d8e2fb50SAxel Dörfler 		out[index2++] = in[index];
285d8e2fb50SAxel Dörfler 		index+=3;
286d8e2fb50SAxel Dörfler 	}
287d8e2fb50SAxel Dörfler }
288d8e2fb50SAxel Dörfler 
289d8e2fb50SAxel Dörfler 
290d8e2fb50SAxel Dörfler inline void
convert_from_32_to_24(uint8 * in,uint8 * out,int32 inRowBytes)2919e34f742SAxel Dörfler convert_from_32_to_24(uint8* in, uint8* out, int32 inRowBytes)
292d8e2fb50SAxel Dörfler {
29351623681SAxel Dörfler 	inRowBytes /= 4;
29451623681SAxel Dörfler 
2959e34f742SAxel Dörfler 	for (int32 i = 0; i < inRowBytes; i++) {
2969e34f742SAxel Dörfler 		out[0] = in[2];
2979e34f742SAxel Dörfler 		out[1] = in[1];
2989e34f742SAxel Dörfler 		out[2] = in[0];
2999e34f742SAxel Dörfler 
3009e34f742SAxel Dörfler 		in += 4;
3019e34f742SAxel Dörfler 		out += 3;
302d8e2fb50SAxel Dörfler 	}
303d8e2fb50SAxel Dörfler }
304d8e2fb50SAxel Dörfler 
305d8e2fb50SAxel Dörfler 
306d8e2fb50SAxel Dörfler inline void
convert_from_32b_to_24(uint8 * in,uint8 * out,int32 inRowBytes)3079e34f742SAxel Dörfler convert_from_32b_to_24(uint8* in, uint8* out, int32 inRowBytes)
308d8e2fb50SAxel Dörfler {
30951623681SAxel Dörfler 	inRowBytes /= 4;
31051623681SAxel Dörfler 
3119e34f742SAxel Dörfler 	for (int32 i = 0; i < inRowBytes; i++) {
31251623681SAxel Dörfler 		out[0] = in[1];
31351623681SAxel Dörfler 		out[1] = in[2];
31451623681SAxel Dörfler 		out[2] = in[3];
3159e34f742SAxel Dörfler 
3169e34f742SAxel Dörfler 		in += 4;
3179e34f742SAxel Dörfler 		out += 3;
318d8e2fb50SAxel Dörfler 	}
319d8e2fb50SAxel Dörfler }
320d8e2fb50SAxel Dörfler 
321d8e2fb50SAxel Dörfler 
3229e34f742SAxel Dörfler //	#pragma mark - conversion for decompression
3239e34f742SAxel Dörfler 
3249e34f742SAxel Dörfler 
325d8e2fb50SAxel Dörfler inline void
convert_from_CMYK_to_32_photoshop(uint8 * in,uint8 * out,int32 inRowBytes,int32 xStep)3269e34f742SAxel Dörfler convert_from_CMYK_to_32_photoshop(uint8* in, uint8* out, int32 inRowBytes, int32 xStep)
327d8e2fb50SAxel Dörfler {
3289e34f742SAxel Dörfler 	for (int32 i = 0; i < inRowBytes; i += 4) {
3299e34f742SAxel Dörfler 		int32 black = in[3];
3309e34f742SAxel Dörfler 		out[0] = in[2] * black / 255;
3319e34f742SAxel Dörfler 		out[1] = in[1] * black / 255;
3329e34f742SAxel Dörfler 		out[2] = in[0] * black / 255;
3339e34f742SAxel Dörfler 		out[3] = 255;
3349e34f742SAxel Dörfler 
3359e34f742SAxel Dörfler 		in += 4;
3369e34f742SAxel Dörfler 		out += xStep;
337d8e2fb50SAxel Dörfler 	}
338d8e2fb50SAxel Dörfler }
339d8e2fb50SAxel Dörfler 
340d8e2fb50SAxel Dörfler 
341d8e2fb50SAxel Dörfler //!	!!! UNTESTED !!!
342d8e2fb50SAxel Dörfler inline void
convert_from_CMYK_to_32(uint8 * in,uint8 * out,int32 inRowBytes,int32 xStep)3439e34f742SAxel Dörfler convert_from_CMYK_to_32(uint8* in, uint8* out, int32 inRowBytes, int32 xStep)
344d8e2fb50SAxel Dörfler {
3459e34f742SAxel Dörfler 	for (int32 i = 0; i < inRowBytes; i += 4) {
3469e34f742SAxel Dörfler 		int32 black = 255 - in[3];
3479e34f742SAxel Dörfler 		out[0] = ((255 - in[2]) * black) / 255;
3489e34f742SAxel Dörfler 		out[1] = ((255 - in[1]) * black) / 255;
3499e34f742SAxel Dörfler 		out[2] = ((255 - in[0]) * black) / 255;
3509e34f742SAxel Dörfler 		out[3] = 255;
3519e34f742SAxel Dörfler 
3529e34f742SAxel Dörfler 		in += 4;
3539e34f742SAxel Dörfler 		out += xStep;
354d8e2fb50SAxel Dörfler 	}
355d8e2fb50SAxel Dörfler }
356d8e2fb50SAxel Dörfler 
357d8e2fb50SAxel Dörfler 
358d8e2fb50SAxel Dörfler //!	RGB24 8:8:8 to xRGB 8:8:8:8
359d8e2fb50SAxel Dörfler inline void
convert_from_24_to_32(uint8 * in,uint8 * out,int32 inRowBytes,int32 xStep)3609e34f742SAxel Dörfler convert_from_24_to_32(uint8* in, uint8* out, int32 inRowBytes, int32 xStep)
361d8e2fb50SAxel Dörfler {
3629e34f742SAxel Dörfler 	for (int32 i = 0; i < inRowBytes; i += 3) {
3639e34f742SAxel Dörfler 		out[0] = in[2];
3649e34f742SAxel Dörfler 		out[1] = in[1];
3659e34f742SAxel Dörfler 		out[2] = in[0];
3669e34f742SAxel Dörfler 		out[3] = 255;
3679e34f742SAxel Dörfler 
3689e34f742SAxel Dörfler 		in += 3;
3699e34f742SAxel Dörfler 		out += xStep;
3709e34f742SAxel Dörfler 	}
3719e34f742SAxel Dörfler }
3729e34f742SAxel Dörfler 
3739e34f742SAxel Dörfler 
3749e34f742SAxel Dörfler //! 8-bit to 8-bit, only need when rotating the image
3759e34f742SAxel Dörfler void
translate_8(uint8 * in,uint8 * out,int32 inRowBytes,int32 xStep)3769e34f742SAxel Dörfler translate_8(uint8* in, uint8* out, int32 inRowBytes, int32 xStep)
3779e34f742SAxel Dörfler {
3789e34f742SAxel Dörfler 	for (int32 i = 0; i < inRowBytes; i++) {
3799e34f742SAxel Dörfler 		out[0] = in[0];
3809e34f742SAxel Dörfler 
3819e34f742SAxel Dörfler 		in++;
3829e34f742SAxel Dörfler 		out += xStep;
383d8e2fb50SAxel Dörfler 	}
384d8e2fb50SAxel Dörfler }
385d8e2fb50SAxel Dörfler 
386d8e2fb50SAxel Dörfler 
387b98ef4f9SStephan Aßmus } // namespace conversion
3888687ff64SAxel Dörfler 
3898687ff64SAxel Dörfler 
390d8e2fb50SAxel Dörfler //	#pragma mark -
391d8e2fb50SAxel Dörfler 
392d8e2fb50SAxel Dörfler 
SSlider(const char * name,const char * label,BMessage * message,int32 minValue,int32 maxValue,orientation posture,thumb_style thumbType,uint32 flags)393b98ef4f9SStephan Aßmus SSlider::SSlider(const char* name, const char* label,
394d8e2fb50SAxel Dörfler 		BMessage* message, int32 minValue, int32 maxValue, orientation posture,
395b98ef4f9SStephan Aßmus 		thumb_style thumbType, uint32 flags)
396b98ef4f9SStephan Aßmus 	: BSlider(name, label, message, minValue, maxValue,
397b98ef4f9SStephan Aßmus 		posture, thumbType, flags)
3989949213aSStephan Aßmus {
3998687ff64SAxel Dörfler 	rgb_color barColor = { 0, 0, 229, 255 };
4008687ff64SAxel Dörfler 	UseFillColor(true, &barColor);
4019949213aSStephan Aßmus }
4029949213aSStephan Aßmus 
4038687ff64SAxel Dörfler 
4048687ff64SAxel Dörfler //!	Update status string - show actual value
405b20d13f4SStefano Ceccherini const char*
UpdateText() const4069949213aSStephan Aßmus SSlider::UpdateText() const
4079949213aSStephan Aßmus {
408bb4537c8SJérôme Duval 	snprintf(fStatusLabel, sizeof(fStatusLabel), "%" B_PRId32, Value());
4098687ff64SAxel Dörfler 	return fStatusLabel;
4109949213aSStephan Aßmus }
4119949213aSStephan Aßmus 
4128687ff64SAxel Dörfler 
413d8e2fb50SAxel Dörfler //	#pragma mark -
4149949213aSStephan Aßmus 
415d8e2fb50SAxel Dörfler 
TranslatorReadView(const char * name,TranslatorSettings * settings)416b98ef4f9SStephan Aßmus TranslatorReadView::TranslatorReadView(const char* name,
417b98ef4f9SStephan Aßmus 	TranslatorSettings* settings)
418b98ef4f9SStephan Aßmus 	:
419b98ef4f9SStephan Aßmus 	BView(name, 0, new BGroupLayout(B_HORIZONTAL)),
420d8e2fb50SAxel Dörfler 	fSettings(settings)
421b98ef4f9SStephan Aßmus 		// settings should already be Acquired()
4229949213aSStephan Aßmus {
4232e49ff35SSiarzhuk Zharski 	fAlwaysRGB32 = new BCheckBox("alwaysrgb32",
4242e49ff35SSiarzhuk Zharski 		B_TRANSLATE("Read greyscale images as RGB32"),
425d8e2fb50SAxel Dörfler 		new BMessage(VIEW_MSG_SET_ALWAYSRGB32));
426b98ef4f9SStephan Aßmus 	if (fSettings->SetGetBool(JPEG_SET_ALWAYS_RGB32, NULL))
427b98ef4f9SStephan Aßmus 		fAlwaysRGB32->SetValue(B_CONTROL_ON);
4289949213aSStephan Aßmus 
4292e49ff35SSiarzhuk Zharski 	fPhotoshopCMYK = new BCheckBox("photoshopCMYK",
4302e49ff35SSiarzhuk Zharski 		B_TRANSLATE("Use CMYK code with 0 for 100% ink coverage"),
4318687ff64SAxel Dörfler 		new BMessage(VIEW_MSG_SET_PHOTOSHOPCMYK));
432b98ef4f9SStephan Aßmus 	if (fSettings->SetGetBool(JPEG_SET_PHOTOSHOP_CMYK, NULL))
433b98ef4f9SStephan Aßmus 		fPhotoshopCMYK->SetValue(B_CONTROL_ON);
4349949213aSStephan Aßmus 
4352e49ff35SSiarzhuk Zharski 	fShowErrorBox = new BCheckBox("error",
4362e49ff35SSiarzhuk Zharski 		B_TRANSLATE("Show warning messages"),
4378687ff64SAxel Dörfler 		new BMessage(VIEW_MSG_SET_SHOWREADERRORBOX));
438b98ef4f9SStephan Aßmus 	if (fSettings->SetGetBool(JPEG_SET_SHOWREADWARNING, NULL))
439b98ef4f9SStephan Aßmus 		fShowErrorBox->SetValue(B_CONTROL_ON);
4409949213aSStephan Aßmus 
441d9c440a5SJanus 	BLayoutBuilder::Group<>(this, B_VERTICAL)
442d9c440a5SJanus 		.SetInsets(B_USE_DEFAULT_SPACING)
443b98ef4f9SStephan Aßmus 		.Add(fAlwaysRGB32)
444b98ef4f9SStephan Aßmus 		.Add(fPhotoshopCMYK)
445b98ef4f9SStephan Aßmus 		.Add(fShowErrorBox)
4467d48219bSHannah Boneß 		.AddGlue();
447b98ef4f9SStephan Aßmus }
448b98ef4f9SStephan Aßmus 
449b98ef4f9SStephan Aßmus 
~TranslatorReadView()450b98ef4f9SStephan Aßmus TranslatorReadView::~TranslatorReadView()
451b98ef4f9SStephan Aßmus {
452b98ef4f9SStephan Aßmus 	fSettings->Release();
4539949213aSStephan Aßmus }
4549949213aSStephan Aßmus 
4558687ff64SAxel Dörfler 
4569949213aSStephan Aßmus void
AttachedToWindow()4579949213aSStephan Aßmus TranslatorReadView::AttachedToWindow()
4589949213aSStephan Aßmus {
459b98ef4f9SStephan Aßmus 	BView::AttachedToWindow();
460b20d13f4SStefano Ceccherini 
4618687ff64SAxel Dörfler 	fAlwaysRGB32->SetTarget(this);
4628687ff64SAxel Dörfler 	fPhotoshopCMYK->SetTarget(this);
4638687ff64SAxel Dörfler 	fShowErrorBox->SetTarget(this);
4649949213aSStephan Aßmus }
4659949213aSStephan Aßmus 
4668687ff64SAxel Dörfler 
4679949213aSStephan Aßmus void
MessageReceived(BMessage * message)4689949213aSStephan Aßmus TranslatorReadView::MessageReceived(BMessage* message)
4699949213aSStephan Aßmus {
4708687ff64SAxel Dörfler 	switch (message->what) {
4719949213aSStephan Aßmus 		case VIEW_MSG_SET_ALWAYSRGB32:
4729949213aSStephan Aßmus 		{
4739949213aSStephan Aßmus 			int32 value;
4749949213aSStephan Aßmus 			if (message->FindInt32("be:value", &value) == B_OK) {
475b98ef4f9SStephan Aßmus 				bool boolValue = value;
476b98ef4f9SStephan Aßmus 				fSettings->SetGetBool(JPEG_SET_ALWAYS_RGB32, &boolValue);
477b98ef4f9SStephan Aßmus 				fSettings->SaveSettings();
4789949213aSStephan Aßmus 			}
4799949213aSStephan Aßmus 			break;
4809949213aSStephan Aßmus 		}
4819949213aSStephan Aßmus 		case VIEW_MSG_SET_PHOTOSHOPCMYK:
4829949213aSStephan Aßmus 		{
4839949213aSStephan Aßmus 			int32 value;
4849949213aSStephan Aßmus 			if (message->FindInt32("be:value", &value) == B_OK) {
485b98ef4f9SStephan Aßmus 				bool boolValue = value;
486b98ef4f9SStephan Aßmus 				fSettings->SetGetBool(JPEG_SET_PHOTOSHOP_CMYK, &boolValue);
487b98ef4f9SStephan Aßmus 				fSettings->SaveSettings();
4889949213aSStephan Aßmus 			}
4899949213aSStephan Aßmus 			break;
4909949213aSStephan Aßmus 		}
4919949213aSStephan Aßmus 		case VIEW_MSG_SET_SHOWREADERRORBOX:
4929949213aSStephan Aßmus 		{
4939949213aSStephan Aßmus 			int32 value;
4949949213aSStephan Aßmus 			if (message->FindInt32("be:value", &value) == B_OK) {
495b98ef4f9SStephan Aßmus 				bool boolValue = value;
496b98ef4f9SStephan Aßmus 				fSettings->SetGetBool(JPEG_SET_SHOWREADWARNING, &boolValue);
497b98ef4f9SStephan Aßmus 				fSettings->SaveSettings();
4989949213aSStephan Aßmus 			}
4999949213aSStephan Aßmus 			break;
5009949213aSStephan Aßmus 		}
5019949213aSStephan Aßmus 		default:
5029949213aSStephan Aßmus 			BView::MessageReceived(message);
5039949213aSStephan Aßmus 			break;
5049949213aSStephan Aßmus 	}
5059949213aSStephan Aßmus }
5069949213aSStephan Aßmus 
5079949213aSStephan Aßmus 
5088687ff64SAxel Dörfler //	#pragma mark - TranslatorWriteView
5099949213aSStephan Aßmus 
5108687ff64SAxel Dörfler 
TranslatorWriteView(const char * name,TranslatorSettings * settings)511b98ef4f9SStephan Aßmus TranslatorWriteView::TranslatorWriteView(const char* name,
512b98ef4f9SStephan Aßmus 	TranslatorSettings* settings)
513b98ef4f9SStephan Aßmus 	:
514b98ef4f9SStephan Aßmus 	BView(name, 0, new BGroupLayout(B_VERTICAL)),
515d8e2fb50SAxel Dörfler 	fSettings(settings)
516b98ef4f9SStephan Aßmus 		// settings should already be Acquired()
5179949213aSStephan Aßmus {
5182e49ff35SSiarzhuk Zharski 	fQualitySlider = new SSlider("quality", B_TRANSLATE("Output quality"),
5198687ff64SAxel Dörfler 		new BMessage(VIEW_MSG_SET_QUALITY), 0, 100);
5208687ff64SAxel Dörfler 	fQualitySlider->SetHashMarks(B_HASH_MARKS_BOTTOM);
5218687ff64SAxel Dörfler 	fQualitySlider->SetHashMarkCount(10);
52203901b6cSJérôme Duval 	fQualitySlider->SetLimitLabels(B_TRANSLATE("Low"), B_TRANSLATE("High"));
523b98ef4f9SStephan Aßmus 	fQualitySlider->SetValue(fSettings->SetGetInt32(JPEG_SET_QUALITY, NULL));
5249949213aSStephan Aßmus 
5252e49ff35SSiarzhuk Zharski 	fSmoothingSlider = new SSlider("smoothing",
5262e49ff35SSiarzhuk Zharski 		B_TRANSLATE("Output smoothing strength"),
5278687ff64SAxel Dörfler 		new BMessage(VIEW_MSG_SET_SMOOTHING), 0, 100);
5288687ff64SAxel Dörfler 	fSmoothingSlider->SetHashMarks(B_HASH_MARKS_BOTTOM);
5298687ff64SAxel Dörfler 	fSmoothingSlider->SetHashMarkCount(10);
53003901b6cSJérôme Duval 	fSmoothingSlider->SetLimitLabels(B_TRANSLATE("None"), B_TRANSLATE("High"));
531b98ef4f9SStephan Aßmus 	fSmoothingSlider->SetValue(
532b98ef4f9SStephan Aßmus 		fSettings->SetGetInt32(JPEG_SET_SMOOTHING, NULL));
5339949213aSStephan Aßmus 
5342e49ff35SSiarzhuk Zharski 	fProgress = new BCheckBox("progress",
5352e49ff35SSiarzhuk Zharski 		B_TRANSLATE("Use progressive compression"),
5368687ff64SAxel Dörfler 		new BMessage(VIEW_MSG_SET_PROGRESSIVE));
537b98ef4f9SStephan Aßmus 	if (fSettings->SetGetBool(JPEG_SET_PROGRESSIVE, NULL))
538b98ef4f9SStephan Aßmus 		fProgress->SetValue(B_CONTROL_ON);
5399949213aSStephan Aßmus 
5402e49ff35SSiarzhuk Zharski 	fSmallerFile = new BCheckBox("smallerfile",
5412e49ff35SSiarzhuk Zharski 		B_TRANSLATE("Make file smaller (sligthtly worse quality)"),
5428687ff64SAxel Dörfler 		new BMessage(VIEW_MSG_SET_SMALLERFILE));
543b98ef4f9SStephan Aßmus 	if (fSettings->SetGetBool(JPEG_SET_SMALL_FILES))
544b98ef4f9SStephan Aßmus 		fSmallerFile->SetValue(B_CONTROL_ON);
545b98ef4f9SStephan Aßmus 
5462e49ff35SSiarzhuk Zharski 	fOptimizeColors = new BCheckBox("optimizecolors",
5472e49ff35SSiarzhuk Zharski 		B_TRANSLATE("Prevent colors 'washing out'"),
548b98ef4f9SStephan Aßmus 		new BMessage(VIEW_MSG_SET_OPTIMIZECOLORS));
549b98ef4f9SStephan Aßmus 	if (fSettings->SetGetBool(JPEG_SET_OPT_COLORS, NULL))
550b98ef4f9SStephan Aßmus 		fOptimizeColors->SetValue(B_CONTROL_ON);
551b98ef4f9SStephan Aßmus 	else
5528687ff64SAxel Dörfler 		fSmallerFile->SetEnabled(false);
5539949213aSStephan Aßmus 
5542e49ff35SSiarzhuk Zharski 	fGrayAsRGB24 = new BCheckBox("gray1asrgb24",
5552e49ff35SSiarzhuk Zharski 		B_TRANSLATE("Write black-and-white images as RGB24"),
5568687ff64SAxel Dörfler 		new BMessage(VIEW_MSG_SET_GRAY1ASRGB24));
557b98ef4f9SStephan Aßmus 	if (fSettings->SetGetBool(JPEG_SET_GRAY1_AS_RGB24))
558b98ef4f9SStephan Aßmus 		fGrayAsRGB24->SetValue(B_CONTROL_ON);
5599949213aSStephan Aßmus 
560d9c440a5SJanus 	BLayoutBuilder::Group<>(this, B_VERTICAL)
561d9c440a5SJanus 		.SetInsets(B_USE_DEFAULT_SPACING)
562b98ef4f9SStephan Aßmus 		.Add(fQualitySlider)
563b98ef4f9SStephan Aßmus 		.Add(fSmoothingSlider)
564b98ef4f9SStephan Aßmus 		.Add(fProgress)
565b98ef4f9SStephan Aßmus 		.Add(fOptimizeColors)
566b98ef4f9SStephan Aßmus 		.Add(fSmallerFile)
567b98ef4f9SStephan Aßmus 		.Add(fGrayAsRGB24)
5687d48219bSHannah Boneß 		.AddGlue();
569b98ef4f9SStephan Aßmus }
5709949213aSStephan Aßmus 
571b98ef4f9SStephan Aßmus 
~TranslatorWriteView()572b98ef4f9SStephan Aßmus TranslatorWriteView::~TranslatorWriteView()
573b98ef4f9SStephan Aßmus {
574b98ef4f9SStephan Aßmus 	fSettings->Release();
5759949213aSStephan Aßmus }
5769949213aSStephan Aßmus 
5778687ff64SAxel Dörfler 
5789949213aSStephan Aßmus void
AttachedToWindow()5799949213aSStephan Aßmus TranslatorWriteView::AttachedToWindow()
5809949213aSStephan Aßmus {
581b98ef4f9SStephan Aßmus 	BView::AttachedToWindow();
582b20d13f4SStefano Ceccherini 
5838687ff64SAxel Dörfler 	fQualitySlider->SetTarget(this);
5848687ff64SAxel Dörfler 	fSmoothingSlider->SetTarget(this);
5858687ff64SAxel Dörfler 	fProgress->SetTarget(this);
5868687ff64SAxel Dörfler 	fOptimizeColors->SetTarget(this);
5878687ff64SAxel Dörfler 	fSmallerFile->SetTarget(this);
5888687ff64SAxel Dörfler 	fGrayAsRGB24->SetTarget(this);
5899949213aSStephan Aßmus }
5909949213aSStephan Aßmus 
5918687ff64SAxel Dörfler 
5929949213aSStephan Aßmus void
MessageReceived(BMessage * message)5939949213aSStephan Aßmus TranslatorWriteView::MessageReceived(BMessage* message)
5949949213aSStephan Aßmus {
5958687ff64SAxel Dörfler 	switch (message->what) {
5969949213aSStephan Aßmus 		case VIEW_MSG_SET_QUALITY:
5979949213aSStephan Aßmus 		{
5989949213aSStephan Aßmus 			int32 value;
5999949213aSStephan Aßmus 			if (message->FindInt32("be:value", &value) == B_OK) {
600b98ef4f9SStephan Aßmus 				fSettings->SetGetInt32(JPEG_SET_QUALITY, &value);
601b98ef4f9SStephan Aßmus 				fSettings->SaveSettings();
6029949213aSStephan Aßmus 			}
6039949213aSStephan Aßmus 			break;
6049949213aSStephan Aßmus 		}
6059949213aSStephan Aßmus 		case VIEW_MSG_SET_SMOOTHING:
6069949213aSStephan Aßmus 		{
6079949213aSStephan Aßmus 			int32 value;
6089949213aSStephan Aßmus 			if (message->FindInt32("be:value", &value) == B_OK) {
609b98ef4f9SStephan Aßmus 				fSettings->SetGetInt32(JPEG_SET_SMOOTHING, &value);
610b98ef4f9SStephan Aßmus 				fSettings->SaveSettings();
6119949213aSStephan Aßmus 			}
6129949213aSStephan Aßmus 			break;
6139949213aSStephan Aßmus 		}
6149949213aSStephan Aßmus 		case VIEW_MSG_SET_PROGRESSIVE:
6159949213aSStephan Aßmus 		{
6169949213aSStephan Aßmus 			int32 value;
6179949213aSStephan Aßmus 			if (message->FindInt32("be:value", &value) == B_OK) {
618b98ef4f9SStephan Aßmus 				bool boolValue = value;
619b98ef4f9SStephan Aßmus 				fSettings->SetGetBool(JPEG_SET_PROGRESSIVE, &boolValue);
620b98ef4f9SStephan Aßmus 				fSettings->SaveSettings();
6219949213aSStephan Aßmus 			}
6229949213aSStephan Aßmus 			break;
6239949213aSStephan Aßmus 		}
6249949213aSStephan Aßmus 		case VIEW_MSG_SET_OPTIMIZECOLORS:
6259949213aSStephan Aßmus 		{
6269949213aSStephan Aßmus 			int32 value;
6279949213aSStephan Aßmus 			if (message->FindInt32("be:value", &value) == B_OK) {
628b98ef4f9SStephan Aßmus 				bool boolValue = value;
629b98ef4f9SStephan Aßmus 				fSettings->SetGetBool(JPEG_SET_OPT_COLORS, &boolValue);
630b98ef4f9SStephan Aßmus 				fSmallerFile->SetEnabled(value);
631b98ef4f9SStephan Aßmus 				fSettings->SaveSettings();
6329949213aSStephan Aßmus 			}
6339949213aSStephan Aßmus 			break;
6349949213aSStephan Aßmus 		}
6359949213aSStephan Aßmus 		case VIEW_MSG_SET_SMALLERFILE:
6369949213aSStephan Aßmus 		{
6379949213aSStephan Aßmus 			int32 value;
6389949213aSStephan Aßmus 			if (message->FindInt32("be:value", &value) == B_OK) {
639b98ef4f9SStephan Aßmus 				bool boolValue = value;
640b98ef4f9SStephan Aßmus 				fSettings->SetGetBool(JPEG_SET_SMALL_FILES, &boolValue);
641b98ef4f9SStephan Aßmus 				fSettings->SaveSettings();
6429949213aSStephan Aßmus 			}
6439949213aSStephan Aßmus 			break;
6449949213aSStephan Aßmus 		}
6459949213aSStephan Aßmus 		case VIEW_MSG_SET_GRAY1ASRGB24:
6469949213aSStephan Aßmus 		{
6479949213aSStephan Aßmus 			int32 value;
6489949213aSStephan Aßmus 			if (message->FindInt32("be:value", &value) == B_OK) {
649b98ef4f9SStephan Aßmus 				bool boolValue = value;
650b98ef4f9SStephan Aßmus 				fSettings->SetGetBool(JPEG_SET_GRAY1_AS_RGB24, &boolValue);
651b98ef4f9SStephan Aßmus 				fSettings->SaveSettings();
6529949213aSStephan Aßmus 			}
6539949213aSStephan Aßmus 			break;
6549949213aSStephan Aßmus 		}
6559949213aSStephan Aßmus 		default:
6569949213aSStephan Aßmus 			BView::MessageReceived(message);
6579949213aSStephan Aßmus 			break;
6589949213aSStephan Aßmus 	}
6599949213aSStephan Aßmus }
6609949213aSStephan Aßmus 
6619949213aSStephan Aßmus 
662d8e2fb50SAxel Dörfler //	#pragma mark -
6639949213aSStephan Aßmus 
664d8e2fb50SAxel Dörfler 
TranslatorAboutView(const char * name)665b98ef4f9SStephan Aßmus TranslatorAboutView::TranslatorAboutView(const char* name)
666b98ef4f9SStephan Aßmus 	:
667b98ef4f9SStephan Aßmus 	BView(name, 0, new BGroupLayout(B_VERTICAL))
6689949213aSStephan Aßmus {
669b98ef4f9SStephan Aßmus 	BAlignment labelAlignment = BAlignment(B_ALIGN_LEFT, B_ALIGN_TOP);
6701da233a7SSiarzhuk Zharski 	BStringView* title = new BStringView("Title", sTranslatorName);
6719949213aSStephan Aßmus 	title->SetFont(be_bold_font);
672b98ef4f9SStephan Aßmus 	title->SetExplicitAlignment(labelAlignment);
6739949213aSStephan Aßmus 
6743292b902SHumdinger 	char versionString[100];
6753292b902SHumdinger 	snprintf(versionString, sizeof(versionString),
6763292b902SHumdinger 		B_TRANSLATE("Version %d.%d.%d"),
6773292b902SHumdinger 		(int)(sTranslatorVersion >> 8),
6783292b902SHumdinger 		(int)((sTranslatorVersion >> 4) & 0xf),
6793292b902SHumdinger 		(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);
686f0650dc9Slooncraz 	infoView->SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
687*5f61e00aSDale Cieslak 	rgb_color textColor = ui_color(B_PANEL_TEXT_COLOR);
688*5f61e00aSDale Cieslak 	infoView->SetFontAndColor(be_plain_font, B_FONT_ALL, &textColor);
689b98ef4f9SStephan Aßmus 	infoView->MakeEditable(false);
6909949213aSStephan Aßmus 
691d9c440a5SJanus 	BLayoutBuilder::Group<>(this, B_VERTICAL, 0)
692d9c440a5SJanus 		.SetInsets(B_USE_DEFAULT_SPACING)
693b98ef4f9SStephan Aßmus 		.Add(title)
694b98ef4f9SStephan Aßmus 		.Add(version)
6957d48219bSHannah Boneß 		.Add(infoView);
6969949213aSStephan Aßmus }
6979949213aSStephan Aßmus 
6989949213aSStephan Aßmus 
TranslatorView(const char * name,TranslatorSettings * settings)699b98ef4f9SStephan Aßmus TranslatorView::TranslatorView(const char* name, TranslatorSettings* settings)
700b98ef4f9SStephan Aßmus 	:
701d9c440a5SJanus 	BTabView(name, B_WIDTH_FROM_LABEL)
7029949213aSStephan Aßmus {
703d9c440a5SJanus 	SetBorder(B_NO_BORDER);
704d9c440a5SJanus 
70570d59669SSiarzhuk Zharski 	AddTab(new TranslatorWriteView(B_TRANSLATE("Write"), settings->Acquire()));
70670d59669SSiarzhuk Zharski 	AddTab(new TranslatorReadView(B_TRANSLATE("Read"), settings->Acquire()));
70770d59669SSiarzhuk Zharski 	AddTab(new TranslatorAboutView(B_TRANSLATE("About")));
7089949213aSStephan Aßmus 
709b98ef4f9SStephan Aßmus 	settings->Release();
7109949213aSStephan Aßmus }
7119949213aSStephan Aßmus 
7129949213aSStephan Aßmus 
713d8e2fb50SAxel Dörfler //	#pragma mark - Translator Add-On
7149949213aSStephan Aßmus 
7159949213aSStephan Aßmus 
716b98ef4f9SStephan Aßmus BView*
NewConfigView(TranslatorSettings * settings)717b98ef4f9SStephan Aßmus JPEGTranslator::NewConfigView(TranslatorSettings* settings)
7189949213aSStephan Aßmus {
719b98ef4f9SStephan Aßmus 	BView* configView = new TranslatorView("TranslatorView", settings);
720b98ef4f9SStephan Aßmus 	return configView;
7219949213aSStephan Aßmus }
7229949213aSStephan Aßmus 
723b98ef4f9SStephan Aßmus 
724d8e2fb50SAxel Dörfler /*! Determine whether or not we can handle this data */
7259949213aSStephan Aßmus status_t
DerivedIdentify(BPositionIO * inSource,const translation_format * inFormat,BMessage * ioExtension,translator_info * outInfo,uint32 outType)726b98ef4f9SStephan Aßmus JPEGTranslator::DerivedIdentify(BPositionIO* inSource,
727b98ef4f9SStephan Aßmus 	const translation_format* inFormat, BMessage* ioExtension,
728b98ef4f9SStephan Aßmus 	translator_info* outInfo, uint32 outType)
7299949213aSStephan Aßmus {
730d8e2fb50SAxel Dörfler 	if (outType != 0 && outType != B_TRANSLATOR_BITMAP && outType != JPEG_FORMAT)
7319949213aSStephan Aßmus 		return B_NO_TRANSLATOR;
7329949213aSStephan Aßmus 
7339949213aSStephan Aßmus 	// !!! You might need to make this buffer bigger to test for your native format
7349949213aSStephan Aßmus 	off_t position = inSource->Position();
7359949213aSStephan Aßmus 	char header[sizeof(TranslatorBitmap)];
7369949213aSStephan Aßmus 	status_t err = inSource->Read(header, sizeof(TranslatorBitmap));
7379949213aSStephan Aßmus 	inSource->Seek(position, SEEK_SET);
738d8e2fb50SAxel Dörfler 	if (err < B_OK)
739d8e2fb50SAxel Dörfler 		return err;
7409949213aSStephan Aßmus 
7419949213aSStephan Aßmus 	if (B_BENDIAN_TO_HOST_INT32(((TranslatorBitmap *)header)->magic) == B_TRANSLATOR_BITMAP) {
742b98ef4f9SStephan Aßmus 		if (PopulateInfoFromFormat(outInfo, B_TRANSLATOR_BITMAP) != B_OK)
743b98ef4f9SStephan Aßmus 			return B_NO_TRANSLATOR;
7449949213aSStephan Aßmus 	} else {
7459949213aSStephan Aßmus 		// First 3 bytes in jpg files are always the same from what i've seen so far
7469949213aSStephan Aßmus 		// check them
7479949213aSStephan Aßmus 		if (header[0] == (char)0xff && header[1] == (char)0xd8 && header[2] == (char)0xff) {
748b98ef4f9SStephan Aßmus 			if (PopulateInfoFromFormat(outInfo, JPEG_FORMAT) != B_OK)
7499949213aSStephan Aßmus 				return B_NO_TRANSLATOR;
750b98ef4f9SStephan Aßmus 
7519949213aSStephan Aßmus 		} else
7529949213aSStephan Aßmus 			return B_NO_TRANSLATOR;
7539949213aSStephan Aßmus 	}
7549949213aSStephan Aßmus 
7559949213aSStephan Aßmus 	return B_OK;
7569949213aSStephan Aßmus }
7579949213aSStephan Aßmus 
758b98ef4f9SStephan Aßmus 
7599949213aSStephan Aßmus status_t
DerivedTranslate(BPositionIO * inSource,const translator_info * inInfo,BMessage * ioExtension,uint32 outType,BPositionIO * outDestination,int32 baseType)760b98ef4f9SStephan Aßmus JPEGTranslator::DerivedTranslate(BPositionIO* inSource,
761b98ef4f9SStephan Aßmus 	const translator_info* inInfo, BMessage* ioExtension, uint32 outType,
762b98ef4f9SStephan Aßmus 	BPositionIO* outDestination, int32 baseType)
7639949213aSStephan Aßmus {
764dbc936acSStephan Aßmus 	// Setup a "breakpoint" since throwing exceptions does not seem to work
765dbc936acSStephan Aßmus 	// at all in an add-on. (?)
766dbc936acSStephan Aßmus 	// In the be_jerror.cpp we implement a handler for critical library errors
767dbc936acSStephan Aßmus 	// (be_error_exit()) and there we use the longjmp() function to return to
768dbc936acSStephan Aßmus 	// this place. If this happens, it is as if the setjmp() call is called
769dbc936acSStephan Aßmus 	// a second time, but this time the return value will be 1. The first
770dbc936acSStephan Aßmus 	// invokation will return 0.
771b91634cbSStephan Aßmus 	jmp_buf longJumpBuffer;
772b91634cbSStephan Aßmus 	int jmpRet = setjmp(longJumpBuffer);
773dbc936acSStephan Aßmus 	if (jmpRet == 1)
774dbc936acSStephan Aßmus 		return B_ERROR;
775dbc936acSStephan Aßmus 
776dbc936acSStephan Aßmus 	try {
7779949213aSStephan Aßmus 		// What action to take, based on the findings of Identify()
7789949213aSStephan Aßmus 		if (outType == inInfo->type) {
7799949213aSStephan Aßmus 			return Copy(inSource, outDestination);
780dbc936acSStephan Aßmus 		} else if (inInfo->type == B_TRANSLATOR_BITMAP
781dbc936acSStephan Aßmus 				&& outType == JPEG_FORMAT) {
782b91634cbSStephan Aßmus 			return Compress(inSource, outDestination, &longJumpBuffer);
783dbc936acSStephan Aßmus 		} else if (inInfo->type == JPEG_FORMAT
784863a6388SAdrien Destugues 				&& (outType == B_TRANSLATOR_BITMAP || outType == 0)) {
785863a6388SAdrien Destugues 			// This is the default if no specific outType was requested.
786b91634cbSStephan Aßmus 			return Decompress(inSource, outDestination, ioExtension,
787b91634cbSStephan Aßmus 				&longJumpBuffer);
7889949213aSStephan Aßmus 		}
789dbc936acSStephan Aßmus 	} catch (...) {
79070d59669SSiarzhuk Zharski 		syslog(LOG_ERR, "libjpeg encountered a critical error (caught C++ "
79170d59669SSiarzhuk Zharski 			"exception).\n");
792dbc936acSStephan Aßmus 		return B_ERROR;
793dbc936acSStephan Aßmus 	}
7949949213aSStephan Aßmus 
7959949213aSStephan Aßmus 	return B_NO_TRANSLATOR;
7969949213aSStephan Aßmus }
7979949213aSStephan Aßmus 
798b98ef4f9SStephan Aßmus 
799d8e2fb50SAxel Dörfler /*!	The user has requested the same format for input and output, so just copy */
800b98ef4f9SStephan Aßmus status_t
Copy(BPositionIO * in,BPositionIO * out)801b98ef4f9SStephan Aßmus JPEGTranslator::Copy(BPositionIO* in, BPositionIO* out)
8029949213aSStephan Aßmus {
8039949213aSStephan Aßmus 	int block_size = 65536;
8049949213aSStephan Aßmus 	void* buffer = malloc(block_size);
8059949213aSStephan Aßmus 	char temp[1024];
8069949213aSStephan Aßmus 	if (buffer == NULL) {
8079949213aSStephan Aßmus 		buffer = temp;
8089949213aSStephan Aßmus 		block_size = 1024;
8099949213aSStephan Aßmus 	}
8109949213aSStephan Aßmus 	status_t err = B_OK;
8119949213aSStephan Aßmus 
8129949213aSStephan Aßmus 	// Read until end of file or error
8139949213aSStephan Aßmus 	while (1) {
8149949213aSStephan Aßmus 		ssize_t to_read = block_size;
8159949213aSStephan Aßmus 		err = in->Read(buffer, to_read);
8169949213aSStephan Aßmus 		// Explicit check for EOF
8179949213aSStephan Aßmus 		if (err == -1) {
8189949213aSStephan Aßmus 			if (buffer != temp) free(buffer);
8199949213aSStephan Aßmus 			return B_OK;
8209949213aSStephan Aßmus 		}
8219949213aSStephan Aßmus 		if (err <= B_OK) break;
8229949213aSStephan Aßmus 		to_read = err;
8239949213aSStephan Aßmus 		err = out->Write(buffer, to_read);
8249949213aSStephan Aßmus 		if (err != to_read) if (err >= 0) err = B_DEVICE_FULL;
8259949213aSStephan Aßmus 		if (err < B_OK) break;
8269949213aSStephan Aßmus 	}
8279949213aSStephan Aßmus 
8289949213aSStephan Aßmus 	if (buffer != temp) free(buffer);
8299949213aSStephan Aßmus 	return (err >= 0) ? B_OK : err;
8309949213aSStephan Aßmus }
8319949213aSStephan Aßmus 
832d8e2fb50SAxel Dörfler 
833d8e2fb50SAxel Dörfler /*!	Encode into the native format */
834b98ef4f9SStephan Aßmus status_t
Compress(BPositionIO * in,BPositionIO * out,const jmp_buf * longJumpBuffer)835b98ef4f9SStephan Aßmus JPEGTranslator::Compress(BPositionIO* in, BPositionIO* out,
836b98ef4f9SStephan Aßmus 	const jmp_buf* longJumpBuffer)
8379949213aSStephan Aßmus {
838b98ef4f9SStephan Aßmus 	using namespace conversion;
8399949213aSStephan Aßmus 
8409949213aSStephan Aßmus 	// Read info about bitmap
8419949213aSStephan Aßmus 	TranslatorBitmap header;
8429949213aSStephan Aßmus 	status_t err = in->Read(&header, sizeof(TranslatorBitmap));
843d8e2fb50SAxel Dörfler 	if (err < B_OK)
844d8e2fb50SAxel Dörfler 		return err;
845d8e2fb50SAxel Dörfler 	else if (err < (int)sizeof(TranslatorBitmap))
846d8e2fb50SAxel Dörfler 		return B_ERROR;
8479949213aSStephan Aßmus 
8489949213aSStephan Aßmus 	// Grab dimension, color space, and size information from the stream
8499949213aSStephan Aßmus 	BRect bounds;
8509949213aSStephan Aßmus 	bounds.left = B_BENDIAN_TO_HOST_FLOAT(header.bounds.left);
8519949213aSStephan Aßmus 	bounds.top = B_BENDIAN_TO_HOST_FLOAT(header.bounds.top);
8529949213aSStephan Aßmus 	bounds.right = B_BENDIAN_TO_HOST_FLOAT(header.bounds.right);
8539949213aSStephan Aßmus 	bounds.bottom = B_BENDIAN_TO_HOST_FLOAT(header.bounds.bottom);
8549949213aSStephan Aßmus 
8559949213aSStephan Aßmus 	int32 in_row_bytes = B_BENDIAN_TO_HOST_INT32(header.rowBytes);
8569949213aSStephan Aßmus 
8579949213aSStephan Aßmus 	int width = bounds.IntegerWidth() + 1;
8589949213aSStephan Aßmus 	int height = bounds.IntegerHeight() + 1;
8599949213aSStephan Aßmus 
8609949213aSStephan Aßmus 	// Function pointer to convert function
8619949213aSStephan Aßmus 	// It will point to proper function if needed
8629e34f742SAxel Dörfler 	void (*converter)(uchar* inscanline, uchar* outscanline,
8639e34f742SAxel Dörfler 		int32 inRowBytes) = NULL;
8649949213aSStephan Aßmus 
8659949213aSStephan Aßmus 	// Default color info
8669949213aSStephan Aßmus 	J_COLOR_SPACE jpg_color_space = JCS_RGB;
8679949213aSStephan Aßmus 	int jpg_input_components = 3;
8689949213aSStephan Aßmus 	int32 out_row_bytes;
8699949213aSStephan Aßmus 	int padding = 0;
8709949213aSStephan Aßmus 
871d8e2fb50SAxel Dörfler 	switch ((color_space)B_BENDIAN_TO_HOST_INT32(header.colors)) {
8729949213aSStephan Aßmus 		case B_CMAP8:
8739949213aSStephan Aßmus 			converter = convert_from_cmap8_to_24;
8749949213aSStephan Aßmus 			padding = in_row_bytes - width;
8759949213aSStephan Aßmus 			break;
876d8e2fb50SAxel Dörfler 
8779949213aSStephan Aßmus 		case B_GRAY1:
878b98ef4f9SStephan Aßmus 			if (fSettings->SetGetBool(JPEG_SET_GRAY1_AS_RGB24, NULL)) {
8799949213aSStephan Aßmus 				converter = convert_from_gray1_to_24;
8809949213aSStephan Aßmus 			} else {
8819949213aSStephan Aßmus 				jpg_input_components = 1;
8829949213aSStephan Aßmus 				jpg_color_space = JCS_GRAYSCALE;
8839949213aSStephan Aßmus 				converter = convert_from_gray1_to_gray8;
8849949213aSStephan Aßmus 			}
8859949213aSStephan Aßmus 			padding = in_row_bytes - (width / 8);
8869949213aSStephan Aßmus 			break;
887d8e2fb50SAxel Dörfler 
8889949213aSStephan Aßmus 		case B_GRAY8:
8899949213aSStephan Aßmus 			jpg_input_components = 1;
8909949213aSStephan Aßmus 			jpg_color_space = JCS_GRAYSCALE;
8919949213aSStephan Aßmus 			padding = in_row_bytes - width;
8929949213aSStephan Aßmus 			break;
893d8e2fb50SAxel Dörfler 
8949949213aSStephan Aßmus 		case B_RGB15:
8959949213aSStephan Aßmus 		case B_RGBA15:
8969949213aSStephan Aßmus 			converter = convert_from_15_to_24;
8979949213aSStephan Aßmus 			padding = in_row_bytes - (width * 2);
8989949213aSStephan Aßmus 			break;
899d8e2fb50SAxel Dörfler 
9009949213aSStephan Aßmus 		case B_RGB15_BIG:
9019949213aSStephan Aßmus 		case B_RGBA15_BIG:
9029949213aSStephan Aßmus 			converter = convert_from_15b_to_24;
9039949213aSStephan Aßmus 			padding = in_row_bytes - (width * 2);
9049949213aSStephan Aßmus 			break;
905d8e2fb50SAxel Dörfler 
9069949213aSStephan Aßmus 		case B_RGB16:
9079949213aSStephan Aßmus 			converter = convert_from_16_to_24;
9089949213aSStephan Aßmus 			padding = in_row_bytes - (width * 2);
9099949213aSStephan Aßmus 			break;
910d8e2fb50SAxel Dörfler 
9119949213aSStephan Aßmus 		case B_RGB16_BIG:
9129949213aSStephan Aßmus 			converter = convert_from_16b_to_24;
9139949213aSStephan Aßmus 			padding = in_row_bytes - (width * 2);
9149949213aSStephan Aßmus 			break;
915d8e2fb50SAxel Dörfler 
9169949213aSStephan Aßmus 		case B_RGB24:
9179949213aSStephan Aßmus 			converter = convert_from_24_to_24;
9189949213aSStephan Aßmus 			padding = in_row_bytes - (width * 3);
9199949213aSStephan Aßmus 			break;
920d8e2fb50SAxel Dörfler 
9219949213aSStephan Aßmus 		case B_RGB24_BIG:
9229949213aSStephan Aßmus 			padding = in_row_bytes - (width * 3);
9239949213aSStephan Aßmus 			break;
924d8e2fb50SAxel Dörfler 
9259949213aSStephan Aßmus 		case B_RGB32:
9269949213aSStephan Aßmus 		case B_RGBA32:
9279949213aSStephan Aßmus 			converter = convert_from_32_to_24;
9289949213aSStephan Aßmus 			padding = in_row_bytes - (width * 4);
9299949213aSStephan Aßmus 			break;
930d8e2fb50SAxel Dörfler 
9319949213aSStephan Aßmus 		case B_RGB32_BIG:
9329949213aSStephan Aßmus 		case B_RGBA32_BIG:
9339949213aSStephan Aßmus 			converter = convert_from_32b_to_24;
9349949213aSStephan Aßmus 			padding = in_row_bytes - (width * 4);
9359949213aSStephan Aßmus 			break;
936d8e2fb50SAxel Dörfler 
9379949213aSStephan Aßmus 		case B_CMYK32:
9389949213aSStephan Aßmus 			jpg_color_space = JCS_CMYK;
9399949213aSStephan Aßmus 			jpg_input_components = 4;
9409949213aSStephan Aßmus 			padding = in_row_bytes - (width * 4);
9419949213aSStephan Aßmus 			break;
942d8e2fb50SAxel Dörfler 
9439949213aSStephan Aßmus 		default:
94470d59669SSiarzhuk Zharski 			syslog(LOG_ERR, "Wrong type: Color space not implemented.\n");
9459949213aSStephan Aßmus 			return B_ERROR;
9469949213aSStephan Aßmus 	}
9479949213aSStephan Aßmus 	out_row_bytes = jpg_input_components * width;
9489949213aSStephan Aßmus 
9499949213aSStephan Aßmus 	// Set basic things needed for jpeg writing
9509949213aSStephan Aßmus 	struct jpeg_compress_struct cinfo;
951e4bd005dSIngo Weinhold 	struct be_jpeg_error_mgr jerr;
952b98ef4f9SStephan Aßmus 	cinfo.err = be_jpeg_std_error(&jerr, fSettings, longJumpBuffer);
9539949213aSStephan Aßmus 	jpeg_create_compress(&cinfo);
9549949213aSStephan Aßmus 	be_jpeg_stdio_dest(&cinfo, out);
9559949213aSStephan Aßmus 
9569949213aSStephan Aßmus 	// Set basic values
9579949213aSStephan Aßmus 	cinfo.image_width = width;
9589949213aSStephan Aßmus 	cinfo.image_height = height;
9599949213aSStephan Aßmus 	cinfo.input_components = jpg_input_components;
9609949213aSStephan Aßmus 	cinfo.in_color_space = jpg_color_space;
9619949213aSStephan Aßmus 	jpeg_set_defaults(&cinfo);
9629949213aSStephan Aßmus 
9639949213aSStephan Aßmus 	// Set better accuracy
9649949213aSStephan Aßmus 	cinfo.dct_method = JDCT_ISLOW;
9659949213aSStephan Aßmus 
9669949213aSStephan Aßmus 	// This is needed to prevent some colors loss
9679949213aSStephan Aßmus 	// With it generated jpegs are as good as from Fireworks (at last! :D)
968b98ef4f9SStephan Aßmus 	if (fSettings->SetGetBool(JPEG_SET_OPT_COLORS, NULL)) {
9699949213aSStephan Aßmus 		int index = 0;
9709949213aSStephan Aßmus 		while (index < cinfo.num_components) {
9719949213aSStephan Aßmus 			cinfo.comp_info[index].h_samp_factor = 1;
9729949213aSStephan Aßmus 			cinfo.comp_info[index].v_samp_factor = 1;
9739949213aSStephan Aßmus 			// This will make file smaller, but with worse quality more or less
9749949213aSStephan Aßmus 			// like with 93%-94% (but it's subjective opinion) on tested images
9759949213aSStephan Aßmus 			// but with smaller size (between 92% and 93% on tested images)
976b98ef4f9SStephan Aßmus 			if (fSettings->SetGetBool(JPEG_SET_SMALL_FILES))
9779949213aSStephan Aßmus 				cinfo.comp_info[index].quant_tbl_no = 1;
9789949213aSStephan Aßmus 			// This will make bigger file, but also better quality ;]
9799949213aSStephan Aßmus 			// from my tests it seems like useless - better quality with smaller
9809949213aSStephan Aßmus 			// can be acheived without this
9819949213aSStephan Aßmus //			cinfo.comp_info[index].dc_tbl_no = 1;
9829949213aSStephan Aßmus //			cinfo.comp_info[index].ac_tbl_no = 1;
9839949213aSStephan Aßmus 			index++;
9849949213aSStephan Aßmus 		}
9859949213aSStephan Aßmus 	}
9869949213aSStephan Aßmus 
9879949213aSStephan Aßmus 	// Set quality
988b98ef4f9SStephan Aßmus 	jpeg_set_quality(&cinfo, fSettings->SetGetInt32(JPEG_SET_QUALITY, NULL), true);
9899949213aSStephan Aßmus 
9909949213aSStephan Aßmus 	// Set progressive compression if needed
9919949213aSStephan Aßmus 	// if not, turn on optimizing in libjpeg
992b98ef4f9SStephan Aßmus 	if (fSettings->SetGetBool(JPEG_SET_PROGRESSIVE, NULL))
9939949213aSStephan Aßmus 		jpeg_simple_progression(&cinfo);
9949949213aSStephan Aßmus 	else
9959949213aSStephan Aßmus 		cinfo.optimize_coding = TRUE;
9969949213aSStephan Aßmus 
9979949213aSStephan Aßmus 	// Set smoothing (effect like Blur)
998b98ef4f9SStephan Aßmus 	cinfo.smoothing_factor = fSettings->SetGetInt32(JPEG_SET_SMOOTHING, NULL);
9999949213aSStephan Aßmus 
10009949213aSStephan Aßmus 	// Initialize compression
10019949213aSStephan Aßmus 	jpeg_start_compress(&cinfo, TRUE);
10029949213aSStephan Aßmus 
10039949213aSStephan Aßmus 	// Declare scanlines
10049949213aSStephan Aßmus 	JSAMPROW in_scanline = NULL;
10059949213aSStephan Aßmus 	JSAMPROW out_scanline = NULL;
1006b98ef4f9SStephan Aßmus 	JSAMPROW writeline;
1007b98ef4f9SStephan Aßmus 		// Pointer to in_scanline (default) or out_scanline (if there will be conversion)
10089949213aSStephan Aßmus 
10099949213aSStephan Aßmus 	// Allocate scanline
10109949213aSStephan Aßmus 	// Use libjpeg memory allocation functions, so in case of error it will free them itself
1011d8e2fb50SAxel Dörfler 	in_scanline = (unsigned char *)(cinfo.mem->alloc_large)((j_common_ptr)&cinfo,
1012d8e2fb50SAxel Dörfler 		JPOOL_PERMANENT, in_row_bytes);
10139949213aSStephan Aßmus 
10149949213aSStephan Aßmus 	// We need 2nd scanline storage ony for conversion
10159949213aSStephan Aßmus 	if (converter != NULL) {
10169949213aSStephan Aßmus 		// There will be conversion, allocate second scanline...
10179949213aSStephan Aßmus 		// Use libjpeg memory allocation functions, so in case of error it will free them itself
1018d8e2fb50SAxel Dörfler 	    out_scanline = (unsigned char *)(cinfo.mem->alloc_large)((j_common_ptr)&cinfo,
1019d8e2fb50SAxel Dörfler 	    	JPOOL_PERMANENT, out_row_bytes);
10209949213aSStephan Aßmus 		// ... and make it the one to write to file
10219949213aSStephan Aßmus 		writeline = out_scanline;
10229949213aSStephan Aßmus 	} else
10239949213aSStephan Aßmus 		writeline = in_scanline;
10249949213aSStephan Aßmus 
10259949213aSStephan Aßmus 	while (cinfo.next_scanline < cinfo.image_height) {
10269949213aSStephan Aßmus 		// Read scanline
10279949213aSStephan Aßmus 		err = in->Read(in_scanline, in_row_bytes);
10289949213aSStephan Aßmus 		if (err < in_row_bytes)
1029d8e2fb50SAxel Dörfler 			return err < B_OK ? Error((j_common_ptr)&cinfo, err)
1030d8e2fb50SAxel Dörfler 				: Error((j_common_ptr)&cinfo, B_ERROR);
10319949213aSStephan Aßmus 
10329949213aSStephan Aßmus 		// Convert if needed
10339949213aSStephan Aßmus 		if (converter != NULL)
10349949213aSStephan Aßmus 			converter(in_scanline, out_scanline, in_row_bytes - padding);
10359949213aSStephan Aßmus 
10369949213aSStephan Aßmus 		// Write scanline
10379949213aSStephan Aßmus 	   	jpeg_write_scanlines(&cinfo, &writeline, 1);
10389949213aSStephan Aßmus 	}
10399949213aSStephan Aßmus 
10409949213aSStephan Aßmus 	jpeg_finish_compress(&cinfo);
10419949213aSStephan Aßmus 	jpeg_destroy_compress(&cinfo);
10429949213aSStephan Aßmus 	return B_OK;
10439949213aSStephan Aßmus }
10449949213aSStephan Aßmus 
1045d8e2fb50SAxel Dörfler 
1046d8e2fb50SAxel Dörfler /*!	Decode the native format */
1047b98ef4f9SStephan Aßmus status_t
Decompress(BPositionIO * in,BPositionIO * out,BMessage * ioExtension,const jmp_buf * longJumpBuffer)1048b98ef4f9SStephan Aßmus JPEGTranslator::Decompress(BPositionIO* in, BPositionIO* out,
1049b98ef4f9SStephan Aßmus 	BMessage* ioExtension, const jmp_buf* longJumpBuffer)
10509949213aSStephan Aßmus {
1051b98ef4f9SStephan Aßmus 	using namespace conversion;
10529949213aSStephan Aßmus 
10539949213aSStephan Aßmus 	// Set basic things needed for jpeg reading
10549949213aSStephan Aßmus 	struct jpeg_decompress_struct cinfo;
1055e4bd005dSIngo Weinhold 	struct be_jpeg_error_mgr jerr;
1056b98ef4f9SStephan Aßmus 	cinfo.err = be_jpeg_std_error(&jerr, fSettings, longJumpBuffer);
10579949213aSStephan Aßmus 	jpeg_create_decompress(&cinfo);
10589949213aSStephan Aßmus 	be_jpeg_stdio_src(&cinfo, in);
10599949213aSStephan Aßmus 
106052e8f46aSAxel Dörfler 	jpeg_save_markers(&cinfo, MARKER_EXIF, 131072);
106152e8f46aSAxel Dörfler 		// make sure the EXIF tag is stored
106252e8f46aSAxel Dörfler 
10639949213aSStephan Aßmus 	// Read info about image
10649949213aSStephan Aßmus 	jpeg_read_header(&cinfo, TRUE);
10659949213aSStephan Aßmus 
106652e8f46aSAxel Dörfler 	BMessage exif;
106752e8f46aSAxel Dörfler 
1068f13b5de6SAxel Dörfler 	// parse EXIF data and add it ioExtension, if any
106952e8f46aSAxel Dörfler 	jpeg_marker_struct* marker = cinfo.marker_list;
107052e8f46aSAxel Dörfler 	while (marker != NULL) {
107152e8f46aSAxel Dörfler 		if (marker->marker == MARKER_EXIF
107252e8f46aSAxel Dörfler 			&& !strncmp((char*)marker->data, "Exif", 4)) {
1073f13b5de6SAxel Dörfler 			if (ioExtension != NULL) {
107452e8f46aSAxel Dörfler 				// Strip EXIF header from TIFF data
107552e8f46aSAxel Dörfler 				ioExtension->AddData("exif", B_RAW_TYPE,
107652e8f46aSAxel Dörfler 					(uint8*)marker->data + 6, marker->data_length - 6);
1077f13b5de6SAxel Dörfler 			}
107852e8f46aSAxel Dörfler 
107952e8f46aSAxel Dörfler 			BMemoryIO io(marker->data + 6, marker->data_length - 6);
108052e8f46aSAxel Dörfler 			convert_exif_to_message(io, exif);
108152e8f46aSAxel Dörfler 		}
108252e8f46aSAxel Dörfler 		marker = marker->next;
108352e8f46aSAxel Dörfler 	}
108452e8f46aSAxel Dörfler 
10859949213aSStephan Aßmus 	// Default color info
108652e8f46aSAxel Dörfler 	color_space outColorSpace = B_RGB32;
108752e8f46aSAxel Dörfler 	int outColorComponents = 4;
10889949213aSStephan Aßmus 
10899949213aSStephan Aßmus 	// Function pointer to convert function
10909949213aSStephan Aßmus 	// It will point to proper function if needed
109152e8f46aSAxel Dörfler 	void (*converter)(uchar* inScanLine, uchar* outScanLine,
10929e34f742SAxel Dörfler 		int32 inRowBytes, int32 xStep) = convert_from_24_to_32;
10939949213aSStephan Aßmus 
10949949213aSStephan Aßmus 	// If color space isn't rgb
10959949213aSStephan Aßmus 	if (cinfo.out_color_space != JCS_RGB) {
1096d8e2fb50SAxel Dörfler 		switch (cinfo.out_color_space) {
10979949213aSStephan Aßmus 			case JCS_UNKNOWN:		/* error/unspecified */
109870d59669SSiarzhuk Zharski 				syslog(LOG_ERR, "From Type: Jpeg uses unknown color type\n");
10999949213aSStephan Aßmus 				break;
11009949213aSStephan Aßmus 			case JCS_GRAYSCALE:		/* monochrome */
11019949213aSStephan Aßmus 				// Check if user wants to read only as RGB32 or not
1102b98ef4f9SStephan Aßmus 				if (!fSettings->SetGetBool(JPEG_SET_ALWAYS_RGB32, NULL)) {
11039949213aSStephan Aßmus 					// Grayscale
110452e8f46aSAxel Dörfler 					outColorSpace = B_GRAY8;
110552e8f46aSAxel Dörfler 					outColorComponents = 1;
11069e34f742SAxel Dörfler 					converter = translate_8;
11079949213aSStephan Aßmus 				} else {
11089949213aSStephan Aßmus 					// RGB
11099949213aSStephan Aßmus 					cinfo.out_color_space = JCS_RGB;
11109949213aSStephan Aßmus 					cinfo.output_components = 3;
11119949213aSStephan Aßmus 					converter = convert_from_24_to_32;
11129949213aSStephan Aßmus 				}
11139949213aSStephan Aßmus 				break;
11149949213aSStephan Aßmus 			case JCS_YCbCr:		/* Y/Cb/Cr (also known as YUV) */
11159949213aSStephan Aßmus 				cinfo.out_color_space = JCS_RGB;
11169949213aSStephan Aßmus 				converter = convert_from_24_to_32;
11179949213aSStephan Aßmus 				break;
11189949213aSStephan Aßmus 			case JCS_YCCK:		/* Y/Cb/Cr/K */
11199949213aSStephan Aßmus 				// Let libjpeg convert it to CMYK
11209949213aSStephan Aßmus 				cinfo.out_color_space = JCS_CMYK;
11219949213aSStephan Aßmus 				// Fall through to CMYK since we need the same settings
11229949213aSStephan Aßmus 			case JCS_CMYK:		/* C/M/Y/K */
11239949213aSStephan Aßmus 				// Use proper converter
1124b98ef4f9SStephan Aßmus 				if (fSettings->SetGetBool(JPEG_SET_PHOTOSHOP_CMYK))
11259949213aSStephan Aßmus 					converter = convert_from_CMYK_to_32_photoshop;
11269949213aSStephan Aßmus 				else
11279949213aSStephan Aßmus 					converter = convert_from_CMYK_to_32;
11289949213aSStephan Aßmus 				break;
11299949213aSStephan Aßmus 			default:
113070d59669SSiarzhuk Zharski 				syslog(LOG_ERR,
113170d59669SSiarzhuk Zharski 						"From Type: Jpeg uses hmm... i don't know really :(\n");
11329949213aSStephan Aßmus 				break;
11339949213aSStephan Aßmus 		}
11349949213aSStephan Aßmus 	}
11359949213aSStephan Aßmus 
11369949213aSStephan Aßmus 	// Initialize decompression
11379949213aSStephan Aßmus 	jpeg_start_decompress(&cinfo);
11389949213aSStephan Aßmus 
11399e34f742SAxel Dörfler 	// retrieve orientation from settings/EXIF
114052e8f46aSAxel Dörfler 	int32 orientation;
11419e34f742SAxel Dörfler 	if (ioExtension == NULL
11429e34f742SAxel Dörfler 		|| ioExtension->FindInt32("exif:orientation", &orientation) != B_OK) {
114352e8f46aSAxel Dörfler 		if (exif.FindInt32("Orientation", &orientation) != B_OK)
114452e8f46aSAxel Dörfler 			orientation = 1;
114552e8f46aSAxel Dörfler 	}
11469949213aSStephan Aßmus 
11479e34f742SAxel Dörfler 	if (orientation != 1 && converter == NULL)
11489e34f742SAxel Dörfler 		converter = translate_8;
11499e34f742SAxel Dörfler 
11509e34f742SAxel Dörfler 	int32 outputWidth = orientation > 4 ? cinfo.output_height : cinfo.output_width;
11519e34f742SAxel Dörfler 	int32 outputHeight = orientation > 4 ? cinfo.output_width : cinfo.output_height;
11529e34f742SAxel Dörfler 
11539e34f742SAxel Dörfler 	int32 destOffset = dest_index(outputWidth, outputHeight,
11549e34f742SAxel Dörfler 		0, 0, orientation) * outColorComponents;
11559e34f742SAxel Dörfler 	int32 xStep = dest_index(outputWidth, outputHeight,
11569e34f742SAxel Dörfler 		1, 0, orientation) * outColorComponents - destOffset;
11579e34f742SAxel Dörfler 	int32 yStep = dest_index(outputWidth, outputHeight,
11589e34f742SAxel Dörfler 		0, 1, orientation) * outColorComponents - destOffset;
11599e34f742SAxel Dörfler 	bool needAll = orientation != 1;
11609e34f742SAxel Dörfler 
11619e34f742SAxel Dörfler 	// Initialize this bounds rect to the size of your image
11629e34f742SAxel Dörfler 	BRect bounds(0, 0, outputWidth - 1, outputHeight - 1);
11639e34f742SAxel Dörfler 
11649e34f742SAxel Dörfler #if 0
11659e34f742SAxel Dörfler printf("destOffset = %ld, xStep = %ld, yStep = %ld, input: %ld x %ld, output: %ld x %ld, orientation %ld\n",
11669e34f742SAxel Dörfler 	destOffset, xStep, yStep, (int32)cinfo.output_width, (int32)cinfo.output_height,
11679e34f742SAxel Dörfler 	bounds.IntegerWidth() + 1, bounds.IntegerHeight() + 1, orientation);
11689e34f742SAxel Dörfler #endif
11699e34f742SAxel Dörfler 
11709949213aSStephan Aßmus 	// Bytes count in one line of image (scanline)
11719e34f742SAxel Dörfler 	int32 inRowBytes = cinfo.output_width * cinfo.output_components;
11729e34f742SAxel Dörfler 	int32 rowBytes = (bounds.IntegerWidth() + 1) * outColorComponents;
11739e34f742SAxel Dörfler 	int32 dataSize = cinfo.output_width * cinfo.output_height
11749e34f742SAxel Dörfler 		* outColorComponents;
11759949213aSStephan Aßmus 
11769949213aSStephan Aßmus 	// Fill out the B_TRANSLATOR_BITMAP's header
11779949213aSStephan Aßmus 	TranslatorBitmap header;
11789949213aSStephan Aßmus 	header.magic = B_HOST_TO_BENDIAN_INT32(B_TRANSLATOR_BITMAP);
11799949213aSStephan Aßmus 	header.bounds.left = B_HOST_TO_BENDIAN_FLOAT(bounds.left);
11809949213aSStephan Aßmus 	header.bounds.top = B_HOST_TO_BENDIAN_FLOAT(bounds.top);
11819949213aSStephan Aßmus 	header.bounds.right = B_HOST_TO_BENDIAN_FLOAT(bounds.right);
11829949213aSStephan Aßmus 	header.bounds.bottom = B_HOST_TO_BENDIAN_FLOAT(bounds.bottom);
118352e8f46aSAxel Dörfler 	header.colors = (color_space)B_HOST_TO_BENDIAN_INT32(outColorSpace);
118452e8f46aSAxel Dörfler 	header.rowBytes = B_HOST_TO_BENDIAN_INT32(rowBytes);
11859e34f742SAxel Dörfler 	header.dataSize = B_HOST_TO_BENDIAN_INT32(dataSize);
11869949213aSStephan Aßmus 
11879949213aSStephan Aßmus 	// Write out the header
11889949213aSStephan Aßmus 	status_t err = out->Write(&header, sizeof(TranslatorBitmap));
1189d8e2fb50SAxel Dörfler 	if (err < B_OK)
1190d8e2fb50SAxel Dörfler 		return Error((j_common_ptr)&cinfo, err);
1191d8e2fb50SAxel Dörfler 	else if (err < (int)sizeof(TranslatorBitmap))
1192d8e2fb50SAxel Dörfler 		return Error((j_common_ptr)&cinfo, B_ERROR);
11939949213aSStephan Aßmus 
11949949213aSStephan Aßmus 	// Declare scanlines
11959e34f742SAxel Dörfler 	JSAMPROW inScanLine = NULL;
11969e34f742SAxel Dörfler 	uint8* dest = NULL;
11979e34f742SAxel Dörfler 	uint8* destLine = NULL;
11989949213aSStephan Aßmus 
11999949213aSStephan Aßmus 	// Allocate scanline
12009949213aSStephan Aßmus 	// Use libjpeg memory allocation functions, so in case of error it will free them itself
12019e34f742SAxel Dörfler     inScanLine = (unsigned char *)(cinfo.mem->alloc_large)((j_common_ptr)&cinfo,
12029e34f742SAxel Dörfler     	JPOOL_PERMANENT, inRowBytes);
12039949213aSStephan Aßmus 
12049949213aSStephan Aßmus 	// We need 2nd scanline storage only for conversion
12059949213aSStephan Aßmus 	if (converter != NULL) {
12069949213aSStephan Aßmus 		// There will be conversion, allocate second scanline...
1207b98ef4f9SStephan Aßmus 		// Use libjpeg memory allocation functions, so in case of error it will
1208b98ef4f9SStephan Aßmus 		// free them itself
12099e34f742SAxel Dörfler 	    dest = (uint8*)(cinfo.mem->alloc_large)((j_common_ptr)&cinfo,
12109e34f742SAxel Dörfler 	    	JPOOL_PERMANENT, needAll ? dataSize : rowBytes);
12119e34f742SAxel Dörfler 	    destLine = dest + destOffset;
12129949213aSStephan Aßmus 	} else
12139e34f742SAxel Dörfler 		destLine = inScanLine;
12149949213aSStephan Aßmus 
12159949213aSStephan Aßmus 	while (cinfo.output_scanline < cinfo.output_height) {
12169949213aSStephan Aßmus 		// Read scanline
12179e34f742SAxel Dörfler 		jpeg_read_scanlines(&cinfo, &inScanLine, 1);
12189949213aSStephan Aßmus 
12199949213aSStephan Aßmus 		// Convert if needed
12209949213aSStephan Aßmus 		if (converter != NULL)
12219e34f742SAxel Dörfler 			converter(inScanLine, destLine, inRowBytes, xStep);
12229949213aSStephan Aßmus 
12239e34f742SAxel Dörfler 		if (!needAll) {
12249949213aSStephan Aßmus 	  		// Write the scanline buffer to the output stream
12259e34f742SAxel Dörfler 			ssize_t bytesWritten = out->Write(destLine, rowBytes);
12269e34f742SAxel Dörfler 			if (bytesWritten < rowBytes) {
12279e34f742SAxel Dörfler 				return bytesWritten < B_OK
12289e34f742SAxel Dörfler 					? Error((j_common_ptr)&cinfo, bytesWritten)
1229d8e2fb50SAxel Dörfler 					: Error((j_common_ptr)&cinfo, B_ERROR);
12309949213aSStephan Aßmus 			}
12319e34f742SAxel Dörfler 		} else
12329e34f742SAxel Dörfler 			destLine += yStep;
12339e34f742SAxel Dörfler 	}
12349e34f742SAxel Dörfler 
12359e34f742SAxel Dörfler 	if (needAll) {
12369e34f742SAxel Dörfler 		ssize_t bytesWritten = out->Write(dest, dataSize);
12379e34f742SAxel Dörfler 		if (bytesWritten < dataSize) {
12389e34f742SAxel Dörfler 			return bytesWritten < B_OK
12399e34f742SAxel Dörfler 				? Error((j_common_ptr)&cinfo, bytesWritten)
12409e34f742SAxel Dörfler 				: Error((j_common_ptr)&cinfo, B_ERROR);
12419e34f742SAxel Dörfler 		}
12429e34f742SAxel Dörfler 	}
12439949213aSStephan Aßmus 
12449949213aSStephan Aßmus 	jpeg_finish_decompress(&cinfo);
12459949213aSStephan Aßmus 	jpeg_destroy_decompress(&cinfo);
12469949213aSStephan Aßmus 	return B_OK;
12479949213aSStephan Aßmus }
12489949213aSStephan Aßmus 
1249b98ef4f9SStephan Aßmus /*! have the other PopulateInfoFromFormat() check both inputFormats & outputFormats */
1250b98ef4f9SStephan Aßmus status_t
PopulateInfoFromFormat(translator_info * info,uint32 formatType,translator_id id)1251b98ef4f9SStephan Aßmus JPEGTranslator::PopulateInfoFromFormat(translator_info* info,
1252b98ef4f9SStephan Aßmus 	uint32 formatType, translator_id id)
1253b98ef4f9SStephan Aßmus {
1254b98ef4f9SStephan Aßmus 	int32 formatCount;
1255b98ef4f9SStephan Aßmus 	const translation_format* formats = OutputFormats(&formatCount);
1256b98ef4f9SStephan Aßmus 	for (int i = 0; i <= 1 ;formats = InputFormats(&formatCount), i++) {
1257b98ef4f9SStephan Aßmus 		if (PopulateInfoFromFormat(info, formatType,
1258b98ef4f9SStephan Aßmus 			formats, formatCount) == B_OK) {
1259b98ef4f9SStephan Aßmus 			info->translator = id;
1260b98ef4f9SStephan Aßmus 			return B_OK;
1261b98ef4f9SStephan Aßmus 		}
1262b98ef4f9SStephan Aßmus 	}
1263b98ef4f9SStephan Aßmus 
1264b98ef4f9SStephan Aßmus 	return B_ERROR;
1265b98ef4f9SStephan Aßmus }
1266b98ef4f9SStephan Aßmus 
1267b98ef4f9SStephan Aßmus 
1268b98ef4f9SStephan Aßmus status_t
PopulateInfoFromFormat(translator_info * info,uint32 formatType,const translation_format * formats,int32 formatCount)1269b98ef4f9SStephan Aßmus JPEGTranslator::PopulateInfoFromFormat(translator_info* info,
1270b98ef4f9SStephan Aßmus 	uint32 formatType, const translation_format* formats, int32 formatCount)
1271b98ef4f9SStephan Aßmus {
1272b98ef4f9SStephan Aßmus 	for (int i = 0; i < formatCount; i++) {
1273b98ef4f9SStephan Aßmus 		if (formats[i].type == formatType) {
1274b98ef4f9SStephan Aßmus 			info->type = formatType;
1275b98ef4f9SStephan Aßmus 			info->group = formats[i].group;
1276b98ef4f9SStephan Aßmus 			info->quality = formats[i].quality;
1277b98ef4f9SStephan Aßmus 			info->capability = formats[i].capability;
127870d59669SSiarzhuk Zharski 			BString str1(formats[i].name);
127970d59669SSiarzhuk Zharski 			str1.ReplaceFirst("Be Bitmap Format (JPEGTranslator)",
128070d59669SSiarzhuk Zharski 				B_TRANSLATE("Be Bitmap Format (JPEGTranslator)"));
1281c7eabc40SMurai Takashi 			strlcpy(info->name, str1.String(), sizeof(info->name));
1282b98ef4f9SStephan Aßmus 			strcpy(info->MIME,  formats[i].MIME);
1283b98ef4f9SStephan Aßmus 			return B_OK;
1284b98ef4f9SStephan Aßmus 		}
1285b98ef4f9SStephan Aßmus 	}
1286b98ef4f9SStephan Aßmus 
1287b98ef4f9SStephan Aßmus 	return B_ERROR;
1288b98ef4f9SStephan Aßmus }
1289b98ef4f9SStephan Aßmus 
1290d8e2fb50SAxel Dörfler /*!
1291d8e2fb50SAxel Dörfler 	Frees jpeg alocated memory
1292d8e2fb50SAxel Dörfler 	Returns given error (B_ERROR by default)
1293d8e2fb50SAxel Dörfler */
1294b98ef4f9SStephan Aßmus status_t
Error(j_common_ptr cinfo,status_t error)1295b98ef4f9SStephan Aßmus JPEGTranslator::Error(j_common_ptr cinfo, status_t error)
12969949213aSStephan Aßmus {
12979949213aSStephan Aßmus 	jpeg_destroy(cinfo);
12989949213aSStephan Aßmus 	return error;
12999949213aSStephan Aßmus }
1300d8e2fb50SAxel Dörfler 
1301d8e2fb50SAxel Dörfler 
JPEGTranslator()1302b98ef4f9SStephan Aßmus JPEGTranslator::JPEGTranslator()
1303bf243977SPhilippe Houdoin 	: BaseTranslator(sTranslatorName, sTranslatorInfo, sTranslatorVersion,
1304bf243977SPhilippe Houdoin 		sInputFormats,  kNumInputFormats,
1305bf243977SPhilippe Houdoin 		sOutputFormats, kNumOutputFormats,
1306bf243977SPhilippe Houdoin 		SETTINGS_FILE,
1307bf243977SPhilippe Houdoin 		sDefaultSettings, kNumDefaultSettings,
1308b98ef4f9SStephan Aßmus 		B_TRANSLATOR_BITMAP, JPEG_FORMAT)
1309b98ef4f9SStephan Aßmus {}
1310b98ef4f9SStephan Aßmus 
1311b98ef4f9SStephan Aßmus 
1312b98ef4f9SStephan Aßmus BTranslator*
make_nth_translator(int32 n,image_id you,uint32 flags,...)1313b98ef4f9SStephan Aßmus make_nth_translator(int32 n, image_id you, uint32 flags, ...)
1314b98ef4f9SStephan Aßmus {
1315b98ef4f9SStephan Aßmus 	if (n == 0)
1316b98ef4f9SStephan Aßmus 		return new JPEGTranslator();
1317b98ef4f9SStephan Aßmus 
1318b98ef4f9SStephan Aßmus 	return NULL;
1319b98ef4f9SStephan Aßmus }
1320d8e2fb50SAxel Dörfler 
1321d8e2fb50SAxel Dörfler 
1322d8e2fb50SAxel Dörfler int
main(int,char **)1323117da2d7SAxel Dörfler main(int, char**)
1324117da2d7SAxel Dörfler {
1325117da2d7SAxel Dörfler 	BApplication app("application/x-vnd.Haiku-JPEGTranslator");
1326b98ef4f9SStephan Aßmus 	JPEGTranslator* translator = new JPEGTranslator();
1327bf243977SPhilippe Houdoin 	if (LaunchTranslatorWindow(translator, sTranslatorName) == B_OK)
1328d8e2fb50SAxel Dörfler 		app.Run();
1329b98ef4f9SStephan Aßmus 
1330d8e2fb50SAxel Dörfler 	return 0;
1331d8e2fb50SAxel Dörfler }
1332d8e2fb50SAxel Dörfler 
1333