Skip to content

Commit 90f794f

Browse files
Merge pull request #2277 from kevinbackhouse/iptcDataSegs
Simplify the iptcDataSegs logic in jpgimage.cpp
2 parents 97e58a4 + 8e5b811 commit 90f794f

File tree

2 files changed

+32
-50
lines changed

2 files changed

+32
-50
lines changed

src/jpgimage.cpp

Lines changed: 18 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ void JpegBase::readMetadata() {
146146
byte marker = advanceToMarker(ErrorCode::kerNotAJpeg);
147147

148148
while (marker != sos_ && marker != eoi_ && search > 0) {
149-
auto [sizebuf, size] = readSegmentSize(marker, *io_);
149+
const auto [sizebuf, size] = readSegmentSize(marker, *io_);
150150

151151
// Read the rest of the segment.
152152
DataBuf buf(size);
@@ -304,7 +304,7 @@ void JpegBase::printStructure(std::ostream& out, PrintStructureOption option, in
304304
}
305305

306306
bool bPrint = option == kpsBasic || option == kpsRecursive;
307-
std::vector<size_t> iptcDataSegs;
307+
std::vector<std::pair<size_t, size_t>> iptcDataSegs;
308308

309309
if (bPrint || option == kpsXMP || option == kpsIccProfile || option == kpsIptcErase) {
310310
// mnemonic for markers
@@ -347,7 +347,7 @@ void JpegBase::printStructure(std::ostream& out, PrintStructureOption option, in
347347
first = false;
348348
bool bLF = bPrint;
349349

350-
auto [sizebuf, size] = readSegmentSize(marker, *io_);
350+
const auto [sizebuf, size] = readSegmentSize(marker, *io_);
351351

352352
// Read the rest of the segment.
353353
DataBuf buf(size);
@@ -412,8 +412,7 @@ void JpegBase::printStructure(std::ostream& out, PrintStructureOption option, in
412412
}
413413
} else if (option == kpsIptcErase && signature == "Photoshop 3.0") {
414414
// delete IPTC data segment from JPEG
415-
iptcDataSegs.push_back(io_->tell() - size);
416-
iptcDataSegs.push_back(size);
415+
iptcDataSegs.emplace_back(io_->tell() - size, io_->tell());
417416
} else if (bPrint) {
418417
const size_t start = 2;
419418
const size_t end = size > 34 ? 34 : size;
@@ -518,62 +517,31 @@ void JpegBase::printStructure(std::ostream& out, PrintStructureOption option, in
518517
}
519518
}
520519
if (option == kpsIptcErase && !iptcDataSegs.empty()) {
521-
#ifdef EXIV2_DEBUG_MESSAGES
522-
std::cout << "iptc data blocks: " << iptcDataSegs.size() << std::endl;
523-
uint32_t toggle = 0;
524-
for (auto&& iptc : iptcDataSegs) {
525-
std::cout << iptc;
526-
if (toggle++ % 2)
527-
std::cout << std::endl;
528-
else
529-
std::cout << ' ';
530-
}
531-
#endif
532-
size_t count = iptcDataSegs.size();
533-
534-
// figure out which blocks to copy
535-
std::vector<size_t> pos(count + 2);
536-
pos[0] = 0;
537-
// copy the data that is not iptc
538-
auto it = iptcDataSegs.begin();
539-
for (size_t i = 0; i < count; i++) {
540-
bool bOdd = (i % 2) != 0;
541-
bool bEven = !bOdd;
542-
pos[i + 1] = bEven ? *it : pos[i] + *it;
543-
++it;
544-
}
545-
pos[count + 1] = io_->size();
546-
#ifdef EXIV2_DEBUG_MESSAGES
547-
for (size_t i = 0; i < count + 2; i++)
548-
std::cout << pos[i] << " ";
549-
std::cout << std::endl;
550-
#endif
520+
// Add a sentinel to the end of iptcDataSegs
521+
iptcDataSegs.emplace_back(io_->size(), 0);
522+
551523
// $ dd bs=1 skip=$((0)) count=$((13164)) if=ETH0138028.jpg of=E1.jpg
552524
// $ dd bs=1 skip=$((49304)) count=2000000 if=ETH0138028.jpg of=E2.jpg
553525
// cat E1.jpg E2.jpg > E.jpg
554526
// exiv2 -pS E.jpg
555527

556528
// binary copy io_ to a temporary file
557529
MemIo tempIo;
558-
for (size_t i = 0; i < (count / 2) + 1; i++) {
559-
size_t start = pos[2 * i] + 2; // step JPG 2 byte marker
560-
if (start == 2)
561-
start = 0; // read the file 2 byte SOI
562-
size_t length = pos[2 * i + 1] - start;
563-
if (length) {
564-
#ifdef EXIV2_DEBUG_MESSAGES
565-
std::cout << start << ":" << length << std::endl;
566-
#endif
567-
io_->seekOrThrow(start, BasicIo::beg, ErrorCode::kerFailedToReadImageData);
568-
DataBuf buf(length);
569-
io_->readOrThrow(buf.data(), buf.size(), ErrorCode::kerFailedToReadImageData);
570-
tempIo.write(buf.c_data(), buf.size());
571-
}
530+
size_t start = 0;
531+
for (const auto& p : iptcDataSegs) {
532+
const size_t length = p.first - start;
533+
io_->seekOrThrow(start, BasicIo::beg, ErrorCode::kerFailedToReadImageData);
534+
DataBuf buf(length);
535+
io_->readOrThrow(buf.data(), buf.size(), ErrorCode::kerFailedToReadImageData);
536+
tempIo.write(buf.c_data(), buf.size());
537+
start = p.second + 2; // skip the 2 byte marker
572538
}
573539

574540
io_->seekOrThrow(0, BasicIo::beg, ErrorCode::kerFailedToReadImageData);
575541
io_->transfer(tempIo); // may throw
576542
io_->seekOrThrow(0, BasicIo::beg, ErrorCode::kerFailedToReadImageData);
543+
544+
// Check that the result is correctly formatted.
577545
readMetadata();
578546
}
579547
} // JpegBase::printStructure
@@ -591,7 +559,7 @@ void JpegBase::writeMetadata() {
591559
}
592560

593561
DataBuf JpegBase::readNextSegment(byte marker) {
594-
auto [sizebuf, size] = readSegmentSize(marker, *io_);
562+
const auto [sizebuf, size] = readSegmentSize(marker, *io_);
595563

596564
// Read the rest of the segment.
597565
DataBuf buf(size);
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# -*- coding: utf-8 -*-
2+
3+
from system_tests import CaseMeta, CopyTmpFiles
4+
@CopyTmpFiles("$data_path/FurnaceCreekInn.jpg")
5+
6+
class jpg_iptcDataSegs(metaclass=CaseMeta):
7+
"""
8+
test for the iptcDataSegs code in jpgimage.cpp
9+
"""
10+
filename = "$tmp_path/FurnaceCreekInn.jpg"
11+
commands = ["$exiv2 -d I rm $filename"]
12+
retval = [0]
13+
stderr = [""]
14+
stdout = [""]

0 commit comments

Comments
 (0)