xref: /haiku/src/add-ons/translators/jpeg2000/JPEG2000Translator.cpp (revision 52f7c9389475e19fc21487b38064b4390eeb6fea)
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 	rgb_color textColor = ui_color(B_PANEL_TEXT_COLOR);
729 	infoView->SetFontAndColor(be_plain_font, B_FONT_ALL, &textColor);
730 	infoView->MakeEditable(false);
731 
732 	BLayoutBuilder::Group<>(this, B_VERTICAL, 0)
733 		.SetInsets(B_USE_DEFAULT_SPACING)
734 		.Add(title)
735 		.Add(version)
736 		.Add(infoView);
737 }
738 
739 
740 //	#pragma mark -
741 
742 
743 TranslatorView::TranslatorView(const char* name, TranslatorSettings* settings)
744 	:
745 	BTabView(name, B_WIDTH_FROM_LABEL)
746 {
747 	SetBorder(B_NO_BORDER);
748 
749 	AddTab(new TranslatorWriteView(B_TRANSLATE("Write"),
750 		settings->Acquire()));
751 	AddTab(new TranslatorReadView(B_TRANSLATE("Read"),
752 		settings->Acquire()));
753 	AddTab(new TranslatorAboutView(B_TRANSLATE("About")));
754 
755 	settings->Release();
756 
757  	BFont font;
758  	GetFont(&font);
759  	SetExplicitPreferredSize(
760 		BSize((font.Size() * 380) / 12, (font.Size() * 250) / 12));
761 }
762 
763 
764 //	#pragma mark -
765 
766 BView*
767 JP2Translator::NewConfigView(TranslatorSettings* settings)
768 {
769 	BView* outView = new TranslatorView("TranslatorView", settings);
770 	return outView;
771 }
772 
773 
774 JP2Translator::JP2Translator()
775 	: BaseTranslator(sTranslatorName, sTranslatorInfo, sTranslatorVersion,
776 		sInputFormats, kNumInputFormats,
777 		sOutputFormats, kNumOutputFormats,
778 		JP2_SETTINGS_FILE,
779 		sDefaultSettings, kNumDefaultSettings,
780 		B_TRANSLATOR_BITMAP, JP2_FORMAT)
781 {
782 }
783 
784 
785 //!	Determine whether or not we can handle this data
786 status_t
787 JP2Translator::DerivedIdentify(BPositionIO* inSource,
788 	const translation_format* inFormat, BMessage* ioExtension,
789 	translator_info* outInfo, uint32 outType)
790 {
791 	if ((outType != 0) && (outType != B_TRANSLATOR_BITMAP)
792 		&& outType != JP2_FORMAT)
793 		return B_NO_TRANSLATOR;
794 
795 	// !!! You might need to make this buffer bigger to test for your
796 	// native format
797 	off_t position = inSource->Position();
798 	uint8 header[sizeof(TranslatorBitmap)];
799 	status_t err = inSource->Read(header, sizeof(TranslatorBitmap));
800 	inSource->Seek(position, SEEK_SET);
801 	if (err < B_OK)
802 		return err;
803 
804 	if (B_BENDIAN_TO_HOST_INT32(((TranslatorBitmap *)header)->magic)
805 		== B_TRANSLATOR_BITMAP) {
806 		if (PopulateInfoFromFormat(outInfo, B_TRANSLATOR_BITMAP) != B_OK)
807 			return B_NO_TRANSLATOR;
808 	} else {
809 		if ((((header[4] << 24) | (header[5] << 16) | (header[6] << 8)
810 			| header[7]) == JP2_BOX_JP) // JP2
811 			|| (header[0] == (JPC_MS_SOC >> 8) && header[1]
812 			== (JPC_MS_SOC & 0xff)))	// JPC
813 		{
814 			if (PopulateInfoFromFormat(outInfo, JP2_FORMAT) != B_OK)
815 				return B_NO_TRANSLATOR;
816 		} else
817 			return B_NO_TRANSLATOR;
818 	}
819 
820 	return B_OK;
821 }
822 
823 
824 status_t
825 JP2Translator::DerivedTranslate(BPositionIO* inSource,
826 	const translator_info* inInfo, BMessage* ioExtension, uint32 outType,
827 	BPositionIO* outDestination, int32 baseType)
828 {
829 	// If no specific type was requested, convert to the interchange format
830 	if (outType == 0)
831 		outType = B_TRANSLATOR_BITMAP;
832 
833 	// What action to take, based on the findings of Identify()
834 	if (outType == inInfo->type)
835 		return Copy(inSource, outDestination);
836 	if (inInfo->type == B_TRANSLATOR_BITMAP && outType == JP2_FORMAT)
837 		return Compress(inSource, outDestination);
838 	if (inInfo->type == JP2_FORMAT && outType == B_TRANSLATOR_BITMAP)
839 		return Decompress(inSource, outDestination);
840 
841 	return B_NO_TRANSLATOR;
842 }
843 
844 
845 //!	The user has requested the same format for input and output, so just copy
846 status_t
847 JP2Translator::Copy(BPositionIO* in, BPositionIO* out)
848 {
849 	int block_size = 65536;
850 	void* buffer = malloc(block_size);
851 	char temp[1024];
852 	if (buffer == NULL) {
853 		buffer = temp;
854 		block_size = 1024;
855 	}
856 	status_t err = B_OK;
857 
858 	// Read until end of file or error
859 	while (1) {
860 		ssize_t to_read = block_size;
861 		err = in->Read(buffer, to_read);
862 		// Explicit check for EOF
863 		if (err == -1) {
864 			if (buffer != temp)
865 				free(buffer);
866 			return B_OK;
867 		}
868 		if (err <= B_OK) break;
869 		to_read = err;
870 		err = out->Write(buffer, to_read);
871 		if (err != to_read) if (err >= 0) err = B_DEVICE_FULL;
872 		if (err < B_OK) break;
873 	}
874 
875 	if (buffer != temp)
876 		free(buffer);
877 	return (err >= 0) ? B_OK : err;
878 }
879 
880 
881 //!	Encode into the native format
882 status_t
883 JP2Translator::Compress(BPositionIO* in, BPositionIO* out)
884 {
885 	using namespace conversion;
886 
887 	// Read info about bitmap
888 	TranslatorBitmap header;
889 	status_t err = in->Read(&header, sizeof(TranslatorBitmap));
890 	if (err < B_OK)
891 		return err;
892 	if (err < (int)sizeof(TranslatorBitmap))
893 		return B_ERROR;
894 
895 	// Grab dimension, color space, and size information from the stream
896 	BRect bounds;
897 	bounds.left = B_BENDIAN_TO_HOST_FLOAT(header.bounds.left);
898 	bounds.top = B_BENDIAN_TO_HOST_FLOAT(header.bounds.top);
899 	bounds.right = B_BENDIAN_TO_HOST_FLOAT(header.bounds.right);
900 	bounds.bottom = B_BENDIAN_TO_HOST_FLOAT(header.bounds.bottom);
901 
902 	int32 in_row_bytes = B_BENDIAN_TO_HOST_INT32(header.rowBytes);
903 
904 	int width = bounds.IntegerWidth() + 1;
905 	int height = bounds.IntegerHeight() + 1;
906 
907 	// Function pointer to write function
908 	// It MUST point to proper function
909 	void (*converter)(jas_matrix_t** pixels, uchar* inscanline,
910 		int width) = write_rgba32;
911 
912 	// Default color info
913 	int out_color_space = JAS_CLRSPC_SRGB;
914 	int out_color_components = 3;
915 
916 	switch ((color_space)B_BENDIAN_TO_HOST_INT32(header.colors)) {
917 		case B_GRAY1:
918 			if (fSettings->SetGetBool(JP2_SET_GRAY1_AS_B_RGB24)) {
919 				converter = write_gray1_to_rgb24;
920 			} else {
921 				out_color_components = 1;
922 				out_color_space = JAS_CLRSPC_SGRAY;
923 				converter = write_gray1_to_gray;
924 			}
925 			break;
926 
927 		case B_CMAP8:
928 			converter = write_cmap8_to_rgb24;
929 			break;
930 
931 		case B_GRAY8:
932 			out_color_components = 1;
933 			out_color_space = JAS_CLRSPC_SGRAY;
934 			converter = write_gray;
935 			break;
936 
937 		case B_RGB15:
938 		case B_RGBA15:
939 			converter = write_rgb15_to_rgb24;
940 			break;
941 
942 		case B_RGB15_BIG:
943 		case B_RGBA15_BIG:
944 			converter = write_rgb15b_to_rgb24;
945 			break;
946 
947 		case B_RGB16:
948 			converter = write_rgb16_to_rgb24;
949 			break;
950 
951 		case B_RGB16_BIG:
952 			converter = write_rgb16b_to_rgb24;
953 			break;
954 
955 		case B_RGB24:
956 			converter = write_rgb24;
957 			break;
958 
959 		case B_RGB24_BIG:
960 			converter = write_rgb24b;
961 			break;
962 
963 		case B_RGB32:
964 			converter = write_rgb32_to_rgb24;
965 			break;
966 
967 		case B_RGB32_BIG:
968 			converter = write_rgb32b_to_rgb24;
969 			break;
970 
971 		case B_RGBA32:
972 		/*
973 			// In theory it should be possible to write 4 color components
974 			// to jp2, so it should be possible to have transparency.
975 			// Unfortunetly libjasper does not agree with that
976 			// For now i don't know how to modify it :(
977 
978 			out_color_components = 4;
979 			converter = write_rgba32;
980 		*/
981 			converter = write_rgb32_to_rgb24;
982 			break;
983 
984 		case B_RGBA32_BIG:
985 		/*
986 			// In theory it should be possible to write 4 color components
987 			// to jp2, so it should be possible to have transparency.
988 			// Unfortunetly libjasper does not agree with that
989 			// For now i don't know how to modify it :(
990 
991 			out_color_components = 4;
992 			converter = write_rgba32b;
993 		*/
994 			converter = write_rgb32b_to_rgb24;
995 			break;
996 
997 		default:
998 			syslog(LOG_ERR, "Unknown color space.\n");
999 			return B_ERROR;
1000 	}
1001 
1002 	jas_image_t* image;
1003 	jas_stream_t* outs;
1004 	jas_matrix_t* pixels[4];
1005 	jas_image_cmptparm_t component_info[4];
1006 
1007 	if (jas_init())
1008 		return B_ERROR;
1009 
1010 	if (!(outs = jas_stream_positionIOopen(out)))
1011 		return B_ERROR;
1012 
1013 	int32 i = 0;
1014 	for (i = 0; i < (long)out_color_components; i++) {
1015 		(void) memset(component_info + i, 0, sizeof(jas_image_cmptparm_t));
1016 		component_info[i].hstep = 1;
1017 		component_info[i].vstep = 1;
1018 		component_info[i].width = (unsigned int)width;
1019 		component_info[i].height = (unsigned int)height;
1020 		component_info[i].prec = (unsigned int)8;
1021 	}
1022 
1023 	image = jas_image_create((short)out_color_components, component_info,
1024 		out_color_space);
1025 	if (image == (jas_image_t *)NULL)
1026 		return Error(outs, NULL, NULL, 0, NULL, B_ERROR);
1027 
1028 	uchar *in_scanline = (uchar*) malloc(in_row_bytes);
1029 	if (in_scanline == NULL)
1030 		return Error(outs, image, NULL, 0, NULL, B_ERROR);
1031 
1032 	for (i = 0; i < (long)out_color_components; i++) {
1033 		pixels[i] = jas_matrix_create(1, (unsigned int)width);
1034 		if (pixels[i] == (jas_matrix_t *)NULL)
1035 			return Error(outs, image, pixels, i+1, in_scanline, B_ERROR);
1036 	}
1037 
1038 	int32 y = 0;
1039 	for (y = 0; y < (long)height; y++) {
1040 		err = in->Read(in_scanline, in_row_bytes);
1041 		if (err < in_row_bytes) {
1042 			return (err < B_OK) ? Error(outs, image, pixels,
1043 					out_color_components, in_scanline, err)
1044 				: Error(outs, image, pixels, out_color_components, in_scanline,
1045 					B_ERROR);
1046 		}
1047 
1048 		converter(pixels, in_scanline, width);
1049 
1050 		for (i = 0; i < (long)out_color_components; i++) {
1051 			(void)jas_image_writecmpt(image, (short)i, 0, (unsigned int)y,
1052 				(unsigned int)width, 1, pixels[i]);
1053 		}
1054 	}
1055 
1056 	char opts[16];
1057 	sprintf(opts, "rate=%1f",
1058 		(float)fSettings->SetGetInt32(JP2_SET_QUALITY) / 100.0);
1059 
1060 	if (jas_image_encode(image, outs, jas_image_strtofmt(
1061 			fSettings->SetGetBool(JP2_SET_JPC) ?
1062 				(char*)"jpc" : (char*)"jp2"), opts)) {
1063 		return Error(outs, image, pixels,
1064 			out_color_components, in_scanline, err);
1065 	}
1066 
1067 	free(in_scanline);
1068 
1069 	for (i = 0; i < (long)out_color_components; i++)
1070 		jas_matrix_destroy(pixels[i]);
1071 
1072 	jas_stream_close(outs);
1073 	jas_image_destroy(image);
1074 	jas_image_clearfmts();
1075 
1076 	return B_OK;
1077 }
1078 
1079 
1080 //!	Decode the native format
1081 status_t
1082 JP2Translator::Decompress(BPositionIO* in, BPositionIO* out)
1083 {
1084 	using namespace conversion;
1085 
1086 	jas_image_t* image;
1087 	jas_stream_t* ins;
1088 	jas_matrix_t* pixels[4];
1089 
1090 	if (jas_init())
1091 		return B_ERROR;
1092 
1093 	if (!(ins = jas_stream_positionIOopen(in)))
1094 		return B_ERROR;
1095 
1096 	if (!(image = jas_image_decode(ins, -1, 0)))
1097 		return Error(ins, NULL, NULL, 0, NULL, B_ERROR);
1098 
1099 	// Default color info
1100 	color_space out_color_space;
1101 	int out_color_components;
1102 	int	in_color_components = jas_image_numcmpts(image);
1103 
1104 	// Function pointer to read function
1105 	// It MUST point to proper function
1106 	void (*converter)(jas_matrix_t** pixels, uchar* outscanline,
1107 		int width) = NULL;
1108 
1109 	switch (jas_clrspc_fam(jas_image_clrspc(image))) {
1110 		case JAS_CLRSPC_FAM_RGB:
1111 			out_color_components = 4;
1112 			if (in_color_components == 3) {
1113 				out_color_space = B_RGB32;
1114 				converter = read_rgb24_to_rgb32;
1115 			} else if (in_color_components == 4) {
1116 				out_color_space = B_RGBA32;
1117 				converter = read_rgba32;
1118 			} else {
1119 				syslog(LOG_ERR, "Other than RGB with 3 or 4 color "
1120 					"components not implemented.\n");
1121 				return Error(ins, image, NULL, 0, NULL, B_ERROR);
1122 			}
1123 			break;
1124 		case JAS_CLRSPC_FAM_GRAY:
1125 			if (fSettings->SetGetBool(JP2_SET_GRAY8_AS_B_RGB32)) {
1126 				out_color_space = B_RGB32;
1127 				out_color_components = 4;
1128 				converter = read_gray_to_rgb32;
1129 			} else {
1130 				out_color_space = B_GRAY8;
1131 				out_color_components = 1;
1132 				converter = read_gray;
1133 			}
1134 			break;
1135 		case JAS_CLRSPC_FAM_YCBCR:
1136 			syslog(LOG_ERR, "Color space YCBCR not implemented yet.\n");
1137 			return Error(ins, image, NULL, 0, NULL, B_ERROR);
1138 			break;
1139 		case JAS_CLRSPC_UNKNOWN:
1140 		default:
1141 			syslog(LOG_ERR, "Color space unknown. \n");
1142 			return Error(ins, image, NULL, 0, NULL, B_ERROR);
1143 			break;
1144 	}
1145 
1146 	float width = (float)jas_image_width(image);
1147 	float height = (float)jas_image_height(image);
1148 
1149 	// Bytes count in one line of image (scanline)
1150 	int64 out_row_bytes = (int32)width * out_color_components;
1151 		// NOTE: things will go wrong if "out_row_bytes" wouldn't fit into 32 bits
1152 
1153 	// !!! Initialize this bounds rect to the size of your image
1154 	BRect bounds(0, 0, width - 1, height - 1);
1155 
1156 
1157 	// Fill out the B_TRANSLATOR_BITMAP's header
1158 	TranslatorBitmap header;
1159 	header.magic = B_HOST_TO_BENDIAN_INT32(B_TRANSLATOR_BITMAP);
1160 	header.bounds.left = B_HOST_TO_BENDIAN_FLOAT(bounds.left);
1161 	header.bounds.top = B_HOST_TO_BENDIAN_FLOAT(bounds.top);
1162 	header.bounds.right = B_HOST_TO_BENDIAN_FLOAT(bounds.right);
1163 	header.bounds.bottom = B_HOST_TO_BENDIAN_FLOAT(bounds.bottom);
1164 	header.colors = (color_space)B_HOST_TO_BENDIAN_INT32(out_color_space);
1165 	header.rowBytes = B_HOST_TO_BENDIAN_INT32(out_row_bytes);
1166 	header.dataSize = B_HOST_TO_BENDIAN_INT32((int32)(out_row_bytes * height));
1167 
1168 	// Write out the header
1169 	status_t err = out->Write(&header, sizeof(TranslatorBitmap));
1170 	if (err < B_OK)
1171 		return Error(ins, image, NULL, 0, NULL, err);
1172 	if (err < (int)sizeof(TranslatorBitmap))
1173 		return Error(ins, image, NULL, 0, NULL, B_ERROR);
1174 
1175 	uchar *out_scanline = (uchar*) malloc(out_row_bytes);
1176 	if (out_scanline == NULL)
1177 		return Error(ins, image, NULL, 0, NULL, B_ERROR);
1178 
1179 	int32 i = 0;
1180 	for (i = 0; i < (long)in_color_components; i++) {
1181 		pixels[i] = jas_matrix_create(1, (unsigned int)width);
1182 		if (pixels[i] == (jas_matrix_t *)NULL)
1183 			return Error(ins, image, pixels, i + 1, out_scanline, B_ERROR);
1184 	}
1185 
1186 	int32 y = 0;
1187 	for (y = 0; y < (long)height; y++) {
1188 		for (i = 0; i < (long)in_color_components; i++) {
1189 			(void)jas_image_readcmpt(image, (short)i, 0, (unsigned int)y,
1190 				(unsigned int)width, 1, pixels[i]);
1191 		}
1192 
1193 		converter(pixels, out_scanline, (int32)width);
1194 
1195 		err = out->Write(out_scanline, out_row_bytes);
1196 		if (err < out_row_bytes) {
1197 			return (err < B_OK) ? Error(ins, image, pixels, in_color_components,
1198 				out_scanline, err)
1199 				: Error(ins, image, pixels, in_color_components, out_scanline,
1200 					B_ERROR);
1201 		}
1202 	}
1203 
1204 	free(out_scanline);
1205 
1206 	for (i = 0; i < (long)in_color_components; i++)
1207 		jas_matrix_destroy(pixels[i]);
1208 
1209 	jas_stream_close(ins);
1210 	jas_image_destroy(image);
1211 	jas_image_clearfmts();
1212 
1213 	return B_OK;
1214 }
1215 
1216 
1217 /*! searches in both inputFormats & outputFormats */
1218 status_t
1219 JP2Translator::PopulateInfoFromFormat(translator_info* info,
1220 	uint32 formatType, translator_id id)
1221 {
1222 	int32 formatCount;
1223 	const translation_format* formats = OutputFormats(&formatCount);
1224 
1225 	for (int i = 0; i <= 1; formats = InputFormats(&formatCount), i++) {
1226 		if (PopulateInfoFromFormat(info, formatType,
1227 			formats, formatCount) == B_OK) {
1228 			info->translator = id;
1229 			return B_OK;
1230 		}
1231 	}
1232 
1233 	return B_ERROR;
1234 }
1235 
1236 
1237 status_t
1238 JP2Translator::PopulateInfoFromFormat(translator_info* info,
1239 	uint32 formatType, const translation_format* formats, int32 formatCount)
1240 {
1241 	for (int i = 0; i < formatCount; i++) {
1242 		if (formats[i].type == formatType) {
1243 			info->type = formatType;
1244 			info->group = formats[i].group;
1245 			info->quality = formats[i].quality;
1246 			info->capability = formats[i].capability;
1247 			if (strcmp(formats[i].name, B_TRANSLATOR_BITMAP_DESCRIPTION)
1248 				== 0) {
1249 				strlcpy(info->name,
1250 					B_TRANSLATE(B_TRANSLATOR_BITMAP_DESCRIPTION),
1251 					sizeof(info->name));
1252 			} else {
1253 				strlcpy(info->name, formats[i].name, sizeof(info->name));
1254 			}
1255 			strlcpy(info->MIME, formats[i].MIME, sizeof(info->MIME));
1256 			return B_OK;
1257 		}
1258 	}
1259 
1260 	return B_ERROR;
1261 }
1262 
1263 
1264 /*!
1265 	Frees jpeg alocated memory
1266 	Returns given error (B_ERROR by default)
1267 */
1268 status_t
1269 Error(jas_stream_t* stream, jas_image_t* image, jas_matrix_t** pixels,
1270 	int32 pixels_count, uchar* scanline, status_t error)
1271 {
1272 	if (pixels) {
1273 		int32 i;
1274 		for (i = 0; i < (long)pixels_count; i++) {
1275 			if (pixels[i] != NULL)
1276 				jas_matrix_destroy(pixels[i]);
1277 		}
1278 	}
1279 	if (stream)
1280 		jas_stream_close(stream);
1281 	if (image)
1282 		jas_image_destroy(image);
1283 
1284 	jas_image_clearfmts();
1285 	free(scanline);
1286 
1287 	return error;
1288 }
1289 
1290 
1291 //	#pragma mark -
1292 
1293 BTranslator*
1294 make_nth_translator(int32 n, image_id you, uint32 flags, ...)
1295 {
1296 	if (!n)
1297 		return new JP2Translator();
1298 
1299 	return NULL;
1300 }
1301 
1302 
1303 int
1304 main()
1305 {
1306 	BApplication app("application/x-vnd.Haiku-JPEG2000Translator");
1307 	JP2Translator* translator = new JP2Translator();
1308 	if (LaunchTranslatorWindow(translator, sTranslatorName) == B_OK)
1309 		app.Run();
1310 
1311 	return 0;
1312 }
1313 
1314