Coverage Report

Created: 2026-01-10 06:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/exiv2/src/orfimage.cpp
Line
Count
Source
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
3
// included header files
4
#include "orfimage.hpp"
5
6
#include "basicio.hpp"
7
#include "config.h"
8
#include "error.hpp"
9
#include "futils.hpp"
10
#include "image.hpp"
11
#include "orfimage_int.hpp"
12
#include "tags.hpp"
13
#include "tiffcomposite_int.hpp"
14
#include "tiffimage.hpp"
15
#include "tiffimage_int.hpp"
16
17
#include <iostream>
18
19
// *****************************************************************************
20
// class member definitions
21
namespace Exiv2 {
22
using namespace Internal;
23
24
OrfImage::OrfImage(BasicIo::UniquePtr io, bool create) :
25
191
    TiffImage(/*ImageType::orf, mdExif | mdIptc | mdXmp,*/ std::move(io), create) {
26
191
  setTypeSupported(ImageType::orf, mdExif | mdIptc | mdXmp);
27
191
}  // OrfImage::OrfImage
28
29
0
std::string OrfImage::mimeType() const {
30
0
  return "image/x-olympus-orf";
31
0
}
32
33
63
uint32_t OrfImage::pixelWidth() const {
34
63
  auto imageWidth = exifData_.findKey(Exiv2::ExifKey("Exif.Image.ImageWidth"));
35
63
  if (imageWidth != exifData_.end() && imageWidth->count() > 0) {
36
12
    return imageWidth->toUint32();
37
12
  }
38
51
  return 0;
39
63
}
40
41
63
uint32_t OrfImage::pixelHeight() const {
42
63
  auto imageHeight = exifData_.findKey(Exiv2::ExifKey("Exif.Image.ImageLength"));
43
63
  if (imageHeight != exifData_.end() && imageHeight->count() > 0) {
44
15
    return imageHeight->toUint32();
45
15
  }
46
48
  return 0;
47
63
}
48
49
0
void OrfImage::setComment(const std::string&) {
50
  // not supported
51
0
  throw(Error(ErrorCode::kerInvalidSettingForImage, "Image comment", "ORF"));
52
0
}
53
54
92
void OrfImage::printStructure(std::ostream& out, PrintStructureOption option, size_t depth) {
55
92
  out << "ORF IMAGE" << '\n';
56
92
  if (io_->open() != 0)
57
0
    throw Error(ErrorCode::kerDataSourceOpenFailed, io_->path(), strError());
58
  // Ensure that this is the correct image type
59
92
  if (imageType() == ImageType::none && !isOrfType(*io_, false)) {
60
0
    if (io_->error() || io_->eof())
61
0
      throw Error(ErrorCode::kerFailedToReadImageData);
62
0
    throw Error(ErrorCode::kerNotAJpeg);
63
0
  }
64
65
92
  io_->seek(0, BasicIo::beg);
66
67
92
  printTiffStructure(io(), out, option, depth);
68
92
}  // OrfImage::printStructure
69
70
191
void OrfImage::readMetadata() {
71
#ifdef EXIV2_DEBUG_MESSAGES
72
  std::cerr << "Reading ORF file " << io_->path() << "\n";
73
#endif
74
191
  if (io_->open() != 0) {
75
0
    throw Error(ErrorCode::kerDataSourceOpenFailed, io_->path(), strError());
76
0
  }
77
191
  IoCloser closer(*io_);
78
  // Ensure that this is the correct image type
79
191
  if (!isOrfType(*io_, false)) {
80
0
    if (io_->error() || io_->eof())
81
0
      throw Error(ErrorCode::kerFailedToReadImageData);
82
0
    throw Error(ErrorCode::kerNotAnImage, "ORF");
83
0
  }
84
191
  clearMetadata();
85
191
  ByteOrder bo = OrfParser::decode(exifData_, iptcData_, xmpData_, io_->mmap(), io_->size());
86
191
  setByteOrder(bo);
87
191
}
88
89
45
void OrfImage::writeMetadata() {
90
#ifdef EXIV2_DEBUG_MESSAGES
91
  std::cerr << "Writing ORF file " << io_->path() << "\n";
92
#endif
93
45
  ByteOrder bo = byteOrder();
94
45
  const byte* pData = nullptr;
95
45
  size_t size = 0;
96
45
  IoCloser closer(*io_);
97
  // Ensure that this is the correct image type
98
45
  if (io_->open() == 0 && isOrfType(*io_, false)) {
99
45
    pData = io_->mmap(true);
100
45
    size = io_->size();
101
45
    OrfHeader orfHeader;
102
45
    if (0 == orfHeader.read(pData, 8)) {
103
0
      bo = orfHeader.byteOrder();
104
0
    }
105
45
  }
106
45
  if (bo == invalidByteOrder) {
107
0
    bo = littleEndian;
108
0
  }
109
45
  setByteOrder(bo);
110
45
  OrfParser::encode(*io_, pData, size, bo, exifData_, iptcData_, xmpData_);  // may throw
111
45
}  // OrfImage::writeMetadata
112
113
191
ByteOrder OrfParser::decode(ExifData& exifData, IptcData& iptcData, XmpData& xmpData, const byte* pData, size_t size) {
114
191
  OrfHeader orfHeader;
115
191
  return TiffParserWorker::decode(exifData, iptcData, xmpData, pData, size, Tag::root, TiffMapping::findDecoder,
116
191
                                  &orfHeader);
117
191
}
118
119
WriteMethod OrfParser::encode(BasicIo& io, const byte* pData, size_t size, ByteOrder byteOrder, ExifData& exifData,
120
45
                              const IptcData& iptcData, const XmpData& xmpData) {
121
  // Delete IFDs which do not occur in TIFF images
122
45
  static constexpr auto filteredIfds = {
123
45
      IfdId::panaRawId,
124
45
  };
125
45
  for (auto&& filteredIfd : filteredIfds) {
126
#ifdef EXIV2_DEBUG_MESSAGES
127
    std::cerr << "Warning: Exif IFD " << filteredIfd << " not encoded\n";
128
#endif
129
45
    exifData.erase(std::remove_if(exifData.begin(), exifData.end(), FindExifdatum(filteredIfd)), exifData.end());
130
45
  }
131
132
45
  OrfHeader header(byteOrder);
133
45
  return TiffParserWorker::encode(io, pData, size, exifData, iptcData, xmpData, Tag::root, TiffMapping::findEncoder,
134
45
                                  &header, nullptr);
135
45
}
136
137
// *************************************************************************
138
// free functions
139
191
Image::UniquePtr newOrfInstance(BasicIo::UniquePtr io, bool create) {
140
191
  auto image = std::make_unique<OrfImage>(std::move(io), create);
141
191
  if (!image->good()) {
142
0
    return nullptr;
143
0
  }
144
191
  return image;
145
191
}
146
147
42.1k
bool isOrfType(BasicIo& iIo, bool advance) {
148
42.1k
  const int32_t len = 8;
149
42.1k
  byte buf[len];
150
42.1k
  iIo.read(buf, len);
151
42.1k
  if (iIo.error() || iIo.eof()) {
152
428
    return false;
153
428
  }
154
41.7k
  OrfHeader orfHeader;
155
41.7k
  bool rc = orfHeader.read(buf, len);
156
41.7k
  if (!advance || !rc) {
157
41.7k
    iIo.seek(-len, BasicIo::cur);
158
41.7k
  }
159
41.7k
  return rc;
160
42.1k
}
161
162
}  // namespace Exiv2