| 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 |  | 
|---|