summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt benh@kernel.crashing.org <benh@tika.localdomain>2006-11-27 17:29:47 +1100
committerBenjamin Herrenschmidt <benh@tika.localdomain>2006-11-27 17:29:47 +1100
commitd05c451f30a391b5fe582fa5a0d5e7a32673b57a (patch)
tree4c5c9e29ac35f8812dbe4561b1810a48f2a1823a
parentf58ed76153b4469c4241003e3371a0a2dfc9bf7e (diff)
Add a basic .png loader using libpng
If you use that, you also need to link on libpng. Only quickly tested for now, there are some weird things with libpng that I might not have gotten right, some comments are welcome. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r--twin_png.c184
-rw-r--r--twin_png.h30
2 files changed, 214 insertions, 0 deletions
diff --git a/twin_png.c b/twin_png.c
new file mode 100644
index 0000000..afe492a
--- /dev/null
+++ b/twin_png.c
@@ -0,0 +1,184 @@
+/*
+ * Libpng interface to twin
+ *
+ * Copyright 2006 Benjamin Herrenschmidt <benh@kernel.crashing.org>
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with the Twin Library; see the file COPYING. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "twin_png.h"
+
+#if 0
+#include <stdio.h>
+#define DEBUG(fmt...) printf(fmt)
+#else
+#define DEBUG(fmt...)
+#endif
+
+typedef struct _twin_png_priv {
+ int fd;
+} twin_png_priv_t;
+
+static void twin_png_read_fn(png_structp png, png_bytep data, png_size_t size)
+{
+ twin_png_priv_t *priv = png_get_io_ptr(png);
+ int n;
+
+ n = read(priv->fd, data, size);
+ DEBUG(" twin_png_read_fn size=%d, got=%d\n", size, n);
+ if (n < size)
+ png_error(png, "end of file !\n");
+}
+
+twin_pixmap_t *twin_png_to_pixmap(const char *filepath, twin_format_t fmt)
+{
+ uint8_t signature[8];
+ int fd, i, rb = 0;
+ size_t n;
+ png_structp png = NULL;
+ png_infop info = NULL;
+ twin_pixmap_t *pix = NULL;
+ twin_png_priv_t priv;
+ png_uint_32 width, height;
+ int depth, ctype, interlace;
+ png_bytep *rowp = NULL;
+
+ DEBUG("png read for %s, format=%d\n", filepath, fmt);
+
+ fd = open(filepath, O_RDONLY);
+ if (fd < 0)
+ goto fail;
+
+ DEBUG("checking signature...\n");
+
+ n = read(fd, signature, 8);
+ if (png_sig_cmp(signature, 0, n) != 0)
+ goto fail_close;
+
+ DEBUG("creating libpng structures...\n");
+
+ png = png_create_read_struct(PNG_LIBPNG_VER_STRING,
+ NULL, NULL, NULL);
+ if (png == NULL)
+ goto fail_close;
+
+ info = png_create_info_struct(png);
+ if (info == NULL)
+ goto fail_free;
+
+ if (setjmp(png_jmpbuf(png))) {
+ DEBUG("* error callback *\n");
+ if (pix)
+ twin_pixmap_destroy(pix);
+ pix = NULL;
+ goto fail_free;
+ }
+ priv.fd = fd;
+ png_set_read_fn(png, &priv, twin_png_read_fn);
+
+ png_set_sig_bytes(png, n);
+
+ DEBUG("reading picture infos ...\n");
+ png_read_info(png, info);
+ png_get_IHDR(png, info, &width, &height, &depth, &ctype, &interlace,
+ int_p_NULL, int_p_NULL);
+
+ DEBUG(" 1- size/depth/ctype/int = %ldx%ld/%d/%d/%d\n",
+ width, height, depth, ctype, interlace);
+
+ if (depth == 16)
+ png_set_strip_16(png);
+ if (ctype == PNG_COLOR_TYPE_PALETTE)
+ png_set_palette_to_rgb(png);
+ if (ctype == PNG_COLOR_TYPE_GRAY && depth < 8)
+ png_set_gray_1_2_4_to_8(png);
+ if (png_get_valid(png, info, PNG_INFO_tRNS))
+ png_set_tRNS_to_alpha(png);
+
+ png_get_IHDR(png, info, &width, &height, &depth, &ctype, &interlace,
+ int_p_NULL, int_p_NULL);
+
+ DEBUG(" 2- size/depth/ctype/int = %ldx%ld/%d/%d/%d\n",
+ width, height, depth, ctype, interlace);
+
+ switch(fmt) {
+ case TWIN_A8:
+ if (ctype != PNG_COLOR_TYPE_GRAY ||
+ depth != 8)
+ goto fail_free;
+ rb = width;
+ break;
+ case TWIN_RGB16:
+ /* unsupported for now */
+ goto fail_free;
+ case TWIN_ARGB32:
+ if (ctype == PNG_COLOR_TYPE_RGB)
+ png_set_filler(png, 0xff, PNG_FILLER_BEFORE);
+ if (ctype == PNG_COLOR_TYPE_RGB_ALPHA)
+ png_set_swap_alpha(png);
+ if (ctype == PNG_COLOR_TYPE_GRAY ||
+ ctype == PNG_COLOR_TYPE_GRAY_ALPHA)
+ png_set_gray_to_rgb(png);
+
+ png_get_IHDR(png, info, &width, &height, &depth, &ctype,
+ &interlace, int_p_NULL, int_p_NULL);
+
+ DEBUG(" 3- size/depth/ctype/int = %ldx%ld/%d/%d/%d\n",
+ width, height, depth, ctype, interlace);
+
+ if (depth != 8)
+ goto fail_free;
+ rb = width * 4;
+ break;
+ }
+ DEBUG(" rowbytes = %d\n", rb);
+
+ DEBUG("preparing pixmap & row pointer array...\n");
+
+ rowp = malloc(height * sizeof(png_bytep));
+ if (rowp == NULL)
+ goto fail_free;
+ pix = twin_pixmap_create(fmt, width, height);
+ if (pix == NULL)
+ goto fail_free;
+ for (i = 0; i < height; i++)
+ rowp[i] = pix->p.b + rb * i;
+
+ DEBUG("reading image...\n");
+
+ png_read_image(png, rowp);
+
+ png_read_end(png, NULL);
+
+ fail_free:
+ if (rowp)
+ free(rowp);
+ png_destroy_read_struct(&png, &info, png_infopp_NULL);
+ fail_close:
+ close(fd);
+ fail:
+ return pix;
+}
+
diff --git a/twin_png.h b/twin_png.h
new file mode 100644
index 0000000..a4f1e3b
--- /dev/null
+++ b/twin_png.h
@@ -0,0 +1,30 @@
+/*
+ * Libpng interface to twin
+ *
+ * Copyright 2006 Benjamin Herrenschmidt <benh@kernel.crashing.org>
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with the Twin Library; see the file COPYING. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef _TWIN_PNG_H_
+#define _TWIN_PNG_H_
+
+#include "twin.h"
+
+#include <png.h>
+
+twin_pixmap_t *twin_png_to_pixmap(const char *filepath, twin_format_t fmt);
+
+#endif /* _TWIN_PNG_H_ */