Coverage Report

Created: 2023-09-25 06:41

/src/xpdf-4.04/splash/SplashBitmap.cc
Line
Count
Source (jump to first uncovered line)
1
//========================================================================
2
//
3
// SplashBitmap.cc
4
//
5
// Copyright 2003-2013 Glyph & Cog, LLC
6
//
7
//========================================================================
8
9
#include <aconf.h>
10
11
#ifdef USE_GCC_PRAGMAS
12
#pragma implementation
13
#endif
14
15
#include <stdio.h>
16
#include <limits.h>
17
#include "gmem.h"
18
#include "gmempp.h"
19
#include "gfile.h"
20
#include "Trace.h"
21
#include "SplashErrorCodes.h"
22
#include "SplashBitmap.h"
23
24
//------------------------------------------------------------------------
25
// SplashBitmap
26
//------------------------------------------------------------------------
27
28
SplashBitmap::SplashBitmap(int widthA, int heightA, int rowPad,
29
         SplashColorMode modeA, GBool alphaA,
30
0
         GBool topDown, SplashBitmap *parentA) {
31
  // NB: this code checks that rowSize fits in a signed 32-bit
32
  // integer, because some code (outside this class) makes that
33
  // assumption
34
0
  width = widthA;
35
0
  height = heightA;
36
0
  mode = modeA;
37
0
  switch (mode) {
38
0
  case splashModeMono1:
39
0
    if (width <= 0) {
40
0
      gMemError("invalid bitmap width");
41
0
    }
42
0
    rowSize = (width + 7) >> 3;
43
0
    break;
44
0
  case splashModeMono8:
45
0
    if (width <= 0) {
46
0
      gMemError("invalid bitmap width");
47
0
    }
48
0
    rowSize = width;
49
0
    break;
50
0
  case splashModeRGB8:
51
0
  case splashModeBGR8:
52
0
    if (width <= 0 || width > INT_MAX / 3) {
53
0
      gMemError("invalid bitmap width");
54
0
    }
55
0
    rowSize = (SplashBitmapRowSize)width * 3;
56
0
    break;
57
0
#if SPLASH_CMYK
58
0
  case splashModeCMYK8:
59
0
    if (width <= 0 || width > INT_MAX / 4) {
60
0
      gMemError("invalid bitmap width");
61
0
    }
62
0
    rowSize = (SplashBitmapRowSize)width * 4;
63
0
    break;
64
0
#endif
65
0
  }
66
0
  rowSize += rowPad - 1;
67
0
  rowSize -= rowSize % rowPad;
68
69
0
  traceAlloc(this, "alloc bitmap: %d x %d x %d %s -> %lld bytes",
70
0
       width, height, splashColorModeNComps[mode],
71
0
       alphaA ? "with alpha" : "without alpha",
72
0
       height * rowSize + (alphaA ? height * width : 0));
73
74
0
  parent = parentA;
75
0
  oldData = NULL;
76
0
  oldAlpha = NULL;
77
0
  oldRowSize = 0;
78
0
  oldAlphaRowSize = 0;
79
0
  oldHeight = 0;
80
0
  if (parent && parent->oldData &&
81
0
      parent->oldRowSize == rowSize &&
82
0
      parent->oldHeight == height) {
83
0
    data = parent->oldData;
84
0
    parent->oldData = NULL;
85
0
    traceMessage("reusing bitmap memory");
86
0
  } else {
87
0
    data = (SplashColorPtr)gmallocn64(height, rowSize);
88
0
    traceMessage("not reusing bitmap memory"
89
0
     " (parent=%p parent->oldData=%p same-size=%d)",
90
0
     parent, parent ? parent->oldData : NULL,
91
0
     parent ? (parent->oldRowSize == rowSize &&
92
0
         parent->oldHeight == height) : 0);
93
0
  }
94
0
  if (!topDown) {
95
0
    data += (height - 1) * rowSize;
96
0
    rowSize = -rowSize;
97
0
  }
98
0
  if (alphaA) {
99
0
    alphaRowSize = width;
100
0
    if (parent && parent->oldAlpha &&
101
0
  parent->oldAlphaRowSize == alphaRowSize &&
102
0
  parent->oldHeight == height) {
103
0
      alpha = parent->oldAlpha;
104
0
      parent->oldAlpha = NULL;
105
0
    } else {
106
0
      alpha = (Guchar *)gmallocn64(height, alphaRowSize);
107
0
    }
108
0
  } else {
109
0
    alphaRowSize = 0;
110
0
    alpha = NULL;
111
0
  }
112
0
}
113
114
0
SplashBitmap::~SplashBitmap() {
115
0
  traceFree(this, "free bitmap");
116
0
  if (data && rowSize < 0) {
117
0
    rowSize = -rowSize;
118
0
    data -= (height - 1) * rowSize;
119
0
  }
120
0
  if (parent && rowSize > 4000000 / height) {
121
0
    gfree(parent->oldData);
122
0
    gfree(parent->oldAlpha);
123
0
    parent->oldData = data;
124
0
    parent->oldAlpha = alpha;
125
0
    parent->oldRowSize = rowSize;
126
0
    parent->oldAlphaRowSize = alphaRowSize;
127
0
    parent->oldHeight = height;
128
0
  } else {
129
0
    gfree(data);
130
0
    gfree(alpha);
131
0
  }
132
0
  gfree(oldData);
133
0
  gfree(oldAlpha);
134
0
}
135
136
0
SplashError SplashBitmap::writePNMFile(char *fileName) {
137
0
  FILE *f;
138
0
  SplashError err;
139
140
0
  if (!(f = openFile(fileName, "wb"))) {
141
0
    return splashErrOpenFile;
142
0
  }
143
0
  err = writePNMFile(f);
144
0
  fclose(f);
145
0
  return err;
146
0
}
147
148
0
SplashError SplashBitmap::writePNMFile(FILE *f) {
149
0
  SplashColorPtr row, p;
150
0
  int x, y;
151
152
0
  switch (mode) {
153
154
0
  case splashModeMono1:
155
0
    fprintf(f, "P4\n%d %d\n", width, height);
156
0
    row = data;
157
0
    for (y = 0; y < height; ++y) {
158
0
      p = row;
159
0
      for (x = 0; x < width; x += 8) {
160
0
  fputc(*p ^ 0xff, f);
161
0
  ++p;
162
0
      }
163
0
      row += rowSize;
164
0
    }
165
0
    break;
166
167
0
  case splashModeMono8:
168
0
    fprintf(f, "P5\n%d %d\n255\n", width, height);
169
0
    row = data;
170
0
    for (y = 0; y < height; ++y) {
171
0
      fwrite(row, 1, width, f);
172
0
      row += rowSize;
173
0
    }
174
0
    break;
175
176
0
  case splashModeRGB8:
177
0
    fprintf(f, "P6\n%d %d\n255\n", width, height);
178
0
    row = data;
179
0
    for (y = 0; y < height; ++y) {
180
0
      fwrite(row, 1, 3 * width, f);
181
0
      row += rowSize;
182
0
    }
183
0
    break;
184
185
0
  case splashModeBGR8:
186
0
    fprintf(f, "P6\n%d %d\n255\n", width, height);
187
0
    row = data;
188
0
    for (y = 0; y < height; ++y) {
189
0
      p = row;
190
0
      for (x = 0; x < width; ++x) {
191
0
  fputc(splashBGR8R(p), f);
192
0
  fputc(splashBGR8G(p), f);
193
0
  fputc(splashBGR8B(p), f);
194
0
  p += 3;
195
0
      }
196
0
      row += rowSize;
197
0
    }
198
0
    break;
199
200
0
#if SPLASH_CMYK
201
0
  case splashModeCMYK8:
202
0
    fprintf(f, "P7\n");
203
0
    fprintf(f, "WIDTH %d\n", width);
204
0
    fprintf(f, "HEIGHT %d\n", height);
205
0
    fprintf(f, "DEPTH 4\n");
206
0
    fprintf(f, "MAXVAL 255\n");
207
0
    fprintf(f, "TUPLTYPE CMYK\n");
208
0
    fprintf(f, "ENDHDR\n");
209
0
    row = data;
210
0
    for (y = 0; y < height; ++y) {
211
0
      fwrite(row, 1, 4 * width, f);
212
0
      row += rowSize;
213
0
    }
214
0
    break;
215
0
#endif
216
217
0
  }
218
219
0
  return splashOk;
220
0
}
221
222
0
SplashError SplashBitmap::writeAlphaPGMFile(char *fileName) {
223
0
  FILE *f;
224
225
0
  if (!alpha) {
226
0
    return splashErrModeMismatch;
227
0
  }
228
0
  if (!(f = openFile(fileName, "wb"))) {
229
0
    return splashErrOpenFile;
230
0
  }
231
0
  fprintf(f, "P5\n%d %d\n255\n", width, height);
232
0
  fwrite(alpha, 1, width * height, f);
233
0
  fclose(f);
234
0
  return splashOk;
235
0
}
236
237
238
0
void SplashBitmap::getPixel(int x, int y, SplashColorPtr pixel) {
239
0
  SplashColorPtr p;
240
241
0
  if (y < 0 || y >= height || x < 0 || x >= width) {
242
0
    return;
243
0
  }
244
0
  switch (mode) {
245
0
  case splashModeMono1:
246
0
    p = &data[y * rowSize + (x >> 3)];
247
0
    pixel[0] = (p[0] & (0x80 >> (x & 7))) ? 0xff : 0x00;
248
0
    break;
249
0
  case splashModeMono8:
250
0
    p = &data[y * rowSize + x];
251
0
    pixel[0] = p[0];
252
0
    break;
253
0
  case splashModeRGB8:
254
0
    p = &data[y * rowSize + 3 * x];
255
0
    pixel[0] = p[0];
256
0
    pixel[1] = p[1];
257
0
    pixel[2] = p[2];
258
0
    break;
259
0
  case splashModeBGR8:
260
0
    p = &data[y * rowSize + 3 * x];
261
0
    pixel[0] = p[2];
262
0
    pixel[1] = p[1];
263
0
    pixel[2] = p[0];
264
0
    break;
265
0
#if SPLASH_CMYK
266
0
  case splashModeCMYK8:
267
0
    p = &data[y * rowSize + 4 * x];
268
0
    pixel[0] = p[0];
269
0
    pixel[1] = p[1];
270
0
    pixel[2] = p[2];
271
0
    pixel[3] = p[3];
272
0
    break;
273
0
#endif
274
0
  }
275
0
}
276
277
0
Guchar SplashBitmap::getAlpha(int x, int y) {
278
0
  return alpha[y * (size_t)width + x];
279
0
}
280
281
0
SplashColorPtr SplashBitmap::takeData() {
282
0
  SplashColorPtr data2;
283
284
0
  data2 = data;
285
0
  data = NULL;
286
0
  return data2;
287
0
}
288