xref: /haiku/src/add-ons/translators/jpeg2000/JPEG2000Translator.cpp (revision 7056e542b7e59831b783e0c892ce27af93d893b3)
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 	{
450 		jas_matrix_setv(pixels[0], x, scanline[index++]);
451 		jas_matrix_setv(pixels[1], x, scanline[index++]);
452 		jas_matrix_setv(pixels[2], x, scanline[index++]);
453 		jas_matrix_setv(pixels[3], x, scanline[index++]);
454 		x++;
455 	}
456 }
457 
458 
459 }// end namespace conversion
460 
461 
462 //	#pragma mark -	jasper I/O
463 
464 
465 static int
466 Read(jas_stream_obj_t* object, char* buffer, const int length)
467 {
468 	return (*(BPositionIO**)object)->Read(buffer, length);
469 }
470 
471 
472 static int
473 Write(jas_stream_obj_t* object, char* buffer, const int length)
474 {
475 	return (*(BPositionIO**)object)->Write(buffer, length);
476 }
477 
478 
479 static long
480 Seek(jas_stream_obj_t* object, long offset, int origin)
481 {
482 	return (*(BPositionIO**)object)->Seek(offset, origin);
483 }
484 
485 
486 static int
487 Close(jas_stream_obj_t* object)
488 {
489 	return 0;
490 }
491 
492 
493 static jas_stream_ops_t positionIOops = {
494 	Read,
495 	Write,
496 	Seek,
497 	Close
498 };
499 
500 
501 static jas_stream_t*
502 jas_stream_positionIOopen(BPositionIO *positionIO)
503 {
504 	jas_stream_t* stream;
505 
506 	stream = (jas_stream_t *)malloc(sizeof(jas_stream_t));
507 	if (stream == (jas_stream_t *)NULL)
508 		return (jas_stream_t *)NULL;
509 
510 	memset(stream, 0, sizeof(jas_stream_t));
511 	stream->rwlimit_ = -1;
512 	stream->obj_=(jas_stream_obj_t *)malloc(sizeof(BPositionIO*));
513 	if (stream->obj_ == (jas_stream_obj_t *)NULL) {
514 		free(stream);
515 		return (jas_stream_t *)NULL;
516 	}
517 
518 	*((BPositionIO**)stream->obj_) = positionIO;
519 	stream->ops_ = (&positionIOops);
520 	stream->openmode_ = JAS_STREAM_READ | JAS_STREAM_WRITE | JAS_STREAM_BINARY;
521 	stream->bufbase_ = stream->tinybuf_;
522 	stream->bufsize_ = 1;
523 	stream->bufstart_ = (&stream->bufbase_[JAS_STREAM_MAXPUTBACK]);
524 	stream->ptr_ = stream->bufstart_;
525 	stream->bufmode_ |= JAS_STREAM_UNBUF & JAS_STREAM_BUFMODEMASK;
526 
527 	return stream;
528 }
529 
530 
531 //	#pragma mark -
532 
533 
534 SSlider::SSlider(const char* name, const char* label,
535 		BMessage* message, int32 minValue, int32 maxValue, orientation posture,
536 		thumb_style thumbType, uint32 flags)
537 	:
538 	BSlider(name, label, message, minValue, maxValue,
539 		posture, thumbType, flags)
540 {
541 	rgb_color barColor = { 0, 0, 229, 255 };
542 	UseFillColor(true, &barColor);
543 }
544 
545 
546 //!	Update status string - show actual value
547 const char*
548 SSlider::UpdateText() const
549 {
550 	snprintf(fStatusLabel, sizeof(fStatusLabel), "%" B_PRId32, Value());
551 	return fStatusLabel;
552 }
553 
554 
555 //	#pragma mark -
556 
557 
558 TranslatorReadView::TranslatorReadView(const char* name,
559 	TranslatorSettings* settings)
560 	:
561 	BView(name, 0, new BGroupLayout(B_VERTICAL)),
562 	fSettings(settings)
563 {
564 	fGrayAsRGB32 = new BCheckBox("grayasrgb32",
565 		B_TRANSLATE("Read greyscale images as RGB32"),
566 		new BMessage(VIEW_MSG_SET_GRAYASRGB32));
567 	if (fSettings->SetGetBool(JP2_SET_GRAY8_AS_B_RGB32))
568 		fGrayAsRGB32->SetValue(B_CONTROL_ON);
569 
570 	float padding = 10.0f;
571 	BLayoutBuilder::Group<>(this, B_VERTICAL)
572 		.SetInsets(padding)
573 		.Add(fGrayAsRGB32)
574 		.AddGlue();
575 }
576 
577 
578 TranslatorReadView::~TranslatorReadView()
579 {
580 	fSettings->Release();
581 }
582 
583 
584 void
585 TranslatorReadView::AttachedToWindow()
586 {
587 	fGrayAsRGB32->SetTarget(this);
588 }
589 
590 
591 void
592 TranslatorReadView::MessageReceived(BMessage* message)
593 {
594 	switch (message->what) {
595 		case VIEW_MSG_SET_GRAYASRGB32:
596 		{
597 			int32 value;
598 			if (message->FindInt32("be:value", &value) == B_OK) {
599 				bool boolValue = value;
600 				fSettings->SetGetBool(JP2_SET_GRAY8_AS_B_RGB32, &boolValue);
601 				fSettings->SaveSettings();
602 			}
603 			break;
604 		}
605 		default:
606 			BView::MessageReceived(message);
607 			break;
608 	}
609 }
610 
611 
612 //	#pragma mark - TranslatorWriteView
613 
614 
615 TranslatorWriteView::TranslatorWriteView(const char* name,
616 	TranslatorSettings* settings)
617 	:
618 	BView(name, 0, new BGroupLayout(B_VERTICAL)),
619 	fSettings(settings)
620 {
621 	fQualitySlider = new SSlider("quality", B_TRANSLATE("Output quality"),
622 		new BMessage(VIEW_MSG_SET_QUALITY), 0, 100);
623 	fQualitySlider->SetHashMarks(B_HASH_MARKS_BOTTOM);
624 	fQualitySlider->SetHashMarkCount(10);
625 	fQualitySlider->SetLimitLabels(B_TRANSLATE("Low"), B_TRANSLATE("High"));
626 	fQualitySlider->SetValue(fSettings->SetGetInt32(JP2_SET_QUALITY));
627 
628 	fGrayAsRGB24 = new BCheckBox("gray1asrgb24",
629 		B_TRANSLATE("Write black-and-white images as RGB24"),
630 		new BMessage(VIEW_MSG_SET_GRAY1ASRGB24));
631 	if (fSettings->SetGetBool(JP2_SET_GRAY1_AS_B_RGB24))
632 		fGrayAsRGB24->SetValue(B_CONTROL_ON);
633 
634 	fCodeStreamOnly = new BCheckBox("codestreamonly",
635 		B_TRANSLATE("Output only codestream (.jpc)"),
636 		new BMessage(VIEW_MSG_SET_JPC));
637 	if (fSettings->SetGetBool(JP2_SET_JPC))
638 		fCodeStreamOnly->SetValue(B_CONTROL_ON);
639 
640 	BLayoutBuilder::Group<>(this, B_VERTICAL)
641 		.SetInsets(B_USE_DEFAULT_SPACING)
642 		.Add(fQualitySlider)
643 		.Add(fGrayAsRGB24)
644 		.Add(fCodeStreamOnly)
645 		.AddGlue();
646 }
647 
648 
649 TranslatorWriteView::~TranslatorWriteView()
650 {
651 	fSettings->Release();
652 }
653 
654 
655 void
656 TranslatorWriteView::AttachedToWindow()
657 {
658 	fQualitySlider->SetTarget(this);
659 	fGrayAsRGB24->SetTarget(this);
660 	fCodeStreamOnly->SetTarget(this);
661 }
662 
663 
664 void
665 TranslatorWriteView::MessageReceived(BMessage* message)
666 {
667 	switch (message->what) {
668 		case VIEW_MSG_SET_QUALITY:
669 		{
670 			int32 value;
671 			if (message->FindInt32("be:value", &value) == B_OK) {
672 				fSettings->SetGetInt32(JP2_SET_QUALITY, &value);
673 				fSettings->SaveSettings();
674 			}
675 			break;
676 		}
677 		case VIEW_MSG_SET_GRAY1ASRGB24:
678 		{
679 			int32 value;
680 			if (message->FindInt32("be:value", &value) == B_OK) {
681 				bool boolValue = value;
682 				fSettings->SetGetBool(JP2_SET_GRAY1_AS_B_RGB24, &boolValue);
683 				fSettings->SaveSettings();
684 			}
685 			break;
686 		}
687 		case VIEW_MSG_SET_JPC:
688 		{
689 			int32 value;
690 			if (message->FindInt32("be:value", &value) == B_OK) {
691 				bool boolValue = value;
692 				fSettings->SetGetBool(JP2_SET_JPC, &boolValue);
693 				fSettings->SaveSettings();
694 			}
695 			break;
696 		}
697 		default:
698 			BView::MessageReceived(message);
699 			break;
700 	}
701 }
702 
703 
704 //	#pragma mark -
705 
706 
707 TranslatorAboutView::TranslatorAboutView(const char* name)
708 	:
709 	BView(name, 0, new BGroupLayout(B_VERTICAL))
710 {
711 	BAlignment labelAlignment = BAlignment(B_ALIGN_LEFT, B_ALIGN_TOP);
712 	BStringView* title = new BStringView("Title", sTranslatorName);
713 	title->SetFont(be_bold_font);
714 	title->SetExplicitAlignment(labelAlignment);
715 
716 	char versionString[100];
717 	snprintf(versionString, sizeof(versionString),
718 		B_TRANSLATE("Version %d.%d.%d"),
719 		static_cast<int>(sTranslatorVersion >> 8),
720 		static_cast<int>((sTranslatorVersion >> 4) & 0xf),
721 		static_cast<int>(sTranslatorVersion & 0xf));
722 
723 	BStringView* version = new BStringView("Version", versionString);
724 	version->SetExplicitAlignment(labelAlignment);
725 
726 	BTextView* infoView = new BTextView("info");
727 	infoView->SetText(sTranslatorInfo);
728 	infoView->SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
729 	infoView->MakeEditable(false);
730 
731 	BLayoutBuilder::Group<>(this, B_VERTICAL, 0)
732 		.SetInsets(B_USE_DEFAULT_SPACING)
733 		.Add(title)
734 		.Add(version)
735 		.Add(infoView);
736 }
737 
738 
739 //	#pragma mark -
740 
741 
742 TranslatorView::TranslatorView(const char* name, TranslatorSettings* settings)
743 	:
744 	BTabView(name, B_WIDTH_FROM_LABEL)
745 {
746 	SetBorder(B_NO_BORDER);
747 
748 	AddTab(new TranslatorWriteView(B_TRANSLATE("Write"),
749 		settings->Acquire()));
750 	AddTab(new TranslatorReadView(B_TRANSLATE("Read"),
751 		settings->Acquire()));
752 	AddTab(new TranslatorAboutView(B_TRANSLATE("About")));
753 
754 	settings->Release();
755 
756  	BFont font;
757  	GetFont(&font);
758  	SetExplicitPreferredSize(
759 		BSize((font.Size() * 380) / 12, (font.Size() * 250) / 12));
760 }
761 
762 
763 //	#pragma mark -
764 
765 BView*
766 JP2Translator::NewConfigView(TranslatorSettings* settings)
767 {
768 	BView* outView = new TranslatorView("TranslatorView", settings);
769 	return outView;
770 }
771 
772 
773 JP2Translator::JP2Translator()
774 	: BaseTranslator(sTranslatorName, sTranslatorInfo, sTranslatorVersion,
775 		sInputFormats, kNumInputFormats,
776 		sOutputFormats, kNumOutputFormats,
777 		JP2_SETTINGS_FILE,
778 		sDefaultSettings, kNumDefaultSettings,
779 		B_TRANSLATOR_BITMAP, JP2_FORMAT)
780 {
781 }
782 
783 
784 //!	Determine whether or not we can handle this data
785 status_t
786 JP2Translator::DerivedIdentify(BPositionIO* inSource,
787 	const translation_format* inFormat, BMessage* ioExtension,
788 	translator_info* outInfo, uint32 outType)
789 {
790 	if ((outType != 0) && (outType != B_TRANSLATOR_BITMAP)
791 		&& outType != JP2_FORMAT)
792 		return B_NO_TRANSLATOR;
793 
794 	// !!! You might need to make this buffer bigger to test for your
795 	// native format
796 	off_t position = inSource->Position();
797 	uint8 header[sizeof(TranslatorBitmap)];
798 	status_t err = inSource->Read(header, sizeof(TranslatorBitmap));
799 	inSource->Seek(position, SEEK_SET);
800 	if (err < B_OK)
801 		return err;
802 
803 	if (B_BENDIAN_TO_HOST_INT32(((TranslatorBitmap *)header)->magic)
804 		== B_TRANSLATOR_BITMAP) {
805 		if (PopulateInfoFromFormat(outInfo, B_TRANSLATOR_BITMAP) != B_OK)
806 			return B_NO_TRANSLATOR;
807 	} else {
808 		if ((((header[4] << 24) | (header[5] << 16) | (header[6] << 8)
809 			| header[7]) == JP2_BOX_JP) // JP2
810 			|| (header[0] == (JPC_MS_SOC >> 8) && header[1]
811 			== (JPC_MS_SOC & 0xff)))	// JPC
812 		{
813 			if (PopulateInfoFromFormat(outInfo, JP2_FORMAT) != B_OK)
814 				return B_NO_TRANSLATOR;
815 		} else
816 			return B_NO_TRANSLATOR;
817 	}
818 
819 	return B_OK;
820 }
821 
822 
823 status_t
824 JP2Translator::DerivedTranslate(BPositionIO* inSource,
825 	const translator_info* inInfo, BMessage* ioExtension, uint32 outType,
826 	BPositionIO* outDestination, int32 baseType)
827 {
828 	// If no specific type was requested, convert to the interchange format
829 	if (outType == 0)
830 		outType = B_TRANSLATOR_BITMAP;
831 
832 	// What action to take, based on the findings of Identify()
833 	if (outType == inInfo->type)
834 		return Copy(inSource, outDestination);
835 	if (inInfo->type == B_TRANSLATOR_BITMAP && outType == JP2_FORMAT)
836 		return Compress(inSource, outDestination);
837 	if (inInfo->type == JP2_FORMAT && outType == B_TRANSLATOR_BITMAP)
838 		return Decompress(inSource, outDestination);
839 
840 	return B_NO_TRANSLATOR;
841 }
842 
843 
844 //!	The user has requested the same format for input and output, so just copy
845 status_t
846 JP2Translator::Copy(BPositionIO* in, BPositionIO* out)
847 {
848 	int block_size = 65536;
849 	void* buffer = malloc(block_size);
850 	char temp[1024];
851 	if (buffer == NULL) {
852 		buffer = temp;
853 		block_size = 1024;
854 	}
855 	status_t err = B_OK;
856 
857 	// Read until end of file or error
858 	while (1) {
859 		ssize_t to_read = block_size;
860 		err = in->Read(buffer, to_read);
861 		// Explicit check for EOF
862 		if (err == -1) {
863 			if (buffer != temp)
864 				free(buffer);
865 			return B_OK;
866 		}
867 		if (err <= B_OK) break;
868 		to_read = err;
869 		err = out->Write(buffer, to_read);
870 		if (err != to_read) if (err >= 0) err = B_DEVICE_FULL;
871 		if (err < B_OK) break;
872 	}
873 
874 	if (buffer != temp)
875 		free(buffer);
876 	return (err >= 0) ? B_OK : err;
877 }
878 
879 
880 //!	Encode into the native format
881 status_t
882 JP2Translator::Compress(BPositionIO* in, BPositionIO* out)
883 {
884 	using namespace conversion;
885 
886 	// Read info about bitmap
887 	TranslatorBitmap header;
888 	status_t err = in->Read(&header, sizeof(TranslatorBitmap));
889 	if (err < B_OK)
890 		return err;
891 	if (err < (int)sizeof(TranslatorBitmap))
892 		return B_ERROR;
893 
894 	// Grab dimension, color space, and size information from the stream
895 	BRect bounds;
896 	bounds.left = B_BENDIAN_TO_HOST_FLOAT(header.bounds.left);
897 	bounds.top = B_BENDIAN_TO_HOST_FLOAT(header.bounds.top);
898 	bounds.right = B_BENDIAN_TO_HOST_FLOAT(header.bounds.right);
899 	bounds.bottom = B_BENDIAN_TO_HOST_FLOAT(header.bounds.bottom);
900 
901 	int32 in_row_bytes = B_BENDIAN_TO_HOST_INT32(header.rowBytes);
902 
903 	int width = bounds.IntegerWidth() + 1;
904 	int height = bounds.IntegerHeight() + 1;
905 
906 	// Function pointer to write function
907 	// It MUST point to proper function
908 	void (*converter)(jas_matrix_t** pixels, uchar* inscanline,
909 		int width) = write_rgba32;
910 
911 	// Default color info
912 	int out_color_space = JAS_CLRSPC_SRGB;
913 	int out_color_components = 3;
914 
915 	switch ((color_space)B_BENDIAN_TO_HOST_INT32(header.colors)) {
916 		case B_GRAY1:
917 			if (fSettings->SetGetBool(JP2_SET_GRAY1_AS_B_RGB24)) {
918 				converter = write_gray1_to_rgb24;
919 			} else {
920 				out_color_components = 1;
921 				out_color_space = JAS_CLRSPC_SGRAY;
922 				converter = write_gray1_to_gray;
923 			}
924 			break;
925 
926 		case B_CMAP8:
927 			converter = write_cmap8_to_rgb24;
928 			break;
929 
930 		case B_GRAY8:
931 			out_color_components = 1;
932 			out_color_space = JAS_CLRSPC_SGRAY;
933 			converter = write_gray;
934 			break;
935 
936 		case B_RGB15:
937 		case B_RGBA15:
938 			converter = write_rgb15_to_rgb24;
939 			break;
940 
941 		case B_RGB15_BIG:
942 		case B_RGBA15_BIG:
943 			converter = write_rgb15b_to_rgb24;
944 			break;
945 
946 		case B_RGB16:
947 			converter = write_rgb16_to_rgb24;
948 			break;
949 
950 		case B_RGB16_BIG:
951 			converter = write_rgb16b_to_rgb24;
952 			break;
953 
954 		case B_RGB24:
955 			converter = write_rgb24;
956 			break;
957 
958 		case B_RGB24_BIG:
959 			converter = write_rgb24b;
960 			break;
961 
962 		case B_RGB32:
963 			converter = write_rgb32_to_rgb24;
964 			break;
965 
966 		case B_RGB32_BIG:
967 			converter = write_rgb32b_to_rgb24;
968 			break;
969 
970 		case B_RGBA32:
971 		/*
972 			// In theory it should be possible to write 4 color components
973 			// to jp2, so it should be possible to have transparency.
974 			// Unfortunetly libjasper does not agree with that
975 			// For now i don't know how to modify it :(
976 
977 			out_color_components = 4;
978 			converter = write_rgba32;
979 		*/
980 			converter = write_rgb32_to_rgb24;
981 			break;
982 
983 		case B_RGBA32_BIG:
984 		/*
985 			// In theory it should be possible to write 4 color components
986 			// to jp2, so it should be possible to have transparency.
987 			// Unfortunetly libjasper does not agree with that
988 			// For now i don't know how to modify it :(
989 
990 			out_color_components = 4;
991 			converter = write_rgba32b;
992 		*/
993 			converter = write_rgb32b_to_rgb24;
994 			break;
995 
996 		default:
997 			syslog(LOG_ERR, "Unknown color space.\n");
998 			return B_ERROR;
999 	}
1000 
1001 	jas_image_t* image;
1002 	jas_stream_t* outs;
1003 	jas_matrix_t* pixels[4];
1004 	jas_image_cmptparm_t component_info[4];
1005 
1006 	if (jas_init())
1007 		return B_ERROR;
1008 
1009 	if (!(outs = jas_stream_positionIOopen(out)))
1010 		return B_ERROR;
1011 
1012 	int32 i = 0;
1013 	for (i = 0; i < (long)out_color_components; i++) {
1014 		(void) memset(component_info + i, 0, sizeof(jas_image_cmptparm_t));
1015 		component_info[i].hstep = 1;
1016 		component_info[i].vstep = 1;
1017 		component_info[i].width = (unsigned int)width;
1018 		component_info[i].height = (unsigned int)height;
1019 		component_info[i].prec = (unsigned int)8;
1020 	}
1021 
1022 	image = jas_image_create((short)out_color_components, component_info,
1023 		out_color_space);
1024 	if (image == (jas_image_t *)NULL)
1025 		return Error(outs, NULL, NULL, 0, NULL, B_ERROR);
1026 
1027 	uchar *in_scanline = (uchar*) malloc(in_row_bytes);
1028 	if (in_scanline == NULL)
1029 		return Error(outs, image, NULL, 0, NULL, B_ERROR);
1030 
1031 	for (i = 0; i < (long)out_color_components; i++) {
1032 		pixels[i] = jas_matrix_create(1, (unsigned int)width);
1033 		if (pixels[i] == (jas_matrix_t *)NULL)
1034 			return Error(outs, image, pixels, i+1, in_scanline, B_ERROR);
1035 	}
1036 
1037 	int32 y = 0;
1038 	for (y = 0; y < (long)height; y++) {
1039 		err = in->Read(in_scanline, in_row_bytes);
1040 		if (err < in_row_bytes) {
1041 			return (err < B_OK) ? Error(outs, image, pixels,
1042 					out_color_components, in_scanline, err)
1043 				: Error(outs, image, pixels, out_color_components, in_scanline,
1044 					B_ERROR);
1045 		}
1046 
1047 		converter(pixels, in_scanline, width);
1048 
1049 		for (i = 0; i < (long)out_color_components; i++) {
1050 			(void)jas_image_writecmpt(image, (short)i, 0, (unsigned int)y,
1051 				(unsigned int)width, 1, pixels[i]);
1052 		}
1053 	}
1054 
1055 	char opts[16];
1056 	sprintf(opts, "rate=%1f",
1057 		(float)fSettings->SetGetInt32(JP2_SET_QUALITY) / 100.0);
1058 
1059 	if (jas_image_encode(image, outs, jas_image_strtofmt(
1060 			fSettings->SetGetBool(JP2_SET_JPC) ?
1061 				(char*)"jpc" : (char*)"jp2"), opts)) {
1062 		return Error(outs, image, pixels,
1063 			out_color_components, in_scanline, err);
1064 	}
1065 
1066 	free(in_scanline);
1067 
1068 	for (i = 0; i < (long)out_color_components; i++)
1069 		jas_matrix_destroy(pixels[i]);
1070 
1071 	jas_stream_close(outs);
1072 	jas_image_destroy(image);
1073 	jas_image_clearfmts();
1074 
1075 	return B_OK;
1076 }
1077 
1078 
1079 //!	Decode the native format
1080 status_t
1081 JP2Translator::Decompress(BPositionIO* in, BPositionIO* out)
1082 {
1083 	using namespace conversion;
1084 
1085 	jas_image_t* image;
1086 	jas_stream_t* ins;
1087 	jas_matrix_t* pixels[4];
1088 
1089 	if (jas_init())
1090 		return B_ERROR;
1091 
1092 	if (!(ins = jas_stream_positionIOopen(in)))
1093 		return B_ERROR;
1094 
1095 	if (!(image = jas_image_decode(ins, -1, 0)))
1096 		return Error(ins, NULL, NULL, 0, NULL, B_ERROR);
1097 
1098 	// Default color info
1099 	color_space out_color_space;
1100 	int out_color_components;
1101 	int	in_color_components = jas_image_numcmpts(image);
1102 
1103 	// Function pointer to read function
1104 	// It MUST point to proper function
1105 	void (*converter)(jas_matrix_t** pixels, uchar* outscanline,
1106 		int width) = NULL;
1107 
1108 	switch (jas_clrspc_fam(jas_image_clrspc(image))) {
1109 		case JAS_CLRSPC_FAM_RGB:
1110 			out_color_components = 4;
1111 			if (in_color_components == 3) {
1112 				out_color_space = B_RGB32;
1113 				converter = read_rgb24_to_rgb32;
1114 			} else if (in_color_components == 4) {
1115 				out_color_space = B_RGBA32;
1116 				converter = read_rgba32;
1117 			} else {
1118 				syslog(LOG_ERR, "Other than RGB with 3 or 4 color "
1119 					"components not implemented.\n");
1120 				return Error(ins, image, NULL, 0, NULL, B_ERROR);
1121 			}
1122 			break;
1123 		case JAS_CLRSPC_FAM_GRAY:
1124 			if (fSettings->SetGetBool(JP2_SET_GRAY8_AS_B_RGB32)) {
1125 				out_color_space = B_RGB32;
1126 				out_color_components = 4;
1127 				converter = read_gray_to_rgb32;
1128 			} else {
1129 				out_color_space = B_GRAY8;
1130 				out_color_components = 1;
1131 				converter = read_gray;
1132 			}
1133 			break;
1134 		case JAS_CLRSPC_FAM_YCBCR:
1135 			syslog(LOG_ERR, "Color space YCBCR not implemented yet.\n");
1136 			return Error(ins, image, NULL, 0, NULL, B_ERROR);
1137 			break;
1138 		case JAS_CLRSPC_UNKNOWN:
1139 		default:
1140 			syslog(LOG_ERR, "Color space unknown. \n");
1141 			return Error(ins, image, NULL, 0, NULL, B_ERROR);
1142 			break;
1143 	}
1144 
1145 	float width = (float)jas_image_width(image);
1146 	float height = (float)jas_image_height(image);
1147 
1148 	// Bytes count in one line of image (scanline)
1149 	int64 out_row_bytes = (int32)width * out_color_components;
1150 		// NOTE: things will go wrong if "out_row_bytes" wouldn't fit into 32 bits
1151 
1152 	// !!! Initialize this bounds rect to the size of your image
1153 	BRect bounds(0, 0, width - 1, height - 1);
1154 
1155 
1156 	// Fill out the B_TRANSLATOR_BITMAP's header
1157 	TranslatorBitmap header;
1158 	header.magic = B_HOST_TO_BENDIAN_INT32(B_TRANSLATOR_BITMAP);
1159 	header.bounds.left = B_HOST_TO_BENDIAN_FLOAT(bounds.left);
1160 	header.bounds.top = B_HOST_TO_BENDIAN_FLOAT(bounds.top);
1161 	header.bounds.right = B_HOST_TO_BENDIAN_FLOAT(bounds.right);
1162 	header.bounds.bottom = B_HOST_TO_BENDIAN_FLOAT(bounds.bottom);
1163 	header.colors = (color_space)B_HOST_TO_BENDIAN_INT32(out_color_space);
1164 	header.rowBytes = B_HOST_TO_BENDIAN_INT32(out_row_bytes);
1165 	header.dataSize = B_HOST_TO_BENDIAN_INT32((int32)(out_row_bytes * height));
1166 
1167 	// Write out the header
1168 	status_t err = out->Write(&header, sizeof(TranslatorBitmap));
1169 	if (err < B_OK)
1170 		return Error(ins, image, NULL, 0, NULL, err);
1171 	if (err < (int)sizeof(TranslatorBitmap))
1172 		return Error(ins, image, NULL, 0, NULL, B_ERROR);
1173 
1174 	uchar *out_scanline = (uchar*) malloc(out_row_bytes);
1175 	if (out_scanline == NULL)
1176 		return Error(ins, image, NULL, 0, NULL, B_ERROR);
1177 
1178 	int32 i = 0;
1179 	for (i = 0; i < (long)in_color_components; i++) {
1180 		pixels[i] = jas_matrix_create(1, (unsigned int)width);
1181 		if (pixels[i] == (jas_matrix_t *)NULL)
1182 			return Error(ins, image, pixels, i + 1, out_scanline, B_ERROR);
1183 	}
1184 
1185 	int32 y = 0;
1186 	for (y = 0; y < (long)height; y++) {
1187 		for (i = 0; i < (long)in_color_components; i++) {
1188 			(void)jas_image_readcmpt(image, (short)i, 0, (unsigned int)y,
1189 				(unsigned int)width, 1, pixels[i]);
1190 		}
1191 
1192 		converter(pixels, out_scanline, (int32)width);
1193 
1194 		err = out->Write(out_scanline, out_row_bytes);
1195 		if (err < out_row_bytes) {
1196 			return (err < B_OK) ? Error(ins, image, pixels, in_color_components,
1197 				out_scanline, err)
1198 				: Error(ins, image, pixels, in_color_components, out_scanline,
1199 					B_ERROR);
1200 		}
1201 	}
1202 
1203 	free(out_scanline);
1204 
1205 	for (i = 0; i < (long)in_color_components; i++)
1206 		jas_matrix_destroy(pixels[i]);
1207 
1208 	jas_stream_close(ins);
1209 	jas_image_destroy(image);
1210 	jas_image_clearfmts();
1211 
1212 	return B_OK;
1213 }
1214 
1215 
1216 /*! searches in both inputFormats & outputFormats */
1217 status_t
1218 JP2Translator::PopulateInfoFromFormat(translator_info* info,
1219 	uint32 formatType, translator_id id)
1220 {
1221 	int32 formatCount;
1222 	const translation_format* formats = OutputFormats(&formatCount);
1223 
1224 	for (int i = 0; i <= 1; formats = InputFormats(&formatCount), i++) {
1225 		if (PopulateInfoFromFormat(info, formatType,
1226 			formats, formatCount) == B_OK) {
1227 			info->translator = id;
1228 			return B_OK;
1229 		}
1230 	}
1231 
1232 	return B_ERROR;
1233 }
1234 
1235 
1236 status_t
1237 JP2Translator::PopulateInfoFromFormat(translator_info* info,
1238 	uint32 formatType, const translation_format* formats, int32 formatCount)
1239 {
1240 	for (int i = 0; i < formatCount; i++) {
1241 		if (formats[i].type == formatType) {
1242 			info->type = formatType;
1243 			info->group = formats[i].group;
1244 			info->quality = formats[i].quality;
1245 			info->capability = formats[i].capability;
1246 			if (strncmp(formats[i].name,
1247 				"Be Bitmap Format (JPEG2000Translator)",
1248 				sizeof("Be Bitmap Format (JPEG2000Translator)")) == 0)
1249 				strncpy(info->name,
1250 					B_TRANSLATE("Be Bitmap Format (JPEG2000Translator)"),
1251 					sizeof(info->name));
1252 			else
1253 				strncpy(info->name, formats[i].name, sizeof(info->name));
1254 			strncpy(info->MIME,  formats[i].MIME, sizeof(info->MIME));
1255 			return B_OK;
1256 		}
1257 	}
1258 
1259 	return B_ERROR;
1260 }
1261 
1262 
1263 /*!
1264 	Frees jpeg alocated memory
1265 	Returns given error (B_ERROR by default)
1266 */
1267 status_t
1268 Error(jas_stream_t* stream, jas_image_t* image, jas_matrix_t** pixels,
1269 	int32 pixels_count, uchar* scanline, status_t error)
1270 {
1271 	if (pixels) {
1272 		int32 i;
1273 		for (i = 0; i < (long)pixels_count; i++) {
1274 			if (pixels[i] != NULL)
1275 				jas_matrix_destroy(pixels[i]);
1276 		}
1277 	}
1278 	if (stream)
1279 		jas_stream_close(stream);
1280 	if (image)
1281 		jas_image_destroy(image);
1282 
1283 	jas_image_clearfmts();
1284 	free(scanline);
1285 
1286 	return error;
1287 }
1288 
1289 
1290 //	#pragma mark -
1291 
1292 BTranslator*
1293 make_nth_translator(int32 n, image_id you, uint32 flags, ...)
1294 {
1295 	if (!n)
1296 		return new JP2Translator();
1297 
1298 	return NULL;
1299 }
1300 
1301 
1302 int
1303 main()
1304 {
1305 	BApplication app("application/x-vnd.Haiku-JPEG2000Translator");
1306 	JP2Translator* translator = new JP2Translator();
1307 	if (LaunchTranslatorWindow(translator, sTranslatorName) == B_OK)
1308 		app.Run();
1309 
1310 	return 0;
1311 }
1312 
1313