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