aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab+samsung@kernel.org>2018-08-23 09:31:55 (GMT)
committerMauro Carvalho Chehab <mchehab+samsung@kernel.org>2018-08-28 11:21:23 (GMT)
commit620cd17e2c922773110196c63b332a58c06e88ae (patch)
tree22f12711b9ec82fc75c89d7faea4f66bbdb3bb5f
parentc42bfe9d70c708aecc7bd5dc045383284e4b039b (diff)
Use cairo instead of using GdkPixmap
This is another obsolete part of Gtk 2 API. Replace it in favor of using cairo instead. While here, remove code duplication, as image display logic was on 3 different places. Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
-rw-r--r--src/callbacks.c174
-rw-r--r--src/main.c19
-rw-r--r--src/v4l.h1
3 files changed, 120 insertions, 74 deletions
diff --git a/src/callbacks.c b/src/callbacks.c
index cf809cb..60c2eff 100644
--- a/src/callbacks.c
+++ b/src/callbacks.c
@@ -437,7 +437,6 @@ void on_change_size_activate (GtkWidget * widget, cam * cam)
if (cam->read == FALSE)
start_streaming(cam);
- cam->pixmap = gdk_pixmap_new (NULL, cam->width, cam->height, cam->desk_depth);
gtk_widget_set_size_request (GTK_WIDGET(gtk_builder_get_object(cam->xml, "da")),
cam->width, cam->height);
@@ -552,82 +551,149 @@ apply_filters(cam* cam) {
// threshold (cam->pic_buf, cam->width, cam->height, cam->dither);
}
+#define MULT(d,c,a,t) G_STMT_START { t = c * a + 0x7f; d = ((t >> 8) + t) >> 8; } G_STMT_END
+
/*
- * get image from cam - does all the work ;)
+ * As GTK+2 doesn't have gdk_cairo_surface_create_from_pixbuf, we
+ * Borrowed its implementation from
+ * https://github.com/bratsche/gtk-/blob/master/gdk/gdkcairo.c
+ * With a small backport.
*/
-gint
-read_timeout_func(cam* cam) {
- int i, count = 0;
- GdkGC *gc;
- unsigned char *pic_buf = cam->pic_buf;
-
- v4l2_read (cam->dev, cam->pic_buf, (cam->width * cam->height * cam->bpp / 8));
- frames2++;
- /*
- * update_rec.x = 0;
- * update_rec.y = 0;
- * update_rec.width = cam->width;
- * update_rec.height = cam->height;
- */
- count++;
- /*
- * refer the frame
- */
+cairo_surface_t *create_from_pixbuf(const GdkPixbuf *pixbuf,
+ GdkWindow *for_window)
+{
+ gint width = gdk_pixbuf_get_width (pixbuf);
+ gint height = gdk_pixbuf_get_height (pixbuf);
+ guchar *gdk_pixels = gdk_pixbuf_get_pixels (pixbuf);
+ int gdk_rowstride = gdk_pixbuf_get_rowstride (pixbuf);
+ int n_channels = gdk_pixbuf_get_n_channels (pixbuf);
+ int cairo_stride;
+ guchar *cairo_pixels;
+ cairo_format_t format;
+ cairo_surface_t *surface;
+ int j;
+
+ format = CAIRO_FORMAT_RGB24;
+
+ surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24,
+ width, height);
+ cairo_stride = cairo_image_surface_get_stride (surface);
+ cairo_pixels = cairo_image_surface_get_data (surface);
+
+ for (j = height; j; j--) {
+ guchar *p = gdk_pixels;
+ guchar *q = cairo_pixels;
+
+ if (n_channels == 3) {
+ guchar *end = p + 3 * width;
+
+ while (p < end) {
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+ q[0] = p[2];
+ q[1] = p[1];
+ q[2] = p[0];
+#else
+ q[1] = p[0];
+ q[2] = p[1];
+ q[3] = p[2];
+#endif
+ p += 3;
+ q += 4;
+ }
+ } else {
+ guchar *end = p + 4 * width;
+ guint t1,t2,t3;
+
+ while (p < end) {
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+ MULT(q[0], p[2], p[3], t1);
+ MULT(q[1], p[1], p[3], t2);
+ MULT(q[2], p[0], p[3], t3);
+ q[3] = p[3];
+#else
+ q[0] = p[3];
+ MULT(q[1], p[0], p[3], t1);
+ MULT(q[2], p[1], p[3], t2);
+ MULT(q[3], p[2], p[3], t3);
+#endif
+
+ p += 4;
+ q += 4;
+ }
+
+#undef MULT
+ }
- if (cam->pixformat == V4L2_PIX_FMT_YUV420) {
- yuv420p_to_rgb (cam->pic_buf, cam->tmp, cam->width, cam->height, cam->bpp / 8);
- pic_buf = cam->tmp;
+ gdk_pixels += gdk_rowstride;
+ cairo_pixels += cairo_stride;
}
- apply_filters(cam);
-
- gc = gdk_gc_new (cam->pixmap);
- gdk_draw_rgb_image (cam->pixmap,
- gc, 0, 0,
- cam->width, cam->height,
- GDK_RGB_DITHER_NORMAL, pic_buf,
- cam->width * cam->bpp / 8);
-
- gtk_widget_queue_draw_area (GTK_WIDGET(gtk_builder_get_object(cam->xml, "da")), 0,
- 0, cam->width, cam->height);
- return 1;
-
+ cairo_surface_mark_dirty (surface);
+ return surface;
}
-gint timeout_func (cam * cam)
+static void show_buffer(cam* cam)
{
- int i, count = 0;
- GdkGC *gc;
+ int i;
+ GdkPixbuf *pb;
unsigned char *pic_buf = cam->pic_buf;
+ const GdkRectangle rect = {
+ .x = 0, .y = 0,
+ .width = cam->width, .height = cam->height
+ };
- capture_buffers(cam, cam->pic_buf, cam->width * cam->height * cam->bytesperline);
-
- count++;
/*
- * refer the frame
+ * refer the frame
*/
if (cam->pixformat == V4L2_PIX_FMT_YUV420) {
yuv420p_to_rgb (cam->pic_buf, cam->tmp, cam->width, cam->height, cam->bpp / 8);
pic_buf = cam->tmp;
}
- apply_filters(cam);
+ apply_filters(cam);
+
+ /* Use cairo to display the pixel buffer */
+ pb = gdk_pixbuf_new_from_data(pic_buf, GDK_COLORSPACE_RGB, FALSE, 8,
+ cam->width, cam->height,
+ (cam->width * cam->bpp / 8), NULL,
+ NULL);
- gc = gdk_gc_new (cam->pixmap);
+ GtkWidget *widget = GTK_WIDGET(gtk_builder_get_object(cam->xml, "da"));
- gdk_draw_rgb_image (cam->pixmap,
- gc, 0, 0,
- cam->width, cam->height,
- GDK_RGB_DITHER_NORMAL, pic_buf,
- cam->width * cam->bpp / 8);
+ cairo_surface_t *surface = create_from_pixbuf(pb, widget->window);
+ cairo_t *cr = gdk_cairo_create(widget->window);
+ cairo_set_source_surface(cr, surface, 0, 0);
- gtk_widget_queue_draw_area (GTK_WIDGET(gtk_builder_get_object(cam->xml, "da")), 0,
- 0, cam->width, cam->height);
+ gdk_cairo_rectangle(cr, &rect);
+ cairo_fill(cr);
+ cairo_destroy(cr);
+
+ frames++;
frames2++;
- g_object_unref ((gpointer) gc);
- return 1;
+}
+
+/*
+ * get image from cam - does all the work ;)
+ */
+gint
+read_timeout_func(cam* cam) {
+ v4l2_read (cam->dev, cam->pic_buf,
+ (cam->width * cam->height * cam->bpp / 8));
+
+ show_buffer(cam);
+
+ return TRUE;
+}
+
+gint timeout_func (cam * cam)
+{
+ capture_buffers(cam, cam->pic_buf, cam->width * cam->height * cam->bytesperline);
+
+ show_buffer(cam);
+
+ return TRUE;
}
gint fps (GtkWidget * sb)
diff --git a/src/main.c b/src/main.c
index 36da14a..cfe28c2 100644
--- a/src/main.c
+++ b/src/main.c
@@ -16,21 +16,6 @@
#include "camorama-stock-items.h"
-gboolean
-draw_camera_callback (GtkWidget *widget, GdkEventExpose *event, gpointer data)
-{
- cam* camera = data;
-
- gdk_draw_drawable (widget->window,
- widget->style->fg_gc[gtk_widget_get_state (widget)],
- camera->pixmap,
- event->area.x, event->area.y, event->area.x,
- event->area.y, event->area.width, event->area.height);
-
- frames++;
- return TRUE;
-}
-
static int ver = 0, max = 0, min = 0;
static int half = 0, use_read = 0, buggery = 0;
static gchar *poopoo = NULL;
@@ -73,7 +58,6 @@ main(int argc, char *argv[]) {
/* set some default values */
cam->frame_number = 0;
- cam->pixmap = NULL;
cam->size = PICHALF;
cam->video_dev = NULL;
cam->read = FALSE;
@@ -218,7 +202,6 @@ main(int argc, char *argv[]) {
printf ("using read()\n");
pt2Function = read_timeout_func;
}
- cam->pixmap = gdk_pixmap_new (NULL, cam->width, cam->height, cam->desk_depth);
cam->xml = gtk_builder_new ();
if (!gtk_builder_add_from_file (cam->xml,
@@ -241,8 +224,6 @@ main(int argc, char *argv[]) {
GtkWidget *widget = GTK_WIDGET (gtk_builder_get_object (cam->xml, "da"));
gtk_widget_show (widget);
- g_signal_connect (widget, "expose_event",
- G_CALLBACK (draw_camera_callback), cam);
cam->idle_id = gtk_idle_add ((GSourceFunc) pt2Function, (gpointer) cam);
diff --git a/src/v4l.h b/src/v4l.h
index 45f25cf..89260c6 100644
--- a/src/v4l.h
+++ b/src/v4l.h
@@ -71,7 +71,6 @@ typedef struct camera {
gboolean cap, rcap, acap, show_adjustments, show_effects;
gboolean timestamp, rtimestamp, usedate, usestring;
gboolean rtimefn, timefn;
- GdkPixmap *pixmap;
GtkWidget *da, *tray_tooltip, *status;
unsigned char *pic_buf, *tmp;
guint timeout_id, idle_id;

Privacy Policy