diff options
| author | Mathieu Malaterre <mathieu.malaterre@gmail.com> | 2012-09-28 08:11:41 +0000 |
|---|---|---|
| committer | Mathieu Malaterre <mathieu.malaterre@gmail.com> | 2012-09-28 08:11:41 +0000 |
| commit | d518970039a19a2a9b6d2bdd592cc88a43897bbb (patch) | |
| tree | 57bac2cf7e63e9352228231062763baac627563c /src/bin/wx/OPJViewer/source/wxjp2parser.cpp | |
| parent | 8363a6ab1e031bb4b2e40a92e56efd40fdab1aa1 (diff) | |
[trunk] Start FolderReorgProposal task
Update issue 177
Diffstat (limited to 'src/bin/wx/OPJViewer/source/wxjp2parser.cpp')
| -rw-r--r-- | src/bin/wx/OPJViewer/source/wxjp2parser.cpp | 1116 |
1 files changed, 1116 insertions, 0 deletions
diff --git a/src/bin/wx/OPJViewer/source/wxjp2parser.cpp b/src/bin/wx/OPJViewer/source/wxjp2parser.cpp new file mode 100644 index 00000000..182def8b --- /dev/null +++ b/src/bin/wx/OPJViewer/source/wxjp2parser.cpp @@ -0,0 +1,1116 @@ +/* + * Copyright (c) 2007, Digital Signal Processing Laboratory, Università degli studi di Perugia (UPG), Italy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include "OPJViewer.h" + +/* defines */ +#define SHORT_DESCR_LEN 32 +#define LONG_DESCR_LEN 256 + +/* enumeration for file formats */ +#define J2FILENUM 4 +typedef enum { + + JP2_FILE, + J2K_FILE, + MJ2_FILE, + UNK_FILE + +} j2filetype; + +/* enumeration for the box types */ +#define j22boxNUM 23 +typedef enum { + + FILE_BOX, + JP_BOX, + FTYP_BOX, + JP2H_BOX, + IHDR_BOX, + COLR_BOX, + JP2C_BOX, + JP2I_BOX, + XML_BOX, + UUID_BOX, + UINF_BOX, + MOOV_BOX, + MVHD_BOX, + TRAK_BOX, + TKHD_BOX, + MDIA_BOX, + MDHD_BOX, + HDLR_BOX, + MINF_BOX, + VMHD_BOX, + STBL_BOX, + STSD_BOX, + STSZ_BOX, + MJP2_BOX, + MDAT_BOX, + ANY_BOX, + UNK_BOX + +} j22boxtype; + +/* the box structure itself */ +struct boxdef { + + char value[5]; /* hexadecimal value/string*/ + char name[SHORT_DESCR_LEN]; /* short description */ + char descr[LONG_DESCR_LEN]; /* long description */ + int sbox; /* is it a superbox? */ + int req[J2FILENUM]; /* mandatory box */ + j22boxtype ins; /* contained in box... */ + +}; + + +/* jp2 family box signatures */ +#define FILE_SIGN "" +#define JP_SIGN "jP\040\040" +#define FTYP_SIGN "ftyp" +#define JP2H_SIGN "jp2h" +#define IHDR_SIGN "ihdr" +#define COLR_SIGN "colr" +#define JP2C_SIGN "jp2c" +#define JP2I_SIGN "jp2i" +#define XML_SIGN "xml\040" +#define UUID_SIGN "uuid" +#define UINF_SIGN "uinf" +#define MOOV_SIGN "moov" +#define MVHD_SIGN "mvhd" +#define TRAK_SIGN "trak" +#define TKHD_SIGN "tkhd" +#define MDIA_SIGN "mdia" +#define MDHD_SIGN "mdhd" +#define HDLR_SIGN "hdlr" +#define MINF_SIGN "minf" +#define VMHD_SIGN "vmhd" +#define STBL_SIGN "stbl" +#define STSD_SIGN "stsd" +#define STSZ_SIGN "stsz" +#define MJP2_SIGN "mjp2" +#define MDAT_SIGN "mdat" +#define ANY_SIGN "" +#define UNK_SIGN "" + +/* the possible boxes */ +struct boxdef j22box[] = +{ +/* sign */ {FILE_SIGN, +/* short */ "placeholder for nothing", +/* long */ "Nothing to say", +/* sbox */ 0, +/* req */ {1, 1, 1}, +/* ins */ FILE_BOX}, + +/* sign */ {JP_SIGN, +/* short */ "JPEG 2000 Signature box", +/* long */ "This box uniquely identifies the file as being part of the JPEG 2000 family of files", +/* sbox */ 0, +/* req */ {1, 1, 1}, +/* ins */ FILE_BOX}, + +/* sign */ {FTYP_SIGN, +/* short */ "File Type box", +/* long */ "This box specifies file type, version and compatibility information, including specifying if this file " + "is a conforming JP2 file or if it can be read by a conforming JP2 reader", +/* sbox */ 0, +/* req */ {1, 1, 1}, +/* ins */ FILE_BOX}, + +/* sign */ {JP2H_SIGN, +/* short */ "JP2 Header box", +/* long */ "This box contains a series of boxes that contain header-type information about the file", +/* sbox */ 1, +/* req */ {1, 1, 1}, +/* ins */ FILE_BOX}, + +/* sign */ {IHDR_SIGN, +/* short */ "Image Header box", +/* long */ "This box specifies the size of the image and other related fields", +/* sbox */ 0, +/* req */ {1, 1, 1}, +/* ins */ JP2H_BOX}, + +/* sign */ {COLR_SIGN, +/* short */ "Colour Specification box", +/* long */ "This box specifies the colourspace of the image", +/* sbox */ 0, +/* req */ {1, 1, 1}, +/* ins */ JP2H_BOX}, + +/* sign */ {JP2C_SIGN, +/* short */ "Contiguous Codestream box", +/* long */ "This box contains the codestream as defined by Annex A", +/* sbox */ 0, +/* req */ {1, 1, 1}, +/* ins */ FILE_BOX}, + +/* sign */ {JP2I_SIGN, +/* short */ "Intellectual Property box", +/* long */ "This box contains intellectual property information about the image", +/* sbox */ 0, +/* req */ {0, 0, 0}, +/* ins */ FILE_BOX}, + +/* sign */ {XML_SIGN, +/* short */ "XML box", +/* long */ "This box provides a tool by which vendors can add XML formatted information to a JP2 file", +/* sbox */ 0, +/* req */ {0, 0, 0}, +/* ins */ FILE_BOX}, + +/* sign */ {UUID_SIGN, +/* short */ "UUID box", +/* long */ "This box provides a tool by which vendors can add additional information to a file " + "without risking conflict with other vendors", +/* sbox */ 0, +/* req */ {0, 0, 0}, +/* ins */ FILE_BOX}, + +/* sign */ {UINF_SIGN, +/* short */ "UUID Info box", +/* long */ "This box provides a tool by which a vendor may provide access to additional information associated with a UUID", +/* sbox */ 0, +/* req */ {0, 0, 0}, +/* ins */ FILE_BOX}, + +/* sign */ {MOOV_SIGN, +/* short */ "Movie box", +/* long */ "This box contains the media data. In video tracks, this box would contain JPEG2000 video frames", +/* sbox */ 1, +/* req */ {1, 1, 1}, +/* ins */ FILE_BOX}, + +/* sign */ {MVHD_SIGN, +/* short */ "Movie Header box", +/* long */ "This box defines overall information which is media-independent, and relevant to the entire presentation " + "considered as a whole", +/* sbox */ 0, +/* req */ {1, 1, 1}, +/* ins */ MOOV_BOX}, + +/* sign */ {TRAK_SIGN, +/* short */ "Track box", +/* long */ "This is a container box for a single track of a presentation. A presentation may consist of one or more tracks", +/* sbox */ 1, +/* req */ {1, 1, 1}, +/* ins */ MOOV_BOX}, + +/* sign */ {TKHD_SIGN, +/* short */ "Track Header box", +/* long */ "This box specifies the characteristics of a single track. Exactly one Track Header Box is contained in a track", +/* sbox */ 0, +/* req */ {1, 1, 1}, +/* ins */ TRAK_BOX}, + +/* sign */ {MDIA_SIGN, +/* short */ "Media box", +/* long */ "The media declaration container contains all the objects which declare information about the media data " + "within a track", +/* sbox */ 1, +/* req */ {1, 1, 1}, +/* ins */ TRAK_BOX}, + +/* sign */ {MDHD_SIGN, +/* short */ "Media Header box", +/* long */ "The media header declares overall information which is media-independent, and relevant to characteristics " + "of the media in a track", +/* sbox */ 0, +/* req */ {1, 1, 1}, +/* ins */ MDIA_BOX}, + +/* sign */ {HDLR_SIGN, +/* short */ "Handler Reference box", +/* long */ "This box within a Media Box declares the process by which the media-data in the track may be presented, " + "and thus, the nature of the media in a track", +/* sbox */ 0, +/* req */ {1, 1, 1}, +/* ins */ MDIA_BOX}, + +/* sign */ {MINF_SIGN, +/* short */ "Media Information box", +/* long */ "This box contains all the objects which declare characteristic information of the media in the track", +/* sbox */ 1, +/* req */ {1, 1, 1}, +/* ins */ MDIA_BOX}, + +/* sign */ {VMHD_SIGN, +/* short */ "Video Media Header box", +/* long */ "The video media header contains general presentation information, independent of the coding, for video media", +/* sbox */ 0, +/* req */ {1, 1, 1}, +/* ins */ MINF_BOX}, + +/* sign */ {STBL_SIGN, +/* short */ "Sample Table box", +/* long */ "The sample table contains all the time and data indexing of the media samples in a track", +/* sbox */ 1, +/* req */ {1, 1, 1}, +/* ins */ MINF_BOX}, + +/* sign */ {STSD_SIGN, +/* short */ "STSD Sample Description box", +/* long */ "The sample description table gives detailed information about the coding type used, and any initialization " + "information needed for that coding", +/* sbox */ 0, +/* req */ {1, 1, 1}, +/* ins */ MINF_BOX}, + +/* sign */ {STSZ_SIGN, +/* short */ "Sample Size box", +/* long */ "This box contains the sample count and a table giving the size of each sample", +/* sbox */ 0, +/* req */ {1, 1, 1}, +/* ins */ STBL_BOX}, + +/* sign */ {MJP2_SIGN, +/* short */ "MJP2 Sample Description box", +/* long */ "The MJP2 sample description table gives detailed information about the coding type used, and any initialization " + "information needed for that coding", +/* sbox */ 0, +/* req */ {1, 1, 1}, +/* ins */ MINF_BOX}, + +/* sign */ {MDAT_SIGN, +/* short */ "Media Data box", +/* long */ "The meta-data for a presentation is stored in the single Movie Box which occurs at the top-level of a file", +/* sbox */ 1, +/* req */ {1, 1, 1}, +/* ins */ FILE_BOX}, + +/* sign */ {ANY_SIGN, +/* short */ "Any box", +/* long */ "All the existing boxes", +/* sbox */ 0, +/* req */ {0, 0, 0}, +/* ins */ FILE_BOX}, + +/* sign */ {UNK_SIGN, +/* short */ "Unknown Type box", +/* long */ "The signature is not recognised to be that of an existing box", +/* sbox */ 0, +/* req */ {0, 0, 0}, +/* ins */ ANY_BOX} + +}; + + +/* macro functions */ +/* From little endian to big endian, 2 and 4 bytes */ +#define BYTE_SWAP2(X) ((X & 0x00FF) << 8) | ((X & 0xFF00) >> 8) +#define BYTE_SWAP4(X) ((X & 0x000000FF) << 24) | ((X & 0x0000FF00) << 8) | ((X & 0x00FF0000) >> 8) | ((X & 0xFF000000) >> 24) + +#ifdef __WXGTK__ +#define BYTE_SWAP8(X) ((X & 0x00000000000000FFULL) << 56) | ((X & 0x000000000000FF00ULL) << 40) | \ + ((X & 0x0000000000FF0000ULL) << 24) | ((X & 0x00000000FF000000ULL) << 8) | \ + ((X & 0x000000FF00000000ULL) >> 8) | ((X & 0x0000FF0000000000ULL) >> 24) | \ + ((X & 0x00FF000000000000ULL) >> 40) | ((X & 0xFF00000000000000ULL) >> 56) +#else +#define BYTE_SWAP8(X) ((X & 0x00000000000000FF) << 56) | ((X & 0x000000000000FF00) << 40) | \ + ((X & 0x0000000000FF0000) << 24) | ((X & 0x00000000FF000000) << 8) | \ + ((X & 0x000000FF00000000) >> 8) | ((X & 0x0000FF0000000000) >> 24) | \ + ((X & 0x00FF000000000000) >> 40) | ((X & 0xFF00000000000000) >> 56) +#endif + +/* From codestream to int values */ +#define STREAM_TO_UINT32(C, P) (((unsigned long int) (C)[(P) + 0] << 24) + \ + ((unsigned long int) (C)[(P) + 1] << 16) + \ + ((unsigned long int) (C)[(P) + 2] << 8) + \ + ((unsigned long int) (C)[(P) + 3] << 0)) + +#define STREAM_TO_UINT16(C, P) (((unsigned long int) (C)[(P) + 0] << 8) + \ + ((unsigned long int) (C)[(P) + 1] << 0)) + +#define OPJREAD_LONG(F,L,N) { \ + if (F->Read(fourbytes, 4) < 4) { \ + wxLogMessage(wxT("Problem reading " N " from the file (file ended?)")); \ + return -1; \ + }; \ + L = STREAM_TO_UINT32(fourbytes, 0); \ + } + +/* handling functions */ +#define ITEM_PER_ROW 10 + +//#define indprint if (0) printf("%.*s", 2 * level + 9, indent), printf +char indent[] = " " + " " + " " + " "; + +void indprint(wxString printout, int level) +{ + wxLogMessage(/*wxString::Format(wxT("%.*s"), 2 * level + 9, indent) + */printout); +} + +/* Box handler function */ +int OPJParseThread::box_handler_function(int boxtype, wxFile *fileid, wxFileOffset filepoint, wxFileOffset filelimit, + wxTreeItemId parentid, int level, char *scansign, unsigned long int *scanpoint) +{ + switch ((j22boxtype) boxtype) { + + + /* JPEG 2000 Signature box */ + case (JP_BOX): { + + unsigned long int checkdata = 0; + fileid->Read(&checkdata, sizeof(unsigned long int)); + checkdata = BYTE_SWAP4(checkdata); + + // add info + wxTreeItemId currid = m_tree->AppendItem(parentid, + wxString::Format(wxT("Check data: %X -> %s"), checkdata, (checkdata == 0x0D0A870A) ? wxT("OK") : wxT("KO")), + m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1, + new OPJMarkerData(wxT("INFO")) + ); + + }; + break; + + + /* JPEG 2000 codestream box */ + case (JP2C_BOX): { + + // add info + wxTreeItemId currid = m_tree->AppendItem(parentid, + wxString(wxT("Codestream")), + m_tree->TreeCtrlIcon_Folder, m_tree->TreeCtrlIcon_Folder + 1, + new OPJMarkerData(wxT("INFO-CSTREAM"), m_tree->m_fname.GetFullPath(), filepoint, filelimit) + ); + + m_tree->SetItemHasChildren(currid); + + // parse the file + //ParseJ2KFile(fileid, filepoint, filelimit, currid); + + }; + break; + + + + + + /* File Type box */ + case (FTYP_BOX): { + + char BR[4], CL[4]; + unsigned long int MinV, numCL, i; + fileid->Read(BR, sizeof(char) * 4); + fileid->Read(&MinV, sizeof(unsigned long int)); + MinV = BYTE_SWAP4(MinV); + numCL = (filelimit - fileid->Tell()) / 4; + + // add info + wxTreeItemId currid = m_tree->AppendItem(parentid, + wxT("Brand/Minor version: ") + + wxString::FromAscii(BR).Truncate(4) + + wxString::Format(wxT("/%d"), MinV), + m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1, + new OPJMarkerData(wxT("INFO")) + ); + + currid = m_tree->AppendItem(parentid, + wxString::Format(wxT("Compatibility list")), + m_tree->TreeCtrlIcon_Folder, m_tree->TreeCtrlIcon_Folder + 1, + new OPJMarkerData(wxT("INFO")) + ); + + for (i = 0; i < numCL; i++) { + fileid->Read(CL, sizeof(char) * 4); + m_tree->AppendItem(currid, + wxString::FromAscii(CL).Truncate(4), + m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1, + new OPJMarkerData(wxT("INFO")) + ); + }; + + }; + break; + + + + /* JP2 Header box */ + case (IHDR_BOX): { + + unsigned long int height, width; + unsigned short int nc; + unsigned char bpc, C, UnkC, IPR; + fileid->Read(&height, sizeof(unsigned long int)); + height = BYTE_SWAP4(height); + fileid->Read(&width, sizeof(unsigned long int)); + width = BYTE_SWAP4(width); + fileid->Read(&nc, sizeof(unsigned short int)); + nc = BYTE_SWAP2(nc); + fileid->Read(&bpc, sizeof(unsigned char)); + fileid->Read(&C, sizeof(unsigned char)); + fileid->Read(&UnkC, sizeof(unsigned char)); + fileid->Read(&IPR, sizeof(unsigned char)); + + // add info + wxTreeItemId currid = m_tree->AppendItem(parentid, + wxString::Format(wxT("Dimensions: %d x %d x %d @ %d bpc"), width, height, nc, bpc + 1), + m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1, + new OPJMarkerData(wxT("INFO")) + ); + + currid = m_tree->AppendItem(parentid, + wxString::Format(wxT("Compression type: %d"), C), + m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1, + new OPJMarkerData(wxT("INFO")) + ); + + currid = m_tree->AppendItem(parentid, + wxString::Format(wxT("Colourspace unknown: %d"), UnkC), + m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1, + new OPJMarkerData(wxT("INFO")) + ); + + currid = m_tree->AppendItem(parentid, + wxString::Format(wxT("Intellectual Property Rights: %d"), IPR), + m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1, + new OPJMarkerData(wxT("INFO")) + ); + + }; + break; + + + + /* Colour Specification box */ + case (COLR_BOX): { + + unsigned char METH, PREC, APPROX; + char methdescr[80], enumcsdescr[80]; + unsigned long int EnumCS; + fileid->Read(&METH, sizeof(unsigned char)); + switch (METH) { + case 1: + strcpy(methdescr, "Enumerated Colourspace"); + break; + case 2: + strcpy(methdescr, "Restricted ICC profile"); + break; + default: + strcpy(methdescr, "Unknown"); + break; + }; + fileid->Read(&PREC, sizeof(unsigned char)); + fileid->Read(&APPROX, sizeof(unsigned char)); + if (METH != 2) { + fileid->Read(&EnumCS, sizeof(unsigned long int)); + EnumCS = BYTE_SWAP4(EnumCS); + switch (EnumCS) { + case 16: + strcpy(enumcsdescr, "sRGB"); + break; + case 17: + strcpy(enumcsdescr, "greyscale"); + break; + case 18: + strcpy(enumcsdescr, "sYCC"); + break; + default: + strcpy(enumcsdescr, "Unknown"); + break; + }; + }; + + // add info + wxTreeItemId currid = m_tree->AppendItem(parentid, + wxString::Format(wxT("Specification method: %d ("), METH) + + wxString::FromAscii(methdescr) + + wxT(")"), + m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1, + new OPJMarkerData(wxT("INFO")) + ); + + currid = m_tree->AppendItem(parentid, + wxString::Format(wxT("Precedence: %d"), PREC), + m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1, + new OPJMarkerData(wxT("INFO")) + ); + + currid = m_tree->AppendItem(parentid, + wxString::Format(wxT("Colourspace approximation: %d"), APPROX), + m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1, + new OPJMarkerData(wxT("INFO")) + ); + + if (METH != 2) + currid = m_tree->AppendItem(parentid, + wxString::Format(wxT("Enumerated colourspace: %d ("), EnumCS) + + wxString::FromAscii(enumcsdescr) + + wxT(")"), + m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1, + new OPJMarkerData(wxT("INFO")) + ); + + if (METH != 1) + currid = m_tree->AppendItem(parentid, + wxString::Format(wxT("ICC profile: there is one")), + m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1, + new OPJMarkerData(wxT("INFO")) + ); + + + }; + break; + + + + + + + /* Movie Header Box */ + case (MVHD_BOX): { + + unsigned long int version, rate, matrix[9], next_track_ID; + unsigned short int volume; + fileid->Read(&version, sizeof(unsigned long int)); + version = BYTE_SWAP4(version); + if (version == 0) { + unsigned long int creation_time, modification_time, timescale, duration; + fileid->Read(&creation_time, sizeof(unsigned long int)); + creation_time = BYTE_SWAP4(creation_time); + fileid->Read(&modification_time, sizeof(unsigned long int)); + modification_time = BYTE_SWAP4(modification_time); + fileid->Read(×cale, sizeof(unsigned long int)); + timescale = BYTE_SWAP4(timescale); + fileid->Read(&duration, sizeof(unsigned long int)); + duration = BYTE_SWAP4(duration); + const long unix_time = creation_time - 2082844800L; + wxTreeItemId currid = m_tree->AppendItem(parentid, + wxString::Format(wxT("Creation time: %u (%.24s)"), creation_time, ctime(&unix_time)), + m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1, + new OPJMarkerData(wxT("INFO")) + ); + const long unix_time1 = modification_time - 2082844800L; + currid = m_tree->AppendItem(parentid, + wxString::Format(wxT("Modification time: %u (%.24s)"), modification_time, ctime(&unix_time1)), + m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1, + new OPJMarkerData(wxT("INFO")) + ); + currid = m_tree->AppendItem(parentid, + wxString::Format(wxT("Timescale: %u (%.6fs)"), timescale, 1.0 / (float) timescale), + m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1, + new OPJMarkerData(wxT("INFO")) + ); + currid = m_tree->AppendItem(parentid, + wxString::Format(wxT("Duration: %u (%.3fs)"), duration, (float) duration / (float) timescale), + m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1, + new OPJMarkerData(wxT("INFO")) + ); + } else { + int8byte creation_time, modification_time, duration; + unsigned long int timescale; + fileid->Read(&creation_time, sizeof(int8byte)); + creation_time = BYTE_SWAP8(creation_time); + fileid->Read(&modification_time, sizeof(int8byte)); + modification_time = BYTE_SWAP8(modification_time); + fileid->Read(×cale, sizeof(unsigned long int)); + timescale = BYTE_SWAP4(timescale); + fileid->Read(&duration, sizeof(int8byte)); + duration = BYTE_SWAP8(duration); + wxTreeItemId currid = m_tree->AppendItem(parentid, + wxString::Format(wxT("Creation time: %u"), creation_time), + m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1, + new OPJMarkerData(wxT("INFO")) + ); + currid = m_tree->AppendItem(parentid, + wxString::Format(wxT("Modification time: %u"), modification_time), + m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1, + new OPJMarkerData(wxT("INFO")) + ); + currid = m_tree->AppendItem(parentid, + wxString::Format(wxT("Timescale: %u"), timescale), + m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1, + new OPJMarkerData(wxT("INFO")) + ); + currid = m_tree->AppendItem(parentid, + wxString::Format(wxT("Duration: %u"), duration), + m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1, + new OPJMarkerData(wxT("INFO")) + ); + }; + fileid->Read(&rate, sizeof(unsigned long int)); + rate = BYTE_SWAP4(rate); + fileid->Read(&volume, sizeof(unsigned short int)); + volume = BYTE_SWAP2(volume); + fileid->Seek(6, wxFromCurrent); + fileid->Read(&matrix, sizeof(unsigned char) * 9); + fileid->Seek(4, wxFromCurrent); + fileid->Read(&next_track_ID, sizeof(unsigned long int)); + next_track_ID = BYTE_SWAP4(next_track_ID); + wxTreeItemId currid = m_tree->AppendItem(parentid, + wxString::Format(wxT("Rate: %d (%d.%d)"), rate, rate >> 16, rate & 0x0000FFFF), + m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1, + new OPJMarkerData(wxT("INFO")) + ); + currid = m_tree->AppendItem(parentid, + wxString::Format(wxT("Volume: %d (%d.%d)"), volume, volume >> 8, volume & 0x00FF), + m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1, + new OPJMarkerData(wxT("INFO")) + ); + currid = m_tree->AppendItem(parentid, + wxString::Format(wxT("Next track ID: %d"), next_track_ID), + m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1, + new OPJMarkerData(wxT("INFO")) + ); + }; + break; + + + /* Sample Description box */ + case (STSD_BOX): { + + unsigned long int version, entry_count; + fileid->Read(&version, sizeof(unsigned long int)); + version = BYTE_SWAP4(version); + fileid->Read(&entry_count, sizeof(unsigned long int)); + entry_count = BYTE_SWAP4(entry_count); + wxTreeItemId currid = m_tree->AppendItem(parentid, + wxString::Format(wxT("Entry count: %d"), entry_count), + m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1, + new OPJMarkerData(wxT("INFO"), m_tree->m_fname.GetFullPath(), filepoint, filelimit) + ); + jpeg2000parse(fileid, filepoint + 8, filelimit, parentid, level + 1, scansign, scanpoint); + }; + break; + + + /* Sample Size box */ + case (STSZ_BOX): { + + unsigned long int version, sample_size, sample_count, entry_size; + + fileid->Read(&version, sizeof(unsigned long int)); + version = BYTE_SWAP4(version); + + fileid->Read(&sample_size, sizeof(unsigned long int)); + sample_size = BYTE_SWAP4(sample_size); + + if (sample_size == 0) { + fileid->Read(&sample_count, sizeof(unsigned long int)); + sample_count = BYTE_SWAP4(sample_count); + + wxTreeItemId currid = m_tree->AppendItem(parentid, + wxString::Format(wxT("Sample count: %d"), sample_count), + m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1, + new OPJMarkerData(wxT("INFO"), m_tree->m_fname.GetFullPath(), filepoint, filelimit) + ); + + currid = m_tree->AppendItem(parentid, + wxT("Entries size (bytes)"), + m_tree->TreeCtrlIcon_Folder, m_tree->TreeCtrlIcon_Folder + 1, + new OPJMarkerData(wxT("INFO"), m_tree->m_fname.GetFullPath(), filepoint, filelimit) + ); + + wxString text; + for (unsigned int s = 0; s < sample_count; s++) { + fileid->Read(&entry_size, sizeof(unsigned long int)); + entry_size = BYTE_SWAP4(entry_size); + + text << wxString::Format(wxT("%d, "), entry_size); + + if (((s % 10) == (ITEM_PER_ROW - 1)) || (s == (sample_count - 1))) { + m_tree->AppendItem(currid, + text, + m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1, + new OPJMarkerData(wxT("INFO"), m_tree->m_fname.GetFullPath(), filepoint, filelimit) + ); + text = wxT(""); + } + + } + + } + + }; + break; + + + /* Video Media Header box */ + case (VMHD_BOX): { + + unsigned long int version; + unsigned short int graphicsmode, opcolor[3]; + char graphicsdescr[100]; + + fileid->Read(&version, sizeof(unsigned long int)); + version = BYTE_SWAP4(version); + + fileid->Read(&graphicsmode, sizeof(unsigned short int)); + graphicsmode = BYTE_SWAP2(graphicsmode); + switch (graphicsmode) { + case (0x00): + strcpy(graphicsdescr, "copy"); + break; + case (0x24): + strcpy(graphicsdescr, "transparent"); + break; + case (0x0100): + strcpy(graphicsdescr, "alpha"); + break; + case (0x0101): + strcpy(graphicsdescr, "whitealpha"); + break; + case (0x0102): + strcpy(graphicsdescr, "blackalpha"); + break; + default: + strcpy(graphicsdescr, "unknown"); + break; + }; + + fileid->Read(opcolor, 3 * sizeof(unsigned short int)); + opcolor[0] = BYTE_SWAP2(opcolor[0]); + opcolor[1] = BYTE_SWAP2(opcolor[1]); + opcolor[2] = BYTE_SWAP2(opcolor[2]); + + wxTreeItemId currid = m_tree->AppendItem(parentid, + wxString::Format(wxT("Composition mode: %d (")) + + wxString::FromAscii(graphicsdescr) + + wxT(")"), + m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1, + new OPJMarkerData(wxT("INFO"), m_tree->m_fname.GetFullPath(), filepoint, filelimit) + ); + + currid = m_tree->AppendItem(parentid, + wxString::Format(wxT("OP color: %d %d %d"), opcolor[0], opcolor[1], opcolor[2]), + m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1, + new OPJMarkerData(wxT("INFO"), m_tree->m_fname.GetFullPath(), filepoint, filelimit) + ); + }; + break; + + + + /* MJP2 Sample Description box */ + case (MJP2_BOX): { + + unsigned short int height, width, depth; + unsigned long int horizresolution, vertresolution; + char compressor_name[32]; + fileid->Seek(24, wxFromCurrent); + fileid->Read(&width, sizeof(unsigned short int)); + width = BYTE_SWAP2(width); + fileid->Read(&height, sizeof(unsigned short int)); + height = BYTE_SWAP2(height); + fileid->Read(&horizresolution, sizeof(unsigned long int)); + horizresolution = BYTE_SWAP4(horizresolution); + fileid->Read(&vertresolution, sizeof(unsigned long int)); + vertresolution = BYTE_SWAP4(vertresolution); + fileid->Seek(6, wxFromCurrent); + fileid->Read(compressor_name, sizeof(char) * 32); + fileid->Read(&depth, sizeof(unsigned short int)); + depth = BYTE_SWAP2(depth); + wxTreeItemId currid = m_tree->AppendItem(parentid, + wxString::Format(wxT("Dimensions: %d x %d @ %d bpp"), width, height, depth), + m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1, + new OPJMarkerData(wxT("INFO"), m_tree->m_fname.GetFullPath(), filepoint, filelimit) + ); + currid = m_tree->AppendItem(parentid, + wxString::Format(wxT("Resolution: %d.%d x %d.%d"), horizresolution >> 16, horizresolution & 0x0000FFFF, + vertresolution >> 16, vertresolution & 0x0000FFFF), + m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1, + new OPJMarkerData(wxT("INFO")) + ); + currid = m_tree->AppendItem(parentid, + wxString::Format(wxT("Compressor: %.32s"), compressor_name), + m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1, + new OPJMarkerData(wxT("INFO")) + ); + jpeg2000parse(fileid, filepoint + 78, filelimit, parentid, level + 1, scansign, scanpoint); + + }; + break; + + /* Media Header box */ + case (MDHD_BOX): { + unsigned long int version; + unsigned short int language; + fileid->Read(&version, sizeof(unsigned long int)); + version = BYTE_SWAP4(version); + if (version == 0) { + unsigned long int creation_time, modification_time, timescale, duration; + fileid->Read(&creation_time, sizeof(unsigned long int)); + creation_time = BYTE_SWAP4(creation_time); + fileid->Read(&modification_time, sizeof(unsigned long int)); + modification_time = BYTE_SWAP4(modification_time); + fileid->Read(×cale, sizeof(unsigned long int)); + timescale = BYTE_SWAP4(timescale); + fileid->Read(&duration, sizeof(unsigned long int)); + duration = BYTE_SWAP4(duration); + const long unix_time = creation_time - 2082844800L; + wxTreeItemId currid = m_tree->AppendItem(parentid, + wxString::Format(wxT("Creation time: %u (%.24s)"), creation_time, ctime(&unix_time)), + m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1, + new OPJMarkerData(wxT("INFO")) + ); + const long unix_time1 = modification_time - 2082844800L; + currid = m_tree->AppendItem(parentid, + wxString::Format(wxT("Modification time: %u (%.24s)"), modification_time, ctime(&unix_time1)), + m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1, + new OPJMarkerData(wxT("INFO")) + ); + currid = m_tree->AppendItem(parentid, + wxString::Format(wxT("Timescale: %u (%.6fs)"), timescale, 1.0 / (float) timescale), + m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1, + new OPJMarkerData(wxT("INFO")) + ); + currid = m_tree->AppendItem(parentid, + wxString::Format(wxT("Duration: %u (%.3fs)"), duration, (float) duration / (float) timescale), + m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1, + new OPJMarkerData(wxT("INFO")) + ); + } else { + int8byte creation_time, modification_time, duration; + unsigned long int timescale; + fileid->Read(&creation_time, sizeof(int8byte)); + creation_time = BYTE_SWAP8(creation_time); + fileid->Read(&modification_time, sizeof(int8byte)); + modification_time = BYTE_SWAP8(modification_time); + fileid->Read(×cale, sizeof(unsigned long int)); + timescale = BYTE_SWAP4(timescale); + fileid->Read(&duration, sizeof(int8byte)); + duration = BYTE_SWAP8(duration); + wxTreeItemId currid = m_tree->AppendItem(parentid, + wxString::Format(wxT("Creation time: %u"), creation_time), + m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1, + new OPJMarkerData(wxT("INFO")) + ); + currid = m_tree->AppendItem(parentid, + wxString::Format(wxT("Modification time: %u"), modification_time), + m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1, + new OPJMarkerData(wxT("INFO")) + ); + currid = m_tree->AppendItem(parentid, + wxString::Format(wxT("Timescale: %u"), timescale), + m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1, + new OPJMarkerData(wxT("INFO")) + ); + currid = m_tree->AppendItem(parentid, + wxString::Format(wxT("Duration: %u"), duration), + m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1, + new OPJMarkerData(wxT("INFO")) + ); + } + fileid->Read(&language, sizeof(unsigned short int)); + + wxTreeItemId currid = m_tree->AppendItem(parentid, + wxString::Format(wxT("Language: %d (%c%c%c)"), language & 0xEFFF, + 0x60 + (char) ((language >> 10) & 0x001F), 0x60 + (char) ((language >> 5) & 0x001F), 0x60 + (char) ((language >> 0) & 0x001F)), + m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1, + new OPJMarkerData(wxT("INFO")) + ); + }; + break; + + /* Media Handler box */ + case (HDLR_BOX): { + unsigned long int version, predefined, temp[3]; + char handler[4], name[256]; + int namelen = wxMin(256, (filelimit - filepoint - 24)); + fileid->Read(&version, sizeof(unsigned long int)); + version = BYTE_SWAP4(version); + fileid->Read(&predefined, sizeof(unsigned long int)); + fileid->Read(handler, 4 * sizeof(char)); + fileid->Read(&temp, 3 * sizeof(unsigned long int)); + fileid->Read(name, namelen * sizeof(char)); + + wxTreeItemId currid = m_tree->AppendItem(parentid, + wxString::Format(wxT("Handler: %.4s"), handler), + m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1, + new OPJMarkerData(wxT("INFO")) + ); + + currid = m_tree->AppendItem(parentid, + wxString::Format(wxT("Name: %.255s"), name), + m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1, + new OPJMarkerData(wxT("INFO")) + ); + + } + break; + + /* not yet implemented */ + default: + break; + + }; + + return (0); +} + + +void OPJParseThread::ParseJP2File(wxFile *fileid, wxFileOffset filepoint, wxFileOffset filelimit, wxTreeItemId parentid) +{ + unsigned long int scanpoint; + + jpeg2000parse(fileid, filepoint, filelimit, parentid, 0, NULL, &scanpoint); +} + +/* the parsing function itself */ +/* + fileid = fid of the file to scan (you should open it by yourself) + filepoint = first byte where to start to scan from (usually 0) + filelimit = first byte where to stop to scan from (usually the file size) + level = set this to 0 + scansign = signature to scan for (NULL avoids search, returns " " if successful) + scanpoint = point where the scan signature lies +*/ +int OPJParseThread::jpeg2000parse(wxFile *fileid, wxFileOffset filepoint, wxFileOffset filelimit, + wxTreeItemId parentid, int level, char *scansign, unsigned long int *scanpoint) +{ + unsigned long int LBox = 0x00000000; + //int LBox_read; + char TBox[5] = "\0\0\0\0"; + //int TBox_read; + int8byte XLBox = 0x0000000000000000; + //int XLBox_read; + unsigned long int box_length = 0; + int last_box = 0, box_num = 0; + int box_type = ANY_BOX; + unsigned char /*onebyte[1], twobytes[2],*/ fourbytes[4]; + + /* cycle all over the file */ + box_num = 0; + last_box = 0; + while (!last_box) { + + /* do not exceed file limit */ + if (filepoint >= filelimit) + return (0); + + /* seek on file */ + if (fileid->Seek(filepoint, wxFromStart) == wxInvalidOffset) + return (-1); + + /* read the mandatory LBox, 4 bytes */ + if (fileid->Read(fourbytes, 4) < 4) { + WriteText(wxT("Problem reading LBox from the file (file ended?)")); + return -1; + }; + LBox = STREAM_TO_UINT32(fourbytes, 0); + + /* read the mandatory TBox, 4 bytes */ + if (fileid->Read(TBox, 4) < 4) { + WriteText(wxT("Problem reading TBox from the file (file ended?)")); + return -1; + }; + + /* look if scansign is got */ + if ((scansign != NULL) && (memcmp(TBox, scansign, 4) == 0)) { + memcpy(scansign, " ", 4); + *scanpoint = filepoint; + + /* hack/exploit */ + // stop as soon as you find the codebox + return (0); + + }; + + /* determine the box type */ + for (box_type = JP_BOX; box_type < UNK_BOX; box_type++) + if (memcmp(TBox, j22box[box_type].value, 4) == 0) + break; + + /* read the optional XLBox, 8 bytes */ + if (LBox == 1) { + + if (fileid->Read(&XLBox, 8) < 8) { + WriteText(wxT("Problem reading XLBox from the file (file ended?)")); + return -1; + }; + box_length = (unsigned long int) BYTE_SWAP8(XLBox); + + } else if (LBox == 0x00000000) { + + /* last box in file */ + last_box = 1; + box_length = filelimit - filepoint; + + } else + + box_length = LBox; + + /* show box info */ + + // append the marker + int image, imageSel; + image = m_tree->TreeCtrlIcon_Folder; + imageSel = image + 1; + wxTreeItemId currid = m_tree->AppendItem(parentid, + wxString::Format(wxT("%03d: "), box_num) + + wxString::FromAscii(TBox) + + wxString::Format(wxT(" (0x%04X)"), + ((unsigned long int) TBox[3]) + ((unsigned long int) TBox[2] << 8) + + ((unsigned long int) TBox[1] << 16) + ((unsigned long int) TBox[0] << 24) + ), + image, imageSel, + new OPJMarkerData(wxT("BOX"), m_tree->m_fname.GetFullPath(), filepoint, filepoint + box_length) + ); + + // append some info + image = m_tree->TreeCtrlIcon_File; + imageSel = image + 1; + + // box name + wxTreeItemId subcurrid1 = m_tree->AppendItem(currid, + wxT("*** ") + wxString::FromAscii(j22box[box_type].name) + wxT(" ***"), + image, imageSel, + new OPJMarkerData(wxT("INFO")) + ); + m_tree->SetItemFont(subcurrid1, *wxITALIC_FONT); + + // position and length + wxTreeItemId subcurrid2 = m_tree->AppendItem(currid, + wxLongLong(filepoint).ToString() + wxT(" > ") + wxLongLong(filepoint + box_length - 1).ToString() + + wxT(", ") + wxString::Format(wxT("%d + 8 (%d)"), box_length, box_length + 8), + image, imageSel, + new OPJMarkerData(wxT("INFO")) + ); + + /* go deep in the box */ + box_handler_function((int) box_type, fileid, (LBox == 1) ? (filepoint + 16) : (filepoint + 8), filepoint + box_length, + currid, level, scansign, scanpoint); + + /* if it's a superbox go inside it */ + if (j22box[box_type].sbox) + jpeg2000parse(fileid, (LBox == 1) ? (filepoint + 16) : (filepoint + 8), filepoint + box_length, + currid, level + 1, scansign, scanpoint); + + /* increment box number and filepoint*/ + box_num++; + filepoint += box_length; + + }; + + /* all good */ + return (0); +} + |
