Coverage Report

Created: 2026-09-06 07:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libwpg/src/lib/WPGBitmap.cpp
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2
/* libwpg
3
 * Version: MPL 2.0 / LGPLv2.1+
4
 *
5
 * This Source Code Form is subject to the terms of the Mozilla Public
6
 * License, v. 2.0. If a copy of the MPL was not distributed with this
7
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
 *
9
 * Major Contributor(s):
10
 * Copyright (C) 2007 Ariya Hidayat (ariya@kde.org)
11
 * Copyright (C) 2006 Ariya Hidayat (ariya@kde.org)
12
 *
13
 * For minor contributions see the git repository.
14
 *
15
 * Alternatively, the contents of this file may be used under the terms
16
 * of the GNU Lesser General Public License Version 2.1 or later
17
 * (LGPLv2.1+), in which case the provisions of the LGPLv2.1+ are
18
 * applicable instead of those above.
19
 *
20
 * For further information visit http://libwpg.sourceforge.net
21
 */
22
23
/* "This product is not manufactured, approved, or supported by
24
 * Corel Corporation or Corel Corporation Limited."
25
 */
26
27
#include "WPGBitmap.h"
28
29
#include <cassert>
30
#include <vector>
31
32
#include "libwpg_utils.h"
33
34
#define DUMP_BITMAP 0
35
36
#if DUMP_BITMAP
37
static unsigned bitmapId = 0;
38
#include <sstream>
39
#endif
40
41
namespace
42
{
43
44
void writeU8(std::vector<unsigned char> &buffer, const int value)
45
0
{
46
0
  buffer.push_back(static_cast<unsigned char>(value & 0xFF));
47
0
}
48
49
void writeU16(std::vector<unsigned char> &buffer, const int value)
50
0
{
51
0
  writeU8(buffer, value & 0xFF);
52
0
  writeU8(buffer, (value >> 8) & 0xFF);
53
0
}
54
55
void writeU32(std::vector<unsigned char> &buffer, const int value)
56
0
{
57
0
  writeU8(buffer, value & 0xFF);
58
0
  writeU8(buffer, (value >> 8) & 0xFF);
59
0
  writeU8(buffer, (value >> 16) & 0xFF);
60
0
  writeU8(buffer, (value >> 24) & 0xFF);
61
0
}
62
63
}
64
65
class libwpg::WPGBitmap::Private
66
{
67
public:
68
  int width;
69
  int height;
70
  int vRes;
71
  int hRes;
72
  bool vFlip;
73
  bool hFlip;
74
  std::unique_ptr<WPGColor[]> pixels;
75
  librevenge::RVNGBinaryData dib;
76
77
0
  Private(int w, int h): width(w), height(h), vRes(72), hRes(72), vFlip(false), hFlip(false), pixels(nullptr), dib() {}
78
private:
79
  // Unimplemented to prevent compiler from creating crasher ones
80
  Private(const Private &);
81
  Private &operator=(const Private &);
82
};
83
84
libwpg::WPGBitmap::WPGBitmap(int w, int h, int verticalResolution, int horizontalResolution, bool verticalFlip, bool horizontalFlip) :
85
0
  d(new Private(w, h))
