[RFC][PATCH] remove gdk-pixbuf and use libpng
Tiago Vignatti
tiago.vignatti at nokia.com
Wed Feb 9 03:06:39 PST 2011
Signed-off-by: Tiago Vignatti <tiago.vignatti at nokia.com>
---
This patch is a WIP to remove gdk-pixbuf dependency and use libpng instead.
It is unfinished though and only compositor with simple-client works.
In principle, gdk-pixbuf is a bit bloated and brings a big package dependency
in some platforms which makes harder to try Wayland. On the other hand,
gdk-pixbuf has several modules to convert a bunch of image formats in pixel
data, whereas libpng has only one, obviously. This is the drawback on using
lipng. However, I guess compositor and clients could live happy with libpng
only given they are made for demonstration purposes (well, at least at the
moment).
I won't be playing with this on the next days, but I'd love to help anyone
with this work in the case I got a positive feedback here. Then, the short
TODO on my mind:
- fix command line parsing in compositor.c
- apply analogue changes for other clients and screenshooter
Thanks!
Tiago
clients/dnd.c | 2 +
clients/image.c | 6 +++
clients/window.c | 6 +++
compositor/compositor.c | 92 +++++++++++++++++++++++++++++++++-----------
compositor/screenshooter.c | 8 ++++
configure.ac | 4 +-
6 files changed, 93 insertions(+), 25 deletions(-)
diff --git a/clients/dnd.c b/clients/dnd.c
index 1625ffd..48d8dc0 100644
--- a/clients/dnd.c
+++ b/clients/dnd.c
@@ -30,7 +30,9 @@
#include <sys/time.h>
#include <cairo.h>
#include <glib.h>
+#ifdef GDK_STUFF
#include <gdk-pixbuf/gdk-pixbuf.h>
+#endif
#include "wayland-client.h"
#include "wayland-glib.h"
diff --git a/clients/image.c b/clients/image.c
index 3eada1e..ca144e4 100644
--- a/clients/image.c
+++ b/clients/image.c
@@ -31,7 +31,9 @@
#include <time.h>
#include <cairo.h>
#include <glib.h>
+#ifdef GDK_STUFF
#include <gdk-pixbuf/gdk-pixbuf.h>
+#endif
#include "wayland-client.h"
#include "wayland-glib.h"
@@ -45,6 +47,7 @@ struct image {
gchar *filename;
};
+#ifdef GDK_STUFF
static void
set_source_pixbuf(cairo_t *cr,
const GdkPixbuf *pixbuf,
@@ -133,10 +136,12 @@ set_source_pixbuf(cairo_t *cr,
src_y + .5 * (src_height - height));
cairo_surface_destroy(surface);
}
+#endif
static void
image_draw(struct image *image)
{
+#ifdef GDK_STUFF
struct rectangle allocation;
GdkPixbuf *pb;
cairo_t *cr;
@@ -179,6 +184,7 @@ image_draw(struct image *image)
window_flush(image->window);
cairo_surface_destroy(surface);
+#endif
}
static void
diff --git a/clients/window.c b/clients/window.c
index b802518..9fa523e 100644
--- a/clients/window.c
+++ b/clients/window.c
@@ -33,7 +33,9 @@
#include <cairo.h>
#include <glib.h>
#include <glib-object.h>
+#ifdef GDK_STUFF
#include <gdk-pixbuf/gdk-pixbuf.h>
+#endif
#include <sys/mman.h>
#define EGL_EGLEXT_PROTOTYPES 1
@@ -281,6 +283,7 @@ display_create_egl_image_surface_from_file(struct display *display,
const char *filename,
struct rectangle *rect)
{
+#ifdef GDK_STUFF
cairo_surface_t *surface;
GdkPixbuf *pixbuf;
GError *error = NULL;
@@ -335,6 +338,7 @@ display_create_egl_image_surface_from_file(struct display *display,
g_object_unref(pixbuf);
return surface;
+#endif
}
#endif
@@ -429,6 +433,7 @@ display_create_shm_surface_from_file(struct display *display,
const char *filename,
struct rectangle *rect)
{
+#ifdef GDK_STUFF
cairo_surface_t *surface;
GdkPixbuf *pixbuf;
GError *error = NULL;
@@ -481,6 +486,7 @@ display_create_shm_surface_from_file(struct display *display,
g_object_unref(pixbuf);
return surface;
+#endif
}
static int
diff --git a/compositor/compositor.c b/compositor/compositor.c
index 535b3f1..8bbe387 100644
--- a/compositor/compositor.c
+++ b/compositor/compositor.c
@@ -28,7 +28,8 @@
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
-#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <png.h>
+#include <signal.h> /* SIGTERM and SIGINT */
#include <math.h>
#include <linux/input.h>
@@ -45,10 +46,11 @@ struct wlsc_switcher {
* advertise that through a service on the session dbus.
*/
static const char *option_socket_name = NULL;
-static const char *option_background = "background.jpg";
+static const char *option_background = "background.png";
static const char *option_geometry = "1024x640";
static int option_connector = 0;
+#ifdef GDK_STUFF
static const GOptionEntry option_entries[] = {
{ "background", 'b', 0, G_OPTION_ARG_STRING,
&option_background, "Background image" },
@@ -60,6 +62,7 @@ static const GOptionEntry option_entries[] = {
&option_socket_name, "Socket Name" },
{ NULL }
};
+#endif
static void
wlsc_matrix_init(struct wlsc_matrix *matrix)
@@ -198,33 +201,76 @@ destroy_surface(struct wl_resource *resource, struct wl_client *client)
uint32_t *
wlsc_load_image(const char *filename, int width, int height)
{
- GdkPixbuf *pixbuf;
- GError *error = NULL;
int stride, i, n_channels;
- unsigned char *pixels, *end, *argb_pixels, *s, *d;
-
- pixbuf = gdk_pixbuf_new_from_file_at_scale(filename,
- width, height,
- FALSE, &error);
- if (error != NULL) {
- fprintf(stderr, "failed to load image: %s\n", error->message);
- g_error_free(error);
+ unsigned char *end, *argb_pixels, *s, *d;
+
+ int y;
+ png_byte bit_depth;
+ png_structp png_ptr;
+ png_infop info_ptr;
+ int number_of_passes;
+ png_bytep * row_pointers;
+
+ char header[8]; // 8 is the maximum size that can be checked
+
+ /* open file and test for it being a png */
+ FILE *fp = fopen(filename, "rb");
+ if (!fp)
+ fprintf(stderr, "file %s could not be opened for reading", filename);
+
+ fread(header, 1, 8, fp);
+
+ if (png_sig_cmp((png_bytep) header, 0, 8)) {
+ fprintf(stderr, "file %s is not recognized as a PNG file", filename);
return NULL;
}
- stride = gdk_pixbuf_get_rowstride(pixbuf);
- pixels = gdk_pixbuf_get_pixels(pixbuf);
- n_channels = gdk_pixbuf_get_n_channels(pixbuf);
+ /* initialize stuff */
+ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ if (!png_ptr)
+ fprintf(stderr, "png_create_read_struct failed");
- argb_pixels = malloc (height * width * 4);
- if (argb_pixels == NULL) {
- g_object_unref(pixbuf);
+ info_ptr = png_create_info_struct(png_ptr);
+ if (!info_ptr)
+ fprintf(stderr, "png_create_info_struct failed");
+
+ if (setjmp(png_jmpbuf(png_ptr))) {
+ fprintf(stderr, "error during init_io");
return NULL;
}
+ png_init_io(png_ptr, fp);
+ png_set_sig_bytes(png_ptr, 8);
+ png_set_swap_alpha(png_ptr);
+ png_read_info(png_ptr, info_ptr);
+
+ bit_depth = png_get_bit_depth(png_ptr, info_ptr);
+ n_channels = png_get_channels(png_ptr, info_ptr);
+ stride = width * bit_depth * n_channels / 8;
+
+ number_of_passes = png_set_interlace_handling(png_ptr);
+ png_read_update_info(png_ptr, info_ptr);
+
+ /* read file */
+ if (setjmp(png_jmpbuf(png_ptr)))
+ fprintf(stderr, "error during read_image");
+
+ row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * height);
+ for (y=0; y < height; y++)
+ row_pointers[y] = malloc(png_get_rowbytes(png_ptr, info_ptr));
+
+ png_read_image(png_ptr, row_pointers);
+ fclose(fp);
+
+ /* TODO: implement color type checking */
+
+ argb_pixels = malloc (height * width * 4);
+ if (argb_pixels == NULL)
+ return NULL;
+
if (n_channels == 4) {
for (i = 0; i < height; i++) {
- s = pixels + i * stride;
+ s = (unsigned char *)row_pointers[i];
end = s + width * 4;
d = argb_pixels + i * width * 4;
while (s < end) {
@@ -243,7 +289,7 @@ wlsc_load_image(const char *filename, int width, int height)
}
} else if (n_channels == 3) {
for (i = 0; i < height; i++) {
- s = pixels + i * stride;
+ s = (unsigned char *)row_pointers[i];
end = s + width * 3;
d = argb_pixels + i * width * 4;
while (s < end) {
@@ -257,8 +303,6 @@ wlsc_load_image(const char *filename, int width, int height)
}
}
- g_object_unref(pixbuf);
-
return (uint32_t *) argb_pixels;
}
@@ -1283,9 +1327,10 @@ int main(int argc, char *argv[])
struct wl_display *display;
struct wlsc_compositor *ec;
struct wl_event_loop *loop;
+ int width, height;
+#ifdef GDK_STUFF
GError *error = NULL;
GOptionContext *context;
- int width, height;
g_type_init(); /* GdkPixbuf needs this, it seems. */
@@ -1295,6 +1340,7 @@ int main(int argc, char *argv[])
fprintf(stderr, "option parsing failed: %s\n", error->message);
exit(EXIT_FAILURE);
}
+#endif
if (sscanf(option_geometry, "%dx%d", &width, &height) != 2) {
fprintf(stderr, "invalid geometry option: %s \n",
option_geometry);
diff --git a/compositor/screenshooter.c b/compositor/screenshooter.c
index 53ed931..a5cece3 100644
--- a/compositor/screenshooter.c
+++ b/compositor/screenshooter.c
@@ -18,7 +18,11 @@
#include <stdlib.h>
#include <GLES2/gl2.h>
+#ifdef GDK_STUFF
#include <gdk-pixbuf/gdk-pixbuf.h>
+#else
+#include <stdio.h>
+#endif
#include "compositor.h"
#include "screenshooter-server-protocol.h"
@@ -34,8 +38,10 @@ screenshooter_shoot(struct wl_client *client, struct wl_screenshooter *shooter)
struct wlsc_compositor *ec = shooter->ec;
struct wlsc_output *output;
char buffer[256];
+#ifdef GDK_STUFF
GdkPixbuf *pixbuf;
GError *error = NULL;
+#endif
unsigned char *data;
int i, j;
@@ -56,11 +62,13 @@ screenshooter_shoot(struct wl_client *client, struct wl_screenshooter *shooter)
for (j = 3; j < output->width * output->height * 4; j += 4)
data[j] = 0xff;
+#ifdef GDK_STUFF
pixbuf = gdk_pixbuf_new_from_data(data, GDK_COLORSPACE_RGB, TRUE,
8, output->width, output->height, output->width * 4,
NULL, NULL);
gdk_pixbuf_save(pixbuf, buffer, "png", &error, NULL);
g_object_unref(pixbuf);
+#endif
free(data);
}
}
diff --git a/configure.ac b/configure.ac
index 868ebb8..38e4ab5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -23,9 +23,9 @@ PKG_PROG_PKG_CONFIG()
PKG_CHECK_MODULES(FFI, [libffi])
PKG_CHECK_MODULES(COMPOSITOR,
- [egl >= 7.10 glesv2 gdk-pixbuf-2.0 libudev >= 136 libdrm >= 2.4.23] xcb-dri2 xcb-xfixes)
+ [egl >= 7.10 glesv2 libudev >= 136 libdrm >= 2.4.23] libpng xcb-dri2 xcb-xfixes)
PKG_CHECK_MODULES(GLES2, [egl >= 7.10 glesv2 libdrm >= 2.4.23])
-PKG_CHECK_MODULES(CLIENT, [egl >= 7.10 gl cairo >= 1.10.0 gdk-pixbuf-2.0 glib-2.0 gobject-2.0 xkbcommon libdrm >= 2.4.23])
+PKG_CHECK_MODULES(CLIENT, [egl >= 7.10 gl cairo >= 1.10.0 libpng glib-2.0 gobject-2.0 xkbcommon libdrm >= 2.4.23])
PKG_CHECK_MODULES(POPPLER, [poppler-glib gdk-2.0 gio-2.0],
[have_poppler=yes], [have_poppler=no])
AM_CONDITIONAL(HAVE_POPPLER, test "x$have_poppler" = "xyes")
--
1.7.1
More information about the wayland-devel
mailing list