From: Hans de Goede Date: Tue, 6 Nov 2018 08:15:22 +0000 (+0100) Subject: ply-image: Add support for loading BMPs X-Git-Tag: 0.9.5~84^2~12 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f5915187b44dd18dd9d1956d169bb17fbd4078d4;p=thirdparty%2Fplymouth.git ply-image: Add support for loading BMPs Add support for loading BMP files. This is needed to be able to read the the ACPI BGRT graphics (the firmware splash shown at boot by the firmware). Signed-off-by: Hans de Goede --- diff --git a/src/libply-splash-graphics/ply-image.c b/src/libply-splash-graphics/ply-image.c index fbf42d61..204fd2e1 100644 --- a/src/libply-splash-graphics/ply-image.c +++ b/src/libply-splash-graphics/ply-image.c @@ -55,6 +55,27 @@ struct _ply_image ply_pixel_buffer_t *buffer; }; +struct bmp_file_header { + uint16_t id; + uint32_t file_size; + uint32_t reserved; + uint32_t bitmap_offset; +} __attribute__((__packed__)); + +struct bmp_dib_header { + uint32_t dib_header_size; + int32_t width; + int32_t height; + uint16_t planes; + uint16_t bpp; + uint32_t compression; + uint32_t bitmap_size; + uint32_t horz_resolution; + uint32_t vert_resolution; + uint32_t colors_used; + uint32_t colors_important; +} __attribute__((__packed__)); + const uint8_t png_header[8] = { 0x89, 'P', 'N', 'G', 0x0d, 0x0a, 0x1a, 0x0a }; ply_image_t * @@ -189,6 +210,69 @@ ply_image_load_png (ply_image_t *image, FILE *fp) return true; } +static bool +ply_image_load_bmp (ply_image_t *image, FILE *fp) +{ + uint32_t x, y, src_y, width, height, bmp_pitch, *dst; + struct bmp_file_header file_header; + struct bmp_dib_header dib_header; + uint8_t r, g, b, *buf, *src; + bool ret = false; + + assert (image != NULL); + assert (fp != NULL); + + if (fread (&file_header, 1, sizeof(struct bmp_file_header), fp) != sizeof(struct bmp_file_header)) + return false; + + if (fread (&dib_header, 1, sizeof(struct bmp_dib_header), fp) != sizeof(struct bmp_dib_header)) + return false; + + if (dib_header.dib_header_size != 40 || dib_header.width < 0 || + dib_header.planes != 1 || dib_header.bpp != 24 || + dib_header.compression != 0) + return false; + + width = dib_header.width; + height = abs (dib_header.height); + bmp_pitch = (3 * width + 3) & ~3; + + buf = malloc (bmp_pitch * height); + assert (buf); + + if (fseek (fp, file_header.bitmap_offset, SEEK_SET) != 0) + goto out; + + if (fread (buf, 1, bmp_pitch * height, fp) != bmp_pitch * height) + goto out; + + image->buffer = ply_pixel_buffer_new (width, height); + dst = ply_pixel_buffer_get_argb32_data (image->buffer); + + for (y = 0; y < height; y++) { + /* Positive header height means upside down row order */ + if (dib_header.height > 0) + src_y = (height - 1) - y; + else + src_y = y; + + src = buf + src_y * bmp_pitch; + + for (x = 0; x < width; x++) { + b = *src++; + g = *src++; + r = *src++; + *dst++ = (0xff << 24) | (r << 16) | (g << 8) | (b << 0); + } + } + + ply_pixel_buffer_set_opaque (image->buffer, true); + ret = true; +out: + free (buf); + return ret; +} + bool ply_image_load (ply_image_t *image) { @@ -212,6 +296,10 @@ ply_image_load (ply_image_t *image) if (memcmp (header, png_header, sizeof(png_header)) == 0) ret = ply_image_load_png (image, fp); + else if (((struct bmp_file_header *)header)->id == 0x4d42 && + ((struct bmp_file_header *)header)->reserved == 0) + ret = ply_image_load_bmp (image, fp); + out: fclose (fp); return ret;