86
0
{
87
0
  assert(w >= 0);
88
0
  assert(h >= 0);
89
0
  d->vRes = verticalResolution;
90
0
  d->hRes = horizontalResolution;
91
0
  d->vFlip = verticalFlip;
92
0
  d->hFlip = horizontalFlip;
93
0
  d->pixels.reset(new WPGColor[unsigned(w) * unsigned(h)]);
94
0
}
95
96
libwpg::WPGBitmap::~WPGBitmap()
97
0
{
98
0
}
99
100
0
libwpg::WPGBitmap::WPGBitmap(const WPGBitmap &bitmap): d(new Private(0,0))
101
0
{
102
0
  copyFrom(bitmap);
103
0
}
104
105
libwpg::WPGBitmap &libwpg::WPGBitmap::operator=(const WPGBitmap &bitmap)
106
0
{
107
0
  if (this != &bitmap)
108
0
    copyFrom(bitmap);
109
0
  return *this;
110
0
}
111
112
void libwpg::WPGBitmap::copyFrom(const WPGBitmap &bitmap)
113
0
{
114
0
  d->width = bitmap.d->width;
115
0
  d->height = bitmap.d->height;
116
0
  d->pixels.reset(new WPGColor[d->width*d->height]);
117
0
  for (int i=0; i < d->width*d->height; i++)
118
0
    d->pixels[i] = bitmap.d->pixels[i];
119
0
}
120
121
int libwpg::WPGBitmap::width() const
122
0
{
123
0
  return d->width;
124
0
}
125
126
int libwpg::WPGBitmap::height() const
127
0
{
128
0
  return d->height;
129
0
}
130
131
int libwpg::WPGBitmap::vres() const
132
0
{
133
0
  return d->vRes;
134
0
}
135
136
int libwpg::WPGBitmap::hres() const
137
0
{
138
0
  return d->hRes;
139
0
}
140
141
void libwpg::WPGBitmap::setPixel(int x, int y, const libwpg::WPGColor &color)
142
0
{
143
0
  if ((x < 0) || (y <0) || (x >= d->width) || (y >= d->height))
144
0
    return;
145
146
0
  d->pixels[y *d->width + x] = color;
147
0
}
148
149
const librevenge::RVNGBinaryData &libwpg::WPGBitmap::getDIB() const
150
0
{
151
0
  if (d->dib.size() || d->height <= 0 || d->width <= 0)
152
0
    return d->dib;
153
154
0
  auto tmpPixelSize = (unsigned)(d->height * d->width);
155
0
  if (tmpPixelSize < (unsigned)d->height) // overflow
156
0
    return d->dib;
157
158
0
  unsigned tmpDIBImageSize = tmpPixelSize * 4;
159
0
  if (tmpPixelSize > tmpDIBImageSize) // overflow !!!
160
0
    return d->dib;
161
162
0
  unsigned tmpDIBOffsetBits = 14 + 40;
163
0
  unsigned tmpDIBFileSize = tmpDIBOffsetBits + tmpDIBImageSize;
164
0
  if (tmpDIBImageSize > tmpDIBFileSize) // overflow !!!
165
0
    return d->dib;
166
167
0
  std::vector<unsigned char> tmpDIBBuffer;
168
0
  tmpDIBBuffer.reserve(tmpDIBFileSize);
169
170
  // Create DIB file header
171
0
  writeU16(tmpDIBBuffer, 0x4D42);  // Type
172
0
  writeU32(tmpDIBBuffer, (int) tmpDIBFileSize); // Size
173
0
  writeU16(tmpDIBBuffer, 0); // Reserved1
174
0
  writeU16(tmpDIBBuffer, 0); // Reserved2
175
0
  writeU32(tmpDIBBuffer, (int) tmpDIBOffsetBits); // OffsetBits
176
177
0
  WPG_DEBUG_MSG(("WPGBitmap: DIB file header end = %lu\n", static_cast<unsigned long>(tmpDIBBuffer.size() - 1)));
178
179
  // Create DIB Info header
180
0
  writeU32(tmpDIBBuffer, 40); // Size
181
0
  writeU32(tmpDIBBuffer, width());  // Width
182
0
  writeU32(tmpDIBBuffer, height()); // Height
183
0
  writeU16(tmpDIBBuffer, 1); // Planes
184
0
  writeU16(tmpDIBBuffer, 32); // BitCount
185
0
  writeU32(tmpDIBBuffer, 0); // Compression
186
0
  writeU32(tmpDIBBuffer, (int)tmpDIBImageSize); // SizeImage
187
0
  writeU32(tmpDIBBuffer, (int)(hres()*100.0/2.54)); // XPelsPerMeter
188
0
  writeU32(tmpDIBBuffer, (int)(vres()*100.0/2.54)); // YPelsPerMeter
189
0
  writeU32(tmpDIBBuffer, 0); // ColorsUsed
190
0
  writeU32(tmpDIBBuffer, 0); // ColorsImportant
191
192
0
  WPG_DEBUG_MSG(("WPGBitmap: DIB info header end = %lu\n", static_cast<unsigned long>(tmpDIBBuffer.size() - 1)));
193
194
  // Write DIB Image data
195
196
0
  int i = 0;
197
0
  int j = 0;
198
0
  if (d->vFlip)
199
0
    for (i = 0; i < d->height && tmpDIBBuffer.size() < tmpDIBFileSize; i++)
200
0
    {
201
0
      if (d->hFlip)
202
0
        for (j = d->width - 1; j >= 0 && tmpDIBBuffer.size() < tmpDIBFileSize; j--)
203
0
        {
204
0
          writeU8(tmpDIBBuffer, d->pixels[i*d->width + j].blue);
205
0
          writeU8(tmpDIBBuffer, d->pixels[i*d->width + j].green);
206
0
          writeU8(tmpDIBBuffer, d->pixels[i*d->width + j].red);
207
0
          writeU8(tmpDIBBuffer, d->pixels[i*d->width + j].alpha);
208
0
        }
209
0
      else
210
0
        for (j = 0; j < d->width && tmpDIBBuffer.size() < tmpDIBFileSize; j++)
211
0
        {
212
0
          writeU8(tmpDIBBuffer, d->pixels[i*d->width + j].blue);
213
0
          writeU8(tmpDIBBuffer, d->pixels[i*d->width + j].green);
214
0
          writeU8(tmpDIBBuffer, d->pixels[i*d->width + j].red);
215
0
          writeU8(tmpDIBBuffer, d->pixels[i*d->width + j].alpha);
216
0
        }
217
0
    }
218
0
  else
219
0
    for (i = d->height - 1; i >= 0 && tmpDIBBuffer.size() < tmpDIBFileSize; i--)
220
0
    {
221
0
      if (d->hFlip)
222
0
        for (j = d->width - 1; j >= 0 && tmpDIBBuffer.size() < tmpDIBFileSize; j--)
223
0
        {
224
0
          writeU8(tmpDIBBuffer, d->pixels[i*d->width + j].blue);
225
0
          writeU8(tmpDIBBuffer, d->pixels[i*d->width + j].green);
226
0
          writeU8(tmpDIBBuffer, d->pixels[i*d->width + j].red);
227
0
          writeU8(tmpDIBBuffer, d->pixels[i*d->width + j].alpha);
228
0
        }
229
0
      else
230
0
        for (j = 0; j < d->width && tmpDIBBuffer.size() < tmpDIBFileSize; j++)
231
0
        {
232
0
          writeU8(tmpDIBBuffer, d->pixels[i*d->width + j].blue);
233
0
          writeU8(tmpDIBBuffer, d->pixels[i*d->width + j].green);
234
0
          writeU8(tmpDIBBuffer, d->pixels[i*d->width + j].red);
235
0
          writeU8(tmpDIBBuffer, d->pixels[i*d->width + j].alpha);
236
0
        }
237
0
    }
238
239
0
  WPG_DEBUG_MSG(("WPGBitmap: DIB file size = %lu\n", static_cast<unsigned long>(tmpDIBBuffer.size() - 1)));
240
241
0
  d->dib.append(tmpDIBBuffer.data(), tmpDIBBuffer.size());
242
243
  // temporary for debug - dump the binary bmp (need to have write access in the current directory
244
#if DUMP_BITMAP
245
  std::ostringstream filename;
246
  filename << "binarydump" << bitmapId++ << ".bmp";
247
  FILE *f = fopen(filename.str().c_str(), "wb");
248
  if (f)
249
  {
250
    for (size_t k = 0; k < tmpDIBBuffer.size(); k++)
251
      fprintf(f, "%c",tmpDIBBuffer[k]);
252
    fclose(f);
253
  }
254
#endif
255
256
0
  return d->dib;
257
0
}
258
/* vim:set shiftwidth=4 softtabstop=4 noexpandtab: */