* grub-core/video/readers/png.c: Support paletted images and clean up
greyscale support.
This commit is contained in:
parent
e84f818865
commit
fa31ee9c2c
2 changed files with 126 additions and 103 deletions
|
@ -1,3 +1,8 @@
|
||||||
|
2013-09-28 Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
|
||||||
|
* grub-core/video/readers/png.c: Support paletted images and clean up
|
||||||
|
greyscale support.
|
||||||
|
|
||||||
2013-09-28 Vladimir Serbinenko <phcoder@gmail.com>
|
2013-09-28 Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
|
||||||
* grub-core/term/terminfo.c (grub_terminfo_readkey): Fix
|
* grub-core/term/terminfo.c (grub_terminfo_readkey): Fix
|
||||||
|
|
|
@ -52,9 +52,13 @@ enum
|
||||||
#define PNG_FILTER_VALUE_PAETH 4
|
#define PNG_FILTER_VALUE_PAETH 4
|
||||||
#define PNG_FILTER_VALUE_LAST 5
|
#define PNG_FILTER_VALUE_LAST 5
|
||||||
|
|
||||||
#define PNG_CHUNK_IHDR 0x49484452
|
enum
|
||||||
#define PNG_CHUNK_IDAT 0x49444154
|
{
|
||||||
#define PNG_CHUNK_IEND 0x49454e44
|
PNG_CHUNK_IHDR = 0x49484452,
|
||||||
|
PNG_CHUNK_IDAT = 0x49444154,
|
||||||
|
PNG_CHUNK_IEND = 0x49454e44,
|
||||||
|
PNG_CHUNK_PLTE = 0x504c5445
|
||||||
|
};
|
||||||
|
|
||||||
#define Z_DEFLATED 8
|
#define Z_DEFLATED 8
|
||||||
#define Z_FLAG_DICT 32
|
#define Z_FLAG_DICT 32
|
||||||
|
@ -94,7 +98,7 @@ struct grub_png_data
|
||||||
grub_uint32_t next_offset;
|
grub_uint32_t next_offset;
|
||||||
|
|
||||||
int image_width, image_height, bpp, is_16bit;
|
int image_width, image_height, bpp, is_16bit;
|
||||||
int raw_bytes, is_gray, is_alpha;
|
int raw_bytes, is_gray, is_alpha, is_palette;
|
||||||
grub_uint8_t *image_data;
|
grub_uint8_t *image_data;
|
||||||
|
|
||||||
int inside_idat, idat_remain;
|
int inside_idat, idat_remain;
|
||||||
|
@ -107,6 +111,8 @@ struct grub_png_data
|
||||||
int dist_maxval[DEFLATE_HUFF_LEN];
|
int dist_maxval[DEFLATE_HUFF_LEN];
|
||||||
int dist_offset[DEFLATE_HUFF_LEN];
|
int dist_offset[DEFLATE_HUFF_LEN];
|
||||||
|
|
||||||
|
grub_uint8_t palette[256][3];
|
||||||
|
|
||||||
struct huff_table code_table;
|
struct huff_table code_table;
|
||||||
struct huff_table dist_table;
|
struct huff_table dist_table;
|
||||||
|
|
||||||
|
@ -213,6 +219,26 @@ grub_png_get_bits (struct grub_png_data *data, int num)
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
grub_png_decode_image_palette (struct grub_png_data *data,
|
||||||
|
unsigned len)
|
||||||
|
{
|
||||||
|
unsigned i = 0, j;
|
||||||
|
|
||||||
|
if (len == 0 || len % 3 != 0)
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
|
||||||
|
for (i = 0; 3 * i < len && i < 256; i++)
|
||||||
|
for (j = 0; j < 3; j++)
|
||||||
|
data->palette[i][j] = grub_png_get_byte (data);
|
||||||
|
for (i *= 3; i < len; i++)
|
||||||
|
grub_png_get_byte (data);
|
||||||
|
|
||||||
|
grub_png_get_dword (data);
|
||||||
|
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_png_decode_image_header (struct grub_png_data *data)
|
grub_png_decode_image_header (struct grub_png_data *data)
|
||||||
{
|
{
|
||||||
|
@ -233,14 +259,23 @@ grub_png_decode_image_header (struct grub_png_data *data)
|
||||||
data->is_16bit = (color_bits == 16);
|
data->is_16bit = (color_bits == 16);
|
||||||
|
|
||||||
color_type = grub_png_get_byte (data);
|
color_type = grub_png_get_byte (data);
|
||||||
if (color_type & ~(PNG_COLOR_MASK_ALPHA | PNG_COLOR_MASK_COLOR))
|
/* According to PNG spec, no other types are valid. */
|
||||||
|
if ((color_type & ~(PNG_COLOR_MASK_ALPHA | PNG_COLOR_MASK_COLOR))
|
||||||
|
&& (color_type != PNG_COLOR_TYPE_PALETTE))
|
||||||
|
return grub_error (GRUB_ERR_BAD_FILE_TYPE,
|
||||||
|
"png: color type not supported");
|
||||||
|
if (color_type == PNG_COLOR_TYPE_PALETTE)
|
||||||
|
data->is_palette = 1;
|
||||||
|
if (data->is_16bit && data->is_palette)
|
||||||
return grub_error (GRUB_ERR_BAD_FILE_TYPE,
|
return grub_error (GRUB_ERR_BAD_FILE_TYPE,
|
||||||
"png: color type not supported");
|
"png: color type not supported");
|
||||||
if (color_type & PNG_COLOR_MASK_ALPHA)
|
if (color_type & PNG_COLOR_MASK_ALPHA)
|
||||||
blt = GRUB_VIDEO_BLIT_FORMAT_RGBA_8888;
|
blt = GRUB_VIDEO_BLIT_FORMAT_RGBA_8888;
|
||||||
else
|
else
|
||||||
blt = GRUB_VIDEO_BLIT_FORMAT_RGB_888;
|
blt = GRUB_VIDEO_BLIT_FORMAT_RGB_888;
|
||||||
if (color_type & PNG_COLOR_MASK_COLOR)
|
if (data->is_palette)
|
||||||
|
data->bpp = 1;
|
||||||
|
else if (color_type & PNG_COLOR_MASK_COLOR)
|
||||||
data->bpp = 3;
|
data->bpp = 3;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -260,7 +295,7 @@ grub_png_decode_image_header (struct grub_png_data *data)
|
||||||
data->bpp <<= 1;
|
data->bpp <<= 1;
|
||||||
|
|
||||||
#ifndef GRUB_CPU_WORDS_BIGENDIAN
|
#ifndef GRUB_CPU_WORDS_BIGENDIAN
|
||||||
if (data->is_16bit || !(color_type & PNG_COLOR_MASK_COLOR))
|
if (data->is_16bit || data->is_gray || data->is_palette)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
data->image_data = grub_malloc (data->image_height *
|
data->image_data = grub_malloc (data->image_height *
|
||||||
|
@ -278,7 +313,7 @@ grub_png_decode_image_header (struct grub_png_data *data)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
data->raw_bytes = data->image_height * (data->image_width * data->bpp + 1)
|
data->raw_bytes = data->image_height * (data->image_width * data->bpp + 1);
|
||||||
|
|
||||||
data->cur_column = 0;
|
data->cur_column = 0;
|
||||||
data->first_line = 1;
|
data->first_line = 1;
|
||||||
|
@ -783,15 +818,35 @@ grub_png_convert_image (struct grub_png_data *data)
|
||||||
d1 = (*data->bitmap)->data;
|
d1 = (*data->bitmap)->data;
|
||||||
d2 = data->image_data + data->is_16bit;
|
d2 = data->image_data + data->is_16bit;
|
||||||
|
|
||||||
/* Only copy the upper 8 bit. */
|
|
||||||
#ifndef GRUB_CPU_WORDS_BIGENDIAN
|
#ifndef GRUB_CPU_WORDS_BIGENDIAN
|
||||||
if (!data->is_gray)
|
#define R4 3
|
||||||
|
#define G4 2
|
||||||
|
#define B4 1
|
||||||
|
#define A4 0
|
||||||
|
#define R3 2
|
||||||
|
#define G3 1
|
||||||
|
#define B3 0
|
||||||
|
#else
|
||||||
|
#define R4 0
|
||||||
|
#define G4 1
|
||||||
|
#define B4 2
|
||||||
|
#define A4 3
|
||||||
|
#define R3 0
|
||||||
|
#define G3 1
|
||||||
|
#define B3 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (data->is_palette)
|
||||||
{
|
{
|
||||||
for (i = 0; i < (data->image_width * data->image_height * data->bpp >> 1);
|
for (i = 0; i < (data->image_width * data->image_height);
|
||||||
i++, d1++, d2 += 2)
|
i++, d1 += 3, d2++)
|
||||||
*d1 = *d2;
|
{
|
||||||
|
d1[R3] = data->palette[d2[0]][2];
|
||||||
|
d1[G3] = data->palette[d2[0]][1];
|
||||||
|
d1[B3] = data->palette[d2[0]][0];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else if (data->is_gray)
|
||||||
{
|
{
|
||||||
switch (data->bpp)
|
switch (data->bpp)
|
||||||
{
|
{
|
||||||
|
@ -800,10 +855,10 @@ grub_png_convert_image (struct grub_png_data *data)
|
||||||
for (i = 0; i < (data->image_width * data->image_height);
|
for (i = 0; i < (data->image_width * data->image_height);
|
||||||
i++, d1 += 4, d2 += 4)
|
i++, d1 += 4, d2 += 4)
|
||||||
{
|
{
|
||||||
d1[3] = d2[3];
|
d1[R4] = d2[3];
|
||||||
d1[1] = d2[3];
|
d1[G4] = d2[3];
|
||||||
d1[2] = d2[3];
|
d1[B4] = d2[3];
|
||||||
d1[0] = d2[1];
|
d1[A4] = d2[1];
|
||||||
}
|
}
|
||||||
case 2:
|
case 2:
|
||||||
if (data->is_16bit)
|
if (data->is_16bit)
|
||||||
|
@ -812,9 +867,9 @@ grub_png_convert_image (struct grub_png_data *data)
|
||||||
for (i = 0; i < (data->image_width * data->image_height);
|
for (i = 0; i < (data->image_width * data->image_height);
|
||||||
i++, d1 += 4, d2 += 2)
|
i++, d1 += 4, d2 += 2)
|
||||||
{
|
{
|
||||||
d1[0] = d2[1];
|
d1[R3] = d2[1];
|
||||||
d1[1] = d2[1];
|
d1[G3] = d2[1];
|
||||||
d1[2] = d2[1];
|
d1[B3] = d2[1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -823,10 +878,10 @@ grub_png_convert_image (struct grub_png_data *data)
|
||||||
for (i = 0; i < (data->image_width * data->image_height);
|
for (i = 0; i < (data->image_width * data->image_height);
|
||||||
i++, d1 += 4, d2 += 2)
|
i++, d1 += 4, d2 += 2)
|
||||||
{
|
{
|
||||||
d1[3] = d2[1];
|
d1[R4] = d2[1];
|
||||||
d1[1] = d2[1];
|
d1[G4] = d2[1];
|
||||||
d1[2] = d2[1];
|
d1[B4] = d2[1];
|
||||||
d1[0] = d2[0];
|
d1[A4] = d2[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -835,52 +890,45 @@ grub_png_convert_image (struct grub_png_data *data)
|
||||||
for (i = 0; i < (data->image_width * data->image_height);
|
for (i = 0; i < (data->image_width * data->image_height);
|
||||||
i++, d1 += 3, d2++)
|
i++, d1 += 3, d2++)
|
||||||
{
|
{
|
||||||
d1[0] = d2[0];
|
d1[R3] = d2[0];
|
||||||
d1[1] = d2[0];
|
d1[G3] = d2[0];
|
||||||
d1[2] = d2[0];
|
d1[B3] = d2[0];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
else
|
||||||
switch (data->bpp)
|
|
||||||
{
|
{
|
||||||
/* 16-bit with alpha. */
|
/* Only copy the upper 8 bit. */
|
||||||
case 8:
|
#ifndef GRUB_CPU_WORDS_BIGENDIAN
|
||||||
for (i = 0; i < (data->image_width * data->image_height);
|
for (i = 0; i < (data->image_width * data->image_height * data->bpp >> 1);
|
||||||
i++, d1 += 4, d2+=8)
|
i++, d1++, d2 += 2)
|
||||||
|
*d1 = *d2;
|
||||||
|
#else
|
||||||
|
switch (data->bpp)
|
||||||
{
|
{
|
||||||
d1[0] = d2[7];
|
/* 16-bit with alpha. */
|
||||||
d1[1] = d2[5];
|
case 8:
|
||||||
d1[2] = d2[3];
|
|
||||||
d1[3] = d2[1];
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
/* 16-bit without alpha. */
|
|
||||||
case 6:
|
|
||||||
for (i = 0; i < (data->image_width * data->image_height);
|
|
||||||
i++, d1 += 3, d2+=6)
|
|
||||||
{
|
|
||||||
d1[0] = d2[5];
|
|
||||||
d1[1] = d2[3];
|
|
||||||
d1[2] = d2[1];
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
if (data->is_16bit)
|
|
||||||
{
|
|
||||||
/* 16-bit gray with alpha. */
|
|
||||||
for (i = 0; i < (data->image_width * data->image_height);
|
for (i = 0; i < (data->image_width * data->image_height);
|
||||||
i++, d1 += 4, d2 += 4)
|
i++, d1 += 4, d2+=8)
|
||||||
{
|
{
|
||||||
d1[0] = d2[3];
|
d1[0] = d2[7];
|
||||||
d1[1] = d2[3];
|
d1[1] = d2[5];
|
||||||
d1[2] = d2[3];
|
d1[2] = d2[3];
|
||||||
d1[3] = d2[1];
|
d1[3] = d2[1];
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
else
|
/* 16-bit without alpha. */
|
||||||
{
|
case 6:
|
||||||
|
for (i = 0; i < (data->image_width * data->image_height);
|
||||||
|
i++, d1 += 3, d2+=6)
|
||||||
|
{
|
||||||
|
d1[0] = d2[5];
|
||||||
|
d1[1] = d2[3];
|
||||||
|
d1[2] = d2[1];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
/* 8-bit with alpha. */
|
/* 8-bit with alpha. */
|
||||||
for (i = 0; i < (data->image_width * data->image_height);
|
for (i = 0; i < (data->image_width * data->image_height);
|
||||||
i++, d1 += 4, d2 += 4)
|
i++, d1 += 4, d2 += 4)
|
||||||
|
@ -890,55 +938,21 @@ grub_png_convert_image (struct grub_png_data *data)
|
||||||
d1[2] = d2[1];
|
d1[2] = d2[1];
|
||||||
d1[3] = d2[0];
|
d1[3] = d2[0];
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
break;
|
/* 8-bit without alpha. */
|
||||||
/* 8-bit without alpha. */
|
case 3:
|
||||||
case 3:
|
|
||||||
for (i = 0; i < (data->image_width * data->image_height);
|
|
||||||
i++, d1 += 3, d2 += 3)
|
|
||||||
{
|
|
||||||
d1[0] = d2[2];
|
|
||||||
d1[1] = d2[1];
|
|
||||||
d1[2] = d2[0];
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
if (data->is_16bit)
|
|
||||||
/* 16-bit gray without alpha. */
|
|
||||||
{
|
|
||||||
for (i = 0; i < (data->image_width * data->image_height);
|
for (i = 0; i < (data->image_width * data->image_height);
|
||||||
i++, d1 += 4, d2 += 2)
|
i++, d1 += 3, d2 += 3)
|
||||||
{
|
{
|
||||||
d1[0] = d2[1];
|
d1[0] = d2[2];
|
||||||
d1[1] = d2[1];
|
d1[1] = d2[1];
|
||||||
d1[2] = d2[1];
|
d1[2] = d2[0];
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
/* 8-bit gray with alpha. */
|
|
||||||
{
|
|
||||||
for (i = 0; i < (data->image_width * data->image_height);
|
|
||||||
i++, d1 += 4, d2 += 2)
|
|
||||||
{
|
|
||||||
d1[0] = d2[1];
|
|
||||||
d1[1] = d2[1];
|
|
||||||
d1[2] = d2[1];
|
|
||||||
d1[3] = d2[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
/* 8-bit gray without alpha. */
|
|
||||||
case 1:
|
|
||||||
for (i = 0; i < (data->image_width * data->image_height);
|
|
||||||
i++, d1 += 3, d2++)
|
|
||||||
{
|
|
||||||
d1[0] = d2[0];
|
|
||||||
d1[1] = d2[0];
|
|
||||||
d1[2] = d2[0];
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
|
@ -966,6 +980,10 @@ grub_png_decode_png (struct grub_png_data *data)
|
||||||
grub_png_decode_image_header (data);
|
grub_png_decode_image_header (data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PNG_CHUNK_PLTE:
|
||||||
|
grub_png_decode_image_palette (data, len);
|
||||||
|
break;
|
||||||
|
|
||||||
case PNG_CHUNK_IDAT:
|
case PNG_CHUNK_IDAT:
|
||||||
data->inside_idat = 1;
|
data->inside_idat = 1;
|
||||||
data->idat_remain = len;
|
data->idat_remain = len;
|
||||||
|
|
Loading…
Reference in a new issue