Skip to content

Commit 472d55e

Browse files
kevinbackhouseneheb
authored andcommitted
Add new method appendIccProfile to fix quadratic performance issue.
1 parent b062259 commit 472d55e

File tree

3 files changed

+32
-14
lines changed

3 files changed

+32
-14
lines changed

include/exiv2/image.hpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,16 @@ class EXIV2API Image {
195195
@param bTestValid - tests that iccProfile contains credible data
196196
*/
197197
virtual void setIccProfile(DataBuf&& iccProfile, bool bTestValid = true);
198+
/*!
199+
@brief Append more bytes to the iccProfile.
200+
@param iccProfile DataBuf containing profile (binary)
201+
@param bTestValid - tests that iccProfile contains credible data
202+
*/
203+
virtual void appendIccProfile(const uint8_t* bytes, size_t size, bool bTestValid);
204+
/*!
205+
@brief Throw an exception if the size at the beginning of the iccProfile isn't correct.
206+
*/
207+
virtual void checkIccProfile();
198208
/*!
199209
@brief Erase iccProfile. the profile is not removed from
200210
the actual image until the writeMetadata() method is called.

src/image.cpp

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -629,16 +629,29 @@ void Image::setComment(const std::string& comment) {
629629
}
630630

631631
void Image::setIccProfile(Exiv2::DataBuf&& iccProfile, bool bTestValid) {
632+
iccProfile_ = std::move(iccProfile);
632633
if (bTestValid) {
633-
if (iccProfile.size() < sizeof(long)) {
634-
throw Error(ErrorCode::kerInvalidIccProfile);
635-
}
636-
const size_t size = iccProfile.read_uint32(0, bigEndian);
637-
if (size != iccProfile.size()) {
638-
throw Error(ErrorCode::kerInvalidIccProfile);
639-
}
634+
checkIccProfile();
635+
}
636+
}
637+
638+
void Image::appendIccProfile(const uint8_t* bytes, size_t size, bool bTestValid) {
639+
const size_t start = iccProfile_.size();
640+
iccProfile_.resize(Safe::add(start, size));
641+
memcpy(iccProfile_.data(start), bytes, size);
642+
if (bTestValid) {
643+
checkIccProfile();
644+
}
645+
}
646+
647+
void Image::checkIccProfile() {
648+
if (iccProfile_.size() < sizeof(long)) {
649+
throw Error(ErrorCode::kerInvalidIccProfile);
650+
}
651+
const size_t size = iccProfile_.read_uint32(0, bigEndian);
652+
if (size != iccProfile_.size()) {
653+
throw Error(ErrorCode::kerInvalidIccProfile);
640654
}
641-
iccProfile_ = std::move(iccProfile);
642655
}
643656

644657
void Image::clearIccProfile() {

src/jpgimage.cpp

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -263,12 +263,7 @@ void JpegBase::readMetadata() {
263263
icc_size = s;
264264
}
265265

266-
DataBuf profile(Safe::add(iccProfile_.size(), icc_size));
267-
if (!iccProfile_.empty()) {
268-
std::copy(iccProfile_.begin(), iccProfile_.end(), profile.begin());
269-
}
270-
std::copy_n(buf.begin() + 2 + 14, icc_size, profile.begin() + iccProfile_.size());
271-
setIccProfile(std::move(profile), chunk == chunks);
266+
appendIccProfile(buf.c_data(2 + 14), icc_size, chunk == chunks);
272267
} else if (pixelHeight_ == 0 && inRange2(marker, sof0_, sof3_, sof5_, sof15_)) {
273268
// We hit a SOFn (start-of-frame) marker
274269
if (size < 8) {

0 commit comments

Comments
 (0)