00001 #include <stdio.h>
00002 #include <string.h>
00003 #include <setjmp.h>
00004 extern "C" {
00005 #include <jpeglib.h>
00006 }
00007 #include "Open.h"
00008 #include "SimpleImage.h"
00009
00010
00011 namespace corona {
00012
00013 static const int JPEG_BUFFER_SIZE = 4096;
00014
00015
00016 void JPEG_init_source(j_decompress_ptr cinfo);
00017 boolean JPEG_fill_input_buffer(j_decompress_ptr cinfo);
00018 void JPEG_skip_input_data(j_decompress_ptr cinfo, long num_bytes);
00019 void JPEG_term_source(j_decompress_ptr cinfo);
00020 void JPEG_error_exit(j_common_ptr cinfo);
00021 void JPEG_emit_message(j_common_ptr cinfo, int msg_level);
00022
00023
00024 struct InternalStruct {
00025 struct {
00026 jpeg_error_mgr mgr;
00027 jmp_buf setjmp_buffer;
00028 } error_mgr;
00029
00030 File* file;
00031 byte buffer[JPEG_BUFFER_SIZE];
00032 };
00033
00035
00036 Image* OpenJPEG(File* file) {
00037
00038
00039 InternalStruct is;
00040 is.file = file;
00041
00042
00043 jpeg_source_mgr mgr;
00044 mgr.bytes_in_buffer = 0;
00045 mgr.next_input_byte = NULL;
00046 mgr.init_source = JPEG_init_source;
00047 mgr.fill_input_buffer = JPEG_fill_input_buffer;
00048 mgr.skip_input_data = JPEG_skip_input_data;
00049 mgr.resync_to_restart = jpeg_resync_to_restart;
00050 mgr.term_source = JPEG_term_source;
00051
00052
00053 jpeg_decompress_struct cinfo;
00054 jpeg_create_decompress(&cinfo);
00055 cinfo.client_data = &is;
00056
00057 cinfo.err = jpeg_std_error(&is.error_mgr.mgr);
00058 is.error_mgr.mgr.error_exit = JPEG_error_exit;
00059
00060 SimpleImage* image = 0;
00061
00062 if (setjmp(is.error_mgr.setjmp_buffer)) {
00063 delete image;
00064 jpeg_destroy_decompress(&cinfo);
00065 return 0;
00066 }
00067
00068 cinfo.src = &mgr;
00069 jpeg_read_header(&cinfo, TRUE);
00070 jpeg_start_decompress(&cinfo);
00071
00072
00073 if (cinfo.output_components != 1 && cinfo.output_components != 3) {
00074 jpeg_finish_decompress(&cinfo);
00075 jpeg_destroy_decompress(&cinfo);
00076 return 0;
00077 }
00078
00079
00080 int row_stride = cinfo.output_width * cinfo.output_components;
00081 JSAMPARRAY buffer = (*cinfo.mem->alloc_sarray)(
00082 (j_common_ptr)&cinfo,
00083 JPOOL_IMAGE,
00084 row_stride,
00085 1);
00086
00087
00088 unsigned width = cinfo.output_width;
00089 unsigned height = cinfo.output_height;
00090 byte* pixels = new byte[width * height * 3];
00091 memset(pixels, 0, width * height * 3);
00092
00093
00094
00095 image = new SimpleImage(width, height, PF_R8G8B8, pixels);
00096
00097
00098 bool finished = true;
00099 while (cinfo.output_scanline < height) {
00100 int num_rows = jpeg_read_scanlines(&cinfo, buffer, 1);
00101 if (num_rows == 0) {
00102 finished = false;
00103 break;
00104 }
00105
00106
00107 if (cinfo.output_components == 1) {
00108 byte* in = (byte*)(*buffer);
00109 for (unsigned i = 0; i < width * num_rows; ++i) {
00110 *pixels++ = *in;
00111 *pixels++ = *in;
00112 *pixels++ = *in;
00113 ++in;
00114 }
00115 } else if (cinfo.output_components == 3) {
00116 memcpy(pixels, (*buffer), num_rows * width * 3);
00117 pixels += num_rows * width * 3;
00118 }
00119 }
00120
00121
00122 if (finished) {
00123 jpeg_finish_decompress(&cinfo);
00124 }
00125 jpeg_destroy_decompress(&cinfo);
00126
00127 return image;
00128 }
00129
00131
00132 void JPEG_init_source(j_decompress_ptr cinfo) {
00133
00134 }
00135
00137
00138 boolean JPEG_fill_input_buffer(j_decompress_ptr cinfo) {
00139
00140
00141 InternalStruct* is = (InternalStruct*)(cinfo->client_data);
00142
00143 int nbytes = is->file->read(is->buffer, JPEG_BUFFER_SIZE);
00144 if (nbytes <= 0) {
00145
00146 is->buffer[0] = (JOCTET)0xFF;
00147 is->buffer[1] = (JOCTET)JPEG_EOI;
00148 nbytes = 2;
00149 }
00150
00151 cinfo->src->bytes_in_buffer = nbytes;
00152 cinfo->src->next_input_byte = is->buffer;
00153 return TRUE;
00154 }
00155
00157
00158 void JPEG_skip_input_data(j_decompress_ptr cinfo, long num_bytes) {
00159
00160 if (num_bytes > 0) {
00161 while (num_bytes > (long)cinfo->src->bytes_in_buffer) {
00162 num_bytes -= (long)cinfo->src->bytes_in_buffer;
00163 JPEG_fill_input_buffer(cinfo);
00164 }
00165 cinfo->src->next_input_byte += (size_t)num_bytes;
00166 cinfo->src->bytes_in_buffer -= (size_t)num_bytes;
00167 }
00168 }
00169
00171
00172 void JPEG_term_source(j_decompress_ptr cinfo) {
00173
00174 }
00175
00177
00178 void JPEG_error_exit(j_common_ptr cinfo) {
00179 InternalStruct* is = (InternalStruct*)(cinfo->client_data);
00180 longjmp(is->error_mgr.setjmp_buffer, 1);
00181 }
00182
00184
00185 void JPEG_emit_message(j_common_ptr , int ) {
00186
00187 }
00188
00190
00191 }