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