xref: /haiku/src/add-ons/translators/jpeg2000/JPEG2000Translator.cpp (revision eea5774f46bba925156498abf9cb1a1165647bf7)
1 /*
2 
3 Copyright (c) 2003, Marcin 'Shard' Konicki
4 All rights reserved.
5 
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
8 
9     * Redistributions of source code must retain the above copyright notice,
10       this list of conditions and the following disclaimer.
11     * Redistributions in binary form must reproduce the above copyright notice,
12       this list of conditions and the following disclaimer in the documentation and/or
13       other materials provided with the distribution.
14     * Name "Marcin Konicki", "Shard" or any combination of them,
15       must not be used to endorse or promote products derived from this
16       software without specific prior written permission from Marcin Konicki.
17 
18 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
22 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
23 OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
28 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 
30 */
31 
32 
33 #include "JPEG2000Translator.h"
34 #include "TranslatorWindow.h"
35 
36 #include <syslog.h>
37 
38 #include <LayoutBuilder.h>
39 #include <TabView.h>
40 #include <TextView.h>
41 
42 
43 #undef B_TRANSLATION_CONTEXT
44 #define B_TRANSLATION_CONTEXT "JPEG2000Translator"
45 
46 // Set these accordingly
47 #define JP2_ACRONYM "JP2"
48 #define JP2_FORMAT 'JP2 '
49 #define JP2_MIME_STRING "image/jp2"
50 #define JP2_DESCRIPTION "JPEG2000 image"
51 
52 // The translation kit's native file type
53 #define B_TRANSLATOR_BITMAP_MIME_STRING "image/x-be-bitmap"
54 #define B_TRANSLATOR_BITMAP_DESCRIPTION "Be Bitmap Format (JPEG2000Translator)"
55 
56 static int32 sTranslatorVersion = B_TRANSLATION_MAKE_VERSION(1, 0, 0);
57 
58 static const char* sTranslatorName = B_TRANSLATE("JPEG2000 images");
59 static const char* sTranslatorInfo = B_TRANSLATE("©2002-2003, Shard\n"
60 	"©2005-2006, Haiku\n"
61 	"\n"
62 	"Based on JasPer library:\n"
63 	"© 1999-2000, Image Power, Inc. and\n"
64 	"the University of British Columbia, Canada.\n"
65 	"© 2001-2003 Michael David Adams.\n"
66 	"\thttp://www.ece.uvic.ca/~mdadams/jasper/\n"
67 	"\n"
68 	"ImageMagick's jp2 codec was used as \"tutorial\".\n"
69 	"\thttp://www.imagemagick.org/\n");
70 
71 static const translation_format sInputFormats[] = {
72 	{ JP2_FORMAT, B_TRANSLATOR_BITMAP, 0.5, 0.5,
73 		JP2_MIME_STRING, JP2_DESCRIPTION },
74 	{ B_TRANSLATOR_BITMAP, B_TRANSLATOR_BITMAP, 0.5, 0.5,
75 		B_TRANSLATOR_BITMAP_MIME_STRING, B_TRANSLATOR_BITMAP_DESCRIPTION },
76 };
77 
78 static const translation_format sOutputFormats[] = {
79 	{ JP2_FORMAT, B_TRANSLATOR_BITMAP, 0.5, 0.5,
80 		JP2_MIME_STRING, JP2_DESCRIPTION },
81 	{ B_TRANSLATOR_BITMAP, B_TRANSLATOR_BITMAP, 0.5, 0.5,
82 		B_TRANSLATOR_BITMAP_MIME_STRING, B_TRANSLATOR_BITMAP_DESCRIPTION },
83 };
84 
85 
86 static const TranSetting sDefaultSettings[] = {
87 	{JP2_SET_QUALITY, TRAN_SETTING_INT32, 25},
88 	{JP2_SET_JPC, TRAN_SETTING_BOOL, false},
89 	{JP2_SET_GRAY1_AS_B_RGB24, TRAN_SETTING_BOOL, false},
90 	{JP2_SET_GRAY8_AS_B_RGB32, TRAN_SETTING_BOOL, true}
91 };
92 
93 const uint32 kNumInputFormats = sizeof(sInputFormats) / sizeof(translation_format);
94 const uint32 kNumOutputFormats = sizeof(sOutputFormats) / sizeof(translation_format);
95 const uint32 kNumDefaultSettings = sizeof(sDefaultSettings) / sizeof(TranSetting);
96 
97 
98 #define	JP2_BOX_JP		0x6a502020
99 #define	JPC_MS_SOC		0xff4f
100 
101 
102 namespace conversion{
103 //!	Make RGB32 scanline from *pixels[3]
104 inline void
105 read_rgb24_to_rgb32(jas_matrix_t** pixels, uchar* scanline, int width)
106 {
107 	int32 index = 0;
108 	int32 x = 0;
109 	while (x < width) {
110 		scanline[index++] = (uchar)jas_matrix_getv(pixels[2], x);
111 		scanline[index++] = (uchar)jas_matrix_getv(pixels[1], x);
112 		scanline[index++] = (uchar)jas_matrix_getv(pixels[0], x);
113 		scanline[index++] = 255;
114 		x++;
115 	}
116 }
117 
118 
119 //!	Make gray scanline from *pixels[1]
120 inline void
121 read_gray_to_rgb32(jas_matrix_t** pixels, uchar* scanline, int width)
122 {
123 	int32 index = 0;
124 	int32 x = 0;
125 	uchar color = 0;
126 	while (x < width) {
127 		color = (uchar)jas_matrix_getv(pixels[0], x++);
128 		scanline[index++] = color;
129 		scanline[index++] = color;
130 		scanline[index++] = color;
131 		scanline[index++] = 255;
132 	}
133 }
134 
135 
136 /*!
137 	Make RGBA32 scanline from *pixels[4]
138 	(just read data to scanline)
139 */
140 inline void
141 read_rgba32(jas_matrix_t** pixels, uchar *scanline, int width)
142 {
143 	int32 index = 0;
144 	int32 x = 0;
145 	while (x < width) {
146 		scanline[index++] = (uchar)jas_matrix_getv(pixels[2], x);
147 		scanline[index++] = (uchar)jas_matrix_getv(pixels[1], x);
148 		scanline[index++] = (uchar)jas_matrix_getv(pixels[0], x);
149 		scanline[index++] = (uchar)jas_matrix_getv(pixels[3], x);
150 		x++;
151 	}
152 }
153 
154 
155 /*!
156 	Make gray scanline from *pixels[1]
157 	(just read data to scanline)
158 */
159 inline void
160 read_gray(jas_matrix_t** pixels, uchar* scanline, int width)
161 {
162 	int32 x = 0;
163 	while (x < width) {
164 		scanline[x] = (uchar)jas_matrix_getv(pixels[0], x);
165 		x++;
166 	}
167 }
168 
169 
170 //!	Make *pixels[1] from gray1 scanline
171 inline void
172 write_gray1_to_gray(jas_matrix_t** pixels, uchar* scanline, int width)
173 {
174 	int32 x = 0;
175 	int32 index = 0;
176 	while (x < (width/8)) {
177 		unsigned char c = scanline[x++];
178 		for (int b = 128; b; b = b >> 1) {
179 			if (c & b)
180 				jas_matrix_setv(pixels[0], index++, 0);
181 			else
182 				jas_matrix_setv(pixels[0], index++, 255);
183 		}
184 	}
185 }
186 
187 
188 //!	Make *pixels[3] from gray1 scanline
189 inline void
190 write_gray1_to_rgb24(jas_matrix_t** pixels, uchar* scanline, int width)
191 {
192 	int32 x = 0;
193 	int32 index = 0;
194 	while (x < (width / 8)) {
195 		unsigned char c = scanline[x++];
196 		for (int b = 128; b; b = b >> 1) {
197 			if (c & b) {
198 				jas_matrix_setv(pixels[0], index, 0);
199 				jas_matrix_setv(pixels[1], index, 0);
200 				jas_matrix_setv(pixels[2], index, 0);
201 			} else {
202 				jas_matrix_setv(pixels[0], index, 255);
203 				jas_matrix_setv(pixels[1], index, 255);
204 				jas_matrix_setv(pixels[2], index, 255);
205 			}
206 			index++;
207 		}
208 	}
209 }
210 
211 
212 //!	Make *pixels[3] from cmap8 scanline
213 inline void
214 write_cmap8_to_rgb24(jas_matrix_t** pixels, uchar* scanline, int width)
215 {
216 	const color_map* map = system_colors();
217 	int32 x = 0;
218 	while (x < width) {
219 		rgb_color color = map->color_list[scanline[x]];
220 
221 		jas_matrix_setv(pixels[0], x, color.red);
222 		jas_matrix_setv(pixels[1], x, color.green);
223 		jas_matrix_setv(pixels[2], x, color.blue);
224 		x++;
225 	}
226 }
227 
228 
229 /*!
230 	Make *pixels[1] from gray scanline
231 	(just write data to pixels)
232 */
233 inline void
234 write_gray(jas_matrix_t** pixels, uchar* scanline, int width)
235 {
236 	int32 x = 0;
237 	while (x < width) {
238 		jas_matrix_setv(pixels[0], x, scanline[x]);
239 		x++;
240 	}
241 }
242 
243 
244 /*!
245 	Make *pixels[3] from RGB15/RGBA15 scanline
246 	(just write data to pixels)
247 */
248 inline void
249 write_rgb15_to_rgb24(jas_matrix_t** pixels, uchar* scanline, int width)
250 {
251 	int32 x = 0;
252 	int32 index = 0;
253 	int16 in_pixel;
254 	while (x < width) {
255 		in_pixel = scanline[index] | (scanline[index+1] << 8);
256 		index += 2;
257 
258 		jas_matrix_setv(pixels[0], x, (char)(((in_pixel & 0x7c00)) >> 7)
259 			| (((in_pixel & 0x7c00)) >> 12));
260 		jas_matrix_setv(pixels[1], x, (char)(((in_pixel & 0x3e0)) >> 2)
261 			| (((in_pixel & 0x3e0)) >> 7));
262 		jas_matrix_setv(pixels[2], x, (char)(((in_pixel & 0x1f)) << 3)
263 			| (((in_pixel & 0x1f)) >> 2));
264 		x++;
265 	}
266 }
267 
268 
269 /*!
270 	Make *pixels[3] from RGB15/RGBA15 bigendian scanline
271 	(just write data to pixels)
272 */
273 inline void
274 write_rgb15b_to_rgb24(jas_matrix_t** pixels, uchar* scanline, int width)
275 {
276 	int32 x = 0;
277 	int32 index = 0;
278 	int16 in_pixel;
279 	while (x < width) {
280 		in_pixel = scanline[index + 1] | (scanline[index] << 8);
281 		index += 2;
282 
283 		jas_matrix_setv(pixels[0], x, (char)(((in_pixel & 0x7c00)) >> 7)
284 			| (((in_pixel & 0x7c00)) >> 12));
285 		jas_matrix_setv(pixels[1], x, (char)(((in_pixel & 0x3e0)) >> 2)
286 			| (((in_pixel & 0x3e0)) >> 7));
287 		jas_matrix_setv(pixels[2], x, (char)(((in_pixel & 0x1f)) << 3)
288 			| (((in_pixel & 0x1f)) >> 2));
289 		x++;
290 	}
291 }
292 
293 
294 /*!
295 	Make *pixels[3] from RGB16/RGBA16 scanline
296 	(just write data to pixels)
297 */
298 inline void
299 write_rgb16_to_rgb24(jas_matrix_t** pixels, uchar* scanline, int width)
300 {
301 	int32 x = 0;
302 	int32 index = 0;
303 	int16 in_pixel;
304 	while (x < width) {
305 		in_pixel = scanline[index] | (scanline[index+1] << 8);
306 		index += 2;
307 
308 		jas_matrix_setv(pixels[0], x, (char)(((in_pixel & 0xf800)) >> 8)
309 			| (((in_pixel & 0x7c00)) >> 12));
310 		jas_matrix_setv(pixels[1], x, (char)(((in_pixel & 0x7e0)) >> 3)
311 			| (((in_pixel & 0x7e0)) >> 9));
312 		jas_matrix_setv(pixels[2], x, (char)(((in_pixel & 0x1f)) << 3)
313 			| (((in_pixel & 0x1f)) >> 2));
314 		x++;
315 	}
316 }
317 
318 
319 /*!
320 	Make *pixels[3] from RGB16/RGBA16 bigendian scanline
321 	(just write data to pixels)
322 */
323 inline void
324 write_rgb16b_to_rgb24(jas_matrix_t** pixels, uchar* scanline, int width)
325 {
326 	int32 x = 0;
327 	int32 index = 0;
328 	int16 in_pixel;
329 	while (x < width) {
330 		in_pixel = scanline[index + 1] | (scanline[index] << 8);
331 		index += 2;
332 
333 		jas_matrix_setv(pixels[0], x, (char)(((in_pixel & 0xf800)) >> 8)
334 			| (((in_pixel & 0xf800)) >> 13));
335 		jas_matrix_setv(pixels[1], x, (char)(((in_pixel & 0x7e0)) >> 3)
336 			| (((in_pixel & 0x7e0)) >> 9));
337 		jas_matrix_setv(pixels[2], x, (char)(((in_pixel & 0x1f)) << 3)
338 			| (((in_pixel & 0x1f)) >> 2));
339 		x++;
340 	}
341 }
342 
343 
344 /*!
345 	Make *pixels[3] from RGB24 scanline
346 	(just write data to pixels)
347 */
348 inline void
349 write_rgb24(jas_matrix_t** pixels, uchar* scanline, int width)
350 {
351 	int32 index = 0;
352 	int32 x = 0;
353 	while (x < width) {
354 		jas_matrix_setv(pixels[2], x, scanline[index++]);
355 		jas_matrix_setv(pixels[1], x, scanline[index++]);
356 		jas_matrix_setv(pixels[0], x, scanline[index++]);
357 		x++;
358 	}
359 }
360 
361 
362 /*!
363 	Make *pixels[3] from RGB24 bigendian scanline
364 	(just write data to pixels)
365 */
366 inline void
367 write_rgb24b(jas_matrix_t** pixels, uchar* scanline, int width)
368 {
369 	int32 index = 0;
370 	int32 x = 0;
371 	while (x < width) {
372 		jas_matrix_setv(pixels[0], x, scanline[index++]);
373 		jas_matrix_setv(pixels[1], x, scanline[index++]);
374 		jas_matrix_setv(pixels[2], x, scanline[index++]);
375 		x++;
376 	}
377 }
378 
379 
380 /*!
381 	Make *pixels[3] from RGB32 scanline
382 	(just write data to pixels)
383 */
384 inline void
385 write_rgb32_to_rgb24(jas_matrix_t** pixels, uchar* scanline, int width)
386 {
387 	int32 index = 0;
388 	int32 x = 0;
389 	while (x < width) {
390 		jas_matrix_setv(pixels[2], x, scanline[index++]);
391 		jas_matrix_setv(pixels[1], x, scanline[index++]);
392 		jas_matrix_setv(pixels[0], x, scanline[index++]);
393 		index++;
394 		x++;
395 	}
396 }
397 
398 
399 /*!
400 	Make *pixels[3] from RGB32 bigendian scanline
401 	(just write data to pixels)
402 */
403 inline void
404 write_rgb32b_to_rgb24(jas_matrix_t** pixels, uchar* scanline, int width)
405 {
406 	int32 index = 0;
407 	int32 x = 0;
408 	while (x < width) {
409 		index++;
410 		jas_matrix_setv(pixels[0], x, scanline[index++]);
411 		jas_matrix_setv(pixels[1], x, scanline[index++]);
412 		jas_matrix_setv(pixels[2], x, scanline[index++]);
413 		x++;
414 	}
415 }
416 
417 
418 /*!
419 	Make *pixels[4] from RGBA32 scanline
420 	(just write data to pixels)
421 	!!! UNTESTED !!!
422 */
423 inline void
424 write_rgba32(jas_matrix_t** pixels, uchar* scanline, int width)
425 {
426 	int32 index = 0;
427 	int32 x = 0;
428 	while (x < width) {
429 		jas_matrix_setv(pixels[3], x, scanline[index++]);
430 		jas_matrix_setv(pixels[2], x, scanline[index++]);
431 		jas_matrix_setv(pixels[1], x, scanline[index++]);
432 		jas_matrix_setv(pixels[0], x, scanline[index++]);
433 		x++;
434 	}
435 }
436 
437 
438 /*!
439 	Make *pixels[4] from RGBA32 bigendian scanline
440 	(just write data to pixels)
441 	!!! UNTESTED !!!
442 */
443 inline void
444 write_rgba32b(jas_matrix_t** pixels, uchar* scanline, int width)
445 {
446 	int32 index = 0;
447 	int32 x = 0;
448 	while (x < width) {
449 		jas_matrix_setv(pixels[0], x, scanline[index++]);
450 		jas_matrix_setv(pixels[1], x, scanline[index++]);
451 		jas_matrix_setv(pixels[2], x, scanline[index++]);
452 		jas_matrix_setv(pixels[3], x, scanline[index++]);
453 		x++;
454 	}
455 }
456 
457 
458 }// end namespace conversion
459 
460 
461 //	#pragma mark -	jasper I/O
462 
463 
464 #if __GNUC__ == 2
465 typedef int jasper_length_t;
466 #else
467 typedef unsigned int jasper_length_t;
468 #endif
469 
470 
471 static int
472 Read(jas_stream_obj_t* object, char* buffer, const jasper_length_t length)
473 {
474 	return (*(BPositionIO**)object)->Read(buffer, length);
475 }
476 
477 
478 static int
479 Write(jas_stream_obj_t* object, const char* buffer, const jasper_length_t length)
480 {
481 	return (*(BPositionIO**)object)->Write(buffer, length);
482 }
483 
484 
485 static long
486 Seek(jas_stream_obj_t* object, long offset, int origin)
487 {
488 	return (*(BPositionIO**)object)->Seek(offset, origin);
489 }
490 
491 
492 static int
493 Close(jas_stream_obj_t* object)
494 {
495 	return 0;
496 }
497 
498 
499 static jas_stream_ops_t positionIOops = {
500 	Read,
501 	Write,
502 	Seek,
503 	Close
504 };
505 
506 
507 static jas_stream_t*
508 jas_stream_positionIOopen(BPositionIO *positionIO)
509 {
510 	jas_stream_t* stream;
511 
512 	stream = (jas_stream_t *)malloc(sizeof(jas_stream_t));
513 	if (stream == (jas_stream_t *)NULL)
514 		return (jas_stream_t *)NULL;
515 
516 	memset(stream, 0, sizeof(jas_stream_t));
517 	stream->rwlimit_ = -1;
518 	stream->obj_=(jas_stream_obj_t *)malloc(sizeof(BPositionIO*));
519 	if (stream->obj_ == (jas_stream_obj_t *)NULL) {
520 		free(stream);
521 		return (jas_stream_t *)NULL;
522 	}
523 
524 	*((BPositionIO**)stream->obj_) = positionIO;
525 	stream->ops_ = (&positionIOops);
526 	stream->openmode_ = JAS_STREAM_READ | JAS_STREAM_WRITE | JAS_STREAM_BINARY;
527 	stream->bufbase_ = stream->tinybuf_;
528 	stream->bufsize_ = 1;
529 	stream->bufstart_ = (&stream->bufbase_[JAS_STREAM_MAXPUTBACK]);
530 	stream->ptr_ = stream->bufstart_;
531 	stream->bufmode_ |= JAS_STREAM_UNBUF & JAS_STREAM_BUFMODEMASK;
532 
533 	return stream;
534 }
535 
536 
537 //	#pragma mark -
538 
539 
540 SSlider::SSlider(const char* name, const char* label,
541 		BMessage* message, int32 minValue, int32 maxValue, orientation posture,
542 		thumb_style thumbType, uint32 flags)
543 	:
544 	BSlider(name, label, message, minValue, maxValue,
545 		posture, thumbType, flags)
546 {
547 	rgb_color barColor = { 0, 0, 229, 255 };
548 	UseFillColor(true, &barColor);
549 }
550 
551 
552 //!	Update status string - show actual value
553 const char*
554 SSlider::UpdateText() const
555 {
556 	snprintf(fStatusLabel, sizeof(fStatusLabel), "%" B_PRId32, Value());
557 	return fStatusLabel;
558 }
559 
560 
561 //	#pragma mark -
562 
563 
564 TranslatorReadView::TranslatorReadView(const char* name,
565 	TranslatorSettings* settings)
566 	:
567 	BView(name, 0, new BGroupLayout(B_VERTICAL)),
568 	fSettings(settings)
569 {
570 	fGrayAsRGB32 = new BCheckBox("grayasrgb32",
571 		B_TRANSLATE("Read greyscale images as RGB32"),
572 		new BMessage(VIEW_MSG_SET_GRAYASRGB32));
573 	if (fSettings->SetGetBool(JP2_SET_GRAY8_AS_B_RGB32))
574 		fGrayAsRGB32->SetValue(B_CONTROL_ON);
575 
576 	float padding = 10.0f;
577 	BLayoutBuilder::Group<>(this, B_VERTICAL)
578 		.SetInsets(padding)
579 		.Add(fGrayAsRGB32)
580 		.AddGlue();
581 }
582 
583 
584 TranslatorReadView::~TranslatorReadView()
585 {
586 	fSettings->Release();
587 }
588 
589 
590 void
591 TranslatorReadView::AttachedToWindow()
592 {
593 	fGrayAsRGB32->SetTarget(this);
594 }
595 
596 
597 void
598 TranslatorReadView::MessageReceived(BMessage* message)
599 {
600 	switch (message->what) {
601 		case VIEW_MSG_SET_GRAYASRGB32:
602 		{
603 			int32 value;
604 			if (message->FindInt32("be:value", &value) == B_OK) {
605 				bool boolValue = value;
606 				fSettings->SetGetBool(JP2_SET_GRAY8_AS_B_RGB32, &boolValue);
607 				fSettings->SaveSettings();
608 			}
609 			break;
610 		}
611 		default:
612 			BView::MessageReceived(message);
613 			break;
614 	}
615 }
616 
617 
618 //	#pragma mark - TranslatorWriteView
619 
620 
621 TranslatorWriteView::TranslatorWriteView(const char* name,
622 	TranslatorSettings* settings)
623 	:
624 	BView(name, 0, new BGroupLayout(B_VERTICAL)),
625 	fSettings(settings)
626 {
627 	fQualitySlider = new SSlider("quality", B_TRANSLATE("Output quality"),
628 		new BMessage(VIEW_MSG_SET_QUALITY), 0, 100);
629 	fQualitySlider->SetHashMarks(B_HASH_MARKS_BOTTOM);
630 	fQualitySlider->SetHashMarkCount(10);
631 	fQualitySlider->SetLimitLabels(B_TRANSLATE("Low"), B_TRANSLATE("High"));
632 	fQualitySlider->SetValue(fSettings->SetGetInt32(JP2_SET_QUALITY));
633 
634 	fGrayAsRGB24 = new BCheckBox("gray1asrgb24",
635 		B_TRANSLATE("Write black-and-white images as RGB24"),
636 		new BMessage(VIEW_MSG_SET_GRAY1ASRGB24));
637 	if (fSettings->SetGetBool(JP2_SET_GRAY1_AS_B_RGB24))
638 		fGrayAsRGB24->SetValue(B_CONTROL_ON);
639 
640 	fCodeStreamOnly = new BCheckBox("codestreamonly",
641 		B_TRANSLATE("Output only codestream (.jpc)"),
642 		new BMessage(VIEW_MSG_SET_JPC));
643 	if (fSettings->SetGetBool(JP2_SET_JPC))
644 		fCodeStreamOnly->SetValue(B_CONTROL_ON);
645 
646 	BLayoutBuilder::Group<>(this, B_VERTICAL)
647 		.SetInsets(B_USE_DEFAULT_SPACING)
648 		.Add(fQualitySlider)
649 		.Add(fGrayAsRGB24)
650 		.Add(fCodeStreamOnly)
651 		.AddGlue();
652 }
653 
654 
655 TranslatorWriteView::~TranslatorWriteView()
656 {
657 	fSettings->Release();
658 }
659 
660 
661 void
662 TranslatorWriteView::AttachedToWindow()
663 {
664 	fQualitySlider->SetTarget(this);
665 	fGrayAsRGB24->SetTarget(this);
666 	fCodeStreamOnly->SetTarget(this);
667 }
668 
669 
670 void
671 TranslatorWriteView::MessageReceived(BMessage* message)
672 {
673 	switch (message->what) {
674 		case VIEW_MSG_SET_QUALITY:
675 		{
676 			int32 value;
677 			if (message->FindInt32("be:value", &value) == B_OK) {
678 				fSettings->SetGetInt32(JP2_SET_QUALITY, &value);
679 				fSettings->SaveSettings();
680 			}
681 			break;
682 		}
683 		case VIEW_MSG_SET_GRAY1ASRGB24:
684 		{
685 			int32 value;
686 			if (message->FindInt32("be:value", &value) == B_OK) {
687 				bool boolValue = value;
688 				fSettings->SetGetBool(JP2_SET_GRAY1_AS_B_RGB24, &boolValue);
689 				fSettings->SaveSettings();
690 			}
691 			break;
692 		}
693 		case VIEW_MSG_SET_JPC:
694 		{
695 			int32 value;
696 			if (message->FindInt32("be:value", &value) == B_OK) {
697 				bool boolValue = value;
698 				fSettings->SetGetBool(JP2_SET_JPC, &boolValue);
699 				fSettings->SaveSettings();
700 			}
701 			break;
702 		}
703 		default:
704 			BView::MessageReceived(message);
705 			break;
706 	}
707 }
708 
709 
710 //	#pragma mark -
711 
712 
713 TranslatorAboutView::TranslatorAboutView(const char* name)
714 	:
715 	BView(name, 0, new BGroupLayout(B_VERTICAL))
716 {
717 	BAlignment labelAlignment = BAlignment(B_ALIGN_LEFT, B_ALIGN_TOP);
718 	BStringView* title = new BStringView("Title", sTranslatorName);
719 	title->SetFont(be_bold_font);
720 	title->SetExplicitAlignment(labelAlignment);
721 
722 	char versionString[100];
723 	snprintf(versionString, sizeof(versionString),
724 		B_TRANSLATE("Version %d.%d.%d"),
725 		static_cast<int>(sTranslatorVersion >> 8),
726 		static_cast<int>((sTranslatorVersion >> 4) & 0xf),
727 		static_cast<int>(sTranslatorVersion & 0xf));
728 
729 	BStringView* version = new BStringView("Version", versionString);
730 	version->SetExplicitAlignment(labelAlignment);
731 
732 	BTextView* infoView = new BTextView("info");
733 	infoView->SetText(sTranslatorInfo);
734 	infoView->SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
735 	rgb_color textColor = ui_color(B_PANEL_TEXT_COLOR);
736 	infoView->SetFontAndColor(be_plain_font, B_FONT_ALL, &textColor);
737 	infoView->MakeEditable(false);
738 
739 	BLayoutBuilder::Group<>(this, B_VERTICAL, 0)
740 		.SetInsets(B_USE_DEFAULT_SPACING)
741 		.Add(title)
742 		.Add(version)
743 		.Add(infoView);
744 }
745 
746 
747 //	#pragma mark -
748 
749 
750 TranslatorView::TranslatorView(const char* name, TranslatorSettings* settings)
751 	:
752 	BTabView(name, B_WIDTH_FROM_LABEL)
753 {
754 	SetBorder(B_NO_BORDER);
755 
756 	AddTab(new TranslatorWriteView(B_TRANSLATE("Write"),
757 		settings->Acquire()));
758 	AddTab(new TranslatorReadView(B_TRANSLATE("Read"),
759 		settings->Acquire()));
760 	AddTab(new TranslatorAboutView(B_TRANSLATE("About")));
761 
762 	settings->Release();
763 }
764 
765 
766 //	#pragma mark -
767 
768 BView*
769 JP2Translator::NewConfigView(TranslatorSettings* settings)
770 {
771 	BView* outView = new TranslatorView("TranslatorView", settings);
772 	return outView;
773 }
774 
775 
776 JP2Translator::JP2Translator()
777 	: BaseTranslator(sTranslatorName, sTranslatorInfo, sTranslatorVersion,
778 		sInputFormats, kNumInputFormats,
779 		sOutputFormats, kNumOutputFormats,
780 		JP2_SETTINGS_FILE,
781 		sDefaultSettings, kNumDefaultSettings,
782 		B_TRANSLATOR_BITMAP, JP2_FORMAT)
783 {
784 }
785 
786 
787 //!	Determine whether or not we can handle this data
788 status_t
789 JP2Translator::DerivedIdentify(BPositionIO* inSource,
790 	const translation_format* inFormat, BMessage* ioExtension,
791 	translator_info* outInfo, uint32 outType)
792 {
793 	if ((outType != 0) && (outType != B_TRANSLATOR_BITMAP)
794 		&& outType != JP2_FORMAT)
795 		return B_NO_TRANSLATOR;
796 
797 	// !!! You might need to make this buffer bigger to test for your
798 	// native format
799 	off_t position = inSource->Position();
800 	uint8 header[sizeof(TranslatorBitmap)];
801 	status_t err = inSource->Read(header, sizeof(TranslatorBitmap));
802 	inSource->Seek(position, SEEK_SET);
803 	if (err < B_OK)
804 		return err;
805 
806 	if (B_BENDIAN_TO_HOST_INT32(((TranslatorBitmap *)header)->magic)
807 		== B_TRANSLATOR_BITMAP) {
808 		if (PopulateInfoFromFormat(outInfo, B_TRANSLATOR_BITMAP) != B_OK)
809 			return B_NO_TRANSLATOR;
810 	} else {
811 		if ((((header[4] << 24) | (header[5] << 16) | (header[6] << 8)
812 			| header[7]) == JP2_BOX_JP) // JP2
813 			|| (header[0] == (JPC_MS_SOC >> 8) && header[1]
814 			== (JPC_MS_SOC & 0xff)))	// JPC
815 		{
816 			if (PopulateInfoFromFormat(outInfo, JP2_FORMAT) != B_OK)
817 				return B_NO_TRANSLATOR;
818 		} else
819 			return B_NO_TRANSLATOR;
820 	}
821 
822 	return B_OK;
823 }
824 
825 
826 status_t
827 JP2Translator::DerivedTranslate(BPositionIO* inSource,
828 	const translator_info* inInfo, BMessage* ioExtension, uint32 outType,
829 	BPositionIO* outDestination, int32 baseType)
830 {
831 	// If no specific type was requested, convert to the interchange format
832 	if (outType == 0)
833 		outType = B_TRANSLATOR_BITMAP;
834 
835 	// What action to take, based on the findings of Identify()
836 	if (outType == inInfo->type)
837 		return Copy(inSource, outDestination);
838 	if (inInfo->type == B_TRANSLATOR_BITMAP && outType == JP2_FORMAT)
839 		return Compress(inSource, outDestination);
840 	if (inInfo->type == JP2_FORMAT && outType == B_TRANSLATOR_BITMAP)
841 		return Decompress(inSource, outDestination);
842 
843 	return B_NO_TRANSLATOR;
844 }
845 
846 
847 //!	The user has requested the same format for input and output, so just copy
848 status_t
849 JP2Translator::Copy(BPositionIO* in, BPositionIO* out)
850 {
851 	int block_size = 65536;
852 	void* buffer = malloc(block_size);
853 	char temp[1024];
854 	if (buffer == NULL) {
855 		buffer = temp;
856 		block_size = 1024;
857 	}
858 	status_t err = B_OK;
859 
860 	// Read until end of file or error
861 	while (1) {
862 		ssize_t to_read = block_size;
863 		err = in->Read(buffer, to_read);
864 		// Explicit check for EOF
865 		if (err == -1) {
866 			if (buffer != temp)
867 				free(buffer);
868 			return B_OK;
869 		}
870 		if (err <= B_OK) break;
871 		to_read = err;
872 		err = out->Write(buffer, to_read);
873 		if (err != to_read) if (err >= 0) err = B_DEVICE_FULL;
874 		if (err < B_OK) break;
875 	}
876 
877 	if (buffer != temp)
878 		free(buffer);
879 	return (err >= 0) ? B_OK : err;
880 }
881 
882 
883 //!	Encode into the native format
884 status_t
885 JP2Translator::Compress(BPositionIO* in, BPositionIO* out)
886 {
887 	using namespace conversion;
888 
889 	// Read info about bitmap
890 	TranslatorBitmap header;
891 	status_t err = in->Read(&header, sizeof(TranslatorBitmap));
892 	if (err < B_OK)
893 		return err;
894 	if (err < (int)sizeof(TranslatorBitmap))
895 		return B_ERROR;
896 
897 	// Grab dimension, color space, and size information from the stream
898 	BRect bounds;
899 	bounds.left = B_BENDIAN_TO_HOST_FLOAT(header.bounds.left);
900 	bounds.top = B_BENDIAN_TO_HOST_FLOAT(header.bounds.top);
901 	bounds.right = B_BENDIAN_TO_HOST_FLOAT(header.bounds.right);
902 	bounds.bottom = B_BENDIAN_TO_HOST_FLOAT(header.bounds.bottom);
903 
904 	int32 in_row_bytes = B_BENDIAN_TO_HOST_INT32(header.rowBytes);
905 
906 	int width = bounds.IntegerWidth() + 1;
907 	int height = bounds.IntegerHeight() + 1;
908 
909 	// Function pointer to write function
910 	// It MUST point to proper function
911 	void (*converter)(jas_matrix_t** pixels, uchar* inscanline,
912 		int width) = write_rgba32;
913 
914 	// Default color info
915 	int out_color_space = JAS_CLRSPC_SRGB;
916 	int out_color_components = 3;
917 
918 	switch ((color_space)B_BENDIAN_TO_HOST_INT32(header.colors)) {
919 		case B_GRAY1:
920 			if (fSettings->SetGetBool(JP2_SET_GRAY1_AS_B_RGB24)) {
921 				converter = write_gray1_to_rgb24;
922 			} else {
923 				out_color_components = 1;
924 				out_color_space = JAS_CLRSPC_SGRAY;
925 				converter = write_gray1_to_gray;
926 			}
927 			break;
928 
929 		case B_CMAP8:
930 			converter = write_cmap8_to_rgb24;
931 			break;
932 
933 		case B_GRAY8:
934 			out_color_components = 1;
935 			out_color_space = JAS_CLRSPC_SGRAY;
936 			converter = write_gray;
937 			break;
938 
939 		case B_RGB15:
940 		case B_RGBA15:
941 			converter = write_rgb15_to_rgb24;
942 			break;
943 
944 		case B_RGB15_BIG:
945 		case B_RGBA15_BIG:
946 			converter = write_rgb15b_to_rgb24;
947 			break;
948 
949 		case B_RGB16:
950 			converter = write_rgb16_to_rgb24;
951 			break;
952 
953 		case B_RGB16_BIG:
954 			converter = write_rgb16b_to_rgb24;
955 			break;
956 
957 		case B_RGB24:
958 			converter = write_rgb24;
959 			break;
960 
961 		case B_RGB24_BIG:
962 			converter = write_rgb24b;
963 			break;
964 
965 		case B_RGB32:
966 			converter = write_rgb32_to_rgb24;
967 			break;
968 
969 		case B_RGB32_BIG:
970 			converter = write_rgb32b_to_rgb24;
971 			break;
972 
973 		case B_RGBA32:
974 		/*
975 			// In theory it should be possible to write 4 color components
976 			// to jp2, so it should be possible to have transparency.
977 			// Unfortunetly libjasper does not agree with that
978 			// For now i don't know how to modify it :(
979 
980 			out_color_components = 4;
981 			converter = write_rgba32;
982 		*/
983 			converter = write_rgb32_to_rgb24;
984 			break;
985 
986 		case B_RGBA32_BIG:
987 		/*
988 			// In theory it should be possible to write 4 color components
989 			// to jp2, so it should be possible to have transparency.
990 			// Unfortunetly libjasper does not agree with that
991 			// For now i don't know how to modify it :(
992 
993 			out_color_components = 4;
994 			converter = write_rgba32b;
995 		*/
996 			converter = write_rgb32b_to_rgb24;
997 			break;
998 
999 		default:
1000 			syslog(LOG_ERR, "Unknown color space.\n");
1001 			return B_ERROR;
1002 	}
1003 
1004 	jas_image_t* image;
1005 	jas_stream_t* outs;
1006 	jas_matrix_t* pixels[4];
1007 	jas_image_cmptparm_t component_info[4];
1008 
1009 	if (jas_init())
1010 		return B_ERROR;
1011 
1012 	if (!(outs = jas_stream_positionIOopen(out)))
1013 		return B_ERROR;
1014 
1015 	int32 i = 0;
1016 	for (i = 0; i < (long)out_color_components; i++) {
1017 		(void) memset(component_info + i, 0, sizeof(jas_image_cmptparm_t));
1018 		component_info[i].hstep = 1;
1019 		component_info[i].vstep = 1;
1020 		component_info[i].width = (unsigned int)width;
1021 		component_info[i].height = (unsigned int)height;
1022 		component_info[i].prec = (unsigned int)8;
1023 	}
1024 
1025 	image = jas_image_create((short)out_color_components, component_info,
1026 		out_color_space);
1027 	if (image == (jas_image_t *)NULL)
1028 		return Error(outs, NULL, NULL, 0, NULL, B_ERROR);
1029 
1030 	uchar *in_scanline = (uchar*) malloc(in_row_bytes);
1031 	if (in_scanline == NULL)
1032 		return Error(outs, image, NULL, 0, NULL, B_ERROR);
1033 
1034 	for (i = 0; i < (long)out_color_components; i++) {
1035 		pixels[i] = jas_matrix_create(1, (unsigned int)width);
1036 		if (pixels[i] == (jas_matrix_t *)NULL)
1037 			return Error(outs, image, pixels, i+1, in_scanline, B_ERROR);
1038 	}
1039 
1040 	int32 y = 0;
1041 	for (y = 0; y < (long)height; y++) {
1042 		err = in->Read(in_scanline, in_row_bytes);
1043 		if (err < in_row_bytes) {
1044 			return (err < B_OK) ? Error(outs, image, pixels,
1045 					out_color_components, in_scanline, err)
1046 				: Error(outs, image, pixels, out_color_components, in_scanline,
1047 					B_ERROR);
1048 		}
1049 
1050 		converter(pixels, in_scanline, width);
1051 
1052 		for (i = 0; i < (long)out_color_components; i++) {
1053 			(void)jas_image_writecmpt(image, (short)i, 0, (unsigned int)y,
1054 				(unsigned int)width, 1, pixels[i]);
1055 		}
1056 	}
1057 
1058 	char opts[16];
1059 	sprintf(opts, "rate=%1f",
1060 		(float)fSettings->SetGetInt32(JP2_SET_QUALITY) / 100.0);
1061 
1062 	if (jas_image_encode(image, outs, jas_image_strtofmt(
1063 			fSettings->SetGetBool(JP2_SET_JPC) ?
1064 				(char*)"jpc" : (char*)"jp2"), opts)) {
1065 		return Error(outs, image, pixels,
1066 			out_color_components, in_scanline, err);
1067 	}
1068 
1069 	free(in_scanline);
1070 
1071 	for (i = 0; i < (long)out_color_components; i++)
1072 		jas_matrix_destroy(pixels[i]);
1073 
1074 	jas_stream_close(outs);
1075 	jas_image_destroy(image);
1076 	jas_image_clearfmts();
1077 
1078 	return B_OK;
1079 }
1080 
1081 
1082 //!	Decode the native format
1083 status_t
1084 JP2Translator::Decompress(BPositionIO* in, BPositionIO* out)
1085 {
1086 	using namespace conversion;
1087 
1088 	jas_image_t* image;
1089 	jas_stream_t* ins;
1090 	jas_matrix_t* pixels[4];
1091 
1092 	if (jas_init())
1093 		return B_ERROR;
1094 
1095 	if (!(ins = jas_stream_positionIOopen(in)))
1096 		return B_ERROR;
1097 
1098 	if (!(image = jas_image_decode(ins, -1, 0)))
1099 		return Error(ins, NULL, NULL, 0, NULL, B_ERROR);
1100 
1101 	// Default color info
1102 	color_space out_color_space;
1103 	int out_color_components;
1104 	int	in_color_components = jas_image_numcmpts(image);
1105 
1106 	// Function pointer to read function
1107 	// It MUST point to proper function
1108 	void (*converter)(jas_matrix_t** pixels, uchar* outscanline,
1109 		int width) = NULL;
1110 
1111 	switch (jas_clrspc_fam(jas_image_clrspc(image))) {
1112 		case JAS_CLRSPC_FAM_RGB:
1113 			out_color_components = 4;
1114 			if (in_color_components == 3) {
1115 				out_color_space = B_RGB32;
1116 				converter = read_rgb24_to_rgb32;
1117 			} else if (in_color_components == 4) {
1118 				out_color_space = B_RGBA32;
1119 				converter = read_rgba32;
1120 			} else {
1121 				syslog(LOG_ERR, "Other than RGB with 3 or 4 color "
1122 					"components not implemented.\n");
1123 				return Error(ins, image, NULL, 0, NULL, B_ERROR);
1124 			}
1125 			break;
1126 		case JAS_CLRSPC_FAM_GRAY:
1127 			if (fSettings->SetGetBool(JP2_SET_GRAY8_AS_B_RGB32)) {
1128 				out_color_space = B_RGB32;
1129 				out_color_components = 4;
1130 				converter = read_gray_to_rgb32;
1131 			} else {
1132 				out_color_space = B_GRAY8;
1133 				out_color_components = 1;
1134 				converter = read_gray;
1135 			}
1136 			break;
1137 		case JAS_CLRSPC_FAM_YCBCR:
1138 			syslog(LOG_ERR, "Color space YCBCR not implemented yet.\n");
1139 			return Error(ins, image, NULL, 0, NULL, B_ERROR);
1140 			break;
1141 		case JAS_CLRSPC_UNKNOWN:
1142 		default:
1143 			syslog(LOG_ERR, "Color space unknown. \n");
1144 			return Error(ins, image, NULL, 0, NULL, B_ERROR);
1145 			break;
1146 	}
1147 
1148 	float width = (float)jas_image_width(image);
1149 	float height = (float)jas_image_height(image);
1150 
1151 	// Bytes count in one line of image (scanline)
1152 	int64 out_row_bytes = (int32)width * out_color_components;
1153 		// NOTE: things will go wrong if "out_row_bytes" wouldn't fit into 32 bits
1154 
1155 	// !!! Initialize this bounds rect to the size of your image
1156 	BRect bounds(0, 0, width - 1, height - 1);
1157 
1158 
1159 	// Fill out the B_TRANSLATOR_BITMAP's header
1160 	TranslatorBitmap header;
1161 	header.magic = B_HOST_TO_BENDIAN_INT32(B_TRANSLATOR_BITMAP);
1162 	header.bounds.left = B_HOST_TO_BENDIAN_FLOAT(bounds.left);
1163 	header.bounds.top = B_HOST_TO_BENDIAN_FLOAT(bounds.top);
1164 	header.bounds.right = B_HOST_TO_BENDIAN_FLOAT(bounds.right);
1165 	header.bounds.bottom = B_HOST_TO_BENDIAN_FLOAT(bounds.bottom);
1166 	header.colors = (color_space)B_HOST_TO_BENDIAN_INT32(out_color_space);
1167 	header.rowBytes = B_HOST_TO_BENDIAN_INT32(out_row_bytes);
1168 	header.dataSize = B_HOST_TO_BENDIAN_INT32((int32)(out_row_bytes * height));
1169 
1170 	// Write out the header
1171 	status_t err = out->Write(&header, sizeof(TranslatorBitmap));
1172 	if (err < B_OK)
1173 		return Error(ins, image, NULL, 0, NULL, err);
1174 	if (err < (int)sizeof(TranslatorBitmap))
1175 		return Error(ins, image, NULL, 0, NULL, B_ERROR);
1176 
1177 	uchar *out_scanline = (uchar*) malloc(out_row_bytes);
1178 	if (out_scanline == NULL)
1179 		return Error(ins, image, NULL, 0, NULL, B_ERROR);
1180 
1181 	int32 i = 0;
1182 	for (i = 0; i < (long)in_color_components; i++) {
1183 		pixels[i] = jas_matrix_create(1, (unsigned int)width);
1184 		if (pixels[i] == (jas_matrix_t *)NULL)
1185 			return Error(ins, image, pixels, i + 1, out_scanline, B_ERROR);
1186 	}
1187 
1188 	int32 y = 0;
1189 	for (y = 0; y < (long)height; y++) {
1190 		for (i = 0; i < (long)in_color_components; i++) {
1191 			(void)jas_image_readcmpt(image, (short)i, 0, (unsigned int)y,
1192 				(unsigned int)width, 1, pixels[i]);
1193 		}
1194 
1195 		converter(pixels, out_scanline, (int32)width);
1196 
1197 		err = out->Write(out_scanline, out_row_bytes);
1198 		if (err < out_row_bytes) {
1199 			return (err < B_OK) ? Error(ins, image, pixels, in_color_components,
1200 				out_scanline, err)
1201 				: Error(ins, image, pixels, in_color_components, out_scanline,
1202 					B_ERROR);
1203 		}
1204 	}
1205 
1206 	free(out_scanline);
1207 
1208 	for (i = 0; i < (long)in_color_components; i++)
1209 		jas_matrix_destroy(pixels[i]);
1210 
1211 	jas_stream_close(ins);
1212 	jas_image_destroy(image);
1213 	jas_image_clearfmts();
1214 
1215 	return B_OK;
1216 }
1217 
1218 
1219 /*! searches in both inputFormats & outputFormats */
1220 status_t
1221 JP2Translator::PopulateInfoFromFormat(translator_info* info,
1222 	uint32 formatType, translator_id id)
1223 {
1224 	int32 formatCount;
1225 	const translation_format* formats = OutputFormats(&formatCount);
1226 
1227 	for (int i = 0; i <= 1; formats = InputFormats(&formatCount), i++) {
1228 		if (PopulateInfoFromFormat(info, formatType,
1229 			formats, formatCount) == B_OK) {
1230 			info->translator = id;
1231 			return B_OK;
1232 		}
1233 	}
1234 
1235 	return B_ERROR;
1236 }
1237 
1238 
1239 status_t
1240 JP2Translator::PopulateInfoFromFormat(translator_info* info,
1241 	uint32 formatType, const translation_format* formats, int32 formatCount)
1242 {
1243 	for (int i = 0; i < formatCount; i++) {
1244 		if (formats[i].type == formatType) {
1245 			info->type = formatType;
1246 			info->group = formats[i].group;
1247 			info->quality = formats[i].quality;
1248 			info->capability = formats[i].capability;
1249 			if (strcmp(formats[i].name, B_TRANSLATOR_BITMAP_DESCRIPTION)
1250 				== 0) {
1251 				strlcpy(info->name,
1252 					B_TRANSLATE(B_TRANSLATOR_BITMAP_DESCRIPTION),
1253 					sizeof(info->name));
1254 			} else {
1255 				strlcpy(info->name, formats[i].name, sizeof(info->name));
1256 			}
1257 			strlcpy(info->MIME, formats[i].MIME, sizeof(info->MIME));
1258 			return B_OK;
1259 		}
1260 	}
1261 
1262 	return B_ERROR;
1263 }
1264 
1265 
1266 /*!
1267 	Frees jpeg alocated memory
1268 	Returns given error (B_ERROR by default)
1269 */
1270 status_t
1271 Error(jas_stream_t* stream, jas_image_t* image, jas_matrix_t** pixels,
1272 	int32 pixels_count, uchar* scanline, status_t error)
1273 {
1274 	if (pixels) {
1275 		int32 i;
1276 		for (i = 0; i < (long)pixels_count; i++) {
1277 			if (pixels[i] != NULL)
1278 				jas_matrix_destroy(pixels[i]);
1279 		}
1280 	}
1281 	if (stream)
1282 		jas_stream_close(stream);
1283 	if (image)
1284 		jas_image_destroy(image);
1285 
1286 	jas_image_clearfmts();
1287 	free(scanline);
1288 
1289 	return error;
1290 }
1291 
1292 
1293 //	#pragma mark -
1294 
1295 BTranslator*
1296 make_nth_translator(int32 n, image_id you, uint32 flags, ...)
1297 {
1298 	if (!n)
1299 		return new JP2Translator();
1300 
1301 	return NULL;
1302 }
1303 
1304 
1305 int
1306 main()
1307 {
1308 	BApplication app("application/x-vnd.Haiku-JPEG2000Translator");
1309 	JP2Translator* translator = new JP2Translator();
1310 	if (LaunchTranslatorWindow(translator, sTranslatorName) == B_OK)
1311 		app.Run();
1312 
1313 	return 0;
1314 }
1315 
1316