summaryrefslogtreecommitdiffstats
path: root/lib/png.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/png.c')
-rw-r--r--lib/png.c89
1 files changed, 89 insertions, 0 deletions
diff --git a/lib/png.c b/lib/png.c
new file mode 100644
index 0000000000..f71fc6abc8
--- /dev/null
+++ b/lib/png.c
@@ -0,0 +1,89 @@
+#include <common.h>
+#include <errno.h>
+#include <malloc.h>
+#include <fb.h>
+#include <asm/byteorder.h>
+#include <init.h>
+#include <image_renderer.h>
+#include <graphic_utils.h>
+#include <linux/zlib.h>
+
+#include "png.h"
+
+z_stream png_stream;
+static int initialized;
+
+int png_uncompress_init(void)
+{
+ if (!initialized++) {
+ png_stream.workspace = malloc(zlib_inflate_workspacesize());
+ if (!png_stream.workspace) {
+ initialized = 0;
+ return -ENOMEM;
+ }
+ png_stream.next_in = NULL;
+ png_stream.avail_in = 0;
+ zlib_inflateInit(&png_stream);
+ }
+ return 0;
+}
+
+void png_uncompress_exit(void)
+{
+ if (!--initialized) {
+ zlib_inflateEnd(&png_stream);
+ vfree(png_stream.workspace);
+ }
+}
+
+static int png_renderer(struct fb_info *info, struct image *img, void* fb,
+ int startx, int starty, void* offscreenbuf)
+{
+ int width, height;
+ void *buf;
+ int xres, yres;
+
+ xres = info->xres;
+ yres = info->yres;
+
+ if (startx < 0) {
+ startx = (xres - img->width) / 2;
+ if (startx < 0)
+ startx = 0;
+ }
+
+ if (starty < 0) {
+ starty = (yres - img->height) / 2;
+ if (starty < 0)
+ starty = 0;
+ }
+
+ width = min(img->width, xres - startx);
+ height = min(img->height, yres - starty);
+
+ buf = offscreenbuf ? offscreenbuf : fb;
+
+ rgba_blend(info, img->data, buf, height, width, startx, starty, true);
+
+ if (offscreenbuf) {
+ int fbsize;
+
+ fbsize = xres * yres * (info->bits_per_pixel >> 3);
+ memcpy(fb, offscreenbuf, fbsize);
+ }
+
+ return img->height;
+}
+
+static struct image_renderer png = {
+ .type = filetype_png,
+ .open = png_open,
+ .close = png_close,
+ .renderer = png_renderer,
+};
+
+static int png_init(void)
+{
+ return image_renderer_register(&png);
+}
+fs_initcall(png_init);