1
// ***************************************************************** -*- C++ -*-
3
* Copyright (C) 2004-2008 Andreas Huggel <ahuggel@gmx.net>
5
* This program is part of the Exiv2 distribution.
7
* This program is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU General Public License
9
* as published by the Free Software Foundation; either version 2
10
* of the License, or (at your option) any later version.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
17
* You should have received a copy of the GNU General Public License
18
* along with this program; if not, write to the Free Software
19
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA.
24
Author(s): Marco Piovanelli, Ovolab (marco)
25
History: 12-Mar-2007, marco: created
27
// *****************************************************************************
29
EXIV2_RCSID("@(#) $Id$")
33
// *****************************************************************************
34
// included header files
36
# include "exv_msvc.h"
38
# include "exv_conf.h"
40
#include "jp2image.hpp"
42
#include "basicio.hpp"
46
// + standard includes
51
// JPEG-2000 box types
52
const uint32_t kJp2BoxTypeJp2Header = 0x6a703268; // 'jp2h'
53
const uint32_t kJp2BoxTypeImageHeader = 0x69686472; // 'ihdr'
54
const uint32_t kJp2BoxTypeUuid = 0x75756964; // 'uuid'
56
// JPEG-2000 UUIDs for embedded metadata
58
// See http://www.jpeg.org/public/wg1n2600.doc for information about embedding IPTC-NAA data in JPEG-2000 files
59
// See http://www.adobe.com/devnet/xmp/pdfs/xmp_specification.pdf for information about embedding XMP data in JPEG-2000 files
60
const char* const kJp2UuidExif = "JpgTiffExif->JP2";
61
const char* const kJp2UuidIptc = "\x33\xc7\xa4\xd2\xb8\x1d\x47\x23\xa0\xba\xf1\xa3\xe0\x97\xad\x38";
62
const char* const kJp2UuidXmp = "\xbe\x7a\xcf\xcb\x97\xa9\x42\xe8\x9c\x71\x99\x94\x91\xe3\xaf\xac";
70
struct Jp2ImageHeaderBox {
73
uint16_t componentCount;
74
uint8_t bitsPerComponent;
75
uint8_t compressionType;
76
uint8_t colorspaceIsUnknown;
77
uint8_t intellectualPropertyFlag;
78
uint16_t compressionTypeProfile;
86
// *****************************************************************************
87
// class member definitions
90
Jp2Image::Jp2Image(BasicIo::AutoPtr io)
91
: Image(ImageType::jp2, mdExif | mdIptc | mdXmp, io)
93
} // Jp2Image::Jp2Image
95
void Jp2Image::setExifData(const ExifData& /*exifData*/)
97
// Todo: implement me!
98
throw(Error(32, "Exif metadata", "JP2"));
101
void Jp2Image::setIptcData(const IptcData& /*iptcData*/)
103
// Todo: implement me!
104
throw(Error(32, "IPTC metadata", "JP2"));
107
void Jp2Image::setComment(const std::string& /*comment*/)
109
// Todo: implement me!
110
throw(Error(32, "Image comment", "JP2"));
113
void Jp2Image::readMetadata()
116
std::cerr << "Exiv2::Jp2Image::readMetadata: Reading JPEG-2000 file " << io_->path() << "\n";
118
if (io_->open() != 0)
120
throw Error(9, io_->path(), strError());
122
IoCloser closer(*io_);
123
// Ensure that this is the correct image type
124
if (!isJp2Type(*io_, true))
126
if (io_->error() || io_->eof()) throw Error(14);
127
throw Error(3, "JPEG-2000");
130
Jp2BoxHeader box = {0,0};
131
Jp2BoxHeader subBox = {0,0};
132
Jp2ImageHeaderBox ihdr = {0,0,0,0,0,0,0,0};
133
Jp2UuidBox uuid = {{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
134
long curOffset = io_->tell();
136
while (io_->read((byte*)&box, sizeof(box)) == sizeof(box))
138
box.boxLength = getLong((byte*)&box.boxLength, bigEndian);
139
box.boxType = getLong((byte*)&box.boxType, bigEndian);
141
if (box.boxLength == 0)
148
case kJp2BoxTypeJp2Header:
150
if (io_->read((byte*)&subBox, sizeof(subBox)) == sizeof(subBox))
152
subBox.boxLength = getLong((byte*)&subBox.boxLength, bigEndian);
153
subBox.boxType = getLong((byte*)&subBox.boxType, bigEndian);
155
if((subBox.boxType == kJp2BoxTypeImageHeader) && (io_->read((byte*)&ihdr, sizeof(ihdr)) == sizeof(ihdr)))
157
ihdr.imageHeight = getLong((byte*)&ihdr.imageHeight, bigEndian);
158
ihdr.imageWidth = getLong((byte*)&ihdr.imageWidth, bigEndian);
159
ihdr.componentCount = getShort((byte*)&ihdr.componentCount, bigEndian);
160
ihdr.compressionTypeProfile = getShort((byte*)&ihdr.compressionTypeProfile, bigEndian);
162
pixelWidth_ = ihdr.imageWidth;
163
pixelHeight_ = ihdr.imageHeight;
169
case kJp2BoxTypeUuid:
171
if (io_->read((byte*)&uuid, sizeof(uuid)) == sizeof(uuid))
173
if(memcmp(uuid.uuid, kJp2UuidExif, sizeof(uuid)) == 0)
175
// we've hit an embedded Exif block
176
DataBuf rawExif(box.boxLength - (sizeof(box) + sizeof(uuid)));
177
io_->read(rawExif.pData_, rawExif.size_);
178
if (io_->error() || io_->eof()) throw Error(14);
179
if (exifData_.load(rawExif.pData_, rawExif.size_)) {
180
#ifndef SUPPRESS_WARNINGS
181
std::cerr << "Warning: Failed to decode Exif metadata.\n";
186
else if(memcmp(uuid.uuid, kJp2UuidIptc, sizeof(uuid)) == 0)
188
// we've hit an embedded IPTC block
189
DataBuf rawIPTC(box.boxLength - (sizeof(box) + sizeof(uuid)));
190
io_->read(rawIPTC.pData_, rawIPTC.size_);
191
if (io_->error() || io_->eof()) throw Error(14);
192
if (iptcData_.load(rawIPTC.pData_, rawIPTC.size_)) {
193
#ifndef SUPPRESS_WARNINGS
194
std::cerr << "Warning: Failed to decode IPTC metadata.\n";
199
else if(memcmp(uuid.uuid, kJp2UuidXmp, sizeof(uuid)) == 0)
201
// we've hit an embedded XMP block
202
DataBuf xmpPacket(box.boxLength - (sizeof(box) + sizeof(uuid)));
203
io_->read(xmpPacket.pData_, xmpPacket.size_);
204
if (io_->error() || io_->eof()) throw Error(14);
205
xmpPacket_.assign(reinterpret_cast<char *>(xmpPacket.pData_), xmpPacket.size_);
206
if (xmpPacket_.size() > 0 && XmpParser::decode(xmpData_, xmpPacket_)) {
207
#ifndef SUPPRESS_WARNINGS
208
std::cerr << "Warning: Failed to decode XMP metadata.\n";
222
curOffset += box.boxLength;
223
if(io_->seek(curOffset, BasicIo::beg) != 0)
225
break; // Todo: should throw an error here
228
} // Jp2Image::readMetadata
230
void Jp2Image::writeMetadata()
232
// Todo: implement me!
233
throw(Error(31, "JP2"));
234
} // Jp2Image::writeMetadata
236
// *************************************************************************
238
Image::AutoPtr newJp2Instance(BasicIo::AutoPtr io, bool /*create*/)
240
Image::AutoPtr image(new Jp2Image(io));
248
bool isJp2Type(BasicIo& iIo, bool advance)
250
// see section B.1.1 (JPEG 2000 Signature box) of JPEG-2000 specification
251
const int32_t len = 12;
252
const unsigned char Jp2Header[len] = { 0x00, 0x00, 0x00, 0x0c, 0x6a, 0x50, 0x20, 0x20, 0x0d, 0x0a, 0x87, 0x0a };
255
if (iIo.error() || iIo.eof())
259
bool matched = (memcmp(buf, Jp2Header, len) == 0);
260
if (!advance || !matched)
262
iIo.seek(-len, BasicIo::cur);