xref: /haiku/src/add-ons/translators/jpeg2000/JPEG2000Translator.cpp (revision 893988af824e65e49e55f517b157db8386e8002b)
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 
37 #include <TabView.h>
38 
39 
40 // Set these accordingly
41 #define JP2_ACRONYM "JP2"
42 #define JP2_FORMAT 'JP2 '
43 #define JP2_MIME_STRING "image/jp2"
44 #define JP2_DESCRIPTION "JPEG2000 image"
45 
46 // The translation kit's native file type
47 #define B_TRANSLATOR_BITMAP_MIME_STRING "image/x-be-bitmap"
48 #define B_TRANSLATOR_BITMAP_DESCRIPTION "Be Bitmap Format (JPEG2000Translator)"
49 
50 // Translation Kit required globals
51 char translatorName[] = "JPEG2000 Images";
52 char translatorInfo[] = "©2002-2003, Shard\n"
53 	"©2005-2006, Haiku\n"
54 	"\n"
55 	"Based on JasPer library:\n"
56 	"© 1999-2000, Image Power, Inc. and\n"
57 	"the University of British Columbia, Canada.\n"
58 	"© 2001-2003 Michael David Adams.\n"
59 	"          http://www.ece.uvic.ca/~mdadams/jasper/\n"
60 	"\n"
61 	"ImageMagick's jp2 codec was used as \"tutorial\".\n"
62 	"          http://www.imagemagick.org/\n";
63 
64 int32 translatorVersion = 0x100;
65 
66 // Define the formats we know how to read
67 translation_format inputFormats[] = {
68 	{ JP2_FORMAT, B_TRANSLATOR_BITMAP, 0.5, 0.5,
69 		JP2_MIME_STRING, JP2_DESCRIPTION },
70 	{ B_TRANSLATOR_BITMAP, B_TRANSLATOR_BITMAP, 0.5, 0.5,
71 		B_TRANSLATOR_BITMAP_MIME_STRING, B_TRANSLATOR_BITMAP_DESCRIPTION },
72 	{},
73 };
74 
75 // Define the formats we know how to write
76 translation_format outputFormats[] = {
77 	{ JP2_FORMAT, B_TRANSLATOR_BITMAP, 0.5, 0.5,
78 		JP2_MIME_STRING, JP2_DESCRIPTION },
79 	{ B_TRANSLATOR_BITMAP, B_TRANSLATOR_BITMAP, 0.5, 0.5,
80 		B_TRANSLATOR_BITMAP_MIME_STRING, B_TRANSLATOR_BITMAP_DESCRIPTION },
81 	{},
82 };
83 
84 
85 //!	Make settings to defaults
86 void
87 LoadDefaultSettings(jpeg_settings *settings)
88 {
89 	settings->Quality = 25;
90 	settings->JPC = false;
91 	settings->B_GRAY1_as_B_RGB24 = false;
92 	settings->B_GRAY8_as_B_RGB32 = true;
93 }
94 
95 
96 //!	Save settings to config file
97 void
98 SaveSettings(jpeg_settings *settings)
99 {
100 	// Make path to settings file
101 	BPath path;
102 	if (find_directory(B_USER_SETTINGS_DIRECTORY, &path, true) != B_OK)
103 		return;
104 
105 	path.Append(SETTINGS_FILE);
106 
107 	// Open settings file (create it if there's no file) and write settings
108 	FILE *file = NULL;
109 	if ((file = fopen(path.Path(), "wb+"))) {
110 		fwrite(settings, sizeof(jpeg_settings), 1, file);
111 		fclose(file);
112 	}
113 }
114 
115 
116 /*!
117 	Load settings from config file
118 	If can't find it make them default and try to save
119 */
120 void
121 LoadSettings(jpeg_settings *settings)
122 {
123 	// Make path to settings file
124 	BPath path;
125 	if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK) {
126 		LoadDefaultSettings(settings);
127 		return;
128 	}
129 
130 	path.Append(SETTINGS_FILE);
131 
132 	// Open settings file (create it if there's no file) and write settings
133 	FILE *file = NULL;
134 	if ((file = fopen(path.Path(), "rb"))) {
135 		if (!fread(settings, sizeof(jpeg_settings), 1, file)) {
136 			// settings struct has changed size
137 			// Load default settings, and Save them
138 			fclose(file);
139 			LoadDefaultSettings(settings);
140 			SaveSettings(settings);
141 		} else
142 			fclose(file);
143 	} else if ((file = fopen(path.Path(), "wb+"))) {
144 		LoadDefaultSettings(settings);
145 		fwrite(settings, sizeof(jpeg_settings), 1, file);
146 		fclose(file);
147 	}
148 }
149 
150 
151 //	#pragma mark - conversion routines
152 
153 
154 //!	Make RGB32 scanline from *pixels[3]
155 inline void
156 read_rgb24_to_rgb32(jas_matrix_t **pixels, jpr_uchar_t *scanline, int width)
157 {
158 	int32 index = 0;
159 	int32 x = 0;
160 	while (x < width) {
161 		scanline[index++] = (jpr_uchar_t)jas_matrix_getv(pixels[2], x);
162 		scanline[index++] = (jpr_uchar_t)jas_matrix_getv(pixels[1], x);
163 		scanline[index++] = (jpr_uchar_t)jas_matrix_getv(pixels[0], x);
164 		scanline[index++] = 255;
165 		x++;
166 	}
167 }
168 
169 
170 //!	Make gray scanline from *pixels[1]
171 inline void
172 read_gray_to_rgb32(jas_matrix_t **pixels, jpr_uchar_t *scanline, int width)
173 {
174 	int32 index = 0;
175 	int32 x = 0;
176 	jpr_uchar_t color = 0;
177 	while (x < width) {
178 		color = (jpr_uchar_t)jas_matrix_getv(pixels[0], x++);
179 		scanline[index++] = color;
180 		scanline[index++] = color;
181 		scanline[index++] = color;
182 		scanline[index++] = 255;
183 	}
184 }
185 
186 
187 /*!
188 	Make RGBA32 scanline from *pixels[4]
189 	(just read data to scanline)
190 */
191 inline void
192 read_rgba32(jas_matrix_t **pixels, jpr_uchar_t *scanline, int width)
193 {
194 	int32 index = 0;
195 	int32 x = 0;
196 	while (x < width) {
197 		scanline[index++] = (jpr_uchar_t)jas_matrix_getv(pixels[2], x);
198 		scanline[index++] = (jpr_uchar_t)jas_matrix_getv(pixels[1], x);
199 		scanline[index++] = (jpr_uchar_t)jas_matrix_getv(pixels[0], x);
200 		scanline[index++] = (jpr_uchar_t)jas_matrix_getv(pixels[3], x);
201 		x++;
202 	}
203 }
204 
205 
206 /*!
207 	Make gray scanline from *pixels[1]
208 	(just read data to scanline)
209 */
210 inline void
211 read_gray(jas_matrix_t **pixels, jpr_uchar_t *scanline, int width)
212 {
213 	int32 x = 0;
214 	while (x < width) {
215 		scanline[x] = (jpr_uchar_t)jas_matrix_getv(pixels[0], x);
216 		x++;
217 	}
218 }
219 
220 
221 //!	Make *pixels[1] from gray1 scanline
222 inline void
223 write_gray1_to_gray(jas_matrix_t **pixels, jpr_uchar_t *scanline, int width)
224 {
225 	int32 x = 0;
226 	int32 index = 0;
227 	while (x < (width/8)) {
228 		unsigned char c = scanline[x++];
229 		for (int b = 128; b; b = b >> 1) {
230 			if (c & b)
231 				jas_matrix_setv(pixels[0], index++, 0);
232 			else
233 				jas_matrix_setv(pixels[0], index++, 255);
234 		}
235 	}
236 }
237 
238 
239 //!	Make *pixels[3] from gray1 scanline
240 inline void
241 write_gray1_to_rgb24(jas_matrix_t **pixels, jpr_uchar_t *scanline, int width)
242 {
243 	int32 x = 0;
244 	int32 index = 0;
245 	while (x < (width/8)) {
246 		unsigned char c = scanline[x++];
247 		for (int b = 128; b; b = b >> 1) {
248 			if (c & b) {
249 				jas_matrix_setv(pixels[0], index, 0);
250 				jas_matrix_setv(pixels[1], index, 0);
251 				jas_matrix_setv(pixels[2], index, 0);
252 			} else {
253 				jas_matrix_setv(pixels[0], index, 255);
254 				jas_matrix_setv(pixels[1], index, 255);
255 				jas_matrix_setv(pixels[2], index, 255);
256 			}
257 			index++;
258 		}
259 	}
260 }
261 
262 
263 //!	Make *pixels[3] from cmap8 scanline
264 inline void
265 write_cmap8_to_rgb24(jas_matrix_t **pixels, jpr_uchar_t *scanline, int width)
266 {
267 	const color_map *map = system_colors();
268 	int32 x = 0;
269 	while (x < width) {
270 		rgb_color color = map->color_list[scanline[x]];
271 
272 		jas_matrix_setv(pixels[0], x, color.red);
273 		jas_matrix_setv(pixels[1], x, color.green);
274 		jas_matrix_setv(pixels[2], x, color.blue);
275 		x++;
276 	}
277 }
278 
279 
280 /*!
281 	Make *pixels[1] from gray scanline
282 	(just write data to pixels)
283 */
284 inline void
285 write_gray(jas_matrix_t **pixels, jpr_uchar_t *scanline, int width)
286 {
287 	int32 x = 0;
288 	while (x < width) {
289 		jas_matrix_setv(pixels[0], x, scanline[x]);
290 		x++;
291 	}
292 }
293 
294 
295 /*!
296 	Make *pixels[3] from RGB15/RGBA15 scanline
297 	(just write data to pixels)
298 */
299 inline void
300 write_rgb15_to_rgb24(jas_matrix_t **pixels, jpr_uchar_t *scanline, int width)
301 {
302 	int32 x = 0;
303 	int32 index = 0;
304 	int16 in_pixel;
305 	while (x < width) {
306 		in_pixel = scanline[index] | (scanline[index+1] << 8);
307 		index += 2;
308 
309 		jas_matrix_setv(pixels[0], x, (char)(((in_pixel & 0x7c00)) >> 7) | (((in_pixel & 0x7c00)) >> 12));
310 		jas_matrix_setv(pixels[1], x, (char)(((in_pixel & 0x3e0)) >> 2) | (((in_pixel & 0x3e0)) >> 7));
311 		jas_matrix_setv(pixels[2], x, (char)(((in_pixel & 0x1f)) << 3) | (((in_pixel & 0x1f)) >> 2));
312 		x++;
313 	}
314 }
315 
316 
317 /*!
318 	Make *pixels[3] from RGB15/RGBA15 bigendian scanline
319 	(just write data to pixels)
320 */
321 inline void
322 write_rgb15b_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 & 0x7c00)) >> 7) | (((in_pixel & 0x7c00)) >> 12));
332 		jas_matrix_setv(pixels[1], x, (char)(((in_pixel & 0x3e0)) >> 2) | (((in_pixel & 0x3e0)) >> 7));
333 		jas_matrix_setv(pixels[2], x, (char)(((in_pixel & 0x1f)) << 3) | (((in_pixel & 0x1f)) >> 2));
334 		x++;
335 	}
336 }
337 
338 
339 /*!
340 	Make *pixels[3] from RGB16/RGBA16 scanline
341 	(just write data to pixels)
342 */
343 inline void
344 write_rgb16_to_rgb24(jas_matrix_t **pixels, jpr_uchar_t *scanline, int width)
345 {
346 	int32 x = 0;
347 	int32 index = 0;
348 	int16 in_pixel;
349 	while (x < width) {
350 		in_pixel = scanline[index] | (scanline[index+1] << 8);
351 		index += 2;
352 
353 		jas_matrix_setv(pixels[0], x, (char)(((in_pixel & 0xf800)) >> 8) | (((in_pixel & 0x7c00)) >> 12));
354 		jas_matrix_setv(pixels[1], x, (char)(((in_pixel & 0x7e0)) >> 3) | (((in_pixel & 0x7e0)) >> 9));
355 		jas_matrix_setv(pixels[2], x, (char)(((in_pixel & 0x1f)) << 3) | (((in_pixel & 0x1f)) >> 2));
356 		x++;
357 	}
358 }
359 
360 
361 /*!
362 	Make *pixels[3] from RGB16/RGBA16 bigendian scanline
363 	(just write data to pixels)
364 */
365 inline void
366 write_rgb16b_to_rgb24(jas_matrix_t **pixels, jpr_uchar_t *scanline, int width)
367 {
368 	int32 x = 0;
369 	int32 index = 0;
370 	int16 in_pixel;
371 	while (x < width) {
372 		in_pixel = scanline[index+1] | (scanline[index] << 8);
373 		index += 2;
374 
375 		jas_matrix_setv(pixels[0], x, (char)(((in_pixel & 0xf800)) >> 8) | (((in_pixel & 0xf800)) >> 13));
376 		jas_matrix_setv(pixels[1], x, (char)(((in_pixel & 0x7e0)) >> 3) | (((in_pixel & 0x7e0)) >> 9));
377 		jas_matrix_setv(pixels[2], x, (char)(((in_pixel & 0x1f)) << 3) | (((in_pixel & 0x1f)) >> 2));
378 		x++;
379 	}
380 }
381 
382 
383 /*!
384 	Make *pixels[3] from RGB24 scanline
385 	(just write data to pixels)
386 */
387 inline void
388 write_rgb24(jas_matrix_t **pixels, jpr_uchar_t *scanline, int width)
389 {
390 	int32 index = 0;
391 	int32 x = 0;
392 	while (x < width) {
393 		jas_matrix_setv(pixels[2], x, scanline[index++]);
394 		jas_matrix_setv(pixels[1], x, scanline[index++]);
395 		jas_matrix_setv(pixels[0], x, scanline[index++]);
396 		x++;
397 	}
398 }
399 
400 
401 /*!
402 	Make *pixels[3] from RGB24 bigendian scanline
403 	(just write data to pixels)
404 */
405 inline void
406 write_rgb24b(jas_matrix_t **pixels, jpr_uchar_t *scanline, int width)
407 {
408 	int32 index = 0;
409 	int32 x = 0;
410 	while (x < width) {
411 		jas_matrix_setv(pixels[0], x, scanline[index++]);
412 		jas_matrix_setv(pixels[1], x, scanline[index++]);
413 		jas_matrix_setv(pixels[2], x, scanline[index++]);
414 		x++;
415 	}
416 }
417 
418 
419 /*!
420 	Make *pixels[3] from RGB32 scanline
421 	(just write data to pixels)
422 */
423 inline void
424 write_rgb32_to_rgb24(jas_matrix_t **pixels, jpr_uchar_t *scanline, int width)
425 {
426 	int32 index = 0;
427 	int32 x = 0;
428 	while (x < width) {
429 		jas_matrix_setv(pixels[2], x, scanline[index++]);
430 		jas_matrix_setv(pixels[1], x, scanline[index++]);
431 		jas_matrix_setv(pixels[0], x, scanline[index++]);
432 		index++;
433 		x++;
434 	}
435 }
436 
437 
438 /*!
439 	Make *pixels[3] from RGB32 bigendian scanline
440 	(just write data to pixels)
441 */
442 inline void
443 write_rgb32b_to_rgb24(jas_matrix_t **pixels, jpr_uchar_t *scanline, int width)
444 {
445 	int32 index = 0;
446 	int32 x = 0;
447 	while (x < width) {
448 		index++;
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 		x++;
453 	}
454 }
455 
456 
457 /*!
458 	Make *pixels[4] from RGBA32 scanline
459 	(just write data to pixels)
460 	!!! UNTESTED !!!
461 */
462 inline void
463 write_rgba32(jas_matrix_t **pixels, jpr_uchar_t *scanline, int width)
464 {
465 	int32 index = 0;
466 	int32 x = 0;
467 	while (x < width) {
468 		jas_matrix_setv(pixels[3], x, scanline[index++]);
469 		jas_matrix_setv(pixels[2], x, scanline[index++]);
470 		jas_matrix_setv(pixels[1], x, scanline[index++]);
471 		jas_matrix_setv(pixels[0], x, scanline[index++]);
472 		x++;
473 	}
474 }
475 
476 
477 /*!
478 	Make *pixels[4] from RGBA32 bigendian scanline
479 	(just write data to pixels)
480 	!!! UNTESTED !!!
481 */
482 inline void
483 write_rgba32b(jas_matrix_t **pixels, jpr_uchar_t *scanline, int width)
484 {
485 	int32 index = 0;
486 	int32 x = 0;
487 	while (x < width)
488 	{
489 		jas_matrix_setv(pixels[0], x, scanline[index++]);
490 		jas_matrix_setv(pixels[1], x, scanline[index++]);
491 		jas_matrix_setv(pixels[2], x, scanline[index++]);
492 		jas_matrix_setv(pixels[3], x, scanline[index++]);
493 		x++;
494 	}
495 }
496 
497 
498 //	#pragma mark -	jasper I/O
499 
500 
501 static int
502 Read(jas_stream_obj_t *object, char *buffer, const int length)
503 {
504 	return (*(BPositionIO**)object)->Read(buffer, length);
505 }
506 
507 
508 static int
509 Write(jas_stream_obj_t *object, char *buffer, const int length)
510 {
511 	return (*(BPositionIO**)object)->Write(buffer, length);
512 }
513 
514 
515 static long
516 Seek(jas_stream_obj_t *object, long offset, int origin)
517 {
518 	return (*(BPositionIO**)object)->Seek(offset, origin);
519 }
520 
521 
522 static int
523 Close(jas_stream_obj_t *object)
524 {
525 	return 0;
526 }
527 
528 
529 static jas_stream_ops_t positionIOops = {
530 	Read,
531 	Write,
532 	Seek,
533 	Close
534 };
535 
536 
537 static jas_stream_t *
538 jas_stream_positionIOopen(BPositionIO *positionIO)
539 {
540 	jas_stream_t *stream;
541 
542 	stream = (jas_stream_t *)malloc(sizeof(jas_stream_t));
543 	if (stream == (jas_stream_t *)NULL)
544 		return (jas_stream_t *)NULL;
545 
546 	memset(stream, 0, sizeof(jas_stream_t));
547 	stream->rwlimit_ = -1;
548 	stream->obj_=(jas_stream_obj_t *)malloc(sizeof(BPositionIO*));
549 	if (stream->obj_ == (jas_stream_obj_t *)NULL) {
550 		free(stream);
551 		return (jas_stream_t *)NULL;
552 	}
553 
554 	*((BPositionIO**)stream->obj_) = positionIO;
555 	stream->ops_ = (&positionIOops);
556 	stream->openmode_ = JAS_STREAM_READ | JAS_STREAM_WRITE | JAS_STREAM_BINARY;
557 	stream->bufbase_ = stream->tinybuf_;
558 	stream->bufsize_ = 1;
559 	stream->bufstart_ = (&stream->bufbase_[JAS_STREAM_MAXPUTBACK]);
560 	stream->ptr_ = stream->bufstart_;
561 	stream->bufmode_ |= JAS_STREAM_UNBUF & JAS_STREAM_BUFMODEMASK;
562 
563 	return stream;
564 }
565 
566 
567 //	#pragma mark - SView
568 
569 
570 SView::SView(BRect frame, const char *name)
571 	: BView(frame, name, B_FOLLOW_NONE, B_WILL_DRAW)
572 {
573 	SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
574 	SetLowColor(ViewColor());
575 
576 	SetFont(be_plain_font);
577 }
578 
579 
580 void
581 SView::AttachedToWindow()
582 {
583 	BView::AttachedToWindow();
584 	ResizeTo(Parent()->Bounds().Width(), Parent()->Bounds().Height());
585 }
586 
587 
588 //	#pragma mark -
589 
590 
591 SSlider::SSlider(BRect frame, const char *name, const char *label,
592 		BMessage *message, int32 minValue, int32 maxValue, orientation posture,
593 		thumb_style thumbType, uint32 resizingMode, uint32 flags)
594 	: BSlider(frame, name, label, message, minValue, maxValue,
595 		posture, thumbType, resizingMode, flags)
596 {
597 	rgb_color barColor = { 0, 0, 229, 255 };
598 	UseFillColor(true, &barColor);
599 }
600 
601 
602 //!	Update status string - show actual value
603 const char*
604 SSlider::UpdateText() const
605 {
606 	snprintf(fStatusLabel, sizeof(fStatusLabel), "%ld", Value());
607 	return fStatusLabel;
608 }
609 
610 
611 //!	BSlider::ResizeToPreferred + Resize width if it's too small to show label
612 // and status
613 void
614 SSlider::ResizeToPreferred()
615 {
616 	int32 width = (int32)ceil(StringWidth(Label()) + StringWidth("9999"));
617 	if (width < 230)
618 		width = 230;
619 
620 	float w, h;
621 	GetPreferredSize(&w, &h);
622 	ResizeTo(width, h);
623 }
624 
625 
626 //	#pragma mark -
627 
628 
629 TranslatorReadView::TranslatorReadView(BRect frame, const char *name,
630 	jpeg_settings *settings)
631 	: SView(frame, name),
632 	fSettings(settings)
633 {
634 	fGrayAsRGB32 = new BCheckBox(BRect(10, 10, 40, 40), "grayasrgb32",
635 		VIEW_LABEL_GRAYASRGB32, new BMessage(VIEW_MSG_SET_GRAYASRGB32));
636 	fGrayAsRGB32->SetFont(be_plain_font);
637 	if (fSettings->B_GRAY8_as_B_RGB32)
638 		fGrayAsRGB32->SetValue(1);
639 
640 	AddChild(fGrayAsRGB32);
641 	fGrayAsRGB32->ResizeToPreferred();
642 }
643 
644 
645 void
646 TranslatorReadView::AttachedToWindow()
647 {
648 	SView::AttachedToWindow();
649 	fGrayAsRGB32->SetTarget(this);
650 }
651 
652 
653 void
654 TranslatorReadView::MessageReceived(BMessage *message)
655 {
656 	switch (message->what) {
657 		case VIEW_MSG_SET_GRAYASRGB32:
658 		{
659 			int32 value;
660 			if (message->FindInt32("be:value", &value) == B_OK) {
661 				fSettings->B_GRAY8_as_B_RGB32 = value;
662 				SaveSettings(fSettings);
663 			}
664 			break;
665 		}
666 		default:
667 			BView::MessageReceived(message);
668 			break;
669 	}
670 }
671 
672 
673 //	#pragma mark - TranslatorWriteView
674 
675 
676 TranslatorWriteView::TranslatorWriteView(BRect frame, const char *name,
677 	jpeg_settings *settings)
678 	: SView(frame, name),
679 	fSettings(settings)
680 {
681 	BRect rect(10, 10, 10, 40);
682 	fQualitySlider = new SSlider(rect, "quality",
683 		VIEW_LABEL_QUALITY, new BMessage(VIEW_MSG_SET_QUALITY), 0, 100);
684 	fQualitySlider->SetHashMarks(B_HASH_MARKS_BOTTOM);
685 	fQualitySlider->SetHashMarkCount(10);
686 	fQualitySlider->SetLimitLabels("Low", "High");
687 	fQualitySlider->SetFont(be_plain_font);
688 	fQualitySlider->SetValue(fSettings->Quality);
689 	AddChild(fQualitySlider);
690 	fQualitySlider->ResizeToPreferred();
691 
692 	rect.OffsetBy(0, fQualitySlider->Bounds().Height() + 10);
693 
694 	fGrayAsRGB24 = new BCheckBox(rect, "gray1asrgb24",
695 		VIEW_LABEL_GRAY1ASRGB24,
696 		new BMessage(VIEW_MSG_SET_GRAY1ASRGB24));
697 	fGrayAsRGB24->SetFont(be_plain_font);
698 	if (fSettings->B_GRAY1_as_B_RGB24)
699 		fGrayAsRGB24->SetValue(1);
700 
701 	AddChild(fGrayAsRGB24);
702 	fGrayAsRGB24->ResizeToPreferred();
703 
704 	rect.OffsetBy(0, fGrayAsRGB24->Bounds().Height() + 10);
705 
706 	fCodeStreamOnly = new BCheckBox(rect, "codestreamonly",
707 		VIEW_LABEL_JPC, new BMessage(VIEW_MSG_SET_JPC));
708 	fCodeStreamOnly->SetFont(be_plain_font);
709 	if (fSettings->JPC)
710 		fCodeStreamOnly->SetValue(1);
711 
712 	AddChild(fCodeStreamOnly);
713 
714 	fCodeStreamOnly->ResizeToPreferred();
715 }
716 
717 
718 void
719 TranslatorWriteView::AttachedToWindow()
720 {
721 	SView::AttachedToWindow();
722 
723 	fQualitySlider->SetTarget(this);
724 	fGrayAsRGB24->SetTarget(this);
725 	fCodeStreamOnly->SetTarget(this);
726 }
727 
728 
729 void
730 TranslatorWriteView::MessageReceived(BMessage *message)
731 {
732 	switch (message->what) {
733 		case VIEW_MSG_SET_QUALITY:
734 		{
735 			int32 value;
736 			if (message->FindInt32("be:value", &value) == B_OK) {
737 				fSettings->Quality = value;
738 				SaveSettings(fSettings);
739 			}
740 			break;
741 		}
742 		case VIEW_MSG_SET_GRAY1ASRGB24:
743 		{
744 			int32 value;
745 			if (message->FindInt32("be:value", &value) == B_OK) {
746 				fSettings->B_GRAY1_as_B_RGB24 = value;
747 				SaveSettings(fSettings);
748 			}
749 			break;
750 		}
751 		case VIEW_MSG_SET_JPC:
752 		{
753 			int32 value;
754 			if (message->FindInt32("be:value", &value) == B_OK) {
755 				fSettings->JPC = value;
756 				SaveSettings(fSettings);
757 			}
758 			break;
759 		}
760 		default:
761 			BView::MessageReceived(message);
762 			break;
763 	}
764 }
765 
766 
767 //	#pragma mark -
768 
769 
770 TranslatorAboutView::TranslatorAboutView(BRect frame, const char *name)
771 	: SView(frame, name)
772 {
773 	BStringView *title = new BStringView(BRect(10, 0, 10, 0), "Title",
774 		translatorName);
775 	title->SetFont(be_bold_font);
776 
777 	AddChild(title);
778 	title->ResizeToPreferred();
779 
780 	BRect rect = title->Bounds();
781 	float space = title->StringWidth("    ");
782 
783 	char versionString[16];
784 	sprintf(versionString, "v%d.%d.%d", (int)(translatorVersion >> 8),
785 		(int)((translatorVersion >> 4) & 0xf), (int)(translatorVersion & 0xf));
786 
787 	BStringView *version = new BStringView(BRect(rect.right+space, rect.top,
788 		rect.right+space, rect.top), "Version", versionString);
789 	version->SetFont(be_plain_font);
790 	version->SetFontSize(9);
791 	// Make version be in the same line as title
792 	version->ResizeToPreferred();
793 	version->MoveBy(0, rect.bottom-version->Frame().bottom);
794 
795 	AddChild(version);
796 
797 	version->ResizeToPreferred();
798 
799 	BRect stringFrame = title->Frame();
800 	// Now for each line in translatorInfo add a BStringView
801 	char* current = translatorInfo;
802 	int32 index = 1;
803 	while (current != NULL && current[0]) {
804 		char text[128];
805 		char* newLine = strchr(current, '\n');
806 		if (newLine == NULL) {
807 			strlcpy(text, current, sizeof(text));
808 			current = NULL;
809 		} else {
810 			strlcpy(text, current, min_c((int32)sizeof(text),
811 				newLine + 1 - current));
812 			current = newLine + 1;
813 		}
814 
815 		stringFrame.OffsetBy(0, stringFrame.Height() + 2);
816 		BStringView* string = new BStringView(stringFrame, "copyright",
817 			text);
818 		if (index > 3)
819 			string->SetFontSize(9);
820 		AddChild(string);
821 		string->ResizeToPreferred();
822 
823 		index++;
824 	}
825 }
826 
827 
828 //	#pragma mark -
829 
830 
831 TranslatorView::TranslatorView(BRect frame, const char *name)
832 	: BTabView(frame, name)
833 {
834 	// Load settings to global settings struct
835 	LoadSettings(&fSettings);
836 
837 	BRect contentSize = ContainerView()->Bounds();
838 	SView *view = new TranslatorWriteView(contentSize, "Write",
839 		&fSettings);
840 	AddTab(view);
841 	view = new TranslatorReadView(contentSize, "Read", &fSettings);
842 	AddTab(view);
843 	view = new TranslatorAboutView(contentSize, "About");
844 	AddTab(view);
845 
846 	ResizeToPreferred();
847 
848 	// Make TranslatorView resize itself with parent
849 	SetFlags(Flags() | B_FOLLOW_ALL);
850 }
851 
852 
853 TranslatorView::~TranslatorView()
854 {
855 }
856 
857 
858 //	#pragma mark -
859 
860 
861 TranslatorWindow::TranslatorWindow(bool quitOnClose)
862 	: BWindow(BRect(100, 100, 100, 100), "JPEG Settings", B_TITLED_WINDOW,
863 		B_NOT_ZOOMABLE | B_ASYNCHRONOUS_CONTROLS)
864 {
865 	BRect extent(0, 0, 0, 0);
866 	BView *config = NULL;
867 	MakeConfig(NULL, &config, &extent);
868 
869 	AddChild(config);
870 	ResizeTo(extent.Width(), extent.Height());
871 
872 	// Make application quit after this window close
873 	if (quitOnClose)
874 		SetFlags(Flags() | B_QUIT_ON_WINDOW_CLOSE);
875 }
876 
877 
878 //	#pragma mark -
879 
880 
881 //!	Hook to create and return our configuration view
882 status_t
883 MakeConfig(BMessage *ioExtension, BView **outView, BRect *outExtent)
884 {
885 	*outView = new TranslatorView(BRect(0, 0, 300, 250), "TranslatorView");
886 	*outExtent = (*outView)->Frame();
887 	return B_OK;
888 }
889 
890 
891 //!	Determine whether or not we can handle this data
892 status_t
893 Identify(BPositionIO *inSource, const translation_format *inFormat,
894 	BMessage *ioExtension, translator_info *outInfo, uint32 outType)
895 {
896 	if ((outType != 0) && (outType != B_TRANSLATOR_BITMAP)
897 		&& outType != JP2_FORMAT)
898 		return B_NO_TRANSLATOR;
899 
900 	// !!! You might need to make this buffer bigger to test for your
901 	// native format
902 	off_t position = inSource->Position();
903 	uint8 header[sizeof(TranslatorBitmap)];
904 	status_t err = inSource->Read(header, sizeof(TranslatorBitmap));
905 	inSource->Seek(position, SEEK_SET);
906 	if (err < B_OK)
907 		return err;
908 
909 	if (B_BENDIAN_TO_HOST_INT32(((TranslatorBitmap *)header)->magic)
910 		== B_TRANSLATOR_BITMAP) {
911 		outInfo->type = inputFormats[1].type;
912 		outInfo->translator = 0;
913 		outInfo->group = inputFormats[1].group;
914 		outInfo->quality = inputFormats[1].quality;
915 		outInfo->capability = inputFormats[1].capability;
916 		strcpy(outInfo->name, inputFormats[1].name);
917 		strcpy(outInfo->MIME, inputFormats[1].MIME);
918 	} else {
919 		if ((((header[4] << 24) | (header[5] << 16) | (header[6] << 8)
920 			| header[7]) == JP2_BOX_JP) // JP2
921 			|| (header[0] == (JPC_MS_SOC >> 8) && header[1]
922 			== (JPC_MS_SOC & 0xff)))	// JPC
923 		{
924 			outInfo->type = inputFormats[0].type;
925 			outInfo->translator = 0;
926 			outInfo->group = inputFormats[0].group;
927 			outInfo->quality = inputFormats[0].quality;
928 			outInfo->capability = inputFormats[0].capability;
929 			strcpy(outInfo->name, inputFormats[0].name);
930 			strcpy(outInfo->MIME, inputFormats[0].MIME);
931 			return B_OK;
932 		} else
933 			return B_NO_TRANSLATOR;
934 	}
935 
936 	return B_OK;
937 }
938 
939 
940 //!	Arguably the most important method in the add-on
941 status_t
942 Translate(BPositionIO *inSource, const translator_info *inInfo,
943 	BMessage *ioExtension, uint32 outType, BPositionIO *outDestination)
944 {
945 	// If no specific type was requested, convert to the interchange format
946 	if (outType == 0)
947 		outType = B_TRANSLATOR_BITMAP;
948 
949 	// What action to take, based on the findings of Identify()
950 	if (outType == inInfo->type)
951 		return Copy(inSource, outDestination);
952 	if (inInfo->type == B_TRANSLATOR_BITMAP && outType == JP2_FORMAT)
953 		return Compress(inSource, outDestination);
954 	if (inInfo->type == JP2_FORMAT && outType == B_TRANSLATOR_BITMAP)
955 		return Decompress(inSource, outDestination);
956 
957 	return B_NO_TRANSLATOR;
958 }
959 
960 
961 //!	The user has requested the same format for input and output, so just copy
962 status_t
963 Copy(BPositionIO *in, BPositionIO *out)
964 {
965 	int block_size = 65536;
966 	void *buffer = malloc(block_size);
967 	char temp[1024];
968 	if (buffer == NULL) {
969 		buffer = temp;
970 		block_size = 1024;
971 	}
972 	status_t err = B_OK;
973 
974 	// Read until end of file or error
975 	while (1) {
976 		ssize_t to_read = block_size;
977 		err = in->Read(buffer, to_read);
978 		// Explicit check for EOF
979 		if (err == -1) {
980 			if (buffer != temp)
981 				free(buffer);
982 			return B_OK;
983 		}
984 		if (err <= B_OK) break;
985 		to_read = err;
986 		err = out->Write(buffer, to_read);
987 		if (err != to_read) if (err >= 0) err = B_DEVICE_FULL;
988 		if (err < B_OK) break;
989 	}
990 
991 	if (buffer != temp)
992 		free(buffer);
993 	return (err >= 0) ? B_OK : err;
994 }
995 
996 
997 //!	Encode into the native format
998 status_t
999 Compress(BPositionIO *in, BPositionIO *out)
1000 {
1001 	// Load settings
1002 	jpeg_settings settings;
1003 	LoadSettings(&settings);
1004 
1005 	// Read info about bitmap
1006 	TranslatorBitmap header;
1007 	status_t err = in->Read(&header, sizeof(TranslatorBitmap));
1008 	if (err < B_OK)
1009 		return err;
1010 	if (err < (int)sizeof(TranslatorBitmap))
1011 		return B_ERROR;
1012 
1013 	// Grab dimension, color space, and size information from the stream
1014 	BRect bounds;
1015 	bounds.left = B_BENDIAN_TO_HOST_FLOAT(header.bounds.left);
1016 	bounds.top = B_BENDIAN_TO_HOST_FLOAT(header.bounds.top);
1017 	bounds.right = B_BENDIAN_TO_HOST_FLOAT(header.bounds.right);
1018 	bounds.bottom = B_BENDIAN_TO_HOST_FLOAT(header.bounds.bottom);
1019 
1020 	int32 in_row_bytes = B_BENDIAN_TO_HOST_INT32(header.rowBytes);
1021 
1022 	int width = bounds.IntegerWidth() + 1;
1023 	int height = bounds.IntegerHeight() + 1;
1024 
1025 	// Function pointer to write function
1026 	// It MUST point to proper function
1027 	void (*converter)(jas_matrix_t **pixels, jpr_uchar_t *inscanline,
1028 		int width) = write_rgba32;
1029 
1030 	// Default color info
1031 	int out_color_space = JAS_IMAGE_CS_RGB;
1032 	int out_color_components = 3;
1033 
1034 	switch ((color_space)B_BENDIAN_TO_HOST_INT32(header.colors)) {
1035 		case B_GRAY1:
1036 			if (settings.B_GRAY1_as_B_RGB24) {
1037 				converter = write_gray1_to_rgb24;
1038 			} else {
1039 				out_color_components = 1;
1040 				out_color_space = JAS_IMAGE_CS_GRAY;
1041 				converter = write_gray1_to_gray;
1042 			}
1043 			break;
1044 
1045 		case B_CMAP8:
1046 			converter = write_cmap8_to_rgb24;
1047 			break;
1048 
1049 		case B_GRAY8:
1050 			out_color_components = 1;
1051 			out_color_space = JAS_IMAGE_CS_GRAY;
1052 			converter = write_gray;
1053 			break;
1054 
1055 		case B_RGB15:
1056 		case B_RGBA15:
1057 			converter = write_rgb15_to_rgb24;
1058 			break;
1059 
1060 		case B_RGB15_BIG:
1061 		case B_RGBA15_BIG:
1062 			converter = write_rgb15b_to_rgb24;
1063 			break;
1064 
1065 		case B_RGB16:
1066 			converter = write_rgb16_to_rgb24;
1067 			break;
1068 
1069 		case B_RGB16_BIG:
1070 			converter = write_rgb16b_to_rgb24;
1071 			break;
1072 
1073 		case B_RGB24:
1074 			converter = write_rgb24;
1075 			break;
1076 
1077 		case B_RGB24_BIG:
1078 			converter = write_rgb24b;
1079 			break;
1080 
1081 		case B_RGB32:
1082 			converter = write_rgb32_to_rgb24;
1083 			break;
1084 
1085 		case B_RGB32_BIG:
1086 			converter = write_rgb32b_to_rgb24;
1087 			break;
1088 
1089 		case B_RGBA32:
1090 		/*
1091 			// In theory it should be possible to write 4 color components
1092 			// to jp2, so it should be possible to have transparency.
1093 			// Unfortunetly libjasper does not agree with that
1094 			// For now i don't know how to modify it :(
1095 
1096 			out_color_components = 4;
1097 			converter = write_rgba32;
1098 		*/
1099 			converter = write_rgb32_to_rgb24;
1100 			break;
1101 
1102 		case B_RGBA32_BIG:
1103 		/*
1104 			// In theory it should be possible to write 4 color components
1105 			// to jp2, so it should be possible to have transparency.
1106 			// Unfortunetly libjasper does not agree with that
1107 			// For now i don't know how to modify it :(
1108 
1109 			out_color_components = 4;
1110 			converter = write_rgba32b;
1111 		*/
1112 			converter = write_rgb32b_to_rgb24;
1113 			break;
1114 
1115 		default:
1116 			fprintf(stderr, "Unknown color space.\n");
1117 			return B_ERROR;
1118 	}
1119 
1120 	jas_image_t *image;
1121 	jas_stream_t *outs;
1122 	jas_matrix_t *pixels[4];
1123 	jas_image_cmptparm_t component_info[4];
1124 
1125 	if (jas_init())
1126 		return B_ERROR;
1127 
1128 	if (!(outs = jas_stream_positionIOopen(out)))
1129 		return B_ERROR;
1130 
1131 	int32 i = 0;
1132 	for (i = 0; i < (long)out_color_components; i++) {
1133 		(void) memset(component_info + i, 0, sizeof(jas_image_cmptparm_t));
1134 		component_info[i].hstep = 1;
1135 		component_info[i].vstep = 1;
1136 		component_info[i].width = (unsigned int)width;
1137 		component_info[i].height = (unsigned int)height;
1138 		component_info[i].prec = (unsigned int)8;
1139 	}
1140 
1141 	image = jas_image_create((short)out_color_components, component_info,
1142 		out_color_space);
1143 	if (image == (jas_image_t *)NULL)
1144 		return Error(outs, NULL, NULL, 0, NULL, B_ERROR);
1145 
1146 	jpr_uchar_t *in_scanline = (jpr_uchar_t*) malloc(in_row_bytes);
1147 	if (in_scanline == NULL)
1148 		return Error(outs, image, NULL, 0, NULL, B_ERROR);
1149 
1150 	for (i = 0; i < (long)out_color_components; i++) {
1151 		pixels[i] = jas_matrix_create(1, (unsigned int)width);
1152 		if (pixels[i] == (jas_matrix_t *)NULL)
1153 			return Error(outs, image, pixels, i+1, in_scanline, B_ERROR);
1154 	}
1155 
1156 	int32 y = 0;
1157 	for (y = 0; y < (long)height; y++) {
1158 		err = in->Read(in_scanline, in_row_bytes);
1159 		if (err < in_row_bytes) {
1160 			return (err < B_OK) ?
1161 				Error(outs, image, pixels, out_color_components, in_scanline,
1162 					err)
1163 				: Error(outs, image, pixels, out_color_components, in_scanline,
1164 					B_ERROR);
1165 		}
1166 
1167 		converter(pixels, in_scanline, width);
1168 
1169 		for (i = 0; i < (long)out_color_components; i++) {
1170 			(void)jas_image_writecmpt(image, (short)i, 0, (unsigned int)y,
1171 				(unsigned int)width, 1, pixels[i]);
1172 		}
1173 	}
1174 
1175 	char opts[16];
1176 	sprintf(opts, "rate=%1f", (float)settings.Quality / 100.0);
1177 	if (jas_image_encode(image, outs, jas_image_strtofmt(settings.JPC ?
1178 		(char*)"jpc" : (char*)"jp2"), opts)) {
1179 		return Error(outs, image, pixels, out_color_components, in_scanline, err);
1180 	}
1181 
1182 	free(in_scanline);
1183 
1184 	for (i = 0; i < (long)out_color_components; i++)
1185 		jas_matrix_destroy(pixels[i]);
1186 
1187 	jas_stream_close(outs);
1188 	jas_image_destroy(image);
1189 	jas_image_clearfmts();
1190 
1191 	return B_OK;
1192 }
1193 
1194 
1195 //!	Decode the native format
1196 status_t
1197 Decompress(BPositionIO *in, BPositionIO *out)
1198 {
1199 	jpeg_settings settings;
1200 	LoadSettings(&settings);
1201 
1202 	jas_image_t *image;
1203 	jas_stream_t *ins;
1204 	jas_matrix_t *pixels[4];
1205 
1206 	if (jas_init())
1207 		return B_ERROR;
1208 
1209 	if (!(ins = jas_stream_positionIOopen(in)))
1210 		return B_ERROR;
1211 
1212 	if (!(image = jas_image_decode(ins, -1, 0)))
1213 		return Error(ins, NULL, NULL, 0, NULL, B_ERROR);
1214 
1215 	// Default color info
1216 	color_space out_color_space;
1217 	int out_color_components;
1218 	int	in_color_components = jas_image_numcmpts(image);
1219 
1220 	// Function pointer to read function
1221 	// It MUST point to proper function
1222 	void (*converter)(jas_matrix_t **pixels, jpr_uchar_t *outscanline,
1223 		int width) = NULL;
1224 
1225 	switch (jas_image_colorspace(image)) {
1226 		case JAS_IMAGE_CS_RGB:
1227 			out_color_components = 4;
1228 			if (in_color_components == 3) {
1229 				out_color_space = B_RGB32;
1230 				converter = read_rgb24_to_rgb32;
1231 			} else if (in_color_components == 4) {
1232 				out_color_space = B_RGBA32;
1233 				converter = read_rgba32;
1234 			} else {
1235 				fprintf(stderr, "Other than RGB with 3 or 4 color components not implemented.\n");
1236 				return Error(ins, image, NULL, 0, NULL, B_ERROR);
1237 			}
1238 			break;
1239 		case JAS_IMAGE_CS_GRAY:
1240 			if (settings.B_GRAY8_as_B_RGB32) {
1241 				out_color_space = B_RGB32;
1242 				out_color_components = 4;
1243 				converter = read_gray_to_rgb32;
1244 			} else {
1245 				out_color_space = B_GRAY8;
1246 				out_color_components = 1;
1247 				converter = read_gray;
1248 			}
1249 			break;
1250 		case JAS_IMAGE_CS_YCBCR:
1251 			fprintf(stderr, "Color space YCBCR not implemented yet.\n");
1252 			return Error(ins, image, NULL, 0, NULL, B_ERROR);
1253 			break;
1254 		case JAS_IMAGE_CS_UNKNOWN:
1255 		default:
1256 			fprintf(stderr, "Color space unkown. \n");
1257 			return Error(ins, image, NULL, 0, NULL, B_ERROR);
1258 			break;
1259 	}
1260 
1261 	float width = (float)jas_image_width(image);
1262 	float height = (float)jas_image_height(image);
1263 
1264 	// Bytes count in one line of image (scanline)
1265 	int64 out_row_bytes = (int32)width * out_color_components;
1266 		// NOTE: things will go wrong if "out_row_bytes" wouldn't fit into 32 bits
1267 
1268 	// !!! Initialize this bounds rect to the size of your image
1269 	BRect bounds(0, 0, width-1, height-1);
1270 
1271 	// Fill out the B_TRANSLATOR_BITMAP's header
1272 	TranslatorBitmap header;
1273 	header.magic = B_HOST_TO_BENDIAN_INT32(B_TRANSLATOR_BITMAP);
1274 	header.bounds.left = B_HOST_TO_BENDIAN_FLOAT(bounds.left);
1275 	header.bounds.top = B_HOST_TO_BENDIAN_FLOAT(bounds.top);
1276 	header.bounds.right = B_HOST_TO_BENDIAN_FLOAT(bounds.right);
1277 	header.bounds.bottom = B_HOST_TO_BENDIAN_FLOAT(bounds.bottom);
1278 	header.colors = (color_space)B_HOST_TO_BENDIAN_INT32(out_color_space);
1279 	header.rowBytes = B_HOST_TO_BENDIAN_INT32(out_row_bytes);
1280 	header.dataSize = B_HOST_TO_BENDIAN_INT32((int32)(out_row_bytes * height));
1281 
1282 	// Write out the header
1283 	status_t err = out->Write(&header, sizeof(TranslatorBitmap));
1284 	if (err < B_OK)
1285 		return Error(ins, image, NULL, 0, NULL, err);
1286 	if (err < (int)sizeof(TranslatorBitmap))
1287 		return Error(ins, image, NULL, 0, NULL, B_ERROR);
1288 
1289 	jpr_uchar_t *out_scanline = (jpr_uchar_t*) malloc(out_row_bytes);
1290 	if (out_scanline == NULL)
1291 		return Error(ins, image, NULL, 0, NULL, B_ERROR);
1292 
1293 	int32 i = 0;
1294 	for (i = 0; i < (long)in_color_components; i++) {
1295 		pixels[i] = jas_matrix_create(1, (unsigned int)width);
1296 		if (pixels[i] == (jas_matrix_t *)NULL)
1297 			return Error(ins, image, pixels, i+1, out_scanline, B_ERROR);
1298 	}
1299 
1300 	int32 y = 0;
1301 	for (y = 0; y < (long)height; y++) {
1302 		for (i = 0; i < (long)in_color_components; i++) {
1303 			(void)jas_image_readcmpt(image, (short)i, 0, (unsigned int)y,
1304 				(unsigned int)width, 1, pixels[i]);
1305 		}
1306 
1307 		converter(pixels, out_scanline, (int32)width);
1308 
1309 		err = out->Write(out_scanline, out_row_bytes);
1310 		if (err < out_row_bytes) {
1311 			return (err < B_OK) ?
1312 				Error(ins, image, pixels, in_color_components, out_scanline,
1313 					err)
1314 				: Error(ins, image, pixels, in_color_components, out_scanline,
1315 					B_ERROR);
1316 		}
1317 	}
1318 
1319 	free(out_scanline);
1320 
1321 	for (i = 0; i < (long)in_color_components; i++)
1322 		jas_matrix_destroy(pixels[i]);
1323 
1324 	jas_stream_close(ins);
1325 	jas_image_destroy(image);
1326 	jas_image_clearfmts();
1327 
1328 	return B_OK;
1329 }
1330 
1331 
1332 /*!
1333 	Frees jpeg alocated memory
1334 	Returns given error (B_ERROR by default)
1335 */
1336 status_t
1337 Error(jas_stream_t *stream, jas_image_t *image, jas_matrix_t **pixels,
1338 	int32 pixels_count, jpr_uchar_t *scanline, status_t error)
1339 {
1340 	if (pixels) {
1341 		int32 i;
1342 		for (i = 0; i < (long)pixels_count; i++) {
1343 			if (pixels[i] != NULL)
1344 				jas_matrix_destroy(pixels[i]);
1345 		}
1346 	}
1347 	if (stream)
1348 		jas_stream_close(stream);
1349 	if (image)
1350 		jas_image_destroy(image);
1351 
1352 	jas_image_clearfmts();
1353 	free(scanline);
1354 
1355 	return error;
1356 }
1357 
1358 
1359 //	#pragma mark -
1360 
1361 
1362 int
1363 main()
1364 {
1365 	BApplication app("application/x-vnd.Haiku-JPEG2000Translator");
1366 
1367 	TranslatorWindow *window = new TranslatorWindow();
1368 	window->Show();
1369 
1370 	app.Run();
1371 	return 0;
1372 }
1373 
1374