Adapted the JPWL and OPJViewer code to new interface; fixed a samll bug in JPWL which...
[openjpeg.git] / OPJViewer / source / imagj2k.cpp
1 /*\r
2  * Copyright (c) 2007, Digital Signal Processing Laboratory, Universit� degli studi di Perugia (UPG), Italy\r
3  * All rights reserved.\r
4  *\r
5  * Redistribution and use in source and binary forms, with or without\r
6  * modification, are permitted provided that the following conditions\r
7  * are met:\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
13  *\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
25  */\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
34 \r
35 // For compilers that support precompilation, includes "wx.h".\r
36 #include "wx/wxprec.h"\r
37 \r
38 #ifdef __BORLANDC__\r
39     #pragma hdrstop\r
40 #endif\r
41 \r
42 #if wxUSE_IMAGE && wxUSE_LIBOPENJPEG\r
43 \r
44 #include "imagj2k.h"\r
45 \r
46 #ifndef WX_PRECOMP\r
47     #include "wx/log.h"\r
48     #include "wx/app.h"\r
49     #include "wx/intl.h"\r
50     #include "wx/bitmap.h"\r
51     #include "wx/module.h"\r
52 #endif\r
53 \r
54 #include "wx/filefn.h"\r
55 #include "wx/wfstream.h"\r
56 \r
57 // ----------------------------------------------------------------------------\r
58 // types\r
59 // ----------------------------------------------------------------------------\r
60 \r
61 \r
62 //-----------------------------------------------------------------------------\r
63 // wxJ2KHandler\r
64 //-----------------------------------------------------------------------------\r
65 \r
66 IMPLEMENT_DYNAMIC_CLASS(wxJ2KHandler,wxImageHandler)\r
67 \r
68 #if wxUSE_STREAMS\r
69 \r
70 //------------- JPEG 2000 Data Source Manager\r
71 \r
72 #define J2K_CFMT 0\r
73 #define JP2_CFMT 1\r
74 #define JPT_CFMT 2\r
75 #define MJ2_CFMT 3\r
76 #define PXM_DFMT 0\r
77 #define PGX_DFMT 1\r
78 #define BMP_DFMT 2\r
79 #define YUV_DFMT 3\r
80 \r
81 #define MAX_MESSAGE_LEN 200\r
82 \r
83 /* sample error callback expecting a FILE* client object */\r
84 void j2k_error_callback(const char *msg, void *client_data) {\r
85         int message_len = strlen(msg) - 1;\r
86         if (msg[message_len] != '\n')\r
87                 message_len = MAX_MESSAGE_LEN;\r
88 #ifndef __WXGTK__ \r
89     wxMutexGuiEnter();\r
90 #endif /* __WXGTK__ */\r
91         wxLogMessage(wxT("[ERROR] %.*s"), message_len, msg);\r
92 #ifndef __WXGTK__ \r
93     wxMutexGuiLeave();\r
94 #endif /* __WXGTK__ */\r
95 }\r
96 \r
97 /* sample warning callback expecting a FILE* client object */\r
98 void j2k_warning_callback(const char *msg, void *client_data) {\r
99         int message_len = strlen(msg) - 1;\r
100         if (msg[message_len] != '\n')\r
101                 message_len = MAX_MESSAGE_LEN;\r
102 #ifndef __WXGTK__ \r
103     wxMutexGuiEnter();\r
104 #endif /* __WXGTK__ */\r
105         wxLogMessage(wxT("[WARNING] %.*s"), message_len, msg);\r
106 #ifndef __WXGTK__ \r
107     wxMutexGuiLeave();\r
108 #endif /* __WXGTK__ */\r
109 }\r
110 \r
111 /* sample debug callback expecting no client object */\r
112 void j2k_info_callback(const char *msg, void *client_data) {\r
113         int message_len = strlen(msg) - 1;\r
114         if (msg[message_len] != '\n')\r
115                 message_len = MAX_MESSAGE_LEN;\r
116 #ifndef __WXGTK__ \r
117     wxMutexGuiEnter();\r
118 #endif /* __WXGTK__ */\r
119         wxLogMessage(wxT("[INFO] %.*s"), message_len, msg);\r
120 #ifndef __WXGTK__ \r
121     wxMutexGuiLeave();\r
122 #endif /* __WXGTK__ */\r
123 }\r
124 \r
125 // load the j2k codestream\r
126 bool wxJ2KHandler::LoadFile(wxImage *image, wxInputStream& stream, bool verbose, int index)\r
127 {\r
128         opj_dparameters_t parameters;   /* decompression parameters */\r
129         opj_event_mgr_t event_mgr;              /* event manager */\r
130         opj_image_t *opjimage = NULL;\r
131         unsigned char *src = NULL;\r
132     unsigned char *ptr;\r
133         int file_length;\r
134         opj_codestream_info_t cstr_info;  /* Codestream information structure */\r
135 \r
136         // destroy the image\r
137     image->Destroy();\r
138 \r
139         /* handle to a decompressor */\r
140         opj_dinfo_t* dinfo = NULL;      \r
141         opj_cio_t *cio = NULL;\r
142 \r
143 \r
144         /* configure the event callbacks (not required) */\r
145         memset(&event_mgr, 0, sizeof(opj_event_mgr_t));\r
146         event_mgr.error_handler = j2k_error_callback;\r
147         event_mgr.warning_handler = j2k_warning_callback;\r
148         event_mgr.info_handler = j2k_info_callback;\r
149 \r
150         /* set decoding parameters to default values */\r
151         opj_set_default_decoder_parameters(&parameters);\r
152 \r
153         /* prepare parameters */\r
154         strncpy(parameters.infile, "", sizeof(parameters.infile)-1);\r
155         strncpy(parameters.outfile, "", sizeof(parameters.outfile)-1);\r
156         parameters.decod_format = J2K_CFMT;\r
157         parameters.cod_format = BMP_DFMT;\r
158         if (m_reducefactor)\r
159                 parameters.cp_reduce = m_reducefactor;\r
160         if (m_qualitylayers)\r
161                 parameters.cp_layer = m_qualitylayers;\r
162 \r
163         /* JPWL only */\r
164 #ifdef USE_JPWL\r
165         parameters.jpwl_exp_comps = m_expcomps;\r
166         parameters.jpwl_max_tiles = m_maxtiles;\r
167         parameters.jpwl_correct = m_enablejpwl;\r
168 #endif /* USE_JPWL */\r
169 \r
170         /* get a decoder handle */\r
171         dinfo = opj_create_decompress(CODEC_J2K);\r
172 \r
173         /* find length of the stream */\r
174         stream.SeekI(0, wxFromEnd);\r
175         file_length = (int) stream.TellI();\r
176 \r
177         /* get data */\r
178         stream.SeekI(0, wxFromStart);\r
179     src = (unsigned char *) malloc(file_length);\r
180         stream.Read(src, file_length);\r
181 \r
182         /* catch events using our callbacks and give a local context */\r
183         opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr);\r
184 \r
185         /* setup the decoder decoding parameters using user parameters */\r
186         opj_setup_decoder(dinfo, &parameters);\r
187 \r
188         /* open a byte stream */\r
189         cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length);\r
190 \r
191         /* decode the stream and fill the image structure */\r
192         opjimage = opj_decode(dinfo, cio, &cstr_info);\r
193         if (!opjimage) {\r
194 #ifndef __WXGTK__ \r
195                 wxMutexGuiEnter();\r
196 #endif /* __WXGTK__ */\r
197                 wxLogError(wxT("J2K: failed to decode image!"));\r
198 #ifndef __WXGTK__ \r
199                 wxMutexGuiLeave();\r
200 #endif /* __WXGTK__ */\r
201                 opj_destroy_decompress(dinfo);\r
202                 opj_cio_close(cio);\r
203                 opj_image_destroy(opjimage);\r
204                 free(src);\r
205                 return false;\r
206         }\r
207 \r
208         /* close the byte stream */\r
209         opj_cio_close(cio);\r
210 \r
211         /* common rendering method */\r
212 #include "imagjpeg2000.cpp"\r
213 \r
214 #ifndef __WXGTK__ \r
215     wxMutexGuiEnter();\r
216 #endif /* __WXGTK__ */\r
217     wxLogMessage(wxT("J2K: image loaded."));\r
218 #ifndef __WXGTK__ \r
219     wxMutexGuiLeave();\r
220 #endif /* __WXGTK__ */\r
221 \r
222         /* close openjpeg structs */\r
223         opj_destroy_decompress(dinfo);\r
224         opj_image_destroy(opjimage);\r
225         free(src);\r
226 \r
227         if (!image->Ok())\r
228                 return false;\r
229         else\r
230                 return true;\r
231 \r
232 }\r
233 \r
234 // save the j2k codestream\r
235 bool wxJ2KHandler::SaveFile( wxImage *wimage, wxOutputStream& stream, bool verbose )\r
236 {\r
237         opj_cparameters_t parameters;   /* compression parameters */\r
238         opj_event_mgr_t event_mgr;              /* event manager */\r
239         opj_image_t *oimage = NULL;\r
240         opj_image_cmptparm_t *cmptparm; \r
241         opj_cio_t *cio = NULL;\r
242         opj_codestream_info_t cstr_info;\r
243         int codestream_length;\r
244         bool bSuccess;\r
245         int i;\r
246         char indexfilename[OPJ_PATH_LEN] = "";  /* index file name */\r
247 \r
248         /*\r
249         configure the event callbacks (not required)\r
250         setting of each callback is optionnal\r
251         */\r
252         memset(&event_mgr, 0, sizeof(opj_event_mgr_t));\r
253         event_mgr.error_handler = j2k_error_callback;\r
254         event_mgr.warning_handler = j2k_warning_callback;\r
255         event_mgr.info_handler = j2k_info_callback;\r
256 \r
257         /* set encoding parameters to default values */\r
258         opj_set_default_encoder_parameters(&parameters);\r
259 \r
260         /* load parameters */\r
261         parameters.cp_cinema = OFF;\r
262 \r
263         /* subsampling */\r
264         if (sscanf(m_subsampling.c_str(), wxT("%d,%d"), &(parameters.subsampling_dx), &(parameters.subsampling_dy)) != 2) {\r
265                 wxLogError(wxT("Wrong sub-sampling encoder setting: dx,dy"));\r
266                 return false;\r
267         }\r
268 \r
269         /* compression rates */\r
270         if (m_rates != wxT("")) {\r
271                 char *s1 = (char *) m_rates.c_str();\r
272                 wxLogMessage("rates %s", s1);\r
273                 while (sscanf(s1, "%f", &(parameters.tcp_rates[parameters.tcp_numlayers])) == 1) {\r
274                         parameters.tcp_numlayers++;\r
275                         while (*s1 && *s1 != ',') {\r
276                                 s1++;\r
277                         }\r
278                         if (!*s1)\r
279                                 break;\r
280                         s1++;\r
281                 }\r
282                 wxLogMessage("%d layers", parameters.tcp_numlayers);\r
283                 parameters.cp_disto_alloc = 1;\r
284         }\r
285 \r
286         /* image quality, dB */\r
287         if (m_rates == wxT("")) {\r
288                 char *s2 = (char *) m_quality.c_str();\r
289                 wxLogMessage("qualities %s", s2);\r
290                 while (sscanf(s2, "%f", &parameters.tcp_distoratio[parameters.tcp_numlayers]) == 1) {\r
291                         parameters.tcp_numlayers++;\r
292                         while (*s2 && *s2 != ',') {\r
293                                 s2++;\r
294                         }\r
295                         if (!*s2)\r
296                                 break;\r
297                         s2++;\r
298                 }\r
299                 wxLogMessage("%d layers", parameters.tcp_numlayers);\r
300                 parameters.cp_fixed_quality = 1;\r
301         }\r
302 \r
303         /* image origin */\r
304         if (sscanf(m_origin.c_str(), "%d,%d", &parameters.image_offset_x0, &parameters.image_offset_y0) != 2) {\r
305                 wxLogError(wxT("bad coordinate of the image origin: x0,y0"));\r
306                 return false;\r
307         }\r
308                                 \r
309         /* Create comment for codestream */\r
310         if(m_enablecomm) {\r
311                 parameters.cp_comment = (char *) malloc(strlen(m_comment.c_str()) + 1);\r
312                 if(parameters.cp_comment) {\r
313                         strcpy(parameters.cp_comment, m_comment.c_str());\r
314                 }\r
315         } else {\r
316                 parameters.cp_comment = NULL;\r
317         }\r
318 \r
319         /* indexing file */\r
320         if (m_enableidx) {\r
321                 strncpy(indexfilename, m_index.c_str(), OPJ_PATH_LEN);\r
322                 wxLogMessage("index file is %s", indexfilename);\r
323         }\r
324 \r
325         /* if no rate entered, lossless by default */\r
326         if (parameters.tcp_numlayers == 0) {\r
327                 parameters.tcp_rates[0] = 0;    /* MOD antonin : losslessbug */\r
328                 parameters.tcp_numlayers++;\r
329                 parameters.cp_disto_alloc = 1;\r
330         }\r
331 \r
332         /* irreversible transform */\r
333         parameters.irreversible = (m_irreversible == true) ? 1 : 0;\r
334 \r
335         /* resolutions */\r
336         parameters.numresolution = m_resolutions;\r
337 \r
338         /* codeblocks size */\r
339         if (m_cbsize != wxT("")) {\r
340                 int cblockw_init = 0, cblockh_init = 0;\r
341                 sscanf(m_cbsize.c_str(), "%d,%d", &cblockw_init, &cblockh_init);\r
342                 if (cblockw_init * cblockh_init > 4096 || cblockw_init > 1024 || cblockw_init < 4 || cblockh_init > 1024 || cblockh_init < 4) {\r
343                         wxLogError("!! Size of code_block error !! Restrictions:\n  width*height<=4096\n  4<=width,height<= 1024");\r
344                         return false;\r
345                 }\r
346                 parameters.cblockw_init = cblockw_init;\r
347                 parameters.cblockh_init = cblockh_init;\r
348         }\r
349 \r
350         /* precincts size */\r
351         if (m_prsize != wxT("")) {\r
352                 char sep;\r
353                 int res_spec = 0;\r
354                 char *s = (char *) m_prsize.c_str();\r
355                 do {\r
356                         sep = 0;\r
357                         sscanf(s, "[%d,%d]%c", &parameters.prcw_init[res_spec], &parameters.prch_init[res_spec], &sep);\r
358                         parameters.csty |= 0x01;\r
359                         res_spec++;\r
360                         s = strpbrk(s, "]") + 2;\r
361                 } while (sep == ',');\r
362                 parameters.res_spec = res_spec;\r
363         }\r
364 \r
365         /* tiles */\r
366         if (m_tsize != wxT("")) {\r
367                 sscanf(m_tsize.c_str(), "%d,%d", &parameters.cp_tdx, &parameters.cp_tdy);\r
368                 parameters.tile_size_on = true;\r
369         }\r
370 \r
371         /* tile origin */\r
372         if (sscanf(m_torigin.c_str(), "%d,%d", &parameters.cp_tx0, &parameters.cp_ty0) != 2) {\r
373                 wxLogError("tile offset setting error: X0,Y0");\r
374                 return false;\r
375         }\r
376 \r
377         /* use SOP */\r
378         if (m_enablesop)\r
379                 parameters.csty |= 0x02;\r
380 \r
381         /* use EPH */\r
382         if (m_enableeph)\r
383                 parameters.csty |= 0x04;\r
384 \r
385 \r
386 \r
387         /* compression settings */\r
388         //parameters.tcp_numlayers = 1;\r
389         //parameters.tcp_rates[0] = 10.0;\r
390         //parameters.cp_disto_alloc = 1;\r
391         //parameters.irreversible = 1;\r
392         parameters.tcp_mct = 1;\r
393 \r
394         /* convert wx image into opj image */\r
395         cmptparm = (opj_image_cmptparm_t*) malloc(3 * sizeof(opj_image_cmptparm_t));\r
396 \r
397         /* initialize opj image components */   \r
398         memset(&cmptparm[0], 0, 3 * sizeof(opj_image_cmptparm_t));\r
399         for(i = 0; i < 3; i++) {                \r
400                 cmptparm[i].prec = 8;\r
401                 cmptparm[i].bpp = 8;\r
402                 cmptparm[i].sgnd = false;\r
403                 cmptparm[i].dx = parameters.subsampling_dx;\r
404                 cmptparm[i].dy = parameters.subsampling_dy;\r
405                 cmptparm[i].w = wimage->GetWidth();\r
406                 cmptparm[i].h = wimage->GetHeight();\r
407         }\r
408 \r
409         /* create the image */\r
410         oimage = opj_image_create(3, &cmptparm[0], CLRSPC_SRGB);\r
411         if(!oimage) {\r
412                 if (cmptparm)\r
413                         free(cmptparm);\r
414                 return false;\r
415         }\r
416 \r
417         /* set image offset and reference grid */\r
418         oimage->x0 = parameters.image_offset_x0;\r
419         oimage->y0 = parameters.image_offset_y0;\r
420         oimage->x1 = parameters.image_offset_x0 + (wimage->GetWidth() - 1) * 1 + 1;\r
421         oimage->y1 = parameters.image_offset_y0 + (wimage->GetHeight() - 1) * 1 + 1;\r
422 \r
423         /* load image data */\r
424         unsigned char *value = wimage->GetData(); \r
425         int area = wimage->GetWidth() * wimage->GetHeight();\r
426         for (i = 0; i < area; i++) {\r
427                         oimage->comps[0].data[i] = *(value++);\r
428                         oimage->comps[1].data[i] = *(value++);\r
429                         oimage->comps[2].data[i] = *(value++);\r
430         }\r
431 \r
432         /* get a J2K compressor handle */\r
433         opj_cinfo_t* cinfo = opj_create_compress(CODEC_J2K);\r
434 \r
435         /* catch events using our callbacks and give a local context */\r
436         opj_set_event_mgr((opj_common_ptr)cinfo, &event_mgr, stderr);\r
437 \r
438         /* setup the encoder parameters using the current image and user parameters */\r
439         opj_setup_encoder(cinfo, &parameters, oimage);\r
440 \r
441         /* open a byte stream for writing */\r
442         /* allocate memory for all tiles */\r
443         cio = opj_cio_open((opj_common_ptr)cinfo, NULL, 0);\r
444 \r
445         /* encode the image */\r
446         bSuccess = opj_encode(cinfo, cio, oimage, &cstr_info);\r
447         if (!bSuccess) {\r
448 \r
449                 opj_cio_close(cio);\r
450                 opj_destroy_compress(cinfo);\r
451                 opj_image_destroy(oimage);\r
452                 if (cmptparm)\r
453                         free(cmptparm);\r
454                 if(parameters.cp_comment)\r
455                         free(parameters.cp_comment);\r
456                 if(parameters.cp_matrice)\r
457                         free(parameters.cp_matrice);\r
458 \r
459 #ifndef __WXGTK__ \r
460     wxMutexGuiEnter();\r
461 #endif /* __WXGTK__ */\r
462 \r
463                 wxLogError(wxT("failed to encode image"));\r
464 \r
465 #ifndef __WXGTK__ \r
466     wxMutexGuiLeave();\r
467 #endif /* __WXGTK__ */\r
468 \r
469                 return false;\r
470         }\r
471         codestream_length = cio_tell(cio);\r
472         wxLogMessage(wxT("Codestream: %d bytes"), codestream_length);\r
473 \r
474         /* write the buffer to stream */\r
475         stream.Write(cio->buffer, codestream_length);\r
476 \r
477         /* close and free the byte stream */\r
478         opj_cio_close(cio);\r
479 \r
480         /* Write the index to disk */\r
481         if (*indexfilename) {\r
482                 bSuccess = write_index_file(&cstr_info, indexfilename);\r
483                 if (bSuccess) {\r
484                         wxLogError(wxT("Failed to output index file"));\r
485                 }\r
486         }\r
487 \r
488         /* free remaining compression structures */\r
489         opj_destroy_compress(cinfo);\r
490 \r
491         /* free image data */\r
492         opj_image_destroy(oimage);\r
493 \r
494         if (cmptparm)\r
495                 free(cmptparm);\r
496         if(parameters.cp_comment)\r
497                 free(parameters.cp_comment);\r
498         if(parameters.cp_matrice)\r
499                 free(parameters.cp_matrice);\r
500 \r
501 #ifndef __WXGTK__ \r
502     wxMutexGuiEnter();\r
503 #endif /* __WXGTK__ */\r
504 \r
505     wxLogMessage(wxT("J2K: Image encoded!"));\r
506 \r
507 #ifndef __WXGTK__ \r
508     wxMutexGuiLeave();\r
509 #endif /* __WXGTK__ */\r
510 \r
511     return true;\r
512 }\r
513 \r
514 #ifdef __VISUALC__\r
515     #pragma warning(default:4611)\r
516 #endif /* VC++ */\r
517 \r
518 // recognize the 0xFF4F JPEG 2000 SOC marker\r
519 bool wxJ2KHandler::DoCanRead( wxInputStream& stream )\r
520 {\r
521     unsigned char hdr[2];\r
522 \r
523     if ( !stream.Read(hdr, WXSIZEOF(hdr)) )\r
524         return false;\r
525 \r
526     return hdr[0] == 0xFF && hdr[1] == 0x4F;\r
527 }\r
528 \r
529 /**\r
530 Create an index and write it to a file\r
531 @param cstr_info Codestream information \r
532 @param index Index filename\r
533 @return Returns 0 if successful, returns 1 otherwise\r
534 */\r
535 bool wxJ2KHandler::write_index_file(opj_codestream_info_t *cstr_info, char *index) {\r
536         int tileno, compno, layno, resno, precno, pack_nb, x, y;\r
537         FILE *stream = NULL;\r
538         int tilepartno;\r
539 \r
540         if (!cstr_info)         \r
541                 return 1;\r
542 \r
543         stream = fopen(index, "w");\r
544         if (!stream) {\r
545                 fprintf(stderr, "failed to open index file [%s] for writing\n", index);\r
546                 return 1;\r
547         }\r
548         \r
549         fprintf(stream, "%d %d\n", cstr_info->image_w, cstr_info->image_h);\r
550         fprintf(stream, "%d\n", cstr_info->prog);\r
551         fprintf(stream, "%d %d\n", cstr_info->tile_x, cstr_info->tile_y);\r
552         fprintf(stream, "%d %d\n", cstr_info->tw, cstr_info->th);\r
553         fprintf(stream, "%d\n", cstr_info->numcomps);\r
554         fprintf(stream, "%d\n", cstr_info->numlayers);\r
555         fprintf(stream, "%d\n", cstr_info->numdecompos);\r
556         \r
557         for (resno = cstr_info->numdecompos; resno >= 0; resno--) {\r
558                 fprintf(stream, "[%d,%d] ", \r
559                         (1 << cstr_info->tile[0].pdx[resno]), (1 << cstr_info->tile[0].pdx[resno]));    /* based on tile 0 */\r
560         }\r
561         fprintf(stream, "\n");\r
562         fprintf(stream, "%d\n", cstr_info->main_head_start);\r
563         fprintf(stream, "%d\n", cstr_info->main_head_end);\r
564         fprintf(stream, "%d\n", cstr_info->codestream_size);\r
565         \r
566         fprintf(stream, "\nINFO ON TILES\n");\r
567         fprintf(stream, "tileno start_pos  end_hd  end_tile   nbparts\n");\r
568         for (tileno = 0; tileno < cstr_info->tw * cstr_info->th; tileno++) {\r
569                 fprintf(stream, "%4d %9d %9d %9d %9d\n",\r
570                         cstr_info->tile[tileno].tileno,\r
571                         cstr_info->tile[tileno].start_pos,\r
572                         cstr_info->tile[tileno].end_header,\r
573                         cstr_info->tile[tileno].end_pos,\r
574                         cstr_info->tile[tileno].num_tps);\r
575         }\r
576                 \r
577         for (tileno = 0; tileno < cstr_info->tw * cstr_info->th; tileno++) {\r
578                 int start_pos, end_ph_pos, end_pos;\r
579                 pack_nb = 0;\r
580 \r
581                 fprintf(stream, "\nTILE %d DETAILS\n", tileno); \r
582                 fprintf(stream, "part_nb tileno  num_packs  start_pos end_tph_pos   end_pos\n");\r
583                 for (tilepartno = 0; tilepartno < cstr_info->tile[tileno].num_tps; tilepartno++)\r
584                         fprintf(stream, "%4d %9d  %9d  %9d %11d %9d\n",\r
585                                 tilepartno, tileno,\r
586                                 cstr_info->tile[tileno].tp[tilepartno].tp_numpacks,\r
587                                 cstr_info->tile[tileno].tp[tilepartno].tp_start_pos,\r
588                                 cstr_info->tile[tileno].tp[tilepartno].tp_end_header,\r
589                                 cstr_info->tile[tileno].tp[tilepartno].tp_end_pos\r
590                                 );\r
591                 if (cstr_info->prog == LRCP) {  /* LRCP */\r
592                         fprintf(stream, "LRCP\npack_nb tileno layno resno compno precno start_pos end_ph_pos end_pos\n");\r
593 \r
594                         for (layno = 0; layno < cstr_info->numlayers; layno++) {\r
595                                 for (resno = 0; resno < cstr_info->numdecompos + 1; resno++) {\r
596                                         for (compno = 0; compno < cstr_info->numcomps; compno++) {\r
597                                                 int prec_max = cstr_info->tile[tileno].pw[resno] * cstr_info->tile[tileno].ph[resno];\r
598                                                 for (precno = 0; precno < prec_max; precno++) {\r
599                                                         start_pos = cstr_info->tile[tileno].packet[pack_nb].start_pos;\r
600                                                         end_ph_pos = cstr_info->tile[tileno].packet[pack_nb].end_ph_pos;\r
601                                                         end_pos = cstr_info->tile[tileno].packet[pack_nb].end_pos;\r
602                                                         fprintf(stream, "%4d %6d %7d %5d %6d  %6d    %6d     %6d %7d\n",\r
603                                                                 pack_nb, tileno, layno, resno, compno, precno, start_pos, end_ph_pos, end_pos);\r
604                                                         pack_nb++;\r
605                                                 }\r
606                                         }\r
607                                 }\r
608                         }\r
609                 } /* LRCP */\r
610                 else if (cstr_info->prog == RLCP) {     /* RLCP */\r
611 \r
612                         fprintf(stream, "RLCP\npack_nb tileno resno layno compno precno start_pos end_ph_pos end_pos\n");\r
613 \r
614                         for (resno = 0; resno < cstr_info->numdecompos + 1; resno++) {\r
615                                 for (layno = 0; layno < cstr_info->numlayers; layno++) {\r
616                                         for (compno = 0; compno < cstr_info->numcomps; compno++) {\r
617                                                 int prec_max = cstr_info->tile[tileno].pw[resno] * cstr_info->tile[tileno].ph[resno];\r
618                                                 for (precno = 0; precno < prec_max; precno++) {\r
619                                                         start_pos = cstr_info->tile[tileno].packet[pack_nb].start_pos;\r
620                                                         end_ph_pos = cstr_info->tile[tileno].packet[pack_nb].end_ph_pos;\r
621                                                         end_pos = cstr_info->tile[tileno].packet[pack_nb].end_pos;\r
622                                                         fprintf(stream, "%4d %6d %5d %7d %6d %6d %9d   %9d %7d\n",\r
623                                                                 pack_nb, tileno, resno, layno, compno, precno, start_pos, end_ph_pos, end_pos);\r
624                                                         pack_nb++;\r
625                                                 }\r
626                                         }\r
627                                 }\r
628                         }\r
629                 } /* RLCP */\r
630                 else if (cstr_info->prog == RPCL) {     /* RPCL */\r
631 \r
632                         fprintf(stream, "RPCL\npack_nb tileno resno precno compno layno start_pos end_ph_pos end_pos\n"); \r
633 \r
634                         for (resno = 0; resno < cstr_info->numdecompos + 1; resno++) {\r
635                                 /* I suppose components have same XRsiz, YRsiz */\r
636                                 int x0 = cstr_info->tile_Ox + tileno - (int)floor((float)tileno/(float)cstr_info->tw ) * cstr_info->tw * cstr_info->tile_x;\r
637                                 int y0 = cstr_info->tile_Ox + (int)floor( (float)tileno/(float)cstr_info->tw ) * cstr_info->tile_y;\r
638                                 int x1 = x0 + cstr_info->tile_x;\r
639                                 int y1 = y0 + cstr_info->tile_y;\r
640                                 for (compno = 0; compno < cstr_info->numcomps; compno++) {\r
641                                         int prec_max = cstr_info->tile[tileno].pw[resno] * cstr_info->tile[tileno].ph[resno];\r
642                                         for (precno = 0; precno < prec_max; precno++) {\r
643                                                 int pcnx = cstr_info->tile[tileno].pw[resno];\r
644                                                 int pcx = (int) pow( 2, cstr_info->tile[tileno].pdx[resno] + cstr_info->numdecompos - resno );\r
645                                                 int pcy = (int) pow( 2, cstr_info->tile[tileno].pdy[resno] + cstr_info->numdecompos - resno );\r
646                                                 int precno_x = precno - (int) floor( (float)precno/(float)pcnx ) * pcnx;\r
647                                                 int precno_y = (int) floor( (float)precno/(float)pcnx );\r
648                                                 for(y = y0; y < y1; y++) {                                                      \r
649                                                         if (precno_y*pcy == y ) {\r
650                                                                 for (x = x0; x < x1; x++) {                                                                     \r
651                                                                         if (precno_x*pcx == x ) {\r
652                                                                                 for (layno = 0; layno < cstr_info->numlayers; layno++) {\r
653                                                                                         start_pos = cstr_info->tile[tileno].packet[pack_nb].start_pos;\r
654                                                                                         end_ph_pos = cstr_info->tile[tileno].packet[pack_nb].end_ph_pos;\r
655                                                                                         end_pos = cstr_info->tile[tileno].packet[pack_nb].end_pos;\r
656                                                                                         fprintf(stream, "%4d %6d %5d %6d %6d %7d %9d   %9d %7d\n",\r
657                                                                                                 pack_nb, tileno, resno, precno, compno, layno, start_pos, end_ph_pos, end_pos); \r
658                                                                                         pack_nb++; \r
659                                                                                 }\r
660                                                                         }\r
661                                                                 }/* x = x0..x1 */\r
662                                                         } \r
663                                                 }  /* y = y0..y1 */\r
664                                         } /* precno */\r
665                                 } /* compno */\r
666                         } /* resno */\r
667                 } /* RPCL */\r
668                 else if (cstr_info->prog == PCRL) {     /* PCRL */\r
669                         /* I suppose components have same XRsiz, YRsiz */\r
670                         int x0 = cstr_info->tile_Ox + tileno - (int)floor( (float)tileno/(float)cstr_info->tw ) * cstr_info->tw * cstr_info->tile_x;\r
671                         int y0 = cstr_info->tile_Ox + (int)floor( (float)tileno/(float)cstr_info->tw ) * cstr_info->tile_y;\r
672                         int x1 = x0 + cstr_info->tile_x;\r
673                         int y1 = y0 + cstr_info->tile_y;\r
674 \r
675                         fprintf(stream, "PCRL\npack_nb tileno precno compno resno layno start_pos end_ph_pos end_pos\n"); \r
676 \r
677                         for (compno = 0; compno < cstr_info->numcomps; compno++) {\r
678                                 for (resno = 0; resno < cstr_info->numdecompos + 1; resno++) {\r
679                                         int prec_max = cstr_info->tile[tileno].pw[resno] * cstr_info->tile[tileno].ph[resno];\r
680                                         for (precno = 0; precno < prec_max; precno++) {\r
681                                                 int pcnx = cstr_info->tile[tileno].pw[resno];\r
682                                                 int pcx = (int) pow( 2, cstr_info->tile[tileno].pdx[resno] + cstr_info->numdecompos - resno );\r
683                                                 int pcy = (int) pow( 2, cstr_info->tile[tileno].pdy[resno] + cstr_info->numdecompos - resno );\r
684                                                 int precno_x = precno - (int) floor( (float)precno/(float)pcnx ) * pcnx;\r
685                                                 int precno_y = (int) floor( (float)precno/(float)pcnx );\r
686                                                 for(y = y0; y < y1; y++) {                                                      \r
687                                                         if (precno_y*pcy == y ) {\r
688                                                                 for (x = x0; x < x1; x++) {                                                                     \r
689                                                                         if (precno_x*pcx == x ) {\r
690                                                                                 for (layno = 0; layno < cstr_info->numlayers; layno++) {\r
691                                                                                         start_pos = cstr_info->tile[tileno].packet[pack_nb].start_pos;\r
692                                                                                         end_ph_pos = cstr_info->tile[tileno].packet[pack_nb].end_ph_pos;\r
693                                                                                         end_pos = cstr_info->tile[tileno].packet[pack_nb].end_pos;\r
694                                                                                         fprintf(stream, "%4d %6d %6d %6d %5d %7d %9d   %9d %7d\n",\r
695                                                                                                 pack_nb, tileno, precno, compno, resno, layno, start_pos, end_ph_pos, end_pos); \r
696                                                                                         pack_nb++; \r
697                                                                                 }\r
698                                                                         }\r
699                                                                 }/* x = x0..x1 */\r
700                                                         } \r
701                                                 }  /* y = y0..y1 */\r
702                                         } /* precno */\r
703                                 } /* resno */\r
704                         } /* compno */\r
705                 } /* PCRL */\r
706                 else {  /* CPRL */\r
707 \r
708                         fprintf(stream, "CPRL\npack_nb tileno compno precno resno layno start_pos end_ph_pos end_pos\n"); \r
709 \r
710                         for (compno = 0; compno < cstr_info->numcomps; compno++) {\r
711                                 /* I suppose components have same XRsiz, YRsiz */\r
712                                 int x0 = cstr_info->tile_Ox + tileno - (int)floor( (float)tileno/(float)cstr_info->tw ) * cstr_info->tw * cstr_info->tile_x;\r
713                                 int y0 = cstr_info->tile_Ox + (int)floor( (float)tileno/(float)cstr_info->tw ) * cstr_info->tile_y;\r
714                                 int x1 = x0 + cstr_info->tile_x;\r
715                                 int y1 = y0 + cstr_info->tile_y;\r
716                                 \r
717                                 for (resno = 0; resno < cstr_info->numdecompos + 1; resno++) {\r
718                                         int prec_max = cstr_info->tile[tileno].pw[resno] * cstr_info->tile[tileno].ph[resno];\r
719                                         for (precno = 0; precno < prec_max; precno++) {\r
720                                                 int pcnx = cstr_info->tile[tileno].pw[resno];\r
721                                                 int pcx = (int) pow( 2, cstr_info->tile[tileno].pdx[resno] + cstr_info->numdecompos - resno );\r
722                                                 int pcy = (int) pow( 2, cstr_info->tile[tileno].pdy[resno] + cstr_info->numdecompos - resno );\r
723                                                 int precno_x = precno - (int) floor( (float)precno/(float)pcnx ) * pcnx;\r
724                                                 int precno_y = (int) floor( (float)precno/(float)pcnx );\r
725                                                 for(y = y0; y < y1; y++) {\r
726                                                         if (precno_y*pcy == y ) {\r
727                                                                 for (x = x0; x < x1; x++) {\r
728                                                                         if (precno_x*pcx == x ) {\r
729                                                                                 for (layno = 0; layno < cstr_info->numlayers; layno++) {\r
730                                                                                         start_pos = cstr_info->tile[tileno].packet[pack_nb].start_pos;\r
731                                                                                         end_ph_pos = cstr_info->tile[tileno].packet[pack_nb].end_ph_pos;\r
732                                                                                         end_pos = cstr_info->tile[tileno].packet[pack_nb].end_pos;\r
733                                                                                         fprintf(stream, "%4d %6d %6d %6d %5d %7d %9d   %9d %7d\n",\r
734                                                                                                 pack_nb, tileno, compno, precno, resno, layno, start_pos, end_ph_pos, end_pos); \r
735                                                                                         pack_nb++; \r
736                                                                                 }\r
737                                                                         }\r
738                                                                 }/* x = x0..x1 */\r
739                                                         }\r
740                                                 } /* y = y0..y1 */\r
741                                         } /* precno */\r
742                                 } /* resno */\r
743                         } /* compno */\r
744                 } /* CPRL */   \r
745         } /* tileno */\r
746         \r
747         fclose(stream);\r
748 \r
749         fprintf(stderr,"Generated index file %s\n", index);\r
750 \r
751         return true;\r
752 }\r
753 \r
754 #endif   // wxUSE_STREAMS\r
755 \r
756 #endif   // wxUSE_LIBOPENJPEG\r