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 /* defines */
29 #define SHORT_DESCR_LEN 32
30 #define LONG_DESCR_LEN 256
31
32 /* enumeration for file formats */
33 #define J2FILENUM 4
34 typedef enum {
35
36 JP2_FILE,
37 J2K_FILE,
38 MJ2_FILE,
39 UNK_FILE
40
41 } j2filetype;
42
43 /* enumeration for the box types */
44 #define j22boxNUM 23
45 typedef enum {
46
47 FILE_BOX,
48 JP_BOX,
49 FTYP_BOX,
50 JP2H_BOX,
51 IHDR_BOX,
52 COLR_BOX,
53 JP2C_BOX,
54 JP2I_BOX,
55 XML_BOX,
56 UUID_BOX,
57 UINF_BOX,
58 MOOV_BOX,
59 MVHD_BOX,
60 TRAK_BOX,
61 TKHD_BOX,
62 MDIA_BOX,
63 MDHD_BOX,
64 HDLR_BOX,
65 MINF_BOX,
66 VMHD_BOX,
67 STBL_BOX,
68 STSD_BOX,
69 STSZ_BOX,
70 MJP2_BOX,
71 MDAT_BOX,
72 ANY_BOX,
73 UNK_BOX
74
75 } j22boxtype;
76
77 /* the box structure itself */
78 struct boxdef {
79
80 char value[5]; /* hexadecimal value/string*/
81 char name[SHORT_DESCR_LEN]; /* short description */
82 char descr[LONG_DESCR_LEN]; /* long description */
83 int sbox; /* is it a superbox? */
84 int req[J2FILENUM]; /* mandatory box */
85 j22boxtype ins; /* contained in box... */
86
87 };
88
89
90 /* jp2 family box signatures */
91 #define FILE_SIGN ""
92 #define JP_SIGN "jP\040\040"
93 #define FTYP_SIGN "ftyp"
94 #define JP2H_SIGN "jp2h"
95 #define IHDR_SIGN "ihdr"
96 #define COLR_SIGN "colr"
97 #define JP2C_SIGN "jp2c"
98 #define JP2I_SIGN "jp2i"
99 #define XML_SIGN "xml\040"
100 #define UUID_SIGN "uuid"
101 #define UINF_SIGN "uinf"
102 #define MOOV_SIGN "moov"
103 #define MVHD_SIGN "mvhd"
104 #define TRAK_SIGN "trak"
105 #define TKHD_SIGN "tkhd"
106 #define MDIA_SIGN "mdia"
107 #define MDHD_SIGN "mdhd"
108 #define HDLR_SIGN "hdlr"
109 #define MINF_SIGN "minf"
110 #define VMHD_SIGN "vmhd"
111 #define STBL_SIGN "stbl"
112 #define STSD_SIGN "stsd"
113 #define STSZ_SIGN "stsz"
114 #define MJP2_SIGN "mjp2"
115 #define MDAT_SIGN "mdat"
116 #define ANY_SIGN ""
117 #define UNK_SIGN ""
118
119 /* the possible boxes */
120 struct boxdef j22box[] =
121 {
122 /* sign */ {FILE_SIGN,
123 /* short */ "placeholder for nothing",
124 /* long */ "Nothing to say",
125 /* sbox */ 0,
126 /* req */ {1, 1, 1},
127 /* ins */ FILE_BOX},
128
129 /* sign */ {JP_SIGN,
130 /* short */ "JPEG 2000 Signature box",
131 /* long */ "This box uniquely identifies the file as being part of the JPEG 2000 family of files",
132 /* sbox */ 0,
133 /* req */ {1, 1, 1},
134 /* ins */ FILE_BOX},
135
136 /* sign */ {FTYP_SIGN,
137 /* short */ "File Type box",
138 /* long */ "This box specifies file type, version and compatibility information, including specifying if this file "
139 "is a conforming JP2 file or if it can be read by a conforming JP2 reader",
140 /* sbox */ 0,
141 /* req */ {1, 1, 1},
142 /* ins */ FILE_BOX},
143
144 /* sign */ {JP2H_SIGN,
145 /* short */ "JP2 Header box",
146 /* long */ "This box contains a series of boxes that contain header-type information about the file",
147 /* sbox */ 1,
148 /* req */ {1, 1, 1},
149 /* ins */ FILE_BOX},
150
151 /* sign */ {IHDR_SIGN,
152 /* short */ "Image Header box",
153 /* long */ "This box specifies the size of the image and other related fields",
154 /* sbox */ 0,
155 /* req */ {1, 1, 1},
156 /* ins */ JP2H_BOX},
157
158 /* sign */ {COLR_SIGN,
159 /* short */ "Colour Specification box",
160 /* long */ "This box specifies the colourspace of the image",
161 /* sbox */ 0,
162 /* req */ {1, 1, 1},
163 /* ins */ JP2H_BOX},
164
165 /* sign */ {JP2C_SIGN,
166 /* short */ "Contiguous Codestream box",
167 /* long */ "This box contains the codestream as defined by Annex A",
168 /* sbox */ 0,
169 /* req */ {1, 1, 1},
170 /* ins */ FILE_BOX},
171
172 /* sign */ {JP2I_SIGN,
173 /* short */ "Intellectual Property box",
174 /* long */ "This box contains intellectual property information about the image",
175 /* sbox */ 0,
176 /* req */ {0, 0, 0},
177 /* ins */ FILE_BOX},
178
179 /* sign */ {XML_SIGN,
180 /* short */ "XML box",
181 /* long */ "This box provides a tool by which vendors can add XML formatted information to a JP2 file",
182 /* sbox */ 0,
183 /* req */ {0, 0, 0},
184 /* ins */ FILE_BOX},
185
186 /* sign */ {UUID_SIGN,
187 /* short */ "UUID box",
188 /* long */ "This box provides a tool by which vendors can add additional information to a file "
189 "without risking conflict with other vendors",
190 /* sbox */ 0,
191 /* req */ {0, 0, 0},
192 /* ins */ FILE_BOX},
193
194 /* sign */ {UINF_SIGN,
195 /* short */ "UUID Info box",
196 /* long */ "This box provides a tool by which a vendor may provide access to additional information associated with a UUID",
197 /* sbox */ 0,
198 /* req */ {0, 0, 0},
199 /* ins */ FILE_BOX},
200
201 /* sign */ {MOOV_SIGN,
202 /* short */ "Movie box",
203 /* long */ "This box contains the media data. In video tracks, this box would contain JPEG2000 video frames",
204 /* sbox */ 1,
205 /* req */ {1, 1, 1},
206 /* ins */ FILE_BOX},
207
208 /* sign */ {MVHD_SIGN,
209 /* short */ "Movie Header box",
210 /* long */ "This box defines overall information which is media-independent, and relevant to the entire presentation "
211 "considered as a whole",
212 /* sbox */ 0,
213 /* req */ {1, 1, 1},
214 /* ins */ MOOV_BOX},
215
216 /* sign */ {TRAK_SIGN,
217 /* short */ "Track box",
218 /* long */ "This is a container box for a single track of a presentation. A presentation may consist of one or more tracks",
219 /* sbox */ 1,
220 /* req */ {1, 1, 1},
221 /* ins */ MOOV_BOX},
222
223 /* sign */ {TKHD_SIGN,
224 /* short */ "Track Header box",
225 /* long */ "This box specifies the characteristics of a single track. Exactly one Track Header Box is contained in a track",
226 /* sbox */ 0,
227 /* req */ {1, 1, 1},
228 /* ins */ TRAK_BOX},
229
230 /* sign */ {MDIA_SIGN,
231 /* short */ "Media box",
232 /* long */ "The media declaration container contains all the objects which declare information about the media data "
233 "within a track",
234 /* sbox */ 1,
235 /* req */ {1, 1, 1},
236 /* ins */ TRAK_BOX},
237
238 /* sign */ {MDHD_SIGN,
239 /* short */ "Media Header box",
240 /* long */ "The media header declares overall information which is media-independent, and relevant to characteristics "
241 "of the media in a track",
242 /* sbox */ 0,
243 /* req */ {1, 1, 1},
244 /* ins */ MDIA_BOX},
245
246 /* sign */ {HDLR_SIGN,
247 /* short */ "Handler Reference box",
248 /* long */ "This box within a Media Box declares the process by which the media-data in the track may be presented, "
249 "and thus, the nature of the media in a track",
250 /* sbox */ 0,
251 /* req */ {1, 1, 1},
252 /* ins */ MDIA_BOX},
253
254 /* sign */ {MINF_SIGN,
255 /* short */ "Media Information box",
256 /* long */ "This box contains all the objects which declare characteristic information of the media in the track",
257 /* sbox */ 1,
258 /* req */ {1, 1, 1},
259 /* ins */ MDIA_BOX},
260
261 /* sign */ {VMHD_SIGN,
262 /* short */ "Video Media Header box",
263 /* long */ "The video media header contains general presentation information, independent of the coding, for video media",
264 /* sbox */ 0,
265 /* req */ {1, 1, 1},
266 /* ins */ MINF_BOX},
267
268 /* sign */ {STBL_SIGN,
269 /* short */ "Sample Table box",
270 /* long */ "The sample table contains all the time and data indexing of the media samples in a track",
271 /* sbox */ 1,
272 /* req */ {1, 1, 1},
273 /* ins */ MINF_BOX},
274
275 /* sign */ {STSD_SIGN,
276 /* short */ "STSD Sample Description box",
277 /* long */ "The sample description table gives detailed information about the coding type used, and any initialization "
278 "information needed for that coding",
279 /* sbox */ 0,
280 /* req */ {1, 1, 1},
281 /* ins */ MINF_BOX},
282
283 /* sign */ {STSZ_SIGN,
284 /* short */ "Sample Size box",
285 /* long */ "This box contains the sample count and a table giving the size of each sample",
286 /* sbox */ 0,
287 /* req */ {1, 1, 1},
288 /* ins */ STBL_BOX},
289
290 /* sign */ {MJP2_SIGN,
291 /* short */ "MJP2 Sample Description box",
292 /* long */ "The MJP2 sample description table gives detailed information about the coding type used, and any initialization "
293 "information needed for that coding",
294 /* sbox */ 0,
295 /* req */ {1, 1, 1},
296 /* ins */ MINF_BOX},
297
298 /* sign */ {MDAT_SIGN,
299 /* short */ "Media Data box",
300 /* long */ "The meta-data for a presentation is stored in the single Movie Box which occurs at the top-level of a file",
301 /* sbox */ 1,
302 /* req */ {1, 1, 1},
303 /* ins */ FILE_BOX},
304
305 /* sign */ {ANY_SIGN,
306 /* short */ "Any box",
307 /* long */ "All the existing boxes",
308 /* sbox */ 0,
309 /* req */ {0, 0, 0},
310 /* ins */ FILE_BOX},
311
312 /* sign */ {UNK_SIGN,
313 /* short */ "Unknown Type box",
314 /* long */ "The signature is not recognised to be that of an existing box",
315 /* sbox */ 0,
316 /* req */ {0, 0, 0},
317 /* ins */ ANY_BOX}
318
319 };
320
321
322 /* macro functions */
323 /* From little endian to big endian, 2 and 4 bytes */
324 #define BYTE_SWAP2(X) ((X & 0x00FF) << 8) | ((X & 0xFF00) >> 8)
325 #define BYTE_SWAP4(X) ((X & 0x000000FF) << 24) | ((X & 0x0000FF00) << 8) | ((X & 0x00FF0000) >> 8) | ((X & 0xFF000000) >> 24)
326
327 #ifdef __WXGTK__
328 #define BYTE_SWAP8(X) ((X & 0x00000000000000FFULL) << 56) | ((X & 0x000000000000FF00ULL) << 40) | \
329 ((X & 0x0000000000FF0000ULL) << 24) | ((X & 0x00000000FF000000ULL) << 8) | \
330 ((X & 0x000000FF00000000ULL) >> 8) | ((X & 0x0000FF0000000000ULL) >> 24) | \
331 ((X & 0x00FF000000000000ULL) >> 40) | ((X & 0xFF00000000000000ULL) >> 56)
332 #else
333 #define BYTE_SWAP8(X) ((X & 0x00000000000000FF) << 56) | ((X & 0x000000000000FF00) << 40) | \
334 ((X & 0x0000000000FF0000) << 24) | ((X & 0x00000000FF000000) << 8) | \
335 ((X & 0x000000FF00000000) >> 8) | ((X & 0x0000FF0000000000) >> 24) | \
336 ((X & 0x00FF000000000000) >> 40) | ((X & 0xFF00000000000000) >> 56)
337 #endif
338
339 /* From codestream to int values */
340 #define STREAM_TO_UINT32(C, P) (((unsigned long int) (C)[(P) + 0] << 24) + \
341 ((unsigned long int) (C)[(P) + 1] << 16) + \
342 ((unsigned long int) (C)[(P) + 2] << 8) + \
343 ((unsigned long int) (C)[(P) + 3] << 0))
344
345 #define STREAM_TO_UINT16(C, P) (((unsigned long int) (C)[(P) + 0] << 8) + \
346 ((unsigned long int) (C)[(P) + 1] << 0))
347
348 #define OPJREAD_LONG(F,L,N) { \
349 if (F->Read(fourbytes, 4) < 4) { \
350 wxLogMessage(wxT("Problem reading " N " from the file (file ended?)")); \
351 return -1; \
352 }; \
353 L = STREAM_TO_UINT32(fourbytes, 0); \
354 }
355
356 /* handling functions */
357 #define ITEM_PER_ROW 10
358
359 //#define indprint if (0) printf("%.*s", 2 * level + 9, indent), printf
360 char indent[] = " "
361 " "
362 " "
363 " ";
364
indprint(wxString printout,int level)365 void indprint(wxString printout, int level)
366 {
367 wxLogMessage(/*wxString::Format(wxT("%.*s"), 2 * level + 9, indent) + */printout);
368 }
369
370 /* Box handler function */
box_handler_function(int boxtype,wxFile * fileid,wxFileOffset filepoint,wxFileOffset filelimit,wxTreeItemId parentid,int level,char * scansign,unsigned long int * scanpoint)371 int OPJParseThread::box_handler_function(int boxtype, wxFile *fileid, wxFileOffset filepoint, wxFileOffset filelimit,
372 wxTreeItemId parentid, int level, char *scansign, unsigned long int *scanpoint)
373 {
374 switch ((j22boxtype) boxtype) {
375
376
377 /* JPEG 2000 Signature box */
378 case (JP_BOX): {
379
380 unsigned long int checkdata = 0;
381 fileid->Read(&checkdata, sizeof(unsigned long int));
382 checkdata = BYTE_SWAP4(checkdata);
383
384 // add info
385 wxTreeItemId currid = m_tree->AppendItem(parentid,
386 wxString::Format(wxT("Check data: %X -> %s"), checkdata, (checkdata == 0x0D0A870A) ? wxT("OK") : wxT("KO")),
387 m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
388 new OPJMarkerData(wxT("INFO"))
389 );
390
391 };
392 break;
393
394
395 /* JPEG 2000 codestream box */
396 case (JP2C_BOX): {
397
398 // add info
399 wxTreeItemId currid = m_tree->AppendItem(parentid,
400 wxString(wxT("Codestream")),
401 m_tree->TreeCtrlIcon_Folder, m_tree->TreeCtrlIcon_Folder + 1,
402 new OPJMarkerData(wxT("INFO-CSTREAM"), m_tree->m_fname.GetFullPath(), filepoint, filelimit)
403 );
404
405 m_tree->SetItemHasChildren(currid);
406
407 // parse the file
408 //ParseJ2KFile(fileid, filepoint, filelimit, currid);
409
410 };
411 break;
412
413
414
415
416
417 /* File Type box */
418 case (FTYP_BOX): {
419
420 char BR[4], CL[4];
421 unsigned long int MinV, numCL, i;
422 fileid->Read(BR, sizeof(char) * 4);
423 fileid->Read(&MinV, sizeof(unsigned long int));
424 MinV = BYTE_SWAP4(MinV);
425 numCL = (filelimit - fileid->Tell()) / 4;
426
427 // add info
428 wxTreeItemId currid = m_tree->AppendItem(parentid,
429 wxT("Brand/Minor version: ") +
430 wxString::FromAscii(BR).Truncate(4) +
431 wxString::Format(wxT("/%d"), MinV),
432 m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
433 new OPJMarkerData(wxT("INFO"))
434 );
435
436 currid = m_tree->AppendItem(parentid,
437 wxString::Format(wxT("Compatibility list")),
438 m_tree->TreeCtrlIcon_Folder, m_tree->TreeCtrlIcon_Folder + 1,
439 new OPJMarkerData(wxT("INFO"))
440 );
441
442 for (i = 0; i < numCL; i++) {
443 fileid->Read(CL, sizeof(char) * 4);
444 m_tree->AppendItem(currid,
445 wxString::FromAscii(CL).Truncate(4),
446 m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
447 new OPJMarkerData(wxT("INFO"))
448 );
449 };
450
451 };
452 break;
453
454
455
456 /* JP2 Header box */
457 case (IHDR_BOX): {
458
459 unsigned long int height, width;
460 unsigned short int nc;
461 unsigned char bpc, C, UnkC, IPR;
462 fileid->Read(&height, sizeof(unsigned long int));
463 height = BYTE_SWAP4(height);
464 fileid->Read(&width, sizeof(unsigned long int));
465 width = BYTE_SWAP4(width);
466 fileid->Read(&nc, sizeof(unsigned short int));
467 nc = BYTE_SWAP2(nc);
468 fileid->Read(&bpc, sizeof(unsigned char));
469 fileid->Read(&C, sizeof(unsigned char));
470 fileid->Read(&UnkC, sizeof(unsigned char));
471 fileid->Read(&IPR, sizeof(unsigned char));
472
473 // add info
474 wxTreeItemId currid = m_tree->AppendItem(parentid,
475 wxString::Format(wxT("Dimensions: %d x %d x %d @ %d bpc"), width, height, nc, bpc + 1),
476 m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
477 new OPJMarkerData(wxT("INFO"))
478 );
479
480 currid = m_tree->AppendItem(parentid,
481 wxString::Format(wxT("Compression type: %d"), C),
482 m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
483 new OPJMarkerData(wxT("INFO"))
484 );
485
486 currid = m_tree->AppendItem(parentid,
487 wxString::Format(wxT("Colourspace unknown: %d"), UnkC),
488 m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
489 new OPJMarkerData(wxT("INFO"))
490 );
491
492 currid = m_tree->AppendItem(parentid,
493 wxString::Format(wxT("Intellectual Property Rights: %d"), IPR),
494 m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
495 new OPJMarkerData(wxT("INFO"))
496 );
497
498 };
499 break;
500
501
502
503 /* Colour Specification box */
504 case (COLR_BOX): {
505
506 unsigned char METH, PREC, APPROX;
507 char methdescr[80], enumcsdescr[80];
508 unsigned long int EnumCS;
509 fileid->Read(&METH, sizeof(unsigned char));
510 switch (METH) {
511 case 1:
512 strcpy(methdescr, "Enumerated Colourspace");
513 break;
514 case 2:
515 strcpy(methdescr, "Restricted ICC profile");
516 break;
517 default:
518 strcpy(methdescr, "Unknown");
519 break;
520 };
521 fileid->Read(&PREC, sizeof(unsigned char));
522 fileid->Read(&APPROX, sizeof(unsigned char));
523 if (METH != 2) {
524 fileid->Read(&EnumCS, sizeof(unsigned long int));
525 EnumCS = BYTE_SWAP4(EnumCS);
526 switch (EnumCS) {
527 case 16:
528 strcpy(enumcsdescr, "sRGB");
529 break;
530 case 17:
531 strcpy(enumcsdescr, "greyscale");
532 break;
533 case 18:
534 strcpy(enumcsdescr, "sYCC");
535 break;
536 default:
537 strcpy(enumcsdescr, "Unknown");
538 break;
539 };
540 };
541
542 // add info
543 wxTreeItemId currid = m_tree->AppendItem(parentid,
544 wxString::Format(wxT("Specification method: %d ("), METH) +
545 wxString::FromAscii(methdescr) +
546 wxT(")"),
547 m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
548 new OPJMarkerData(wxT("INFO"))
549 );
550
551 currid = m_tree->AppendItem(parentid,
552 wxString::Format(wxT("Precedence: %d"), PREC),
553 m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
554 new OPJMarkerData(wxT("INFO"))
555 );
556
557 currid = m_tree->AppendItem(parentid,
558 wxString::Format(wxT("Colourspace approximation: %d"), APPROX),
559 m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
560 new OPJMarkerData(wxT("INFO"))
561 );
562
563 if (METH != 2)
564 currid = m_tree->AppendItem(parentid,
565 wxString::Format(wxT("Enumerated colourspace: %d ("), EnumCS) +
566 wxString::FromAscii(enumcsdescr) +
567 wxT(")"),
568 m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
569 new OPJMarkerData(wxT("INFO"))
570 );
571
572 if (METH != 1)
573 currid = m_tree->AppendItem(parentid,
574 wxString::Format(wxT("ICC profile: there is one")),
575 m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
576 new OPJMarkerData(wxT("INFO"))
577 );
578
579
580 };
581 break;
582
583
584
585
586
587
588 /* Movie Header Box */
589 case (MVHD_BOX): {
590
591 unsigned long int version, rate, matrix[9], next_track_ID;
592 unsigned short int volume;
593 fileid->Read(&version, sizeof(unsigned long int));
594 version = BYTE_SWAP4(version);
595 if (version == 0) {
596 unsigned long int creation_time, modification_time, timescale, duration;
597 fileid->Read(&creation_time, sizeof(unsigned long int));
598 creation_time = BYTE_SWAP4(creation_time);
599 fileid->Read(&modification_time, sizeof(unsigned long int));
600 modification_time = BYTE_SWAP4(modification_time);
601 fileid->Read(×cale, sizeof(unsigned long int));
602 timescale = BYTE_SWAP4(timescale);
603 fileid->Read(&duration, sizeof(unsigned long int));
604 duration = BYTE_SWAP4(duration);
605 const long unix_time = creation_time - 2082844800L;
606 wxTreeItemId currid = m_tree->AppendItem(parentid,
607 wxString::Format(wxT("Creation time: %u (%.24s)"), creation_time, ctime(&unix_time)),
608 m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
609 new OPJMarkerData(wxT("INFO"))
610 );
611 const long unix_time1 = modification_time - 2082844800L;
612 currid = m_tree->AppendItem(parentid,
613 wxString::Format(wxT("Modification time: %u (%.24s)"), modification_time, ctime(&unix_time1)),
614 m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
615 new OPJMarkerData(wxT("INFO"))
616 );
617 currid = m_tree->AppendItem(parentid,
618 wxString::Format(wxT("Timescale: %u (%.6fs)"), timescale, 1.0 / (float) timescale),
619 m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
620 new OPJMarkerData(wxT("INFO"))
621 );
622 currid = m_tree->AppendItem(parentid,
623 wxString::Format(wxT("Duration: %u (%.3fs)"), duration, (float) duration / (float) timescale),
624 m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
625 new OPJMarkerData(wxT("INFO"))
626 );
627 } else {
628 int8byte creation_time, modification_time, duration;
629 unsigned long int timescale;
630 fileid->Read(&creation_time, sizeof(int8byte));
631 creation_time = BYTE_SWAP8(creation_time);
632 fileid->Read(&modification_time, sizeof(int8byte));
633 modification_time = BYTE_SWAP8(modification_time);
634 fileid->Read(×cale, sizeof(unsigned long int));
635 timescale = BYTE_SWAP4(timescale);
636 fileid->Read(&duration, sizeof(int8byte));
637 duration = BYTE_SWAP8(duration);
638 wxTreeItemId currid = m_tree->AppendItem(parentid,
639 wxString::Format(wxT("Creation time: %u"), creation_time),
640 m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
641 new OPJMarkerData(wxT("INFO"))
642 );
643 currid = m_tree->AppendItem(parentid,
644 wxString::Format(wxT("Modification time: %u"), modification_time),
645 m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
646 new OPJMarkerData(wxT("INFO"))
647 );
648 currid = m_tree->AppendItem(parentid,
649 wxString::Format(wxT("Timescale: %u"), timescale),
650 m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
651 new OPJMarkerData(wxT("INFO"))
652 );
653 currid = m_tree->AppendItem(parentid,
654 wxString::Format(wxT("Duration: %u"), duration),
655 m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
656 new OPJMarkerData(wxT("INFO"))
657 );
658 };
659 fileid->Read(&rate, sizeof(unsigned long int));
660 rate = BYTE_SWAP4(rate);
661 fileid->Read(&volume, sizeof(unsigned short int));
662 volume = BYTE_SWAP2(volume);
663 fileid->Seek(6, wxFromCurrent);
664 fileid->Read(&matrix, sizeof(unsigned char) * 9);
665 fileid->Seek(4, wxFromCurrent);
666 fileid->Read(&next_track_ID, sizeof(unsigned long int));
667 next_track_ID = BYTE_SWAP4(next_track_ID);
668 wxTreeItemId currid = m_tree->AppendItem(parentid,
669 wxString::Format(wxT("Rate: %d (%d.%d)"), rate, rate >> 16, rate & 0x0000FFFF),
670 m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
671 new OPJMarkerData(wxT("INFO"))
672 );
673 currid = m_tree->AppendItem(parentid,
674 wxString::Format(wxT("Volume: %d (%d.%d)"), volume, volume >> 8, volume & 0x00FF),
675 m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
676 new OPJMarkerData(wxT("INFO"))
677 );
678 currid = m_tree->AppendItem(parentid,
679 wxString::Format(wxT("Next track ID: %d"), next_track_ID),
680 m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
681 new OPJMarkerData(wxT("INFO"))
682 );
683 };
684 break;
685
686
687 /* Sample Description box */
688 case (STSD_BOX): {
689
690 unsigned long int version, entry_count;
691 fileid->Read(&version, sizeof(unsigned long int));
692 version = BYTE_SWAP4(version);
693 fileid->Read(&entry_count, sizeof(unsigned long int));
694 entry_count = BYTE_SWAP4(entry_count);
695 wxTreeItemId currid = m_tree->AppendItem(parentid,
696 wxString::Format(wxT("Entry count: %d"), entry_count),
697 m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
698 new OPJMarkerData(wxT("INFO"), m_tree->m_fname.GetFullPath(), filepoint, filelimit)
699 );
700 jpeg2000parse(fileid, filepoint + 8, filelimit, parentid, level + 1, scansign, scanpoint);
701 };
702 break;
703
704
705 /* Sample Size box */
706 case (STSZ_BOX): {
707
708 unsigned long int version, sample_size, sample_count, entry_size;
709
710 fileid->Read(&version, sizeof(unsigned long int));
711 version = BYTE_SWAP4(version);
712
713 fileid->Read(&sample_size, sizeof(unsigned long int));
714 sample_size = BYTE_SWAP4(sample_size);
715
716 if (sample_size == 0) {
717 fileid->Read(&sample_count, sizeof(unsigned long int));
718 sample_count = BYTE_SWAP4(sample_count);
719
720 wxTreeItemId currid = m_tree->AppendItem(parentid,
721 wxString::Format(wxT("Sample count: %d"), sample_count),
722 m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
723 new OPJMarkerData(wxT("INFO"), m_tree->m_fname.GetFullPath(), filepoint, filelimit)
724 );
725
726 currid = m_tree->AppendItem(parentid,
727 wxT("Entries size (bytes)"),
728 m_tree->TreeCtrlIcon_Folder, m_tree->TreeCtrlIcon_Folder + 1,
729 new OPJMarkerData(wxT("INFO"), m_tree->m_fname.GetFullPath(), filepoint, filelimit)
730 );
731
732 wxString text;
733 for (unsigned int s = 0; s < sample_count; s++) {
734 fileid->Read(&entry_size, sizeof(unsigned long int));
735 entry_size = BYTE_SWAP4(entry_size);
736
737 text << wxString::Format(wxT("%d, "), entry_size);
738
739 if (((s % 10) == (ITEM_PER_ROW - 1)) || (s == (sample_count - 1))) {
740 m_tree->AppendItem(currid,
741 text,
742 m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
743 new OPJMarkerData(wxT("INFO"), m_tree->m_fname.GetFullPath(), filepoint, filelimit)
744 );
745 text = wxT("");
746 }
747
748 }
749
750 }
751
752 };
753 break;
754
755
756 /* Video Media Header box */
757 case (VMHD_BOX): {
758
759 unsigned long int version;
760 unsigned short int graphicsmode, opcolor[3];
761 char graphicsdescr[100];
762
763 fileid->Read(&version, sizeof(unsigned long int));
764 version = BYTE_SWAP4(version);
765
766 fileid->Read(&graphicsmode, sizeof(unsigned short int));
767 graphicsmode = BYTE_SWAP2(graphicsmode);
768 switch (graphicsmode) {
769 case (0x00):
770 strcpy(graphicsdescr, "copy");
771 break;
772 case (0x24):
773 strcpy(graphicsdescr, "transparent");
774 break;
775 case (0x0100):
776 strcpy(graphicsdescr, "alpha");
777 break;
778 case (0x0101):
779 strcpy(graphicsdescr, "whitealpha");
780 break;
781 case (0x0102):
782 strcpy(graphicsdescr, "blackalpha");
783 break;
784 default:
785 strcpy(graphicsdescr, "unknown");
786 break;
787 };
788
789 fileid->Read(opcolor, 3 * sizeof(unsigned short int));
790 opcolor[0] = BYTE_SWAP2(opcolor[0]);
791 opcolor[1] = BYTE_SWAP2(opcolor[1]);
792 opcolor[2] = BYTE_SWAP2(opcolor[2]);
793
794 wxTreeItemId currid = m_tree->AppendItem(parentid,
795 wxString::Format(wxT("Composition mode: %d (")) +
796 wxString::FromAscii(graphicsdescr) +
797 wxT(")"),
798 m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
799 new OPJMarkerData(wxT("INFO"), m_tree->m_fname.GetFullPath(), filepoint, filelimit)
800 );
801
802 currid = m_tree->AppendItem(parentid,
803 wxString::Format(wxT("OP color: %d %d %d"), opcolor[0], opcolor[1], opcolor[2]),
804 m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
805 new OPJMarkerData(wxT("INFO"), m_tree->m_fname.GetFullPath(), filepoint, filelimit)
806 );
807 };
808 break;
809
810
811
812 /* MJP2 Sample Description box */
813 case (MJP2_BOX): {
814
815 unsigned short int height, width, depth;
816 unsigned long int horizresolution, vertresolution;
817 char compressor_name[32];
818 fileid->Seek(24, wxFromCurrent);
819 fileid->Read(&width, sizeof(unsigned short int));
820 width = BYTE_SWAP2(width);
821 fileid->Read(&height, sizeof(unsigned short int));
822 height = BYTE_SWAP2(height);
823 fileid->Read(&horizresolution, sizeof(unsigned long int));
824 horizresolution = BYTE_SWAP4(horizresolution);
825 fileid->Read(&vertresolution, sizeof(unsigned long int));
826 vertresolution = BYTE_SWAP4(vertresolution);
827 fileid->Seek(6, wxFromCurrent);
828 fileid->Read(compressor_name, sizeof(char) * 32);
829 fileid->Read(&depth, sizeof(unsigned short int));
830 depth = BYTE_SWAP2(depth);
831 wxTreeItemId currid = m_tree->AppendItem(parentid,
832 wxString::Format(wxT("Dimensions: %d x %d @ %d bpp"), width, height, depth),
833 m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
834 new OPJMarkerData(wxT("INFO"), m_tree->m_fname.GetFullPath(), filepoint, filelimit)
835 );
836 currid = m_tree->AppendItem(parentid,
837 wxString::Format(wxT("Resolution: %d.%d x %d.%d"), horizresolution >> 16, horizresolution & 0x0000FFFF,
838 vertresolution >> 16, vertresolution & 0x0000FFFF),
839 m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
840 new OPJMarkerData(wxT("INFO"))
841 );
842 currid = m_tree->AppendItem(parentid,
843 wxString::Format(wxT("Compressor: %.32s"), compressor_name),
844 m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
845 new OPJMarkerData(wxT("INFO"))
846 );
847 jpeg2000parse(fileid, filepoint + 78, filelimit, parentid, level + 1, scansign, scanpoint);
848
849 };
850 break;
851
852 /* Media Header box */
853 case (MDHD_BOX): {
854 unsigned long int version;
855 unsigned short int language;
856 fileid->Read(&version, sizeof(unsigned long int));
857 version = BYTE_SWAP4(version);
858 if (version == 0) {
859 unsigned long int creation_time, modification_time, timescale, duration;
860 fileid->Read(&creation_time, sizeof(unsigned long int));
861 creation_time = BYTE_SWAP4(creation_time);
862 fileid->Read(&modification_time, sizeof(unsigned long int));
863 modification_time = BYTE_SWAP4(modification_time);
864 fileid->Read(×cale, sizeof(unsigned long int));
865 timescale = BYTE_SWAP4(timescale);
866 fileid->Read(&duration, sizeof(unsigned long int));
867 duration = BYTE_SWAP4(duration);
868 const long unix_time = creation_time - 2082844800L;
869 wxTreeItemId currid = m_tree->AppendItem(parentid,
870 wxString::Format(wxT("Creation time: %u (%.24s)"), creation_time, ctime(&unix_time)),
871 m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
872 new OPJMarkerData(wxT("INFO"))
873 );
874 const long unix_time1 = modification_time - 2082844800L;
875 currid = m_tree->AppendItem(parentid,
876 wxString::Format(wxT("Modification time: %u (%.24s)"), modification_time, ctime(&unix_time1)),
877 m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
878 new OPJMarkerData(wxT("INFO"))
879 );
880 currid = m_tree->AppendItem(parentid,
881 wxString::Format(wxT("Timescale: %u (%.6fs)"), timescale, 1.0 / (float) timescale),
882 m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
883 new OPJMarkerData(wxT("INFO"))
884 );
885 currid = m_tree->AppendItem(parentid,
886 wxString::Format(wxT("Duration: %u (%.3fs)"), duration, (float) duration / (float) timescale),
887 m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
888 new OPJMarkerData(wxT("INFO"))
889 );
890 } else {
891 int8byte creation_time, modification_time, duration;
892 unsigned long int timescale;
893 fileid->Read(&creation_time, sizeof(int8byte));
894 creation_time = BYTE_SWAP8(creation_time);
895 fileid->Read(&modification_time, sizeof(int8byte));
896 modification_time = BYTE_SWAP8(modification_time);
897 fileid->Read(×cale, sizeof(unsigned long int));
898 timescale = BYTE_SWAP4(timescale);
899 fileid->Read(&duration, sizeof(int8byte));
900 duration = BYTE_SWAP8(duration);
901 wxTreeItemId currid = m_tree->AppendItem(parentid,
902 wxString::Format(wxT("Creation time: %u"), creation_time),
903 m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
904 new OPJMarkerData(wxT("INFO"))
905 );
906 currid = m_tree->AppendItem(parentid,
907 wxString::Format(wxT("Modification time: %u"), modification_time),
908 m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
909 new OPJMarkerData(wxT("INFO"))
910 );
911 currid = m_tree->AppendItem(parentid,
912 wxString::Format(wxT("Timescale: %u"), timescale),
913 m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
914 new OPJMarkerData(wxT("INFO"))
915 );
916 currid = m_tree->AppendItem(parentid,
917 wxString::Format(wxT("Duration: %u"), duration),
918 m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
919 new OPJMarkerData(wxT("INFO"))
920 );
921 }
922 fileid->Read(&language, sizeof(unsigned short int));
923
924 wxTreeItemId currid = m_tree->AppendItem(parentid,
925 wxString::Format(wxT("Language: %d (%c%c%c)"), language & 0xEFFF,
926 0x60 + (char) ((language >> 10) & 0x001F), 0x60 + (char) ((language >> 5) & 0x001F), 0x60 + (char) ((language >> 0) & 0x001F)),
927 m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
928 new OPJMarkerData(wxT("INFO"))
929 );
930 };
931 break;
932
933 /* Media Handler box */
934 case (HDLR_BOX): {
935 unsigned long int version, predefined, temp[3];
936 char handler[4], name[256];
937 int namelen = wxMin(256, (filelimit - filepoint - 24));
938 fileid->Read(&version, sizeof(unsigned long int));
939 version = BYTE_SWAP4(version);
940 fileid->Read(&predefined, sizeof(unsigned long int));
941 fileid->Read(handler, 4 * sizeof(char));
942 fileid->Read(&temp, 3 * sizeof(unsigned long int));
943 fileid->Read(name, namelen * sizeof(char));
944
945 wxTreeItemId currid = m_tree->AppendItem(parentid,
946 wxString::Format(wxT("Handler: %.4s"), handler),
947 m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
948 new OPJMarkerData(wxT("INFO"))
949 );
950
951 currid = m_tree->AppendItem(parentid,
952 wxString::Format(wxT("Name: %.255s"), name),
953 m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
954 new OPJMarkerData(wxT("INFO"))
955 );
956
957 }
958 break;
959
960 /* not yet implemented */
961 default:
962 break;
963
964 };
965
966 return (0);
967 }
968
969
ParseJP2File(wxFile * fileid,wxFileOffset filepoint,wxFileOffset filelimit,wxTreeItemId parentid)970 void OPJParseThread::ParseJP2File(wxFile *fileid, wxFileOffset filepoint, wxFileOffset filelimit, wxTreeItemId parentid)
971 {
972 unsigned long int scanpoint;
973
974 jpeg2000parse(fileid, filepoint, filelimit, parentid, 0, NULL, &scanpoint);
975 }
976
977 /* the parsing function itself */
978 /*
979 fileid = fid of the file to scan (you should open it by yourself)
980 filepoint = first byte where to start to scan from (usually 0)
981 filelimit = first byte where to stop to scan from (usually the file size)
982 level = set this to 0
983 scansign = signature to scan for (NULL avoids search, returns " " if successful)
984 scanpoint = point where the scan signature lies
985 */
jpeg2000parse(wxFile * fileid,wxFileOffset filepoint,wxFileOffset filelimit,wxTreeItemId parentid,int level,char * scansign,unsigned long int * scanpoint)986 int OPJParseThread::jpeg2000parse(wxFile *fileid, wxFileOffset filepoint, wxFileOffset filelimit,
987 wxTreeItemId parentid, int level, char *scansign, unsigned long int *scanpoint)
988 {
989 unsigned long int LBox = 0x00000000;
990 //int LBox_read;
991 char TBox[5] = "\0\0\0\0";
992 //int TBox_read;
993 int8byte XLBox = 0x0000000000000000;
994 //int XLBox_read;
995 unsigned long int box_length = 0;
996 int last_box = 0, box_num = 0;
997 int box_type = ANY_BOX;
998 unsigned char /*onebyte[1], twobytes[2],*/ fourbytes[4];
999
1000 /* cycle all over the file */
1001 box_num = 0;
1002 last_box = 0;
1003 while (!last_box) {
1004
1005 /* do not exceed file limit */
1006 if (filepoint >= filelimit)
1007 return (0);
1008
1009 /* seek on file */
1010 if (fileid->Seek(filepoint, wxFromStart) == wxInvalidOffset)
1011 return (-1);
1012
1013 /* read the mandatory LBox, 4 bytes */
1014 if (fileid->Read(fourbytes, 4) < 4) {
1015 WriteText(wxT("Problem reading LBox from the file (file ended?)"));
1016 return -1;
1017 };
1018 LBox = STREAM_TO_UINT32(fourbytes, 0);
1019
1020 /* read the mandatory TBox, 4 bytes */
1021 if (fileid->Read(TBox, 4) < 4) {
1022 WriteText(wxT("Problem reading TBox from the file (file ended?)"));
1023 return -1;
1024 };
1025
1026 /* look if scansign is got */
1027 if ((scansign != NULL) && (memcmp(TBox, scansign, 4) == 0)) {
1028 memcpy(scansign, " ", 4);
1029 *scanpoint = filepoint;
1030
1031 /* hack/exploit */
1032 // stop as soon as you find the codebox
1033 return (0);
1034
1035 };
1036
1037 /* determine the box type */
1038 for (box_type = JP_BOX; box_type < UNK_BOX; box_type++)
1039 if (memcmp(TBox, j22box[box_type].value, 4) == 0)
1040 break;
1041
1042 /* read the optional XLBox, 8 bytes */
1043 if (LBox == 1) {
1044
1045 if (fileid->Read(&XLBox, 8) < 8) {
1046 WriteText(wxT("Problem reading XLBox from the file (file ended?)"));
1047 return -1;
1048 };
1049 box_length = (unsigned long int) BYTE_SWAP8(XLBox);
1050
1051 } else if (LBox == 0x00000000) {
1052
1053 /* last box in file */
1054 last_box = 1;
1055 box_length = filelimit - filepoint;
1056
1057 } else
1058
1059 box_length = LBox;
1060
1061 /* show box info */
1062
1063 // append the marker
1064 int image, imageSel;
1065 image = m_tree->TreeCtrlIcon_Folder;
1066 imageSel = image + 1;
1067 wxTreeItemId currid = m_tree->AppendItem(parentid,
1068 wxString::Format(wxT("%03d: "), box_num) +
1069 wxString::FromAscii(TBox) +
1070 wxString::Format(wxT(" (0x%04X)"),
1071 ((unsigned long int) TBox[3]) + ((unsigned long int) TBox[2] << 8) +
1072 ((unsigned long int) TBox[1] << 16) + ((unsigned long int) TBox[0] << 24)
1073 ),
1074 image, imageSel,
1075 new OPJMarkerData(wxT("BOX"), m_tree->m_fname.GetFullPath(), filepoint, filepoint + box_length)
1076 );
1077
1078 // append some info
1079 image = m_tree->TreeCtrlIcon_File;
1080 imageSel = image + 1;
1081
1082 // box name
1083 wxTreeItemId subcurrid1 = m_tree->AppendItem(currid,
1084 wxT("*** ") + wxString::FromAscii(j22box[box_type].name) + wxT(" ***"),
1085 image, imageSel,
1086 new OPJMarkerData(wxT("INFO"))
1087 );
1088 m_tree->SetItemFont(subcurrid1, *wxITALIC_FONT);
1089
1090 // position and length
1091 wxTreeItemId subcurrid2 = m_tree->AppendItem(currid,
1092 wxLongLong(filepoint).ToString() + wxT(" > ") + wxLongLong(filepoint + box_length - 1).ToString() +
1093 wxT(", ") + wxString::Format(wxT("%d + 8 (%d)"), box_length, box_length + 8),
1094 image, imageSel,
1095 new OPJMarkerData(wxT("INFO"))
1096 );
1097
1098 /* go deep in the box */
1099 box_handler_function((int) box_type, fileid, (LBox == 1) ? (filepoint + 16) : (filepoint + 8), filepoint + box_length,
1100 currid, level, scansign, scanpoint);
1101
1102 /* if it's a superbox go inside it */
1103 if (j22box[box_type].sbox)
1104 jpeg2000parse(fileid, (LBox == 1) ? (filepoint + 16) : (filepoint + 8), filepoint + box_length,
1105 currid, level + 1, scansign, scanpoint);
1106
1107 /* increment box number and filepoint*/
1108 box_num++;
1109 filepoint += box_length;
1110
1111 };
1112
1113 /* all good */
1114 return (0);
1115 }
1116
1117