From 6b2506eac65a7fb593146aa4044f7171615fd62f Mon Sep 17 00:00:00 2001 From: Sebastian Rasmussen Date: Fri, 25 Mar 2016 10:52:35 +0100 Subject: bmp: Improve fallback handling of palette color entries. * Use a better 4-bit fallback palette (use vga palette as indicated by variable name instead of 16 color web palette) * Determine if existing palette entries are grayscale and if so use a grayscale palette instead of the vga or web palette * Extend the web palette with black entries to make it eaiser to copy from. --- source/fitz/load-bmp.c | 92 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 67 insertions(+), 25 deletions(-) (limited to 'source/fitz/load-bmp.c') 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; -- cgit v1.2.3