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