diff --git a/src/jpgimage.cpp b/src/jpgimage.cpp index 67f6fd04..208067d8 100644 --- a/src/jpgimage.cpp +++ b/src/jpgimage.cpp @@ -904,12 +904,15 @@ namespace Exiv2 { void JpegBase::doWriteMetadata(BasicIo& outIo) { - if (!io_->isopen()) throw Error(kerInputDataReadFailed); - if (!outIo.isopen()) throw Error(kerImageWriteFailed); + if (!io_->isopen()) + throw Error(kerInputDataReadFailed); + if (!outIo.isopen()) + throw Error(kerImageWriteFailed); // Ensure that this is the correct image type if (!isThisType(*io_, true)) { - if (io_->error() || io_->eof()) throw Error(kerInputDataReadFailed); + if (io_->error() || io_->eof()) + throw Error(kerInputDataReadFailed); throw Error(kerNoImageInInputData); } @@ -924,7 +927,7 @@ namespace Exiv2 { int skipApp1Exif = -1; int skipApp1Xmp = -1; bool foundCompletePsData = false; - bool foundIccData = false; + bool foundIccData = false; std::vector skipApp13Ps3; std::vector skipApp2Icc; int skipCom = -1; @@ -933,11 +936,13 @@ namespace Exiv2 { xmpData().usePacket(writeXmpFromPacket()); // Write image header - if (writeHeader(outIo)) throw Error(kerImageWriteFailed); + if (writeHeader(outIo)) + throw Error(kerImageWriteFailed); // Read section marker int marker = advanceToMarker(); - if (marker < 0) throw Error(kerNoImageInInputData); + if (marker < 0) + throw Error(kerNoImageInInputData); // First find segments of interest. Normally app0 is first and we want // to insert after it. But if app0 comes after com, app1 and app13 then @@ -945,104 +950,120 @@ namespace Exiv2 { while (marker != sos_ && marker != eoi_ && search < 6) { // Read size and signature (ok if this hits EOF) bufRead = io_->read(buf.pData_, bufMinSize); - if (io_->error()) throw Error(kerInputDataReadFailed); + if (io_->error()) + throw Error(kerInputDataReadFailed); uint16_t size = getUShort(buf.pData_, bigEndian); if (marker == app0_) { - if (size < 2) throw Error(kerNoImageInInputData); + if (size < 2) + throw Error(kerNoImageInInputData); insertPos = count + 1; - if (io_->seek(size-bufRead, BasicIo::cur)) throw Error(kerNoImageInInputData); - } - else if ( skipApp1Exif == -1 - && marker == app1_ && memcmp(buf.pData_ + 2, exifId_, 6) == 0) { - if (size < 8) throw Error(kerNoImageInInputData); + if (io_->seek(size - bufRead, BasicIo::cur)) + throw Error(kerNoImageInInputData); + } else if (skipApp1Exif == -1 && marker == app1_ && memcmp(buf.pData_ + 2, exifId_, 6) == 0) { + if (size < 8) + throw Error(kerNoImageInInputData); skipApp1Exif = count; ++search; // Seek to beginning and read the current Exif data io_->seek(8 - bufRead, BasicIo::cur); rawExif.alloc(size - 8); io_->read(rawExif.pData_, rawExif.size_); - if (io_->error() || io_->eof()) throw Error(kerNoImageInInputData); - } - else if ( skipApp1Xmp == -1 - && marker == app1_ && memcmp(buf.pData_ + 2, xmpId_, 29) == 0) { - if (size < 31) throw Error(kerNoImageInInputData); + if (io_->error() || io_->eof()) + throw Error(kerNoImageInInputData); + } else if (skipApp1Xmp == -1 && marker == app1_ && memcmp(buf.pData_ + 2, xmpId_, 29) == 0) { + if (size < 31) + throw Error(kerNoImageInInputData); skipApp1Xmp = count; ++search; - if (io_->seek(size-bufRead, BasicIo::cur)) throw Error(kerNoImageInInputData); - } - else if ( marker == app2_ && memcmp(buf.pData_ + 2, iccId_, 11)== 0 ) { - if (size < 31) throw Error(kerNoImageInInputData); + if (io_->seek(size - bufRead, BasicIo::cur)) + throw Error(kerNoImageInInputData); + } else if (marker == app2_ && memcmp(buf.pData_ + 2, iccId_, 11) == 0) { + if (size < 31) + throw Error(kerNoImageInInputData); skipApp2Icc.push_back(count); - if ( !foundIccData ) { + if (!foundIccData) { ++search; - foundIccData = true ; + foundIccData = true; } - if (io_->seek(size-bufRead, BasicIo::cur)) throw Error(kerNoImageInInputData); - } - else if ( !foundCompletePsData - && marker == app13_ && memcmp(buf.pData_ + 2, Photoshop::ps3Id_, 14) == 0) { + if (io_->seek(size - bufRead, BasicIo::cur)) + throw Error(kerNoImageInInputData); + } 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(kerNoImageInInputData); + if (size < 16) + throw Error(kerNoImageInInputData); skipApp13Ps3.push_back(count); io_->seek(16 - bufRead, BasicIo::cur); // 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(kerInputDataReadFailed); + if (io_->error() || io_->eof()) + throw Error(kerInputDataReadFailed); // Append to psBlob append(psBlob, psData.pData_, psData.size_); // Check whether psBlob is complete - if (psBlob.size() > 0 && Photoshop::valid(&psBlob[0],(long) psBlob.size())) { + if (psBlob.size() > 0 && Photoshop::valid(&psBlob[0], (long)psBlob.size())) { foundCompletePsData = true; } - } - else if (marker == com_ && skipCom == -1) { - if (size < 2) throw Error(kerNoImageInInputData); + } else if (marker == com_ && skipCom == -1) { + if (size < 2) + throw Error(kerNoImageInInputData); // Jpegs can have multiple comments, but for now only handle // the first one (most jpegs only have one anyway). skipCom = count; ++search; - if (io_->seek(size-bufRead, BasicIo::cur)) throw Error(kerNoImageInInputData); - } - else { - if (size < 2) throw Error(kerNoImageInInputData); - if (io_->seek(size-bufRead, BasicIo::cur)) throw Error(kerNoImageInInputData); + if (io_->seek(size - bufRead, BasicIo::cur)) + throw Error(kerNoImageInInputData); + } else { + if (size < 2) + throw Error(kerNoImageInInputData); + if (io_->seek(size - bufRead, BasicIo::cur)) + throw Error(kerNoImageInInputData); } // As in jpeg-6b/wrjpgcom.c: // We will insert the new comment marker just before SOFn. // This (a) causes the new comment to appear after, rather than before, // existing comments; and (b) ensures that comments come after any JFIF // or JFXX markers, as required by the JFIF specification. - if ( comPos == 0 && inRange2(marker,sof0_,sof3_,sof5_,sof15_) ) { + if (comPos == 0 && inRange2(marker, sof0_, sof3_, sof5_, sof15_)) { comPos = count; ++search; } marker = advanceToMarker(); - if (marker < 0) throw Error(kerNoImageInInputData); + if (marker < 0) + throw Error(kerNoImageInInputData); ++count; } - if (!foundCompletePsData && psBlob.size() > 0) throw Error(kerNoImageInInputData); - search += (int) skipApp13Ps3.size() + (int) skipApp2Icc.size(); + if (!foundCompletePsData && psBlob.size() > 0) + throw Error(kerNoImageInInputData); + search += (int)skipApp13Ps3.size() + (int)skipApp2Icc.size(); if (comPos == 0) { - if (marker == eoi_) comPos = count; - else comPos = insertPos; + if (marker == eoi_) + comPos = count; + else + comPos = insertPos; ++search; } - if (exifData_.count() > 0) ++search; - if (writeXmpFromPacket() == false && xmpData_.count() > 0) ++search; - if (writeXmpFromPacket() == true && xmpPacket_.size() > 0) ++search; - if (foundCompletePsData || iptcData_.count() > 0) ++search; - if (!comment_.empty()) ++search; + if (exifData_.count() > 0) + ++search; + if (writeXmpFromPacket() == false && xmpData_.count() > 0) + ++search; + if (writeXmpFromPacket() == true && xmpPacket_.size() > 0) + ++search; + if (foundCompletePsData || iptcData_.count() > 0) + ++search; + if (!comment_.empty()) + ++search; io_->seek(seek, BasicIo::beg); count = 0; marker = advanceToMarker(); - if (marker < 0) throw Error(kerNoImageInInputData); + if (marker < 0) + throw Error(kerNoImageInInputData); // To simplify this a bit, new segments are inserts at either the start // or right after app0. This is standard in most jpegs, but has the @@ -1051,7 +1072,8 @@ namespace Exiv2 { while (marker != sos_ && search > 0) { // Read size and signature (ok if this hits EOF) bufRead = io_->read(buf.pData_, bufMinSize); - if (io_->error()) throw Error(kerInputDataReadFailed); + if (io_->error()) + throw Error(kerInputDataReadFailed); // Careful, this can be a meaningless number for empty // images with only an eoi_ marker uint16_t size = getUShort(buf.pData_, bigEndian); @@ -1067,11 +1089,7 @@ namespace Exiv2 { bo = littleEndian; setByteOrder(bo); } - WriteMethod wm = ExifParser::encode(blob, - rawExif.pData_, - rawExif.size_, - bo, - exifData_); + WriteMethod wm = ExifParser::encode(blob, rawExif.pData_, rawExif.size_, bo, exifData_); const byte* pExifData = rawExif.pData_; uint32_t exifSize = rawExif.size_; if (wm == wmIntrusive) { @@ -1083,20 +1101,24 @@ namespace Exiv2 { tmpBuf[0] = 0xff; tmpBuf[1] = app1_; - if (exifSize + 8 > 0xffff) throw Error(kerTooLargeJpegSegment, "Exif"); + if (exifSize + 8 > 0xffff) + throw Error(kerTooLargeJpegSegment, "Exif"); us2Data(tmpBuf + 2, static_cast(exifSize + 8), bigEndian); std::memcpy(tmpBuf + 4, exifId_, 6); - if (outIo.write(tmpBuf, 10) != 10) throw Error(kerImageWriteFailed); + if (outIo.write(tmpBuf, 10) != 10) + throw Error(kerImageWriteFailed); // Write new Exif data buffer - if ( outIo.write(pExifData, exifSize) - != static_cast(exifSize)) throw Error(kerImageWriteFailed); - if (outIo.error()) throw Error(kerImageWriteFailed); + if (outIo.write(pExifData, exifSize) != static_cast(exifSize)) + throw Error(kerImageWriteFailed); + if (outIo.error()) + throw Error(kerImageWriteFailed); --search; } } if (writeXmpFromPacket() == false) { - if (XmpParser::encode(xmpPacket_, xmpData_, XmpParser::useCompactFormat | XmpParser::omitAllFormatting) > 1) { + if (XmpParser::encode(xmpPacket_, xmpData_, + XmpParser::useCompactFormat | XmpParser::omitAllFormatting) > 1) { #ifndef SUPPRESS_WARNINGS EXV_ERROR << "Failed to encode XMP metadata.\n"; #endif @@ -1107,15 +1129,19 @@ namespace Exiv2 { tmpBuf[0] = 0xff; tmpBuf[1] = app1_; - if (xmpPacket_.size() + 31 > 0xffff) throw Error(kerTooLargeJpegSegment, "XMP"); + if (xmpPacket_.size() + 31 > 0xffff) + throw Error(kerTooLargeJpegSegment, "XMP"); us2Data(tmpBuf + 2, static_cast(xmpPacket_.size() + 31), bigEndian); std::memcpy(tmpBuf + 4, xmpId_, 29); - if (outIo.write(tmpBuf, 33) != 33) throw Error(kerImageWriteFailed); + if (outIo.write(tmpBuf, 33) != 33) + throw Error(kerImageWriteFailed); // Write new XMP packet - if ( outIo.write(reinterpret_cast(xmpPacket_.data()), static_cast(xmpPacket_.size())) - != static_cast(xmpPacket_.size())) throw Error(kerImageWriteFailed); - if (outIo.error()) throw Error(kerImageWriteFailed); + if (outIo.write(reinterpret_cast(xmpPacket_.data()), + static_cast(xmpPacket_.size())) != static_cast(xmpPacket_.size())) + throw Error(kerImageWriteFailed); + if (outIo.error()) + throw Error(kerImageWriteFailed); --search; } @@ -1125,29 +1151,33 @@ namespace Exiv2 { tmpBuf[0] = 0xff; tmpBuf[1] = app2_; - int chunk_size = 256*256-40 ; // leave bytes for marker, header and padding - int size = (int) iccProfile_.size_ ; - int chunks = 1 + (size-1) / chunk_size ; - if (iccProfile_.size_ > 256*chunk_size) throw Error(kerTooLargeJpegSegment, "IccProfile"); - for ( int chunk = 0 ; chunk < chunks ; chunk ++ ) { - int bytes = size > chunk_size ? chunk_size : size ; // bytes to write - size -= bytes ; + int chunk_size = 256 * 256 - 40; // leave bytes for marker, header and padding + int size = (int)iccProfile_.size_; + int chunks = 1 + (size - 1) / chunk_size; + if (iccProfile_.size_ > 256 * chunk_size) + throw Error(kerTooLargeJpegSegment, "IccProfile"); + for (int chunk = 0; chunk < chunks; chunk++) { + int bytes = size > chunk_size ? chunk_size : size; // bytes to write + size -= bytes; // write JPEG marker (2 bytes) - if (outIo.write(tmpBuf, 2) != 2) throw Error(kerImageWriteFailed); // JPEG Marker + if (outIo.write(tmpBuf, 2) != 2) + throw Error(kerImageWriteFailed); // JPEG Marker // write length (2 bytes). length includes the 2 bytes for the length - us2Data(tmpBuf + 2, 2+14+bytes, bigEndian); - if (outIo.write(tmpBuf+2, 2) != 2) throw Error(kerImageWriteFailed); // JPEG Length + us2Data(tmpBuf + 2, 2 + 14 + bytes, bigEndian); + if (outIo.write(tmpBuf + 2, 2) != 2) + throw Error(kerImageWriteFailed); // JPEG Length // write the ICC_PROFILE header (14 bytes) char pad[2]; - pad[0] = chunk+1; + pad[0] = chunk + 1; pad[1] = chunks; - outIo.write((const byte *) iccId_,12); - outIo.write((const byte *) pad, 2); - if (outIo.write(iccProfile_.pData_+ (chunk*chunk_size), bytes) != bytes) + outIo.write((const byte*)iccId_, 12); + outIo.write((const byte*)pad, 2); + if (outIo.write(iccProfile_.pData_ + (chunk * chunk_size), bytes) != bytes) + throw Error(kerImageWriteFailed); + if (outIo.error()) throw Error(kerImageWriteFailed); - if (outIo.error()) throw Error(kerImageWriteFailed); } --search; } @@ -1155,9 +1185,8 @@ namespace Exiv2 { 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(psBlob.size() > 0 ? &psBlob[0] : 0, - (long) psBlob.size(), - iptcData_); + DataBuf newPsData = + Photoshop::setIptcIrb(psBlob.size() > 0 ? &psBlob[0] : 0, (long)psBlob.size(), iptcData_); const long maxChunkSize = 0xffff - 16; const byte* chunkStart = newPsData.pData_; const byte* chunkEnd = chunkStart + newPsData.size_; @@ -1180,12 +1209,16 @@ namespace Exiv2 { tmpBuf[1] = app13_; us2Data(tmpBuf + 2, static_cast(chunkSize + 16), bigEndian); std::memcpy(tmpBuf + 4, Photoshop::ps3Id_, 14); - if (outIo.write(tmpBuf, 18) != 18) throw Error(kerImageWriteFailed); - if (outIo.error()) throw Error(kerImageWriteFailed); + if (outIo.write(tmpBuf, 18) != 18) + throw Error(kerImageWriteFailed); + if (outIo.error()) + throw Error(kerImageWriteFailed); // Write next chunk of the Photoshop IRB data buffer - if (outIo.write(chunkStart, chunkSize) != chunkSize) throw Error(kerImageWriteFailed); - if (outIo.error()) throw Error(kerImageWriteFailed); + if (outIo.write(chunkStart, chunkSize) != chunkSize) + throw Error(kerImageWriteFailed); + if (outIo.error()) + throw Error(kerImageWriteFailed); chunkStart += chunkSize; } @@ -1199,42 +1232,48 @@ namespace Exiv2 { tmpBuf[0] = 0xff; tmpBuf[1] = com_; - if (comment_.length() + 3 > 0xffff) throw Error(kerTooLargeJpegSegment, "JPEG comment"); + if (comment_.length() + 3 > 0xffff) + throw Error(kerTooLargeJpegSegment, "JPEG comment"); us2Data(tmpBuf + 2, static_cast(comment_.length() + 3), bigEndian); - if (outIo.write(tmpBuf, 4) != 4) throw Error(kerImageWriteFailed); - if (outIo.write((byte*)comment_.data(), (long)comment_.length()) - != (long)comment_.length()) throw Error(kerImageWriteFailed); - if (outIo.putb(0)==EOF) throw Error(kerImageWriteFailed); - if (outIo.error()) throw Error(kerImageWriteFailed); + if (outIo.write(tmpBuf, 4) != 4) + throw Error(kerImageWriteFailed); + if (outIo.write((byte*)comment_.data(), (long)comment_.length()) != (long)comment_.length()) + throw Error(kerImageWriteFailed); + if (outIo.putb(0) == EOF) + throw Error(kerImageWriteFailed); + if (outIo.error()) + throw Error(kerImageWriteFailed); --search; } --search; } if (marker == eoi_) { break; - } - else if ( skipApp1Exif == count - || skipApp1Xmp == count - || std::find(skipApp13Ps3.begin(), skipApp13Ps3.end(), count) != skipApp13Ps3.end() - || std::find(skipApp2Icc.begin() , skipApp2Icc.end(), count) != skipApp2Icc.end() - || skipCom == count) { + } else if (skipApp1Exif == count || skipApp1Xmp == count || + std::find(skipApp13Ps3.begin(), skipApp13Ps3.end(), count) != skipApp13Ps3.end() || + std::find(skipApp2Icc.begin(), skipApp2Icc.end(), count) != skipApp2Icc.end() || + skipCom == count) { --search; - io_->seek(size-bufRead, BasicIo::cur); - } - else { - if (size < 2) throw Error(kerNoImageInInputData); - buf.alloc(size+2); - io_->seek(-bufRead-2, BasicIo::cur); - io_->read(buf.pData_, size+2); - if (io_->error() || io_->eof()) throw Error(kerInputDataReadFailed); - if (outIo.write(buf.pData_, size+2) != size+2) throw Error(kerImageWriteFailed); - if (outIo.error()) throw Error(kerImageWriteFailed); + io_->seek(size - bufRead, BasicIo::cur); + } else { + if (size < 2) + throw Error(kerNoImageInInputData); + buf.alloc(size + 2); + io_->seek(-bufRead - 2, BasicIo::cur); + io_->read(buf.pData_, size + 2); + if (io_->error() || io_->eof()) + throw Error(kerInputDataReadFailed); + if (outIo.write(buf.pData_, size + 2) != size + 2) + throw Error(kerImageWriteFailed); + if (outIo.error()) + throw Error(kerImageWriteFailed); } // Next marker marker = advanceToMarker(); - if (marker < 0) throw Error(kerNoImageInInputData); + if (marker < 0) + throw Error(kerNoImageInInputData); ++count; } @@ -1246,12 +1285,14 @@ namespace Exiv2 { io_->seek(-2, BasicIo::cur); buf.alloc(4096); long readSize = 0; - while ((readSize=io_->read(buf.pData_, buf.size_))) { - if (outIo.write(buf.pData_, readSize) != readSize) throw Error(kerImageWriteFailed); + while ((readSize = io_->read(buf.pData_, buf.size_))) { + if (outIo.write(buf.pData_, readSize) != readSize) + throw Error(kerImageWriteFailed); } - if (outIo.error()) throw Error(kerImageWriteFailed); + if (outIo.error()) + throw Error(kerImageWriteFailed); - } // JpegBase::doWriteMetadata + } // JpegBase::doWriteMetadata const byte JpegImage::soi_ = 0xd8; const byte JpegImage::blank_[] = { diff --git a/src/makernote_int.cpp b/src/makernote_int.cpp index 5eff8913..2aa23147 100644 --- a/src/makernote_int.cpp +++ b/src/makernote_int.cpp @@ -982,23 +982,18 @@ namespace Exiv2 { return new TiffIfdMakernote(tag, group, mnGroup, new PanasonicMnHeader, false); } - TiffComponent* newPentaxMn(uint16_t tag, - IfdId group, - IfdId /*mnGroup*/, - const byte* pData, - uint32_t size, - ByteOrder /*byteOrder*/) + TiffComponent* newPentaxMn(uint16_t tag, IfdId group, IfdId /*mnGroup*/, const byte* pData, uint32_t size, + ByteOrder /*byteOrder*/) { - if ( size > 8 - && std::string(reinterpret_cast(pData), 8) == std::string("PENTAX \0", 8)) { + if (size > 8 && std::string(reinterpret_cast(pData), 8) == std::string("PENTAX \0", 8)) { // Require at least the header and an IFD with 1 entry - if (size < PentaxDngMnHeader::sizeOfSignature() + 18) return 0; + if (size < PentaxDngMnHeader::sizeOfSignature() + 18) + return 0; return newPentaxDngMn2(tag, group, pentaxDngId); - } - else if ( size > 4 - && std::string(reinterpret_cast(pData), 4) == std::string("AOC\0", 4)) { + } else if (size > 4 && std::string(reinterpret_cast(pData), 4) == std::string("AOC\0", 4)) { // Require at least the header and an IFD with 1 entry - if (size < PentaxMnHeader::sizeOfSignature() + 18) return 0; + if (size < PentaxMnHeader::sizeOfSignature() + 18) + return 0; return newPentaxMn2(tag, group, pentaxId); } else return 0;