/src/mupdf/source/fitz/load-bmp.c
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (C) 2004-2021 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 | 1.56k | #define read8(p) ((p)[0]) |
136 | 300 | #define read16(p) (((p)[1] << 8) | (p)[0]) |
137 | 5.10k | #define read32(p) (((p)[3] << 24) | ((p)[2] << 16) | ((p)[1] << 8) | (p)[0]) |
138 | | |
139 | 552 | #define DPM_TO_DPI(dpm) ((dpm) * 25.4f / 1000.0f) |
140 | | |
141 | 553 | #define is_bitmap_array(p) ((p)[0] == 'B' && (p)[1] == 'A') |
142 | 827 | #define is_bitmap(p) ((p)[0] == 'B' && (p)[1] == 'M') |
143 | | |
144 | 60 | #define is_os2_bmp(info) ((info)->version == 12 || (info)->version == 16 || (info)->version == 64) |
145 | 2.93k | #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 | 520 | #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 | 17 | #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 | 260 | #define is_valid_compression(info) (is_valid_win_compression(info) || is_valid_os2_compression(info)) |
150 | | |
151 | 488 | #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 | 464 | #define is_valid_rle8_bitcount(info) ((info)->compression == BI_RLE8 && (info)->bitcount == 8) |
153 | 431 | #define is_valid_rle4_bitcount(info) ((info)->compression == BI_RLE4 && (info)->bitcount == 4) |
154 | 398 | #define is_valid_bitfields_bitcount(info) (is_win_bmp(info) && (info)->compression == BI_BITFIELDS && ((info)->bitcount == 16 || (info)->bitcount == 32)) |
155 | 252 | #define is_valid_jpeg_bitcount(info) (is_win_bmp(info) && (info)->compression == BI_JPEG && (info)->bitcount == 0) |
156 | 252 | #define is_valid_png_bitcount(info) (is_win_bmp(info) && (info)->compression == BI_PNG && (info)->bitcount == 0) |
157 | 252 | #define is_valid_alphabits_bitcount(info) (is_win_bmp(info) && (info)->compression == BI_ALPHABITS && ((info)->bitcount == 16 || (info)->bitcount == 32)) |
158 | 248 | #define is_valid_rle24_bitcount(info) (is_os2_bmp(info) && (info)->compression == BI_RLE24 && (info)->bitcount == 24) |
159 | 4 | #define is_valid_huffman1d_bitcount(info) (is_os2_bmp(info) && (info)->compression == BI_HUFFMAN1D && (info)->bitcount == 1) |
160 | 244 | #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 | 276 | #define has_palette(info) ((info)->bitcount == 1 || (info)->bitcount == 2 || (info)->bitcount == 4 || (info)->bitcount == 8) |
163 | 276 | #define has_color_masks(info) (((info)->bitcount == 16 || (info)->bitcount == 32) && (info)->version == 40 && ((info)->compression == BI_BITFIELDS || (info)->compression == BI_ALPHABITS)) |
164 | 238 | #define has_color_profile(info) ((info)->version == 108 || (info)->version == 124) |
165 | | |
166 | 86 | #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 | 276 | { |
171 | 276 | if (end - p < 14) |
172 | 0 | fz_throw(ctx, FZ_ERROR_FORMAT, "premature end in file header in bmp image"); |
173 | | |
174 | 276 | if (!is_bitmap(p)) |
175 | 1 | fz_throw(ctx, FZ_ERROR_FORMAT, "invalid signature %02x%02x in bmp image", p[0], p[1]); |
176 | | |
177 | 275 | info->type[0] = read8(p + 0); |
178 | 275 | 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 | 275 | info->bitmapoffset = read32(p + 10); |
183 | | |
184 | 275 | return p + 14; |
185 | 276 | } |
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 | 33 | { |
346 | 33 | const unsigned char *sp; |
347 | 33 | unsigned char *dp, *ep, *decompressed; |
348 | 33 | uint32_t width = info->width; |
349 | 33 | uint32_t height = info->height; |
350 | 33 | uint32_t stride; |
351 | 33 | uint32_t x, y; |
352 | 33 | int i; |
353 | | |
354 | 33 | stride = (width + 3) / 4 * 4; |
355 | | |
356 | 33 | sp = p; |
357 | 33 | dp = decompressed = fz_calloc(ctx, height, stride); |
358 | 33 | ep = dp + height * stride; |
359 | 33 | x = 0; |
360 | 33 | y = 0; |
361 | | |
362 | 11.2k | while (sp + 2 <= *end) |
363 | 11.2k | { |
364 | 11.2k | if (sp[0] == 0 && sp[1] == 0) |
365 | 539 | { /* end of line */ |
366 | 539 | sp += 2; |
367 | 539 | x = 0; |
368 | 539 | y++; |
369 | 539 | } |
370 | 10.6k | else if (sp[0] == 0 && sp[1] == 1) |
371 | 2 | { /* end of bitmap */ |
372 | 2 | sp += 2; |
373 | 2 | break; |
374 | 2 | } |
375 | 10.6k | else if (sp[0] == 0 && sp[1] == 2) |
376 | 21 | { /* delta */ |
377 | 21 | sp +=2; |
378 | 21 | x += sp < *end ? *sp++ : 0; |
379 | 21 | y += sp < *end ? *sp++ : 0; |
380 | 21 | } |
381 | 10.6k | else if (sp[0] == 0 && sp[1] >= 3) |
382 | 139 | { /* absolute */ |
383 | 139 | int dn, sn, pad; |
384 | 139 | dn = sp[1]; |
385 | 139 | sn = dn; |
386 | 139 | pad = sn & 1; |
387 | 139 | sp += 2; |
388 | 139 | if (sn > *end - sp) |
389 | 20 | { |
390 | 20 | fz_warn(ctx, "premature end of pixel data in absolute code in bmp image"); |
391 | 20 | sn = *end - sp; |
392 | 20 | pad = 0; |
393 | 20 | dn = sn; |
394 | 20 | } |
395 | 119 | 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 | 14.8k | for (i = 0; i < dn; i++) |
401 | 14.7k | { |
402 | 14.7k | uint32_t actualx = x; |
403 | 14.7k | uint32_t actualy = y; |
404 | 14.7k | if (actualx >= width || actualy >= height) |
405 | 13.7k | { |
406 | 13.7k | actualx = x % width; |
407 | 13.7k | actualy = y + x / width; |
408 | 13.7k | } |
409 | 14.7k | if (actualx < width && actualy < height) |
410 | 1.45k | { |
411 | 1.45k | dp = decompressed + actualy * stride + actualx; |
412 | 1.45k | *dp++ = sp[i]; |
413 | 1.45k | } |
414 | 14.7k | x++; |
415 | 14.7k | } |
416 | 139 | sp += sn + pad; |
417 | 139 | } |
418 | 10.5k | else |
419 | 10.5k | { /* encoded */ |
420 | 10.5k | int dn, sn; |
421 | 10.5k | dn = sp[0]; |
422 | 10.5k | sn = 1; |
423 | 10.5k | sp++; |
424 | 1.15M | for (i = 0; i < dn; i++) |
425 | 1.14M | { |
426 | 1.14M | uint32_t actualx = x; |
427 | 1.14M | uint32_t actualy = y; |
428 | 1.14M | if (actualx >= width || actualy >= height) |
429 | 1.13M | { |
430 | 1.13M | actualx = x % width; |
431 | 1.13M | actualy = y + x / width; |
432 | 1.13M | } |
433 | 1.14M | if (actualx < width && actualy < height) |
434 | 79.5k | { |
435 | 79.5k | dp = decompressed + actualy * stride + actualx; |
436 | 79.5k | *dp++ = sp[0]; |
437 | 79.5k | } |
438 | 1.14M | x++; |
439 | 1.14M | } |
440 | 10.5k | sp += sn; |
441 | 10.5k | } |
442 | 11.2k | } |
443 | | |
444 | 33 | info->compression = BI_NONE; |
445 | 33 | info->bitcount = 8; |
446 | 33 | *end = ep; |
447 | 33 | return decompressed; |
448 | 33 | } |
449 | | |
450 | | static unsigned char * |
451 | | bmp_decompress_rle4(fz_context *ctx, struct info *info, const unsigned char *p, const unsigned char **end) |
452 | 33 | { |
453 | 33 | const unsigned char *sp; |
454 | 33 | unsigned char *dp, *ep, *decompressed; |
455 | 33 | uint32_t width = info->width; |
456 | 33 | uint32_t height = info->height; |
457 | 33 | uint32_t stride; |
458 | 33 | uint32_t x, y; |
459 | 33 | int i; |
460 | | |
461 | 33 | stride = ((width + 1) / 2 + 3) / 4 * 4; |
462 | | |
463 | 33 | sp = p; |
464 | 33 | dp = decompressed = fz_calloc(ctx, height, stride); |
465 | 33 | ep = dp + height * stride; |
466 | 33 | x = 0; |
467 | 33 | y = 0; |
468 | | |
469 | 1.28k | while (sp + 2 <= *end) |
470 | 1.25k | { |
471 | 1.25k | if (sp[0] == 0 && sp[1] == 0) |
472 | 189 | { /* end of line */ |
473 | 189 | sp += 2; |
474 | 189 | x = 0; |
475 | 189 | y++; |
476 | 189 | } |
477 | 1.06k | else if (sp[0] == 0 && sp[1] == 1) |
478 | 2 | { /* end of bitmap */ |
479 | 2 | sp += 2; |
480 | 2 | break; |
481 | 2 | } |
482 | 1.06k | 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 | 1.05k | else if (sp[0] == 0 && sp[1] >= 3) |
489 | 132 | { /* absolute */ |
490 | 132 | int dn, sn, pad; |
491 | 132 | dn = sp[1]; |
492 | 132 | sn = (dn + 1) / 2; |
493 | 132 | pad = sn & 1; |
494 | 132 | sp += 2; |
495 | 132 | if (sn > *end - sp) |
496 | 17 | { |
497 | 17 | fz_warn(ctx, "premature end of pixel data in absolute code in bmp image"); |
498 | 17 | sn = *end - sp; |
499 | 17 | pad = 0; |
500 | 17 | dn = sn * 2; |
501 | 17 | } |
502 | 115 | 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 | 2.94k | for (i = 0; i < dn; i++) |
508 | 2.81k | { |
509 | 2.81k | uint32_t actualx = x; |
510 | 2.81k | uint32_t actualy = y; |
511 | 2.81k | if (actualx >= width || actualy >= height) |
512 | 1.62k | { |
513 | 1.62k | actualx = x % width; |
514 | 1.62k | actualy = y + x / width; |
515 | 1.62k | } |
516 | 2.81k | if (actualx < width && actualy < height) |
517 | 1.30k | { |
518 | 1.30k | int val = i & 1 ? (sp[i >> 1]) & 0xF : (sp[i >> 1] >> 4) & 0xF; |
519 | 1.30k | dp = decompressed + actualy * stride + actualx / 2; |
520 | 1.30k | if (x & 1) |
521 | 649 | *dp++ |= val; |
522 | 651 | else |
523 | 651 | *dp |= val << 4; |
524 | 1.30k | } |
525 | 2.81k | x++; |
526 | 2.81k | } |
527 | 132 | sp += sn + pad; |
528 | 132 | } |
529 | 926 | else |
530 | 926 | { /* encoded */ |
531 | 926 | int dn, sn; |
532 | 926 | dn = sp[0]; |
533 | 926 | sn = 1; |
534 | 926 | sp++; |
535 | 85.9k | for (i = 0; i < dn; i++) |
536 | 85.0k | { |
537 | 85.0k | uint32_t actualx = x; |
538 | 85.0k | uint32_t actualy = y; |
539 | 85.0k | if (actualx >= width || actualy >= height) |
540 | 78.3k | { |
541 | 78.3k | actualx = x % width; |
542 | 78.3k | actualy = y + x / width; |
543 | 78.3k | } |
544 | 85.0k | if (actualx < width && actualy < height) |
545 | 8.71k | { |
546 | 8.71k | int val = i & 1 ? (sp[0] & 0xf) : (sp[0] >> 4) & 0xf; |
547 | 8.71k | dp = decompressed + actualy * stride + actualx / 2; |
548 | 8.71k | if (x & 1) |
549 | 4.35k | *dp++ |= val; |
550 | 4.36k | else |
551 | 4.36k | *dp |= val << 4; |
552 | 8.71k | } |
553 | 85.0k | x++; |
554 | 85.0k | } |
555 | 926 | sp += sn; |
556 | 926 | } |
557 | 1.25k | } |
558 | | |
559 | 33 | info->compression = BI_NONE; |
560 | 33 | info->bitcount = 4; |
561 | 33 | *end = ep; |
562 | 33 | return decompressed; |
563 | 33 | } |
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 | 225 | { |
568 | 225 | const unsigned int mults[] = { 0, 8191, 2730, 1170, 546, 264, 130, 64 }; |
569 | 225 | fz_pixmap *pix; |
570 | 225 | const unsigned char *ssp; |
571 | 225 | unsigned char *ddp; |
572 | 225 | unsigned char *decompressed = NULL; |
573 | 225 | uint32_t bitcount; |
574 | 225 | uint32_t width; |
575 | 225 | int32_t height; |
576 | 225 | uint32_t sstride; |
577 | 225 | int32_t dstride; |
578 | 225 | unsigned int rmult, gmult, bmult, amult; |
579 | 225 | unsigned int rtrunc, gtrunc, btrunc, atrunc; |
580 | 225 | uint32_t x; |
581 | 225 | int32_t y; |
582 | | |
583 | 225 | assert(info->width > 0 && info->width <= SHRT_MAX); |
584 | 225 | assert(info->height > 0 && info->height <= SHRT_MAX); |
585 | | |
586 | 225 | if (info->compression == BI_NONE) |
587 | 18 | ssp = p; |
588 | 207 | else if (info->compression == BI_RLE4) |
589 | 33 | ssp = decompressed = bmp_decompress_rle4(ctx, info, p, &end); |
590 | 174 | else if (info->compression == BI_RLE8) |
591 | 33 | ssp = decompressed = bmp_decompress_rle8(ctx, info, p, &end); |
592 | 141 | else if (is_win_bmp(info) && (info->compression == BI_BITFIELDS || info->compression == BI_ALPHABITS)) |
593 | 141 | 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 | 225 | bitcount = info->bitcount; |
602 | 225 | width = info->width; |
603 | 225 | height = info->height; |
604 | | |
605 | 225 | sstride = ((width * bitcount + 31) / 32) * 4; |
606 | 225 | if (ssp + sstride * height > end) |
607 | 151 | { |
608 | 151 | int32_t h = (end - ssp) / sstride; |
609 | 151 | if (h == 0 || h > SHRT_MAX) |
610 | 9 | { |
611 | 9 | fz_free(ctx, decompressed); |
612 | 9 | fz_throw(ctx, FZ_ERROR_LIMIT, "image dimensions out of range in bmp image"); |
613 | 9 | } |
614 | 151 | } |
615 | | |
616 | 432 | fz_try(ctx) |
617 | 432 | { |
618 | 216 | pix = fz_new_pixmap(ctx, info->cs, width, height, NULL, 1); |
619 | 216 | fz_set_pixmap_resolution(ctx, pix, info->xres, info->yres); |
620 | 216 | fz_clear_pixmap(ctx, pix); |
621 | 216 | } |
622 | 432 | fz_catch(ctx) |
623 | 0 | { |
624 | 0 | fz_free(ctx, decompressed); |
625 | 0 | fz_rethrow(ctx); |
626 | 0 | } |
627 | | |
628 | 216 | ddp = pix->samples; |
629 | 216 | dstride = pix->stride; |
630 | 216 | if (!info->topdown) |
631 | 160 | { |
632 | 160 | ddp = pix->samples + ((size_t) (height - 1)) * ((size_t) dstride); |
633 | 160 | dstride = -dstride; |
634 | 160 | } |
635 | | |
636 | 216 | if (ssp + sstride * height > end) |
637 | 142 | { |
638 | 142 | fz_warn(ctx, "premature end in bitmap data in bmp image"); |
639 | 142 | height = (end - ssp) / sstride; |
640 | 142 | } |
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 | 216 | rmult = info->rbits < 8 ? mults[info->rbits] : 1; |
652 | 216 | gmult = info->gbits < 8 ? mults[info->gbits] : 1; |
653 | 216 | bmult = info->bbits < 8 ? mults[info->bbits] : 1; |
654 | 216 | amult = info->abits < 8 ? mults[info->abits] : 1; |
655 | 216 | rtrunc = info->rbits < 8 ? 5 : (info->rbits - 8); |
656 | 216 | gtrunc = info->gbits < 8 ? 5 : (info->gbits - 8); |
657 | 216 | btrunc = info->bbits < 8 ? 5 : (info->bbits - 8); |
658 | 216 | 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 | 82.8k | for (y = 0; y < height; y++) |
667 | 82.6k | { |
668 | 82.6k | const unsigned char *sp = ssp + ((size_t) y) * ((size_t) sstride); |
669 | 82.6k | unsigned char *dp = ddp + ((size_t) y) * ((size_t) dstride); |
670 | | |
671 | 82.6k | switch (bitcount) |
672 | 82.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 | 6.51k | case 32: |
692 | 13.2k | for (x = 0; x < width; x++) |
693 | 6.72k | { |
694 | 6.72k | uint32_t sample = |
695 | 6.72k | (((uint32_t) sp[3]) << 24) | |
696 | 6.72k | (((uint32_t) sp[2]) << 16) | |
697 | 6.72k | (((uint32_t) sp[1]) << 8) | |
698 | 6.72k | (((uint32_t) sp[0]) << 0); |
699 | 6.72k | uint32_t r = (sample & info->rmask) >> info->rshift; |
700 | 6.72k | uint32_t g = (sample & info->gmask) >> info->gshift; |
701 | 6.72k | uint32_t b = (sample & info->bmask) >> info->bshift; |
702 | 6.72k | uint32_t a = info->abits == 0 ? 255 : (sample & info->amask) >> info->ashift; |
703 | 6.72k | *dp++ = (r * rmult) >> rtrunc; |
704 | 6.72k | *dp++ = (g * gmult) >> gtrunc; |
705 | 6.72k | *dp++ = (b * bmult) >> btrunc; |
706 | 6.72k | *dp++ = info->abits == 0 ? a : (a * amult) >> atrunc; |
707 | 6.72k | sp += 4; |
708 | 6.72k | } |
709 | 6.51k | break; |
710 | 575 | case 24: |
711 | 5.61k | for (x = 0; x < width; x++) |
712 | 5.03k | { |
713 | 5.03k | *dp++ = sp[2]; |
714 | 5.03k | *dp++ = sp[1]; |
715 | 5.03k | *dp++ = sp[0]; |
716 | 5.03k | *dp++ = 255; |
717 | 5.03k | sp += 3; |
718 | 5.03k | } |
719 | 575 | break; |
720 | 2.76k | case 16: |
721 | 8.23k | for (x = 0; x < width; x++) |
722 | 5.46k | { |
723 | 5.46k | uint16_t sample = |
724 | 5.46k | (((uint16_t)sp[1]) << 8) | |
725 | 5.46k | (((uint16_t)sp[0]) << 0); |
726 | 5.46k | uint16_t r = (sample & info->rmask) >> info->rshift; |
727 | 5.46k | uint16_t g = (sample & info->gmask) >> info->gshift; |
728 | 5.46k | uint16_t b = (sample & info->bmask) >> info->bshift; |
729 | 5.46k | uint16_t a = (sample & info->amask) >> info->ashift; |
730 | 5.46k | *dp++ = (r * rmult) >> rtrunc; |
731 | 5.46k | *dp++ = (g * gmult) >> gtrunc; |
732 | 5.46k | *dp++ = (b * bmult) >> btrunc; |
733 | 5.46k | *dp++ = info->abits == 0 ? 255 : (a * amult) >> atrunc; |
734 | 5.46k | sp += 2; |
735 | 5.46k | } |
736 | 2.76k | break; |
737 | 60.9k | case 8: |
738 | 103M | for (x = 0; x < width; x++) |
739 | 103M | { |
740 | 103M | *dp++ = info->palette[3 * sp[0] + 0]; |
741 | 103M | *dp++ = info->palette[3 * sp[0] + 1]; |
742 | 103M | *dp++ = info->palette[3 * sp[0] + 2]; |
743 | 103M | *dp++ = 255; |
744 | 103M | sp++; |
745 | 103M | } |
746 | 60.9k | break; |
747 | 11.3k | case 4: |
748 | 92.9M | for (x = 0; x < width; x++) |
749 | 92.9M | { |
750 | 92.9M | int idx; |
751 | 92.9M | switch (x & 1) |
752 | 92.9M | { |
753 | 46.4M | case 0: idx = (sp[0] >> 4) & 0x0f; break; |
754 | 46.4M | case 1: idx = (sp[0] >> 0) & 0x0f; sp++; break; |
755 | 92.9M | } |
756 | 92.9M | *dp++ = info->palette[3 * idx + 0]; |
757 | 92.9M | *dp++ = info->palette[3 * idx + 1]; |
758 | 92.9M | *dp++ = info->palette[3 * idx + 2]; |
759 | 92.9M | *dp++ = 255; |
760 | 92.9M | } |
761 | 11.3k | break; |
762 | 11.3k | 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 | 416 | case 1: |
780 | 4.87k | for (x = 0; x < width; x++) |
781 | 4.45k | { |
782 | 4.45k | int idx; |
783 | 4.45k | switch (x & 7) |
784 | 4.45k | { |
785 | 913 | case 0: idx = (sp[0] >> 7) & 0x01; break; |
786 | 516 | case 1: idx = (sp[0] >> 6) & 0x01; break; |
787 | 516 | case 2: idx = (sp[0] >> 5) & 0x01; break; |
788 | 516 | case 3: idx = (sp[0] >> 4) & 0x01; break; |
789 | 499 | case 4: idx = (sp[0] >> 3) & 0x01; break; |
790 | 499 | case 5: idx = (sp[0] >> 2) & 0x01; break; |
791 | 499 | case 6: idx = (sp[0] >> 1) & 0x01; break; |
792 | 499 | case 7: idx = (sp[0] >> 0) & 0x01; sp++; break; |
793 | 4.45k | } |
794 | 4.45k | *dp++ = info->palette[3 * idx + 0]; |
795 | 4.45k | *dp++ = info->palette[3 * idx + 1]; |
796 | 4.45k | *dp++ = info->palette[3 * idx + 2]; |
797 | 4.45k | *dp++ = 255; |
798 | 4.45k | } |
799 | 416 | break; |
800 | 82.6k | } |
801 | 82.6k | } |
802 | | |
803 | 216 | fz_free(ctx, decompressed); |
804 | 216 | fz_premultiply_pixmap(ctx, pix); |
805 | 216 | return pix; |
806 | 216 | } |
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 | 141 | { |
811 | 141 | if (info->colorspacetype == 0) |
812 | 101 | { |
813 | 101 | float matrix[9] = { 1, 0, 0, 0, 1, 0, 0, 0, 1 }; |
814 | 101 | float wp[3] = { 0.95047f, 1.0f, 1.08883f }; /* D65 white point */ |
815 | 101 | float bp[3] = { 0, 0, 0 }; |
816 | 101 | float gamma[3] = { 1, 1, 1 }; |
817 | 101 | int i; |
818 | | |
819 | 404 | for (i = 0; i < 3; i++) |
820 | 303 | gamma[i] = (float) info->gamma[i] / (float) (1 << 16); |
821 | 1.01k | for (i = 0; i < 9; i++) |
822 | 909 | 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 | 101 | return fz_new_cal_rgb_colorspace(ctx, wp, bp, gamma, matrix); |
834 | 101 | } |
835 | 40 | 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 | 40 | 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 | 40 | else if (info->colorspacetype == 0x4d424544) |
846 | 15 | { |
847 | 15 | fz_buffer *profile; |
848 | 15 | fz_colorspace *cs; |
849 | | |
850 | 15 | if ((uint32_t)(end - begin) <= info->profileoffset) |
851 | 7 | { |
852 | 7 | fz_warn(ctx, "ignoring color profile located outside bmp image"); |
853 | 7 | return NULL; |
854 | 7 | } |
855 | 8 | 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 | 6 | 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 | 6 | profile = fz_new_buffer_from_copied_data(ctx, begin + info->profileoffset, info->profilesize); |
867 | | |
868 | 12 | fz_try(ctx) |
869 | 12 | cs = fz_new_icc_colorspace(ctx, FZ_COLORSPACE_RGB, 0, "BMPRGB", profile); |
870 | 12 | fz_always(ctx) |
871 | 6 | fz_drop_buffer(ctx, profile); |
872 | 6 | fz_catch(ctx) |
873 | 5 | fz_rethrow(ctx); |
874 | | |
875 | 1 | return cs; |
876 | 6 | } |
877 | 25 | else if (info->colorspacetype == 0x73524742) |
878 | 0 | { |
879 | 0 | return fz_keep_colorspace(ctx, fz_device_rgb(ctx)); |
880 | 0 | } |
881 | | |
882 | 25 | fz_warn(ctx, "ignoring color profile with unknown type in bmp image"); |
883 | 25 | return NULL; |
884 | 141 | } |
885 | | |
886 | | static void |
887 | | compute_mask_info(unsigned int mask, unsigned int *shift, unsigned int *bits) |
888 | 1.08k | { |
889 | 1.08k | *bits = 0; |
890 | 1.08k | *shift = 0; |
891 | | |
892 | 3.11k | while (mask && (mask & 1) == 0) { |
893 | 2.03k | *shift += 1; |
894 | 2.03k | mask >>= 1; |
895 | 2.03k | } |
896 | 3.09k | while (mask && (mask & 1) == 1) { |
897 | 2.01k | *bits += 1; |
898 | 2.01k | mask >>= 1; |
899 | 2.01k | } |
900 | 1.08k | } |
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 | 8 | { |
905 | 8 | int size = 0; |
906 | | |
907 | 8 | if (info->compression == BI_BITFIELDS) |
908 | 4 | { |
909 | 4 | size = 12; |
910 | 4 | if (end - p < 12) |
911 | 0 | fz_throw(ctx, FZ_ERROR_FORMAT, "premature end in mask header in bmp image"); |
912 | | |
913 | 4 | info->rmask = read32(p + 0); |
914 | 4 | info->gmask = read32(p + 4); |
915 | 4 | info->bmask = read32(p + 8); |
916 | 4 | } |
917 | 4 | else if (info->compression == BI_ALPHABITS) |
918 | 4 | { |
919 | 4 | size = 16; |
920 | 4 | if (end - p < 16) |
921 | 0 | fz_throw(ctx, FZ_ERROR_FORMAT, "premature end in mask header in bmp image"); |
922 | | |
923 | 4 | info->rmask = read32(p + 0); |
924 | 4 | info->gmask = read32(p + 4); |
925 | 4 | info->bmask = read32(p + 8); |
926 | 4 | info->amask = read32(p + 12); |
927 | 4 | } |
928 | | |
929 | 8 | return p + size; |
930 | 8 | } |
931 | | |
932 | | static int |
933 | | bmp_palette_is_gray(fz_context *ctx, struct info *info, int readcolors) |
934 | 78 | { |
935 | 78 | int i; |
936 | 210 | for (i = 0; i < readcolors; i++) |
937 | 158 | { |
938 | 158 | int rgdiff = fz_absi(info->palette[3 * i + 0] - info->palette[3 * i + 1]); |
939 | 158 | int gbdiff = fz_absi(info->palette[3 * i + 1] - info->palette[3 * i + 2]); |
940 | 158 | int rbdiff = fz_absi(info->palette[3 * i + 0] - info->palette[3 * i + 2]); |
941 | 158 | if (rgdiff > 2 || gbdiff > 2 || rbdiff > 2) |
942 | 26 | return 0; |
943 | 158 | } |
944 | 52 | return 1; |
945 | 78 | } |
946 | | |
947 | | static void |
948 | | bmp_load_default_palette(fz_context *ctx, struct info *info, int readcolors) |
949 | 81 | { |
950 | 81 | int i; |
951 | | |
952 | 81 | fz_warn(ctx, "color table too short; loading default palette"); |
953 | | |
954 | 81 | if (info->bitcount == 8) |
955 | 42 | { |
956 | 42 | if (!bmp_palette_is_gray(ctx, info, readcolors)) |
957 | 10 | memcpy(&info->palette[readcolors * 3], &web_palette[readcolors * 3], |
958 | 10 | sizeof(web_palette) - readcolors * 3); |
959 | 32 | else |
960 | 8.19k | for (i = readcolors; i < 256; i++) |
961 | 8.16k | { |
962 | 8.16k | info->palette[3 * i + 0] = i; |
963 | 8.16k | info->palette[3 * i + 1] = i; |
964 | 8.16k | info->palette[3 * i + 2] = i; |
965 | 8.16k | } |
966 | 42 | } |
967 | 39 | else if (info->bitcount == 4) |
968 | 36 | { |
969 | 36 | if (!bmp_palette_is_gray(ctx, info, readcolors)) |
970 | 16 | memcpy(&info->palette[readcolors * 3], &vga_palette[readcolors * 3], |
971 | 16 | sizeof(vga_palette) - readcolors * 3); |
972 | 20 | else |
973 | 327 | for (i = readcolors; i < 16; i++) |
974 | 307 | { |
975 | 307 | info->palette[3 * i + 0] = (i << 4) | i; |
976 | 307 | info->palette[3 * i + 1] = (i << 4) | i; |
977 | 307 | info->palette[3 * i + 2] = (i << 4) | i; |
978 | 307 | } |
979 | 36 | } |
980 | 3 | else if (info->bitcount == 2) |
981 | 0 | memcpy(info->palette, gray_palette, sizeof(gray_palette)); |
982 | 3 | else if (info->bitcount == 1) |
983 | 3 | memcpy(info->palette, bw_palette, sizeof(bw_palette)); |
984 | 81 | } |
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 | 86 | { |
989 | 86 | int i, expected, present, entry_size; |
990 | | |
991 | 86 | entry_size = palette_entry_size(info); |
992 | | |
993 | 86 | if (info->colors == 0) |
994 | 12 | expected = info->colors = 1 << info->bitcount; |
995 | 74 | else |
996 | 74 | expected = fz_mini(info->colors, 1 << info->bitcount); |
997 | | |
998 | 86 | if (info->bitmapoffset == 0) |
999 | 0 | present = fz_mini(expected, (end - p) / entry_size); |
1000 | 86 | else |
1001 | 86 | present = fz_mini(expected, (begin + info->bitmapoffset - p) / entry_size); |
1002 | | |
1003 | 423 | for (i = 0; i < present; i++) |
1004 | 337 | { |
1005 | | /* ignore alpha channel even if present */ |
1006 | 337 | info->palette[3 * i + 0] = read8(p + i * entry_size + 2); |
1007 | 337 | info->palette[3 * i + 1] = read8(p + i * entry_size + 1); |
1008 | 337 | info->palette[3 * i + 2] = read8(p + i * entry_size + 0); |
1009 | 337 | } |
1010 | | |
1011 | 86 | if (present < expected) |
1012 | 81 | bmp_load_default_palette(ctx, info, present); |
1013 | | |
1014 | 86 | return p + present * entry_size; |
1015 | 86 | } |
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 | 275 | { |
1020 | 275 | uint32_t size; |
1021 | | |
1022 | 275 | if (end - p < 4) |
1023 | 0 | fz_throw(ctx, FZ_ERROR_FORMAT, "premature end in info header in bmp image"); |
1024 | 275 | size = info->version = read32(p + 0); |
1025 | | |
1026 | 275 | if (!is_win_bmp(info) && !is_os2_bmp(info)) |
1027 | 5 | fz_throw(ctx, FZ_ERROR_FORMAT, "unknown header version (%u) in bmp image", info->version); |
1028 | 270 | 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 | 270 | info->compression = BI_NONE; |
1033 | | |
1034 | | /* OS/2 1.x or Windows v2 */ |
1035 | 270 | if (size == 12) |
1036 | 15 | { |
1037 | | /* read32(p+0) == header size */ |
1038 | 15 | info->width = read16(p + 4); |
1039 | 15 | info->height = read16(p + 6); |
1040 | | /* read16(p+8) == planes */ |
1041 | 15 | info->bitcount = read16(p + 10); |
1042 | 15 | } |
1043 | | /* OS/2 2.x short header */ |
1044 | 270 | if (size >= 16) |
1045 | 255 | { |
1046 | | /* read32(p+0) == header size */ |
1047 | 255 | info->width = read32(p + 4); |
1048 | 255 | info->height = read32(p + 8); |
1049 | | /* read16(p+12) == planes */ |
1050 | 255 | info->bitcount = read16(p + 14); |
1051 | 255 | } |
1052 | | |
1053 | | /* default masks */ |
1054 | 270 | if (info->bitcount == 16) |
1055 | 79 | { |
1056 | 79 | info->rmask = 0x00007c00; |
1057 | 79 | info->gmask = 0x000003e0; |
1058 | 79 | info->bmask = 0x0000001f; |
1059 | 79 | info->amask = 0x00000000; |
1060 | 79 | } |
1061 | 191 | else if (info->bitcount == 24 || info->bitcount == 32) |
1062 | 82 | { |
1063 | 82 | info->rmask = 0x00ff0000; |
1064 | 82 | info->gmask = 0x0000ff00; |
1065 | 82 | info->bmask = 0x000000ff; |
1066 | 82 | info->amask = 0x00000000; |
1067 | 82 | } |
1068 | | |
1069 | | /* Windows v3 header */ |
1070 | 270 | if (size >= 40) |
1071 | 253 | { |
1072 | 253 | info->compression = read32(p + 16); |
1073 | 253 | info->bitmapsize = read32(p + 20); |
1074 | 253 | info->xres = read32(p + 24); |
1075 | 253 | info->yres = read32(p + 28); |
1076 | 253 | info->colors = read32(p + 32); |
1077 | 253 | if (info->bitcount >= 32) |
1078 | 95 | { |
1079 | 95 | if (info->colors != 0) |
1080 | 86 | fz_warn(ctx, "Suspect BMP header; bitcount=%d, colors=%d", info->bitcount, info->colors); |
1081 | 95 | info->colors = 0; |
1082 | 95 | } |
1083 | 158 | else if (info->colors > (1U<<info->bitcount)) |
1084 | 120 | { |
1085 | 120 | fz_warn(ctx, "Suspect BMP header; bitcount=%d, colors=%d", info->bitcount, info->colors); |
1086 | 120 | info->colors = 1<<info->bitcount; |
1087 | 120 | } |
1088 | | /* read32(p+36) == important colors */ |
1089 | 253 | } |
1090 | | /* Windows v3 header with RGB masks */ |
1091 | 270 | if (size == 52 || size == 56 || size == 108 || size == 124) |
1092 | 175 | { |
1093 | 175 | info->rmask = read32(p + 40); |
1094 | 175 | info->gmask = read32(p + 44); |
1095 | 175 | info->bmask = read32(p + 48); |
1096 | 175 | } |
1097 | | /* Windows v3 header with RGBA masks */ |
1098 | 270 | if (size == 56 || size == 108 || size == 124) |
1099 | 174 | { |
1100 | 174 | info->amask = read32(p + 52); |
1101 | 174 | } |
1102 | | /* OS/2 2.x long header */ |
1103 | 270 | if (size == 64) |
1104 | 3 | { |
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 | 3 | } |
1114 | | /* Windows v4 header */ |
1115 | 270 | if (size >= 108) |
1116 | 153 | { |
1117 | 153 | info->colorspacetype = read32(p + 56); |
1118 | | |
1119 | 153 | info->endpoints[0] = read32(p + 60); |
1120 | 153 | info->endpoints[1] = read32(p + 64); |
1121 | 153 | info->endpoints[2] = read32(p + 68); |
1122 | | |
1123 | 153 | info->endpoints[3] = read32(p + 72); |
1124 | 153 | info->endpoints[4] = read32(p + 76); |
1125 | 153 | info->endpoints[5] = read32(p + 80); |
1126 | | |
1127 | 153 | info->endpoints[6] = read32(p + 84); |
1128 | 153 | info->endpoints[7] = read32(p + 88); |
1129 | 153 | info->endpoints[8] = read32(p + 92); |
1130 | | |
1131 | 153 | info->gamma[0] = read32(p + 96); |
1132 | 153 | info->gamma[1] = read32(p + 100); |
1133 | 153 | info->gamma[2] = read32(p + 104); |
1134 | 153 | } |
1135 | | /* Windows v5 header */ |
1136 | 270 | if (size >= 124) |
1137 | 20 | { |
1138 | 20 | info->intent = read32(p + 108); |
1139 | 20 | info->profileoffset = read32(p + 112); |
1140 | 20 | info->profilesize = read32(p + 116); |
1141 | | /* read32(p+120) == reserved */ |
1142 | 20 | } |
1143 | | |
1144 | 270 | return p + size; |
1145 | 270 | } |
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 | 276 | { |
1151 | 276 | const unsigned char *profilebegin; |
1152 | | |
1153 | 276 | memset(info, 0x00, sizeof (*info)); |
1154 | 276 | info->colorspacetype = 0xffffffff; |
1155 | | |
1156 | 276 | p = profilebegin = bmp_read_file_header(ctx, info, begin, end, p); |
1157 | | |
1158 | 276 | p = bmp_read_info_header(ctx, info, begin, end, p); |
1159 | | |
1160 | | /* clamp bitmap offset to buffer size */ |
1161 | 276 | if (info->bitmapoffset < (uint32_t)(p - begin)) |
1162 | 68 | info->bitmapoffset = (uint32_t)(p - begin); |
1163 | 276 | if ((uint32_t)(end - begin) < info->bitmapoffset) |
1164 | 27 | info->bitmapoffset = end - begin; |
1165 | | |
1166 | 276 | if (has_palette(info)) |
1167 | 86 | p = bmp_read_palette(ctx, info, begin, end, p); |
1168 | | |
1169 | 276 | if (has_color_masks(info)) |
1170 | 8 | p = bmp_read_color_masks(ctx, info, begin, end, p); |
1171 | | |
1172 | 276 | info->xres = DPM_TO_DPI(info->xres); |
1173 | 276 | info->yres = DPM_TO_DPI(info->yres); |
1174 | | |
1175 | | /* extract topdown/bottomup from height for windows bitmaps */ |
1176 | 276 | if (is_win_bmp(info)) |
1177 | 265 | { |
1178 | 265 | int bits = info->version == 12 ? 16 : 32; |
1179 | | |
1180 | 265 | info->topdown = (info->height >> (bits - 1)) & 1; |
1181 | 265 | if (info->topdown) |
1182 | 67 | { |
1183 | 67 | info->height--; |
1184 | 67 | info->height = ~info->height; |
1185 | 67 | info->height &= bits == 16 ? 0xffff : 0xffffffff; |
1186 | 67 | } |
1187 | 265 | } |
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 | 276 | if (info->version == 108 && |
1195 | 276 | info->rmask == 0x73524742 && /* colorspacetype */ |
1196 | 276 | info->gmask == 0x00000000 && /* endpoints[0] */ |
1197 | 276 | info->bmask == 0x00000000 && /* endpoints[1] */ |
1198 | 276 | info->amask == 0x00000000 && /* endpoints[2] */ |
1199 | 276 | info->colorspacetype == 0x00000000 && /* endpoints[3] */ |
1200 | 276 | info->endpoints[0] == 0x00000000 && /* endpoints[4] */ |
1201 | 276 | info->endpoints[1] == 0x00000000 && /* endpoints[5] */ |
1202 | 276 | info->endpoints[2] == 0x00000000 && /* endpoints[6] */ |
1203 | 276 | info->endpoints[3] == 0x00000000 && /* endpoints[7] */ |
1204 | 276 | info->endpoints[4] == 0x00000000 && /* endpoints[8] */ |
1205 | 276 | info->endpoints[5] == 0x00000000 && /* gamma[0] */ |
1206 | 276 | info->endpoints[6] == 0x00000000 && /* gamma[1] */ |
1207 | 276 | info->endpoints[7] == 0x00000000 && /* gamma[2] */ |
1208 | 276 | 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 | 276 | compute_mask_info(info->rmask, &info->rshift, &info->rbits); |
1233 | 276 | compute_mask_info(info->gmask, &info->gshift, &info->gbits); |
1234 | 276 | compute_mask_info(info->bmask, &info->bshift, &info->bbits); |
1235 | 276 | 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 | 276 | if (info->width == 0 || info->width > SHRT_MAX || info->height == 0 || info->height > SHRT_MAX) |
1284 | 16 | fz_throw(ctx, FZ_ERROR_LIMIT, "image dimensions (%u x %u) out of range in bmp image", info->width, info->height); |
1285 | 260 | if (!is_valid_compression(info)) |
1286 | 16 | fz_throw(ctx, FZ_ERROR_FORMAT, "unsupported compression method (%u) in bmp image", info->compression); |
1287 | 244 | if (!is_valid_bitcount(info)) |
1288 | 4 | fz_throw(ctx, FZ_ERROR_FORMAT, "invalid bits per pixel (%u) for compression (%u) in bmp image", info->bitcount, info->compression); |
1289 | 240 | if (info->rbits > info->bitcount) |
1290 | 0 | fz_throw(ctx, FZ_ERROR_FORMAT, "unsupported %u bit red mask in bmp image", info->rbits); |
1291 | 240 | if (info->gbits > info->bitcount) |
1292 | 0 | fz_throw(ctx, FZ_ERROR_FORMAT, "unsupported %u bit green mask in bmp image", info->gbits); |
1293 | 240 | if (info->bbits > info->bitcount) |
1294 | 1 | fz_throw(ctx, FZ_ERROR_FORMAT, "unsupported %u bit blue mask in bmp image", info->bbits); |
1295 | 239 | 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 | 238 | if (has_color_profile(info)) |
1300 | 141 | info->cs = bmp_read_color_profile(ctx, info, profilebegin, end); |
1301 | 238 | if (!info->cs) |
1302 | 125 | info->cs = fz_keep_colorspace(ctx, fz_device_rgb(ctx)); |
1303 | | |
1304 | 238 | if (only_metadata) |
1305 | 0 | return NULL; |
1306 | | |
1307 | | /* bitmap cannot begin before headers have ended */ |
1308 | 238 | if ((uint32_t)(p - begin) < info->bitmapoffset) |
1309 | 15 | p = begin + info->bitmapoffset; |
1310 | | |
1311 | 238 | 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 | 238 | 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 | 238 | else |
1324 | 238 | return bmp_read_bitmap(ctx, info, begin, end, p); |
1325 | 238 | } |
1326 | | |
1327 | | fz_pixmap * |
1328 | | fz_load_bmp_subimage(fz_context *ctx, const unsigned char *buf, size_t len, int subimage) |
1329 | 276 | { |
1330 | 276 | const unsigned char *begin = buf; |
1331 | 276 | const unsigned char *end = buf + len; |
1332 | 276 | const unsigned char *p = begin; |
1333 | 276 | struct info info = { 0 }; |
1334 | 276 | int nextoffset = 0; |
1335 | 276 | fz_pixmap *image = NULL; |
1336 | 276 | int origidx = subimage; |
1337 | | |
1338 | 276 | (void) p; |
1339 | | |
1340 | 276 | do |
1341 | 276 | { |
1342 | 276 | p = begin + nextoffset; |
1343 | | |
1344 | 276 | 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 | 276 | if (is_bitmap_array(p)) |
1348 | 1 | { |
1349 | | /* read16(p+0) == type */ |
1350 | | /* read32(p+2) == size of this header in bytes */ |
1351 | 1 | nextoffset = read32(p + 6); |
1352 | | /* read16(p+10) == suitable pelx dimensions */ |
1353 | | /* read16(p+12) == suitable pely dimensions */ |
1354 | 1 | p += 14; |
1355 | 1 | (void) p; |
1356 | 1 | } |
1357 | 275 | else if (is_bitmap(p)) |
1358 | 275 | { |
1359 | 275 | nextoffset = 0; |
1360 | 275 | } |
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 | 276 | 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 | 276 | else |
1373 | 276 | subimage--; |
1374 | | |
1375 | 276 | } while (subimage >= 0 && nextoffset > 0); |
1376 | | |
1377 | 276 | if (subimage != -1) |
1378 | 0 | fz_throw(ctx, FZ_ERROR_ARGUMENT, "subimage index (%d) out of range in bmp image", origidx); |
1379 | | |
1380 | 552 | fz_try(ctx) |
1381 | 552 | image = bmp_read_image(ctx, &info, begin, end, p, 0); |
1382 | 552 | fz_always(ctx) |
1383 | 276 | fz_drop_colorspace(ctx, info.cs); |
1384 | 276 | fz_catch(ctx) |
1385 | 60 | fz_rethrow(ctx); |
1386 | | |
1387 | 216 | return image; |
1388 | 276 | } |
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 | 276 | { |
1460 | 276 | const unsigned char *begin = buf; |
1461 | 276 | const unsigned char *end = buf + len; |
1462 | 276 | uint32_t nextoffset = 0; |
1463 | 276 | int count = 0; |
1464 | | |
1465 | 276 | do |
1466 | 277 | { |
1467 | 277 | const unsigned char *p = begin + nextoffset; |
1468 | | |
1469 | 277 | if (end - p < 14) |
1470 | 0 | fz_throw(ctx, FZ_ERROR_FORMAT, "not enough data for bitmap array in bmp image"); |
1471 | | |
1472 | 277 | if (is_bitmap_array(p)) |
1473 | 1 | { |
1474 | | /* read16(p+0) == type */ |
1475 | | /* read32(p+2) == size of this header in bytes */ |
1476 | 1 | nextoffset = read32(p + 6); |
1477 | | /* read16(p+10) == suitable pelx dimensions */ |
1478 | | /* read16(p+12) == suitable pely dimensions */ |
1479 | 1 | p += 14; |
1480 | 1 | } |
1481 | 276 | else if (is_bitmap(p)) |
1482 | 275 | { |
1483 | 275 | nextoffset = 0; |
1484 | 275 | } |
1485 | 1 | else |
1486 | 1 | { |
1487 | 1 | fz_warn(ctx, "treating invalid subimage as end of file"); |
1488 | 1 | nextoffset = 0; |
1489 | 1 | } |
1490 | | |
1491 | 277 | 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 | 277 | else |
1497 | 277 | count++; |
1498 | | |
1499 | 277 | } while (nextoffset > 0); |
1500 | | |
1501 | 276 | return count; |
1502 | 276 | } |
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 | } |