openjpeg/OPJViewer/source/wxj2kparser.cpp

338 lines
9.9 KiB
C++

/*
* 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"
/* From little endian to big endian, 2 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)
/* 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))
/* Markers values */
enum {
SOC_VAL = 0xFF4F,
SOT_VAL = 0xFF90,
SOD_VAL = 0xFF93,
EOC_VAL = 0xFFD9,
SIZ_VAL = 0xFF51,
COD_VAL = 0xFF52,
COC_VAL = 0xFF53,
RGN_VAL = 0xFF5E,
QCD_VAL = 0xFF5C,
QCC_VAL = 0xFF5D,
POD_VAL = 0xFF5F,
TLM_VAL = 0xFF55,
PLM_VAL = 0xFF57,
PLT_VAL = 0xFF58,
PPM_VAL = 0xFF60,
PPT_VAL = 0xFF61,
SOP_VAL = 0xFF91,
EPH_VAL = 0xFF92,
CME_VAL = 0xFF64,
#ifndef USEOLDJPWL
EPB_VAL = 0xFF66,
ESD_VAL = 0xFF67,
EPC_VAL = 0xFF68,
RED_VAL = 0xFF69
#else
EPB_VAL = 0xFF96,
ESD_VAL = 0xFF98,
EPC_VAL = 0xFF97,
RED_VAL = 0xFF99
#endif
};
// All the markers in one vector
unsigned short int marker_val[] = {
SOC_VAL, SOT_VAL, SOD_VAL, EOC_VAL,
SIZ_VAL,
COD_VAL, COC_VAL, RGN_VAL, QCD_VAL, QCC_VAL, POD_VAL,
TLM_VAL, PLM_VAL, PLT_VAL, PPM_VAL, PPT_VAL,
SOP_VAL, EPH_VAL,
CME_VAL,
EPB_VAL, ESD_VAL, EPC_VAL, RED_VAL
};
// Marker names
char *marker_name[] = {
"SOC", "SOT", "SOD", "EOC",
"SIZ",
"COD", "COC", "RGN", "QCD", "QCC", "POD",
"TLM", "PLM", "PLT", "PPM", "PPT",
"SOP", "EPH",
"CME",
"EPB", "ESD", "EPC", "RED"
};
// Marker descriptions
char *marker_descr[] = {
"Start of codestream", "Start of tile-part", "Start of data", "End of codestream",
"Image and tile size",
"Coding style default", "Coding style component", "Region-of-interest", "Quantization default",
"Quantization component", "Progression order change, default",
"Tile-part lengths, main header", "Packet length, main header", "Packets length, tile-part header",
"Packed packet headers, main header", "Packed packet headers, tile-part header",
"Start of packet", "End of packet header",
"Comment and extension",
"Error Protection Block", "Error Sensitivity Descriptor", "Error Protection Capability",
"Residual Errors Descriptor"
};
void OPJParseThread::ParseJ2KFile(wxFile *m_file, wxFileOffset offset, wxFileOffset length, wxTreeItemId parentid)
{
// check if the file is opened
if (m_file->IsOpened())
WriteText(wxT("File OK"));
else
return;
// position at the beginning
m_file->Seek(offset, wxFromStart);
//WriteText(wxString::Format(wxT("from to %d"), length));
// navigate the file
int m, inside_sod = 0, nmarks = 0, maxmarks = 10000, done = 0;
unsigned char onebyte[1];
unsigned char twobytes[2];
unsigned char fourbytes[4];
unsigned short int currmark;
unsigned short int currlen;
int lastPsot = 0, lastsotpos = 0;
WriteText(wxT("Start search..."));
while ((offset < length) && (!m_file->Eof())) {
done = 0;
// read da marka
if (m_file->Read(twobytes, 2) != 2)
break;
currmark = (((unsigned short int) twobytes[0]) << 8) + (unsigned short int) twobytes[1];
// Markers cycle
for (m = 0; m < 23; m++) {
// check the marker
if (currmark == marker_val[m]) {
if (currmark == SOD_VAL) {
// we enter SOD
currlen = 0;
inside_sod = 1;
} else if ((currmark == SOC_VAL) || (currmark == EOC_VAL) || (currmark == EPH_VAL))
currlen = 0;
else {
// read length
if (m_file->Read(twobytes, 2) != 2)
break;
currlen = (((unsigned short int) twobytes[0]) << 8) + (unsigned short int) twobytes[1];
}
// inside SOD, only some markers are allowed
if (inside_sod && (currmark != SOD_VAL) && (currmark != SOT_VAL)
&& (currmark != EOC_VAL) && (currmark != SOP_VAL) && (currmark != EPH_VAL))
break; /*randomly marker coincident data */
if (inside_sod && (currmark == SOT_VAL) && (lastPsot == 0))
inside_sod = 0; /* random data coincident with SOT, but last SOT was the last one */
if (inside_sod && (currmark == SOT_VAL))
inside_sod = 0; /* new tile part */
// here we pass to AppendItem() normal and selected item images (we
// suppose that selected image follows the normal one in the enum)
int image, imageSel;
image = m_tree->TreeCtrlIcon_Folder;
imageSel = image + 1;
// append the marker
wxTreeItemId currid = m_tree->AppendItem(parentid,
wxString::Format(wxT("%03d: %s (0x%04X)"), nmarks, marker_name[m], marker_val[m]),
image, imageSel,
new OPJMarkerData(wxT("MARK"), m_tree->m_fname.GetFullPath(), offset, offset + currlen + 1)
);
// append some info
image = m_tree->TreeCtrlIcon_File;
imageSel = image + 1;
// marker name
wxTreeItemId subcurrid1 = m_tree->AppendItem(currid,
wxT("*** ") + wxString(marker_descr[m]) + wxT(" ***"),
image, imageSel,
new OPJMarkerData(wxT("INFO"))
);
m_tree->SetItemFont(subcurrid1, *wxITALIC_FONT);
// position and length
wxTreeItemId subcurrid2 = m_tree->AppendItem(currid,
wxLongLong(offset).ToString() + wxT(" > ") + wxLongLong(offset + currlen + 1).ToString() +
wxT(", ") + wxString::Format(wxT("%d + 2 (%d)"), currlen, currlen + 2),
image, imageSel,
new OPJMarkerData(wxT("INFO"))
);
// give additional info on markers
switch (currmark) {
case SOP_VAL:
{
// read packet number
if (m_file->Read(twobytes, 2) != 2)
break;
int packnum = STREAM_TO_UINT16(twobytes, 0);;
wxTreeItemId subcurrid3 = m_tree->AppendItem(currid,
wxString::Format(wxT("Pack. no. %d"), packnum),
image, imageSel,
new OPJMarkerData(wxT("INFO"))
);
}
break;
case SIZ_VAL:
{
m_file->Seek(2, wxFromCurrent);
if (m_file->Read(fourbytes, 4) != 4)
break;
unsigned long int xsiz = STREAM_TO_UINT32(fourbytes, 0);
if (m_file->Read(fourbytes, 4) != 4)
break;
unsigned long int ysiz = STREAM_TO_UINT32(fourbytes, 0);
m_file->Seek(24, wxFromCurrent);
if (m_file->Read(twobytes, 2) != 2)
break;
unsigned short int csiz = STREAM_TO_UINT16(twobytes, 0);
if (m_file->Read(onebyte, 1) != 1)
break;
unsigned char ssiz = onebyte[0];
wxTreeItemId subcurrid3 = m_tree->AppendItem(currid,
wxString::Format(wxT("%d x %d, %d comps. @ %d bpp"), xsiz, ysiz, csiz, (ssiz + 1) & 0xEF),
image, imageSel,
new OPJMarkerData(wxT("INFO"))
);
}
break;
case SOT_VAL:
{
if (m_file->Read(twobytes, 2) != 2)
break;
unsigned short int isot = STREAM_TO_UINT16(twobytes, 0);
if (m_file->Read(fourbytes, 4) != 4)
break;
unsigned long int psot = STREAM_TO_UINT32(fourbytes, 0);
if (m_file->Read(onebyte, 1) != 1)
break;
unsigned char tpsot = onebyte[0];
if (m_file->Read(onebyte, 1) != 1)
break;
unsigned char tnsot = onebyte[0];
wxTreeItemId subcurrid3 = m_tree->AppendItem(currid,
wxString::Format(wxT("tile %d, psot = %d, part %d of %d"), isot, psot, tpsot, tnsot),
image, imageSel,
new OPJMarkerData(wxT("INFO"))
);
lastPsot = psot;
lastsotpos = offset;
};
break;
case CME_VAL:
{
#define showlen 25
unsigned char comment[showlen];
m_file->Seek(2, wxFromCurrent);
if (m_file->Read(comment, showlen) != showlen)
break;
wxTreeItemId subcurrid3 = m_tree->AppendItem(currid,
wxString::Format(wxT("%.*s%s"), wxMin(showlen, currlen - 4), comment,
(((currlen - 4) > showlen) ? "..." : "")),
image, imageSel,
new OPJMarkerData(wxT("INFO"))
);
}
break;
default:
break;
}
// increment number of markers
nmarks++;
if (nmarks >= maxmarks)
break;
// increment offset
if (currmark == SOD_VAL)
offset += lastPsot - (offset - lastsotpos);
else
offset += (2 + currlen);
m_file->Seek(offset, wxFromStart);
done = 1;
break;
}
}
if (done)
continue;
else {
offset++;
m_file->Seek(offset, wxFromStart);
}
}
}