2 * Copyright (c) 2007, Digital Signal Processing Laboratory, Universit� degli studi di Perugia (UPG), Italy
\r
3 * All rights reserved.
\r
5 * Redistribution and use in source and binary forms, with or without
\r
6 * modification, are permitted provided that the following conditions
\r
8 * 1. Redistributions of source code must retain the above copyright
\r
9 * notice, this list of conditions and the following disclaimer.
\r
10 * 2. Redistributions in binary form must reproduce the above copyright
\r
11 * notice, this list of conditions and the following disclaimer in the
\r
12 * documentation and/or other materials provided with the distribution.
\r
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
\r
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
\r
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
\r
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
\r
18 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
\r
19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
\r
20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
\r
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
\r
22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
\r
23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
\r
24 * POSSIBILITY OF SUCH DAMAGE.
\r
26 /////////////////////////////////////////////////////////////////////////////
\r
27 // Name: imagj2k.cpp
\r
28 // Purpose: wxImage JPEG 2000 codestream handler
\r
29 // Author: Giuseppe Baruffa - based on imagjpeg.cpp, Vaclav Slavik
\r
30 // RCS-ID: $Id: imagj2k.cpp,v 0.00 2007/02/08 23:59:00 MW Exp $
\r
31 // Copyright: (c) Giuseppe Baruffa
\r
32 // Licence: wxWindows licence
\r
33 /////////////////////////////////////////////////////////////////////////////
\r
35 // For compilers that support precompilation, includes "wx.h".
\r
36 #include "wx/wxprec.h"
\r
42 #if wxUSE_IMAGE && wxUSE_LIBOPENJPEG
\r
44 #include "imagj2k.h"
\r
49 #include "wx/intl.h"
\r
50 #include "wx/bitmap.h"
\r
51 #include "wx/module.h"
\r
54 #include "wx/filefn.h"
\r
55 #include "wx/wfstream.h"
\r
57 // ----------------------------------------------------------------------------
\r
59 // ----------------------------------------------------------------------------
\r
62 //-----------------------------------------------------------------------------
\r
64 //-----------------------------------------------------------------------------
\r
66 IMPLEMENT_DYNAMIC_CLASS(wxJ2KHandler,wxImageHandler)
\r
70 //------------- JPEG 2000 Data Source Manager
\r
81 #define MAX_MESSAGE_LEN 200
\r
83 /* sample error callback expecting a FILE* client object */
\r
84 void j2k_error_callback(const char *msg, void *client_data) {
\r
85 char m_msg[MAX_MESSAGE_LEN];
\r
86 int message_len = strlen(msg) - 1;
\r
87 if (msg[message_len] != '\n')
\r
88 message_len = MAX_MESSAGE_LEN;
\r
89 sprintf(m_msg, "[ERROR] %.*s", message_len, msg);
\r
91 wxLogMessage(m_msg);
\r
94 /* sample warning callback expecting a FILE* client object */
\r
95 void j2k_warning_callback(const char *msg, void *client_data) {
\r
96 char m_msg[MAX_MESSAGE_LEN];
\r
97 int message_len = strlen(msg) - 1;
\r
98 if (msg[message_len] != '\n')
\r
99 message_len = MAX_MESSAGE_LEN;
\r
100 sprintf(m_msg, "[WARNING] %.*s", message_len, msg);
\r
102 wxLogMessage(m_msg);
\r
105 /* sample debug callback expecting no client object */
\r
106 void j2k_info_callback(const char *msg, void *client_data) {
\r
107 char m_msg[MAX_MESSAGE_LEN];
\r
108 int message_len = strlen(msg) - 1;
\r
109 if (msg[message_len] != '\n')
\r
110 message_len = MAX_MESSAGE_LEN;
\r
111 sprintf(m_msg, "[INFO] %.*s", message_len, msg);
\r
113 wxLogMessage(m_msg);
\r
117 // load the j2k codestream
\r
118 bool wxJ2KHandler::LoadFile(wxImage *image, wxInputStream& stream, bool verbose, int index)
\r
120 opj_dparameters_t parameters; /* decompression parameters */
\r
121 opj_event_mgr_t event_mgr; /* event manager */
\r
122 opj_image_t *opjimage = NULL;
\r
123 unsigned char *src = NULL;
\r
124 unsigned char *ptr;
\r
128 // destroy the image
\r
131 /* handle to a decompressor */
\r
132 opj_dinfo_t* dinfo = NULL;
\r
133 opj_cio_t *cio = NULL;
\r
135 /* configure the event callbacks (not required) */
\r
136 memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
\r
137 event_mgr.error_handler = j2k_error_callback;
\r
138 event_mgr.warning_handler = j2k_warning_callback;
\r
139 event_mgr.info_handler = j2k_info_callback;
\r
141 /* set decoding parameters to default values */
\r
142 opj_set_default_decoder_parameters(¶meters);
\r
144 /* prepare parameters */
\r
145 strncpy(parameters.infile, "", sizeof(parameters.infile)-1);
\r
146 strncpy(parameters.outfile, "", sizeof(parameters.outfile)-1);
\r
147 parameters.decod_format = J2K_CFMT;
\r
148 parameters.cod_format = BMP_DFMT;
\r
149 if (m_reducefactor)
\r
150 parameters.cp_reduce = m_reducefactor;
\r
151 if (m_qualitylayers)
\r
152 parameters.cp_layer = m_qualitylayers;
\r
153 /*if (n_components)
\r
154 parameters. = n_components;*/
\r
158 parameters.jpwl_exp_comps = m_expcomps;
\r
159 parameters.jpwl_max_tiles = m_maxtiles;
\r
160 parameters.jpwl_correct = m_enablejpwl;
\r
161 #endif /* USE_JPWL */
\r
163 /* get a decoder handle */
\r
164 dinfo = opj_create_decompress(CODEC_J2K);
\r
166 /* find length of the stream */
\r
167 stream.SeekI(0, wxFromEnd);
\r
168 file_length = (int) stream.TellI();
\r
171 stream.SeekI(0, wxFromStart);
\r
172 src = (unsigned char *) malloc(file_length);
\r
173 stream.Read(src, file_length);
\r
175 /* catch events using our callbacks and give a local context */
\r
176 opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr);
\r
178 /* setup the decoder decoding parameters using user parameters */
\r
179 opj_setup_decoder(dinfo, ¶meters);
\r
181 /* open a byte stream */
\r
182 cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length);
\r
184 /* decode the stream and fill the image structure */
\r
185 opjimage = opj_decode(dinfo, cio);
\r
188 wxLogError(wxT("J2K: failed to decode image!"));
\r
190 opj_destroy_decompress(dinfo);
\r
191 opj_cio_close(cio);
\r
192 opj_image_destroy(opjimage);
\r
197 /* close the byte stream */
\r
198 opj_cio_close(cio);
\r
200 // check image components
\r
201 if ((opjimage->numcomps != 1) && (opjimage->numcomps != 3)) {
\r
203 wxLogError(wxT("J2K: weird number of components"));
\r
205 opj_destroy_decompress(dinfo);
\r
210 // check image depth (only on the first one, for now)
\r
211 shiftbpp = opjimage->comps[0].prec - 8;
\r
213 // prepare image size
\r
214 image->Create(opjimage->comps[0].w, opjimage->comps[0].h, true );
\r
216 // access image raw data
\r
217 image->SetMask( false );
\r
218 ptr = image->GetData();
\r
220 // RGB color picture
\r
221 if (opjimage->numcomps == 3) {
\r
223 int *r = opjimage->comps[0].data;
\r
224 int *g = opjimage->comps[1].data;
\r
225 int *b = opjimage->comps[2].data;
\r
226 if (shiftbpp > 0) {
\r
227 for (row = 0; row < opjimage->comps[0].h; row++) {
\r
228 for (col = 0; col < opjimage->comps[0].w; col++) {
\r
230 *(ptr++) = (*(r++)) >> shiftbpp;
\r
231 *(ptr++) = (*(g++)) >> shiftbpp;
\r
232 *(ptr++) = (*(b++)) >> shiftbpp;
\r
237 } else if (shiftbpp < 0) {
\r
238 for (row = 0; row < opjimage->comps[0].h; row++) {
\r
239 for (col = 0; col < opjimage->comps[0].w; col++) {
\r
241 *(ptr++) = (*(r++)) << -shiftbpp;
\r
242 *(ptr++) = (*(g++)) << -shiftbpp;
\r
243 *(ptr++) = (*(b++)) << -shiftbpp;
\r
249 for (row = 0; row < opjimage->comps[0].h; row++) {
\r
250 for (col = 0; col < opjimage->comps[0].w; col++) {
\r
262 if (opjimage->numcomps == 1) {
\r
264 int *y = opjimage->comps[0].data;
\r
265 if (shiftbpp > 0) {
\r
266 for (row = 0; row < opjimage->comps[0].h; row++) {
\r
267 for (col = 0; col < opjimage->comps[0].w; col++) {
\r
269 *(ptr++) = (*(y)) >> shiftbpp;
\r
270 *(ptr++) = (*(y)) >> shiftbpp;
\r
271 *(ptr++) = (*(y++)) >> shiftbpp;
\r
275 } else if (shiftbpp < 0) {
\r
276 for (row = 0; row < opjimage->comps[0].h; row++) {
\r
277 for (col = 0; col < opjimage->comps[0].w; col++) {
\r
279 *(ptr++) = (*(y)) << -shiftbpp;
\r
280 *(ptr++) = (*(y)) << -shiftbpp;
\r
281 *(ptr++) = (*(y++)) << -shiftbpp;
\r
286 for (row = 0; row < opjimage->comps[0].h; row++) {
\r
287 for (col = 0; col < opjimage->comps[0].w; col++) {
\r
299 wxLogMessage(wxT("J2K: image loaded."));
\r
302 /* close openjpeg structs */
\r
303 opj_destroy_decompress(dinfo);
\r
304 opj_image_destroy(opjimage);
\r
314 // save the j2k codestream
\r
315 bool wxJ2KHandler::SaveFile( wxImage *image, wxOutputStream& stream, bool verbose )
\r
317 wxLogError(wxT("J2K: Couldn't save image -> not implemented."));
\r
322 #pragma warning(default:4611)
\r
325 // recognize the 0xFF4F JPEG 2000 SOC marker
\r
326 bool wxJ2KHandler::DoCanRead( wxInputStream& stream )
\r
328 unsigned char hdr[2];
\r
330 if ( !stream.Read(hdr, WXSIZEOF(hdr)) )
\r
333 return hdr[0] == 0xFF && hdr[1] == 0x4F;
\r
336 #endif // wxUSE_STREAMS
\r
338 #endif // wxUSE_LIBOPENJPEG
\r