From fa7223d103e763fba7bfd2aa71814e291cc8b511 Mon Sep 17 00:00:00 2001 From: HumanDynamo Date: Mon, 12 Jun 2006 05:22:12 +0000 Subject: [PATCH] New PNG image parser to extract EXIF/IPTC RAW profiles embeded in text tags by ImageMagick/GraphicsMagick during image convertion Current implementation is read only. TODO : Fix configure rules about zlib depency require by this implementation. Optimize image loading. --- src/Makefile | 4 +- src/imgreg.cpp | 4 +- src/pngchunk.cpp | 334 +++++++++++++++++++++++++++++++++++++++++++++++ src/pngchunk.hpp | 88 +++++++++++++ src/pngimage.cpp | 187 ++++++++++++++++++++++++++ src/pngimage.hpp | 186 ++++++++++++++++++++++++++ 6 files changed, 801 insertions(+), 2 deletions(-) create mode 100644 src/pngchunk.cpp create mode 100644 src/pngchunk.hpp create mode 100644 src/pngimage.cpp create mode 100644 src/pngimage.hpp diff --git a/src/Makefile b/src/Makefile index 3f12b0d1..7318705f 100644 --- a/src/Makefile +++ b/src/Makefile @@ -75,6 +75,8 @@ CCSRC = basicio.cpp \ nikonmn.cpp \ olympusmn.cpp \ panasonicmn.cpp \ + pngimage.cpp \ + pngchunk.cpp \ sigmamn.cpp \ sonymn.cpp \ tags.cpp \ @@ -193,7 +195,7 @@ endif # Compilation shortcuts COMPILE.cc = $(CXX) $(CXXFLAGS) $(CXXDEFS) $(CXXINCS) -c COMPILE.c = $(CC) $(CFLAGS) $(DEFS) $(INCS) -c -LINK.cc = $(CXX) $(CXXFLAGS) $(LDLIBS) $(LDFLAGS) -rpath $(libdir) +LINK.cc = $(CXX) $(CXXFLAGS) $(LDLIBS) $(LDFLAGS) -lz -rpath $(libdir) # ****************************************************************************** # Rules diff --git a/src/imgreg.cpp b/src/imgreg.cpp index ee24017a..fc308e36 100644 --- a/src/imgreg.cpp +++ b/src/imgreg.cpp @@ -37,6 +37,7 @@ EXIV2_RCSID("@(#) $Id$"); #include "crwimage.hpp" #include "mrwimage.hpp" #include "tiffimage.hpp" +#include "pngimage.hpp" // + standard includes @@ -50,7 +51,8 @@ namespace Exiv2 { // Registry(ImageType::cr2, newCr2Instance, isCr2Type), Registry(ImageType::crw, newCrwInstance, isCrwType), Registry(ImageType::mrw, newMrwInstance, isMrwType), - Registry(ImageType::tiff, newTiffInstance, isTiffType) + Registry(ImageType::tiff, newTiffInstance, isTiffType), + Registry(ImageType::png, newPngInstance, isPngType) }; } // namespace Exiv2 diff --git a/src/pngchunk.cpp b/src/pngchunk.cpp new file mode 100644 index 00000000..00890dd8 --- /dev/null +++ b/src/pngchunk.cpp @@ -0,0 +1,334 @@ +// ***************************************************************** -*- C++ -*- +/* + * Copyright (C) 2006 Andreas Huggel + * + * 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: pngchunk.cpp + Version: $Rev: 816 $ + History: 07-Jun-06, gc: submitted + Credits: See header file + */ +// ***************************************************************************** +#include "rcsid.hpp" +EXIV2_RCSID("@(#) $Id: pngchunk.cpp 816 2006-06-04 15:21:19Z ahuggel $"); + +// ***************************************************************************** +// included header files +#ifdef _MSC_VER +# include "exv_msvc.h" +#else +# include "exv_conf.h" +#endif + +#define DEBUG 1 + +// some defines to make it easier +#define PNG_CHUNK_TYPE(data, index) &data[index+4] +#define PNG_CHUNK_DATA(data, index, offset) data[8+index+offset] +#define PNG_CHUNK_HEADER_SIZE 12 + +// To uncompress text chunck +#include + +#include "pngchunk.hpp" +#include "tiffparser.hpp" +#include "exif.hpp" +#include "iptc.hpp" +#include "image.hpp" +#include "error.hpp" + +// + standard includes +#include +#include +#include +#include + +// ***************************************************************************** +// class member definitions +namespace Exiv2 { + + void PngChunk::decode(Image* pImage, + const byte* pData, + long size) + { + assert(pImage != 0); + assert(pData != 0); + + // look for a tEXt chunk + long index = 8; + index += getLong(&pData[index], bigEndian) + PNG_CHUNK_HEADER_SIZE; + + while(index < size-PNG_CHUNK_HEADER_SIZE) + { + while (index < size-PNG_CHUNK_HEADER_SIZE && + strncmp((char*)PNG_CHUNK_TYPE(pData, index), "tEXt", 4) && + strncmp((char*)PNG_CHUNK_TYPE(pData, index), "zTXt", 4)) + { + if (!strncmp((char*)PNG_CHUNK_TYPE(pData, index), "IEND", 4)) + throw Error(14); + + index += getLong(&pData[index], bigEndian) + PNG_CHUNK_HEADER_SIZE; + } + + if (index < size-PNG_CHUNK_HEADER_SIZE) + { + // we found a tEXt or zTXt field + + // get the key, it's a null terminated string at the chunk start + const byte *key = &PNG_CHUNK_DATA(pData, index, 0); + + int keysize=0; + for ( ; key[keysize] != 0 ; keysize++) + { + // look if we reached the end of the file (it might be corrupted) + if (8+index+keysize >= size) + throw Error(14); + } + + DataBuf arr; + + if(!strncmp((char*)PNG_CHUNK_TYPE(pData, index), "zTXt", 4)) + { + // Extract a deflate compressed Latin-1 text chunk + +#ifdef DEBUG + std::cerr << "Exiv2::PngChunk::decode: We found a zTXt field\n"; +#endif + // we get the compression method after the key + const byte* compressionMethod = &PNG_CHUNK_DATA(pData, index, keysize+1); + if ( *compressionMethod != 0x00 ) + { + // then it isn't zlib compressed and we are sunk +#ifdef DEBUG + std::cerr << "Exiv2::PngChunk::decode: Non-standard compression method.\n"; +#endif + throw Error(14); + } + + // compressed string after the compression technique spec + const byte* compressedText = &PNG_CHUNK_DATA(pData, index, keysize+2); + uint compressedTextSize = getLong(&pData[index], bigEndian)-keysize-2; + + // security check, also considering overflow wraparound from the addition -- + // we may endup with a /smaller/ index if we wrap all the way around + long firstIndex = (long)(compressedText - pData); + long onePastLastIndex = firstIndex + compressedTextSize; + if ( onePastLastIndex > size || onePastLastIndex <= firstIndex) + throw Error(14); + + uLongf uncompressedLen = compressedTextSize * 2; // just a starting point + int zlibResult; + + do + { + arr.alloc(uncompressedLen); + zlibResult = uncompress((Bytef*)arr.pData_, &uncompressedLen, + compressedText, compressedTextSize); + + if (Z_OK == zlibResult) + { + // then it is all OK + arr.alloc(uncompressedLen); + } + else if (Z_BUF_ERROR == zlibResult) + { + // the uncompressedArray needs to be larger +#ifdef DEBUG + std::cerr << "Exiv2::PngChunk::decode: doubling size for decompression.\n"; +#endif + uncompressedLen *= 2; + + // DoS protection. can't be bigger than 64k + if ( uncompressedLen > 131072 ) + break; + } + else + { + // something bad happened + throw Error(14); + } + } + while (Z_BUF_ERROR == zlibResult); + + if (zlibResult != Z_OK) + throw Error(14); + } + else if (!strncmp((char*)PNG_CHUNK_TYPE(pData, index), "tEXt", 4)) + { + // Extract a non-compressed Latin-1 text chunk +#ifdef DEBUG + std::cerr << "Exiv2::PngChunk::decode: We found a tEXt field\n"; +#endif + // the text comes after the key, but isn't null terminated + const byte* text = &PNG_CHUNK_DATA(pData, index, keysize+1); + long textsize = getLong(&pData[index], bigEndian)-keysize-1; + + // security check, also considering overflow wraparound from the addition -- + // we may endup with a /smaller/ index if we wrap all the way around + long firstIndex = (long)(text - pData); + long onePastLastIndex = firstIndex + textsize; + + if ( onePastLastIndex > size || onePastLastIndex <= firstIndex) + throw Error(14); + + arr.alloc(textsize); + arr = DataBuf(text, textsize); + } + else + { +#ifdef DEBUG + std::cerr << "Exiv2::PngChunk::decode: We found a field, not expected though\n"; +#endif + throw Error(14); + } + +#ifdef DEBUG + std::cerr << "Exiv2::PngChunk::decode: Found PNG entry " << std::string((const char*)key) << " / " + << std::string((const char*)arr.pData_, 64) << "\n"; +#endif + + // We look if an EXIF raw profile exist. + + if ( memcmp("Raw profile type exif", key, 21) == 0 || + memcmp("Raw profile type APP1", key, 21) == 0 ) + { + DataBuf exifData = readRawProfile(arr); + long length = exifData.size_; + + if (length > 0) + { + // Find the position of Exif header in bytes array. + + const byte exifHeader[] = { 0x45, 0x78, 0x69, 0x66, 0x00, 0x00 }; + long pos = -1; + + for (long i=0 ; i < length-(long)sizeof(exifHeader) ; i++) + { + if (memcmp(exifHeader, &exifData.pData_[i], sizeof(exifHeader)) == 0) + { + pos = i; + break; + } + } + + // If found it, store only these data at from this place. + + if (pos !=-1) + { +#ifdef DEBUG + std::cerr << "Exiv2::PngChunk::decode: Exif header found at position " << pos << "\n"; +#endif + pos = pos + sizeof(exifHeader); + TiffParser::decode(pImage, exifData.pData_+pos, length-pos, TiffCreator::create); + } + } + } + + // We look if an IPTC raw profile exist. + + if ( memcmp("Raw profile type iptc", key, 21) == 0 ) + { + DataBuf iptcData = readRawProfile(arr); + long length = iptcData.size_; + + if (length > 0) + pImage->iptcData().load(iptcData.pData_, length); + } + + index += getLong(&pData[index], bigEndian) + PNG_CHUNK_HEADER_SIZE; + } + } + + } // PngChunk::decode + + DataBuf PngChunk::readRawProfile(const DataBuf& text) + { + DataBuf info; + register long i; + register unsigned char *dp; + const char *sp; + uint nibbles; + long length; + unsigned char unhex[103]={0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,1, 2,3,4,5,6,7,8,9,0,0, + 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,10,11,12, + 13,14,15}; + + sp = (char*)text.pData_+1; + + // Look for newline + + while (*sp != '\n') + sp++; + + // Look for length + + while (*sp == '\0' || *sp == ' ' || *sp == '\n') + sp++; + + length = (long) atol(sp); + + while (*sp != ' ' && *sp != '\n') + sp++; + + // Allocate space + + if (length == 0) + { + std::cerr << "Exiv2::PngChunk::readRawProfile: Unable To Copy Raw Profile: invalid profile length\n"; + return DataBuf(); + } + + info.alloc(length); + + if (info.size_ != length) + { + std::cerr << "Exiv2::PngChunk::readRawProfile: Unable To Copy Raw Profile: cannot allocate memory\n"; + return DataBuf(); + } + + // Copy profile, skipping white space and column 1 "=" signs + + dp = (unsigned char*)info.pData_; + nibbles = length * 2; + + for (i = 0; i < (long) nibbles; i++) + { + while (*sp < '0' || (*sp > '9' && *sp < 'a') || *sp > 'f') + { + if (*sp == '\0') + { + std::cerr << "Exiv2::PngChunk::readRawProfile: Unable To Copy Raw Profile: ran out of data\n"; + return DataBuf(); + } + + sp++; + } + + if (i%2 == 0) + *dp = (unsigned char) (16*unhex[(int) *sp++]); + else + (*dp++) += unhex[(int) *sp++]; + } + + return info; + } // PngChunk::readRawProfile +} // namespace Exiv2 diff --git a/src/pngchunk.hpp b/src/pngchunk.hpp new file mode 100644 index 00000000..dea485a2 --- /dev/null +++ b/src/pngchunk.hpp @@ -0,0 +1,88 @@ +// ***************************************************************** -*- C++ -*- +/* + * Copyright (C) 2006 Andreas Huggel + * + * 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 pngchunk.hpp + @brief Class PngChunk to parse PNG chunk data. + @version $Rev: 808 $ + @author Andreas Huggel (ahu) + ahuggel@gmx.net + @author Gilles Caulier (gc) + caulier dot gilles at kdemail dot net + @date 13-Jun-06, gc: submitted + */ +#ifndef PNGCHUNK_HPP_ +#define PNGCHUNK_HPP_ + +// ***************************************************************************** +// included header files +#include "types.hpp" + +// + standard includes +#include +#include + +// ***************************************************************************** +// namespace extensions +namespace Exiv2 { + +// ***************************************************************************** +// class declarations + + class Image; + +// ***************************************************************************** +// class definitions + + /*! + @brief Stateless parser class for data in PNG chunk format. Images use this + class to decode and encode PNG-based data. + */ + class PngChunk { + public: + /*! + @brief Decode PNG chunk metadata from a data buffer \em pData of length + \em size into \em pImage. + + @param pImage Pointer to the image to hold the metadata + @param pData Pointer to the data buffer. Must point to PNG chunk data; + no checks are performed. + @param size Length of the data buffer. + */ + static void decode(Image* pImage, + const byte* pData, + long size); + + private: + //! @name Accessors + //@{ + + /*! + @brief Todo: Decode ImageMagick raw text profile including encoded Exif/Iptc metadata byte array. + */ + static DataBuf readRawProfile(const DataBuf& text); + + //@} + + }; // class PngChunk + +} // namespace Exiv2 + +#endif // #ifndef PNGCHUNK_HPP_ diff --git a/src/pngimage.cpp b/src/pngimage.cpp new file mode 100644 index 00000000..a336e0a2 --- /dev/null +++ b/src/pngimage.cpp @@ -0,0 +1,187 @@ +// ***************************************************************** -*- C++ -*- +/* + * Copyright (C) 2006 Andreas Huggel + * + * 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: pngimage.cpp + Version: $Rev: 808 $ + History: 07-Jun-06, gc: submitted + Credits: See header file + */ +// ***************************************************************************** +#include "rcsid.hpp" +EXIV2_RCSID("@(#) $Id: pngimage.cpp 808 2006-06-01 15:09:39Z ahuggel $"); + +// ***************************************************************************** + +#define DEBUG 1 + +// ***************************************************************************** +// included header files +#ifdef _MSC_VER +# include "exv_msvc.h" +#else +# include "exv_conf.h" +#endif + +#include "pngchunk.hpp" +#include "pngimage.hpp" +#include "image.hpp" +#include "basicio.hpp" +#include "error.hpp" +#include "futils.hpp" + +// + standard includes +#include +#include +#include +#include + +// ***************************************************************************** +// class member definitions +namespace Exiv2 { + + PngImage::PngImage(BasicIo::AutoPtr io, bool create) + : Image(mdExif | mdIptc), io_(io) + { + if (create) + { + IoCloser closer(*io_); + io_->open(); + } + } // PngImage::PngImage + + bool PngImage::good() const + { + if (io_->open() != 0) return false; + IoCloser closer(*io_); + return isThisType(*io_, false); + } + + void PngImage::clearMetadata() + { + clearExifData(); + } + + void PngImage::setMetadata(const Image& image) + { + setExifData(image.exifData()); + } + + void PngImage::clearExifData() + { + exifData_.clear(); + } + + void PngImage::setExifData(const ExifData& exifData) + { + exifData_ = exifData; + } + + void PngImage::clearIptcData() + { + iptcData_.clear(); + } + + void PngImage::setIptcData(const IptcData& iptcData) + { + iptcData_ = iptcData; + } + + void PngImage::clearComment() + { + // not supported + } + + void PngImage::setComment(const std::string& comment) + { + // not supported + } + + void PngImage::readMetadata() + { +#ifdef DEBUG + std::cerr << "Exiv2::PngImage::readMetadata: Reading PNG 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 (!isThisType(*io_, false)) + { + if (io_->error() || io_->eof()) throw Error(14); + throw Error(3, "PNG"); + } + + clearMetadata(); + + DataBuf buf = io_->read(io_->size()); + if (io_->error() || io_->eof()) throw Error(14); + + PngChunk::decode(this, buf.pData_, buf.size_); + + } // PngImage::readMetadata + + void PngImage::writeMetadata() + { + /* + TODO: implement me! + */ + } // PngImage::writeMetadata + + bool PngImage::isThisType(BasicIo& iIo, bool advance) const + { + return isPngType(iIo, advance); + } + + // ************************************************************************* + // free functions + + Image::AutoPtr newPngInstance(BasicIo::AutoPtr io, bool create) + { + Image::AutoPtr image(new PngImage(io, create)); + if (!image->good()) + { + image.reset(); + } + return image; + } + + bool isPngType(BasicIo& iIo, bool advance) + { + const int32_t len = 8; + const unsigned char pngID[8] = {'\211', 'P', 'N', 'G', '\r', '\n', '\032', '\n'}; + byte buf[len]; + iIo.read(buf, len); + if (iIo.error() || iIo.eof()) + { + return false; + } + int rc = memcmp(buf, pngID, 8); + if (!advance || rc != 0) + { + iIo.seek(-len, BasicIo::cur); + } + + return rc == 0; + } +} // namespace Exiv2 diff --git a/src/pngimage.hpp b/src/pngimage.hpp new file mode 100644 index 00000000..92c120cf --- /dev/null +++ b/src/pngimage.hpp @@ -0,0 +1,186 @@ +// ***************************************************************** -*- C++ -*- +/* + * Copyright (C) 2006 Andreas Huggel + * + * 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 pngimage.hpp + @brief PNG image, implemented using the following references: + PNG specification by W3C
+ PNG tags list by Phil Harvey
+ @version $Rev: 797 $ + @author Andreas Huggel (ahu) + ahuggel@gmx.net + @author Gilles Caulier (gc) + caulier dot gilles at kdemail dot net + @date 07-Jun-06, gc: submitted + */ +#ifndef PNGIMAGE_HPP_ +#define PNGIMAGE_HPP_ + +// ***************************************************************************** +// included header files +#include "exif.hpp" +#include "iptc.hpp" +#include "image.hpp" + +// + standard includes +#include + +// ***************************************************************************** +// namespace extensions +namespace Exiv2 { + +// ***************************************************************************** +// class definitions + + // Add PNG to the supported image formats + namespace ImageType { + const int png = 6; //!< PNG image type (see class PngImage) + } + + /*! + @brief Class to access raw PNG images. Exif/IPTC metadata are supported + directly. + */ + class PngImage : public Image { + friend bool isPngType(BasicIo& iIo, bool advance); + + //! @name NOT Implemented + //@{ + //! Copy constructor + PngImage(const PngImage& rhs); + //! Assignment operator + PngImage& operator=(const PngImage& rhs); + //@} + + public: + //! @name Creators + //@{ + /*! + @brief Constructor that can either open an existing PNG 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). + */ + PngImage(BasicIo::AutoPtr io, bool create); + //! Destructor + ~PngImage() {} + //@} + + //! @name Manipulators + //@{ + void readMetadata(); + /*! + @brief Todo: Write metadata back to the image. This method is not + yet implemented. + */ + void writeMetadata(); + void setExifData(const ExifData& exifData); + void clearExifData(); + void setIptcData(const IptcData& iptcData); + void clearIptcData(); + /*! + @brief Not supported. PNG format does not contain a comment. + Calling this function will do nothing. + */ + void setComment(const std::string& comment); + /*! + @brief Not supported. PNG format does not contain a comment. + Calling this function will do nothing. + */ + void clearComment(); + void setMetadata(const Image& image); + void clearMetadata(); + ExifData& exifData() { return exifData_; } + IptcData& iptcData() { return iptcData_; } + //@} + + //! @name Accessors + //@{ + bool good() const; + const ExifData& exifData() const { return exifData_; } + const IptcData& iptcData() const { return iptcData_; } + std::string comment() const { return comment_; } + BasicIo& io() const { return *io_; } + //@} + + private: + //! @name Accessors + //@{ + /*! + @brief Determine if the content of the BasicIo instance is a PNG image. + + The advance flag determines if the read position in the stream is + moved (see below). This applies only if the type matches and the + function returns true. If the type does not match, the stream + position is not changed. However, if reading from the stream fails, + the stream position is undefined. Consult the stream state to obtain + more information in this case. + + @param iIo BasicIo instance to read from. + @param advance Flag indicating whether the position of the io + should be advanced by the number of characters read to + analyse the data (true) or left at its original + position (false). This applies only if the type matches. + @return true if the data matches the type of this class;
+ false if the data does not match + */ + bool isThisType(BasicIo& iIo, bool advance) const; + /*! + @brief Todo: Write PNG header. Not implemented yet. + */ + int writeHeader(BasicIo& oIo) const; + + //@} + + // DATA + BasicIo::AutoPtr io_; //!< Image data io pointer + ExifData exifData_; //!< Exif data container + IptcData iptcData_; //!< IPTC data container + std::string comment_; //!< User comment + + }; // class PngImage + +// ***************************************************************************** +// 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 PngImage instance and return an auto-pointer to it. + Caller owns the returned object and the auto-pointer ensures that + it will be deleted. + */ + Image::AutoPtr newPngInstance(BasicIo::AutoPtr io, bool create); + + //! Check if the file iIo is a PNG image. + bool isPngType(BasicIo& iIo, bool advance); + +} // namespace Exiv2 + +#endif // #ifndef PNGIMAGE_HPP_