Coverage Report

Created: 2025-12-31 07:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/exiv2/src/mrwimage.cpp
Line
Count
Source
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
3
// included header files
4
#include "mrwimage.hpp"
5
6
#include "basicio.hpp"
7
#include "config.h"
8
#include "enforce.hpp"
9
#include "error.hpp"
10
#include "futils.hpp"
11
#include "image.hpp"
12
#include "tags.hpp"
13
#include "tiffimage.hpp"
14
15
#include <array>
16
#include <cstring>
17
18
#ifdef EXIV2_DEBUG_MESSAGES
19
#include <iostream>
20
#endif
21
22
namespace Exiv2 {
23
MrwImage::MrwImage(BasicIo::UniquePtr io, bool /*create*/) :
24
477
    Image(ImageType::mrw, mdExif | mdIptc | mdXmp, std::move(io)) {
25
477
}
26
27
0
std::string MrwImage::mimeType() const {
28
0
  return "image/x-minolta-mrw";
29
0
}
30
31
32
uint32_t MrwImage::pixelWidth() const {
32
32
  auto imageWidth = exifData_.findKey(Exiv2::ExifKey("Exif.Image.ImageWidth"));
33
32
  if (imageWidth != exifData_.end() && imageWidth->count() > 0) {
34
6
    return imageWidth->toUint32();
35
6
  }
36
26
  return 0;
37
32
}
38
39
32
uint32_t MrwImage::pixelHeight() const {
40
32
  auto imageHeight = exifData_.findKey(Exiv2::ExifKey("Exif.Image.ImageLength"));
41
32
  if (imageHeight != exifData_.end() && imageHeight->count() > 0) {
42
6
    return imageHeight->toUint32();
43
6
  }
44
26
  return 0;
45
32
}
46
47
0
void MrwImage::setExifData(const ExifData& /*exifData*/) {
48
  // Todo: implement me!
49
0
  throw(Error(ErrorCode::kerInvalidSettingForImage, "Exif metadata", "MRW"));
50
0
}
51
52
0
void MrwImage::setIptcData(const IptcData& /*iptcData*/) {
53
  // Todo: implement me!
54
0
  throw(Error(ErrorCode::kerInvalidSettingForImage, "IPTC metadata", "MRW"));
55
0
}
56
57
0
void MrwImage::setComment(const std::string&) {
58
  // not supported
59
0
  throw(Error(ErrorCode::kerInvalidSettingForImage, "Image comment", "MRW"));
60
0
}
61
62
477
void MrwImage::readMetadata() {
63
#ifdef EXIV2_DEBUG_MESSAGES
64
  std::cerr << "Reading MRW file " << io_->path() << "\n";
65
#endif
66
477
  if (io_->open() != 0) {
67
0
    throw Error(ErrorCode::kerDataSourceOpenFailed, io_->path(), strError());
68
0
  }
69
477
  IoCloser closer(*io_);
70
  // Ensure that this is the correct image type
71
477
  if (!isMrwType(*io_, false)) {
72
0
    if (io_->error() || io_->eof())
73
0
      throw Error(ErrorCode::kerFailedToReadImageData);
74
0
    throw Error(ErrorCode::kerNotAnImage, "MRW");
75
0
  }
76
477
  clearMetadata();
77
78
  // Find the TTW block and read it into a buffer
79
477
  uint32_t const len = 8;
80
477
  byte tmp[len];
81
477
  io_->read(tmp, len);
82
477
  uint32_t pos = len;
83
477
  uint32_t const end = getULong(tmp + 4, bigEndian);
84
85
477
  pos += len;
86
477
  Internal::enforce(pos <= end, ErrorCode::kerFailedToReadImageData);
87
477
  io_->read(tmp, len);
88
477
  if (io_->error() || io_->eof())
89
0
    throw Error(ErrorCode::kerFailedToReadImageData);
90
91
1.40k
  while (memcmp(tmp + 1, "TTW", 3) != 0) {
92
924
    uint32_t const siz = getULong(tmp + 4, bigEndian);
93
924
    Internal::enforce(siz <= end - pos, ErrorCode::kerFailedToReadImageData);
94
924
    pos += siz;
95
924
    io_->seek(siz, BasicIo::cur);
96
924
    Internal::enforce(!io_->error() && !io_->eof(), ErrorCode::kerFailedToReadImageData);
97
98
924
    Internal::enforce(len <= end - pos, ErrorCode::kerFailedToReadImageData);
99
924
    pos += len;
100
924
    io_->read(tmp, len);
101
924
    Internal::enforce(!io_->error() && !io_->eof(), ErrorCode::kerFailedToReadImageData);
102
924
  }
103
104
477
  const uint32_t siz = getULong(tmp + 4, bigEndian);
105
  // First do an approximate bounds check of siz, so that we don't
106
  // get DOS-ed by a 4GB allocation on the next line. If siz is
107
  // greater than io_->size() then it is definitely invalid. But the
108
  // exact bounds checking is done by the call to io_->read, which
109
  // will fail if there are fewer than siz bytes left to read.
110
477
  Internal::enforce(siz <= io_->size(), ErrorCode::kerFailedToReadImageData);
111
477
  DataBuf buf(siz);
112
477
  io_->read(buf.data(), buf.size());
113
477
  Internal::enforce(!io_->error() && !io_->eof(), ErrorCode::kerFailedToReadImageData);
114
115
477
  ByteOrder bo = TiffParser::decode(exifData_, iptcData_, xmpData_, buf.c_data(), buf.size());
116
477
  setByteOrder(bo);
117
477
}  // MrwImage::readMetadata
118
119
16
void MrwImage::writeMetadata() {
120
  // Todo: implement me!
121
16
  throw(Error(ErrorCode::kerWritingImageFormatUnsupported, "MRW"));
122
16
}  // MrwImage::writeMetadata
123
124
// *************************************************************************
125
// free functions
126
477
Image::UniquePtr newMrwInstance(BasicIo::UniquePtr io, bool create) {
127
477
  auto image = std::make_unique<MrwImage>(std::move(io), create);
128
477
  if (!image->good()) {
129
0
    return nullptr;
130
0
  }
131
477
  return image;
132
477
}
133
134
73.6k
bool isMrwType(BasicIo& iIo, bool advance) {
135
73.6k
  const int32_t len = 4;
136
73.6k
  const std::array<byte, len> MrwId{0x0, 0x4d, 0x52, 0x4d};
137
73.6k
  std::array<byte, len> buf;
138
73.6k
  iIo.read(buf.data(), len);
139
73.6k
  if (iIo.error() || iIo.eof()) {
140
245
    return false;
141
245
  }
142
73.3k
  bool rc = buf == MrwId;
143
73.3k
  if (!advance || !rc) {
144
73.3k
    iIo.seek(-len, BasicIo::cur);
145
73.3k
  }
146
73.3k
  return rc;
147
73.6k
}
148
149
}  // namespace Exiv2