2003/04/10 08:21:38
[org.ibex.core.git] / src / org / xwt / plat / GCJ.cc
1 extern "C" {
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include <setjmp.h>
5 #include "jpeglib.h"
6 }
7 #include <gcj/cni.h>
8 #include <gcj/array.h>
9
10 #include <java/lang/RuntimeException.h>
11 #include <java/io/InputStream.h>
12 #include <org/xwt/plat/GCJ.h>
13 #include <org/xwt/plat/GCJ$JPEG.h>
14
15 #define INPUT_BUF_SIZE (1024 * 16)
16
17 typedef struct {
18     struct jpeg_source_mgr pub;
19     org::xwt::plat::GCJ$JPEG* myself;
20 } source_manager;
21
22 void jpeg_error_handler (j_common_ptr cinfo) {
23   jstring message = JvNewStringLatin1(cinfo->err->jpeg_message_table[cinfo->err->msg_code]);
24   throw new java::lang::RuntimeException(message);
25 }
26
27 void term_source (j_decompress_ptr cinfo) { }
28 void init_source (j_decompress_ptr cinfo) { }
29
30 boolean fill_input_buffer (j_decompress_ptr cinfo) {
31   source_manager* src = (source_manager*)cinfo->src;
32   jint nbytes = src->myself->is->read(src->myself->buffer, 0, INPUT_BUF_SIZE);
33   if (nbytes <= 0) {
34     // the JPEG library specifically suggests padding the end with EOF markers
35     elements(src->myself->buffer)[0] = (jbyte)0xFF;
36     elements(src->myself->buffer)[1] = (jbyte)JPEG_EOI;
37     nbytes = 2;
38   }
39   src->pub.next_input_byte = (JOCTET*)elements(src->myself->buffer);
40   src->pub.bytes_in_buffer = nbytes;
41   return 1;
42 }
43
44 void skip_input_data (j_decompress_ptr cinfo, long num_bytes) {
45   source_manager* src = (source_manager*)cinfo->src;
46   if (num_bytes > 0) {
47     while (num_bytes > (long) src->pub.bytes_in_buffer) {
48       num_bytes -= (long) src->pub.bytes_in_buffer;
49       (void) fill_input_buffer(cinfo);
50     }
51     src->pub.next_input_byte += (size_t) num_bytes;
52     src->pub.bytes_in_buffer -= (size_t) num_bytes;
53   }
54 }
55
56 void org::xwt::plat::GCJ$JPEG::nativeDecompress() {
57     struct jpeg_decompress_struct cinfo;
58   
59     // set up our error handler
60     struct jpeg_error_mgr error_handler;
61     cinfo.err = jpeg_std_error(&error_handler);
62     error_handler.error_exit = &jpeg_error_handler;
63     
64     jpeg_create_decompress(&cinfo);
65     try {
66         source_manager src;
67         buffer = JvNewByteArray(INPUT_BUF_SIZE);
68         src.pub.init_source = init_source;
69         src.pub.fill_input_buffer = fill_input_buffer;
70         src.pub.skip_input_data = skip_input_data;
71         src.pub.resync_to_restart = jpeg_resync_to_restart;
72         src.pub.term_source = term_source;
73         src.myself = this;
74         src.pub.next_input_byte = (JOCTET*)elements(buffer);
75         src.pub.bytes_in_buffer = 0;
76         cinfo.src = (jpeg_source_mgr*)&src;
77
78         jpeg_read_header(&cinfo, 1);
79         jpeg_start_decompress(&cinfo);
80         width = cinfo.output_width;
81         height = cinfo.output_height;
82         data = JvNewIntArray(width * height);
83
84         while (cinfo.output_scanline < cinfo.output_height) {
85           JSAMPLE* dest = (JSAMPLE*)(elements(data) + cinfo.output_scanline * width);
86           jpeg_read_scanlines(&cinfo, &dest, 1);
87         }
88         
89         jpeg_finish_decompress(&cinfo);
90
91         // fill in the alpha components
92         for(int i=0; i<data->length; i++)
93           elements(data)[i] |= (jint)0xff000000;
94
95     } catch (java::lang::Throwable* t) {
96         jpeg_destroy_decompress(&cinfo);
97         throw t;
98     }
99     jpeg_destroy_decompress(&cinfo);
100 }
101
102