1 | #include "mupdf/fitz.h" |
2 | |
3 | #include <string.h> |
4 | #include <limits.h> |
5 | |
6 | static const unsigned char web_palette[] = { |
7 | 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x66, 0x00, 0x00, 0x99, 0x00, 0x00, 0xCC, 0x00, 0x00, 0xFF, 0x00, 0x00, |
8 | 0x00, 0x00, 0x33, 0x33, 0x00, 0x33, 0x66, 0x00, 0x33, 0x99, 0x00, 0x33, 0xCC, 0x00, 0x33, 0xFF, 0x00, 0x33, |
9 | 0x00, 0x00, 0x66, 0x33, 0x00, 0x66, 0x66, 0x00, 0x66, 0x99, 0x00, 0x66, 0xCC, 0x00, 0x66, 0xFF, 0x00, 0x66, |
10 | 0x00, 0x00, 0x99, 0x33, 0x00, 0x99, 0x66, 0x00, 0x99, 0x99, 0x00, 0x99, 0xCC, 0x00, 0x99, 0xFF, 0x00, 0x99, |
11 | 0x00, 0x00, 0xCC, 0x33, 0x00, 0xCC, 0x66, 0x00, 0xCC, 0x99, 0x00, 0xCC, 0xCC, 0x00, 0xCC, 0xFF, 0x00, 0xCC, |
12 | 0x00, 0x00, 0xFF, 0x33, 0x00, 0xFF, 0x66, 0x00, 0xFF, 0x99, 0x00, 0xFF, 0xCC, 0x00, 0xFF, 0xFF, 0x00, 0xFF, |
13 | 0x00, 0x33, 0x00, 0x33, 0x33, 0x00, 0x66, 0x33, 0x00, 0x99, 0x33, 0x00, 0xCC, 0x33, 0x00, 0xFF, 0x33, 0x00, |
14 | 0x00, 0x33, 0x33, 0x33, 0x33, 0x33, 0x66, 0x33, 0x33, 0x99, 0x33, 0x33, 0xCC, 0x33, 0x33, 0xFF, 0x33, 0x33, |
15 | 0x00, 0x33, 0x66, 0x33, 0x33, 0x66, 0x66, 0x33, 0x66, 0x99, 0x33, 0x66, 0xCC, 0x33, 0x66, 0xFF, 0x33, 0x66, |
16 | 0x00, 0x33, 0x99, 0x33, 0x33, 0x99, 0x66, 0x33, 0x99, 0x99, 0x33, 0x99, 0xCC, 0x33, 0x99, 0xFF, 0x33, 0x99, |
17 | 0x00, 0x33, 0xCC, 0x33, 0x33, 0xCC, 0x66, 0x33, 0xCC, 0x99, 0x33, 0xCC, 0xCC, 0x33, 0xCC, 0xFF, 0x33, 0xCC, |
18 | 0x00, 0x33, 0xFF, 0x33, 0x33, 0xFF, 0x66, 0x33, 0xFF, 0x99, 0x33, 0xFF, 0xCC, 0x33, 0xFF, 0xFF, 0x33, 0xFF, |
19 | 0x00, 0x66, 0x00, 0x33, 0x66, 0x00, 0x66, 0x66, 0x00, 0x99, 0x66, 0x00, 0xCC, 0x66, 0x00, 0xFF, 0x66, 0x00, |
20 | 0x00, 0x66, 0x33, 0x33, 0x66, 0x33, 0x66, 0x66, 0x33, 0x99, 0x66, 0x33, 0xCC, 0x66, 0x33, 0xFF, 0x66, 0x33, |
21 | 0x00, 0x66, 0x66, 0x33, 0x66, 0x66, 0x66, 0x66, 0x66, 0x99, 0x66, 0x66, 0xCC, 0x66, 0x66, 0xFF, 0x66, 0x66, |
22 | 0x00, 0x66, 0x99, 0x33, 0x66, 0x99, 0x66, 0x66, 0x99, 0x99, 0x66, 0x99, 0xCC, 0x66, 0x99, 0xFF, 0x66, 0x99, |
23 | 0x00, 0x66, 0xCC, 0x33, 0x66, 0xCC, 0x66, 0x66, 0xCC, 0x99, 0x66, 0xCC, 0xCC, 0x66, 0xCC, 0xFF, 0x66, 0xCC, |
24 | 0x00, 0x66, 0xFF, 0x33, 0x66, 0xFF, 0x66, 0x66, 0xFF, 0x99, 0x66, 0xFF, 0xCC, 0x66, 0xFF, 0xFF, 0x66, 0xFF, |
25 | 0x00, 0x99, 0x00, 0x33, 0x99, 0x00, 0x66, 0x99, 0x00, 0x99, 0x99, 0x00, 0xCC, 0x99, 0x00, 0xFF, 0x99, 0x00, |
26 | 0x00, 0x99, 0x33, 0x33, 0x99, 0x33, 0x66, 0x99, 0x33, 0x99, 0x99, 0x33, 0xCC, 0x99, 0x33, 0xFF, 0x99, 0x33, |
27 | 0x00, 0x99, 0x66, 0x33, 0x99, 0x66, 0x66, 0x99, 0x66, 0x99, 0x99, 0x66, 0xCC, 0x99, 0x66, 0xFF, 0x99, 0x66, |
28 | 0x00, 0x99, 0x99, 0x33, 0x99, 0x99, 0x66, 0x99, 0x99, 0x99, 0x99, 0x99, 0xCC, 0x99, 0x99, 0xFF, 0x99, 0x99, |
29 | 0x00, 0x99, 0xCC, 0x33, 0x99, 0xCC, 0x66, 0x99, 0xCC, 0x99, 0x99, 0xCC, 0xCC, 0x99, 0xCC, 0xFF, 0x99, 0xCC, |
30 | 0x00, 0x99, 0xFF, 0x33, 0x99, 0xFF, 0x66, 0x99, 0xFF, 0x99, 0x99, 0xFF, 0xCC, 0x99, 0xFF, 0xFF, 0x99, 0xFF, |
31 | 0x00, 0xCC, 0x00, 0x33, 0xCC, 0x00, 0x66, 0xCC, 0x00, 0x99, 0xCC, 0x00, 0xCC, 0xCC, 0x00, 0xFF, 0xCC, 0x00, |
32 | 0x00, 0xCC, 0x33, 0x33, 0xCC, 0x33, 0x66, 0xCC, 0x33, 0x99, 0xCC, 0x33, 0xCC, 0xCC, 0x33, 0xFF, 0xCC, 0x33, |
33 | 0x00, 0xCC, 0x66, 0x33, 0xCC, 0x66, 0x66, 0xCC, 0x66, 0x99, 0xCC, 0x66, 0xCC, 0xCC, 0x66, 0xFF, 0xCC, 0x66, |
34 | 0x00, 0xCC, 0x99, 0x33, 0xCC, 0x99, 0x66, 0xCC, 0x99, 0x99, 0xCC, 0x99, 0xCC, 0xCC, 0x99, 0xFF, 0xCC, 0x99, |
35 | 0x00, 0xCC, 0xCC, 0x33, 0xCC, 0xCC, 0x66, 0xCC, 0xCC, 0x99, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xFF, 0xCC, 0xCC, |
36 | 0x00, 0xCC, 0xFF, 0x33, 0xCC, 0xFF, 0x66, 0xCC, 0xFF, 0x99, 0xCC, 0xFF, 0xCC, 0xCC, 0xFF, 0xFF, 0xCC, 0xFF, |
37 | 0x00, 0xFF, 0x00, 0x33, 0xFF, 0x00, 0x66, 0xFF, 0x00, 0x99, 0xFF, 0x00, 0xCC, 0xFF, 0x00, 0xFF, 0xFF, 0x00, |
38 | 0x00, 0xFF, 0x33, 0x33, 0xFF, 0x33, 0x66, 0xFF, 0x33, 0x99, 0xFF, 0x33, 0xCC, 0xFF, 0x33, 0xFF, 0xFF, 0x33, |
39 | 0x00, 0xFF, 0x66, 0x33, 0xFF, 0x66, 0x66, 0xFF, 0x66, 0x99, 0xFF, 0x66, 0xCC, 0xFF, 0x66, 0xFF, 0xFF, 0x66, |
40 | 0x00, 0xFF, 0x99, 0x33, 0xFF, 0x99, 0x66, 0xFF, 0x99, 0x99, 0xFF, 0x99, 0xCC, 0xFF, 0x99, 0xFF, 0xFF, 0x99, |
41 | 0x00, 0xFF, 0xCC, 0x33, 0xFF, 0xCC, 0x66, 0xFF, 0xCC, 0x99, 0xFF, 0xCC, 0xCC, 0xFF, 0xCC, 0xFF, 0xFF, 0xCC, |
42 | 0x00, 0xFF, 0xFF, 0x33, 0xFF, 0xFF, 0x66, 0xFF, 0xFF, 0x99, 0xFF, 0xFF, 0xCC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
43 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
44 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
45 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
46 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
47 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
48 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
49 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
50 | }; |
51 | |
52 | static const unsigned char vga_palette[] = { |
53 | 0x00, 0x00, 0x00, 0x00, 0x00, 0xAA, 0x00, 0xAA, 0x00, 0x00, 0xAA, 0xAA, |
54 | 0xAA, 0x00, 0x00, 0xAA, 0x00, 0xAA, 0xAA, 0x55, 0x00, 0xAA, 0xAA, 0xAA, |
55 | 0x55, 0x55, 0x55, 0x55, 0x55, 0xFF, 0x55, 0xFF, 0x55, 0x55, 0xFF, 0xFF, |
56 | 0xFF, 0x55, 0x55, 0xFF, 0x55, 0xFF, 0xFF, 0xFF, 0x55, 0xFF, 0xFF, 0xFF, |
57 | }; |
58 | |
59 | static const unsigned char gray_palette[] = { |
60 | 0x00, 0x00, 0x00, 0x54, 0x54, 0x54, |
61 | 0xA8, 0xA8, 0xA8, 0xFF, 0xFF, 0xFF, |
62 | }; |
63 | |
64 | static const unsigned char bw_palette[] = { |
65 | 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, |
66 | }; |
67 | |
68 | enum { |
69 | BI_RLE24 = -1, |
70 | BI_RGB = 0, |
71 | BI_RLE8 = 1, |
72 | BI_RLE4 = 2, |
73 | BI_BITFIELDS = 3, |
74 | BI_JPEG = 4, |
75 | BI_PNG = 5, |
76 | BI_ALPHABITS = 6, |
77 | BI_UNSUPPORTED = 42, |
78 | }; |
79 | |
80 | struct info |
81 | { |
82 | int filesize; |
83 | int offset; |
84 | int topdown; |
85 | int width, height; |
86 | int xres, yres; |
87 | int bitcount; |
88 | int compression; |
89 | int colors; |
90 | int rmask, gmask, bmask, amask; |
91 | unsigned char palette[256 * 3]; |
92 | |
93 | int ; |
94 | int palettetype; |
95 | unsigned char *samples; |
96 | |
97 | int rshift, gshift, bshift, ashift; |
98 | int rbits, gbits, bbits, abits; |
99 | }; |
100 | |
101 | #define read8(p) ((p)[0]) |
102 | #define read16(p) (((p)[1] << 8) | (p)[0]) |
103 | #define read32(p) (((p)[3] << 24) | ((p)[2] << 16) | ((p)[1] << 8) | (p)[0]) |
104 | |
105 | static const unsigned char * |
106 | (fz_context *ctx, struct info *info, const unsigned char *p, const unsigned char *end) |
107 | { |
108 | if (end - p < 14) |
109 | fz_throw(ctx, FZ_ERROR_GENERIC, "premature end in file header in bmp image" ); |
110 | |
111 | if (memcmp(&p[0], "BM" , 2)) |
112 | fz_throw(ctx, FZ_ERROR_GENERIC, "invalid signature in bmp image" ); |
113 | |
114 | info->filesize = read32(p + 2); |
115 | info->offset = read32(p + 10); |
116 | |
117 | return p + 14; |
118 | } |
119 | |
120 | static const unsigned char * |
121 | (fz_context *ctx, struct info *info, const unsigned char *p, const unsigned char *end) |
122 | { |
123 | int size; |
124 | |
125 | size = read32(p + 0); |
126 | if (size != 12) |
127 | fz_throw(ctx, FZ_ERROR_GENERIC, "unsupported core header size in bmp image" ); |
128 | |
129 | if (size >= 12) |
130 | { |
131 | if (end - p < 12) |
132 | fz_throw(ctx, FZ_ERROR_GENERIC, "premature end in bitmap core header in bmp image" ); |
133 | |
134 | info->width = read16(p + 4); |
135 | info->height = read16(p + 6); |
136 | info->bitcount = read16(p + 10); |
137 | } |
138 | |
139 | info->xres = 2835; |
140 | info->yres = 2835; |
141 | info->compression = BI_RGB; |
142 | info->palettetype = 0; |
143 | |
144 | return p + size; |
145 | } |
146 | |
147 | static const unsigned char * |
148 | (fz_context *ctx, struct info *info, const unsigned char *p, const unsigned char *end) |
149 | { |
150 | int size; |
151 | |
152 | size = read32(p + 0); |
153 | if (size != 16 && size != 64) |
154 | fz_throw(ctx, FZ_ERROR_GENERIC, "unsupported os2 header size in bmp image" ); |
155 | |
156 | if (size >= 16) |
157 | { |
158 | if (end - p < 16) |
159 | fz_throw(ctx, FZ_ERROR_GENERIC, "premature end in bitmap os2 header in bmp image" ); |
160 | |
161 | info->width = read32(p + 4); |
162 | info->height = read32(p + 8); |
163 | info->bitcount = read16(p + 14); |
164 | |
165 | info->compression = BI_RGB; |
166 | } |
167 | if (size >= 64) |
168 | { |
169 | if (end - p < 64) |
170 | fz_throw(ctx, FZ_ERROR_GENERIC, "premature end in bitmap os2 header in bmp image" ); |
171 | |
172 | info->compression = read32(p + 16); |
173 | info->xres = read32(p + 24); |
174 | info->yres = read32(p + 28); |
175 | info->colors = read32(p + 32); |
176 | |
177 | /* 4 in this header is interpreted as 24 bit RLE encoding */ |
178 | if (info->compression < 0) |
179 | info->compression = BI_UNSUPPORTED; |
180 | else if (info->compression == 4) |
181 | info->compression = BI_RLE24; |
182 | } |
183 | |
184 | info->palettetype = 1; |
185 | |
186 | return p + size; |
187 | } |
188 | |
189 | static void maskinfo(unsigned int mask, int *shift, int *bits) |
190 | { |
191 | *bits = 0; |
192 | *shift = 0; |
193 | if (mask) { |
194 | while ((mask & 1) == 0) { |
195 | *shift += 1; |
196 | mask >>= 1; |
197 | } |
198 | while ((mask & 1) == 1) { |
199 | *bits += 1; |
200 | mask >>= 1; |
201 | } |
202 | } |
203 | } |
204 | |
205 | static const unsigned char * |
206 | (fz_context *ctx, struct info *info, const unsigned char *p, const unsigned char *end) |
207 | { |
208 | int size; |
209 | |
210 | size = read32(p + 0); |
211 | if (size != 40 && size != 52 && size != 56 && size != 64 && |
212 | size != 108 && size != 124) |
213 | fz_throw(ctx, FZ_ERROR_GENERIC, "unsupported info header size in bmp image" ); |
214 | |
215 | if (size >= 40) |
216 | { |
217 | if (end - p < 40) |
218 | fz_throw(ctx, FZ_ERROR_GENERIC, "premature end in bitmap info header in bmp image" ); |
219 | |
220 | info->width = read32(p + 4); |
221 | info->topdown = (p[8 + 3] & 0x80) != 0; |
222 | if (info->topdown) |
223 | info->height = -read32(p + 8); |
224 | else |
225 | info->height = read32(p + 8); |
226 | info->bitcount = read16(p + 14); |
227 | info->compression = read32(p + 16); |
228 | info->xres = read32(p + 24); |
229 | info->yres = read32(p + 28); |
230 | info->colors = read32(p + 32); |
231 | |
232 | if (size == 40 && info->compression == BI_BITFIELDS && (info->bitcount == 16 || info->bitcount == 32)) |
233 | info->extramasks = 1; |
234 | else if (size == 40 && info->compression == BI_ALPHABITS && (info->bitcount == 16 || info->bitcount == 32)) |
235 | info->extramasks = 1; |
236 | |
237 | if (info->bitcount == 16) { |
238 | info->rmask = 0x00007c00; |
239 | info->gmask = 0x000003e0; |
240 | info->bmask = 0x0000001f; |
241 | info->amask = 0x00000000; |
242 | } else if (info->bitcount == 32) { |
243 | info->rmask = 0x00ff0000; |
244 | info->gmask = 0x0000ff00; |
245 | info->bmask = 0x000000ff; |
246 | info->amask = 0x00000000; |
247 | } |
248 | } |
249 | if (size >= 52) |
250 | { |
251 | if (end - p < 52) |
252 | fz_throw(ctx, FZ_ERROR_GENERIC, "premature end in bitmap info header in bmp image" ); |
253 | |
254 | if (info->compression == BI_BITFIELDS) { |
255 | info->rmask = read32(p + 40); |
256 | info->gmask = read32(p + 44); |
257 | info->bmask = read32(p + 48); |
258 | } |
259 | } |
260 | if (size >= 56) |
261 | { |
262 | if (end - p < 56) |
263 | fz_throw(ctx, FZ_ERROR_GENERIC, "premature end in bitmap info header in bmp image" ); |
264 | |
265 | if (info->compression == BI_BITFIELDS) { |
266 | info->amask = read32(p + 52); |
267 | } |
268 | } |
269 | |
270 | info->palettetype = 1; |
271 | |
272 | return p + size; |
273 | } |
274 | |
275 | static const unsigned char * |
276 | (fz_context *ctx, struct info *info, const unsigned char *p, const unsigned char *end) |
277 | { |
278 | int size = 0; |
279 | |
280 | if (info->compression == BI_BITFIELDS) |
281 | { |
282 | size = 12; |
283 | if (end - p < 12) |
284 | fz_throw(ctx, FZ_ERROR_GENERIC, "premature end in mask header in bmp image" ); |
285 | |
286 | info->rmask = read32(p + 0); |
287 | info->gmask = read32(p + 4); |
288 | info->bmask = read32(p + 8); |
289 | } |
290 | else if (info->compression == BI_ALPHABITS) |
291 | { |
292 | size = 16; |
293 | if (end - p < 16) |
294 | fz_throw(ctx, FZ_ERROR_GENERIC, "premature end in mask header in bmp image" ); |
295 | |
296 | /* ignore alpha mask */ |
297 | info->rmask = read32(p + 0); |
298 | info->gmask = read32(p + 4); |
299 | info->bmask = read32(p + 8); |
300 | } |
301 | |
302 | return p + size; |
303 | } |
304 | |
305 | static int |
306 | bmp_palette_is_gray(fz_context *ctx, struct info *info, int readcolors) |
307 | { |
308 | int i; |
309 | for (i = 0; i < readcolors; i++) |
310 | { |
311 | int rgdiff = fz_absi(info->palette[3 * i + 0] - info->palette[3 * i + 1]); |
312 | int gbdiff = fz_absi(info->palette[3 * i + 1] - info->palette[3 * i + 2]); |
313 | int rbdiff = fz_absi(info->palette[3 * i + 0] - info->palette[3 * i + 2]); |
314 | if (rgdiff > 2 || gbdiff > 2 || rbdiff > 2) |
315 | return 0; |
316 | } |
317 | return 1; |
318 | } |
319 | |
320 | static void |
321 | bmp_load_default_palette(fz_context *ctx, struct info *info, int readcolors) |
322 | { |
323 | int i; |
324 | |
325 | fz_warn(ctx, "color table too short; loading default palette" ); |
326 | |
327 | if (info->bitcount == 8) |
328 | { |
329 | if (!bmp_palette_is_gray(ctx, info, readcolors)) |
330 | memcpy(&info->palette[readcolors * 3], &web_palette[readcolors * 3], |
331 | sizeof(web_palette) - readcolors * 3); |
332 | else |
333 | for (i = readcolors; i < 256; i++) |
334 | { |
335 | info->palette[3 * i + 0] = i; |
336 | info->palette[3 * i + 1] = i; |
337 | info->palette[3 * i + 2] = i; |
338 | } |
339 | } |
340 | else if (info->bitcount == 4) |
341 | { |
342 | if (!bmp_palette_is_gray(ctx, info, readcolors)) |
343 | memcpy(&info->palette[readcolors * 3], &vga_palette[readcolors * 3], |
344 | sizeof(vga_palette) - readcolors * 3); |
345 | else |
346 | for (i = readcolors; i < 16; i++) |
347 | { |
348 | info->palette[3 * i + 0] = (i << 4) | i; |
349 | info->palette[3 * i + 1] = (i << 4) | i; |
350 | info->palette[3 * i + 2] = (i << 4) | i; |
351 | } |
352 | } |
353 | else if (info->bitcount == 2) |
354 | memcpy(info->palette, gray_palette, sizeof(gray_palette)); |
355 | else if (info->bitcount == 1) |
356 | memcpy(info->palette, bw_palette, sizeof(bw_palette)); |
357 | } |
358 | |
359 | static const unsigned char * |
360 | bmp_read_color_table(fz_context *ctx, struct info *info, const unsigned char *p, const unsigned char *end) |
361 | { |
362 | int i, colors, readcolors; |
363 | |
364 | if (info->bitcount > 8) |
365 | return p; |
366 | |
367 | if (info->colors == 0) |
368 | colors = 1 << info->bitcount; |
369 | else |
370 | colors = info->colors; |
371 | |
372 | colors = fz_mini(colors, 1 << info->bitcount); |
373 | |
374 | if (info->palettetype == 0) |
375 | { |
376 | readcolors = fz_mini(colors, (end - p) / 3); |
377 | for (i = 0; i < readcolors; i++) |
378 | { |
379 | info->palette[3 * i + 0] = read8(p + i * 3 + 2); |
380 | info->palette[3 * i + 1] = read8(p + i * 3 + 1); |
381 | info->palette[3 * i + 2] = read8(p + i * 3 + 0); |
382 | } |
383 | if (readcolors < colors) |
384 | bmp_load_default_palette(ctx, info, readcolors); |
385 | return p + readcolors * 3; |
386 | } |
387 | else |
388 | { |
389 | readcolors = fz_mini(colors, (end - p) / 4); |
390 | for (i = 0; i < readcolors; i++) |
391 | { |
392 | /* ignore alpha channel */ |
393 | info->palette[3 * i + 0] = read8(p + i * 4 + 2); |
394 | info->palette[3 * i + 1] = read8(p + i * 4 + 1); |
395 | info->palette[3 * i + 2] = read8(p + i * 4 + 0); |
396 | } |
397 | if (readcolors < colors) |
398 | bmp_load_default_palette(ctx, info, readcolors); |
399 | return p + readcolors * 4; |
400 | } |
401 | |
402 | return p; |
403 | } |
404 | |
405 | static unsigned char * |
406 | bmp_decompress_rle24(fz_context *ctx, struct info *info, const unsigned char *p, const unsigned char **end) |
407 | { |
408 | const unsigned char *sp; |
409 | unsigned char *dp, *ep, *decompressed; |
410 | int width = info->width; |
411 | int height = info->height; |
412 | int stride; |
413 | int x, i; |
414 | |
415 | stride = (width*3 + 3) / 4 * 4; |
416 | |
417 | sp = p; |
418 | dp = decompressed = fz_calloc(ctx, height, stride); |
419 | ep = dp + height * stride; |
420 | x = 0; |
421 | |
422 | while (sp + 2 <= *end) |
423 | { |
424 | if (sp[0] == 0 && sp[1] == 0) |
425 | { /* end of line */ |
426 | if (x*3 < stride) |
427 | dp += stride - x*3; |
428 | sp += 2; |
429 | x = 0; |
430 | } |
431 | else if (sp[0] == 0 && sp[1] == 1) |
432 | { /* end of bitmap */ |
433 | dp = ep; |
434 | break; |
435 | } |
436 | else if (sp[0] == 0 && sp[1] == 2) |
437 | { /* delta */ |
438 | int deltax, deltay; |
439 | if (sp + 4 > *end) |
440 | break; |
441 | deltax = sp[2]; |
442 | deltay = sp[3]; |
443 | dp += deltax*3 + deltay * stride; |
444 | sp += 4; |
445 | x += deltax; |
446 | } |
447 | else if (sp[0] == 0 && sp[1] >= 3) |
448 | { /* absolute */ |
449 | int n = sp[1] * 3; |
450 | int nn = (n + 1) / 2 * 2; |
451 | if (sp + 2 + nn > *end) |
452 | break; |
453 | if (dp + n > ep) { |
454 | fz_warn(ctx, "buffer overflow in bitmap data in bmp image" ); |
455 | break; |
456 | } |
457 | sp += 2; |
458 | for (i = 0; i < n; i++) |
459 | dp[i] = sp[i]; |
460 | dp += n; |
461 | sp += (n + 1) / 2 * 2; |
462 | x += n; |
463 | } |
464 | else |
465 | { /* encoded */ |
466 | int n = sp[0] * 3; |
467 | if (sp + 1 + 3 > *end) |
468 | break; |
469 | if (dp + n > ep) { |
470 | fz_warn(ctx, "buffer overflow in bitmap data in bmp image" ); |
471 | break; |
472 | } |
473 | for (i = 0; i < n / 3; i++) { |
474 | dp[i * 3 + 0] = sp[1]; |
475 | dp[i * 3 + 1] = sp[2]; |
476 | dp[i * 3 + 2] = sp[3]; |
477 | } |
478 | dp += n; |
479 | sp += 1 + 3; |
480 | x += n; |
481 | } |
482 | } |
483 | |
484 | if (dp < ep) |
485 | fz_warn(ctx, "premature end of bitmap data in bmp image" ); |
486 | |
487 | info->compression = BI_RGB; |
488 | info->bitcount = 24; |
489 | *end = ep; |
490 | return decompressed; |
491 | } |
492 | |
493 | static unsigned char * |
494 | bmp_decompress_rle8(fz_context *ctx, struct info *info, const unsigned char *p, const unsigned char **end) |
495 | { |
496 | const unsigned char *sp; |
497 | unsigned char *dp, *ep, *decompressed; |
498 | int width = info->width; |
499 | int height = info->height; |
500 | int stride; |
501 | int x, i; |
502 | |
503 | stride = (width + 3) / 4 * 4; |
504 | |
505 | sp = p; |
506 | dp = decompressed = fz_calloc(ctx, height, stride); |
507 | ep = dp + height * stride; |
508 | x = 0; |
509 | |
510 | while (sp + 2 <= *end) |
511 | { |
512 | if (sp[0] == 0 && sp[1] == 0) |
513 | { /* end of line */ |
514 | if (x < stride) |
515 | dp += stride - x; |
516 | sp += 2; |
517 | x = 0; |
518 | } |
519 | else if (sp[0] == 0 && sp[1] == 1) |
520 | { /* end of bitmap */ |
521 | dp = ep; |
522 | break; |
523 | } |
524 | else if (sp[0] == 0 && sp[1] == 2) |
525 | { /* delta */ |
526 | int deltax, deltay; |
527 | if (sp + 4 > *end) |
528 | break; |
529 | deltax = sp[2]; |
530 | deltay = sp[3]; |
531 | dp += deltax + deltay * stride; |
532 | sp += 4; |
533 | x += deltax; |
534 | } |
535 | else if (sp[0] == 0 && sp[1] >= 3) |
536 | { /* absolute */ |
537 | int n = sp[1]; |
538 | int nn = (n + 1) / 2 * 2; |
539 | if (sp + 2 + nn > *end) |
540 | break; |
541 | if (dp + n > ep) { |
542 | fz_warn(ctx, "buffer overflow in bitmap data in bmp image" ); |
543 | break; |
544 | } |
545 | sp += 2; |
546 | for (i = 0; i < n; i++) |
547 | dp[i] = sp[i]; |
548 | dp += n; |
549 | sp += (n + 1) / 2 * 2; |
550 | x += n; |
551 | } |
552 | else |
553 | { /* encoded */ |
554 | int n = sp[0]; |
555 | if (dp + n > ep) { |
556 | fz_warn(ctx, "buffer overflow in bitmap data in bmp image" ); |
557 | break; |
558 | } |
559 | for (i = 0; i < n; i++) |
560 | dp[i] = sp[1]; |
561 | dp += n; |
562 | sp += 2; |
563 | x += n; |
564 | } |
565 | } |
566 | |
567 | if (dp < ep) |
568 | fz_warn(ctx, "premature end of bitmap data in bmp image" ); |
569 | |
570 | info->compression = BI_RGB; |
571 | info->bitcount = 8; |
572 | *end = ep; |
573 | return decompressed; |
574 | } |
575 | |
576 | static unsigned char * |
577 | bmp_decompress_rle4(fz_context *ctx, struct info *info, const unsigned char *p, const unsigned char **end) |
578 | { |
579 | const unsigned char *sp; |
580 | unsigned char *dp, *ep, *decompressed; |
581 | int width = info->width; |
582 | int height = info->height; |
583 | int stride; |
584 | int i, x; |
585 | |
586 | stride = ((width + 1) / 2 + 3) / 4 * 4; |
587 | |
588 | sp = p; |
589 | dp = decompressed = fz_calloc(ctx, height, stride); |
590 | ep = dp + height * stride; |
591 | x = 0; |
592 | |
593 | while (sp + 2 <= *end) |
594 | { |
595 | if (sp[0] == 0 && sp[1] == 0) |
596 | { /* end of line */ |
597 | int xx = x / 2; |
598 | if (xx < stride) |
599 | dp += stride - xx; |
600 | sp += 2; |
601 | x = 0; |
602 | } |
603 | else if (sp[0] == 0 && sp[1] == 1) |
604 | { /* end of bitmap */ |
605 | dp = ep; |
606 | break; |
607 | } |
608 | else if (sp[0] == 0 && sp[1] == 2) |
609 | { /* delta */ |
610 | int deltax, deltay, startlow; |
611 | if (sp + 4 > *end) |
612 | break; |
613 | deltax = sp[2]; |
614 | deltay = sp[3]; |
615 | startlow = x & 1; |
616 | dp += (deltax + startlow) / 2 + deltay * stride; |
617 | sp += 4; |
618 | x += deltax; |
619 | } |
620 | else if (sp[0] == 0 && sp[1] >= 3) |
621 | { /* absolute */ |
622 | int n = sp[1]; |
623 | int nn = ((n + 1) / 2 + 1) / 2 * 2; |
624 | if (sp + 2 + nn > *end) |
625 | break; |
626 | if (dp + n / 2 > ep) { |
627 | fz_warn(ctx, "buffer overflow in bitmap data in bmp image" ); |
628 | break; |
629 | } |
630 | sp += 2; |
631 | for (i = 0; i < n; i++, x++) |
632 | { |
633 | int val = i & 1 ? (sp[i/2]) & 0xF : (sp[i/2] >> 4) & 0xF; |
634 | if (x & 1) |
635 | *dp++ |= val; |
636 | else |
637 | *dp |= val << 4; |
638 | } |
639 | sp += nn; |
640 | } |
641 | else |
642 | { /* encoded */ |
643 | int n = sp[0]; |
644 | int hi = (sp[1] >> 4) & 0xF; |
645 | int lo = sp[1] & 0xF; |
646 | if (dp + n / 2 + (x & 1) > ep) { |
647 | fz_warn(ctx, "buffer overflow in bitmap data in bmp image" ); |
648 | break; |
649 | } |
650 | for (i = 0; i < n; i++, x++) |
651 | { |
652 | int val = i & 1 ? lo : hi; |
653 | if (x & 1) |
654 | *dp++ |= val; |
655 | else |
656 | *dp |= val << 4; |
657 | } |
658 | sp += 2; |
659 | } |
660 | } |
661 | |
662 | info->compression = BI_RGB; |
663 | info->bitcount = 4; |
664 | *end = ep; |
665 | return decompressed; |
666 | } |
667 | |
668 | static fz_pixmap * |
669 | bmp_read_bitmap(fz_context *ctx, struct info *info, const unsigned char *p, const unsigned char *end) |
670 | { |
671 | const int mults[] = { 0, 8191, 2730, 1170, 546, 264, 130, 64 }; |
672 | fz_pixmap *pix; |
673 | const unsigned char *ssp; |
674 | unsigned char *ddp; |
675 | unsigned char *decompressed = NULL; |
676 | int bitcount, width, height; |
677 | int sstride, dstride; |
678 | int rmult, gmult, bmult, amult; |
679 | int rtrunc, gtrunc, btrunc, atrunc; |
680 | int x, y; |
681 | |
682 | if (info->compression == BI_RLE8) |
683 | ssp = decompressed = bmp_decompress_rle8(ctx, info, p, &end); |
684 | else if (info->compression == BI_RLE4) |
685 | ssp = decompressed = bmp_decompress_rle4(ctx, info, p, &end); |
686 | else if (info->compression == BI_RLE24) |
687 | ssp = decompressed = bmp_decompress_rle24(ctx, info, p, &end); |
688 | else |
689 | ssp = p; |
690 | |
691 | bitcount = info->bitcount; |
692 | width = info->width; |
693 | height = info->height; |
694 | |
695 | sstride = ((width * bitcount + 31) / 32) * 4; |
696 | |
697 | if (ssp + sstride * height > end) |
698 | { |
699 | fz_free(ctx, decompressed); |
700 | fz_throw(ctx, FZ_ERROR_GENERIC, "premature end in bitmap data in bmp image" ); |
701 | } |
702 | |
703 | fz_try(ctx) |
704 | pix = fz_new_pixmap(ctx, fz_device_rgb(ctx), width, height, NULL, 1); |
705 | fz_catch(ctx) |
706 | { |
707 | fz_free(ctx, decompressed); |
708 | fz_rethrow(ctx); |
709 | } |
710 | |
711 | ddp = pix->samples; |
712 | dstride = pix->stride; |
713 | if (!info->topdown) |
714 | { |
715 | ddp = pix->samples + (height - 1) * dstride; |
716 | dstride = -dstride; |
717 | } |
718 | |
719 | /* These only apply for components in 16-bit and 32-bit mode |
720 | 1-bit (1 * 8191) / 32 |
721 | 2-bit (3 * 2730) / 32 |
722 | 3-bit (7 * 1170) / 32 |
723 | 4-bit (15 * 546) / 32 |
724 | 5-bit (31 * 264) / 32 |
725 | 6-bit (63 * 130) / 32 |
726 | 7-bit (127 * 64) / 32 |
727 | */ |
728 | rmult = info->rbits < 8 ? mults[info->rbits] : 1; |
729 | gmult = info->gbits < 8 ? mults[info->gbits] : 1; |
730 | bmult = info->bbits < 8 ? mults[info->bbits] : 1; |
731 | amult = info->abits < 8 ? mults[info->abits] : 1; |
732 | rtrunc = info->rbits < 8 ? 5 : (info->rbits - 8); |
733 | gtrunc = info->gbits < 8 ? 5 : (info->gbits - 8); |
734 | btrunc = info->bbits < 8 ? 5 : (info->bbits - 8); |
735 | atrunc = info->abits < 8 ? 5 : (info->abits - 8); |
736 | |
737 | for (y = 0; y < height; y++) |
738 | { |
739 | const unsigned char *sp = ssp + y * sstride; |
740 | unsigned char *dp = ddp + y * dstride; |
741 | |
742 | switch (bitcount) |
743 | { |
744 | case 32: |
745 | for (x = 0; x < width; x++) |
746 | { |
747 | unsigned int sample = (sp[3] << 24) | (sp[2] << 16) | (sp[1] << 8) | sp[0]; |
748 | unsigned int r = (sample & info->rmask) >> info->rshift; |
749 | unsigned int g = (sample & info->gmask) >> info->gshift; |
750 | unsigned int b = (sample & info->bmask) >> info->bshift; |
751 | unsigned int a = info->abits == 0 ? 255 : (sample & info->amask) >> info->ashift; |
752 | *dp++ = (r * rmult) >> rtrunc; |
753 | *dp++ = (g * gmult) >> gtrunc; |
754 | *dp++ = (b * bmult) >> btrunc; |
755 | *dp++ = info->abits == 0 ? a : (a * amult) >> atrunc; |
756 | sp += 4; |
757 | } |
758 | break; |
759 | case 24: |
760 | for (x = 0; x < width; x++) |
761 | { |
762 | *dp++ = sp[2]; |
763 | *dp++ = sp[1]; |
764 | *dp++ = sp[0]; |
765 | *dp++ = 255; |
766 | sp += 3; |
767 | } |
768 | break; |
769 | case 16: |
770 | for (x = 0; x < width; x++) |
771 | { |
772 | unsigned int sample = (sp[1] << 8) | sp[0]; |
773 | unsigned int r = (sample & info->rmask) >> info->rshift; |
774 | unsigned int g = (sample & info->gmask) >> info->gshift; |
775 | unsigned int b = (sample & info->bmask) >> info->bshift; |
776 | unsigned int a = (sample & info->amask) >> info->ashift; |
777 | *dp++ = (r * rmult) >> rtrunc; |
778 | *dp++ = (g * gmult) >> gtrunc; |
779 | *dp++ = (b * bmult) >> btrunc; |
780 | *dp++ = info->abits == 0 ? 255 : (a * amult) >> atrunc; |
781 | sp += 2; |
782 | } |
783 | break; |
784 | case 8: |
785 | for (x = 0; x < width; x++) |
786 | { |
787 | *dp++ = info->palette[3 * sp[0] + 0]; |
788 | *dp++ = info->palette[3 * sp[0] + 1]; |
789 | *dp++ = info->palette[3 * sp[0] + 2]; |
790 | *dp++ = 255; |
791 | sp++; |
792 | } |
793 | break; |
794 | case 4: |
795 | for (x = 0; x < width; x++) |
796 | { |
797 | int idx; |
798 | switch (x & 1) |
799 | { |
800 | case 0: idx = (sp[0] >> 4) & 0x0f; break; |
801 | case 1: idx = (sp[0] >> 0) & 0x0f; sp++; break; |
802 | } |
803 | *dp++ = info->palette[3 * idx + 0]; |
804 | *dp++ = info->palette[3 * idx + 1]; |
805 | *dp++ = info->palette[3 * idx + 2]; |
806 | *dp++ = 255; |
807 | } |
808 | break; |
809 | case 2: |
810 | for (x = 0; x < width; x++) |
811 | { |
812 | int idx; |
813 | switch (x & 3) |
814 | { |
815 | case 0: idx = (sp[0] >> 6) & 0x03; break; |
816 | case 1: idx = (sp[0] >> 4) & 0x03; break; |
817 | case 2: idx = (sp[0] >> 2) & 0x03; break; |
818 | case 3: idx = (sp[0] >> 0) & 0x03; sp++; break; |
819 | } |
820 | *dp++ = info->palette[3 * idx + 0]; |
821 | *dp++ = info->palette[3 * idx + 1]; |
822 | *dp++ = info->palette[3 * idx + 2]; |
823 | *dp++ = 255; |
824 | } |
825 | break; |
826 | case 1: |
827 | for (x = 0; x < width; x++) |
828 | { |
829 | int idx; |
830 | switch (x & 7) |
831 | { |
832 | case 0: idx = (sp[0] >> 7) & 0x01; break; |
833 | case 1: idx = (sp[0] >> 6) & 0x01; break; |
834 | case 2: idx = (sp[0] >> 5) & 0x01; break; |
835 | case 3: idx = (sp[0] >> 4) & 0x01; break; |
836 | case 4: idx = (sp[0] >> 3) & 0x01; break; |
837 | case 5: idx = (sp[0] >> 2) & 0x01; break; |
838 | case 6: idx = (sp[0] >> 1) & 0x01; break; |
839 | case 7: idx = (sp[0] >> 0) & 0x01; sp++; break; |
840 | } |
841 | *dp++ = info->palette[3 * idx + 0]; |
842 | *dp++ = info->palette[3 * idx + 1]; |
843 | *dp++ = info->palette[3 * idx + 2]; |
844 | *dp++ = 255; |
845 | } |
846 | break; |
847 | } |
848 | } |
849 | |
850 | fz_free(ctx, decompressed); |
851 | fz_premultiply_pixmap(ctx, pix); |
852 | return pix; |
853 | } |
854 | |
855 | static fz_pixmap * |
856 | bmp_read_image(fz_context *ctx, struct info *info, const unsigned char *p, size_t total, int only_metadata) |
857 | { |
858 | const unsigned char *begin = p; |
859 | const unsigned char *end = p + total; |
860 | int size; |
861 | |
862 | memset(info, 0x00, sizeof (*info)); |
863 | |
864 | p = bmp_read_file_header(ctx, info, p, end); |
865 | |
866 | info->filesize = fz_mini(info->filesize, (int)total); |
867 | |
868 | if (end - p < 4) |
869 | fz_throw(ctx, FZ_ERROR_GENERIC, "premature end in bitmap core header in bmp image" ); |
870 | size = read32(p + 0); |
871 | |
872 | if (size == 12) |
873 | p = bmp_read_bitmap_core_header(ctx, info, p, end); |
874 | else if (size == 40 || size == 52 || size == 56 || size == 108 || size == 124) |
875 | { |
876 | p = bmp_read_bitmap_info_header(ctx, info, p, end); |
877 | if (info->extramasks) |
878 | p = bmp_read_extra_masks(ctx, info, p, end); |
879 | } |
880 | else if (size == 16 || size == 64) |
881 | p = bmp_read_bitmap_os2_header(ctx, info, p, end); |
882 | else |
883 | fz_throw(ctx, FZ_ERROR_GENERIC, "invalid header size (%d) in bmp image" , size); |
884 | |
885 | maskinfo(info->rmask, &info->rshift, &info->rbits); |
886 | maskinfo(info->gmask, &info->gshift, &info->gbits); |
887 | maskinfo(info->bmask, &info->bshift, &info->bbits); |
888 | maskinfo(info->amask, &info->ashift, &info->abits); |
889 | |
890 | if (info->width <= 0 || info->width > SHRT_MAX || info->height <= 0 || info->height > SHRT_MAX) |
891 | fz_throw(ctx, FZ_ERROR_GENERIC, "dimensions (%d x %d) out of range in bmp image" , |
892 | info->width, info->height); |
893 | if (info->compression != BI_RGB && info->compression != BI_RLE8 && |
894 | info->compression != BI_RLE4 && info->compression != BI_BITFIELDS && |
895 | info->compression != BI_JPEG && info->compression != BI_PNG && |
896 | info->compression != BI_ALPHABITS && info->compression != BI_RLE24) |
897 | fz_throw(ctx, FZ_ERROR_GENERIC, "unsupported compression method (%d) in bmp image" , info->compression); |
898 | if ((info->compression == BI_RGB && info->bitcount != 1 && |
899 | info->bitcount != 2 && info->bitcount != 4 && |
900 | info->bitcount != 8 && info->bitcount != 16 && |
901 | info->bitcount != 24 && info->bitcount != 32) || |
902 | (info->compression == BI_RLE8 && info->bitcount != 8) || |
903 | (info->compression == BI_RLE4 && info->bitcount != 4) || |
904 | (info->compression == BI_BITFIELDS && info->bitcount != 16 && info->bitcount != 32) || |
905 | (info->compression == BI_JPEG && info->bitcount != 0) || |
906 | (info->compression == BI_PNG && info->bitcount != 0) || |
907 | (info->compression == BI_ALPHABITS && info->bitcount != 16 && info->bitcount != 32) || |
908 | (info->compression == BI_RLE24 && info->bitcount != 24)) |
909 | fz_throw(ctx, FZ_ERROR_GENERIC, "invalid bits per pixel (%d) for compression (%d) in bmp image" , |
910 | info->bitcount, info->compression); |
911 | if (info->rbits < 0 || info->rbits > info->bitcount) |
912 | fz_throw(ctx, FZ_ERROR_GENERIC, "unsupported %d bit red mask in bmp image" , info->rbits); |
913 | if (info->gbits < 0 || info->gbits > info->bitcount) |
914 | fz_throw(ctx, FZ_ERROR_GENERIC, "unsupported %d bit green mask in bmp image" , info->gbits); |
915 | if (info->bbits < 0 || info->bbits > info->bitcount) |
916 | fz_throw(ctx, FZ_ERROR_GENERIC, "unsupported %d bit blue mask in bmp image" , info->bbits); |
917 | if (info->abits < 0 || info->abits > info->bitcount) |
918 | fz_throw(ctx, FZ_ERROR_GENERIC, "unsupported %d bit alpha mask in bmp image" , info->abits); |
919 | |
920 | if (only_metadata) |
921 | return NULL; |
922 | |
923 | if (info->compression == BI_JPEG) |
924 | { |
925 | if (p - begin < info->offset) |
926 | p = begin + info->offset; |
927 | return fz_load_jpeg(ctx, p, end - p); |
928 | } |
929 | else if (info->compression == BI_PNG) |
930 | { |
931 | if (p - begin < info->offset) |
932 | p = begin + info->offset; |
933 | return fz_load_png(ctx, p, end - p); |
934 | } |
935 | else |
936 | { |
937 | const unsigned char *color_table_end = begin + info->offset; |
938 | if (end - begin < info->offset) |
939 | color_table_end = end; |
940 | p = bmp_read_color_table(ctx, info, p, color_table_end); |
941 | |
942 | if (p - begin < info->offset) |
943 | p = begin + info->offset; |
944 | return bmp_read_bitmap(ctx, info, p, end); |
945 | } |
946 | } |
947 | |
948 | fz_pixmap * |
949 | fz_load_bmp(fz_context *ctx, const unsigned char *p, size_t total) |
950 | { |
951 | struct info bmp; |
952 | fz_pixmap *image; |
953 | |
954 | image = bmp_read_image(ctx, &bmp, p, total, 0); |
955 | image->xres = bmp.xres / (1000.0f / 25.4f); |
956 | image->yres = bmp.yres / (1000.0f / 25.4f); |
957 | |
958 | return image; |
959 | } |
960 | |
961 | void |
962 | 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) |
963 | { |
964 | struct info bmp; |
965 | |
966 | bmp_read_image(ctx, &bmp, p, total, 1); |
967 | |
968 | *cspacep = fz_keep_colorspace(ctx, fz_device_rgb(ctx)); |
969 | *wp = bmp.width; |
970 | *hp = bmp.height; |
971 | *xresp = bmp.xres / (1000.0f / 25.4f); |
972 | *yresp = bmp.yres / (1000.0f / 25.4f); |
973 | } |
974 | |