From ebea8991e57ef77eaa4963c7afa3690ca011bbca Mon Sep 17 00:00:00 2001 From: Robin Mills Date: Thu, 13 Oct 2016 08:54:00 +0000 Subject: [PATCH] #1243 Work-in-progress. Added test/data/relax.jp2 which has an embedded ICC profile. --- src/jp2image.cpp | 95 +++++++++++++++++++++++++++--------- test/data/bugfixes-test.out | Bin 1917035 -> 1923265 bytes test/data/relax.jp2 | Bin 0 -> 16298 bytes 3 files changed, 72 insertions(+), 23 deletions(-) create mode 100644 test/data/relax.jp2 diff --git a/src/jp2image.cpp b/src/jp2image.cpp index 3f11325f..4bd5acc0 100644 --- a/src/jp2image.cpp +++ b/src/jp2image.cpp @@ -51,6 +51,31 @@ const uint32_t kJp2BoxTypeImageHeader = 0x69686472; // 'ihdr' const uint32_t kJp2BoxTypeColorHeader = 0x636f6c72; // 'colr' const uint32_t kJp2BoxTypeUuid = 0x75756964; // 'uuid' +// from openjpeg-2.1.2/src/lib/openjp2/jp2.h +/*#define JPIP_JPIP 0x6a706970*/ + +#define JP2_JP 0x6a502020 /**< JPEG 2000 signature box */ +#define JP2_FTYP 0x66747970 /**< File type box */ +#define JP2_JP2H 0x6a703268 /**< JP2 header box (super-box) */ +#define JP2_IHDR 0x69686472 /**< Image header box */ +#define JP2_COLR 0x636f6c72 /**< Colour specification box */ +#define JP2_JP2C 0x6a703263 /**< Contiguous codestream box */ +#define JP2_URL 0x75726c20 /**< Data entry URL box */ +#define JP2_PCLR 0x70636c72 /**< Palette box */ +#define JP2_CMAP 0x636d6170 /**< Component Mapping box */ +#define JP2_CDEF 0x63646566 /**< Channel Definition box */ +#define JP2_DTBL 0x6474626c /**< Data Reference box */ +#define JP2_BPCC 0x62706363 /**< Bits per component box */ +#define JP2_JP2 0x6a703220 /**< File type fields */ + +/* For the future */ +/* #define JP2_RES 0x72657320 */ /**< Resolution box (super-box) */ +/* #define JP2_JP2I 0x6a703269 */ /**< Intellectual property box */ +/* #define JP2_XML 0x786d6c20 */ /**< XML box */ +/* #define JP2_UUID 0x75756994 */ /**< UUID box */ +/* #define JP2_UINF 0x75696e66 */ /**< UUID info box (super-box) */ +/* #define JP2_ULST 0x756c7374 */ /**< UUID list box */ + // JPEG-2000 UUIDs for embedded metadata // // See http://www.jpeg.org/public/wg1n2600.doc for information about embedding IPTC-NAA data in JPEG-2000 files @@ -225,7 +250,7 @@ namespace Exiv2 DataBuf icc(iccLength); ::memcpy(icc.pData_,data.pData_+pad,icc.size_); #ifdef DEBUG - const char* iccPath = "/tmp/jp2.icc"; + const char* iccPath = "/tmp/libexiv2_jp2.icc"; FILE* f = fopen(iccPath,"wb"); if ( f ) { fwrite(icc.pData_,icc.size_,1,f); @@ -269,11 +294,11 @@ namespace Exiv2 { DataBuf rawData; long bufRead; - bool bExif = memcmp(uuid.uuid, kJp2UuidExif, sizeof(uuid))==0; - bool bIptc = memcmp(uuid.uuid, kJp2UuidIptc, sizeof(uuid))==0; - bool bXMP = memcmp(uuid.uuid, kJp2UuidXmp , sizeof(uuid))==0; + bool bIsExif = memcmp(uuid.uuid, kJp2UuidExif, sizeof(uuid))==0; + bool bIsIPTC = memcmp(uuid.uuid, kJp2UuidIptc, sizeof(uuid))==0; + bool bIsXMP = memcmp(uuid.uuid, kJp2UuidXmp , sizeof(uuid))==0; - if(bExif) + if(bIsExif) { #ifdef DEBUG std::cout << "Exiv2::Jp2Image::readMetadata: Exif data found\n"; @@ -323,7 +348,7 @@ namespace Exiv2 } } - if(bIptc) + if(bIsIPTC) { #ifdef DEBUG std::cout << "Exiv2::Jp2Image::readMetadata: Iptc data found\n"; @@ -342,7 +367,7 @@ namespace Exiv2 } } - if(bXMP) + if(bIsXMP) { #ifdef DEBUG std::cout << "Exiv2::Jp2Image::readMetadata: Xmp data found\n"; @@ -394,7 +419,24 @@ namespace Exiv2 bLF = false ; } } - + /* + static std::string printGUID(const uuid& guid) + { + long* data1 = (long*) &guid.uuid[0]; + return Internal::stringFormat("{%08X,%04X,%04X,%02X%02X%02X%02X%02X%02X%02X%02X}", + + *data1,*data2,*data3,*data4, + + id->Data2, + + id->Data3, + + id->Data4[0], + + id->Data4[1], + + id->Data4[2], + + id->Data4[3], + + id->Data4[4], + + id->Data4[5], + + id->Data4[6], + + id->Data4[7]); + } +*/ void Jp2Image::printStructure(std::ostream& out, PrintStructureOption option,int depth) { if (io_->open() != 0) throw Error(9, io_->path(), strError()); @@ -408,10 +450,12 @@ namespace Exiv2 out << "STRUCTURE OF JPEG2000 FILE: " << io_->path() << std::endl; out << " address | length | box | data" << std::endl ; - bool bPrint = option==kpsBasic || option==kpsRecursive; - bool bRecursive = option == kpsRecursive; - bool bICC = option == kpsIccProfile; - if ( bPrint || option == kpsXMP || option == kpsIccProfile || option == kpsIptcErase ) { + bool bPrint = option == kpsBasic || option==kpsRecursive; + bool bRecursive = option == kpsRecursive; + bool bICC = option == kpsIccProfile; + bool bXMP = option == kpsXMP; + bool bIPTCErase = option == kpsIptcErase; + if ( bPrint || bXMP || bICC || bIPTCErase ) { long position = 0; Jp2BoxHeader box = {1,1}; @@ -445,7 +489,8 @@ namespace Exiv2 DataBuf data(subBox.length+8); io_->read(data.pData_,data.size_); - if ( bPrint ) out << Internal::stringFormat("%8ld | %8ld | sub:",restore,subBox.length) << toAscii(subBox.type) <<" | " << "yyyyyy" << std::endl; + if ( bPrint ) out << Internal::stringFormat("%8ld | %8ld | sub:",restore,subBox.length) << toAscii(subBox.type) + <<" | " << Internal::binaryToString(data.pData_,data.size_< 40 ? data.size_:40,sizeof(uuid)) << std::endl; if(subBox.type == kJp2BoxTypeColorHeader) { @@ -467,14 +512,16 @@ namespace Exiv2 if (io_->read((byte*)&uuid, sizeof(uuid)) == sizeof(uuid)) { - bool bExif = memcmp(uuid.uuid, kJp2UuidExif, sizeof(uuid))==0; - bool bIptc = memcmp(uuid.uuid, kJp2UuidIptc, sizeof(uuid))==0; - bool bXMP = memcmp(uuid.uuid, kJp2UuidXmp , sizeof(uuid))==0; + bool bIsExif = memcmp(uuid.uuid, kJp2UuidExif, sizeof(uuid))==0; + bool bIsIPTC = memcmp(uuid.uuid, kJp2UuidIptc, sizeof(uuid))==0; + bool bIsXMP = memcmp(uuid.uuid, kJp2UuidXmp , sizeof(uuid))==0; + bool bUnknown= ! (bIsExif || bIsIPTC || bIsXMP); if ( bPrint ) { - if ( bExif ) out << "Exif" ; - if ( bIptc ) out << "IPTC" ; - if ( bXMP ) out << "XMP" ; + if ( bIsExif ) out << "Exif: " ; + if ( bIsIPTC ) out << "IPTC: " ; + if ( bIsXMP ) out << "XMP : " ; + if ( bUnknown) out << "????: " ; } DataBuf rawData; @@ -483,23 +530,25 @@ namespace Exiv2 if (io_->error()) throw Error(14); if (bufRead != rawData.size_) throw Error(20); - if(bExif && bRecursive && rawData.size_ > 0) + if ( bPrint )out << Internal::binaryToString(rawData.pData_,rawData.size_< 40 ? rawData.size_:40,0); + lf(out,bLF); + + if(bIsExif && bRecursive && rawData.size_ > 0) { if ( (rawData.pData_[0] == rawData.pData_[1]) && (rawData.pData_[0]=='I' || rawData.pData_[0]=='M' ) ) { - lf(out,bLF); BasicIo::AutoPtr p = BasicIo::AutoPtr(new MemIo(rawData.pData_,rawData.size_)); TiffImage::printTiffStructure(*p,out,option,depth); } } - if(bIptc && bRecursive) + if(bIsIPTC && bRecursive) { IptcData::printStructure(out,rawData.pData_,rawData.size_,depth); } - if(bXMP && option & kpsXMP ) + if(bIsXMP && bXMP ) { out.write((const char*)rawData.pData_,rawData.size_); } diff --git a/test/data/bugfixes-test.out b/test/data/bugfixes-test.out index 473ee886234e605ad75dacb9aded7563d7bd5fab..d4e1ea86c7107a17196405e1ab45afa9456ce762 100644 GIT binary patch delta 2147 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 Sfphpf4|x3yLCwbBtN#zjp7UP- literal 0 HcmV?d00001