]> git.ipfire.org Git - thirdparty/plymouth.git/commitdiff
ply-image: Add support for loading BMPs
authorHans de Goede <hdegoede@redhat.com>
Tue, 6 Nov 2018 08:15:22 +0000 (09:15 +0100)
committerHans de Goede <hdegoede@redhat.com>
Tue, 27 Nov 2018 07:48:56 +0000 (08:48 +0100)
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 <hdegoede@redhat.com>
src/libply-splash-graphics/ply-image.c

index fbf42d6151673977834dc2ac9d50a63d2ad29378..204fd2e1db7fb1dfff63a514ae9cb7b0e7c13fbf 100644 (file)
@@ -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;