comparison mupdf-source/source/fitz/load-bmp.c @ 2:b50eed0cc0ef upstream

ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4. The directory name has changed: no version number in the expanded directory now.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:43:07 +0200
parents
children
comparison
equal deleted inserted replaced
1:1d09e1dec1d9 2:b50eed0cc0ef
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 #define read8(p) ((p)[0])
136 #define read16(p) (((p)[1] << 8) | (p)[0])
137 #define read32(p) (((p)[3] << 24) | ((p)[2] << 16) | ((p)[1] << 8) | (p)[0])
138
139 #define DPM_TO_DPI(dpm) ((dpm) * 25.4f / 1000.0f)
140
141 #define is_bitmap_array(p) ((p)[0] == 'B' && (p)[1] == 'A')
142 #define is_bitmap(p) ((p)[0] == 'B' && (p)[1] == 'M')
143
144 #define is_os2_bmp(info) ((info)->version == 12 || (info)->version == 16 || (info)->version == 64)
145 #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 #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 #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 #define is_valid_compression(info) (is_valid_win_compression(info) || is_valid_os2_compression(info))
150
151 #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 #define is_valid_rle8_bitcount(info) ((info)->compression == BI_RLE8 && (info)->bitcount == 8)
153 #define is_valid_rle4_bitcount(info) ((info)->compression == BI_RLE4 && (info)->bitcount == 4)
154 #define is_valid_bitfields_bitcount(info) (is_win_bmp(info) && (info)->compression == BI_BITFIELDS && ((info)->bitcount == 16 || (info)->bitcount == 32))
155 #define is_valid_jpeg_bitcount(info) (is_win_bmp(info) && (info)->compression == BI_JPEG && (info)->bitcount == 0)
156 #define is_valid_png_bitcount(info) (is_win_bmp(info) && (info)->compression == BI_PNG && (info)->bitcount == 0)
157 #define is_valid_alphabits_bitcount(info) (is_win_bmp(info) && (info)->compression == BI_ALPHABITS && ((info)->bitcount == 16 || (info)->bitcount == 32))
158 #define is_valid_rle24_bitcount(info) (is_os2_bmp(info) && (info)->compression == BI_RLE24 && (info)->bitcount == 24)
159 #define is_valid_huffman1d_bitcount(info) (is_os2_bmp(info) && (info)->compression == BI_HUFFMAN1D && (info)->bitcount == 1)
160 #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 #define has_palette(info) ((info)->bitcount == 1 || (info)->bitcount == 2 || (info)->bitcount == 4 || (info)->bitcount == 8)
163 #define has_color_masks(info) (((info)->bitcount == 16 || (info)->bitcount == 32) && (info)->version == 40 && ((info)->compression == BI_BITFIELDS || (info)->compression == BI_ALPHABITS))
164 #define has_color_profile(info) ((info)->version == 108 || (info)->version == 124)
165
166 #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 {
171 if (end - p < 14)
172 fz_throw(ctx, FZ_ERROR_FORMAT, "premature end in file header in bmp image");
173
174 if (!is_bitmap(p))
175 fz_throw(ctx, FZ_ERROR_FORMAT, "invalid signature %02x%02x in bmp image", p[0], p[1]);
176
177 info->type[0] = read8(p + 0);
178 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 info->bitmapoffset = read32(p + 10);
183
184 return p + 14;
185 }
186
187 static unsigned char *
188 bmp_decompress_huffman1d(fz_context *ctx, struct info *info, const unsigned char *p, const unsigned char **end)
189 {
190 fz_stream *encstm, *decstm;
191 fz_buffer *buf;
192 unsigned char *decoded;
193 size_t size;
194
195 encstm = fz_open_memory(ctx, p, *end - p);
196
197 fz_var(decstm);
198 fz_var(buf);
199
200 fz_try(ctx)
201 {
202 decstm = fz_open_faxd(ctx, encstm,
203 0, /* 1 dimensional encoding */
204 0, /* end of line not required */
205 0, /* encoded byte align */
206 info->width, info->height,
207 0, /* end of block expected */
208 1 /* black is 1 */
209 );
210 buf = fz_read_all(ctx, decstm, 1024);
211 size = fz_buffer_extract(ctx, buf, &decoded);
212 *end = decoded + size;
213 }
214 fz_always(ctx)
215 {
216 fz_drop_buffer(ctx, buf);
217 fz_drop_stream(ctx, decstm);
218 fz_drop_stream(ctx, encstm);
219 }
220 fz_catch(ctx)
221 fz_rethrow(ctx);
222
223 return decoded;
224 }
225
226 static unsigned char *
227 bmp_decompress_rle24(fz_context *ctx, struct info *info, const unsigned char *p, const unsigned char **end)
228 {
229 const unsigned char *sp;
230 unsigned char *dp, *ep, *decompressed;
231 uint32_t width = info->width;
232 uint32_t height = info->height;
233 uint32_t stride;
234 uint32_t x, y;
235 int i;
236
237 stride = (width*3 + 3) / 4 * 4;
238
239 sp = p;
240 dp = decompressed = fz_calloc(ctx, height, stride);
241 ep = dp + height * stride;
242 x = 0;
243 y = 0;
244
245 while (sp + 2 <= *end)
246 {
247 if (sp[0] == 0 && sp[1] == 0)
248 { /* end of line */
249 sp += 2;
250 x = 0;
251 y++;
252 }
253 else if (sp[0] == 0 && sp[1] == 1)
254 { /* end of bitmap */
255 sp += 2;
256 break;
257 }
258 else if (sp[0] == 0 && sp[1] == 2)
259 { /* delta */
260 sp += 2;
261 x += sp < *end ? *sp++ : 0;
262 y += sp < *end ? *sp++ : 0;
263 }
264 else if (sp[0] == 0 && sp[1] >= 3)
265 { /* absolute */
266 int dn, sn, pad;
267 dn = sp[1];
268 sn = (dn * 3 + 1) / 2 * 2;
269 pad = sn & 1;
270 sp += 2;
271 if (sn > *end - sp)
272 {
273 fz_warn(ctx, "premature end of pixel data in absolute code in bmp image");
274 sn = ((*end - sp) / 3) * 3;
275 pad = (*end - sp) % 3;
276 dn = sn / 3;
277 }
278 else if (sn + pad > *end - sp)
279 {
280 fz_warn(ctx, "premature end of padding in absolute code in bmp image");
281 pad = 0;
282 }
283 for (i = 0; i < dn; i++)
284 {
285 uint32_t actualx = x;
286 uint32_t actualy = y;
287 if (actualx >= width || actualy >= height)
288 {
289 actualx = x % width;
290 actualy = y + x / width;
291 }
292 if (actualx < width && actualy < height)
293 {
294 dp = decompressed + actualy * stride + actualx * 3;
295 *dp++ = sp[i * 3 + 0];
296 *dp++ = sp[i * 3 + 1];
297 *dp++ = sp[i * 3 + 2];
298 }
299 x++;
300 }
301 sp += sn + pad;
302 }
303 else
304 { /* encoded */
305 int dn, sn;
306 dn = sp[0];
307 sn = 3;
308 sp++;
309 if (sn > *end - sp)
310 {
311 fz_warn(ctx, "premature end of pixel data in encoded code in bmp image");
312 sn = 0;
313 dn = 0;
314 }
315 for (i = 0; i < dn; i++)
316 {
317 uint32_t actualx = x;
318 uint32_t actualy = y;
319 if (actualx >= width || actualy >= height)
320 {
321 actualx = x % width;
322 actualy = y + x / width;
323 }
324 if (actualx < width && actualy < height)
325 {
326 dp = decompressed + actualy * stride + actualx * 3;
327 *dp++ = sp[0];
328 *dp++ = sp[1];
329 *dp++ = sp[2];
330 }
331 x++;
332 }
333 sp += sn;
334 }
335 }
336
337 info->compression = BI_NONE;
338 info->bitcount = 24;
339 *end = ep;
340 return decompressed;
341 }
342
343 static unsigned char *
344 bmp_decompress_rle8(fz_context *ctx, struct info *info, const unsigned char *p, const unsigned char **end)
345 {
346 const unsigned char *sp;
347 unsigned char *dp, *ep, *decompressed;
348 uint32_t width = info->width;
349 uint32_t height = info->height;
350 uint32_t stride;
351 uint32_t x, y;
352 int i;
353
354 stride = (width + 3) / 4 * 4;
355
356 sp = p;
357 dp = decompressed = fz_calloc(ctx, height, stride);
358 ep = dp + height * stride;
359 x = 0;
360 y = 0;
361
362 while (sp + 2 <= *end)
363 {
364 if (sp[0] == 0 && sp[1] == 0)
365 { /* end of line */
366 sp += 2;
367 x = 0;
368 y++;
369 }
370 else if (sp[0] == 0 && sp[1] == 1)
371 { /* end of bitmap */
372 sp += 2;
373 break;
374 }
375 else if (sp[0] == 0 && sp[1] == 2)
376 { /* delta */
377 sp +=2;
378 x += sp < *end ? *sp++ : 0;
379 y += sp < *end ? *sp++ : 0;
380 }
381 else if (sp[0] == 0 && sp[1] >= 3)
382 { /* absolute */
383 int dn, sn, pad;
384 dn = sp[1];
385 sn = dn;
386 pad = sn & 1;
387 sp += 2;
388 if (sn > *end - sp)
389 {
390 fz_warn(ctx, "premature end of pixel data in absolute code in bmp image");
391 sn = *end - sp;
392 pad = 0;
393 dn = sn;
394 }
395 else if (sn + pad > *end - sp)
396 {
397 fz_warn(ctx, "premature end of padding in absolute code in bmp image");
398 pad = 0;
399 }
400 for (i = 0; i < dn; i++)
401 {
402 uint32_t actualx = x;
403 uint32_t actualy = y;
404 if (actualx >= width || actualy >= height)
405 {
406 actualx = x % width;
407 actualy = y + x / width;
408 }
409 if (actualx < width && actualy < height)
410 {
411 dp = decompressed + actualy * stride + actualx;
412 *dp++ = sp[i];
413 }
414 x++;
415 }
416 sp += sn + pad;
417 }
418 else
419 { /* encoded */
420 int dn, sn;
421 dn = sp[0];
422 sn = 1;
423 sp++;
424 for (i = 0; i < dn; i++)
425 {
426 uint32_t actualx = x;
427 uint32_t actualy = y;
428 if (actualx >= width || actualy >= height)
429 {
430 actualx = x % width;
431 actualy = y + x / width;
432 }
433 if (actualx < width && actualy < height)
434 {
435 dp = decompressed + actualy * stride + actualx;
436 *dp++ = sp[0];
437 }
438 x++;
439 }
440 sp += sn;
441 }
442 }
443
444 info->compression = BI_NONE;
445 info->bitcount = 8;
446 *end = ep;
447 return decompressed;
448 }
449
450 static unsigned char *
451 bmp_decompress_rle4(fz_context *ctx, struct info *info, const unsigned char *p, const unsigned char **end)
452 {
453 const unsigned char *sp;
454 unsigned char *dp, *ep, *decompressed;
455 uint32_t width = info->width;
456 uint32_t height = info->height;
457 uint32_t stride;
458 uint32_t x, y;
459 int i;
460
461 stride = ((width + 1) / 2 + 3) / 4 * 4;
462
463 sp = p;
464 dp = decompressed = fz_calloc(ctx, height, stride);
465 ep = dp + height * stride;
466 x = 0;
467 y = 0;
468
469 while (sp + 2 <= *end)
470 {
471 if (sp[0] == 0 && sp[1] == 0)
472 { /* end of line */
473 sp += 2;
474 x = 0;
475 y++;
476 }
477 else if (sp[0] == 0 && sp[1] == 1)
478 { /* end of bitmap */
479 sp += 2;
480 break;
481 }
482 else if (sp[0] == 0 && sp[1] == 2)
483 { /* delta */
484 sp += 2;
485 x += sp < *end ? *sp++ : 0;
486 y += sp < *end ? *sp++ : 0;
487 }
488 else if (sp[0] == 0 && sp[1] >= 3)
489 { /* absolute */
490 int dn, sn, pad;
491 dn = sp[1];
492 sn = (dn + 1) / 2;
493 pad = sn & 1;
494 sp += 2;
495 if (sn > *end - sp)
496 {
497 fz_warn(ctx, "premature end of pixel data in absolute code in bmp image");
498 sn = *end - sp;
499 pad = 0;
500 dn = sn * 2;
501 }
502 else if (sn + pad > *end - sp)
503 {
504 fz_warn(ctx, "premature end of padding in absolute code in bmp image");
505 pad = 0;
506 }
507 for (i = 0; i < dn; i++)
508 {
509 uint32_t actualx = x;
510 uint32_t actualy = y;
511 if (actualx >= width || actualy >= height)
512 {
513 actualx = x % width;
514 actualy = y + x / width;
515 }
516 if (actualx < width && actualy < height)
517 {
518 int val = i & 1 ? (sp[i >> 1]) & 0xF : (sp[i >> 1] >> 4) & 0xF;
519 dp = decompressed + actualy * stride + actualx / 2;
520 if (x & 1)
521 *dp++ |= val;
522 else
523 *dp |= val << 4;
524 }
525 x++;
526 }
527 sp += sn + pad;
528 }
529 else
530 { /* encoded */
531 int dn, sn;
532 dn = sp[0];
533 sn = 1;
534 sp++;
535 for (i = 0; i < dn; i++)
536 {
537 uint32_t actualx = x;
538 uint32_t actualy = y;
539 if (actualx >= width || actualy >= height)
540 {
541 actualx = x % width;
542 actualy = y + x / width;
543 }
544 if (actualx < width && actualy < height)
545 {
546 int val = i & 1 ? (sp[0] & 0xf) : (sp[0] >> 4) & 0xf;
547 dp = decompressed + actualy * stride + actualx / 2;
548 if (x & 1)
549 *dp++ |= val;
550 else
551 *dp |= val << 4;
552 }
553 x++;
554 }
555 sp += sn;
556 }
557 }
558
559 info->compression = BI_NONE;
560 info->bitcount = 4;
561 *end = ep;
562 return decompressed;
563 }
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 {
568 const unsigned int mults[] = { 0, 8191, 2730, 1170, 546, 264, 130, 64 };
569 fz_pixmap *pix;
570 const unsigned char *ssp;
571 unsigned char *ddp;
572 unsigned char *decompressed = NULL;
573 uint32_t bitcount;
574 uint32_t width;
575 int32_t height;
576 uint32_t sstride;
577 int32_t dstride;
578 unsigned int rmult, gmult, bmult, amult;
579 unsigned int rtrunc, gtrunc, btrunc, atrunc;
580 uint32_t x;
581 int32_t y;
582
583 assert(info->width > 0 && info->width <= SHRT_MAX);
584 assert(info->height > 0 && info->height <= SHRT_MAX);
585
586 if (info->compression == BI_NONE)
587 ssp = p;
588 else if (info->compression == BI_RLE4)
589 ssp = decompressed = bmp_decompress_rle4(ctx, info, p, &end);
590 else if (info->compression == BI_RLE8)
591 ssp = decompressed = bmp_decompress_rle8(ctx, info, p, &end);
592 else if (is_win_bmp(info) && (info->compression == BI_BITFIELDS || info->compression == BI_ALPHABITS))
593 ssp = p;
594 else if (is_os2_bmp(info) && info->compression == BI_RLE24)
595 ssp = decompressed = bmp_decompress_rle24(ctx, info, p, &end);
596 else if (is_os2_bmp(info) && info->compression == BI_HUFFMAN1D)
597 ssp = decompressed = bmp_decompress_huffman1d(ctx, info, p, &end);
598 else
599 fz_throw(ctx, FZ_ERROR_FORMAT, "unhandled compression (%u) in bmp image", info->compression);
600
601 bitcount = info->bitcount;
602 width = info->width;
603 height = info->height;
604
605 sstride = ((width * bitcount + 31) / 32) * 4;
606 if (ssp + sstride * height > end)
607 {
608 int32_t h = (end - ssp) / sstride;
609 if (h == 0 || h > SHRT_MAX)
610 {
611 fz_free(ctx, decompressed);
612 fz_throw(ctx, FZ_ERROR_LIMIT, "image dimensions out of range in bmp image");
613 }
614 }
615
616 fz_try(ctx)
617 {
618 pix = fz_new_pixmap(ctx, info->cs, width, height, NULL, 1);
619 fz_set_pixmap_resolution(ctx, pix, info->xres, info->yres);
620 fz_clear_pixmap(ctx, pix);
621 }
622 fz_catch(ctx)
623 {
624 fz_free(ctx, decompressed);
625 fz_rethrow(ctx);
626 }
627
628 ddp = pix->samples;
629 dstride = pix->stride;
630 if (!info->topdown)
631 {
632 ddp = pix->samples + ((size_t) (height - 1)) * ((size_t) dstride);
633 dstride = -dstride;
634 }
635
636 if (ssp + sstride * height > end)
637 {
638 fz_warn(ctx, "premature end in bitmap data in bmp image");
639 height = (end - ssp) / sstride;
640 }
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 rmult = info->rbits < 8 ? mults[info->rbits] : 1;
652 gmult = info->gbits < 8 ? mults[info->gbits] : 1;
653 bmult = info->bbits < 8 ? mults[info->bbits] : 1;
654 amult = info->abits < 8 ? mults[info->abits] : 1;
655 rtrunc = info->rbits < 8 ? 5 : (info->rbits - 8);
656 gtrunc = info->gbits < 8 ? 5 : (info->gbits - 8);
657 btrunc = info->bbits < 8 ? 5 : (info->bbits - 8);
658 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 for (y = 0; y < height; y++)
667 {
668 const unsigned char *sp = ssp + ((size_t) y) * ((size_t) sstride);
669 unsigned char *dp = ddp + ((size_t) y) * ((size_t) dstride);
670
671 switch (bitcount)
672 {
673 case 64:
674 for (x = 0; x < width; x++)
675 {
676 uint32_t a = (((uint16_t)sp[7]) << 8) | (((uint16_t)sp[6]) << 0);
677 uint32_t r = (((uint16_t)sp[5]) << 8) | (((uint16_t)sp[4]) << 0);
678 uint32_t g = (((uint16_t)sp[3]) << 8) | (((uint16_t)sp[2]) << 0);
679 uint32_t b = (((uint16_t)sp[1]) << 8) | (((uint16_t)sp[0]) << 0);
680 r = (r * 255 + 4096) >> 13;
681 g = (g * 255 + 4096) >> 13;
682 b = (b * 255 + 4096) >> 13;
683 a = (a * 255 + 4096) >> 13;
684 *dp++ = r;
685 *dp++ = g;
686 *dp++ = b;
687 *dp++ = a;
688 sp += 8;
689 }
690 break;
691 case 32:
692 for (x = 0; x < width; x++)
693 {
694 uint32_t sample =
695 (((uint32_t) sp[3]) << 24) |
696 (((uint32_t) sp[2]) << 16) |
697 (((uint32_t) sp[1]) << 8) |
698 (((uint32_t) sp[0]) << 0);
699 uint32_t r = (sample & info->rmask) >> info->rshift;
700 uint32_t g = (sample & info->gmask) >> info->gshift;
701 uint32_t b = (sample & info->bmask) >> info->bshift;
702 uint32_t a = info->abits == 0 ? 255 : (sample & info->amask) >> info->ashift;
703 *dp++ = (r * rmult) >> rtrunc;
704 *dp++ = (g * gmult) >> gtrunc;
705 *dp++ = (b * bmult) >> btrunc;
706 *dp++ = info->abits == 0 ? a : (a * amult) >> atrunc;
707 sp += 4;
708 }
709 break;
710 case 24:
711 for (x = 0; x < width; x++)
712 {
713 *dp++ = sp[2];
714 *dp++ = sp[1];
715 *dp++ = sp[0];
716 *dp++ = 255;
717 sp += 3;
718 }
719 break;
720 case 16:
721 for (x = 0; x < width; x++)
722 {
723 uint16_t sample =
724 (((uint16_t)sp[1]) << 8) |
725 (((uint16_t)sp[0]) << 0);
726 uint16_t r = (sample & info->rmask) >> info->rshift;
727 uint16_t g = (sample & info->gmask) >> info->gshift;
728 uint16_t b = (sample & info->bmask) >> info->bshift;
729 uint16_t a = (sample & info->amask) >> info->ashift;
730 *dp++ = (r * rmult) >> rtrunc;
731 *dp++ = (g * gmult) >> gtrunc;
732 *dp++ = (b * bmult) >> btrunc;
733 *dp++ = info->abits == 0 ? 255 : (a * amult) >> atrunc;
734 sp += 2;
735 }
736 break;
737 case 8:
738 for (x = 0; x < width; x++)
739 {
740 *dp++ = info->palette[3 * sp[0] + 0];
741 *dp++ = info->palette[3 * sp[0] + 1];
742 *dp++ = info->palette[3 * sp[0] + 2];
743 *dp++ = 255;
744 sp++;
745 }
746 break;
747 case 4:
748 for (x = 0; x < width; x++)
749 {
750 int idx;
751 switch (x & 1)
752 {
753 case 0: idx = (sp[0] >> 4) & 0x0f; break;
754 case 1: idx = (sp[0] >> 0) & 0x0f; sp++; break;
755 }
756 *dp++ = info->palette[3 * idx + 0];
757 *dp++ = info->palette[3 * idx + 1];
758 *dp++ = info->palette[3 * idx + 2];
759 *dp++ = 255;
760 }
761 break;
762 case 2:
763 for (x = 0; x < width; x++)
764 {
765 int idx;
766 switch (x & 3)
767 {
768 case 0: idx = (sp[0] >> 6) & 0x03; break;
769 case 1: idx = (sp[0] >> 4) & 0x03; break;
770 case 2: idx = (sp[0] >> 2) & 0x03; break;
771 case 3: idx = (sp[0] >> 0) & 0x03; sp++; break;
772 }
773 *dp++ = info->palette[3 * idx + 0];
774 *dp++ = info->palette[3 * idx + 1];
775 *dp++ = info->palette[3 * idx + 2];
776 *dp++ = 255;
777 }
778 break;
779 case 1:
780 for (x = 0; x < width; x++)
781 {
782 int idx;
783 switch (x & 7)
784 {
785 case 0: idx = (sp[0] >> 7) & 0x01; break;
786 case 1: idx = (sp[0] >> 6) & 0x01; break;
787 case 2: idx = (sp[0] >> 5) & 0x01; break;
788 case 3: idx = (sp[0] >> 4) & 0x01; break;
789 case 4: idx = (sp[0] >> 3) & 0x01; break;
790 case 5: idx = (sp[0] >> 2) & 0x01; break;
791 case 6: idx = (sp[0] >> 1) & 0x01; break;
792 case 7: idx = (sp[0] >> 0) & 0x01; sp++; break;
793 }
794 *dp++ = info->palette[3 * idx + 0];
795 *dp++ = info->palette[3 * idx + 1];
796 *dp++ = info->palette[3 * idx + 2];
797 *dp++ = 255;
798 }
799 break;
800 }
801 }
802
803 fz_free(ctx, decompressed);
804 fz_premultiply_pixmap(ctx, pix);
805 return pix;
806 }
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 {
811 if (info->colorspacetype == 0)
812 {
813 float matrix[9] = { 1, 0, 0, 0, 1, 0, 0, 0, 1 };
814 float wp[3] = { 0.95047f, 1.0f, 1.08883f }; /* D65 white point */
815 float bp[3] = { 0, 0, 0 };
816 float gamma[3] = { 1, 1, 1 };
817 int i;
818
819 for (i = 0; i < 3; i++)
820 gamma[i] = (float) info->gamma[i] / (float) (1 << 16);
821 for (i = 0; i < 9; i++)
822 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 return fz_new_cal_rgb_colorspace(ctx, wp, bp, gamma, matrix);
834 }
835 else if (info->colorspacetype == 0x4c494e4b)
836 {
837 fz_warn(ctx, "ignoring linked color profile in bmp image");
838 return NULL;
839 }
840 else if (info->colorspacetype == 0x57696e20)
841 {
842 fz_warn(ctx, "ignoring windows color profile in bmp image");
843 return NULL;
844 }
845 else if (info->colorspacetype == 0x4d424544)
846 {
847 fz_buffer *profile;
848 fz_colorspace *cs;
849
850 if ((uint32_t)(end - begin) <= info->profileoffset)
851 {
852 fz_warn(ctx, "ignoring color profile located outside bmp image");
853 return NULL;
854 }
855 if ((uint32_t)(end - begin) - info->profileoffset < info->profilesize)
856 {
857 fz_warn(ctx, "ignoring truncated color profile in bmp image");
858 return NULL;
859 }
860 if (info->profilesize == 0)
861 {
862 fz_warn(ctx, "ignoring color profile without data in bmp image");
863 return NULL;
864 }
865
866 profile = fz_new_buffer_from_copied_data(ctx, begin + info->profileoffset, info->profilesize);
867
868 fz_try(ctx)
869 cs = fz_new_icc_colorspace(ctx, FZ_COLORSPACE_RGB, 0, "BMPRGB", profile);
870 fz_always(ctx)
871 fz_drop_buffer(ctx, profile);
872 fz_catch(ctx)
873 fz_rethrow(ctx);
874
875 return cs;
876 }
877 else if (info->colorspacetype == 0x73524742)
878 {
879 return fz_keep_colorspace(ctx, fz_device_rgb(ctx));
880 }
881
882 fz_warn(ctx, "ignoring color profile with unknown type in bmp image");
883 return NULL;
884 }
885
886 static void
887 compute_mask_info(unsigned int mask, unsigned int *shift, unsigned int *bits)
888 {
889 *bits = 0;
890 *shift = 0;
891
892 while (mask && (mask & 1) == 0) {
893 *shift += 1;
894 mask >>= 1;
895 }
896 while (mask && (mask & 1) == 1) {
897 *bits += 1;
898 mask >>= 1;
899 }
900 }
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 {
905 int size = 0;
906
907 if (info->compression == BI_BITFIELDS)
908 {
909 size = 12;
910 if (end - p < 12)
911 fz_throw(ctx, FZ_ERROR_FORMAT, "premature end in mask header in bmp image");
912
913 info->rmask = read32(p + 0);
914 info->gmask = read32(p + 4);
915 info->bmask = read32(p + 8);
916 }
917 else if (info->compression == BI_ALPHABITS)
918 {
919 size = 16;
920 if (end - p < 16)
921 fz_throw(ctx, FZ_ERROR_FORMAT, "premature end in mask header in bmp image");
922
923 info->rmask = read32(p + 0);
924 info->gmask = read32(p + 4);
925 info->bmask = read32(p + 8);
926 info->amask = read32(p + 12);
927 }
928
929 return p + size;
930 }
931
932 static int
933 bmp_palette_is_gray(fz_context *ctx, struct info *info, int readcolors)
934 {
935 int i;
936 for (i = 0; i < readcolors; i++)
937 {
938 int rgdiff = fz_absi(info->palette[3 * i + 0] - info->palette[3 * i + 1]);
939 int gbdiff = fz_absi(info->palette[3 * i + 1] - info->palette[3 * i + 2]);
940 int rbdiff = fz_absi(info->palette[3 * i + 0] - info->palette[3 * i + 2]);
941 if (rgdiff > 2 || gbdiff > 2 || rbdiff > 2)
942 return 0;
943 }
944 return 1;
945 }
946
947 static void
948 bmp_load_default_palette(fz_context *ctx, struct info *info, int readcolors)
949 {
950 int i;
951
952 fz_warn(ctx, "color table too short; loading default palette");
953
954 if (info->bitcount == 8)
955 {
956 if (!bmp_palette_is_gray(ctx, info, readcolors))
957 memcpy(&info->palette[readcolors * 3], &web_palette[readcolors * 3],
958 sizeof(web_palette) - readcolors * 3);
959 else
960 for (i = readcolors; i < 256; i++)
961 {
962 info->palette[3 * i + 0] = i;
963 info->palette[3 * i + 1] = i;
964 info->palette[3 * i + 2] = i;
965 }
966 }
967 else if (info->bitcount == 4)
968 {
969 if (!bmp_palette_is_gray(ctx, info, readcolors))
970 memcpy(&info->palette[readcolors * 3], &vga_palette[readcolors * 3],
971 sizeof(vga_palette) - readcolors * 3);
972 else
973 for (i = readcolors; i < 16; i++)
974 {
975 info->palette[3 * i + 0] = (i << 4) | i;
976 info->palette[3 * i + 1] = (i << 4) | i;
977 info->palette[3 * i + 2] = (i << 4) | i;
978 }
979 }
980 else if (info->bitcount == 2)
981 memcpy(info->palette, gray_palette, sizeof(gray_palette));
982 else if (info->bitcount == 1)
983 memcpy(info->palette, bw_palette, sizeof(bw_palette));
984 }
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 {
989 int i, expected, present, entry_size;
990
991 entry_size = palette_entry_size(info);
992
993 if (info->colors == 0)
994 expected = info->colors = 1 << info->bitcount;
995 else
996 expected = fz_mini(info->colors, 1 << info->bitcount);
997
998 if (info->bitmapoffset == 0)
999 present = fz_mini(expected, (end - p) / entry_size);
1000 else
1001 present = fz_mini(expected, (begin + info->bitmapoffset - p) / entry_size);
1002
1003 for (i = 0; i < present; i++)
1004 {
1005 /* ignore alpha channel even if present */
1006 info->palette[3 * i + 0] = read8(p + i * entry_size + 2);
1007 info->palette[3 * i + 1] = read8(p + i * entry_size + 1);
1008 info->palette[3 * i + 2] = read8(p + i * entry_size + 0);
1009 }
1010
1011 if (present < expected)
1012 bmp_load_default_palette(ctx, info, present);
1013
1014 return p + present * entry_size;
1015 }
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 {
1020 uint32_t size;
1021
1022 if (end - p < 4)
1023 fz_throw(ctx, FZ_ERROR_FORMAT, "premature end in info header in bmp image");
1024 size = info->version = read32(p + 0);
1025
1026 if (!is_win_bmp(info) && !is_os2_bmp(info))
1027 fz_throw(ctx, FZ_ERROR_FORMAT, "unknown header version (%u) in bmp image", info->version);
1028 if ((uint32_t)(end - p) < size)
1029 fz_throw(ctx, FZ_ERROR_FORMAT, "premature end in info header in bmp image");
1030
1031 /* default compression */
1032 info->compression = BI_NONE;
1033
1034 /* OS/2 1.x or Windows v2 */
1035 if (size == 12)
1036 {
1037 /* read32(p+0) == header size */
1038 info->width = read16(p + 4);
1039 info->height = read16(p + 6);
1040 /* read16(p+8) == planes */
1041 info->bitcount = read16(p + 10);
1042 }
1043 /* OS/2 2.x short header */
1044 if (size >= 16)
1045 {
1046 /* read32(p+0) == header size */
1047 info->width = read32(p + 4);
1048 info->height = read32(p + 8);
1049 /* read16(p+12) == planes */
1050 info->bitcount = read16(p + 14);
1051 }
1052
1053 /* default masks */
1054 if (info->bitcount == 16)
1055 {
1056 info->rmask = 0x00007c00;
1057 info->gmask = 0x000003e0;
1058 info->bmask = 0x0000001f;
1059 info->amask = 0x00000000;
1060 }
1061 else if (info->bitcount == 24 || info->bitcount == 32)
1062 {
1063 info->rmask = 0x00ff0000;
1064 info->gmask = 0x0000ff00;
1065 info->bmask = 0x000000ff;
1066 info->amask = 0x00000000;
1067 }
1068
1069 /* Windows v3 header */
1070 if (size >= 40)
1071 {
1072 info->compression = read32(p + 16);
1073 info->bitmapsize = read32(p + 20);
1074 info->xres = read32(p + 24);
1075 info->yres = read32(p + 28);
1076 info->colors = read32(p + 32);
1077 if (info->bitcount >= 32)
1078 {
1079 if (info->colors != 0)
1080 fz_warn(ctx, "Suspect BMP header; bitcount=%d, colors=%d", info->bitcount, info->colors);
1081 info->colors = 0;
1082 }
1083 else if (info->colors > (1U<<info->bitcount))
1084 {
1085 fz_warn(ctx, "Suspect BMP header; bitcount=%d, colors=%d", info->bitcount, info->colors);
1086 info->colors = 1<<info->bitcount;
1087 }
1088 /* read32(p+36) == important colors */
1089 }
1090 /* Windows v3 header with RGB masks */
1091 if (size == 52 || size == 56 || size == 108 || size == 124)
1092 {
1093 info->rmask = read32(p + 40);
1094 info->gmask = read32(p + 44);
1095 info->bmask = read32(p + 48);
1096 }
1097 /* Windows v3 header with RGBA masks */
1098 if (size == 56 || size == 108 || size == 124)
1099 {
1100 info->amask = read32(p + 52);
1101 }
1102 /* OS/2 2.x long header */
1103 if (size == 64)
1104 {
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 }
1114 /* Windows v4 header */
1115 if (size >= 108)
1116 {
1117 info->colorspacetype = read32(p + 56);
1118
1119 info->endpoints[0] = read32(p + 60);
1120 info->endpoints[1] = read32(p + 64);
1121 info->endpoints[2] = read32(p + 68);
1122
1123 info->endpoints[3] = read32(p + 72);
1124 info->endpoints[4] = read32(p + 76);
1125 info->endpoints[5] = read32(p + 80);
1126
1127 info->endpoints[6] = read32(p + 84);
1128 info->endpoints[7] = read32(p + 88);
1129 info->endpoints[8] = read32(p + 92);
1130
1131 info->gamma[0] = read32(p + 96);
1132 info->gamma[1] = read32(p + 100);
1133 info->gamma[2] = read32(p + 104);
1134 }
1135 /* Windows v5 header */
1136 if (size >= 124)
1137 {
1138 info->intent = read32(p + 108);
1139 info->profileoffset = read32(p + 112);
1140 info->profilesize = read32(p + 116);
1141 /* read32(p+120) == reserved */
1142 }
1143
1144 return p + size;
1145 }
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 {
1151 const unsigned char *profilebegin;
1152
1153 memset(info, 0x00, sizeof (*info));
1154 info->colorspacetype = 0xffffffff;
1155
1156 p = profilebegin = bmp_read_file_header(ctx, info, begin, end, p);
1157
1158 p = bmp_read_info_header(ctx, info, begin, end, p);
1159
1160 /* clamp bitmap offset to buffer size */
1161 if (info->bitmapoffset < (uint32_t)(p - begin))
1162 info->bitmapoffset = (uint32_t)(p - begin);
1163 if ((uint32_t)(end - begin) < info->bitmapoffset)
1164 info->bitmapoffset = end - begin;
1165
1166 if (has_palette(info))
1167 p = bmp_read_palette(ctx, info, begin, end, p);
1168
1169 if (has_color_masks(info))
1170 p = bmp_read_color_masks(ctx, info, begin, end, p);
1171
1172 info->xres = DPM_TO_DPI(info->xres);
1173 info->yres = DPM_TO_DPI(info->yres);
1174
1175 /* extract topdown/bottomup from height for windows bitmaps */
1176 if (is_win_bmp(info))
1177 {
1178 int bits = info->version == 12 ? 16 : 32;
1179
1180 info->topdown = (info->height >> (bits - 1)) & 1;
1181 if (info->topdown)
1182 {
1183 info->height--;
1184 info->height = ~info->height;
1185 info->height &= bits == 16 ? 0xffff : 0xffffffff;
1186 }
1187 }
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 if (info->version == 108 &&
1195 info->rmask == 0x73524742 && /* colorspacetype */
1196 info->gmask == 0x00000000 && /* endpoints[0] */
1197 info->bmask == 0x00000000 && /* endpoints[1] */
1198 info->amask == 0x00000000 && /* endpoints[2] */
1199 info->colorspacetype == 0x00000000 && /* endpoints[3] */
1200 info->endpoints[0] == 0x00000000 && /* endpoints[4] */
1201 info->endpoints[1] == 0x00000000 && /* endpoints[5] */
1202 info->endpoints[2] == 0x00000000 && /* endpoints[6] */
1203 info->endpoints[3] == 0x00000000 && /* endpoints[7] */
1204 info->endpoints[4] == 0x00000000 && /* endpoints[8] */
1205 info->endpoints[5] == 0x00000000 && /* gamma[0] */
1206 info->endpoints[6] == 0x00000000 && /* gamma[1] */
1207 info->endpoints[7] == 0x00000000 && /* gamma[2] */
1208 info->endpoints[8] == 0x00000002) /* intent */
1209 {
1210 info->rmask = 0;
1211 /* default masks */
1212 if (info->bitcount == 16)
1213 {
1214 info->rmask = 0x00007c00;
1215 info->gmask = 0x000003e0;
1216 info->bmask = 0x0000001f;
1217 info->amask = 0x00000000;
1218 }
1219 else if (info->bitcount >= 24)
1220 {
1221 info->rmask = 0x00ff0000;
1222 info->gmask = 0x0000ff00;
1223 info->bmask = 0x000000ff;
1224 info->amask = 0x00000000;
1225 }
1226
1227 info->colorspacetype = 0x73524742;
1228 info->intent = 0x00000002;
1229 }
1230
1231 /* get number of bits per component and component shift */
1232 compute_mask_info(info->rmask, &info->rshift, &info->rbits);
1233 compute_mask_info(info->gmask, &info->gshift, &info->gbits);
1234 compute_mask_info(info->bmask, &info->bshift, &info->bbits);
1235 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 if (info->width == 0 || info->width > SHRT_MAX || info->height == 0 || info->height > SHRT_MAX)
1284 fz_throw(ctx, FZ_ERROR_LIMIT, "image dimensions (%u x %u) out of range in bmp image", info->width, info->height);
1285 if (!is_valid_compression(info))
1286 fz_throw(ctx, FZ_ERROR_FORMAT, "unsupported compression method (%u) in bmp image", info->compression);
1287 if (!is_valid_bitcount(info))
1288 fz_throw(ctx, FZ_ERROR_FORMAT, "invalid bits per pixel (%u) for compression (%u) in bmp image", info->bitcount, info->compression);
1289 if (info->rbits > info->bitcount)
1290 fz_throw(ctx, FZ_ERROR_FORMAT, "unsupported %u bit red mask in bmp image", info->rbits);
1291 if (info->gbits > info->bitcount)
1292 fz_throw(ctx, FZ_ERROR_FORMAT, "unsupported %u bit green mask in bmp image", info->gbits);
1293 if (info->bbits > info->bitcount)
1294 fz_throw(ctx, FZ_ERROR_FORMAT, "unsupported %u bit blue mask in bmp image", info->bbits);
1295 if (info->abits > info->bitcount)
1296 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 if (has_color_profile(info))
1300 info->cs = bmp_read_color_profile(ctx, info, profilebegin, end);
1301 if (!info->cs)
1302 info->cs = fz_keep_colorspace(ctx, fz_device_rgb(ctx));
1303
1304 if (only_metadata)
1305 return NULL;
1306
1307 /* bitmap cannot begin before headers have ended */
1308 if ((uint32_t)(p - begin) < info->bitmapoffset)
1309 p = begin + info->bitmapoffset;
1310
1311 if (is_win_bmp(info) && info->compression == BI_JPEG)
1312 {
1313 if ((uint32_t)(end - p) < info->bitmapsize)
1314 fz_warn(ctx, "premature end in jpeg image embedded in bmp image");
1315 return fz_load_jpeg(ctx, p, end - p);
1316 }
1317 else if (is_win_bmp(info) && info->compression == BI_PNG)
1318 {
1319 if ((uint32_t)(end - p) < info->bitmapsize)
1320 fz_warn(ctx, "premature end in png image embedded in bmp image");
1321 return fz_load_png(ctx, p, end - p);
1322 }
1323 else
1324 return bmp_read_bitmap(ctx, info, begin, end, p);
1325 }
1326
1327 fz_pixmap *
1328 fz_load_bmp_subimage(fz_context *ctx, const unsigned char *buf, size_t len, int subimage)
1329 {
1330 const unsigned char *begin = buf;
1331 const unsigned char *end = buf + len;
1332 const unsigned char *p = begin;
1333 struct info info = { 0 };
1334 int nextoffset = 0;
1335 fz_pixmap *image = NULL;
1336 int origidx = subimage;
1337
1338 (void) p;
1339
1340 do
1341 {
1342 p = begin + nextoffset;
1343
1344 if (end - p < 14)
1345 fz_throw(ctx, FZ_ERROR_FORMAT, "not enough data for bitmap array (%02x%02x) in bmp image", p[0], p[1]);
1346
1347 if (is_bitmap_array(p))
1348 {
1349 /* read16(p+0) == type */
1350 /* read32(p+2) == size of this header in bytes */
1351 nextoffset = read32(p + 6);
1352 /* read16(p+10) == suitable pelx dimensions */
1353 /* read16(p+12) == suitable pely dimensions */
1354 p += 14;
1355 (void) p;
1356 }
1357 else if (is_bitmap(p))
1358 {
1359 nextoffset = 0;
1360 }
1361 else
1362 {
1363 fz_warn(ctx, "treating invalid subimage as end of file");
1364 nextoffset = 0;
1365 }
1366
1367 if (end - begin < nextoffset)
1368 {
1369 fz_warn(ctx, "treating invalid next subimage offset as end of file");
1370 nextoffset = 0;
1371 }
1372 else
1373 subimage--;
1374
1375 } while (subimage >= 0 && nextoffset > 0);
1376
1377 if (subimage != -1)
1378 fz_throw(ctx, FZ_ERROR_ARGUMENT, "subimage index (%d) out of range in bmp image", origidx);
1379
1380 fz_try(ctx)
1381 image = bmp_read_image(ctx, &info, begin, end, p, 0);
1382 fz_always(ctx)
1383 fz_drop_colorspace(ctx, info.cs);
1384 fz_catch(ctx)
1385 fz_rethrow(ctx);
1386
1387 return image;
1388 }
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 {
1393 const unsigned char *begin = buf;
1394 const unsigned char *end = buf + len;
1395 const unsigned char *p = begin;
1396 struct info info = { 0 };
1397 int nextoffset = 0;
1398 int origidx = subimage;
1399
1400 (void) p;
1401
1402 do
1403 {
1404 p = begin + nextoffset;
1405
1406 if (end - p < 14)
1407 fz_throw(ctx, FZ_ERROR_FORMAT, "not enough data for bitmap array (%02x%02x) in bmp image", p[0], p[1]);
1408
1409 if (is_bitmap_array(p))
1410 {
1411 /* read16(p+0) == type */
1412 /* read32(p+2) == size of this header in bytes */
1413 nextoffset = read32(p + 6);
1414 /* read16(p+10) == suitable pelx dimensions */
1415 /* read16(p+12) == suitable pely dimensions */
1416 p += 14;
1417 (void) p;
1418 }
1419 else if (is_bitmap(p))
1420 {
1421 nextoffset = 0;
1422 }
1423 else
1424 {
1425 fz_warn(ctx, "treating invalid subimage as end of file");
1426 nextoffset = 0;
1427 }
1428
1429 if (end - begin < nextoffset)
1430 {
1431 fz_warn(ctx, "treating invalid next subimage offset as end of file");
1432 nextoffset = 0;
1433 }
1434 else
1435 subimage--;
1436
1437 } while (subimage >= 0 && nextoffset > 0);
1438
1439 if (subimage != -1)
1440 fz_throw(ctx, FZ_ERROR_ARGUMENT, "subimage index (%d) out of range in bmp image", origidx);
1441
1442 fz_try(ctx)
1443 {
1444 (void) bmp_read_image(ctx, &info, begin, end, p, 1);
1445 *cspacep = fz_keep_colorspace(ctx, info.cs);
1446 *wp = info.width;
1447 *hp = info.height;
1448 *xresp = info.xres;
1449 *yresp = info.yres;
1450 }
1451 fz_always(ctx)
1452 fz_drop_colorspace(ctx, info.cs);
1453 fz_catch(ctx)
1454 fz_rethrow(ctx);
1455 }
1456
1457 int
1458 fz_load_bmp_subimage_count(fz_context *ctx, const unsigned char *buf, size_t len)
1459 {
1460 const unsigned char *begin = buf;
1461 const unsigned char *end = buf + len;
1462 uint32_t nextoffset = 0;
1463 int count = 0;
1464
1465 do
1466 {
1467 const unsigned char *p = begin + nextoffset;
1468
1469 if (end - p < 14)
1470 fz_throw(ctx, FZ_ERROR_FORMAT, "not enough data for bitmap array in bmp image");
1471
1472 if (is_bitmap_array(p))
1473 {
1474 /* read16(p+0) == type */
1475 /* read32(p+2) == size of this header in bytes */
1476 nextoffset = read32(p + 6);
1477 /* read16(p+10) == suitable pelx dimensions */
1478 /* read16(p+12) == suitable pely dimensions */
1479 p += 14;
1480 }
1481 else if (is_bitmap(p))
1482 {
1483 nextoffset = 0;
1484 }
1485 else
1486 {
1487 fz_warn(ctx, "treating invalid subimage as end of file");
1488 nextoffset = 0;
1489 }
1490
1491 if (end - begin < nextoffset)
1492 {
1493 fz_warn(ctx, "treating invalid next subimage offset as end of file");
1494 nextoffset = 0;
1495 }
1496 else
1497 count++;
1498
1499 } while (nextoffset > 0);
1500
1501 return count;
1502 }
1503
1504 fz_pixmap *
1505 fz_load_bmp(fz_context *ctx, const unsigned char *p, size_t total)
1506 {
1507 return fz_load_bmp_subimage(ctx, p, total, 0);
1508 }
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 {
1513 fz_load_bmp_info_subimage(ctx, p, total, wp, hp, xresp, yresp, cspacep, 0);
1514 }