# HG changeset patch # User Volker Grabsch # Date 1261561240 -3600 # Node ID 91c407bb6e1f196c33d63e336b7a68eb3f1b8754 # Parent fe658ac3b709fc15e53ce9ef5867269480c2ef77# Parent 837543941a27845f4d762508ceb2a05dbf10969c merge diff -r fe658ac3b709 -r 91c407bb6e1f .hgignore --- a/.hgignore Wed Dec 23 10:40:05 2009 +0100 +++ b/.hgignore Wed Dec 23 10:40:40 2009 +0100 @@ -1,3 +1,4 @@ +^usr/ +^log/ ^pkg/ -^usr/ ^dist/ diff -r fe658ac3b709 -r 91c407bb6e1f src/devil.mk --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/devil.mk Wed Dec 23 10:40:40 2009 +0100 @@ -0,0 +1,63 @@ +# Copyright (C) 2009 Volker Grabsch +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject +# to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +# DevIL +PKG := devil +$(PKG)_IGNORE := +$(PKG)_VERSION := 1.7.8 +$(PKG)_CHECKSUM := bc27e3e830ba666a3af03548789700d10561fcb1 +$(PKG)_SUBDIR := devil-$($(PKG)_VERSION) +$(PKG)_FILE := DevIL-$($(PKG)_VERSION).tar.gz +$(PKG)_WEBSITE := http://openil.sourceforge.net/ +$(PKG)_URL := http://$(SOURCEFORGE_MIRROR)/project/openil/DevIL/$($(PKG)_VERSION)/$($(PKG)_FILE) +$(PKG)_DEPS := gcc zlib openexr jpeg jasper lcms libmng libpng tiff sdl + +define $(PKG)_UPDATE + wget -q -O- 'http://openil.svn.sourceforge.net/viewvc/openil/tags/?sortby=date' | \ + grep ' + * avoid_extended_Photoshop_IRB_warnings +Fri Jun 19 17:57:06 CEST 2009 Volker Grabsch + * handle_extended_Photoshop_IRBs +Thu Jun 4 20:12:36 CEST 2009 Volker Grabsch + * recognize_small_corrupt_IRBs +Thu Jun 4 15:48:36 CEST 2009 Volker Grabsch + * new_function_Photoshop_valid +Thu Jun 4 13:05:49 CEST 2009 Volker Grabsch + * skip_writing_redundant_IPTC_IRBs +Tue May 19 16:03:52 CEST 2009 Volker Grabsch + * read_and_modify_only_the_first_XMP_segment +Tue May 19 14:05:38 CEST 2009 Volker Grabsch + * handle_empty_IRB +diff -rN -u old-trunk-1/src/jpgimage.cpp new-trunk-1/src/jpgimage.cpp +--- old-trunk-1/src/jpgimage.cpp 2009-06-25 17:10:32.000000000 +0200 ++++ new-trunk-1/src/jpgimage.cpp 2009-06-25 17:10:32.000000000 +0200 +@@ -87,6 +87,23 @@ + const char Photoshop::bimId_[] = "8BIM"; + const uint16_t Photoshop::iptc_ = 0x0404; + ++ bool Photoshop::valid(const byte* pPsData, ++ long sizePsData) ++ { ++ const byte *record = 0; ++ uint32_t sizeIptc = 0; ++ uint32_t sizeHdr = 0; ++ const byte* pCur = pPsData; ++ const byte* pEnd = pPsData + sizePsData; ++ int ret = 0; ++ while (pCur < pEnd ++ && 0 == (ret = Photoshop::locateIptcIrb(pCur, static_cast(pEnd - pCur), ++ &record, &sizeHdr, &sizeIptc))) { ++ pCur = record + sizeHdr + sizeIptc + (sizeIptc & 1); ++ } ++ return ret >= 0; ++ } ++ + // Todo: Generalised from JpegBase::locateIptcData without really understanding + // the format (in particular the header). So it remains to be confirmed + // if this also makes sense for psTag != Photoshop::iptc +@@ -106,7 +123,7 @@ + std::cerr << "Photoshop::locateIrb: "; + #endif + // Data should follow Photoshop format, if not exit +- while ( position <= sizePsData - 14 ++ while ( position <= sizePsData - 12 + && memcmp(pPsData + position, Photoshop::bimId_, 4) == 0) { + const byte *hrd = pPsData + position; + position += 4; +@@ -121,8 +138,8 @@ + position += psSize; + if (position + 4 > sizePsData) { + #ifndef SUPPRESS_WARNINGS +- std::cerr << "Error: " +- << "Invalid Photoshop IRB\n"; ++ std::cerr << "Warning: " ++ << "Invalid or extended Photoshop IRB\n"; + #endif + return -2; + } +@@ -130,9 +147,9 @@ + position += 4; + if (dataSize > static_cast(sizePsData - position)) { + #ifndef SUPPRESS_WARNINGS +- std::cerr << "Error: " ++ std::cerr << "Warning: " + << "Invalid Photoshop IRB data size " +- << dataSize << "\n"; ++ << dataSize << " or extended Photoshop IRB\n"; + #endif + return -2; + } +@@ -158,6 +175,13 @@ + #ifdef DEBUG + std::cerr << "pPsData doesn't start with '8BIM'\n"; + #endif ++ if (position < sizePsData) { ++#ifndef SUPPRESS_WARNINGS ++ std::cerr << "Warning: " ++ << "Invalid or extended Photoshop IRB\n"; ++#endif ++ return -2; ++ } + return 3; + } // Photoshop::locateIrb + +@@ -210,15 +234,23 @@ + // Data is padded to be even (but not included in size) + if (rawIptc.size_ & 1) psBlob.push_back(0x00); + } +- // Write existing stuff after record, data is rounded to be even. +- const uint32_t sizeOldData = sizeHdr + sizeIptc + (sizeIptc & 1); +- // Note: Because of the rounding, sizeFront + sizeOldData can be +- // _greater_ than sizePsData by 1 (not just equal), if the original +- // data was not padded. +- if (static_cast(sizePsData) > sizeFront + sizeOldData) { +- append(psBlob, record + sizeOldData, +- sizePsData - sizeFront - sizeOldData); ++ // Write existing stuff after record, ++ // skip the current and all remaining IPTC blocks ++ long pos = sizeFront; ++ while (0 == Photoshop::locateIptcIrb(pPsData + pos, sizePsData - pos, ++ &record, &sizeHdr, &sizeIptc)) { ++ const long newPos = static_cast(record - pPsData); ++ // Copy data up to the IPTC IRB ++ if (newPos > pos) { ++ append(psBlob, pPsData + pos, newPos - pos); ++ } ++ // Skip the IPTC IRB ++ pos = newPos + sizeHdr + sizeIptc + (sizeIptc & 1); ++ } ++ if (pos < sizePsData) { ++ append(psBlob, pPsData + pos, sizePsData - pos); + } ++ // Data is rounded to be even + if (psBlob.size() > 0) rc = DataBuf(&psBlob[0], static_cast(psBlob.size())); + #ifdef DEBUG + std::cerr << "IRB block at the end of Photoshop::setIptcIrb\n"; +@@ -281,9 +313,10 @@ + const long bufMinSize = 36; + long bufRead = 0; + DataBuf buf(bufMinSize); +- Blob iptcBlob; +- bool foundPsData = false; ++ Blob psBlob; ++ bool foundCompletePsData = false; + bool foundExifData = false; ++ bool foundXmpData = false; + + // Read section marker + int marker = advanceToMarker(); +@@ -297,15 +330,6 @@ + if (bufRead < 2) throw Error(15); + uint16_t size = getUShort(buf.pData_, bigEndian); + +- if (foundPsData && marker != app13_) { +- // For IPTC, decrement search only after all app13 segments are +- // loaded, assuming they all appear in sequence. But decode IPTC +- // data after the loop, in case an app13 is the last segment +- // before sos or eoi. +- foundPsData = false; +- if (--search == 0) break; +- } +- + if ( !foundExifData + && marker == app1_ && memcmp(buf.pData_ + 2, exifId_, 6) == 0) { + if (size < 8) { +@@ -328,7 +352,8 @@ + --search; + foundExifData = true; + } +- else if (marker == app1_ && memcmp(buf.pData_ + 2, xmpId_, 29) == 0) { ++ else if ( !foundXmpData ++ && marker == app1_ && memcmp(buf.pData_ + 2, xmpId_, 29) == 0) { + if (size < 31) { + rc = 6; + break; +@@ -345,9 +370,10 @@ + #endif + } + --search; ++ foundXmpData = true; + } +- else if ( marker == app13_ +- && memcmp(buf.pData_ + 2, Photoshop::ps3Id_, 14) == 0) { ++ else if ( !foundCompletePsData ++ && marker == app13_ && memcmp(buf.pData_ + 2, Photoshop::ps3Id_, 14) == 0) { + if (size < 16) { + rc = 2; + break; +@@ -357,32 +383,17 @@ + DataBuf psData(size - 16); + io_->read(psData.pData_, psData.size_); + if (io_->error() || io_->eof()) throw Error(14); +- const byte *record = 0; +- uint32_t sizeIptc = 0; +- uint32_t sizeHdr = 0; + #ifdef DEBUG + std::cerr << "Found app13 segment, size = " << size << "\n"; + //hexdump(std::cerr, psData.pData_, psData.size_); + #endif +- // Find actual IPTC data within the APP13 segment +- const byte* pEnd = psData.pData_ + psData.size_; +- const byte* pCur = psData.pData_; +- while ( pCur < pEnd +- && 0 == Photoshop::locateIptcIrb(pCur, +- static_cast(pEnd - pCur), +- &record, +- &sizeHdr, +- &sizeIptc)) { +- if (sizeIptc) { +-#ifdef DEBUG +- std::cerr << "Found IPTC IRB, size = " << sizeIptc << "\n"; +-#endif +- append(iptcBlob, record + sizeHdr, sizeIptc); +- } +- pCur = record + sizeHdr + sizeIptc; +- pCur += (sizeIptc & 1); ++ // Append to psBlob ++ append(psBlob, psData.pData_, psData.size_); ++ // Check whether psBlob is complete ++ if (Photoshop::valid(&psBlob[0], psBlob.size())) { ++ --search; ++ foundCompletePsData = true; + } +- foundPsData = true; + } + else if (marker == com_ && comment_.empty()) + { +@@ -437,6 +448,24 @@ + } + } // while there are segments to process + ++ // Find actual IPTC data within the psBlob ++ Blob iptcBlob; ++ const byte *record = 0; ++ uint32_t sizeIptc = 0; ++ uint32_t sizeHdr = 0; ++ const byte* pCur = &psBlob[0]; ++ const byte* pEnd = pCur + psBlob.size(); ++ while ( pCur < pEnd ++ && 0 == Photoshop::locateIptcIrb(pCur, static_cast(pEnd - pCur), ++ &record, &sizeHdr, &sizeIptc)) { ++#ifdef DEBUG ++ std::cerr << "Found IPTC IRB, size = " << sizeIptc << "\n"; ++#endif ++ if (sizeIptc) { ++ append(iptcBlob, record + sizeHdr, sizeIptc); ++ } ++ pCur = record + sizeHdr + sizeIptc + (sizeIptc & 1); ++ } + if ( iptcBlob.size() > 0 + && IptcParser::decode(iptcData_, + &iptcBlob[0], +@@ -489,9 +518,10 @@ + int comPos = 0; + int skipApp1Exif = -1; + int skipApp1Xmp = -1; +- int skipApp13Ps3 = -1; ++ bool foundCompletePsData = false; ++ std::vector skipApp13Ps3; + int skipCom = -1; +- DataBuf psData; ++ Blob psBlob; + DataBuf rawExif; + + // Write image header +@@ -526,24 +556,31 @@ + io_->read(rawExif.pData_, rawExif.size_); + if (io_->error() || io_->eof()) throw Error(22); + } +- else if (marker == app1_ && memcmp(buf.pData_ + 2, xmpId_, 29) == 0) { ++ else if ( skipApp1Xmp == -1 ++ && marker == app1_ && memcmp(buf.pData_ + 2, xmpId_, 29) == 0) { + if (size < 31) throw Error(22); + skipApp1Xmp = count; + ++search; + if (io_->seek(size-bufRead, BasicIo::cur)) throw Error(22); + } +- else if (marker == app13_ && memcmp(buf.pData_ + 2, Photoshop::ps3Id_, 14) == 0) { ++ else if ( !foundCompletePsData ++ && marker == app13_ && memcmp(buf.pData_ + 2, Photoshop::ps3Id_, 14) == 0) { + #ifdef DEBUG + std::cerr << "Found APP13 Photoshop PS3 segment\n"; + #endif + if (size < 16) throw Error(22); +- skipApp13Ps3 = count; +- ++search; ++ skipApp13Ps3.push_back(count); + io_->seek(16 - bufRead, BasicIo::cur); +- psData.alloc(size - 16); + // Load PS data now to allow reinsertion at any point ++ DataBuf psData(size - 16); + io_->read(psData.pData_, size - 16); + if (io_->error() || io_->eof()) throw Error(20); ++ // Append to psBlob ++ append(psBlob, psData.pData_, psData.size_); ++ // Check whether psBlob is complete ++ if (Photoshop::valid(&psBlob[0], psBlob.size())) { ++ foundCompletePsData = true; ++ } + } + else if (marker == com_ && skipCom == -1) { + if (size < 2) throw Error(22); +@@ -583,6 +620,10 @@ + if (marker < 0) throw Error(22); + ++count; + } ++ ++ if (!foundCompletePsData && skipApp13Ps3.size() > 0) throw Error(22); ++ search += skipApp13Ps3.size(); ++ + if (comPos == 0) { + if (marker == eoi_) comPos = count; + else comPos = insertPos; +@@ -591,7 +632,7 @@ + if (exifData_.count() > 0) ++search; + if (writeXmpFromPacket() == false && xmpData_.count() > 0) ++search; + if (writeXmpFromPacket() == true && xmpPacket_.size() > 0) ++search; +- if (iptcData_.count() > 0) ++search; ++ if (foundCompletePsData || iptcData_.count() > 0) ++search; + if (!comment_.empty()) ++search; + + io_->seek(seek, BasicIo::beg); +@@ -673,31 +714,44 @@ + if (outIo.error()) throw Error(21); + --search; + } +- if (psData.size_ > 0 || iptcData_.count() > 0) { ++ if (foundCompletePsData || iptcData_.count() > 0) { + // Set the new IPTC IRB, keeps existing IRBs but removes the + // IPTC block if there is no new IPTC data to write +- DataBuf newPsData = Photoshop::setIptcIrb(psData.pData_, +- psData.size_, ++ DataBuf newPsData = Photoshop::setIptcIrb(&psBlob[0], ++ psBlob.size(), + iptcData_); +- if (newPsData.size_ > 0) { +- // Write APP13 marker, new size, and ps3Id ++ const long maxChunkSize = 0xffff - 16; ++ const byte* chunkStart = newPsData.pData_; ++ const byte* chunkEnd = chunkStart + newPsData.size_; ++ while (chunkStart < chunkEnd) { ++ // Determine size of next chunk ++ long chunkSize = static_cast(chunkEnd - chunkStart); ++ if (chunkSize > maxChunkSize) { ++ chunkSize = maxChunkSize; ++ // Don't break at a valid IRB boundary ++ const long writtenSize = static_cast(chunkStart - newPsData.pData_); ++ if (Photoshop::valid(newPsData.pData_, writtenSize + chunkSize)) { ++ // Since an IRB has minimum size 12, ++ // (chunkSize - 8) can't be also a IRB boundary ++ chunkSize -= 8; ++ } ++ } ++ ++ // Write APP13 marker, chunk size, and ps3Id + tmpBuf[0] = 0xff; + tmpBuf[1] = app13_; +- +- if (newPsData.size_ + 16 > 0xffff) throw Error(37, "IPTC"); +- us2Data(tmpBuf + 2, static_cast(newPsData.size_ + 16), bigEndian); ++ us2Data(tmpBuf + 2, static_cast(chunkSize + 16), bigEndian); + std::memcpy(tmpBuf + 4, Photoshop::ps3Id_, 14); + if (outIo.write(tmpBuf, 18) != 18) throw Error(21); + if (outIo.error()) throw Error(21); + +- // Write new Photoshop IRB data buffer +- if ( outIo.write(newPsData.pData_, newPsData.size_) +- != newPsData.size_) throw Error(21); ++ // Write next chunk of the Photoshop IRB data buffer ++ if (outIo.write(chunkStart, chunkSize) != chunkSize) throw Error(21); + if (outIo.error()) throw Error(21); ++ ++ chunkStart += chunkSize; + } +- if (iptcData_.count() > 0) { +- --search; +- } ++ --search; + } + } + if (comPos == count) { +@@ -724,7 +778,7 @@ + } + else if ( skipApp1Exif == count + || skipApp1Xmp == count +- || skipApp13Ps3 == count ++ || find(skipApp13Ps3.begin(), skipApp13Ps3.end(), count) != skipApp13Ps3.end() + || skipCom == count) { + --search; + io_->seek(size-bufRead, BasicIo::cur); +diff -rN -u old-trunk-1/src/jpgimage.hpp new-trunk-1/src/jpgimage.hpp +--- old-trunk-1/src/jpgimage.hpp 2009-06-25 17:10:32.000000000 +0200 ++++ new-trunk-1/src/jpgimage.hpp 2009-06-25 17:10:32.000000000 +0200 +@@ -64,6 +64,16 @@ + static const uint16_t iptc_; //!< %Photoshop IPTC marker + + /*! ++ @brief Validates all IRBs ++ ++ @param pPsData Existing IRB buffer ++ @param sizePsData Size of the IRB buffer, may be 0 ++ @return true if all IRBs are valid;
++ false otherwise ++ */ ++ static bool valid(const byte* pPsData, ++ long sizePsData); ++ /*! + @brief Locates the data for a %Photoshop tag in a %Photoshop formated memory + buffer. Operates on raw data to simplify reuse. + @param pPsData Pointer to buffer containing entire payload of + +diff -rN -u old-trunk-1/src/jpgimage.cpp new-trunk-1/src/jpgimage.cpp +--- old-trunk-1/src/jpgimage.cpp 2009-07-03 12:02:48.000000000 +0200 ++++ new-trunk-1/src/jpgimage.cpp 2009-07-03 12:02:48.000000000 +0200 +@@ -137,7 +137,7 @@ + psSize += (psSize & 1); + position += psSize; + if (position + 4 > sizePsData) { +-#ifndef SUPPRESS_WARNINGS ++#ifdef DEBUG + std::cerr << "Warning: " + << "Invalid or extended Photoshop IRB\n"; + #endif +@@ -146,7 +146,7 @@ + uint32_t dataSize = getULong(pPsData + position, bigEndian); + position += 4; + if (dataSize > static_cast(sizePsData - position)) { +-#ifndef SUPPRESS_WARNINGS ++#ifdef DEBUG + std::cerr << "Warning: " + << "Invalid Photoshop IRB data size " + << dataSize << " or extended Photoshop IRB\n"; +@@ -176,7 +176,7 @@ + std::cerr << "pPsData doesn't start with '8BIM'\n"; + #endif + if (position < sizePsData) { +-#ifndef SUPPRESS_WARNINGS ++#ifdef DEBUG + std::cerr << "Warning: " + << "Invalid or extended Photoshop IRB\n"; + #endif + diff -r fe658ac3b709 -r 91c407bb6e1f src/exiv2.mk --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/exiv2.mk Wed Dec 23 10:40:40 2009 +0100 @@ -0,0 +1,54 @@ +# Copyright (C) 2009 Volker Grabsch +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject +# to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +# Exiv2 +PKG := exiv2 +$(PKG)_IGNORE := +$(PKG)_VERSION := 0.18.2 +$(PKG)_CHECKSUM := 452c824a780843a568eeef68f30785ee4141b0a8 +$(PKG)_SUBDIR := exiv2-$($(PKG)_VERSION) +$(PKG)_FILE := exiv2-$($(PKG)_VERSION).tar.gz +$(PKG)_WEBSITE := http://www.exiv2.org/ +$(PKG)_URL := http://www.exiv2.org/$($(PKG)_FILE) +$(PKG)_DEPS := gcc libiconv zlib expat + +define $(PKG)_UPDATE + wget -q -O- 'http://www.exiv2.org/download.html' | \ + grep 'href="exiv2-' | \ + $(SED) -n 's,.*exiv2-\([0-9][^>]*\)\.tar.*,\1,p' | \ + head -1 +endef + +define $(PKG)_BUILD + # workaround for the missing snprintf() in the of GCC-4.4.0 + $(SED) 's,#include ,#include ,' -i '$(1)/xmpsdk/src/XMPMeta.cpp' + # wine confuses the cross-compiling detection, so set it explicitly + $(SED) 's,cross_compiling=no,cross_compiling=yes,' -i '$(1)/configure' + cd '$(1)' && ./configure \ + --host='$(TARGET)' \ + --disable-shared \ + --prefix='$(PREFIX)/$(TARGET)' \ + --disable-visibility \ + --disable-nls \ + --with-expat + $(MAKE) -C '$(1)/xmpsdk/src' -j '$(JOBS)' + $(MAKE) -C '$(1)/src' -j '$(JOBS)' install-lib +endef diff -r fe658ac3b709 -r 91c407bb6e1f src/jpeg.mk --- a/src/jpeg.mk Wed Dec 23 10:40:05 2009 +0100 +++ b/src/jpeg.mk Wed Dec 23 10:40:40 2009 +0100 @@ -37,6 +37,8 @@ endef define $(PKG)_BUILD + # avoid redefinition of INT32 + $(SED) 's,#ifndef XMD_H,#if (!defined(XMD_H) \&\& !defined(_BASETSD_H)),' -i '$(1)/jmorecfg.h' cd '$(1)' && ./configure \ CC='$(TARGET)-gcc' RANLIB='$(TARGET)-ranlib' \ --disable-shared \