Coverage Report

Created: 2025-04-11 06:51

/src/exiv2/src/bmpimage.cpp
Line
Count
Source (jump to first uncovered line)
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
  File:      bmpimage.cpp
4
  Author(s): Marco Piovanelli, Ovolab (marco)
5
  History:   05-Mar-2007, marco: created
6
 */
7
8
#include "bmpimage.hpp"
9
#include "basicio.hpp"
10
#include "error.hpp"
11
#include "futils.hpp"
12
#include "image.hpp"
13
14
// + standard includes
15
#include <array>
16
#include <cstring>
17
#include <string>
18
19
#ifdef EXIV2_DEBUG_MESSAGES
20
#include <iostream>
21
#endif
22
23
// *****************************************************************************
24
// class member definitions
25
namespace Exiv2 {
26
11
BmpImage::BmpImage(BasicIo::UniquePtr io) : Image(ImageType::bmp, mdNone, std::move(io)) {
27
11
}
28
29
0
std::string BmpImage::mimeType() const {
30
  // "image/bmp" is a Generic Bitmap
31
0
  return "image/x-ms-bmp";  // Microsoft Bitmap
32
0
}
33
34
0
void BmpImage::setExifData(const ExifData& /*exifData*/) {
35
0
  throw(Error(ErrorCode::kerInvalidSettingForImage, "Exif metadata", "BMP"));
36
0
}
37
38
0
void BmpImage::setIptcData(const IptcData& /*iptcData*/) {
39
0
  throw(Error(ErrorCode::kerInvalidSettingForImage, "IPTC metadata", "BMP"));
40
0
}
41
42
0
void BmpImage::setComment(const std::string&) {
43
0
  throw(Error(ErrorCode::kerInvalidSettingForImage, "Image comment", "BMP"));
44
0
}
45
46
10
void BmpImage::readMetadata() {
47
#ifdef EXIV2_DEBUG_MESSAGES
48
  std::cerr << "Exiv2::BmpImage::readMetadata: Reading Windows bitmap file " << io_->path() << "\n";
49
#endif
50
10
  if (io_->open() != 0) {
51
0
    throw Error(ErrorCode::kerDataSourceOpenFailed, io_->path(), strError());
52
0
  }
53
10
  IoCloser closer(*io_);
54
55
  // Ensure that this is the correct image type
56
10
  if (!isBmpType(*io_, false)) {
57
0
    if (io_->error() || io_->eof())
58
0
      throw Error(ErrorCode::kerFailedToReadImageData);
59
0
    throw Error(ErrorCode::kerNotAnImage, "BMP");
60
0
  }
61
10
  clearMetadata();
62
63
  /*
64
    The Windows bitmap header goes as follows -- all numbers are in little-endian byte order:
65
66
    offset  length   name                   description
67
    ======  =======  =====================  =======
68
     0      2 bytes  signature              always 'BM'
69
     2      4 bytes  bitmap size
70
     6      4 bytes  reserved
71
    10      4 bytes  bitmap offset
72
    14      4 bytes  header size
73
    18      4 bytes  bitmap width
74
    22      4 bytes  bitmap height
75
    26      2 bytes  plane count
76
    28      2 bytes  depth
77
    30      4 bytes  compression            0 = none; 1 = RLE, 8 bits/pixel; 2 = RLE, 4 bits/pixel; 3 = bitfield;
78
    4 = JPEG; 5 = PNG 34      4 bytes  image size             size of the raw bitmap data, in bytes 38      4
79
    bytes  horizontal resolution  (in pixels per meter) 42      4 bytes  vertical resolution    (in pixels per
80
    meter) 46      4 bytes  color count 50      4 bytes  important colors       number of "important" colors
81
  */
82
10
  byte buf[26];
83
10
  if (io_->read(buf, sizeof(buf)) == sizeof(buf)) {
84
10
    pixelWidth_ = getULong(buf + 18, littleEndian);
85
10
    pixelHeight_ = getULong(buf + 22, littleEndian);
86
10
  }
87
10
}
88
89
0
void BmpImage::writeMetadata() {
90
  /// \todo implement me!
91
0
  throw(Error(ErrorCode::kerWritingImageFormatUnsupported, "BMP"));
92
0
}
93
94
// *************************************************************************
95
// free functions
96
11
Image::UniquePtr newBmpInstance(BasicIo::UniquePtr io, bool /*create*/) {
97
11
  auto image = std::make_unique<BmpImage>(std::move(io));
98
11
  if (!image->good()) {
99
1
    return nullptr;
100
1
  }
101
10
  return image;
102
11
}
103
104
7.94k
bool isBmpType(BasicIo& iIo, bool advance) {
105
7.94k
  const int32_t len = 2;
106
7.94k
  const std::array<byte, len> BmpImageId{'B', 'M'};
107
7.94k
  std::array<byte, len> buf;
108
7.94k
  iIo.read(buf.data(), len);
109
7.94k
  if (iIo.error() || iIo.eof()) {
110
165
    return false;
111
165
  }
112
7.78k
  bool matched = buf == BmpImageId;
113
7.78k
  if (!advance || !matched) {
114
7.78k
    iIo.seek(-len, BasicIo::cur);
115
7.78k
  }
116
7.78k
  return matched;
117
7.94k
}
118
}  // namespace Exiv2