[trunk] Backport from OPJViewer version 1.5 over to trunk
[openjpeg.git] / applications / OPJViewer / source / wxj2kparser.cpp
1 /*
2  * Copyright (c) 2007, Digital Signal Processing Laboratory, Universit� degli studi di Perugia (UPG), Italy
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24  * POSSIBILITY OF SUCH DAMAGE.
25  */
26 #include "OPJViewer.h"
27
28 /* From little endian to big endian, 2 bytes */
29 #define BYTE_SWAP2(X)   ((X & 0x00FF) << 8) | ((X & 0xFF00) >> 8)
30 #define BYTE_SWAP4(X)   ((X & 0x000000FF) << 24) | ((X & 0x0000FF00) << 8) | ((X & 0x00FF0000) >> 8) | ((X & 0xFF000000) >> 24)
31
32 /* From codestream to int values */
33 #define STREAM_TO_UINT32(C, P)  (((unsigned long int) (C)[(P) + 0] << 24) + \
34                                                                 ((unsigned long int) (C)[(P) + 1] << 16) + \
35                                                                 ((unsigned long int) (C)[(P) + 2] << 8) + \
36                                                                 ((unsigned long int) (C)[(P) + 3] << 0))
37
38 #define STREAM_TO_UINT16(C, P)  (((unsigned long int) (C)[(P) + 0] << 8) + \
39                                                                 ((unsigned long int) (C)[(P) + 1] << 0))
40
41
42 /* Markers values */
43 #define J2KMARK_NUM 24
44 enum {
45         SOC_VAL = 0xFF4F,
46         SOT_VAL = 0xFF90,
47         SOD_VAL = 0xFF93,
48         EOC_VAL = 0xFFD9,
49         SIZ_VAL = 0xFF51,
50         COD_VAL = 0xFF52,
51         COC_VAL = 0xFF53,
52         RGN_VAL = 0xFF5E,
53         QCD_VAL = 0xFF5C,
54         QCC_VAL = 0xFF5D,
55         POD_VAL = 0xFF5F,
56         TLM_VAL = 0xFF55,
57         PLM_VAL = 0xFF57,
58         PLT_VAL = 0xFF58,
59         PPM_VAL = 0xFF60,
60         PPT_VAL = 0xFF61,
61         SOP_VAL = 0xFF91,
62         EPH_VAL = 0xFF92,
63         COM_VAL = 0xFF64
64 #ifdef USE_JPWL
65         , EPB_VAL       = 0xFF66,
66         ESD_VAL = 0xFF67,
67         EPC_VAL = 0xFF68,
68         RED_VAL = 0xFF69
69         /*, EPB_VAL = 0xFF96,
70         ESD_VAL = 0xFF98,
71         EPC_VAL = 0xFF97,
72         RED_VAL = 0xFF99*/
73 #endif // USE_JPWL
74 #ifdef USE_JPSEC
75         , SEC_VAL = 0xFF65
76 #endif // USE_JPSEC
77 };
78
79 // All the markers in one vector
80 unsigned short int marker_val[] = {
81         SOC_VAL, SOT_VAL, SOD_VAL, EOC_VAL,
82         SIZ_VAL,
83         COD_VAL, COC_VAL, RGN_VAL, QCD_VAL, QCC_VAL, POD_VAL,
84         TLM_VAL, PLM_VAL, PLT_VAL, PPM_VAL, PPT_VAL,
85         SOP_VAL, EPH_VAL,
86         COM_VAL
87 #ifdef USE_JPWL
88         , EPB_VAL, ESD_VAL, EPC_VAL, RED_VAL
89 #endif // USE_JPWL
90 #ifdef USE_JPSEC
91         , SEC_VAL
92 #endif // USE_JPSEC
93 };
94
95 // Marker names
96 static const char *marker_name[] = {
97         "SOC", "SOT", "SOD", "EOC",
98         "SIZ",
99         "COD", "COC", "RGN", "QCD", "QCC", "POD",
100         "TLM", "PLM", "PLT", "PPM", "PPT",
101         "SOP", "EPH",
102         "COM"
103 #ifdef USE_JPWL
104         , "EPB", "ESD", "EPC", "RED"
105 #endif // USE_JPWL
106 #ifdef USE_JPSEC
107         , "SEC"
108 #endif // USE_JPSEC
109 };
110
111 // Marker descriptions
112 static const char *marker_descr[] = {
113         "Start of codestream", "Start of tile-part", "Start of data", "End of codestream",
114         "Image and tile size",
115         "Coding style default", "Coding style component", "Region-of-interest", "Quantization default",
116         "Quantization component", "Progression order change, default",
117         "Tile-part lengths, main header", "Packet length, main header", "Packets length, tile-part header",
118         "Packed packet headers, main header", "Packed packet headers, tile-part header",
119         "Start of packet", "End of packet header",
120         "Comment and extension"
121 #ifdef USE_JPWL
122         , "Error Protection Block", "Error Sensitivity Descriptor", "Error Protection Capability",
123         "Residual Errors Descriptor"
124 #endif // USE_JPWL
125 #ifdef USE_JPSEC
126         , "Main security marker"
127 #endif // USE_JPSEC
128 };
129
130 void OPJParseThread::ParseJ2KFile(wxFile *m_file, wxFileOffset offset, wxFileOffset length, wxTreeItemId parentid)
131 {
132         unsigned short int csiz = 0;
133
134         // check if the file is opened
135         if (m_file->IsOpened())
136                 WriteText(wxT("File OK"));
137         else
138                 return;
139
140         // position at the beginning
141         m_file->Seek(offset, wxFromStart);
142
143         // navigate the file
144         int m, inside_sod = 0, inside_sop = 0;
145         int nmarks = 0, maxmarks = 10000;
146         unsigned char onebyte[1];
147         unsigned char twobytes[2], firstbyte, secondbyte;
148         unsigned char fourbytes[4];
149         unsigned short int currmark;
150         unsigned short int currlen;
151         int lastPsot = 0, lastsotpos = 0;
152
153         WriteText(wxT("Start search..."));
154
155 // advancing macro
156 #define OPJ_ADVANCE(A) {offset += A; if (offset < length) m_file->Seek(offset, wxFromStart); else return;}
157
158         // begin search
159         while ((offset < length) && (!m_file->Eof())) {
160
161                 // read one byte
162                 if (m_file->Read(&firstbyte, 1) != 1)
163                         break;
164
165                 // look for 0xFF
166                 if (firstbyte == 0xFF) {
167
168                         // it is a possible marker
169                         if (m_file->Read(&secondbyte, 1) != 1)
170                                 break;
171                         else
172                                 currmark = (((unsigned short int) firstbyte) << 8) + (unsigned short int) secondbyte;
173
174                 } else {
175
176                         // nope, advance by one and search again
177                         OPJ_ADVANCE(1);
178                         continue;
179                 }
180                 
181                 // search the marker
182                 for (m = 0; m < J2KMARK_NUM; m++) {
183                         if (currmark == marker_val[m])
184                                 break;
185                 }
186
187                 // marker not found
188                 if (m == J2KMARK_NUM) {
189                         // nope, advance by one and search again
190                         OPJ_ADVANCE(1);
191                         continue;
192                 }
193
194                 // if we are inside SOD, only some markers are allowed
195                 if (inside_sod) {
196
197                         // we are inside SOP
198                         if (inside_sop) {
199
200                         }
201
202                         // randomly marker coincident data
203                         if ((currmark != SOT_VAL) &&
204                                 (currmark != EOC_VAL) &&
205                                 (currmark != SOP_VAL) &&
206                                 (currmark != EPH_VAL)) {
207                                 OPJ_ADVANCE(1);
208                                 continue;
209                         }
210
211                         // possible SOT?
212                         if ((currmark == SOT_VAL)) {
213                                 // too early SOT
214                                 if (offset < (lastsotpos + lastPsot)) {
215                                         OPJ_ADVANCE(1);
216                                         continue;
217                                 }
218                                 // we were not in the last tile
219                                 /*if (lastPsot != 0) {
220                                         OPJ_ADVANCE(1);
221                                         break;
222                                 }*/
223                         }
224                 }
225
226                 // beyond this point, the marker MUST BE real
227
228                 // length of current marker segment
229                 if ((currmark == SOD_VAL) ||
230                         (currmark == SOC_VAL) ||
231                         (currmark == EOC_VAL) ||
232                         (currmark == EPH_VAL))
233
234                         // zero length markers
235                         currlen = 0;
236
237                 else {
238
239                         // read length field
240                         if (m_file->Read(twobytes, 2) != 2)
241                                 break;
242
243                         currlen = (((unsigned short int) twobytes[0]) << 8) + (unsigned short int) twobytes[1];
244                 }
245
246                 // here we pass to AppendItem() normal and selected item images (we
247                 // suppose that selected image follows the normal one in the enum)
248                 int image, imageSel;
249                 image = m_tree->TreeCtrlIcon_Folder;
250                 imageSel = image + 1;
251
252                 // append the marker
253                 wxTreeItemId currid = m_tree->AppendItem(parentid,
254                         wxString::Format(wxT("%03d: "), nmarks) +
255                         wxString::FromAscii(marker_name[m]) + 
256                         wxString::Format(wxT(" (0x%04X)"), marker_val[m]),
257                         image, imageSel,
258                         new OPJMarkerData(wxT("MARK") + wxString::Format(wxT(" (%d)"), marker_val[m]),
259                                 m_tree->m_fname.GetFullPath(), offset, offset + currlen + 1)
260                         );
261
262                 // append some info
263                 image = m_tree->TreeCtrlIcon_File;
264                 imageSel = image + 1;
265
266                 // marker name
267                 wxTreeItemId subcurrid1 = m_tree->AppendItem(currid,
268                         wxT("*** ") + wxString::FromAscii(marker_descr[m]) + wxT(" ***"),
269                         image, imageSel,
270                         new OPJMarkerData(wxT("INFO"))
271                         );
272                 m_tree->SetItemFont(subcurrid1, *wxITALIC_FONT);
273
274                 // position and length
275                 wxTreeItemId subcurrid2 = m_tree->AppendItem(currid,
276                         wxLongLong(offset).ToString() + wxT(" > ") + wxLongLong(offset + currlen + 1).ToString() + 
277                         wxT(", ") + wxString::Format(wxT("%d + 2 (%d)"), currlen, currlen + 2),
278                         image, imageSel,
279                         new OPJMarkerData(wxT("INFO"))
280                         );
281
282                 // give additional info on markers
283                 switch (currmark) {
284
285                 /////////
286                 // SOP //
287                 /////////
288                 case SOP_VAL:
289                         {
290                         // read packet number
291                         if (m_file->Read(twobytes, 2) != 2)
292                                 break;
293                         int packnum = STREAM_TO_UINT16(twobytes, 0);
294
295                         image = m_tree->TreeCtrlIcon_File;
296                         imageSel = image + 1;
297
298                         wxTreeItemId subcurrid3 = m_tree->AppendItem(currid,
299                                 wxString::Format(wxT("Pack. no. %d"), packnum),
300                                 image, imageSel,
301                                 new OPJMarkerData(wxT("INFO"))
302                                 );
303                         inside_sop = 1;
304                         };
305                         break;
306
307 #ifdef USE_JPWL
308                 /////////
309                 // RED //
310                 /////////
311                 case RED_VAL:
312                         {
313                         if (m_file->Read(onebyte, 1) != 1)
314                                 break;
315                         unsigned char pred = onebyte[0];
316
317                         image = m_tree->TreeCtrlIcon_File;
318                         imageSel = image + 1;
319
320                         wxString address[] = {
321                                 wxT("Packet addressing"),
322                                 wxT("Byte-range addressing"),
323                                 wxT("Packet-range addressing"),
324                                 wxT("Reserved")
325                         };
326
327                         wxTreeItemId subcurrid = m_tree->AppendItem(currid,
328                                 address[(pred & 0xC0) >> 6],
329                                 image, imageSel,
330                                 new OPJMarkerData(wxT("INFO"))
331                                 );
332
333                         subcurrid = m_tree->AppendItem(currid,
334                                 wxString::Format(wxT("%d bytes range"), (((pred & 0x02) >> 1) + 1) * 2),
335                                 image, imageSel,
336                                 new OPJMarkerData(wxT("INFO"))
337                                 );
338
339                         subcurrid = m_tree->AppendItem(currid,
340                                 pred & 0x01 ? wxT("Errors/erasures in codestream") : wxT("Error free codestream"),
341                                 image, imageSel,
342                                 new OPJMarkerData(wxT("INFO"))
343                                 );
344
345                         subcurrid = m_tree->AppendItem(currid,
346                                 wxString::Format(wxT("Residual corruption level: %d"), (pred & 0x38) >> 3),
347                                 image, imageSel,
348                                 new OPJMarkerData(wxT("INFO"))
349                                 );
350
351                         }
352                         break;
353
354                 /////////
355                 // ESD //
356                 /////////
357                 case ESD_VAL:
358                         {
359                         unsigned short int cesd;
360                         if (csiz < 257) {
361                                 if (m_file->Read(onebyte, 1) != 1)
362                                         break;
363                                 cesd = onebyte[0];
364                         } else {
365                                 if (m_file->Read(twobytes, 2) != 2)
366                                         break;
367                                 cesd = STREAM_TO_UINT16(twobytes, 0);
368                         }
369
370                         if (m_file->Read(onebyte, 1) != 1)
371                                 break;
372                         unsigned char pesd = onebyte[0];
373
374                         image = m_tree->TreeCtrlIcon_File;
375                         imageSel = image + 1;
376
377                         wxTreeItemId subcurrid = m_tree->AppendItem(currid,
378                                 pesd & 0x01 ? wxT("Comp. average") : wxString::Format(wxT("Comp. no. %d"), cesd),
379                                 image, imageSel,
380                                 new OPJMarkerData(wxT("INFO"))
381                                 );
382
383                         wxString meth[] = {
384                                 wxT("Relative error sensitivity"),
385                                 wxT("MSE"),
386                                 wxT("MSE reduction"),
387                                 wxT("PSNR"),
388                                 wxT("PSNR increase"),
389                                 wxT("MAXERR (absolute peak error)"),
390                                 wxT("TSE (total squared error)"),
391                                 wxT("Reserved")
392                         };
393
394                         subcurrid = m_tree->AppendItem(currid,
395                                 meth[(pesd & 0x38) >> 3],
396                                 image, imageSel,
397                                 new OPJMarkerData(wxT("INFO"))
398                                 );
399
400                         wxString address[] = {
401                                 wxT("Packet addressing"),
402                                 wxT("Byte-range addressing"),
403                                 wxT("Packet-range addressing"),
404                                 wxT("Reserved")
405                         };
406
407                         subcurrid = m_tree->AppendItem(currid,
408                                 address[(pesd & 0xC0) >> 6],
409                                 image, imageSel,
410                                 new OPJMarkerData(wxT("INFO"))
411                                 );
412
413                         subcurrid = m_tree->AppendItem(currid,
414                                 wxString::Format(wxT("%d bytes/value, %d bytes range"), ((pesd & 0x04) >> 2) + 1, (((pesd & 0x02) >> 1) + 1) * 2),
415                                 image, imageSel,
416                                 new OPJMarkerData(wxT("INFO"))
417                                 );
418
419                         }
420                         break;
421
422                 /////////
423                 // EPC //
424                 /////////
425                 case EPC_VAL:
426                         {
427                         if (m_file->Read(twobytes, 2) != 2)
428                                 break;
429                         unsigned short int pcrc = STREAM_TO_UINT16(twobytes, 0);
430
431                         if (m_file->Read(fourbytes, 4) != 4)
432                                 break;
433                         unsigned long int dl = STREAM_TO_UINT32(fourbytes, 0);
434
435                         if (m_file->Read(onebyte, 1) != 1)
436                                 break;
437                         unsigned char pepc = onebyte[0];
438
439                         image = m_tree->TreeCtrlIcon_File;
440                         imageSel = image + 1;
441
442                         wxTreeItemId subcurrid = m_tree->AppendItem(currid,
443                                 wxString::Format(wxT("CRC-16 = 0x%x"), pcrc),
444                                 image, imageSel,
445                                 new OPJMarkerData(wxT("INFO"))
446                                 );
447
448                         subcurrid = m_tree->AppendItem(currid,
449                                 wxString::Format(wxT("Tot. length = %d"), dl),
450                                 image, imageSel,
451                                 new OPJMarkerData(wxT("INFO"))
452                                 );
453
454                         subcurrid = m_tree->AppendItem(currid,
455                                 wxString::Format(wxT("%s%s%s%s"),
456                                         pepc & 0x10 ? wxT("ESD, ") : wxT(""),
457                                         pepc & 0x20 ? wxT("RED, ") : wxT(""),
458                                         pepc & 0x40 ? wxT("EPB, ") : wxT(""),
459                                         pepc & 0x80 ? wxT("Info") : wxT("")
460                                         ),
461                                 image, imageSel,
462                                 new OPJMarkerData(wxT("INFO"))
463                                 );
464
465                         }
466                         break;
467
468                 /////////
469                 // EPB //
470                 /////////
471                 case EPB_VAL:
472                         {
473                         if (m_file->Read(onebyte, 1) != 1)
474                                 break;
475                         unsigned char depb = onebyte[0];
476
477                         if (m_file->Read(fourbytes, 4) != 4)
478                                 break;
479                         unsigned long int ldpepb = STREAM_TO_UINT32(fourbytes, 0);
480
481                         if (m_file->Read(fourbytes, 4) != 4)
482                                 break;
483                         unsigned long int pepb = STREAM_TO_UINT32(fourbytes, 0);
484
485                         image = m_tree->TreeCtrlIcon_File;
486                         imageSel = image + 1;
487
488                         wxTreeItemId subcurrid = m_tree->AppendItem(currid,
489                                 wxString::Format(wxT("No. %d, %slatest, %spacked"),
490                                         depb & 0x3F,
491                                         depb & 0x40 ? wxT("") : wxT("not "),
492                                         depb & 0x80 ? wxT("") : wxT("un")),
493                                 image, imageSel,
494                                 new OPJMarkerData(wxT("INFO"))
495                                 );
496
497                         subcurrid = m_tree->AppendItem(currid,
498                                 wxString::Format(wxT("%d bytes protected"), ldpepb),
499                                 image, imageSel,
500                                 new OPJMarkerData(wxT("INFO"))
501                                 );
502
503                         if (pepb == 0x00000000)
504
505                                 subcurrid = m_tree->AppendItem(currid,
506                                         wxT("Predefined codes"),
507                                         image, imageSel,
508                                         new OPJMarkerData(wxT("INFO"))
509                                         );
510
511                         else if ((pepb >= 0x10000000) && (pepb <= 0x1FFFFFFF)) {
512
513                                 wxString text = wxT("CRC code");
514                                 if (pepb == 0x10000000)
515                                         text << wxT(", CCITT (X25) 16 bits");
516                                 else if (pepb == 0x10000001)
517                                         text << wxT(", Ethernet 32 bits");
518                                 else
519                                         text << wxT(", JPWL RA");
520                                 subcurrid = m_tree->AppendItem(currid,
521                                         text,
522                                         image, imageSel,
523                                         new OPJMarkerData(wxT("INFO"))
524                                         );
525
526                         } else if ((pepb >= 0x20000000) && (pepb <= 0x2FFFFFFF)) {
527
528                                 wxString text;
529                                 subcurrid = m_tree->AppendItem(currid,
530                                         wxString::Format(wxT("RS code, RS(%d, %d)"),
531                                                 (pepb & 0x0000FF00) >> 8,
532                                                 (pepb & 0x000000FF)),
533                                         image, imageSel,
534                                         new OPJMarkerData(wxT("INFO"))
535                                         );
536
537                         } else if ((pepb >= 0x30000000) && (pepb <= 0x3FFFFFFE))
538
539                                 subcurrid = m_tree->AppendItem(currid,
540                                         wxT("JPWL RA"),
541                                         image, imageSel,
542                                         new OPJMarkerData(wxT("INFO"))
543                                         );
544
545                         else if (pepb == 0xFFFFFFFF)
546
547                                 subcurrid = m_tree->AppendItem(currid,
548                                         wxT("No method"),
549                                         image, imageSel,
550                                         new OPJMarkerData(wxT("INFO"))
551                                         );
552
553                         }
554                         break;
555 #endif // USE_JPWL
556
557 #ifdef USE_JPSEC
558                 case SEC_VAL:
559                         {
560
561                         }
562                         break;
563 #endif // USE_JPSEC
564
565                 /////////
566                 // SIZ //
567                 /////////
568                 case SIZ_VAL:
569                         {
570                         int c;
571                         
572                         if (m_file->Read(twobytes, 2) != 2)
573                                 break;
574                         unsigned short int rsiz = STREAM_TO_UINT16(twobytes, 0);
575
576                         if (m_file->Read(fourbytes, 4) != 4)
577                                 break;
578                         unsigned long int xsiz = STREAM_TO_UINT32(fourbytes, 0);
579
580                         if (m_file->Read(fourbytes, 4) != 4)
581                                 break;
582                         unsigned long int ysiz = STREAM_TO_UINT32(fourbytes, 0);
583
584                         if (m_file->Read(fourbytes, 4) != 4)
585                                 break;
586                         unsigned long int xosiz = STREAM_TO_UINT32(fourbytes, 0);
587
588                         if (m_file->Read(fourbytes, 4) != 4)
589                                 break;
590                         unsigned long int yosiz = STREAM_TO_UINT32(fourbytes, 0);
591
592                         if (m_file->Read(fourbytes, 4) != 4)
593                                 break;
594                         unsigned long int xtsiz = STREAM_TO_UINT32(fourbytes, 0);
595                         this->m_tree->m_childframe->m_twidth = xtsiz;
596
597                         if (m_file->Read(fourbytes, 4) != 4)
598                                 break;
599                         unsigned long int ytsiz = STREAM_TO_UINT32(fourbytes, 0);
600                         this->m_tree->m_childframe->m_theight = ytsiz;
601
602                         if (m_file->Read(fourbytes, 4) != 4)
603                                 break;
604                         unsigned long int xtosiz = STREAM_TO_UINT32(fourbytes, 0);
605                         this->m_tree->m_childframe->m_tx = xtosiz;
606
607                         if (m_file->Read(fourbytes, 4) != 4)
608                                 break;
609                         unsigned long int ytosiz = STREAM_TO_UINT32(fourbytes, 0);
610                         this->m_tree->m_childframe->m_ty = ytosiz;
611
612                         if (m_file->Read(twobytes, 2) != 2)
613                                 break;
614                         csiz = STREAM_TO_UINT16(twobytes, 0);
615
616                         bool equaldepth = true, equalsize = true;
617                         unsigned char *ssiz  = new unsigned char(csiz);
618                         unsigned char *xrsiz = new unsigned char(csiz);
619                         unsigned char *yrsiz = new unsigned char(csiz);
620
621                         for (c = 0; c < csiz; c++) {
622
623                                 if (m_file->Read(&ssiz[c], 1) != 1)
624                                         break;
625
626                                 if (c > 0)
627                                         equaldepth = equaldepth && (ssiz[c] == ssiz[c - 1]);
628
629                                 if (m_file->Read(&xrsiz[c], 1) != 1)
630                                         break;
631
632                                 if (m_file->Read(&yrsiz[c], 1) != 1)
633                                         break;
634
635                                 if (c > 0)
636                                         equalsize = equalsize && (xrsiz[c] == xrsiz[c - 1]) && (yrsiz[c] == yrsiz[c - 1]) ;
637
638                         }
639
640                         if (equaldepth && equalsize)
641                                 wxTreeItemId subcurrid3 = m_tree->AppendItem(currid,
642                                         wxString::Format(wxT("I: %dx%d (%d, %d), %d c., %d%s bpp"),
643                                         xsiz, ysiz,
644                                         xosiz, yosiz,
645                                         csiz, ((ssiz[0] & 0x7F) + 1),
646                                         (ssiz[0] & 0x80) ? wxT("s") : wxT("u")),
647                                         image, imageSel,
648                                         new OPJMarkerData(wxT("INFO"))
649                                         );
650                         else
651                                 wxTreeItemId subcurrid3 = m_tree->AppendItem(currid,
652                                         wxString::Format(wxT("I: %dx%d (%d, %d), %d c."),
653                                         xsiz, ysiz,
654                                         xosiz, yosiz,
655                                         csiz),
656                                         image, imageSel,
657                                         new OPJMarkerData(wxT("INFO"))
658                                         );
659
660                         wxTreeItemId subcurrid3 = m_tree->AppendItem(currid,
661                                 wxString::Format(wxT("T: %dx%d (%d, %d)"),
662                                 xtsiz, ytsiz,
663                                 xtosiz, ytosiz),
664                                 image, imageSel,
665                                 new OPJMarkerData(wxT("INFO"))
666                                 );
667
668                         image = m_tree->TreeCtrlIcon_Folder;
669                         imageSel = image + 1;
670
671                         wxTreeItemId subcurrid4 = m_tree->AppendItem(currid,
672                                 wxT("Components"),
673                                 image, imageSel,
674                                 new OPJMarkerData(wxT("INFO"))
675                                 );
676
677                         image = m_tree->TreeCtrlIcon_File;
678                         imageSel = image + 1;
679
680                         for (c = 0; c < csiz; c++) {
681
682                                 wxTreeItemId subcurrid5 = m_tree->AppendItem(subcurrid4,
683                                         wxString::Format(wxT("#%d: %dx%d, %d%s bpp"),
684                                         c,
685                                         xsiz/xrsiz[c], ysiz/yrsiz[c],
686                                         ((ssiz[c] & 0x7F) + 1),
687                                         (ssiz[c] & 0x80) ? wxT("s") : wxT("u")),
688                                         image, imageSel,
689                                         new OPJMarkerData(wxT("INFO"))
690                                         );
691
692                         }
693
694                         };
695                         break;
696
697                 /////////
698                 // SOT //
699                 /////////
700                 case SOT_VAL:
701                         {
702                         if (m_file->Read(twobytes, 2) != 2)
703                                 break;
704                         unsigned short int isot = STREAM_TO_UINT16(twobytes, 0);
705
706                         if (m_file->Read(fourbytes, 4) != 4)
707                                 break;
708                         unsigned long int psot = STREAM_TO_UINT32(fourbytes, 0);
709
710                         if (m_file->Read(onebyte, 1) != 1)
711                                 break;
712                         unsigned char tpsot = onebyte[0];
713
714                         if (m_file->Read(onebyte, 1) != 1)
715                                 break;
716                         unsigned char tnsot = onebyte[0];
717
718                         wxTreeItemId subcurrid3 = m_tree->AppendItem(currid,
719                                 wxString::Format(wxT("tile %d, psot = %d, part %d of %d"), isot, psot, tpsot, tnsot),
720                                 image, imageSel,
721                                 new OPJMarkerData(wxT("INFO"))
722                                 );
723
724                         lastPsot = psot;
725                         lastsotpos = offset;
726                         inside_sod = 0;
727                         };
728                         break;
729
730                 /////////
731                 // COC //
732                 /////////
733                 case COC_VAL:
734                         {
735                         unsigned short int ccoc;
736                         if (csiz < 257) {
737                                 if (m_file->Read(onebyte, 1) != 1)
738                                         break;
739                                 ccoc = onebyte[0];
740                         } else {
741                                 if (m_file->Read(twobytes, 2) != 2)
742                                         break;
743                                 ccoc = STREAM_TO_UINT16(twobytes, 0);
744                         }
745
746                         if (m_file->Read(onebyte, 1) != 1)
747                                 break;
748                         unsigned char scoc = onebyte[0];
749
750                         wxTreeItemId subcurrid = m_tree->AppendItem(currid,
751                                 wxString::Format(wxT("Comp. no. %d"), ccoc),
752                                 image, imageSel,
753                                 new OPJMarkerData(wxT("INFO"))
754                                 );
755                         
756                         wxString text;
757                         if (scoc & 0x01)
758                                 text << wxT("Partitioned entropy coder");
759                         else
760                                 text << wxT("Unpartitioned entropy coder");
761
762                         subcurrid = m_tree->AppendItem(currid,
763                                 text,
764                                 image, imageSel,
765                                 new OPJMarkerData(wxT("INFO"))
766                                 );
767
768                         if (m_file->Read(onebyte, 1) != 1)
769                                 break;
770                         unsigned char decomplevs = onebyte[0];
771
772                         if (m_file->Read(onebyte, 1) != 1)
773                                 break;
774                         unsigned char cbswidth = onebyte[0];
775
776                         if (m_file->Read(onebyte, 1) != 1)
777                                 break;
778                         unsigned char cbsheight = onebyte[0];
779
780                         if (m_file->Read(onebyte, 1) != 1)
781                                 break;
782                         unsigned char cbstyle = onebyte[0];
783
784                         if (m_file->Read(onebyte, 1) != 1)
785                                 break;
786                         unsigned char transform = onebyte[0];
787
788                         subcurrid = m_tree->AppendItem(currid,
789                                 wxString::Format(wxT("%d levels (%d resolutions)"), decomplevs, decomplevs + 1),
790                                 image, imageSel,
791                                 new OPJMarkerData(wxT("INFO"))
792                                 );
793
794                         if (transform & 0x01)
795                                 text = wxT("5-3 reversible wavelet");
796                         else
797                                 text = wxT("9-7 irreversible wavelet");
798                         subcurrid = m_tree->AppendItem(currid,
799                                 text,
800                                 image, imageSel,
801                                 new OPJMarkerData(wxT("INFO"))
802                                 );
803
804                         subcurrid = m_tree->AppendItem(currid,
805                                 wxString::Format(wxT("Code-blocks: %dx%d"), 1 << ((cbswidth & 0x0F) + 2), 1 << ((cbsheight & 0x0F) + 2)),
806                                 image, imageSel,
807                                 new OPJMarkerData(wxT("INFO"))
808                                 );
809
810                         image = m_tree->TreeCtrlIcon_Folder;
811                         imageSel = image + 1;
812
813                         wxTreeItemId subcurrid3 = m_tree->AppendItem(currid,
814                                 wxT("Coding styles"),
815                                 image, imageSel,
816                                 new OPJMarkerData(wxT("INFO"))
817                                 );
818
819                         image = m_tree->TreeCtrlIcon_File;
820                         imageSel = image + 1;
821
822                         if (cbstyle & 0x01)
823                                 text = wxT("Selective arithmetic coding bypass");
824                         else
825                                 text = wxT("No selective arithmetic coding bypass");
826                         wxTreeItemId subcurrid4 = m_tree->AppendItem(subcurrid3,
827                                 text,
828                                 image, imageSel,
829                                 new OPJMarkerData(wxT("INFO"))
830                                 );
831
832                         if (cbstyle & 0x02)
833                                 text = wxT("Reset context probabilities on coding pass boundaries");
834                         else
835                                 text = wxT("No reset of context probabilities on coding pass boundaries");
836                         subcurrid4 = m_tree->AppendItem(subcurrid3,
837                                 text,
838                                 image, imageSel,
839                                 new OPJMarkerData(wxT("INFO"))
840                                 );
841
842                         if (cbstyle & 0x04)
843                                 text = wxT("Termination on each coding passs");
844                         else
845                                 text = wxT("No termination on each coding pass");
846                         subcurrid4 = m_tree->AppendItem(subcurrid3,
847                                 text,
848                                 image, imageSel,
849                                 new OPJMarkerData(wxT("INFO"))
850                                 );
851
852                         if (cbstyle & 0x08)
853                                 text = wxT("Vertically stripe causal context");
854                         else
855                                 text = wxT("No vertically stripe causal context");
856                         subcurrid4 = m_tree->AppendItem(subcurrid3,
857                                 text,
858                                 image, imageSel,
859                                 new OPJMarkerData(wxT("INFO"))
860                                 );
861
862                         if (cbstyle & 0x10)
863                                 text = wxT("Predictable termination");
864                         else
865                                 text = wxT("No predictable termination");
866                         subcurrid4 = m_tree->AppendItem(subcurrid3,
867                                 text,
868                                 image, imageSel,
869                                 new OPJMarkerData(wxT("INFO"))
870                                 );
871
872                         if (cbstyle & 0x20)
873                                 text = wxT("Segmentation symbols are used");
874                         else
875                                 text = wxT("No segmentation symbols are used");
876                         subcurrid4 = m_tree->AppendItem(subcurrid3,
877                                 text,
878                                 image, imageSel,
879                                 new OPJMarkerData(wxT("INFO"))
880                                 );
881
882                         }
883                         break;
884
885                 /////////
886                 // COD //
887                 /////////
888                 case COD_VAL:
889                         {
890                         if (m_file->Read(onebyte, 1) != 1)
891                                 break;
892                         unsigned char scod = onebyte[0];
893
894                         wxString text;
895
896                         if (scod & 0x01)
897                                 text << wxT("Partitioned entropy coder");
898                         else
899                                 text << wxT("Unpartitioned entropy coder");
900
901                         wxTreeItemId subcurrid3 = m_tree->AppendItem(currid,
902                                 text,
903                                 image, imageSel,
904                                 new OPJMarkerData(wxT("INFO"))
905                                 );
906
907                         text = wxT("");
908                         if (scod & 0x02)
909                                 text << wxT("Possible SOPs");
910                         else
911                                 text << wxT("No SOPs");
912
913                         if (scod & 0x04)
914                                 text << wxT(", possible EPHs");
915                         else
916                                 text << wxT(", no EPHs");
917
918                         subcurrid3 = m_tree->AppendItem(currid,
919                                 text,
920                                 image, imageSel,
921                                 new OPJMarkerData(wxT("INFO"))
922                                 );
923
924                         if (m_file->Read(onebyte, 1) != 1)
925                                 break;
926                         unsigned char progord = onebyte[0];
927
928                         if (m_file->Read(twobytes, 2) != 2)
929                                 break;
930                         unsigned short int numlayers = STREAM_TO_UINT16(twobytes, 0);
931
932                         if (m_file->Read(onebyte, 1) != 1)
933                                 break;
934                         unsigned char mctransform = onebyte[0];
935
936                         if (m_file->Read(onebyte, 1) != 1)
937                                 break;
938                         unsigned char decomplevs = onebyte[0];
939
940                         if (m_file->Read(onebyte, 1) != 1)
941                                 break;
942                         unsigned char cbswidth = onebyte[0];
943
944                         if (m_file->Read(onebyte, 1) != 1)
945                                 break;
946                         unsigned char cbsheight = onebyte[0];
947
948                         if (m_file->Read(onebyte, 1) != 1)
949                                 break;
950                         unsigned char cbstyle = onebyte[0];
951
952                         if (m_file->Read(onebyte, 1) != 1)
953                                 break;
954                         unsigned char transform = onebyte[0];
955
956                         subcurrid3 = m_tree->AppendItem(currid,
957                                 wxString::Format(wxT("%d levels (%d resolutions)"), decomplevs, decomplevs + 1),
958                                 image, imageSel,
959                                 new OPJMarkerData(wxT("INFO"))
960                                 );
961
962                         text = wxT("");
963                         switch (progord) {
964                         case (0):
965                                 text << wxT("LRCP");
966                                 break;
967                         case (1):
968                                 text << wxT("RLCP");
969                                 break;
970                         case (2):
971                                 text << wxT("LRCP");
972                                 break;
973                         case (3):
974                                 text << wxT("RPCL");
975                                 break;
976                         case (4):
977                                 text << wxT("CPRL");
978                                 break;
979                         default:
980                                 text << wxT("unknown progression");
981                                 break;
982                         }
983                         text << wxString::Format(wxT(", %d layers"), numlayers);
984                         if (transform & 0x01)
985                                 text << wxT(", 5-3 rev.");
986                         else
987                                 text << wxT(", 9-7 irr.");
988                         subcurrid3 = m_tree->AppendItem(currid,
989                                 text,
990                                 image, imageSel,
991                                 new OPJMarkerData(wxT("INFO"))
992                                 );
993
994                         subcurrid3 = m_tree->AppendItem(currid,
995                                 wxString::Format(wxT("Code-blocks: %dx%d"), 1 << ((cbswidth & 0x0F) + 2), 1 << ((cbsheight & 0x0F) + 2)),
996                                 image, imageSel,
997                                 new OPJMarkerData(wxT("INFO"))
998                                 );
999
1000                         switch (mctransform) {
1001                         case (0):
1002                                 {
1003                                 text = wxT("No MCT");
1004                                 }
1005                                 break;
1006                         case (1):
1007                                 {
1008                                 text = wxT("Reversible MCT on 0, 1, 2");
1009                                 }
1010                                 break;
1011                         case (2):
1012                                 {
1013                                 text = wxT("Irreversible MCT on 0, 1, 2");
1014                                 }
1015                                 break;
1016                         default:
1017                                 {
1018                                 text = wxT("Unknown");
1019                                 }
1020                                 break;
1021                         };
1022                         subcurrid3 = m_tree->AppendItem(currid,
1023                                 text,
1024                                 image, imageSel,
1025                                 new OPJMarkerData(wxT("INFO"))
1026                                 );
1027
1028
1029                         image = m_tree->TreeCtrlIcon_Folder;
1030                         imageSel = image + 1;
1031
1032                         subcurrid3 = m_tree->AppendItem(currid,
1033                                 wxT("Coding styles"),
1034                                 image, imageSel,
1035                                 new OPJMarkerData(wxT("INFO"))
1036                                 );
1037
1038                         image = m_tree->TreeCtrlIcon_File;
1039                         imageSel = image + 1;
1040
1041                         if (cbstyle & 0x01)
1042                                 text = wxT("Selective arithmetic coding bypass");
1043                         else
1044                                 text = wxT("No selective arithmetic coding bypass");
1045                         wxTreeItemId subcurrid4 = m_tree->AppendItem(subcurrid3,
1046                                 text,
1047                                 image, imageSel,
1048                                 new OPJMarkerData(wxT("INFO"))
1049                                 );
1050
1051                         if (cbstyle & 0x02)
1052                                 text = wxT("Reset context probabilities on coding pass boundaries");
1053                         else
1054                                 text = wxT("No reset of context probabilities on coding pass boundaries");
1055                         subcurrid4 = m_tree->AppendItem(subcurrid3,
1056                                 text,
1057                                 image, imageSel,
1058                                 new OPJMarkerData(wxT("INFO"))
1059                                 );
1060
1061                         if (cbstyle & 0x04)
1062                                 text = wxT("Termination on each coding passs");
1063                         else
1064                                 text = wxT("No termination on each coding pass");
1065                         subcurrid4 = m_tree->AppendItem(subcurrid3,
1066                                 text,
1067                                 image, imageSel,
1068                                 new OPJMarkerData(wxT("INFO"))
1069                                 );
1070
1071                         if (cbstyle & 0x08)
1072                                 text = wxT("Vertically stripe causal context");
1073                         else
1074                                 text = wxT("No vertically stripe causal context");
1075                         subcurrid4 = m_tree->AppendItem(subcurrid3,
1076                                 text,
1077                                 image, imageSel,
1078                                 new OPJMarkerData(wxT("INFO"))
1079                                 );
1080
1081                         if (cbstyle & 0x10)
1082                                 text = wxT("Predictable termination");
1083                         else
1084                                 text = wxT("No predictable termination");
1085                         subcurrid4 = m_tree->AppendItem(subcurrid3,
1086                                 text,
1087                                 image, imageSel,
1088                                 new OPJMarkerData(wxT("INFO"))
1089                                 );
1090
1091                         if (cbstyle & 0x20)
1092                                 text = wxT("Segmentation symbols are used");
1093                         else
1094                                 text = wxT("No segmentation symbols are used");
1095                         subcurrid4 = m_tree->AppendItem(subcurrid3,
1096                                 text,
1097                                 image, imageSel,
1098                                 new OPJMarkerData(wxT("INFO"))
1099                                 );
1100
1101                         };
1102                         break;
1103
1104                 /////////
1105                 // QCC //
1106                 /////////
1107                 case QCC_VAL:
1108                         {
1109                         unsigned short int cqcc;
1110                         if (csiz < 257) {
1111                                 if (m_file->Read(onebyte, 1) != 1)
1112                                         break;
1113                                 cqcc = onebyte[0];
1114                         } else {
1115                                 if (m_file->Read(twobytes, 2) != 2)
1116                                         break;
1117                                 cqcc = STREAM_TO_UINT16(twobytes, 0);
1118                         }
1119
1120                         wxTreeItemId subcurrid = m_tree->AppendItem(currid,
1121                                 wxString::Format(wxT("Comp. no. %d"), cqcc),
1122                                 image, imageSel,
1123                                 new OPJMarkerData(wxT("INFO"))
1124                                 );
1125                         
1126                         if (m_file->Read(onebyte, 1) != 1)
1127                                 break;
1128                         unsigned char sqcc = onebyte[0];
1129
1130                         wxString text;
1131                         switch (sqcc & 0x1F) {
1132                         case (0):
1133                                 text = wxT("No quantization");
1134                                 break;
1135                         case (1):
1136                                 text = wxT("Scalar implicit");
1137                                 break;
1138                         case (2):
1139                                 text = wxT("Scalar explicit");
1140                                 break;
1141                         default:
1142                                 text = wxT("Unknown");
1143                                 break;
1144                         }
1145                         text << wxString::Format(wxT(", %d guard bits"), (sqcc & 0xE0) >> 5);
1146                         wxTreeItemId subcurrid3 = m_tree->AppendItem(currid,
1147                                 text,
1148                                 image, imageSel,
1149                                 new OPJMarkerData(wxT("INFO"))
1150                                 );
1151
1152                         }
1153                         break;
1154
1155                 /////////
1156                 // QCD //
1157                 /////////
1158                 case QCD_VAL:
1159                         {
1160                         if (m_file->Read(onebyte, 1) != 1)
1161                                 break;
1162                         unsigned char sqcd = onebyte[0];
1163
1164                         wxString text;
1165                         switch (sqcd & 0x1F) {
1166                         case (0):
1167                                 text = wxT("No quantization");
1168                                 break;
1169                         case (1):
1170                                 text = wxT("Scalar implicit");
1171                                 break;
1172                         case (2):
1173                                 text = wxT("Scalar explicit");
1174                                 break;
1175                         default:
1176                                 text = wxT("Unknown");
1177                                 break;
1178                         }
1179                         text << wxString::Format(wxT(", %d guard bits"), (sqcd & 0xE0) >> 5);
1180                         wxTreeItemId subcurrid3 = m_tree->AppendItem(currid,
1181                                 text,
1182                                 image, imageSel,
1183                                 new OPJMarkerData(wxT("INFO"))
1184                                 );
1185
1186                         };
1187                         break;
1188
1189                 /////////
1190                 // COM //
1191                 /////////
1192                 case COM_VAL:
1193                         {
1194                         #define showlen 25
1195                         char comment[showlen];
1196                         wxString comments;
1197
1198                         if (m_file->Read(twobytes, 2) != 2)
1199                                 break;
1200                         unsigned short int rcom = STREAM_TO_UINT16(twobytes, 0);
1201
1202                         wxString text;
1203                         if (rcom == 0)
1204                                 text = wxT("Binary values");
1205                         else if (rcom == 1)
1206                                 text = wxT("ISO 8859-1 (latin-1) values");
1207                         else if (rcom < 65535)
1208                                 text = wxT("Reserved for registration");
1209                         else
1210                                 text = wxT("Reserved for extension");
1211                         wxTreeItemId subcurrid3 = m_tree->AppendItem(currid,
1212                                 text,
1213                                 image, imageSel,
1214                                 new OPJMarkerData(wxT("INFO"))
1215                                 );
1216
1217                         if (m_file->Read(comment, showlen) != showlen)
1218                                 break;
1219                         comments = wxString::FromAscii(comment).Truncate(wxMin(showlen, currlen - 4));
1220                         if ((currlen - 4) > showlen)
1221                                 comments << wxT("...");
1222                         subcurrid3 = m_tree->AppendItem(currid,
1223                                 comments,
1224                                 image, imageSel,
1225                                 new OPJMarkerData(wxT("INFO"))
1226                                 );
1227                         };
1228                         break;
1229
1230                 /////////
1231                 // TLM //
1232                 /////////
1233                 case TLM_VAL:
1234                         {
1235                         if (m_file->Read(onebyte, 1) != 1)
1236                                 break;
1237                         unsigned char ztlm = onebyte[0];
1238
1239                         if (m_file->Read(onebyte, 1) != 1)
1240                                 break;
1241                         unsigned char stlm = onebyte[0];
1242
1243                         image = m_tree->TreeCtrlIcon_File;
1244                         imageSel = image + 1;
1245
1246                         wxTreeItemId subcurrid3 = m_tree->AppendItem(currid,
1247                                 wxString::Format(wxT("TLM #%d"), ztlm),
1248                                 image, imageSel,
1249                                 new OPJMarkerData(wxT("INFO"))
1250                                 );
1251
1252                         subcurrid3 = m_tree->AppendItem(currid,
1253                                 wxString::Format(wxT("%d bits/index, %d bits/length"),
1254                                 8 * ((stlm & 0x30) >> 4), 16 + 16 * ((stlm & 0x40) >> 6)),
1255                                 image, imageSel,
1256                                 new OPJMarkerData(wxT("INFO"))
1257                                 );
1258
1259                         int n, numparts;
1260
1261                         numparts = (currlen - 2) / ( ((stlm & 0x30) >> 4) + 2 + 2 * ((stlm & 0x40) >> 6));
1262
1263                         image = m_tree->TreeCtrlIcon_Folder;
1264                         imageSel = image + 1;
1265
1266                         subcurrid3 = m_tree->AppendItem(currid,
1267                                 wxT("Tile parts"),
1268                                 image, imageSel,
1269                                 new OPJMarkerData(wxT("INFO"))
1270                                 );
1271
1272                         image = m_tree->TreeCtrlIcon_File;
1273                         imageSel = image + 1;
1274
1275                         for (n = 0; n < numparts; n++) {
1276
1277                                 unsigned short int ttlm;
1278                                 unsigned long int ptlm;
1279
1280                                 switch (((stlm & 0x30) >> 4)) {
1281
1282                                 case 0:
1283                                         ttlm = 0;
1284                                         break;
1285
1286                                 case 1:
1287                                         if (m_file->Read(onebyte, 1) != 1)
1288                                                 break;
1289                                         ttlm = onebyte[0];
1290                                         break;
1291
1292                                 case 2:
1293                                         if (m_file->Read(twobytes, 2) != 2)
1294                                                 break;
1295                                         ttlm = STREAM_TO_UINT16(twobytes, 0);
1296                                         break;
1297
1298                                 }
1299
1300                                 switch (((stlm & 0x40) >> 6)) {
1301
1302                                 case 0:
1303                                         if (m_file->Read(twobytes, 2) != 2)
1304                                                 break;
1305                                         ptlm = STREAM_TO_UINT16(twobytes, 0);
1306                                         break;
1307
1308                                 case 1:
1309                                         if (m_file->Read(fourbytes, 4) != 4)
1310                                                 break;
1311                                         ptlm = STREAM_TO_UINT32(fourbytes, 0);
1312                                         break;
1313
1314                                 }
1315
1316                                 wxTreeItemId subcurrid4 = m_tree->AppendItem(subcurrid3,
1317                                         wxString::Format(wxT("Tile %d: %d bytes"), ttlm, ptlm),
1318                                         image, imageSel,
1319                                         new OPJMarkerData(wxT("INFO"))
1320                                         );
1321
1322                         }
1323
1324                         }
1325                         break;
1326
1327                 /////////
1328                 // POD //
1329                 /////////
1330                 case POD_VAL:
1331                         {
1332                         int n, numchanges;
1333
1334                         if (csiz < 257)
1335                                 numchanges = (currlen - 2) / 7;
1336                         else
1337                                 numchanges = (currlen - 2) / 9;
1338
1339                         for (n = 0; n < numchanges; n++) {
1340
1341                                 image = m_tree->TreeCtrlIcon_Folder;
1342                                 imageSel = image + 1;
1343
1344                                 wxTreeItemId subcurrid3 = m_tree->AppendItem(currid,
1345                                         wxString::Format(wxT("Change #%d"), n),
1346                                         image, imageSel,
1347                                         new OPJMarkerData(wxT("INFO"))
1348                                         );
1349
1350                                 if (m_file->Read(onebyte, 1) != 1)
1351                                         break;
1352                                 unsigned char rspod = onebyte[0];
1353
1354                                 unsigned short int cspod;
1355                                 if (csiz < 257) {
1356                                         if (m_file->Read(onebyte, 1) != 1)
1357                                                 break;
1358                                         cspod = onebyte[0];
1359                                 } else {
1360                                         if (m_file->Read(twobytes, 2) != 2)
1361                                                 break;
1362                                         cspod = STREAM_TO_UINT16(twobytes, 0);
1363                                 }
1364
1365                                 if (m_file->Read(twobytes, 2) != 2)
1366                                         break;
1367                                 unsigned short int lyepod = STREAM_TO_UINT16(twobytes, 0);
1368
1369                                 if (m_file->Read(onebyte, 1) != 1)
1370                                         break;
1371                                 unsigned char repod = onebyte[0];
1372
1373                                 unsigned short int cepod;
1374                                 if (csiz < 257) {
1375                                         if (m_file->Read(onebyte, 1) != 1)
1376                                                 break;
1377                                         cepod = onebyte[0];
1378                                 } else {
1379                                         if (m_file->Read(twobytes, 2) != 2)
1380                                                 break;
1381                                         cepod = STREAM_TO_UINT16(twobytes, 0);
1382                                 }
1383
1384                                 if (m_file->Read(onebyte, 1) != 1)
1385                                         break;
1386                                 unsigned char ppod = onebyte[0];
1387
1388                                 image = m_tree->TreeCtrlIcon_File;
1389                                 imageSel = image + 1;
1390
1391                                 wxTreeItemId subcurrid4 = m_tree->AppendItem(subcurrid3,
1392                                         wxString::Format(wxT("%d <= Resolution < %d"), rspod, repod),
1393                                         image, imageSel,
1394                                         new OPJMarkerData(wxT("INFO"))
1395                                         );
1396
1397                                 subcurrid4 = m_tree->AppendItem(subcurrid3,
1398                                         wxString::Format(wxT("%d <= Component < %d"), cspod, cepod),
1399                                         image, imageSel,
1400                                         new OPJMarkerData(wxT("INFO"))
1401                                         );
1402
1403                                 subcurrid4 = m_tree->AppendItem(subcurrid3,
1404                                         wxString::Format(wxT("0 <= Layer < %d"), lyepod),
1405                                         image, imageSel,
1406                                         new OPJMarkerData(wxT("INFO"))
1407                                         );
1408
1409                                 wxString text = wxT("");
1410                                 switch (ppod) {
1411                                 case (0):
1412                                         text << wxT("LRCP");
1413                                         break;
1414                                 case (1):
1415                                         text << wxT("RLCP");
1416                                         break;
1417                                 case (2):
1418                                         text << wxT("LRCP");
1419                                         break;
1420                                 case (3):
1421                                         text << wxT("RPCL");
1422                                         break;
1423                                 case (4):
1424                                         text << wxT("CPRL");
1425                                         break;
1426                                 default:
1427                                         text << wxT("unknown progression");
1428                                         break;
1429                                 }
1430                                 subcurrid4 = m_tree->AppendItem(subcurrid3,
1431                                         text,
1432                                         image, imageSel,
1433                                         new OPJMarkerData(wxT("INFO"))
1434                                         );
1435                         }
1436
1437                         }
1438                         break;
1439
1440                 /////////
1441                 // SOD //
1442                 /////////
1443                 case SOD_VAL:
1444                         {
1445                         inside_sod = 1;
1446                         };
1447                         break;
1448
1449                 default:
1450                         break;
1451                         
1452                 }
1453                                                                 
1454                 // increment number of markers
1455                 if (nmarks++ >= maxmarks) {
1456                         WriteText(wxT("Maximum amount of markers exceeded"));
1457                         break;
1458                 }
1459
1460                 // advance position
1461                 OPJ_ADVANCE(currlen + 2);
1462         }       
1463
1464         WriteText(wxT("Search finished"));
1465 }