Coverage Report

Created: 2024-07-05 06:13

/src/mupdf/source/fitz/load-bmp.c
Line
Count
Source (jump to first uncovered line)
1
// Copyright (C) 2004-2024 Artifex Software, Inc.
2
//
3
// This file is part of MuPDF.
4
//
5
// MuPDF is free software: you can redistribute it and/or modify it under the
6
// terms of the GNU Affero General Public License as published by the Free
7
// Software Foundation, either version 3 of the License, or (at your option)
8
// any later version.
9
//
10
// MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY
11
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12
// FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
13
// details.
14
//
15
// You should have received a copy of the GNU Affero General Public License
16
// along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
17
//
18
// Alternative licensing terms are available from the licensor.
19
// For commercial licensing, see <https://www.artifex.com/> or contact
20
// Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
21
// CA 94129, USA, for further information.
22
23
#include "mupdf/fitz.h"
24
25
#include "image-imp.h"
26
#include "pixmap-imp.h"
27
28
#include <string.h>
29
#include <limits.h>
30
31
#undef BMP_DEBUG
32
33
static const unsigned char web_palette[] = {
34
  0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x66, 0x00, 0x00, 0x99, 0x00, 0x00, 0xCC, 0x00, 0x00, 0xFF, 0x00, 0x00,
35
  0x00, 0x00, 0x33, 0x33, 0x00, 0x33, 0x66, 0x00, 0x33, 0x99, 0x00, 0x33, 0xCC, 0x00, 0x33, 0xFF, 0x00, 0x33,
36
  0x00, 0x00, 0x66, 0x33, 0x00, 0x66, 0x66, 0x00, 0x66, 0x99, 0x00, 0x66, 0xCC, 0x00, 0x66, 0xFF, 0x00, 0x66,
37
  0x00, 0x00, 0x99, 0x33, 0x00, 0x99, 0x66, 0x00, 0x99, 0x99, 0x00, 0x99, 0xCC, 0x00, 0x99, 0xFF, 0x00, 0x99,
38
  0x00, 0x00, 0xCC, 0x33, 0x00, 0xCC, 0x66, 0x00, 0xCC, 0x99, 0x00, 0xCC, 0xCC, 0x00, 0xCC, 0xFF, 0x00, 0xCC,
39
  0x00, 0x00, 0xFF, 0x33, 0x00, 0xFF, 0x66, 0x00, 0xFF, 0x99, 0x00, 0xFF, 0xCC, 0x00, 0xFF, 0xFF, 0x00, 0xFF,
40
  0x00, 0x33, 0x00, 0x33, 0x33, 0x00, 0x66, 0x33, 0x00, 0x99, 0x33, 0x00, 0xCC, 0x33, 0x00, 0xFF, 0x33, 0x00,
41
  0x00, 0x33, 0x33, 0x33, 0x33, 0x33, 0x66, 0x33, 0x33, 0x99, 0x33, 0x33, 0xCC, 0x33, 0x33, 0xFF, 0x33, 0x33,
42
  0x00, 0x33, 0x66, 0x33, 0x33, 0x66, 0x66, 0x33, 0x66, 0x99, 0x33, 0x66, 0xCC, 0x33, 0x66, 0xFF, 0x33, 0x66,
43
  0x00, 0x33, 0x99, 0x33, 0x33, 0x99, 0x66, 0x33, 0x99, 0x99, 0x33, 0x99, 0xCC, 0x33, 0x99, 0xFF, 0x33, 0x99,
44
  0x00, 0x33, 0xCC, 0x33, 0x33, 0xCC, 0x66, 0x33, 0xCC, 0x99, 0x33, 0xCC, 0xCC, 0x33, 0xCC, 0xFF, 0x33, 0xCC,
45
  0x00, 0x33, 0xFF, 0x33, 0x33, 0xFF, 0x66, 0x33, 0xFF, 0x99, 0x33, 0xFF, 0xCC, 0x33, 0xFF, 0xFF, 0x33, 0xFF,
46
  0x00, 0x66, 0x00, 0x33, 0x66, 0x00, 0x66, 0x66, 0x00, 0x99, 0x66, 0x00, 0xCC, 0x66, 0x00, 0xFF, 0x66, 0x00,
47
  0x00, 0x66, 0x33, 0x33, 0x66, 0x33, 0x66, 0x66, 0x33, 0x99, 0x66, 0x33, 0xCC, 0x66, 0x33, 0xFF, 0x66, 0x33,
48
  0x00, 0x66, 0x66, 0x33, 0x66, 0x66, 0x66, 0x66, 0x66, 0x99, 0x66, 0x66, 0xCC, 0x66, 0x66, 0xFF, 0x66, 0x66,
49
  0x00, 0x66, 0x99, 0x33, 0x66, 0x99, 0x66, 0x66, 0x99, 0x99, 0x66, 0x99, 0xCC, 0x66, 0x99, 0xFF, 0x66, 0x99,
50
  0x00, 0x66, 0xCC, 0x33, 0x66, 0xCC, 0x66, 0x66, 0xCC, 0x99, 0x66, 0xCC, 0xCC, 0x66, 0xCC, 0xFF, 0x66, 0xCC,
51
  0x00, 0x66, 0xFF, 0x33, 0x66, 0xFF, 0x66, 0x66, 0xFF, 0x99, 0x66, 0xFF, 0xCC, 0x66, 0xFF, 0xFF, 0x66, 0xFF,
52
  0x00, 0x99, 0x00, 0x33, 0x99, 0x00, 0x66, 0x99, 0x00, 0x99, 0x99, 0x00, 0xCC, 0x99, 0x00, 0xFF, 0x99, 0x00,
53
  0x00, 0x99, 0x33, 0x33, 0x99, 0x33, 0x66, 0x99, 0x33, 0x99, 0x99, 0x33, 0xCC, 0x99, 0x33, 0xFF, 0x99, 0x33,
54
  0x00, 0x99, 0x66, 0x33, 0x99, 0x66, 0x66, 0x99, 0x66, 0x99, 0x99, 0x66, 0xCC, 0x99, 0x66, 0xFF, 0x99, 0x66,
55
  0x00, 0x99, 0x99, 0x33, 0x99, 0x99, 0x66, 0x99, 0x99, 0x99, 0x99, 0x99, 0xCC, 0x99, 0x99, 0xFF, 0x99, 0x99,
56
  0x00, 0x99, 0xCC, 0x33, 0x99, 0xCC, 0x66, 0x99, 0xCC, 0x99, 0x99, 0xCC, 0xCC, 0x99, 0xCC, 0xFF, 0x99, 0xCC,
57
  0x00, 0x99, 0xFF, 0x33, 0x99, 0xFF, 0x66, 0x99, 0xFF, 0x99, 0x99, 0xFF, 0xCC, 0x99, 0xFF, 0xFF, 0x99, 0xFF,
58
  0x00, 0xCC, 0x00, 0x33, 0xCC, 0x00, 0x66, 0xCC, 0x00, 0x99, 0xCC, 0x00, 0xCC, 0xCC, 0x00, 0xFF, 0xCC, 0x00,
59
  0x00, 0xCC, 0x33, 0x33, 0xCC, 0x33, 0x66, 0xCC, 0x33, 0x99, 0xCC, 0x33, 0xCC, 0xCC, 0x33, 0xFF, 0xCC, 0x33,
60
  0x00, 0xCC, 0x66, 0x33, 0xCC, 0x66, 0x66, 0xCC, 0x66, 0x99, 0xCC, 0x66, 0xCC, 0xCC, 0x66, 0xFF, 0xCC, 0x66,
61
  0x00, 0xCC, 0x99, 0x33, 0xCC, 0x99, 0x66, 0xCC, 0x99, 0x99, 0xCC, 0x99, 0xCC, 0xCC, 0x99, 0xFF, 0xCC, 0x99,
62
  0x00, 0xCC, 0xCC, 0x33, 0xCC, 0xCC, 0x66, 0xCC, 0xCC, 0x99, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xFF, 0xCC, 0xCC,
63
  0x00, 0xCC, 0xFF, 0x33, 0xCC, 0xFF, 0x66, 0xCC, 0xFF, 0x99, 0xCC, 0xFF, 0xCC, 0xCC, 0xFF, 0xFF, 0xCC, 0xFF,
64
  0x00, 0xFF, 0x00, 0x33, 0xFF, 0x00, 0x66, 0xFF, 0x00, 0x99, 0xFF, 0x00, 0xCC, 0xFF, 0x00, 0xFF, 0xFF, 0x00,
65
  0x00, 0xFF, 0x33, 0x33, 0xFF, 0x33, 0x66, 0xFF, 0x33, 0x99, 0xFF, 0x33, 0xCC, 0xFF, 0x33, 0xFF, 0xFF, 0x33,
66
  0x00, 0xFF, 0x66, 0x33, 0xFF, 0x66, 0x66, 0xFF, 0x66, 0x99, 0xFF, 0x66, 0xCC, 0xFF, 0x66, 0xFF, 0xFF, 0x66,
67
  0x00, 0xFF, 0x99, 0x33, 0xFF, 0x99, 0x66, 0xFF, 0x99, 0x99, 0xFF, 0x99, 0xCC, 0xFF, 0x99, 0xFF, 0xFF, 0x99,
68
  0x00, 0xFF, 0xCC, 0x33, 0xFF, 0xCC, 0x66, 0xFF, 0xCC, 0x99, 0xFF, 0xCC, 0xCC, 0xFF, 0xCC, 0xFF, 0xFF, 0xCC,
69
  0x00, 0xFF, 0xFF, 0x33, 0xFF, 0xFF, 0x66, 0xFF, 0xFF, 0x99, 0xFF, 0xFF, 0xCC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
70
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
71
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
72
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
73
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
74
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
75
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
77
};
78
79
static const unsigned char vga_palette[] = {
80
  0x00, 0x00, 0x00, 0x00, 0x00, 0xAA, 0x00, 0xAA, 0x00, 0x00, 0xAA, 0xAA,
81
  0xAA, 0x00, 0x00, 0xAA, 0x00, 0xAA, 0xAA, 0x55, 0x00, 0xAA, 0xAA, 0xAA,
82
  0x55, 0x55, 0x55, 0x55, 0x55, 0xFF, 0x55, 0xFF, 0x55, 0x55, 0xFF, 0xFF,
83
  0xFF, 0x55, 0x55, 0xFF, 0x55, 0xFF, 0xFF, 0xFF, 0x55, 0xFF, 0xFF, 0xFF,
84
};
85
86
static const unsigned char gray_palette[] = {
87
  0x00, 0x00, 0x00, 0x54, 0x54, 0x54,
88
  0xA8, 0xA8, 0xA8, 0xFF, 0xFF, 0xFF,
89
};
90
91
static const unsigned char bw_palette[] = {
92
  0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF,
93
};
94
95
enum {
96
  BI_NONE = 0,
97
  BI_RLE8 = 1,
98
  BI_RLE4 = 2,
99
  BI_BITFIELDS = 3,
100
  BI_HUFFMAN1D = 3,
101
  BI_JPEG = 4,
102
  BI_RLE24 = 4,
103
  BI_PNG = 5,
104
  BI_ALPHABITS = 6,
105
};
106
107
struct info
108
{
109
  char type[2];
110
  uint32_t version;
111
  uint32_t bitmapoffset;
112
  uint32_t width, height;
113
  uint16_t bitcount;
114
  uint32_t compression;
115
  uint32_t bitmapsize;
116
  uint32_t xres, yres;
117
  uint32_t colors;
118
  uint32_t rmask, gmask, bmask, amask;
119
  uint8_t palette[256 * 3];
120
  uint32_t colorspacetype;
121
  uint32_t endpoints[3 * 3];
122
  uint32_t gamma[3];
123
  uint32_t intent;
124
  uint32_t profileoffset;
125
  uint32_t profilesize;
126
127
  int topdown;
128
  unsigned int rshift, gshift, bshift, ashift;
129
  unsigned int rbits, gbits, bbits, abits;
130
131
  unsigned char *samples;
132
  fz_colorspace *cs;
133
};
134
135
548
#define read8(p) ((p)[0])
136
141
#define read16(p) (((p)[1] << 8) | (p)[0])
137
2.59k
#define read32(p) (((p)[3] << 24) | ((p)[2] << 16) | ((p)[1] << 8) | (p)[0])
138
139
266
#define DPM_TO_DPI(dpm) ((dpm) * 25.4f / 1000.0f)
140
141
266
#define is_bitmap_array(p) ((p)[0] == 'B' && (p)[1] == 'A')
142
399
#define is_bitmap(p) ((p)[0] == 'B' && (p)[1] == 'M')
143
144
23
#define is_os2_bmp(info) ((info)->version == 12 || (info)->version == 16 || (info)->version == 64)
145
1.44k
#define is_win_bmp(info) ((info)->version == 12 || (info)->version == 40 || (info)->version == 52 || (info)->version == 56 || (info)->version == 108 || (info)->version == 124)
146
147
248
#define is_valid_win_compression(info) (is_win_bmp(info) && ((info)->compression == BI_NONE || (info)->compression == BI_RLE8 || (info)->compression == BI_RLE4 || (info)->compression == BI_BITFIELDS || (info)->compression == BI_JPEG || (info)->compression == BI_PNG || (info)->compression == BI_ALPHABITS || (info)->compression == BI_RLE24))
148
5
#define is_valid_os2_compression(info) (is_os2_bmp(info) && ((info)->compression == BI_NONE || (info)->compression == BI_RLE8 || (info)->compression == BI_RLE4 || (info)->compression == BI_HUFFMAN1D || (info)->compression == BI_RLE24))
149
124
#define is_valid_compression(info) (is_valid_win_compression(info) || is_valid_os2_compression(info))
150
151
240
#define is_valid_rgb_bitcount(info) ((info)->compression == BI_NONE && ((info)->bitcount == 1 || (info)->bitcount == 2 || (info)->bitcount == 4 || (info)->bitcount == 8 || (info)->bitcount == 16 || (info)->bitcount == 24 || (info)->bitcount == 32 || (info)->bitcount == 64))
152
230
#define is_valid_rle8_bitcount(info) ((info)->compression == BI_RLE8 && (info)->bitcount == 8)
153
215
#define is_valid_rle4_bitcount(info) ((info)->compression == BI_RLE4 && (info)->bitcount == 4)
154
202
#define is_valid_bitfields_bitcount(info) (is_win_bmp(info) && (info)->compression == BI_BITFIELDS && ((info)->bitcount == 16 || (info)->bitcount == 32))
155
124
#define is_valid_jpeg_bitcount(info) (is_win_bmp(info) && (info)->compression == BI_JPEG && (info)->bitcount == 0)
156
124
#define is_valid_png_bitcount(info) (is_win_bmp(info) && (info)->compression == BI_PNG && (info)->bitcount == 0)
157
124
#define is_valid_alphabits_bitcount(info) (is_win_bmp(info) && (info)->compression == BI_ALPHABITS && ((info)->bitcount == 16 || (info)->bitcount == 32))
158
122
#define is_valid_rle24_bitcount(info) (is_os2_bmp(info) && (info)->compression == BI_RLE24 && (info)->bitcount == 24)
159
2
#define is_valid_huffman1d_bitcount(info) (is_os2_bmp(info) && (info)->compression == BI_HUFFMAN1D && (info)->bitcount == 1)
160
120
#define is_valid_bitcount(info) (is_valid_rgb_bitcount(info) || is_valid_rle8_bitcount(info) || is_valid_rle4_bitcount(info) || is_valid_bitfields_bitcount(info) || is_valid_jpeg_bitcount(info) || is_valid_png_bitcount(info) || is_valid_alphabits_bitcount(info) || is_valid_rle24_bitcount(info) || is_valid_huffman1d_bitcount(info))
161
162
133
#define has_palette(info) ((info)->bitcount == 1 || (info)->bitcount == 2 || (info)->bitcount == 4 || (info)->bitcount == 8)
163
133
#define has_color_masks(info) (((info)->bitcount == 16 || (info)->bitcount == 32) && (info)->version == 40 && ((info)->compression == BI_BITFIELDS || (info)->compression == BI_ALPHABITS))
164
117
#define has_color_profile(info) ((info)->version == 108 || (info)->version == 124)
165
166
36
#define palette_entry_size(info) ((info)->version == 12 ? 3 : 4)
167
168
static const unsigned char *
169
bmp_read_file_header(fz_context *ctx, struct info *info, const unsigned char *begin, const unsigned char *end, const unsigned char *p)
170
133
{
171
133
  if (end - p < 14)
172
0
    fz_throw(ctx, FZ_ERROR_FORMAT, "premature end in file header in bmp image");
173
174
133
  if (!is_bitmap(p))
175
0
    fz_throw(ctx, FZ_ERROR_FORMAT, "invalid signature %02x%02x in bmp image", p[0], p[1]);
176
177
133
  info->type[0] = read8(p + 0);
178
133
  info->type[1] = read8(p + 1);
179
  /* read32(p+2) == file or header size */
180
  /* read16(p+6) == hotspot x for icons/cursors */
181
  /* read16(p+8) == hotspot y for icons/cursors */
182
133
  info->bitmapoffset = read32(p + 10);
183
184
133
  return p + 14;
185
133
}
186
187
static unsigned char *
188
bmp_decompress_huffman1d(fz_context *ctx, struct info *info, const unsigned char *p, const unsigned char **end)
189
0
{
190
0
  fz_stream *encstm, *decstm;
191
0
  fz_buffer *buf;
192
0
  unsigned char *decoded;
193
0
  size_t size;
194
195
0
  encstm = fz_open_memory(ctx, p, *end - p);
196
197
0
  fz_var(decstm);
198
0
  fz_var(buf);
199
200
0
  fz_try(ctx)
201
0
  {
202
0
    decstm = fz_open_faxd(ctx, encstm,
203
0
      0, /* 1 dimensional encoding */
204
0
      0, /* end of line not required */
205
0
      0, /* encoded byte align */
206
0
      info->width, info->height,
207
0
      0, /* end of block expected */
208
0
      1 /* black is 1 */
209
0
    );
210
0
    buf = fz_read_all(ctx, decstm, 1024);
211
0
    size = fz_buffer_extract(ctx, buf, &decoded);
212
0
    *end = decoded + size;
213
0
  }
214
0
  fz_always(ctx)
215
0
  {
216
0
    fz_drop_buffer(ctx, buf);
217
0
    fz_drop_stream(ctx, decstm);
218
0
    fz_drop_stream(ctx, encstm);
219
0
  }
220
0
  fz_catch(ctx)
221
0
    fz_rethrow(ctx);
222
223
0
  return decoded;
224
0
}
225
226
static unsigned char *
227
bmp_decompress_rle24(fz_context *ctx, struct info *info, const unsigned char *p, const unsigned char **end)
228
0
{
229
0
  const unsigned char *sp;
230
0
  unsigned char *dp, *ep, *decompressed;
231
0
  uint32_t width = info->width;
232
0
  uint32_t height = info->height;
233
0
  uint32_t stride;
234
0
  uint32_t x, y;
235
0
  int i;
236
237
0
  stride = (width*3 + 3) / 4 * 4;
238
239
0
  sp = p;
240
0
  dp = decompressed = fz_calloc(ctx, height, stride);
241
0
  ep = dp + height * stride;
242
0
  x = 0;
243
0
  y = 0;
244
245
0
  while (sp + 2 <= *end)
246
0
  {
247
0
    if (sp[0] == 0 && sp[1] == 0)
248
0
    { /* end of line */
249
0
      sp += 2;
250
0
      x = 0;
251
0
      y++;
252
0
    }
253
0
    else if (sp[0] == 0 && sp[1] == 1)
254
0
    { /* end of bitmap */
255
0
      sp += 2;
256
0
      break;
257
0
    }
258
0
    else if (sp[0] == 0 && sp[1] == 2)
259
0
    { /* delta */
260
0
      sp += 2;
261
0
      x += sp < *end ? *sp++ : 0;
262
0
      y += sp < *end ? *sp++ : 0;
263
0
    }
264
0
    else if (sp[0] == 0 && sp[1] >= 3)
265
0
    { /* absolute */
266
0
      int dn, sn, pad;
267
0
      dn = sp[1];
268
0
      sn = (dn * 3 + 1) / 2 * 2;
269
0
      pad = sn & 1;
270
0
      sp += 2;
271
0
      if (sn > *end - sp)
272
0
      {
273
0
        fz_warn(ctx, "premature end of pixel data in absolute code in bmp image");
274
0
        sn = ((*end - sp) / 3) * 3;
275
0
        pad = (*end - sp) % 3;
276
0
        dn = sn / 3;
277
0
      }
278
0
      else if (sn + pad > *end - sp)
279
0
      {
280
0
        fz_warn(ctx, "premature end of padding in absolute code in bmp image");
281
0
        pad = 0;
282
0
      }
283
0
      for (i = 0; i < dn; i++)
284
0
      {
285
0
        uint32_t actualx = x;
286
0
        uint32_t actualy = y;
287
0
        if (actualx >= width || actualy >= height)
288
0
        {
289
0
          actualx = x % width;
290
0
          actualy = y + x / width;
291
0
        }
292
0
        if (actualx < width && actualy < height)
293
0
        {
294
0
          dp = decompressed + actualy * stride + actualx * 3;
295
0
          *dp++ = sp[i * 3 + 0];
296
0
          *dp++ = sp[i * 3 + 1];
297
0
          *dp++ = sp[i * 3 + 2];
298
0
        }
299
0
        x++;
300
0
      }
301
0
      sp += sn + pad;
302
0
    }
303
0
    else
304
0
    { /* encoded */
305
0
      int dn, sn;
306
0
      dn = sp[0];
307
0
      sn = 3;
308
0
      sp++;
309
0
      if (sn > *end - sp)
310
0
      {
311
0
        fz_warn(ctx, "premature end of pixel data in encoded code in bmp image");
312
0
        sn = 0;
313
0
        dn = 0;
314
0
      }
315
0
      for (i = 0; i < dn; i++)
316
0
      {
317
0
        uint32_t actualx = x;
318
0
        uint32_t actualy = y;
319
0
        if (actualx >= width || actualy >= height)
320
0
        {
321
0
          actualx = x % width;
322
0
          actualy = y + x / width;
323
0
        }
324
0
        if (actualx < width && actualy < height)
325
0
        {
326
0
          dp = decompressed + actualy * stride + actualx * 3;
327
0
          *dp++ = sp[0];
328
0
          *dp++ = sp[1];
329
0
          *dp++ = sp[2];
330
0
        }
331
0
        x++;
332
0
      }
333
0
      sp += sn;
334
0
    }
335
0
  }
336
337
0
  info->compression = BI_NONE;
338
0
  info->bitcount = 24;
339
0
  *end = ep;
340
0
  return decompressed;
341
0
}
342
343
static unsigned char *
344
bmp_decompress_rle8(fz_context *ctx, struct info *info, const unsigned char *p, const unsigned char **end)
345
15
{
346
15
  const unsigned char *sp;
347
15
  unsigned char *dp, *ep, *decompressed;
348
15
  uint32_t width = info->width;
349
15
  uint32_t height = info->height;
350
15
  uint32_t stride;
351
15
  uint32_t x, y;
352
15
  int i;
353
354
15
  stride = (width + 3) / 4 * 4;
355
356
15
  sp = p;
357
15
  dp = decompressed = fz_calloc(ctx, height, stride);
358
15
  ep = dp + height * stride;
359
15
  x = 0;
360
15
  y = 0;
361
362
1.85k
  while (sp + 2 <= *end)
363
1.84k
  {
364
1.84k
    if (sp[0] == 0 && sp[1] == 0)
365
120
    { /* end of line */
366
120
      sp += 2;
367
120
      x = 0;
368
120
      y++;
369
120
    }
370
1.72k
    else if (sp[0] == 0 && sp[1] == 1)
371
1
    { /* end of bitmap */
372
1
      sp += 2;
373
1
      break;
374
1
    }
375
1.72k
    else if (sp[0] == 0 && sp[1] == 2)
376
2
    { /* delta */
377
2
      sp +=2;
378
2
      x += sp < *end ? *sp++ : 0;
379
2
      y += sp < *end ? *sp++ : 0;
380
2
    }
381
1.71k
    else if (sp[0] == 0 && sp[1] >= 3)
382
25
    { /* absolute */
383
25
      int dn, sn, pad;
384
25
      dn = sp[1];
385
25
      sn = dn;
386
25
      pad = sn & 1;
387
25
      sp += 2;
388
25
      if (sn > *end - sp)
389
7
      {
390
7
        fz_warn(ctx, "premature end of pixel data in absolute code in bmp image");
391
7
        sn = *end - sp;
392
7
        pad = 0;
393
7
        dn = sn;
394
7
      }
395
18
      else if (sn + pad > *end - sp)
396
0
      {
397
0
        fz_warn(ctx, "premature end of padding in absolute code in bmp image");
398
0
        pad = 0;
399
0
      }
400
1.76k
      for (i = 0; i < dn; i++)
401
1.73k
      {
402
1.73k
        uint32_t actualx = x;
403
1.73k
        uint32_t actualy = y;
404
1.73k
        if (actualx >= width || actualy >= height)
405
1.53k
        {
406
1.53k
          actualx = x % width;
407
1.53k
          actualy = y + x / width;
408
1.53k
        }
409
1.73k
        if (actualx < width && actualy < height)
410
576
        {
411
576
          dp = decompressed + actualy * stride + actualx;
412
576
          *dp++ = sp[i];
413
576
        }
414
1.73k
        x++;
415
1.73k
      }
416
25
      sp += sn + pad;
417
25
    }
418
1.69k
    else
419
1.69k
    { /* encoded */
420
1.69k
      int dn, sn;
421
1.69k
      dn = sp[0];
422
1.69k
      sn = 1;
423
1.69k
      sp++;
424
169k
      for (i = 0; i < dn; i++)
425
168k
      {
426
168k
        uint32_t actualx = x;
427
168k
        uint32_t actualy = y;
428
168k
        if (actualx >= width || actualy >= height)
429
167k
        {
430
167k
          actualx = x % width;
431
167k
          actualy = y + x / width;
432
167k
        }
433
168k
        if (actualx < width && actualy < height)
434
2.93k
        {
435
2.93k
          dp = decompressed + actualy * stride + actualx;
436
2.93k
          *dp++ = sp[0];
437
2.93k
        }
438
168k
        x++;
439
168k
      }
440
1.69k
      sp += sn;
441
1.69k
    }
442
1.84k
  }
443
444
15
  info->compression = BI_NONE;
445
15
  info->bitcount = 8;
446
15
  *end = ep;
447
15
  return decompressed;
448
15
}
449
450
static unsigned char *
451
bmp_decompress_rle4(fz_context *ctx, struct info *info, const unsigned char *p, const unsigned char **end)
452
13
{
453
13
  const unsigned char *sp;
454
13
  unsigned char *dp, *ep, *decompressed;
455
13
  uint32_t width = info->width;
456
13
  uint32_t height = info->height;
457
13
  uint32_t stride;
458
13
  uint32_t x, y;
459
13
  int i;
460
461
13
  stride = ((width + 1) / 2 + 3) / 4 * 4;
462
463
13
  sp = p;
464
13
  dp = decompressed = fz_calloc(ctx, height, stride);
465
13
  ep = dp + height * stride;
466
13
  x = 0;
467
13
  y = 0;
468
469
2.20k
  while (sp + 2 <= *end)
470
2.19k
  {
471
2.19k
    if (sp[0] == 0 && sp[1] == 0)
472
114
    { /* end of line */
473
114
      sp += 2;
474
114
      x = 0;
475
114
      y++;
476
114
    }
477
2.07k
    else if (sp[0] == 0 && sp[1] == 1)
478
1
    { /* end of bitmap */
479
1
      sp += 2;
480
1
      break;
481
1
    }
482
2.07k
    else if (sp[0] == 0 && sp[1] == 2)
483
3
    { /* delta */
484
3
      sp += 2;
485
3
      x += sp < *end ? *sp++ : 0;
486
3
      y += sp < *end ? *sp++ : 0;
487
3
    }
488
2.07k
    else if (sp[0] == 0 && sp[1] >= 3)
489
100
    { /* absolute */
490
100
      int dn, sn, pad;
491
100
      dn = sp[1];
492
100
      sn = (dn + 1) / 2;
493
100
      pad = sn & 1;
494
100
      sp += 2;
495
100
      if (sn > *end - sp)
496
5
      {
497
5
        fz_warn(ctx, "premature end of pixel data in absolute code in bmp image");
498
5
        sn = *end - sp;
499
5
        pad = 0;
500
5
        dn = sn * 2;
501
5
      }
502
95
      else if (sn + pad > *end - sp)
503
0
      {
504
0
        fz_warn(ctx, "premature end of padding in absolute code in bmp image");
505
0
        pad = 0;
506
0
      }
507
3.87k
      for (i = 0; i < dn; i++)
508
3.77k
      {
509
3.77k
        uint32_t actualx = x;
510
3.77k
        uint32_t actualy = y;
511
3.77k
        if (actualx >= width || actualy >= height)
512
1.24k
        {
513
1.24k
          actualx = x % width;
514
1.24k
          actualy = y + x / width;
515
1.24k
        }
516
3.77k
        if (actualx < width && actualy < height)
517
3.20k
        {
518
3.20k
          int val = i & 1 ? (sp[i >> 1]) & 0xF : (sp[i >> 1] >> 4) & 0xF;
519
3.20k
          dp = decompressed + actualy * stride + actualx / 2;
520
3.20k
          if (x & 1)
521
1.60k
            *dp++ |= val;
522
1.60k
          else
523
1.60k
            *dp |= val << 4;
524
3.20k
        }
525
3.77k
        x++;
526
3.77k
      }
527
100
      sp += sn + pad;
528
100
    }
529
1.97k
    else
530
1.97k
    { /* encoded */
531
1.97k
      int dn, sn;
532
1.97k
      dn = sp[0];
533
1.97k
      sn = 1;
534
1.97k
      sp++;
535
159k
      for (i = 0; i < dn; i++)
536
157k
      {
537
157k
        uint32_t actualx = x;
538
157k
        uint32_t actualy = y;
539
157k
        if (actualx >= width || actualy >= height)
540
66.5k
        {
541
66.5k
          actualx = x % width;
542
66.5k
          actualy = y + x / width;
543
66.5k
        }
544
157k
        if (actualx < width && actualy < height)
545
145k
        {
546
145k
          int val = i & 1 ? (sp[0] & 0xf) : (sp[0] >> 4) & 0xf;
547
145k
          dp = decompressed + actualy * stride + actualx / 2;
548
145k
          if (x & 1)
549
72.8k
            *dp++ |= val;
550
72.8k
          else
551
72.8k
            *dp |= val << 4;
552
145k
        }
553
157k
        x++;
554
157k
      }
555
1.97k
      sp += sn;
556
1.97k
    }
557
2.19k
  }
558
559
13
  info->compression = BI_NONE;
560
13
  info->bitcount = 4;
561
13
  *end = ep;
562
13
  return decompressed;
563
13
}
564
565
static fz_pixmap *
566
bmp_read_bitmap(fz_context *ctx, struct info *info, const unsigned char *begin, const unsigned char *end, const unsigned char *p)
567
108
{
568
108
  const unsigned int mults[] = { 0, 8191, 2730, 1170, 546, 264, 130, 64 };
569
108
  fz_pixmap *pix;
570
108
  const unsigned char *ssp;
571
108
  unsigned char *ddp;
572
108
  unsigned char *decompressed = NULL;
573
108
  uint32_t bitcount;
574
108
  uint32_t width;
575
108
  int32_t height;
576
108
  uint32_t sstride;
577
108
  int32_t dstride;
578
108
  unsigned int rmult, gmult, bmult, amult;
579
108
  unsigned int rtrunc, gtrunc, btrunc, atrunc;
580
108
  uint32_t x;
581
108
  int32_t y;
582
583
108
  assert(info->width > 0 && info->width <= SHRT_MAX);
584
108
  assert(info->height > 0 && info->height <= SHRT_MAX);
585
586
108
  if (info->compression == BI_NONE)
587
8
    ssp = p;
588
100
  else if (info->compression == BI_RLE4)
589
13
    ssp = decompressed = bmp_decompress_rle4(ctx, info, p, &end);
590
87
  else if (info->compression == BI_RLE8)
591
15
    ssp = decompressed = bmp_decompress_rle8(ctx, info, p, &end);
592
72
  else if (is_win_bmp(info) && (info->compression == BI_BITFIELDS || info->compression == BI_ALPHABITS))
593
72
    ssp = p;
594
0
  else if (is_os2_bmp(info) && info->compression == BI_RLE24)
595
0
    ssp = decompressed = bmp_decompress_rle24(ctx, info, p, &end);
596
0
  else if (is_os2_bmp(info) && info->compression == BI_HUFFMAN1D)
597
0
    ssp = decompressed = bmp_decompress_huffman1d(ctx, info, p, &end);
598
0
  else
599
0
    fz_throw(ctx, FZ_ERROR_FORMAT, "unhandled compression (%u)  in bmp image", info->compression);
600
601
108
  bitcount = info->bitcount;
602
108
  width = info->width;
603
108
  height = info->height;
604
605
108
  sstride = ((width * bitcount + 31) / 32) * 4;
606
108
  if (ssp + sstride * height > end)
607
75
  {
608
75
    int32_t h = (end - ssp) / sstride;
609
75
    if (h == 0 || h > SHRT_MAX)
610
5
    {
611
5
      fz_free(ctx, decompressed);
612
5
      fz_throw(ctx, FZ_ERROR_LIMIT, "image dimensions out of range in bmp image");
613
5
    }
614
75
  }
615
616
206
  fz_try(ctx)
617
206
  {
618
103
    pix = fz_new_pixmap(ctx, info->cs, width, height, NULL, 1);
619
103
    fz_set_pixmap_resolution(ctx, pix, info->xres, info->yres);
620
103
    fz_clear_pixmap(ctx, pix);
621
103
  }
622
206
  fz_catch(ctx)
623
0
  {
624
0
    fz_free(ctx, decompressed);
625
0
    fz_rethrow(ctx);
626
0
  }
627
628
103
  ddp = pix->samples;
629
103
  dstride = pix->stride;
630
103
  if (!info->topdown)
631
77
  {
632
77
    ddp = pix->samples + ((size_t) (height - 1)) * ((size_t) dstride);
633
77
    dstride = -dstride;
634
77
  }
635
636
103
  if (ssp + sstride * height > end)
637
70
  {
638
70
    fz_warn(ctx, "premature end in bitmap data in bmp image");
639
70
    height = (end - ssp) / sstride;
640
70
  }
641
642
  /* These are only used for 16- and 32-bit components
643
     1-bit (1 * 8191) / 32
644
     2-bit (3 * 2730) / 32
645
     3-bit (7 * 1170) / 32
646
     4-bit (15 * 546) / 32
647
     5-bit (31 * 264) / 32
648
     6-bit (63 * 130) / 32
649
     7-bit (127 * 64) / 32
650
  */
651
103
  rmult = info->rbits < 8 ? mults[info->rbits] : 1;
652
103
  gmult = info->gbits < 8 ? mults[info->gbits] : 1;
653
103
  bmult = info->bbits < 8 ? mults[info->bbits] : 1;
654
103
  amult = info->abits < 8 ? mults[info->abits] : 1;
655
103
  rtrunc = info->rbits < 8 ? 5 : (info->rbits - 8);
656
103
  gtrunc = info->gbits < 8 ? 5 : (info->gbits - 8);
657
103
  btrunc = info->bbits < 8 ? 5 : (info->bbits - 8);
658
103
  atrunc = info->abits < 8 ? 5 : (info->abits - 8);
659
#ifdef BMP_DEBUG
660
  fz_warn(ctx, "rbits = %2d mult = %2d trunc = %2d", info->rbits, rmult, rtrunc);
661
  fz_warn(ctx, "gbits = %2d mult = %2d trunc = %2d", info->gbits, gmult, gtrunc);
662
  fz_warn(ctx, "bbits = %2d mult = %2d trunc = %2d", info->bbits, bmult, btrunc);
663
  fz_warn(ctx, "abits = %2d mult = %2d trunc = %2d", info->abits, amult, atrunc);
664
#endif
665
666
18.7k
  for (y = 0; y < height; y++)
667
18.6k
  {
668
18.6k
    const unsigned char *sp = ssp + ((size_t) y) * ((size_t) sstride);
669
18.6k
    unsigned char *dp = ddp + ((size_t) y) * ((size_t) dstride);
670
671
18.6k
    switch (bitcount)
672
18.6k
    {
673
0
    case 64:
674
0
      for (x = 0; x < width; x++)
675
0
      {
676
0
        uint32_t a = (((uint16_t)sp[7]) << 8) | (((uint16_t)sp[6]) << 0);
677
0
        uint32_t r = (((uint16_t)sp[5]) << 8) | (((uint16_t)sp[4]) << 0);
678
0
        uint32_t g = (((uint16_t)sp[3]) << 8) | (((uint16_t)sp[2]) << 0);
679
0
        uint32_t b = (((uint16_t)sp[1]) << 8) | (((uint16_t)sp[0]) << 0);
680
0
        r = (r * 255 + 4096) >> 13;
681
0
        g = (g * 255 + 4096) >> 13;
682
0
        b = (b * 255 + 4096) >> 13;
683
0
        a = (a * 255 + 4096) >> 13;
684
0
        *dp++ = r;
685
0
        *dp++ = g;
686
0
        *dp++ = b;
687
0
        *dp++ = a;
688
0
        sp += 8;
689
0
      }
690
0
      break;
691
1.92k
    case 32:
692
3.93k
      for (x = 0; x < width; x++)
693
2.00k
      {
694
2.00k
        uint32_t sample =
695
2.00k
          (((uint32_t) sp[3]) << 24) |
696
2.00k
          (((uint32_t) sp[2]) << 16) |
697
2.00k
          (((uint32_t) sp[1]) <<  8) |
698
2.00k
          (((uint32_t) sp[0]) <<  0);
699
2.00k
        uint32_t r = (sample & info->rmask) >> info->rshift;
700
2.00k
        uint32_t g = (sample & info->gmask) >> info->gshift;
701
2.00k
        uint32_t b = (sample & info->bmask) >> info->bshift;
702
2.00k
        uint32_t a = info->abits == 0 ? 255 : (sample & info->amask) >> info->ashift;
703
2.00k
        *dp++ = (r * rmult) >> rtrunc;
704
2.00k
        *dp++ = (g * gmult) >> gtrunc;
705
2.00k
        *dp++ = (b * bmult) >> btrunc;
706
2.00k
        *dp++ = info->abits == 0 ? a : (a * amult) >> atrunc;
707
2.00k
        sp += 4;
708
2.00k
      }
709
1.92k
      break;
710
179
    case 24:
711
1.79k
      for (x = 0; x < width; x++)
712
1.61k
      {
713
1.61k
        *dp++ = sp[2];
714
1.61k
        *dp++ = sp[1];
715
1.61k
        *dp++ = sp[0];
716
1.61k
        *dp++ = 255;
717
1.61k
        sp += 3;
718
1.61k
      }
719
179
      break;
720
907
    case 16:
721
2.69k
      for (x = 0; x < width; x++)
722
1.78k
      {
723
1.78k
        uint16_t sample =
724
1.78k
          (((uint16_t)sp[1]) << 8) |
725
1.78k
          (((uint16_t)sp[0]) << 0);
726
1.78k
        uint16_t r = (sample & info->rmask) >> info->rshift;
727
1.78k
        uint16_t g = (sample & info->gmask) >> info->gshift;
728
1.78k
        uint16_t b = (sample & info->bmask) >> info->bshift;
729
1.78k
        uint16_t a = (sample & info->amask) >> info->ashift;
730
1.78k
        *dp++ = (r * rmult) >> rtrunc;
731
1.78k
        *dp++ = (g * gmult) >> gtrunc;
732
1.78k
        *dp++ = (b * bmult) >> btrunc;
733
1.78k
        *dp++ = info->abits == 0 ? 255 : (a * amult) >> atrunc;
734
1.78k
        sp += 2;
735
1.78k
      }
736
907
      break;
737
2.06k
    case 8:
738
121k
      for (x = 0; x < width; x++)
739
119k
      {
740
119k
        *dp++ = info->palette[3 * sp[0] + 0];
741
119k
        *dp++ = info->palette[3 * sp[0] + 1];
742
119k
        *dp++ = info->palette[3 * sp[0] + 2];
743
119k
        *dp++ = 255;
744
119k
        sp++;
745
119k
      }
746
2.06k
      break;
747
13.5k
    case 4:
748
58.1M
      for (x = 0; x < width; x++)
749
58.1M
      {
750
58.1M
        int idx;
751
58.1M
        switch (x & 1)
752
58.1M
        {
753
29.0M
        case 0: idx = (sp[0] >> 4) & 0x0f; break;
754
29.0M
        case 1: idx = (sp[0] >> 0) & 0x0f; sp++; break;
755
58.1M
        }
756
58.1M
        *dp++ = info->palette[3 * idx + 0];
757
58.1M
        *dp++ = info->palette[3 * idx + 1];
758
58.1M
        *dp++ = info->palette[3 * idx + 2];
759
58.1M
        *dp++ = 255;
760
58.1M
      }
761
13.5k
      break;
762
13.5k
    case 2:
763
0
      for (x = 0; x < width; x++)
764
0
      {
765
0
        int idx;
766
0
        switch (x & 3)
767
0
        {
768
0
        case 0: idx = (sp[0] >> 6) & 0x03; break;
769
0
        case 1: idx = (sp[0] >> 4) & 0x03; break;
770
0
        case 2: idx = (sp[0] >> 2) & 0x03; break;
771
0
        case 3: idx = (sp[0] >> 0) & 0x03; sp++; break;
772
0
        }
773
0
        *dp++ = info->palette[3 * idx + 0];
774
0
        *dp++ = info->palette[3 * idx + 1];
775
0
        *dp++ = info->palette[3 * idx + 2];
776
0
        *dp++ = 255;
777
0
      }
778
0
      break;
779
25
    case 1:
780
369
      for (x = 0; x < width; x++)
781
344
      {
782
344
        int idx;
783
344
        switch (x & 7)
784
344
        {
785
57
        case 0: idx = (sp[0] >> 7) & 0x01; break;
786
41
        case 1: idx = (sp[0] >> 6) & 0x01; break;
787
41
        case 2: idx = (sp[0] >> 5) & 0x01; break;
788
41
        case 3: idx = (sp[0] >> 4) & 0x01; break;
789
41
        case 4: idx = (sp[0] >> 3) & 0x01; break;
790
41
        case 5: idx = (sp[0] >> 2) & 0x01; break;
791
41
        case 6: idx = (sp[0] >> 1) & 0x01; break;
792
41
        case 7: idx = (sp[0] >> 0) & 0x01; sp++; break;
793
344
        }
794
344
        *dp++ = info->palette[3 * idx + 0];
795
344
        *dp++ = info->palette[3 * idx + 1];
796
344
        *dp++ = info->palette[3 * idx + 2];
797
344
        *dp++ = 255;
798
344
      }
799
25
      break;
800
18.6k
    }
801
18.6k
  }
802
803
103
  fz_free(ctx, decompressed);
804
103
  fz_premultiply_pixmap(ctx, pix);
805
103
  return pix;
806
103
}
807
808
static fz_colorspace *
809
bmp_read_color_profile(fz_context *ctx, struct info *info, const unsigned char *begin, const unsigned char *end)
810
76
{
811
76
  if (info->colorspacetype == 0)
812
50
  {
813
50
    float matrix[9] = { 1, 0, 0, 0, 1, 0, 0, 0, 1 };
814
50
    float wp[3] = { 0.95047f, 1.0f, 1.08883f }; /* D65 white point */
815
50
    float bp[3] = { 0, 0, 0 };
816
50
    float gamma[3] = { 1, 1, 1 };
817
50
    int i;
818
819
200
    for (i = 0; i < 3; i++)
820
150
      gamma[i] = (float) info->gamma[i] / (float) (1 << 16);
821
500
    for (i = 0; i < 9; i++)
822
450
      matrix[i] = (float) info->endpoints[i] / (float) (1 << 30);
823
824
#ifdef BMP_DEBUG
825
    fz_warn(ctx, "wp = %.6f %.6f %.6f", wp[0], wp[1], wp[2]);
826
    fz_warn(ctx, "bp = %.6f %.6f %.6f", bp[0], bp[1], bp[2]);
827
    fz_warn(ctx, "endpoints = %.6f %.6f %.6f", matrix[0], matrix[1], matrix[2]);
828
    fz_warn(ctx, "endpoints = %.6f %.6f %.6f", matrix[3], matrix[4], matrix[5]);
829
    fz_warn(ctx, "endpoints = %.6f %.6f %.6f", matrix[6], matrix[7], matrix[8]);
830
    fz_warn(ctx, "gamma = %.6f %.6f %.6f", gamma[0], gamma[1], gamma[2]);
831
#endif
832
833
50
    return fz_new_cal_rgb_colorspace(ctx, wp, bp, gamma, matrix);
834
50
  }
835
26
  else if (info->colorspacetype == 0x4c494e4b)
836
0
  {
837
0
    fz_warn(ctx, "ignoring linked color profile in bmp image");
838
0
    return NULL;
839
0
  }
840
26
  else if (info->colorspacetype == 0x57696e20)
841
0
  {
842
0
    fz_warn(ctx, "ignoring windows color profile in bmp image");
843
0
    return NULL;
844
0
  }
845
26
  else if (info->colorspacetype == 0x4d424544)
846
10
  {
847
10
    fz_buffer *profile;
848
10
    fz_colorspace *cs;
849
850
10
    if ((uint32_t)(end - begin) <= info->profileoffset)
851
3
    {
852
3
      fz_warn(ctx, "ignoring color profile located outside bmp image");
853
3
      return NULL;
854
3
    }
855
7
    if ((uint32_t)(end - begin) - info->profileoffset < info->profilesize)
856
2
    {
857
2
      fz_warn(ctx, "ignoring truncated color profile in bmp image");
858
2
      return NULL;
859
2
    }
860
5
    if (info->profilesize == 0)
861
0
    {
862
0
      fz_warn(ctx, "ignoring color profile without data in bmp image");
863
0
      return NULL;
864
0
    }
865
866
5
    profile = fz_new_buffer_from_copied_data(ctx, begin + info->profileoffset, info->profilesize);
867
868
10
    fz_try(ctx)
869
10
      cs = fz_new_icc_colorspace(ctx, FZ_COLORSPACE_RGB, 0, "BMPRGB", profile);
870
10
    fz_always(ctx)
871
5
      fz_drop_buffer(ctx, profile);
872
5
    fz_catch(ctx)
873
5
      fz_rethrow(ctx);
874
875
0
    return cs;
876
5
  }
877
16
  else if (info->colorspacetype == 0x73524742)
878
0
  {
879
0
    return fz_keep_colorspace(ctx, fz_device_rgb(ctx));
880
0
  }
881
882
16
  fz_warn(ctx, "ignoring color profile with unknown type in bmp image");
883
16
  return NULL;
884
76
}
885
886
static void
887
compute_mask_info(unsigned int mask, unsigned int *shift, unsigned int *bits)
888
524
{
889
524
  *bits = 0;
890
524
  *shift = 0;
891
892
1.68k
  while (mask && (mask & 1) == 0) {
893
1.16k
    *shift += 1;
894
1.16k
    mask >>= 1;
895
1.16k
  }
896
1.83k
  while (mask && (mask & 1) == 1) {
897
1.31k
    *bits += 1;
898
1.31k
    mask >>= 1;
899
1.31k
  }
900
524
}
901
902
static const unsigned char *
903
bmp_read_color_masks(fz_context *ctx, struct info *info, const unsigned char *begin, const unsigned char *end, const unsigned char *p)
904
4
{
905
4
  int size = 0;
906
907
4
  if (info->compression == BI_BITFIELDS)
908
2
  {
909
2
    size = 12;
910
2
    if (end - p < 12)
911
0
      fz_throw(ctx, FZ_ERROR_FORMAT, "premature end in mask header in bmp image");
912
913
2
    info->rmask = read32(p + 0);
914
2
    info->gmask = read32(p + 4);
915
2
    info->bmask = read32(p + 8);
916
2
  }
917
2
  else if (info->compression == BI_ALPHABITS)
918
2
  {
919
2
    size = 16;
920
2
    if (end - p < 16)
921
0
      fz_throw(ctx, FZ_ERROR_FORMAT, "premature end in mask header in bmp image");
922
923
2
    info->rmask = read32(p + 0);
924
2
    info->gmask = read32(p + 4);
925
2
    info->bmask = read32(p + 8);
926
2
    info->amask = read32(p + 12);
927
2
  }
928
929
4
  return p + size;
930
4
}
931
932
static int
933
bmp_palette_is_gray(fz_context *ctx, struct info *info, int readcolors)
934
33
{
935
33
  int i;
936
71
  for (i = 0; i < readcolors; i++)
937
49
  {
938
49
    int rgdiff = fz_absi(info->palette[3 * i + 0] - info->palette[3 * i + 1]);
939
49
    int gbdiff = fz_absi(info->palette[3 * i + 1] - info->palette[3 * i + 2]);
940
49
    int rbdiff = fz_absi(info->palette[3 * i + 0] - info->palette[3 * i + 2]);
941
49
    if (rgdiff > 2 || gbdiff > 2 || rbdiff > 2)
942
11
      return 0;
943
49
  }
944
22
  return 1;
945
33
}
946
947
static void
948
bmp_load_default_palette(fz_context *ctx, struct info *info, int readcolors)
949
34
{
950
34
  int i;
951
952
34
  fz_warn(ctx, "color table too short; loading default palette");
953
954
34
  if (info->bitcount == 8)
955
17
  {
956
17
    if (!bmp_palette_is_gray(ctx, info, readcolors))
957
3
      memcpy(&info->palette[readcolors * 3], &web_palette[readcolors * 3],
958
3
          sizeof(web_palette) - readcolors * 3);
959
14
    else
960
3.57k
      for (i = readcolors; i < 256; i++)
961
3.56k
      {
962
3.56k
        info->palette[3 * i + 0] = i;
963
3.56k
        info->palette[3 * i + 1] = i;
964
3.56k
        info->palette[3 * i + 2] = i;
965
3.56k
      }
966
17
  }
967
17
  else if (info->bitcount == 4)
968
16
  {
969
16
    if (!bmp_palette_is_gray(ctx, info, readcolors))
970
8
      memcpy(&info->palette[readcolors * 3], &vga_palette[readcolors * 3],
971
8
          sizeof(vga_palette) - readcolors * 3);
972
8
    else
973
131
      for (i = readcolors; i < 16; i++)
974
123
      {
975
123
        info->palette[3 * i + 0] = (i << 4) | i;
976
123
        info->palette[3 * i + 1] = (i << 4) | i;
977
123
        info->palette[3 * i + 2] = (i << 4) | i;
978
123
      }
979
16
  }
980
1
  else if (info->bitcount == 2)
981
0
    memcpy(info->palette, gray_palette, sizeof(gray_palette));
982
1
  else if (info->bitcount == 1)
983
1
    memcpy(info->palette, bw_palette, sizeof(bw_palette));
984
34
}
985
986
static const unsigned char *
987
bmp_read_palette(fz_context *ctx, struct info *info, const unsigned char *begin, const unsigned char *end, const unsigned char *p)
988
36
{
989
36
  int i, expected, present, entry_size;
990
991
36
  entry_size = palette_entry_size(info);
992
993
36
  if (info->colors == 0)
994
6
    expected = info->colors = 1 << info->bitcount;
995
30
  else
996
30
    expected = fz_mini(info->colors, 1 << info->bitcount);
997
998
36
  if (info->bitmapoffset == 0)
999
0
    present = fz_mini(expected, (end - p) / entry_size);
1000
36
  else
1001
36
    present = fz_mini(expected, (begin + info->bitmapoffset - p) / entry_size);
1002
1003
130
  for (i = 0; i < present; i++)
1004
94
  {
1005
    /* ignore alpha channel even if present */
1006
94
    info->palette[3 * i + 0] = read8(p + i * entry_size + 2);
1007
94
    info->palette[3 * i + 1] = read8(p + i * entry_size + 1);
1008
94
    info->palette[3 * i + 2] = read8(p + i * entry_size + 0);
1009
94
  }
1010
1011
36
  if (present < expected)
1012
34
    bmp_load_default_palette(ctx, info, present);
1013
1014
36
  return p + present * entry_size;
1015
36
}
1016
1017
static const unsigned char *
1018
bmp_read_info_header(fz_context *ctx, struct info *info, const unsigned char *begin, const unsigned char *end, const unsigned char *p)
1019
133
{
1020
133
  uint32_t size;
1021
1022
133
  if (end - p < 4)
1023
0
    fz_throw(ctx, FZ_ERROR_FORMAT, "premature end in info header in bmp image");
1024
133
  size = info->version = read32(p + 0);
1025
1026
133
  if (!is_win_bmp(info) && !is_os2_bmp(info))
1027
2
    fz_throw(ctx, FZ_ERROR_FORMAT, "unknown header version (%u) in bmp image", info->version);
1028
131
  if ((uint32_t)(end - p) < size)
1029
0
    fz_throw(ctx, FZ_ERROR_FORMAT, "premature end in info header in bmp image");
1030
1031
  /* default compression */
1032
131
  info->compression = BI_NONE;
1033
1034
  /* OS/2 1.x or Windows v2 */
1035
131
  if (size == 12)
1036
5
  {
1037
    /* read32(p+0) == header size */
1038
5
    info->width = read16(p + 4);
1039
5
    info->height = read16(p + 6);
1040
    /* read16(p+8) == planes */
1041
5
    info->bitcount = read16(p + 10);
1042
5
  }
1043
  /* OS/2 2.x short header */
1044
131
  if (size >= 16)
1045
126
  {
1046
    /* read32(p+0) == header size */
1047
126
    info->width = read32(p + 4);
1048
126
    info->height = read32(p + 8);
1049
    /* read16(p+12) == planes */
1050
126
    info->bitcount = read16(p + 14);
1051
126
  }
1052
1053
  /* default masks */
1054
131
  if (info->bitcount == 16)
1055
48
  {
1056
48
    info->rmask = 0x00007c00;
1057
48
    info->gmask = 0x000003e0;
1058
48
    info->bmask = 0x0000001f;
1059
48
    info->amask = 0x00000000;
1060
48
  }
1061
83
  else if (info->bitcount == 24 || info->bitcount == 32)
1062
36
  {
1063
36
    info->rmask = 0x00ff0000;
1064
36
    info->gmask = 0x0000ff00;
1065
36
    info->bmask = 0x000000ff;
1066
36
    info->amask = 0x00000000;
1067
36
  }
1068
1069
  /* Windows v3 header */
1070
131
  if (size >= 40)
1071
124
  {
1072
124
    info->compression = read32(p + 16);
1073
124
    info->bitmapsize = read32(p + 20);
1074
124
    info->xres = read32(p + 24);
1075
124
    info->yres = read32(p + 28);
1076
124
    info->colors = read32(p + 32);
1077
124
    if (info->bitcount >= 32)
1078
43
    {
1079
43
      if (info->colors != 0)
1080
37
        fz_warn(ctx, "Suspect BMP header; bitcount=%d, colors=%d", info->bitcount, info->colors);
1081
43
      info->colors = 0;
1082
43
    }
1083
81
    else if (info->colors > (1U<<info->bitcount))
1084
63
    {
1085
63
      fz_warn(ctx, "Suspect BMP header; bitcount=%d, colors=%d", info->bitcount, info->colors);
1086
63
      info->colors = 1<<info->bitcount;
1087
63
    }
1088
    /* read32(p+36) == important colors */
1089
124
  }
1090
  /* Windows v3 header with RGB masks */
1091
131
  if (size == 52 || size == 56 || size == 108 || size == 124)
1092
94
  {
1093
94
    info->rmask = read32(p + 40);
1094
94
    info->gmask = read32(p + 44);
1095
94
    info->bmask = read32(p + 48);
1096
94
  }
1097
  /* Windows v3 header with RGBA masks */
1098
131
  if (size == 56 || size == 108 || size == 124)
1099
93
  {
1100
93
    info->amask = read32(p + 52);
1101
93
  }
1102
  /* OS/2 2.x long header */
1103
131
  if (size == 64)
1104
1
  {
1105
    /* read16(p+40) == units */
1106
    /* read16(p+42) == reserved */
1107
    /* read16(p+44) == recording */
1108
    /* read16(p+46) == rendering */
1109
    /* read32(p+48) == size1 */
1110
    /* read32(p+52) == size2 */
1111
    /* read32(p+56) == color encoding */
1112
    /* read32(p+60) == identifier */
1113
1
  }
1114
  /* Windows v4 header */
1115
131
  if (size >= 108)
1116
79
  {
1117
79
    info->colorspacetype = read32(p + 56);
1118
1119
79
    info->endpoints[0] = read32(p + 60);
1120
79
    info->endpoints[1] = read32(p + 64);
1121
79
    info->endpoints[2] = read32(p + 68);
1122
1123
79
    info->endpoints[3] = read32(p + 72);
1124
79
    info->endpoints[4] = read32(p + 76);
1125
79
    info->endpoints[5] = read32(p + 80);
1126
1127
79
    info->endpoints[6] = read32(p + 84);
1128
79
    info->endpoints[7] = read32(p + 88);
1129
79
    info->endpoints[8] = read32(p + 92);
1130
1131
79
    info->gamma[0] = read32(p + 96);
1132
79
    info->gamma[1] = read32(p + 100);
1133
79
    info->gamma[2] = read32(p + 104);
1134
79
  }
1135
  /* Windows v5 header */
1136
131
  if (size >= 124)
1137
13
  {
1138
13
    info->intent = read32(p + 108);
1139
13
    info->profileoffset = read32(p + 112);
1140
13
    info->profilesize = read32(p + 116);
1141
    /* read32(p+120) == reserved */
1142
13
  }
1143
1144
131
  return p + size;
1145
131
}
1146
1147
1148
static fz_pixmap *
1149
bmp_read_image(fz_context *ctx, struct info *info, const unsigned char *begin, const unsigned char *end, const unsigned char *p, int only_metadata)
1150
133
{
1151
133
  const unsigned char *profilebegin;
1152
1153
133
  memset(info, 0x00, sizeof (*info));
1154
133
  info->colorspacetype = 0xffffffff;
1155
1156
133
  p = profilebegin = bmp_read_file_header(ctx, info, begin, end, p);
1157
1158
133
  p = bmp_read_info_header(ctx, info, begin, end, p);
1159
1160
  /* clamp bitmap offset to buffer size */
1161
133
  if (info->bitmapoffset < (uint32_t)(p - begin))
1162
31
    info->bitmapoffset = (uint32_t)(p - begin);
1163
133
  if ((uint32_t)(end - begin) < info->bitmapoffset)
1164
18
    info->bitmapoffset = end - begin;
1165
1166
133
  if (has_palette(info))
1167
36
    p = bmp_read_palette(ctx, info, begin, end, p);
1168
1169
133
  if (has_color_masks(info))
1170
4
    p = bmp_read_color_masks(ctx, info, begin, end, p);
1171
1172
133
  info->xres = DPM_TO_DPI(info->xres);
1173
133
  info->yres = DPM_TO_DPI(info->yres);
1174
1175
  /* extract topdown/bottomup from height for windows bitmaps */
1176
133
  if (is_win_bmp(info))
1177
128
  {
1178
128
    int bits = info->version == 12 ? 16 : 32;
1179
1180
128
    info->topdown = (info->height >> (bits - 1)) & 1;
1181
128
    if (info->topdown)
1182
28
    {
1183
28
      info->height--;
1184
28
      info->height = ~info->height;
1185
28
      info->height &= bits == 16 ? 0xffff : 0xffffffff;
1186
28
    }
1187
128
  }
1188
1189
  /* GIMP incorrectly writes BMP v5 headers that omit color masks
1190
  but include colorspace information. This means they look like
1191
  BMP v4 headers and that we interpret the colorspace information
1192
  partially as color mask data, partially as colorspace information.
1193
  Let's work around this... */
1194
133
  if (info->version == 108 &&
1195
133
      info->rmask == 0x73524742 && /* colorspacetype */
1196
133
      info->gmask == 0x00000000 && /* endpoints[0] */
1197
133
      info->bmask == 0x00000000 && /* endpoints[1] */
1198
133
      info->amask == 0x00000000 && /* endpoints[2] */
1199
133
      info->colorspacetype == 0x00000000 && /* endpoints[3] */
1200
133
      info->endpoints[0] == 0x00000000 && /* endpoints[4] */
1201
133
      info->endpoints[1] == 0x00000000 && /* endpoints[5] */
1202
133
      info->endpoints[2] == 0x00000000 && /* endpoints[6] */
1203
133
      info->endpoints[3] == 0x00000000 && /* endpoints[7] */
1204
133
      info->endpoints[4] == 0x00000000 && /* endpoints[8] */
1205
133
      info->endpoints[5] == 0x00000000 && /* gamma[0] */
1206
133
      info->endpoints[6] == 0x00000000 && /* gamma[1] */
1207
133
      info->endpoints[7] == 0x00000000 && /* gamma[2] */
1208
133
      info->endpoints[8] == 0x00000002) /* intent */
1209
0
  {
1210
0
    info->rmask = 0;
1211
    /* default masks */
1212
0
    if (info->bitcount == 16)
1213
0
    {
1214
0
      info->rmask = 0x00007c00;
1215
0
      info->gmask = 0x000003e0;
1216
0
      info->bmask = 0x0000001f;
1217
0
      info->amask = 0x00000000;
1218
0
    }
1219
0
    else if (info->bitcount >= 24)
1220
0
    {
1221
0
      info->rmask = 0x00ff0000;
1222
0
      info->gmask = 0x0000ff00;
1223
0
      info->bmask = 0x000000ff;
1224
0
      info->amask = 0x00000000;
1225
0
    }
1226
1227
0
    info->colorspacetype = 0x73524742;
1228
0
    info->intent = 0x00000002;
1229
0
  }
1230
1231
  /* get number of bits per component and component shift */
1232
133
  compute_mask_info(info->rmask, &info->rshift, &info->rbits);
1233
133
  compute_mask_info(info->gmask, &info->gshift, &info->gbits);
1234
133
  compute_mask_info(info->bmask, &info->bshift, &info->bbits);
1235
133
  compute_mask_info(info->amask, &info->ashift, &info->abits);
1236
1237
#ifdef BMP_DEBUG
1238
  {
1239
    #define chr(c) (((c) >= ' ' && (c) <= '~') ? (c) : '?')
1240
    fz_warn(ctx, "type = %02x%02x %c%c", info->type[0], info->type[1], chr(info->type[0]), chr(info->type[1]));
1241
    if (is_bitmap_array(info->type)) fz_warn(ctx, "\tbitmap array");
1242
    if (is_bitmap(info->type)) fz_warn(ctx, "\tbitmap");
1243
    fz_warn(ctx, "version = %zu", (size_t) info->version);
1244
    if (is_os2_bmp(info)) fz_warn(ctx, "OS/2 bmp");
1245
    if (is_win_bmp(info)) fz_warn(ctx, "Windows bmp");
1246
    fz_warn(ctx, "bitmapoffset = %zu", (size_t) info->bitmapoffset);
1247
    fz_warn(ctx, "width = %zu", (size_t) info->width);
1248
    fz_warn(ctx, "height = %zu", (size_t) info->height);
1249
    fz_warn(ctx, "bitcount = %zu", (size_t) info->bitcount);
1250
    fz_warn(ctx, "compression = %zu", (size_t) info->compression);
1251
    if (info->compression == BI_NONE) fz_warn(ctx, "\tNone");
1252
    if (info->compression == BI_RLE8) fz_warn(ctx, "\tRLE 8");
1253
    if (info->compression == BI_RLE4) fz_warn(ctx, "\tRLE 4");
1254
    if (is_valid_win_compression(info) && info->compression == BI_BITFIELDS) fz_warn(ctx, "\tBITFIELDS");
1255
    if (is_valid_os2_compression(info) && info->compression == BI_HUFFMAN1D) fz_warn(ctx, "\tHUFFMAN1D");
1256
    if (info->compression == BI_JPEG) fz_warn(ctx, "\tJPEG");
1257
    if (info->compression == BI_RLE24) fz_warn(ctx, "\tRLE24");
1258
    if (info->compression == BI_PNG) fz_warn(ctx, "\tPNG");
1259
    if (info->compression == BI_ALPHABITS) fz_warn(ctx, "\tALPHABITS");
1260
    fz_warn(ctx, "bitmapsize = %zu", (size_t) info->bitmapsize);
1261
    fz_warn(ctx, "xres = %zu", (size_t) info->xres);
1262
    fz_warn(ctx, "yres = %zu", (size_t) info->yres);
1263
    fz_warn(ctx, "colors = %zu", (size_t) info->colors);
1264
    fz_warn(ctx, "rmask = 0x%08zx rshift = %d rbits = %d", (size_t) info->rmask, info->rshift, info->rbits);
1265
    fz_warn(ctx, "gmask = 0x%08zx gshift = %d gbits = %d", (size_t) info->gmask, info->gshift, info->gbits);
1266
    fz_warn(ctx, "bmask = 0x%08zx bshift = %d bbits = %d", (size_t) info->bmask, info->bshift, info->bbits);
1267
    fz_warn(ctx, "amask = 0x%08zx ashift = %d abits = %d", (size_t) info->amask, info->ashift, info->abits);
1268
    fz_warn(ctx, "colorspacetype = %08zx %c%c%c%c", (size_t) info->colorspacetype,
1269
    chr((info->colorspacetype >> 24) & 0xff),
1270
    chr((info->colorspacetype >> 16) & 0xff),
1271
    chr((info->colorspacetype >>  8) & 0xff),
1272
    chr((info->colorspacetype >>  0) & 0xff));
1273
    fz_warn(ctx, "endpoints[%d] = 0x%08zx 0x%08zx 0x%08zx", 0, (size_t) info->endpoints[0], (size_t) info->endpoints[1], (size_t) info->endpoints[2]);
1274
    fz_warn(ctx, "endpoints[%d] = 0x%08zx 0x%08zx 0x%08zx", 3, (size_t) info->endpoints[3], (size_t) info->endpoints[4], (size_t) info->endpoints[5]);
1275
    fz_warn(ctx, "endpoints[%d] = 0x%08zx 0x%08zx 0x%08zx", 6, (size_t) info->endpoints[6], (size_t) info->endpoints[7], (size_t) info->endpoints[8]);
1276
    fz_warn(ctx, "gamma = 0x%08zx 0x%08zx 0x%08zx", (size_t) info->gamma[0], (size_t) info->gamma[1], (size_t) info->gamma[2]);
1277
    fz_warn(ctx, "profileoffset = %zu", (size_t) info->profileoffset);
1278
    fz_warn(ctx, "profilesize = %zu", (size_t) info->profilesize);
1279
    #undef chr
1280
  }
1281
#endif
1282
1283
133
  if (info->width == 0 || info->width > SHRT_MAX || info->height == 0 || info->height > SHRT_MAX)
1284
9
    fz_throw(ctx, FZ_ERROR_LIMIT, "image dimensions (%u x %u) out of range in bmp image", info->width, info->height);
1285
124
  if (!is_valid_compression(info))
1286
4
    fz_throw(ctx, FZ_ERROR_FORMAT, "unsupported compression method (%u) in bmp image", info->compression);
1287
120
  if (!is_valid_bitcount(info))
1288
2
    fz_throw(ctx, FZ_ERROR_FORMAT, "invalid bits per pixel (%u) for compression (%u) in bmp image", info->bitcount, info->compression);
1289
118
  if (info->rbits > info->bitcount)
1290
0
    fz_throw(ctx, FZ_ERROR_FORMAT, "unsupported %u bit red mask in bmp image", info->rbits);
1291
118
  if (info->gbits > info->bitcount)
1292
0
    fz_throw(ctx, FZ_ERROR_FORMAT, "unsupported %u bit green mask in bmp image", info->gbits);
1293
118
  if (info->bbits > info->bitcount)
1294
0
    fz_throw(ctx, FZ_ERROR_FORMAT, "unsupported %u bit blue mask in bmp image", info->bbits);
1295
118
  if (info->abits > info->bitcount)
1296
1
    fz_throw(ctx, FZ_ERROR_FORMAT, "unsupported %u bit alpha mask in bmp image", info->abits);
1297
1298
  /* Read color profile or default to RGB */
1299
117
  if (has_color_profile(info))
1300
76
    info->cs = bmp_read_color_profile(ctx, info, profilebegin, end);
1301
117
  if (!info->cs)
1302
60
    info->cs = fz_keep_colorspace(ctx, fz_device_rgb(ctx));
1303
1304
117
  if (only_metadata)
1305
0
    return NULL;
1306
1307
  /* bitmap cannot begin before headers have ended */
1308
117
  if ((uint32_t)(p - begin) < info->bitmapoffset)
1309
9
    p = begin + info->bitmapoffset;
1310
1311
117
  if (is_win_bmp(info) && info->compression == BI_JPEG)
1312
0
  {
1313
0
    if ((uint32_t)(end - p) < info->bitmapsize)
1314
0
      fz_warn(ctx, "premature end in jpeg image embedded in bmp image");
1315
0
    return fz_load_jpeg(ctx, p, end - p);
1316
0
  }
1317
117
  else if (is_win_bmp(info) && info->compression == BI_PNG)
1318
0
  {
1319
0
    if ((uint32_t)(end - p) < info->bitmapsize)
1320
0
      fz_warn(ctx, "premature end in png image embedded in bmp image");
1321
0
    return fz_load_png(ctx, p, end - p);
1322
0
  }
1323
117
  else
1324
117
    return bmp_read_bitmap(ctx, info, begin, end, p);
1325
117
}
1326
1327
fz_pixmap *
1328
fz_load_bmp_subimage(fz_context *ctx, const unsigned char *buf, size_t len, int subimage)
1329
133
{
1330
133
  const unsigned char *begin = buf;
1331
133
  const unsigned char *end = buf + len;
1332
133
  const unsigned char *p = begin;
1333
133
  struct info info = { 0 };
1334
133
  int nextoffset = 0;
1335
133
  fz_pixmap *image = NULL;
1336
133
  int origidx = subimage;
1337
1338
133
  (void) p;
1339
1340
133
  do
1341
133
  {
1342
133
    p = begin + nextoffset;
1343
1344
133
    if (end - p < 14)
1345
0
      fz_throw(ctx, FZ_ERROR_FORMAT, "not enough data for bitmap array (%02x%02x) in bmp image", p[0], p[1]);
1346
1347
133
    if (is_bitmap_array(p))
1348
0
    {
1349
      /* read16(p+0) == type */
1350
      /* read32(p+2) == size of this header in bytes */
1351
0
      nextoffset = read32(p + 6);
1352
      /* read16(p+10) == suitable pelx dimensions */
1353
      /* read16(p+12) == suitable pely dimensions */
1354
0
      p += 14;
1355
0
      (void) p;
1356
0
    }
1357
133
    else if (is_bitmap(p))
1358
133
    {
1359
133
      nextoffset = 0;
1360
133
    }
1361
0
    else
1362
0
    {
1363
0
      fz_warn(ctx, "treating invalid subimage as end of file");
1364
0
      nextoffset = 0;
1365
0
    }
1366
1367
133
    if (end - begin < nextoffset)
1368
0
    {
1369
0
      fz_warn(ctx, "treating invalid next subimage offset as end of file");
1370
0
      nextoffset = 0;
1371
0
    }
1372
133
    else
1373
133
      subimage--;
1374
1375
133
  } while (subimage >= 0 && nextoffset > 0);
1376
1377
133
  if (subimage != -1)
1378
0
    fz_throw(ctx, FZ_ERROR_ARGUMENT, "subimage index (%d) out of range in bmp image", origidx);
1379
1380
266
  fz_try(ctx)
1381
266
    image = bmp_read_image(ctx, &info, begin, end, p, 0);
1382
266
  fz_always(ctx)
1383
133
    fz_drop_colorspace(ctx, info.cs);
1384
133
  fz_catch(ctx)
1385
30
    fz_rethrow(ctx);
1386
1387
103
  return image;
1388
133
}
1389
1390
void
1391
fz_load_bmp_info_subimage(fz_context *ctx, const unsigned char *buf, size_t len, int *wp, int *hp, int *xresp, int *yresp, fz_colorspace **cspacep, int subimage)
1392
0
{
1393
0
  const unsigned char *begin = buf;
1394
0
  const unsigned char *end = buf + len;
1395
0
  const unsigned char *p = begin;
1396
0
  struct info info = { 0 };
1397
0
  int nextoffset = 0;
1398
0
  int origidx = subimage;
1399
1400
0
  (void) p;
1401
1402
0
  do
1403
0
  {
1404
0
    p = begin + nextoffset;
1405
1406
0
    if (end - p < 14)
1407
0
      fz_throw(ctx, FZ_ERROR_FORMAT, "not enough data for bitmap array (%02x%02x) in bmp image", p[0], p[1]);
1408
1409
0
    if (is_bitmap_array(p))
1410
0
    {
1411
      /* read16(p+0) == type */
1412
      /* read32(p+2) == size of this header in bytes */
1413
0
      nextoffset = read32(p + 6);
1414
      /* read16(p+10) == suitable pelx dimensions */
1415
      /* read16(p+12) == suitable pely dimensions */
1416
0
      p += 14;
1417
0
      (void) p;
1418
0
    }
1419
0
    else if (is_bitmap(p))
1420
0
    {
1421
0
      nextoffset = 0;
1422
0
    }
1423
0
    else
1424
0
    {
1425
0
      fz_warn(ctx, "treating invalid subimage as end of file");
1426
0
      nextoffset = 0;
1427
0
    }
1428
1429
0
    if (end - begin < nextoffset)
1430
0
    {
1431
0
      fz_warn(ctx, "treating invalid next subimage offset as end of file");
1432
0
      nextoffset = 0;
1433
0
    }
1434
0
    else
1435
0
      subimage--;
1436
1437
0
  } while (subimage >= 0 && nextoffset > 0);
1438
1439
0
  if (subimage != -1)
1440
0
    fz_throw(ctx, FZ_ERROR_ARGUMENT, "subimage index (%d) out of range in bmp image", origidx);
1441
1442
0
  fz_try(ctx)
1443
0
  {
1444
0
    (void) bmp_read_image(ctx, &info, begin, end, p, 1);
1445
0
    *cspacep = fz_keep_colorspace(ctx, info.cs);
1446
0
    *wp = info.width;
1447
0
    *hp = info.height;
1448
0
    *xresp = info.xres;
1449
0
    *yresp = info.yres;
1450
0
  }
1451
0
  fz_always(ctx)
1452
0
    fz_drop_colorspace(ctx, info.cs);
1453
0
  fz_catch(ctx)
1454
0
    fz_rethrow(ctx);
1455
0
}
1456
1457
int
1458
fz_load_bmp_subimage_count(fz_context *ctx, const unsigned char *buf, size_t len)
1459
133
{
1460
133
  const unsigned char *begin = buf;
1461
133
  const unsigned char *end = buf + len;
1462
133
  uint32_t nextoffset = 0;
1463
133
  int count = 0;
1464
1465
133
  do
1466
133
  {
1467
133
    const unsigned char *p = begin + nextoffset;
1468
1469
133
    if (end - p < 14)
1470
0
      fz_throw(ctx, FZ_ERROR_FORMAT, "not enough data for bitmap array in bmp image");
1471
1472
133
    if (is_bitmap_array(p))
1473
0
    {
1474
      /* read16(p+0) == type */
1475
      /* read32(p+2) == size of this header in bytes */
1476
0
      nextoffset = read32(p + 6);
1477
      /* read16(p+10) == suitable pelx dimensions */
1478
      /* read16(p+12) == suitable pely dimensions */
1479
0
      p += 14;
1480
0
    }
1481
133
    else if (is_bitmap(p))
1482
133
    {
1483
133
      nextoffset = 0;
1484
133
    }
1485
0
    else
1486
0
    {
1487
0
      fz_warn(ctx, "treating invalid subimage as end of file");
1488
0
      nextoffset = 0;
1489
0
    }
1490
1491
133
    if (end - begin < nextoffset)
1492
0
    {
1493
0
      fz_warn(ctx, "treating invalid next subimage offset as end of file");
1494
0
      nextoffset = 0;
1495
0
    }
1496
133
    else
1497
133
      count++;
1498
1499
133
  } while (nextoffset > 0);
1500
1501
133
  return count;
1502
133
}
1503
1504
fz_pixmap *
1505
fz_load_bmp(fz_context *ctx, const unsigned char *p, size_t total)
1506
0
{
1507
0
  return fz_load_bmp_subimage(ctx, p, total, 0);
1508
0
}
1509
1510
void
1511
fz_load_bmp_info(fz_context *ctx, const unsigned char *p, size_t total, int *wp, int *hp, int *xresp, int *yresp, fz_colorspace **cspacep)
1512
0
{
1513
0
  fz_load_bmp_info_subimage(ctx, p, total, wp, hp, xresp, yresp, cspacep, 0);
1514
0
}