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