Removed r1830, r1826, r1825, r1824 from trunk (PGF image format)
parent
7b75bbaa04
commit
9bbfd1c186
@ -1,331 +0,0 @@
|
|||||||
// ***************************************************************** -*- C++ -*-
|
|
||||||
/*
|
|
||||||
* Copyright (C) 2004-2009 Andreas Huggel <ahuggel@gmx.net>
|
|
||||||
*
|
|
||||||
* This program is part of the Exiv2 distribution.
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
File: pgfimage.cpp
|
|
||||||
Version: $Rev: 1750 $
|
|
||||||
Author(s): Gilles Caulier (cgilles) <caulier dot gilles at gmail dot com>
|
|
||||||
History: 16-Jun-09, gc: submitted
|
|
||||||
Credits: See header file
|
|
||||||
*/
|
|
||||||
// *****************************************************************************
|
|
||||||
#include "rcsid.hpp"
|
|
||||||
EXIV2_RCSID("@(#) $Id: pgfimage.cpp 1750 2009-02-16 14:30:51Z ahuggel $")
|
|
||||||
|
|
||||||
// *****************************************************************************
|
|
||||||
|
|
||||||
#define DEBUG 1
|
|
||||||
|
|
||||||
// *****************************************************************************
|
|
||||||
// included header files
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
# include "exv_msvc.h"
|
|
||||||
#else
|
|
||||||
# include "exv_conf.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "pgfimage.hpp"
|
|
||||||
#include "image.hpp"
|
|
||||||
#include "pngimage.hpp"
|
|
||||||
#include "basicio.hpp"
|
|
||||||
#include "error.hpp"
|
|
||||||
#include "futils.hpp"
|
|
||||||
|
|
||||||
// + standard includes
|
|
||||||
#include <string>
|
|
||||||
#include <cstring>
|
|
||||||
#include <iostream>
|
|
||||||
#include <cassert>
|
|
||||||
|
|
||||||
// Signature from front of PGF file
|
|
||||||
const unsigned char pgfSignature[3] = { 0x50, 0x47, 0x46 };
|
|
||||||
|
|
||||||
const unsigned char pgfBlank[] = { 0x50,0x47,0x46,0x36,0x10,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x18,0x03,0x03,0x00,0x00,0x00,0x14,0x00,0x67,0x08,0x20,0x00,0xc0,0x01,
|
|
||||||
0x00,0x00,0x37,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x37,0x00,
|
|
||||||
0x00,0x78,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x37,0x00,0x00,0x78,0x00,0x00,
|
|
||||||
0x00,0x00,0x01,0x00,0x00,0x00,0x37,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x01,0x00,
|
|
||||||
0x00,0x00,0x37,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x37,0x00,
|
|
||||||
0x00,0x78,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00
|
|
||||||
};
|
|
||||||
|
|
||||||
// *****************************************************************************
|
|
||||||
// class member definitions
|
|
||||||
namespace Exiv2 {
|
|
||||||
|
|
||||||
PgfImage::PgfImage(BasicIo::AutoPtr io, bool create)
|
|
||||||
: Image(ImageType::pgf, mdExif | mdIptc| mdXmp | mdComment, io)
|
|
||||||
{
|
|
||||||
if (create)
|
|
||||||
{
|
|
||||||
if (io_->open() == 0)
|
|
||||||
{
|
|
||||||
#ifdef DEBUG
|
|
||||||
std::cerr << "Exiv2::PgfImage:: Creating PGF image to memory\n";
|
|
||||||
#endif
|
|
||||||
IoCloser closer(*io_);
|
|
||||||
if (io_->write(pgfBlank, sizeof(pgfBlank)) != sizeof(pgfBlank))
|
|
||||||
{
|
|
||||||
#ifdef DEBUG
|
|
||||||
std::cerr << "Exiv2::PgfImage:: Failed to create PGF image on memory\n";
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // PgfImage::PgfImage
|
|
||||||
|
|
||||||
void PgfImage::readMetadata()
|
|
||||||
{
|
|
||||||
#ifdef DEBUG
|
|
||||||
std::cerr << "Exiv2::PgfImage::readMetadata: Reading PGF file " << io_->path() << "\n";
|
|
||||||
#endif
|
|
||||||
if (io_->open() != 0)
|
|
||||||
{
|
|
||||||
throw Error(9, io_->path(), strError());
|
|
||||||
}
|
|
||||||
IoCloser closer(*io_);
|
|
||||||
// Ensure that this is the correct image type
|
|
||||||
if (!isPgfType(*io_, true))
|
|
||||||
{
|
|
||||||
if (io_->error() || io_->eof()) throw Error(14);
|
|
||||||
throw Error(3, "PGF");
|
|
||||||
}
|
|
||||||
clearMetadata();
|
|
||||||
|
|
||||||
readPgfMagicNumber(*io_);
|
|
||||||
|
|
||||||
uint32_t headerSize = readPgfHeaderSize(*io_);
|
|
||||||
|
|
||||||
readPgfHeaderStructure(*io_, &pixelWidth_, &pixelHeight_);
|
|
||||||
|
|
||||||
// And now, the most interresting, the user data byte array where metadata are stored as small image.
|
|
||||||
|
|
||||||
long size = 8 + headerSize - io_->tell();
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
std::cout << "Exiv2::PgfImage::readMetadata: Found Image data (" << size << " bytes)\n";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (size < 0) throw Error(20);
|
|
||||||
if (size == 0) return;
|
|
||||||
|
|
||||||
DataBuf imgData(size);
|
|
||||||
std::memset(imgData.pData_, 0x0, imgData.size_);
|
|
||||||
long bufRead = io_->read(imgData.pData_, imgData.size_);
|
|
||||||
if (io_->error()) throw Error(14);
|
|
||||||
if (bufRead != imgData.size_) throw Error(20);
|
|
||||||
|
|
||||||
Image::AutoPtr image = Exiv2::ImageFactory::open(imgData.pData_, imgData.size_);
|
|
||||||
image->readMetadata();
|
|
||||||
exifData() = image->exifData();
|
|
||||||
iptcData() = image->iptcData();
|
|
||||||
xmpData() = image->xmpData();
|
|
||||||
|
|
||||||
} // PgfImage::readMetadata
|
|
||||||
|
|
||||||
void PgfImage::writeMetadata()
|
|
||||||
{
|
|
||||||
if (io_->open() != 0)
|
|
||||||
{
|
|
||||||
throw Error(9, io_->path(), strError());
|
|
||||||
}
|
|
||||||
IoCloser closer(*io_);
|
|
||||||
BasicIo::AutoPtr tempIo(io_->temporary()); // may throw
|
|
||||||
assert (tempIo.get() != 0);
|
|
||||||
|
|
||||||
doWriteMetadata(*tempIo); // may throw
|
|
||||||
io_->close();
|
|
||||||
io_->transfer(*tempIo); // may throw
|
|
||||||
|
|
||||||
} // PgfImage::writeMetadata
|
|
||||||
|
|
||||||
void PgfImage::doWriteMetadata(BasicIo& outIo)
|
|
||||||
{
|
|
||||||
if (!io_->isopen()) throw Error(20);
|
|
||||||
if (!outIo.isopen()) throw Error(21);
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
std::cout << "Exiv2::PgfImage::doWriteMetadata: Writing PGF file " << io_->path() << "\n";
|
|
||||||
std::cout << "Exiv2::PgfImage::doWriteMetadata: tmp file created " << outIo.path() << "\n";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Ensure that this is the correct image type
|
|
||||||
if (!isPgfType(*io_, true))
|
|
||||||
{
|
|
||||||
if (io_->error() || io_->eof()) throw Error(20);
|
|
||||||
throw Error(22);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure PGF version.
|
|
||||||
byte mnb = readPgfMagicNumber(*io_);
|
|
||||||
|
|
||||||
readPgfHeaderSize(*io_);
|
|
||||||
|
|
||||||
int w, h;
|
|
||||||
DataBuf header = readPgfHeaderStructure(*io_, &w, &h);
|
|
||||||
|
|
||||||
Image::AutoPtr img = ImageFactory::create(ImageType::png);
|
|
||||||
|
|
||||||
img->setExifData(exifData_);
|
|
||||||
img->setIptcData(iptcData_);
|
|
||||||
img->setXmpData(xmpData_);
|
|
||||||
img->writeMetadata();
|
|
||||||
int imgSize = img->io().size();
|
|
||||||
DataBuf imgBuf = img->io().read(imgSize);
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
std::cout << "Exiv2::PgfImage::doWriteMetadata: Creating image to host metadata (" << imgSize << " bytes)\n";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//---------------------------------------------------------------
|
|
||||||
|
|
||||||
// Write PGF Signature.
|
|
||||||
if (outIo.write(pgfSignature, 3) != 3) throw Error(21);
|
|
||||||
|
|
||||||
// Write Magic number.
|
|
||||||
if (outIo.putb(mnb) == EOF) throw Error(21);
|
|
||||||
|
|
||||||
// Write new Header size.
|
|
||||||
uint32_t newHeaderSize = header.size_ + imgSize;
|
|
||||||
DataBuf buffer(4);
|
|
||||||
memcpy (buffer.pData_, &newHeaderSize, 4);
|
|
||||||
if (outIo.write(buffer.pData_, 4) != 4) throw Error(21);
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
std::cout << "Exiv2::PgfImage: new PGF header size : " << newHeaderSize << " bytes\n";
|
|
||||||
|
|
||||||
printf("%x\n", buffer.pData_[0]);
|
|
||||||
printf("%x\n", buffer.pData_[1]);
|
|
||||||
printf("%x\n", buffer.pData_[2]);
|
|
||||||
printf("%x\n", buffer.pData_[3]);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Write Header data.
|
|
||||||
if (outIo.write(header.pData_, header.size_) != header.size_) throw Error(21);
|
|
||||||
|
|
||||||
// Write new metadata byte array.
|
|
||||||
if (outIo.write(imgBuf.pData_, imgBuf.size_) != imgBuf.size_) throw Error(21);
|
|
||||||
|
|
||||||
// Copy the rest of PGF image data.
|
|
||||||
|
|
||||||
DataBuf buf(4096);
|
|
||||||
long readSize = 0;
|
|
||||||
while ((readSize=io_->read(buf.pData_, buf.size_)))
|
|
||||||
{
|
|
||||||
if (outIo.write(buf.pData_, readSize) != readSize) throw Error(21);
|
|
||||||
}
|
|
||||||
if (outIo.error()) throw Error(21);
|
|
||||||
|
|
||||||
} // PgfImage::doWriteMetadata
|
|
||||||
|
|
||||||
byte PgfImage::readPgfMagicNumber(BasicIo& iIo)
|
|
||||||
{
|
|
||||||
byte b = iIo.getb();
|
|
||||||
if (iIo.error()) throw Error(14);
|
|
||||||
|
|
||||||
if (b < 0x36) // 0x36 = '6'.
|
|
||||||
{
|
|
||||||
// Not right Magick version.
|
|
||||||
#ifdef DEBUG
|
|
||||||
std::cout << "Exiv2::PgfImage::readMetadata: wrong Magick number\n";
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
return b;
|
|
||||||
} // PgfImage::readPgfMagicNumber
|
|
||||||
|
|
||||||
uint32_t PgfImage::readPgfHeaderSize(BasicIo& iIo)
|
|
||||||
{
|
|
||||||
DataBuf buffer(4);
|
|
||||||
long bufRead = iIo.read(buffer.pData_, buffer.size_);
|
|
||||||
if (iIo.error()) throw Error(14);
|
|
||||||
if (bufRead != buffer.size_) throw Error(20);
|
|
||||||
|
|
||||||
uint32_t headerSize = 0;
|
|
||||||
memcpy (&headerSize, buffer.pData_, 4); // TODO : check endianness.
|
|
||||||
if (headerSize <= 0 ) throw Error(22);
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
std::cout << "Exiv2::PgfImage: PGF header size : " << headerSize << " bytes\n";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return headerSize;
|
|
||||||
} // PgfImage::readPgfHeaderSize
|
|
||||||
|
|
||||||
DataBuf PgfImage::readPgfHeaderStructure(BasicIo& iIo, int* width, int* height)
|
|
||||||
{
|
|
||||||
DataBuf header(16);
|
|
||||||
long bufRead = iIo.read(header.pData_, header.size_);
|
|
||||||
if (iIo.error()) throw Error(14);
|
|
||||||
if (bufRead != header.size_) throw Error(20);
|
|
||||||
|
|
||||||
memcpy(width, &header.pData_[0], 4); // TODO : check endianness.
|
|
||||||
memcpy(height, &header.pData_[4], 4); // TODO : check endianness.
|
|
||||||
|
|
||||||
/* NOTE: properties not yet used
|
|
||||||
byte nLevels = buffer.pData_[8];
|
|
||||||
byte quality = buffer.pData_[9];
|
|
||||||
byte bpp = buffer.pData_[10];
|
|
||||||
byte channels = buffer.pData_[11];
|
|
||||||
*/
|
|
||||||
byte mode = header.pData_[12];
|
|
||||||
|
|
||||||
if (mode == 2) // Indexed color image. We pass color table (256 * 3 bytes).
|
|
||||||
{
|
|
||||||
header.alloc(16 + 256*3);
|
|
||||||
|
|
||||||
bufRead = iIo.read(&header.pData_[16], 256*3);
|
|
||||||
if (iIo.error()) throw Error(14);
|
|
||||||
if (bufRead != 256*3) throw Error(20);
|
|
||||||
}
|
|
||||||
|
|
||||||
return header;
|
|
||||||
} // PgfImage::readPgfHeaderStructure
|
|
||||||
|
|
||||||
// *************************************************************************
|
|
||||||
// free functions
|
|
||||||
Image::AutoPtr newPgfInstance(BasicIo::AutoPtr io, bool create)
|
|
||||||
{
|
|
||||||
Image::AutoPtr image(new PgfImage(io, create));
|
|
||||||
if (!image->good())
|
|
||||||
{
|
|
||||||
image.reset();
|
|
||||||
}
|
|
||||||
return image;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isPgfType(BasicIo& iIo, bool advance)
|
|
||||||
{
|
|
||||||
const int32_t len = 3;
|
|
||||||
byte buf[len];
|
|
||||||
iIo.read(buf, len);
|
|
||||||
if (iIo.error() || iIo.eof())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
int rc = memcmp(buf, pgfSignature, 3);
|
|
||||||
if (!advance || rc != 0)
|
|
||||||
{
|
|
||||||
iIo.seek(-len, BasicIo::cur);
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc == 0;
|
|
||||||
}
|
|
||||||
} // namespace Exiv2
|
|
@ -1,137 +0,0 @@
|
|||||||
// ***************************************************************** -*- C++ -*-
|
|
||||||
/*
|
|
||||||
* Copyright (C) 2004-2009 Andreas Huggel <ahuggel@gmx.net>
|
|
||||||
*
|
|
||||||
* This program is part of the Exiv2 distribution.
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
/*!
|
|
||||||
@file pgfimage.hpp
|
|
||||||
@brief PGF image, implemented using the following references:
|
|
||||||
<a href="http://www.libpgf.org/uploads/media/PGF_stamm_wscg02.pdf">PGF specification</a> from libpgf web site<br>
|
|
||||||
@version $Rev: 1750 $
|
|
||||||
@author Andreas Huggel (ahu)
|
|
||||||
<a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a>
|
|
||||||
@author Gilles Caulier (cgilles)
|
|
||||||
<a href="mailto:caulier dot gilles at gmail dot com">caulier dot gilles at gmail dot com</a>
|
|
||||||
@date 16-Jun-09, gc: submitted
|
|
||||||
*/
|
|
||||||
#ifndef PGFIMAGE_HPP_
|
|
||||||
#define PGFIMAGE_HPP_
|
|
||||||
|
|
||||||
// *****************************************************************************
|
|
||||||
// included header files
|
|
||||||
#include "image.hpp"
|
|
||||||
#include "basicio.hpp"
|
|
||||||
#include "types.hpp"
|
|
||||||
|
|
||||||
// + standard includes
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
// *****************************************************************************
|
|
||||||
// namespace extensions
|
|
||||||
namespace Exiv2
|
|
||||||
{
|
|
||||||
|
|
||||||
// *****************************************************************************
|
|
||||||
// class definitions
|
|
||||||
|
|
||||||
// Add PGF to the supported image formats
|
|
||||||
namespace ImageType
|
|
||||||
{
|
|
||||||
const int pgf = 17; //!< PGF image type (see class PgfImage)
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief Class to access PGF images. Exif and IPTC metadata are supported
|
|
||||||
directly.
|
|
||||||
*/
|
|
||||||
class EXIV2API PgfImage : public Image {
|
|
||||||
public:
|
|
||||||
//! @name Creators
|
|
||||||
//@{
|
|
||||||
/*!
|
|
||||||
@brief Constructor that can either open an existing PGF image or create
|
|
||||||
a new image from scratch. If a new image is to be created, any
|
|
||||||
existing data is overwritten. Since the constructor can not return
|
|
||||||
a result, callers should check the good() method after object
|
|
||||||
construction to determine success or failure.
|
|
||||||
@param io An auto-pointer that owns a BasicIo instance used for
|
|
||||||
reading and writing image metadata. \b Important: The constructor
|
|
||||||
takes ownership of the passed in BasicIo instance through the
|
|
||||||
auto-pointer. Callers should not continue to use the BasicIo
|
|
||||||
instance after it is passed to this method. Use the Image::io()
|
|
||||||
method to get a temporary reference.
|
|
||||||
@param create Specifies if an existing image should be read (false)
|
|
||||||
or if a new file should be created (true).
|
|
||||||
*/
|
|
||||||
PgfImage(BasicIo::AutoPtr io, bool create);
|
|
||||||
//@}
|
|
||||||
|
|
||||||
//! @name Manipulators
|
|
||||||
//@{
|
|
||||||
void readMetadata();
|
|
||||||
void writeMetadata();
|
|
||||||
//@}
|
|
||||||
|
|
||||||
//! @name Accessors
|
|
||||||
//@{
|
|
||||||
std::string mimeType() const { return "image/pgf"; }
|
|
||||||
//@}
|
|
||||||
|
|
||||||
private:
|
|
||||||
//! @name NOT implemented
|
|
||||||
//@{
|
|
||||||
//! Copy constructor
|
|
||||||
PgfImage(const PgfImage& rhs);
|
|
||||||
//! Assignment operator
|
|
||||||
PgfImage& operator=(const PgfImage& rhs);
|
|
||||||
/*!
|
|
||||||
@brief Provides the main implementation of writeMetadata() by
|
|
||||||
writing all buffered metadata to the provided BasicIo.
|
|
||||||
@param oIo BasicIo instance to write to (a temporary location).
|
|
||||||
|
|
||||||
@return 4 if opening or writing to the associated BasicIo fails
|
|
||||||
*/
|
|
||||||
EXV_DLLLOCAL void doWriteMetadata(BasicIo& oIo);
|
|
||||||
//! Read Magick number. Only version >= 6 is supported.
|
|
||||||
byte readPgfMagicNumber(BasicIo& iIo);
|
|
||||||
//! Read PGF Header size encoded in 32 bits integer.
|
|
||||||
uint32_t readPgfHeaderSize(BasicIo& iIo);
|
|
||||||
//! Read header structure.
|
|
||||||
DataBuf readPgfHeaderStructure(BasicIo& iIo, int* width, int* height);
|
|
||||||
//@}
|
|
||||||
|
|
||||||
}; // class PgfImage
|
|
||||||
|
|
||||||
// *****************************************************************************
|
|
||||||
// template, inline and free functions
|
|
||||||
|
|
||||||
// These could be static private functions on Image subclasses but then
|
|
||||||
// ImageFactory needs to be made a friend.
|
|
||||||
/*!
|
|
||||||
@brief Create a new PgfImage instance and return an auto-pointer to it.
|
|
||||||
Caller owns the returned object and the auto-pointer ensures that
|
|
||||||
it will be deleted.
|
|
||||||
*/
|
|
||||||
EXIV2API Image::AutoPtr newPgfInstance(BasicIo::AutoPtr io, bool create);
|
|
||||||
|
|
||||||
//! Check if the file iIo is a PGF image.
|
|
||||||
EXIV2API bool isPgfType(BasicIo& iIo, bool advance);
|
|
||||||
|
|
||||||
} // namespace Exiv2
|
|
||||||
|
|
||||||
#endif // #ifndef PGFIMAGE_HPP_
|
|
Binary file not shown.
Loading…
Reference in New Issue