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