* grub-core/video/readers/png.c: Support grayscale

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2013-09-27 12:04:09 +02:00
parent e9c492a02e
commit 3ccf16dff9
2 changed files with 154 additions and 44 deletions

View file

@ -1,8 +1,12 @@
2013-09-24 Vladimir Serbinenko <phcoder@gmail.com> 2013-09-27 Vladimir Serbinenko <phcoder@gmail.com>
* grub-core/video/readers/png.c: Support grayscale
2013-09-27 Vladimir Serbinenko <phcoder@gmail.com>
* grub-core/video/readers/jpeg.c: Support grayscale. * grub-core/video/readers/jpeg.c: Support grayscale.
2013-09-24 Jon McCune <jonmccune@google.com> 2013-09-26 Jon McCune <jonmccune@google.com>
* grub-core/commands/loadenv.c: Support skipping signature check * grub-core/commands/loadenv.c: Support skipping signature check
and variable names filtering. and variable names filtering.

View file

@ -29,15 +29,14 @@ GRUB_MOD_LICENSE ("GPLv3+");
/* Uncomment following define to enable PNG debug. */ /* Uncomment following define to enable PNG debug. */
//#define PNG_DEBUG //#define PNG_DEBUG
#define PNG_COLOR_MASK_PALETTE 1 enum
#define PNG_COLOR_MASK_COLOR 2 {
#define PNG_COLOR_MASK_ALPHA 4 PNG_COLOR_TYPE_GRAY = 0,
PNG_COLOR_MASK_PALETTE = 1,
#define PNG_COLOR_TYPE_GRAY 0 PNG_COLOR_MASK_COLOR = 2,
#define PNG_COLOR_TYPE_PALETTE (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE) PNG_COLOR_MASK_ALPHA = 4,
#define PNG_COLOR_TYPE_RGB (PNG_COLOR_MASK_COLOR) PNG_COLOR_TYPE_PALETTE = (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE),
#define PNG_COLOR_TYPE_RGBA (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_ALPHA) };
#define PNG_COLOR_TYPE_GRAYA (PNG_COLOR_MASK_ALPHA)
#define PNG_COMPRESSION_BASE 0 #define PNG_COMPRESSION_BASE 0
@ -94,7 +93,8 @@ struct grub_png_data
grub_uint32_t next_offset; grub_uint32_t next_offset;
int image_width, image_height, bpp, is_16bit, raw_bytes; int image_width, image_height, bpp, is_16bit;
int raw_bytes, is_gray, is_alpha;
grub_uint8_t *image_data; grub_uint8_t *image_data;
int inside_idat, idat_remain; int inside_idat, idat_remain;
@ -218,6 +218,7 @@ grub_png_decode_image_header (struct grub_png_data *data)
{ {
int color_type; int color_type;
int color_bits; int color_bits;
enum grub_video_blit_format blt;
data->image_width = grub_png_get_dword (data); data->image_width = grub_png_get_dword (data);
data->image_height = grub_png_get_dword (data); data->image_height = grub_png_get_dword (data);
@ -232,31 +233,34 @@ 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_TYPE_RGB) if (color_type & ~(PNG_COLOR_MASK_ALPHA | PNG_COLOR_MASK_COLOR))
{
if (grub_video_bitmap_create (data->bitmap, data->image_width,
data->image_height,
GRUB_VIDEO_BLIT_FORMAT_RGB_888))
return grub_errno;
data->bpp = 3;
}
else if (color_type == PNG_COLOR_TYPE_RGBA)
{
if (grub_video_bitmap_create (data->bitmap, data->image_width,
data->image_height,
GRUB_VIDEO_BLIT_FORMAT_RGBA_8888))
return grub_errno;
data->bpp = 4;
}
else
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)
blt = GRUB_VIDEO_BLIT_FORMAT_RGBA_8888;
else
blt = GRUB_VIDEO_BLIT_FORMAT_RGB_888;
if (color_type & PNG_COLOR_MASK_COLOR)
data->bpp = 3;
else
{
data->is_gray = 1;
data->bpp = 1;
}
if (color_type & PNG_COLOR_MASK_ALPHA)
data->bpp++;
if (grub_video_bitmap_create (data->bitmap, data->image_width,
data->image_height,
blt))
return grub_errno;
if (data->is_16bit) if (data->is_16bit)
data->bpp <<= 1; data->bpp <<= 1;
#ifndef GRUB_CPU_WORDS_BIGENDIAN #ifndef GRUB_CPU_WORDS_BIGENDIAN
if (data->is_16bit) if (data->is_16bit || !(color_type & PNG_COLOR_MASK_COLOR))
#endif #endif
{ {
data->image_data = grub_malloc (data->image_height * data->image_data = grub_malloc (data->image_height *
@ -781,9 +785,63 @@ grub_png_convert_image (struct grub_png_data *data)
/* Only copy the upper 8 bit. */ /* Only copy the upper 8 bit. */
#ifndef GRUB_CPU_WORDS_BIGENDIAN #ifndef GRUB_CPU_WORDS_BIGENDIAN
for (i = 0; i < (data->image_width * data->image_height * data->bpp >> 1); if (!data->is_gray)
i++, d1++, d2+=2) {
*d1 = *d2; for (i = 0; i < (data->image_width * data->image_height * data->bpp >> 1);
i++, d1++, d2 += 2)
*d1 = *d2;
}
else
{
switch (data->bpp)
{
case 4:
/* 16-bit gray with alpha. */
for (i = 0; i < (data->image_width * data->image_height);
i++, d1 += 4, d2 += 4)
{
d1[3] = d2[3];
d1[1] = d2[3];
d1[2] = d2[3];
d1[0] = d2[1];
}
case 2:
if (data->is_16bit)
/* 16-bit gray without 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];
}
}
else
/* 8-bit gray with alpha. */
{
for (i = 0; i < (data->image_width * data->image_height);
i++, d1 += 4, d2 += 2)
{
d1[3] = d2[1];
d1[1] = d2[1];
d1[2] = d2[1];
d1[0] = 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;
}
}
#else #else
switch (data->bpp) switch (data->bpp)
{ {
@ -808,15 +866,30 @@ grub_png_convert_image (struct grub_png_data *data)
d1[2] = d2[1]; d1[2] = d2[1];
} }
break; break;
/* 8-bit with alpha. */
case 4: case 4:
for (i = 0; i < (data->image_width * data->image_height); if (data->is_16bit)
i++, d1 += 4, d2 += 4)
{ {
d1[0] = d2[3]; /* 16-bit gray with alpha. */
d1[1] = d2[2]; for (i = 0; i < (data->image_width * data->image_height);
d1[2] = d2[1]; i++, d1 += 4, d2 += 4)
d1[3] = d2[0]; {
d1[0] = d2[3];
d1[1] = d2[3];
d1[2] = d2[3];
d1[3] = d2[1];
}
}
else
{
/* 8-bit with alpha. */
for (i = 0; i < (data->image_width * data->image_height);
i++, d1 += 4, d2 += 4)
{
d1[0] = d2[3];
d1[1] = d2[2];
d1[2] = d2[1];
d1[3] = d2[0];
}
} }
break; break;
/* 8-bit without alpha. */ /* 8-bit without alpha. */
@ -829,6 +902,41 @@ grub_png_convert_image (struct grub_png_data *data)
d1[2] = d2[0]; d1[2] = d2[0];
} }
break; break;
case 2:
if (data->is_16bit)
/* 16-bit gray without 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];
}
}
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
} }
@ -869,9 +977,7 @@ grub_png_decode_png (struct grub_png_data *data)
break; break;
case PNG_CHUNK_IEND: case PNG_CHUNK_IEND:
#ifndef GRUB_CPU_WORDS_BIGENDIAN if (data->image_data)
if (data->is_16bit)
#endif
grub_png_convert_image (data); grub_png_convert_image (data);
return grub_errno; return grub_errno;
@ -926,7 +1032,7 @@ grub_video_reader_png (struct grub_video_bitmap **bitmap,
#if defined(PNG_DEBUG) #if defined(PNG_DEBUG)
static grub_err_t static grub_err_t
grub_cmd_pngtest (grub_command_t cmd __attribute__ ((unused)), grub_cmd_pngtest (grub_command_t cmd_d __attribute__ ((unused)),
int argc, char **args) int argc, char **args)
{ {
struct grub_video_bitmap *bitmap = 0; struct grub_video_bitmap *bitmap = 0;