xref: /haiku/src/add-ons/translators/jpeg2000/JPEG2000Translator.cpp (revision e688bf23d48bfd1216a0cacbdbda5e35a1bcd779)
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 "jp2_cod.h"
35 #include "jpc_cs.h"
36 #include "TranslatorWindow.h"
37 
38 #include <syslog.h>
39 
40 #include <LayoutBuilder.h>
41 #include <TabView.h>
42 #include <TextView.h>
43 
44 
45 #undef B_TRANSLATION_CONTEXT
46 #define B_TRANSLATION_CONTEXT "JPEG2000Translator"
47 
48 // Set these accordingly
49 #define JP2_ACRONYM "JP2"
50 #define JP2_FORMAT 'JP2 '
51 #define JP2_MIME_STRING "image/jp2"
52 #define JP2_DESCRIPTION "JPEG2000 image"
53 
54 // The translation kit's native file type
55 #define B_TRANSLATOR_BITMAP_MIME_STRING "image/x-be-bitmap"
56 #define B_TRANSLATOR_BITMAP_DESCRIPTION "Be Bitmap Format (JPEG2000Translator)"
57 
58 static int32 sTranslatorVersion = B_TRANSLATION_MAKE_VERSION(1, 0, 0);
59 
60 static const char* sTranslatorName = B_TRANSLATE("JPEG2000 images");
61 static const char* sTranslatorInfo = B_TRANSLATE("©2002-2003, Shard\n"
62 	"©2005-2006, Haiku\n"
63 	"\n"
64 	"Based on JasPer library:\n"
65 	"© 1999-2000, Image Power, Inc. and\n"
66 	"the University of British Columbia, Canada.\n"
67 	"© 2001-2003 Michael David Adams.\n"
68 	"\thttp://www.ece.uvic.ca/~mdadams/jasper/\n"
69 	"\n"
70 	"ImageMagick's jp2 codec was used as \"tutorial\".\n"
71 	"\thttp://www.imagemagick.org/\n");
72 
73 static const translation_format sInputFormats[] = {
74 	{ JP2_FORMAT, B_TRANSLATOR_BITMAP, 0.5, 0.5,
75 		JP2_MIME_STRING, JP2_DESCRIPTION },
76 	{ B_TRANSLATOR_BITMAP, B_TRANSLATOR_BITMAP, 0.5, 0.5,
77 		B_TRANSLATOR_BITMAP_MIME_STRING, B_TRANSLATOR_BITMAP_DESCRIPTION },
78 };
79 
80 static const translation_format sOutputFormats[] = {
81 	{ JP2_FORMAT, B_TRANSLATOR_BITMAP, 0.5, 0.5,
82 		JP2_MIME_STRING, JP2_DESCRIPTION },
83 	{ B_TRANSLATOR_BITMAP, B_TRANSLATOR_BITMAP, 0.5, 0.5,
84 		B_TRANSLATOR_BITMAP_MIME_STRING, B_TRANSLATOR_BITMAP_DESCRIPTION },
85 };
86 
87 
88 static const TranSetting sDefaultSettings[] = {
89 	{JP2_SET_QUALITY, TRAN_SETTING_INT32, 25},
90 	{JP2_SET_JPC, TRAN_SETTING_BOOL, false},
91 	{JP2_SET_GRAY1_AS_B_RGB24, TRAN_SETTING_BOOL, false},
92 	{JP2_SET_GRAY8_AS_B_RGB32, TRAN_SETTING_BOOL, true}
93 };
94 
95 const uint32 kNumInputFormats = sizeof(sInputFormats) / sizeof(translation_format);
96 const uint32 kNumOutputFormats = sizeof(sOutputFormats) / sizeof(translation_format);
97 const uint32 kNumDefaultSettings = sizeof(sDefaultSettings) / sizeof(TranSetting);
98 
99 
100 namespace conversion{
101 //!	Make RGB32 scanline from *pixels[3]
102 inline void
103 read_rgb24_to_rgb32(jas_matrix_t** pixels, jpr_uchar_t* scanline, int width)
104 {
105 	int32 index = 0;
106 	int32 x = 0;
107 	while (x < width) {
108 		scanline[index++] = (jpr_uchar_t)jas_matrix_getv(pixels[2], x);
109 		scanline[index++] = (jpr_uchar_t)jas_matrix_getv(pixels[1], x);
110 		scanline[index++] = (jpr_uchar_t)jas_matrix_getv(pixels[0], x);
111 		scanline[index++] = 255;
112 		x++;
113 	}
114 }
115 
116 
117 //!	Make gray scanline from *pixels[1]
118 inline void
119 read_gray_to_rgb32(jas_matrix_t** pixels, jpr_uchar_t* scanline, int width)
120 {
121 	int32 index = 0;
122 	int32 x = 0;
123 	jpr_uchar_t color = 0;
124 	while (x < width) {
125 		color = (jpr_uchar_t)jas_matrix_getv(pixels[0], x++);
126 		scanline[index++] = color;
127 		scanline[index++] = color;
128 		scanline[index++] = color;
129 		scanline[index++] = 255;
130 	}
131 }
132 
133 
134 /*!
135 	Make RGBA32 scanline from *pixels[4]
136 	(just read data to scanline)
137 */
138 inline void
139 read_rgba32(jas_matrix_t** pixels, jpr_uchar_t *scanline, int width)
140 {
141 	int32 index = 0;
142 	int32 x = 0;
143 	while (x < width) {
144 		scanline[index++] = (jpr_uchar_t)jas_matrix_getv(pixels[2], x);
145 		scanline[index++] = (jpr_uchar_t)jas_matrix_getv(pixels[1], x);
146 		scanline[index++] = (jpr_uchar_t)jas_matrix_getv(pixels[0], x);
147 		scanline[index++] = (jpr_uchar_t)jas_matrix_getv(pixels[3], x);
148 		x++;
149 	}
150 }
151 
152 
153 /*!
154 	Make gray scanline from *pixels[1]
155 	(just read data to scanline)
156 */
157 inline void
158 read_gray(jas_matrix_t** pixels, jpr_uchar_t* scanline, int width)
159 {
160 	int32 x = 0;
161 	while (x < width) {
162 		scanline[x] = (jpr_uchar_t)jas_matrix_getv(pixels[0], x);
163 		x++;
164 	}
165 }
166 
167 
168 //!	Make *pixels[1] from gray1 scanline
169 inline void
170 write_gray1_to_gray(jas_matrix_t** pixels, jpr_uchar_t* scanline, int width)
171 {
172 	int32 x = 0;
173 	int32 index = 0;
174 	while (x < (width/8)) {
175 		unsigned char c = scanline[x++];
176 		for (int b = 128; b; b = b >> 1) {
177 			if (c & b)
178 				jas_matrix_setv(pixels[0], index++, 0);
179 			else
180 				jas_matrix_setv(pixels[0], index++, 255);
181 		}
182 	}
183 }
184 
185 
186 //!	Make *pixels[3] from gray1 scanline
187 inline void
188 write_gray1_to_rgb24(jas_matrix_t** pixels, jpr_uchar_t* scanline, int width)
189 {
190 	int32 x = 0;
191 	int32 index = 0;
192 	while (x < (width / 8)) {
193 		unsigned char c = scanline[x++];
194 		for (int b = 128; b; b = b >> 1) {
195 			if (c & b) {
196 				jas_matrix_setv(pixels[0], index, 0);
197 				jas_matrix_setv(pixels[1], index, 0);
198 				jas_matrix_setv(pixels[2], index, 0);
199 			} else {
200 				jas_matrix_setv(pixels[0], index, 255);
201 				jas_matrix_setv(pixels[1], index, 255);
202 				jas_matrix_setv(pixels[2], index, 255);
203 			}
204 			index++;
205 		}
206 	}
207 }
208 
209 
210 //!	Make *pixels[3] from cmap8 scanline
211 inline void
212 write_cmap8_to_rgb24(jas_matrix_t** pixels, jpr_uchar_t* scanline, int width)
213 {
214 	const color_map* map = system_colors();
215 	int32 x = 0;
216 	while (x < width) {
217 		rgb_color color = map->color_list[scanline[x]];
218 
219 		jas_matrix_setv(pixels[0], x, color.red);
220 		jas_matrix_setv(pixels[1], x, color.green);
221 		jas_matrix_setv(pixels[2], x, color.blue);
222 		x++;
223 	}
224 }
225 
226 
227 /*!
228 	Make *pixels[1] from gray scanline
229 	(just write data to pixels)
230 */
231 inline void
232 write_gray(jas_matrix_t** pixels, jpr_uchar_t* scanline, int width)
233 {
234 	int32 x = 0;
235 	while (x < width) {
236 		jas_matrix_setv(pixels[0], x, scanline[x]);
237 		x++;
238 	}
239 }
240 
241 
242 /*!
243 	Make *pixels[3] from RGB15/RGBA15 scanline
244 	(just write data to pixels)
245 */
246 inline void
247 write_rgb15_to_rgb24(jas_matrix_t** pixels, jpr_uchar_t* scanline, int width)
248 {
249 	int32 x = 0;
250 	int32 index = 0;
251 	int16 in_pixel;
252 	while (x < width) {
253 		in_pixel = scanline[index] | (scanline[index+1] << 8);
254 		index += 2;
255 
256 		jas_matrix_setv(pixels[0], x, (char)(((in_pixel & 0x7c00)) >> 7)
257 			| (((in_pixel & 0x7c00)) >> 12));
258 		jas_matrix_setv(pixels[1], x, (char)(((in_pixel & 0x3e0)) >> 2)
259 			| (((in_pixel & 0x3e0)) >> 7));
260 		jas_matrix_setv(pixels[2], x, (char)(((in_pixel & 0x1f)) << 3)
261 			| (((in_pixel & 0x1f)) >> 2));
262 		x++;
263 	}
264 }
265 
266 
267 /*!
268 	Make *pixels[3] from RGB15/RGBA15 bigendian scanline
269 	(just write data to pixels)
270 */
271 inline void
272 write_rgb15b_to_rgb24(jas_matrix_t** pixels, jpr_uchar_t* scanline, int width)
273 {
274 	int32 x = 0;
275 	int32 index = 0;
276 	int16 in_pixel;
277 	while (x < width) {
278 		in_pixel = scanline[index + 1] | (scanline[index] << 8);
279 		index += 2;
280 
281 		jas_matrix_setv(pixels[0], x, (char)(((in_pixel & 0x7c00)) >> 7)
282 			| (((in_pixel & 0x7c00)) >> 12));
283 		jas_matrix_setv(pixels[1], x, (char)(((in_pixel & 0x3e0)) >> 2)
284 			| (((in_pixel & 0x3e0)) >> 7));
285 		jas_matrix_setv(pixels[2], x, (char)(((in_pixel & 0x1f)) << 3)
286 			| (((in_pixel & 0x1f)) >> 2));
287 		x++;
288 	}
289 }
290 
291 
292 /*!
293 	Make *pixels[3] from RGB16/RGBA16 scanline
294 	(just write data to pixels)
295 */
296 inline void
297 write_rgb16_to_rgb24(jas_matrix_t** pixels, jpr_uchar_t* scanline, int width)
298 {
299 	int32 x = 0;
300 	int32 index = 0;
301 	int16 in_pixel;
302 	while (x < width) {
303 		in_pixel = scanline[index] | (scanline[index+1] << 8);
304 		index += 2;
305 
306 		jas_matrix_setv(pixels[0], x, (char)(((in_pixel & 0xf800)) >> 8)
307 			| (((in_pixel & 0x7c00)) >> 12));
308 		jas_matrix_setv(pixels[1], x, (char)(((in_pixel & 0x7e0)) >> 3)
309 			| (((in_pixel & 0x7e0)) >> 9));
310 		jas_matrix_setv(pixels[2], x, (char)(((in_pixel & 0x1f)) << 3)
311 			| (((in_pixel & 0x1f)) >> 2));
312 		x++;
313 	}
314 }
315 
316 
317 /*!
318 	Make *pixels[3] from RGB16/RGBA16 bigendian scanline
319 	(just write data to pixels)
320 */
321 inline void
322 write_rgb16b_to_rgb24(jas_matrix_t** pixels, jpr_uchar_t* scanline, int width)
323 {
324 	int32 x = 0;
325 	int32 index = 0;
326 	int16 in_pixel;
327 	while (x < width) {
328 		in_pixel = scanline[index + 1] | (scanline[index] << 8);
329 		index += 2;
330 
331 		jas_matrix_setv(pixels[0], x, (char)(((in_pixel & 0xf800)) >> 8)
332 			| (((in_pixel & 0xf800)) >> 13));
333 		jas_matrix_setv(pixels[1], x, (char)(((in_pixel & 0x7e0)) >> 3)
334 			| (((in_pixel & 0x7e0)) >> 9));
335 		jas_matrix_setv(pixels[2], x, (char)(((in_pixel & 0x1f)) << 3)
336 			| (((in_pixel & 0x1f)) >> 2));
337 		x++;
338 	}
339 }
340 
341 
342 /*!
343 	Make *pixels[3] from RGB24 scanline
344 	(just write data to pixels)
345 */
346 inline void
347 write_rgb24(jas_matrix_t** pixels, jpr_uchar_t* scanline, int width)
348 {
349 	int32 index = 0;
350 	int32 x = 0;
351 	while (x < width) {
352 		jas_matrix_setv(pixels[2], x, scanline[index++]);
353 		jas_matrix_setv(pixels[1], x, scanline[index++]);
354 		jas_matrix_setv(pixels[0], x, scanline[index++]);
355 		x++;
356 	}
357 }
358 
359 
360 /*!
361 	Make *pixels[3] from RGB24 bigendian scanline
362 	(just write data to pixels)
363 */
364 inline void
365 write_rgb24b(jas_matrix_t** pixels, jpr_uchar_t* scanline, int width)
366 {
367 	int32 index = 0;
368 	int32 x = 0;
369 	while (x < width) {
370 		jas_matrix_setv(pixels[0], x, scanline[index++]);
371 		jas_matrix_setv(pixels[1], x, scanline[index++]);
372 		jas_matrix_setv(pixels[2], x, scanline[index++]);
373 		x++;
374 	}
375 }
376 
377 
378 /*!
379 	Make *pixels[3] from RGB32 scanline
380 	(just write data to pixels)
381 */
382 inline void
383 write_rgb32_to_rgb24(jas_matrix_t** pixels, jpr_uchar_t* scanline, int width)
384 {
385 	int32 index = 0;
386 	int32 x = 0;
387 	while (x < width) {
388 		jas_matrix_setv(pixels[2], x, scanline[index++]);
389 		jas_matrix_setv(pixels[1], x, scanline[index++]);
390 		jas_matrix_setv(pixels[0], x, scanline[index++]);
391 		index++;
392 		x++;
393 	}
394 }
395 
396 
397 /*!
398 	Make *pixels[3] from RGB32 bigendian scanline
399 	(just write data to pixels)
400 */
401 inline void
402 write_rgb32b_to_rgb24(jas_matrix_t** pixels, jpr_uchar_t* scanline, int width)
403 {
404 	int32 index = 0;
405 	int32 x = 0;
406 	while (x < width) {
407 		index++;
408 		jas_matrix_setv(pixels[0], x, scanline[index++]);
409 		jas_matrix_setv(pixels[1], x, scanline[index++]);
410 		jas_matrix_setv(pixels[2], x, scanline[index++]);
411 		x++;
412 	}
413 }
414 
415 
416 /*!
417 	Make *pixels[4] from RGBA32 scanline
418 	(just write data to pixels)
419 	!!! UNTESTED !!!
420 */
421 inline void
422 write_rgba32(jas_matrix_t** pixels, jpr_uchar_t* scanline, int width)
423 {
424 	int32 index = 0;
425 	int32 x = 0;
426 	while (x < width) {
427 		jas_matrix_setv(pixels[3], x, scanline[index++]);
428 		jas_matrix_setv(pixels[2], x, scanline[index++]);
429 		jas_matrix_setv(pixels[1], x, scanline[index++]);
430 		jas_matrix_setv(pixels[0], x, scanline[index++]);
431 		x++;
432 	}
433 }
434 
435 
436 /*!
437 	Make *pixels[4] from RGBA32 bigendian scanline
438 	(just write data to pixels)
439 	!!! UNTESTED !!!
440 */
441 inline void
442 write_rgba32b(jas_matrix_t** pixels, jpr_uchar_t* scanline, int width)
443 {
444 	int32 index = 0;
445 	int32 x = 0;
446 	while (x < width)
447 	{
448 		jas_matrix_setv(pixels[0], x, scanline[index++]);
449 		jas_matrix_setv(pixels[1], x, scanline[index++]);
450 		jas_matrix_setv(pixels[2], x, scanline[index++]);
451 		jas_matrix_setv(pixels[3], x, scanline[index++]);
452 		x++;
453 	}
454 }
455 
456 
457 }// end namespace conversion
458 
459 
460 //	#pragma mark -	jasper I/O
461 
462 
463 static int
464 Read(jas_stream_obj_t* object, char* buffer, const int length)
465 {
466 	return (*(BPositionIO**)object)->Read(buffer, length);
467 }
468 
469 
470 static int
471 Write(jas_stream_obj_t* object, char* buffer, const int length)
472 {
473 	return (*(BPositionIO**)object)->Write(buffer, length);
474 }
475 
476 
477 static long
478 Seek(jas_stream_obj_t* object, long offset, int origin)
479 {
480 	return (*(BPositionIO**)object)->Seek(offset, origin);
481 }
482 
483 
484 static int
485 Close(jas_stream_obj_t* object)
486 {
487 	return 0;
488 }
489 
490 
491 static jas_stream_ops_t positionIOops = {
492 	Read,
493 	Write,
494 	Seek,
495 	Close
496 };
497 
498 
499 static jas_stream_t*
500 jas_stream_positionIOopen(BPositionIO *positionIO)
501 {
502 	jas_stream_t* stream;
503 
504 	stream = (jas_stream_t *)malloc(sizeof(jas_stream_t));
505 	if (stream == (jas_stream_t *)NULL)
506 		return (jas_stream_t *)NULL;
507 
508 	memset(stream, 0, sizeof(jas_stream_t));
509 	stream->rwlimit_ = -1;
510 	stream->obj_=(jas_stream_obj_t *)malloc(sizeof(BPositionIO*));
511 	if (stream->obj_ == (jas_stream_obj_t *)NULL) {
512 		free(stream);
513 		return (jas_stream_t *)NULL;
514 	}
515 
516 	*((BPositionIO**)stream->obj_) = positionIO;
517 	stream->ops_ = (&positionIOops);
518 	stream->openmode_ = JAS_STREAM_READ | JAS_STREAM_WRITE | JAS_STREAM_BINARY;
519 	stream->bufbase_ = stream->tinybuf_;
520 	stream->bufsize_ = 1;
521 	stream->bufstart_ = (&stream->bufbase_[JAS_STREAM_MAXPUTBACK]);
522 	stream->ptr_ = stream->bufstart_;
523 	stream->bufmode_ |= JAS_STREAM_UNBUF & JAS_STREAM_BUFMODEMASK;
524 
525 	return stream;
526 }
527 
528 
529 //	#pragma mark -
530 
531 
532 SSlider::SSlider(const char* name, const char* label,
533 		BMessage* message, int32 minValue, int32 maxValue, orientation posture,
534 		thumb_style thumbType, uint32 flags)
535 	:
536 	BSlider(name, label, message, minValue, maxValue,
537 		posture, thumbType, flags)
538 {
539 	rgb_color barColor = { 0, 0, 229, 255 };
540 	UseFillColor(true, &barColor);
541 }
542 
543 
544 //!	Update status string - show actual value
545 const char*
546 SSlider::UpdateText() const
547 {
548 	snprintf(fStatusLabel, sizeof(fStatusLabel), "%" B_PRId32, Value());
549 	return fStatusLabel;
550 }
551 
552 
553 //	#pragma mark -
554 
555 
556 TranslatorReadView::TranslatorReadView(const char* name,
557 	TranslatorSettings* settings)
558 	:
559 	BView(name, 0, new BGroupLayout(B_VERTICAL)),
560 	fSettings(settings)
561 {
562 	fGrayAsRGB32 = new BCheckBox("grayasrgb32",
563 		B_TRANSLATE("Read greyscale images as RGB32"),
564 		new BMessage(VIEW_MSG_SET_GRAYASRGB32));
565 	if (fSettings->SetGetBool(JP2_SET_GRAY8_AS_B_RGB32))
566 		fGrayAsRGB32->SetValue(B_CONTROL_ON);
567 
568 	float padding = 10.0f;
569 	BLayoutBuilder::Group<>(this, B_VERTICAL)
570 		.SetInsets(padding)
571 		.Add(fGrayAsRGB32)
572 		.AddGlue();
573 }
574 
575 
576 TranslatorReadView::~TranslatorReadView()
577 {
578 	fSettings->Release();
579 }
580 
581 
582 void
583 TranslatorReadView::AttachedToWindow()
584 {
585 	fGrayAsRGB32->SetTarget(this);
586 }
587 
588 
589 void
590 TranslatorReadView::MessageReceived(BMessage* message)
591 {
592 	switch (message->what) {
593 		case VIEW_MSG_SET_GRAYASRGB32:
594 		{
595 			int32 value;
596 			if (message->FindInt32("be:value", &value) == B_OK) {
597 				bool boolValue = value;
598 				fSettings->SetGetBool(JP2_SET_GRAY8_AS_B_RGB32, &boolValue);
599 				fSettings->SaveSettings();
600 			}
601 			break;
602 		}
603 		default:
604 			BView::MessageReceived(message);
605 			break;
606 	}
607 }
608 
609 
610 //	#pragma mark - TranslatorWriteView
611 
612 
613 TranslatorWriteView::TranslatorWriteView(const char* name,
614 	TranslatorSettings* settings)
615 	:
616 	BView(name, 0, new BGroupLayout(B_VERTICAL)),
617 	fSettings(settings)
618 {
619 	fQualitySlider = new SSlider("quality", B_TRANSLATE("Output quality"),
620 		new BMessage(VIEW_MSG_SET_QUALITY), 0, 100);
621 	fQualitySlider->SetHashMarks(B_HASH_MARKS_BOTTOM);
622 	fQualitySlider->SetHashMarkCount(10);
623 	fQualitySlider->SetLimitLabels(B_TRANSLATE("Low"), B_TRANSLATE("High"));
624 	fQualitySlider->SetValue(fSettings->SetGetInt32(JP2_SET_QUALITY));
625 
626 	fGrayAsRGB24 = new BCheckBox("gray1asrgb24",
627 		B_TRANSLATE("Write black-and-white images as RGB24"),
628 		new BMessage(VIEW_MSG_SET_GRAY1ASRGB24));
629 	if (fSettings->SetGetBool(JP2_SET_GRAY1_AS_B_RGB24))
630 		fGrayAsRGB24->SetValue(B_CONTROL_ON);
631 
632 	fCodeStreamOnly = new BCheckBox("codestreamonly",
633 		B_TRANSLATE("Output only codestream (.jpc)"),
634 		new BMessage(VIEW_MSG_SET_JPC));
635 	if (fSettings->SetGetBool(JP2_SET_JPC))
636 		fCodeStreamOnly->SetValue(B_CONTROL_ON);
637 
638 	float padding = 10.0f;
639 	BLayoutBuilder::Group<>(this, B_VERTICAL, padding)
640 		.SetInsets(padding)
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[16];
716 	sprintf(versionString, "v%d.%d.%d",
717 		static_cast<int>(sTranslatorVersion >> 8),
718 		static_cast<int>((sTranslatorVersion >> 4) & 0xf),
719 		static_cast<int>(sTranslatorVersion & 0xf));
720 
721 	BStringView* version = new BStringView("Version", versionString);
722 	version->SetExplicitAlignment(labelAlignment);
723 
724 	BTextView* infoView = new BTextView("info");
725 	infoView->SetText(sTranslatorInfo);
726 	infoView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
727 	infoView->MakeEditable(false);
728 
729 	float padding = 10.0f;
730 	BLayoutBuilder::Group<>(this, B_VERTICAL, padding)
731 		.SetInsets(padding)
732 		.AddGroup(B_HORIZONTAL, padding)
733 			.Add(title)
734 			.Add(version)
735 			.AddGlue()
736 		.End()
737 		.Add(infoView);
738 }
739 
740 
741 //	#pragma mark -
742 
743 
744 TranslatorView::TranslatorView(const char* name, TranslatorSettings* settings)
745 	:
746 	BTabView(name)
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, jpr_uchar_t* inscanline,
909 		int width) = write_rgba32;
910 
911 	// Default color info
912 	int out_color_space = JAS_IMAGE_CS_RGB;
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_IMAGE_CS_GRAY;
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_IMAGE_CS_GRAY;
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 	jpr_uchar_t *in_scanline = (jpr_uchar_t*) 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, jpr_uchar_t* outscanline,
1106 		int width) = NULL;
1107 
1108 	switch (jas_image_colorspace(image)) {
1109 		case JAS_IMAGE_CS_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_IMAGE_CS_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_IMAGE_CS_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_IMAGE_CS_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 	jpr_uchar_t *out_scanline = (jpr_uchar_t*) 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, jpr_uchar_t* 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