|
|
@ -448,11 +448,13 @@ namespace Exiv2
|
|
|
|
|
|
|
|
|
|
|
|
void Jp2Image::printStructure(std::ostream& out, PrintStructureOption option, int depth)
|
|
|
|
void Jp2Image::printStructure(std::ostream& out, PrintStructureOption option, int depth)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (io_->open() != 0) throw Error(kerDataSourceOpenFailed, io_->path(), strError());
|
|
|
|
if (io_->open() != 0)
|
|
|
|
|
|
|
|
throw Error(kerDataSourceOpenFailed, io_->path(), strError());
|
|
|
|
|
|
|
|
|
|
|
|
// Ensure that this is the correct image type
|
|
|
|
// Ensure that this is the correct image type
|
|
|
|
if (!isJp2Type(*io_, false)) {
|
|
|
|
if (!isJp2Type(*io_, false)) {
|
|
|
|
if (io_->error() || io_->eof()) throw Error(kerFailedToReadImageData);
|
|
|
|
if (io_->error() || io_->eof())
|
|
|
|
|
|
|
|
throw Error(kerFailedToReadImageData);
|
|
|
|
throw Error(kerNotAJpeg);
|
|
|
|
throw Error(kerNotAJpeg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -482,44 +484,47 @@ namespace Exiv2
|
|
|
|
box.type = getLong((byte*)&box.type, bigEndian);
|
|
|
|
box.type = getLong((byte*)&box.type, bigEndian);
|
|
|
|
|
|
|
|
|
|
|
|
if (bPrint) {
|
|
|
|
if (bPrint) {
|
|
|
|
out << Internal::stringFormat("%8ld | %8ld | ",(size_t)(position-sizeof(box)),(size_t) box.length) << toAscii(box.type) << " | " ;
|
|
|
|
out << Internal::stringFormat("%8ld | %8ld | ", (size_t)(position - sizeof(box)),
|
|
|
|
|
|
|
|
(size_t)box.length)
|
|
|
|
|
|
|
|
<< toAscii(box.type) << " | ";
|
|
|
|
bLF = true;
|
|
|
|
bLF = true;
|
|
|
|
if ( box.type == kJp2BoxTypeClose ) lf(out,bLF);
|
|
|
|
if (box.type == kJp2BoxTypeClose)
|
|
|
|
|
|
|
|
lf(out, bLF);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ( box.type == kJp2BoxTypeClose ) break;
|
|
|
|
if (box.type == kJp2BoxTypeClose)
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
switch(box.type)
|
|
|
|
switch (box.type) {
|
|
|
|
{
|
|
|
|
case kJp2BoxTypeJp2Header: {
|
|
|
|
case kJp2BoxTypeJp2Header:
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
lf(out, bLF);
|
|
|
|
lf(out, bLF);
|
|
|
|
|
|
|
|
|
|
|
|
while (io_->read((byte*)&subBox, sizeof(subBox)) == sizeof(subBox)
|
|
|
|
while (io_->read((byte*)&subBox, sizeof(subBox)) == sizeof(subBox) &&
|
|
|
|
&& io_->tell() < position + (long) box.length) // don't read beyond the box!
|
|
|
|
io_->tell() < position + (long)box.length) // don't read beyond the box!
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int address = io_->tell() - sizeof(subBox);
|
|
|
|
int address = io_->tell() - sizeof(subBox);
|
|
|
|
subBox.length = getLong((byte*)&subBox.length, bigEndian);
|
|
|
|
subBox.length = getLong((byte*)&subBox.length, bigEndian);
|
|
|
|
subBox.type = getLong((byte*)&subBox.type, bigEndian);
|
|
|
|
subBox.type = getLong((byte*)&subBox.type, bigEndian);
|
|
|
|
|
|
|
|
|
|
|
|
// subBox.length makes no sense if it is larger than the rest of the file
|
|
|
|
if (subBox.length < sizeof(box) || subBox.length > io_->size() - io_->tell()) {
|
|
|
|
if (subBox.length > io_->size() - io_->tell()) {
|
|
|
|
|
|
|
|
throw Error(kerCorruptedMetadata);
|
|
|
|
throw Error(kerCorruptedMetadata);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DataBuf data(subBox.length - sizeof(box));
|
|
|
|
DataBuf data(subBox.length - sizeof(box));
|
|
|
|
io_->read(data.pData_, data.size_);
|
|
|
|
io_->read(data.pData_, data.size_);
|
|
|
|
if (bPrint) {
|
|
|
|
if (bPrint) {
|
|
|
|
out << Internal::stringFormat("%8ld | %8ld | sub:",(size_t)address,(size_t)subBox.length)
|
|
|
|
out << Internal::stringFormat("%8ld | %8ld | sub:", (size_t)address,
|
|
|
|
<< toAscii(subBox.type)
|
|
|
|
(size_t)subBox.length)
|
|
|
|
<<" | " << Internal::binaryToString(makeSlice(data, 0, 30));
|
|
|
|
<< toAscii(subBox.type) << " | "
|
|
|
|
|
|
|
|
<< Internal::binaryToString(makeSlice(data, 0, 30));
|
|
|
|
bLF = true;
|
|
|
|
bLF = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if(subBox.type == kJp2BoxTypeColorHeader)
|
|
|
|
if (subBox.type == kJp2BoxTypeColorHeader) {
|
|
|
|
{
|
|
|
|
|
|
|
|
long pad = 3; // don't know why there are 3 padding bytes
|
|
|
|
long pad = 3; // don't know why there are 3 padding bytes
|
|
|
|
if (bPrint) {
|
|
|
|
if (bPrint) {
|
|
|
|
out << " | pad:";
|
|
|
|
out << " | pad:";
|
|
|
|
for ( int i = 0 ; i < 3 ; i++ ) out<< " " << (int) data.pData_[i];
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
|
|
|
|
|
|
out << " " << (int)data.pData_[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
long iccLength = getULong(data.pData_ + pad, bigEndian);
|
|
|
|
long iccLength = getULong(data.pData_ + pad, bigEndian);
|
|
|
|
if (bPrint) {
|
|
|
|
if (bPrint) {
|
|
|
@ -533,11 +538,8 @@ namespace Exiv2
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
} break;
|
|
|
|
|
|
|
|
|
|
|
|
case kJp2BoxTypeUuid:
|
|
|
|
case kJp2BoxTypeUuid: {
|
|
|
|
{
|
|
|
|
if (io_->read((byte*)&uuid, sizeof(uuid)) == sizeof(uuid)) {
|
|
|
|
|
|
|
|
|
|
|
|
if (io_->read((byte*)&uuid, sizeof(uuid)) == sizeof(uuid))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
bool bIsExif = memcmp(uuid.uuid, kJp2UuidExif, sizeof(uuid)) == 0;
|
|
|
|
bool bIsExif = memcmp(uuid.uuid, kJp2UuidExif, sizeof(uuid)) == 0;
|
|
|
|
bool bIsIPTC = memcmp(uuid.uuid, kJp2UuidIptc, sizeof(uuid)) == 0;
|
|
|
|
bool bIsIPTC = memcmp(uuid.uuid, kJp2UuidIptc, sizeof(uuid)) == 0;
|
|
|
|
bool bIsXMP = memcmp(uuid.uuid, kJp2UuidXmp, sizeof(uuid)) == 0;
|
|
|
|
bool bIsXMP = memcmp(uuid.uuid, kJp2UuidXmp, sizeof(uuid)) == 0;
|
|
|
@ -545,17 +547,23 @@ namespace Exiv2
|
|
|
|
bool bUnknown = !(bIsExif || bIsIPTC || bIsXMP);
|
|
|
|
bool bUnknown = !(bIsExif || bIsIPTC || bIsXMP);
|
|
|
|
|
|
|
|
|
|
|
|
if (bPrint) {
|
|
|
|
if (bPrint) {
|
|
|
|
if ( bIsExif ) out << "Exif: " ;
|
|
|
|
if (bIsExif)
|
|
|
|
if ( bIsIPTC ) out << "IPTC: " ;
|
|
|
|
out << "Exif: ";
|
|
|
|
if ( bIsXMP ) out << "XMP : " ;
|
|
|
|
if (bIsIPTC)
|
|
|
|
if ( bUnknown) out << "????: " ;
|
|
|
|
out << "IPTC: ";
|
|
|
|
|
|
|
|
if (bIsXMP)
|
|
|
|
|
|
|
|
out << "XMP : ";
|
|
|
|
|
|
|
|
if (bUnknown)
|
|
|
|
|
|
|
|
out << "????: ";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DataBuf rawData;
|
|
|
|
DataBuf rawData;
|
|
|
|
rawData.alloc(box.length - sizeof(uuid) - sizeof(box));
|
|
|
|
rawData.alloc(box.length - sizeof(uuid) - sizeof(box));
|
|
|
|
long bufRead = io_->read(rawData.pData_, rawData.size_);
|
|
|
|
long bufRead = io_->read(rawData.pData_, rawData.size_);
|
|
|
|
if (io_->error()) throw Error(kerFailedToReadImageData);
|
|
|
|
if (io_->error())
|
|
|
|
if (bufRead != rawData.size_) throw Error(kerInputDataReadFailed);
|
|
|
|
throw Error(kerFailedToReadImageData);
|
|
|
|
|
|
|
|
if (bufRead != rawData.size_)
|
|
|
|
|
|
|
|
throw Error(kerInputDataReadFailed);
|
|
|
|
|
|
|
|
|
|
|
|
if (bPrint) {
|
|
|
|
if (bPrint) {
|
|
|
|
out << Internal::binaryToString(makeSlice(rawData, 0, 40));
|
|
|
|
out << Internal::binaryToString(makeSlice(rawData, 0, 40));
|
|
|
@ -563,35 +571,34 @@ namespace Exiv2
|
|
|
|
}
|
|
|
|
}
|
|
|
|
lf(out, bLF);
|
|
|
|
lf(out, bLF);
|
|
|
|
|
|
|
|
|
|
|
|
if(bIsExif && bRecursive && rawData.size_ > 0)
|
|
|
|
if (bIsExif && bRecursive && rawData.size_ > 0) {
|
|
|
|
{
|
|
|
|
if ((rawData.pData_[0] == rawData.pData_[1]) &&
|
|
|
|
if ( (rawData.pData_[0] == rawData.pData_[1])
|
|
|
|
(rawData.pData_[0] == 'I' || rawData.pData_[0] == 'M')) {
|
|
|
|
&& (rawData.pData_[0]=='I' || rawData.pData_[0]=='M' )
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
BasicIo::AutoPtr p = BasicIo::AutoPtr(new MemIo(rawData.pData_, rawData.size_));
|
|
|
|
BasicIo::AutoPtr p = BasicIo::AutoPtr(new MemIo(rawData.pData_, rawData.size_));
|
|
|
|
printTiffStructure(*p, out, option, depth);
|
|
|
|
printTiffStructure(*p, out, option, depth);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if(bIsIPTC && bRecursive)
|
|
|
|
if (bIsIPTC && bRecursive) {
|
|
|
|
{
|
|
|
|
|
|
|
|
IptcData::printStructure(out, makeSlice(rawData.pData_, 0, rawData.size_), depth);
|
|
|
|
IptcData::printStructure(out, makeSlice(rawData.pData_, 0, rawData.size_), depth);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if( bIsXMP && bXMP )
|
|
|
|
if (bIsXMP && bXMP) {
|
|
|
|
{
|
|
|
|
|
|
|
|
out.write((const char*)rawData.pData_, rawData.size_);
|
|
|
|
out.write((const char*)rawData.pData_, rawData.size_);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
} break;
|
|
|
|
|
|
|
|
|
|
|
|
default: break;
|
|
|
|
default:
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Move to the next box.
|
|
|
|
// Move to the next box.
|
|
|
|
io_->seek(static_cast<long>(position - sizeof(box) + box.length), BasicIo::beg);
|
|
|
|
io_->seek(static_cast<long>(position - sizeof(box) + box.length), BasicIo::beg);
|
|
|
|
if (io_->error()) throw Error(kerFailedToReadImageData);
|
|
|
|
if (io_->error())
|
|
|
|
if ( bPrint ) lf(out,bLF);
|
|
|
|
throw Error(kerFailedToReadImageData);
|
|
|
|
|
|
|
|
if (bPrint)
|
|
|
|
|
|
|
|
lf(out, bLF);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} // JpegBase::printStructure
|
|
|
|
} // JpegBase::printStructure
|
|
|
|