summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/fitz/load-bmp.c92
1 files changed, 67 insertions, 25 deletions
diff --git a/source/fitz/load-bmp.c b/source/fitz/load-bmp.c
index 3eda1614..8b084638 100644
--- a/source/fitz/load-bmp.c
+++ b/source/fitz/load-bmp.c
@@ -37,15 +37,20 @@ static const unsigned char web_palette[] = {
0x00, 0xFF, 0x99, 0x33, 0xFF, 0x99, 0x66, 0xFF, 0x99, 0x99, 0xFF, 0x99, 0xCC, 0xFF, 0x99, 0xFF, 0xFF, 0x99,
0x00, 0xFF, 0xCC, 0x33, 0xFF, 0xCC, 0x66, 0xFF, 0xCC, 0x99, 0xFF, 0xCC, 0xCC, 0xFF, 0xCC, 0xFF, 0xFF, 0xCC,
0x00, 0xFF, 0xFF, 0x33, 0xFF, 0xFF, 0x66, 0xFF, 0xFF, 0x99, 0xFF, 0xFF, 0xCC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
static const unsigned char vga_palette[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0xFF, 0x00,
- 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0xFF,
- 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x80, 0x00,
- 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0x00, 0x80,
- 0x80, 0x80, 0x00, 0xC0, 0xC0, 0xC0, 0x80, 0x80, 0x80,
- 0x00, 0x00, 0xFF,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xAA, 0x00, 0xAA, 0x00, 0x00, 0xAA, 0xAA,
+ 0xAA, 0x00, 0x00, 0xAA, 0x00, 0xAA, 0xAA, 0x55, 0x00, 0xAA, 0xAA, 0xAA,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0xFF, 0x55, 0xFF, 0x55, 0x55, 0xFF, 0xFF,
+ 0xFF, 0x55, 0x55, 0xFF, 0x55, 0xFF, 0xFF, 0xFF, 0x55, 0xFF, 0xFF, 0xFF,
};
static const unsigned char gray_palette[] = {
@@ -257,13 +262,54 @@ bmp_read_extra_masks(fz_context *ctx, struct info *info, unsigned char *p, unsig
return p + 12;
}
+static int
+bmp_palette_is_gray(fz_context *ctx, struct info *info, int readcolors)
+{
+ int i;
+ for (i = 0; i < readcolors; i++)
+ {
+ int rgdiff = fz_absi(info->palette[3 * i + 0] - info->palette[3 * i + 1]);
+ int gbdiff = fz_absi(info->palette[3 * i + 1] - info->palette[3 * i + 2]);
+ int rbdiff = fz_absi(info->palette[3 * i + 0] - info->palette[3 * i + 2]);
+ if (rgdiff > 2 || gbdiff > 2 || rbdiff > 2)
+ return 0;
+ }
+ return 1;
+}
+
static void
-bmp_load_default_palette(fz_context *ctx, struct info *info)
+bmp_load_default_palette(fz_context *ctx, struct info *info, int readcolors)
{
+ int i;
+
+ fz_warn(ctx, "color table too short; loading default palette");
+
if (info->bitcount == 8)
- memcpy(info->palette, web_palette, sizeof(web_palette));
+ {
+ if (!bmp_palette_is_gray(ctx, info, readcolors))
+ memcpy(&info->palette[readcolors * 3], &web_palette[readcolors * 3],
+ sizeof(web_palette) - readcolors * 3);
+ else
+ for (i = readcolors; i < 256; i++)
+ {
+ info->palette[3 * i + 0] = i;
+ info->palette[3 * i + 1] = i;
+ info->palette[3 * i + 2] = i;
+ }
+ }
else if (info->bitcount == 4)
- memcpy(info->palette, vga_palette, sizeof(vga_palette));
+ {
+ if (!bmp_palette_is_gray(ctx, info, readcolors))
+ memcpy(&info->palette[readcolors * 3], &vga_palette[readcolors * 3],
+ sizeof(vga_palette) - readcolors * 3);
+ else
+ for (i = readcolors; i < 16; i++)
+ {
+ info->palette[3 * i + 0] = (i << 4) | i;
+ info->palette[3 * i + 1] = (i << 4) | i;
+ info->palette[3 * i + 2] = (i << 4) | i;
+ }
+ }
else if (info->bitcount == 2)
memcpy(info->palette, gray_palette, sizeof(gray_palette));
else if (info->bitcount == 1)
@@ -273,7 +319,7 @@ bmp_load_default_palette(fz_context *ctx, struct info *info)
static unsigned char *
bmp_read_color_table(fz_context *ctx, struct info *info, unsigned char *p, unsigned char *end)
{
- int i, colors;
+ int i, colors, readcolors;
if (info->bitcount > 8)
return p;
@@ -287,34 +333,30 @@ bmp_read_color_table(fz_context *ctx, struct info *info, unsigned char *p, unsig
if (info->palettetype == 0)
{
- if (end - p < colors * 3) {
- fz_warn(ctx, "color table too short; loading default palette");
- bmp_load_default_palette(ctx, info);
- colors = (end - p) / 3;
- }
- for (i = 0; i < colors; i++)
+ readcolors = fz_mini(colors, (end - p) / 3);
+ for (i = 0; i < readcolors; i++)
{
info->palette[3 * i + 0] = read8(p + i * 3 + 2);
info->palette[3 * i + 1] = read8(p + i * 3 + 1);
info->palette[3 * i + 2] = read8(p + i * 3 + 0);
}
- return p + colors * 3;
+ if (readcolors < colors)
+ bmp_load_default_palette(ctx, info, readcolors);
+ return p + readcolors * 3;
}
else
{
- if (end - p < colors * 4) {
- fz_warn(ctx, "color table too short; loading default palette");
- bmp_load_default_palette(ctx, info);
- colors = (end - p) / 4;
- }
- for (i = 0; i < colors; i++)
+ readcolors = fz_mini(colors, (end - p) / 4);
+ for (i = 0; i < readcolors; i++)
{
+ /* ignore alpha channel */
info->palette[3 * i + 0] = read8(p + i * 4 + 2);
info->palette[3 * i + 1] = read8(p + i * 4 + 1);
info->palette[3 * i + 2] = read8(p + i * 4 + 0);
- /* ignore alpha channel */
}
- return p + colors * 4;
+ if (readcolors < colors)
+ bmp_load_default_palette(ctx, info, readcolors);
+ return p + readcolors * 4;
}
return p;