Esempio n. 1
0
static cairo_surface_t *
_cairo_surface_create_from_ppm (int     width,
                                int     height,
                                int     colors,
                                int     bits,
                                guchar *buffer,
                                gsize   buffer_size)
{
    cairo_surface_t *surface;
    int              stride;
    guchar          *buffer_p;
    int              r, c;
    guchar          *row;
    guchar          *column;
    guint32          pixel;

    if (bits != 8)
        return NULL;

    surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
    stride = cairo_image_surface_get_stride (surface);

    buffer_p = buffer;
    row = _cairo_image_surface_flush_and_get_data (surface);
    for (r = 0; r < height; r++) {
        column = row;
        for (c = 0; c < width; c++) {
            switch (colors) {
            case 4:
                pixel = CAIRO_RGBA_TO_UINT32 (buffer_p[0], buffer_p[1], buffer_p[2], buffer_p[3]);
                break;
            case 3:
                pixel = CAIRO_RGBA_TO_UINT32 (buffer_p[0], buffer_p[1], buffer_p[2], 0xff);
                break;
            case 1:
                pixel = CAIRO_RGBA_TO_UINT32 (buffer_p[0], buffer_p[0], buffer_p[0], 0xff);
                break;
            }

            memcpy (column, &pixel, sizeof (guint32));

            column += 4;
            buffer_p += colors;
        }
        row += stride;
    }

    cairo_surface_mark_dirty (surface);

    return surface;
}
Esempio n. 2
0
static void
_cairo_surface_reduce_row (guchar *dest_data,
			   guchar *src_row0,
			   guchar *src_row1,
			   guchar *src_row2,
			   int     src_width)
{
	int     x, b;
	ScaleReal  sum;
	int     col0, col1, col2;
	guchar  c[4];
	guint32 pixel;

	/*  Pre calculated gausian matrix
	 *  Standard deviation = 0.71

		12 32 12
		32 86 32
		12 32 12

		Matrix sum is = 262
		Normalize by dividing with 273

	*/

	for (x = 0; x < src_width - (src_width % 2); x += 2) {
		for (b = 0; b < 4; b++) {

			col0 = MAX (x - 1, 0) * 4 + b;
			col1 = x * 4 + b;
			col2 = MIN (x + 1, src_width - 1) * 4 + b;

			sum = 0.0;

			sum += src_row0[col0] * 12;
			sum += src_row0[col1] * 32;
			sum += src_row0[col2] * 12;

			sum += src_row1[col0] * 32;
			sum += src_row1[col1] * 86;
			sum += src_row1[col2] * 32;

			sum += src_row2[col0] * 12;
			sum += src_row2[col1] * 32;
			sum += src_row2[col2] * 12;

			sum /= 262.0;

			c[b] = CLAMP (sum, 0, 255);
		}

		pixel = CAIRO_RGBA_TO_UINT32 (c[CAIRO_RED], c[CAIRO_GREEN], c[CAIRO_BLUE], c[CAIRO_ALPHA]);
		memcpy (dest_data, &pixel, 4);

		dest_data += 4;
	}
}
Esempio n. 3
0
cairo_surface_t *
_cairo_image_surface_create_from_pixbuf (GdkPixbuf *pixbuf)
{
	cairo_surface_t          *surface;
	cairo_surface_metadata_t *metadata;
	int                      width;
	int                      height;
	int                      p_stride;
	int                      p_n_channels;
	guchar                  *p_pixels;
	int                      s_stride;
	unsigned char           *s_pixels;
	int                      h, w;
	guint32                  pixel;
	guchar                   r, g, b, a;

	if (pixbuf == NULL)
		return NULL;

	g_object_get (G_OBJECT (pixbuf),
		      "width", &width,
		      "height", &height,
		      "rowstride", &p_stride,
		      "n-channels", &p_n_channels,
		      "pixels", &p_pixels,
		      NULL );
	surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
	s_stride = cairo_image_surface_get_stride (surface);
	s_pixels = _cairo_image_surface_flush_and_get_data (surface);

	metadata = _cairo_image_surface_get_metadata (surface);
	_cairo_metadata_set_has_alpha (metadata, (p_n_channels == 4));

	if (p_n_channels == 4) {
		guchar *s_iter;
		guchar *p_iter;

		for (h = 0; h < height; h++) {
			s_iter = s_pixels;
			p_iter = p_pixels;

			for (w = 0; w < width; w++) {
				a = p_iter[3];
				if (a == 0xff) {
					pixel = CAIRO_RGBA_TO_UINT32 (p_iter[0], p_iter[1], p_iter[2], 0xff);
				}
				else if (a == 0) {
					pixel = 0;
				}
				else {
					r = _cairo_multiply_alpha (p_iter[0], a);
					g = _cairo_multiply_alpha (p_iter[1], a);
					b = _cairo_multiply_alpha (p_iter[2], a);
					pixel = CAIRO_RGBA_TO_UINT32 (r, g, b, a);
				}
				memcpy (s_iter, &pixel, sizeof (guint32));

				s_iter += 4;
				p_iter += p_n_channels;
			}

			s_pixels += s_stride;
			p_pixels += p_stride;
		}
	}
	else {
		guchar *s_iter;
		guchar *p_iter;

		for (h = 0; h < height; h++) {
			s_iter = s_pixels;
			p_iter = p_pixels;

			for (w = 0; w < width; w++) {
				pixel = CAIRO_RGBA_TO_UINT32 (p_iter[0], p_iter[1], p_iter[2], 0xff);
				memcpy (s_iter, &pixel, sizeof (guint32));

				s_iter += 4;
				p_iter += p_n_channels;
			}

			s_pixels += s_stride;
			p_pixels += p_stride;
		}
	}

	cairo_surface_mark_dirty (surface);

	return surface;
}
Esempio n. 4
0
cairo_surface_t *
_cairo_image_surface_scale_bilinear_2x2 (cairo_surface_t *image,
					 int              new_width,
					 int              new_height)
{
	cairo_surface_t *scaled;
	int              src_width;
	int              src_height;
	guchar          *p_src;
	guchar          *p_dest;
	int              src_rowstride;
	int              dest_rowstride;
	ScaleReal           step_x, step_y;
	guchar          *p_dest_row;
	guchar          *p_src_row;
	guchar          *p_src_col;
	guchar          *p_dest_col;
	ScaleReal           x_src, y_src;
	int              x, y;
	guchar           r00, r01, r10, r11;
	guchar           g00, g01, g10, g11;
	guchar           b00, b01, b10, b11;
	guchar           a00, a01, a10, a11;
	guchar           r, g, b, a;
	guint32          pixel;
	ScaleReal           tmp;
	ScaleReal           x_fract, y_fract;
	int              col, row;

	scaled = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
					     new_width,
					     new_height);

	src_width = cairo_image_surface_get_width  (image);
	src_height = cairo_image_surface_get_height (image);
	p_src = _cairo_image_surface_flush_and_get_data (image);
	p_dest = _cairo_image_surface_flush_and_get_data (scaled);
	src_rowstride = cairo_image_surface_get_stride (image);
	dest_rowstride = cairo_image_surface_get_stride (scaled);

	cairo_surface_flush (scaled);

	step_x = (ScaleReal) src_width / new_width;
	step_y = (ScaleReal) src_height / new_height;
	p_dest_row = p_dest;
	p_src_row = p_src;
	y_src = 0;

	for (y = 0; y < new_height; y++) {
		row = floor (y_src);
		y_fract = y_src - row;
		p_src_row = p_src + (row * src_rowstride);

		p_dest_col = p_dest_row;
		p_src_col = p_src_row;
		x_src = 0;
		for (x = 0; x < new_width; x++) {
			col = floor (x_src);
			x_fract = x_src - col;
			p_src_col = p_src_row + (col * 4);

			/* x00 */

			CAIRO_COPY_RGBA (p_src_col, r00, g00, b00, a00);

			/* x01 */

			if (col + 1 < src_width - 1) {
				p_src_col += 4;
				CAIRO_COPY_RGBA (p_src_col, r01, g01, b01, a01);
			}
			else {
				r01 = r00;
				g01 = g00;
				b01 = b00;
				a01 = a00;
			}

			/* x10 */

			if (row + 1 < src_height - 1) {
				p_src_col = p_src_row + src_rowstride + (col * 4);
				CAIRO_COPY_RGBA (p_src_col, r10, g10, b10, a10);
			}
			else {
				r10 = r00;
				g10 = g00;
				b10 = b00;
				a10 = a00;
			}

			/* x11 */

			if ((row + 1 < src_height - 1) && (col + 1 < src_width - 1)) {
				p_src_col += 4;
				CAIRO_COPY_RGBA (p_src_col, r11, g11, b11, a11);
			}
			else {
				r11 = r00;
				g11 = g00;
				b11 = b00;
				a11 = a00;
			}

			BILINEAR_INTERPOLATE (r, r00, r01, r10, r11, x_fract, y_fract);
			BILINEAR_INTERPOLATE (g, g00, g01, g10, g11, x_fract, y_fract);
			BILINEAR_INTERPOLATE (b, b00, b01, b10, b11, x_fract, y_fract);
			BILINEAR_INTERPOLATE (a, a00, a01, a10, a11, x_fract, y_fract);
			pixel = CAIRO_RGBA_TO_UINT32 (r, g, b, a);
			memcpy (p_dest_col, &pixel, 4);

			p_dest_col += 4;
			x_src += step_x;
		}

		p_dest_row += dest_rowstride;
		y_src += step_y;
	}

	cairo_surface_mark_dirty (scaled);

	return scaled;
}
Esempio n. 5
0
static cairo_surface_t*
rotate (cairo_surface_t *image,
	double           angle,
	gboolean         high_quality,
	guchar           r0,
	guchar           g0,
	guchar           b0,
	guchar           a0,
	GthAsyncTask    *task)
{
	cairo_surface_t *image_with_background;
	cairo_surface_t *rotated;
	double           angle_rad;
	double           cos_angle, sin_angle;
	double           src_width, src_height;
	int              new_width, new_height;
	int              src_rowstride, new_rowstride;
	int              xi, yi;
	double           x, y;
	double           x2, y2;
	int              x2min, y2min;
	int              x2max, y2max;
	double           fx, fy;
	guchar          *p_src, *p_new;
	guchar          *p_src2, *p_new2;
	guchar           r00, r01, r10, r11;
	guchar           g00, g01, g10, g11;
	guchar           b00, b01, b10, b11;
	guchar           a00, a01, a10, a11;
	double           half_new_width;
	double           half_new_height;
	double           half_src_width;
	double           half_src_height;
	int              tmp;
	guchar           r, g, b, a;
	guint32          pixel;

	angle = CLAMP (angle, -90.0, 90.0);
	angle_rad = angle / 180.0 * G_PI;
	cos_angle = cos (angle_rad);
	sin_angle = sin (angle_rad);
	src_width  = cairo_image_surface_get_width  (image);
	src_height = cairo_image_surface_get_height (image);
	new_width  = GDOUBLE_ROUND_TO_INT (      cos_angle  * src_width + fabs(sin_angle) * src_height);
	new_height = GDOUBLE_ROUND_TO_INT (fabs (sin_angle) * src_width +      cos_angle  * src_height);

	if (a0 == 0xff) {
		/* pre-multiply the background color */

		image_with_background = _cairo_image_surface_copy (image);
		p_src = _cairo_image_surface_flush_and_get_data (image);
		p_new = _cairo_image_surface_flush_and_get_data (image_with_background);
		src_rowstride = cairo_image_surface_get_stride (image);
		new_rowstride = cairo_image_surface_get_stride (image_with_background);

		cairo_surface_flush (image_with_background);
		for (yi = 0; yi < src_height; yi++) {
			p_src2 = p_src;
			p_new2 = p_new;
			for (xi = 0; xi < src_width; xi++) {
				a = p_src2[CAIRO_ALPHA];
				r = p_src2[CAIRO_RED] + _cairo_multiply_alpha (r0, 0xff - a);
				g = p_src2[CAIRO_GREEN] + _cairo_multiply_alpha (g0, 0xff - a);
				b = p_src2[CAIRO_BLUE] + _cairo_multiply_alpha (b0, 0xff - a);
				pixel = CAIRO_RGBA_TO_UINT32 (r, g, b, 0xff);
				memcpy (p_new2, &pixel, sizeof (guint32));

				p_new2 += 4;
				p_src2 += 4;
			}
			p_src += src_rowstride;
			p_new += new_rowstride;
		}
		cairo_surface_mark_dirty (image_with_background);
	}
	else
		image_with_background = cairo_surface_reference (image);

	/* create the rotated image */

	rotated = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, new_width, new_height);

	p_src = _cairo_image_surface_flush_and_get_data (image_with_background);
	p_new = _cairo_image_surface_flush_and_get_data (rotated);
	src_rowstride = cairo_image_surface_get_stride (image_with_background);
	new_rowstride = cairo_image_surface_get_stride (rotated);

/*
 * bilinear interpolation
 *            fx
 *    v00------------v01
 *    |        |      |
 * fy |--------v      |
 *    |               |
 *    |               |
 *    |               |
 *    v10------------v11
 */
#define INTERPOLATE(v, v00, v01, v10, v11, fx, fy) \
	tmp = (1.0 - (fy)) * \
	      ((1.0 - (fx)) * (v00) + (fx) * (v01)) \
              + \
              (fy) * \
              ((1.0 - (fx)) * (v10) + (fx) * (v11)); \
	v = CLAMP (tmp, 0, 255);

#define GET_VALUES(r, g, b, a, x, y) \
	if (x >= 0 && x < src_width && y >= 0 && y < src_height) { \
		p_src2 = p_src + src_rowstride * y + 4 * x; \
		r = p_src2[CAIRO_RED]; \
		g = p_src2[CAIRO_GREEN]; \
		b = p_src2[CAIRO_BLUE]; \
		a = p_src2[CAIRO_ALPHA]; \
	} \
	else { \
		r = r0; \
		g = g0; \
		b = b0; \
		a = a0; \
	}

	half_new_width = new_width / 2.0;
	half_new_height = new_height / 2.0;
	half_src_width = src_width / 2.0;
	half_src_height = src_height / 2.0;

	cairo_surface_flush (rotated);

	y = - half_new_height;
	for (yi = 0; yi < new_height; yi++) {
		if (task != NULL) {
			gboolean cancelled;
			double   progress;

			gth_async_task_get_data (task, NULL, &cancelled, NULL);
			if (cancelled)
				goto out;

			progress = (double) yi / new_height;
			gth_async_task_set_data (task, NULL, NULL, &progress);
		}

		p_new2 = p_new;

		x = - half_new_width;
		for (xi = 0; xi < new_width; xi++) {
			x2 = cos_angle * x - sin_angle * y + half_src_width;
			y2 = sin_angle * x + cos_angle * y + half_src_height;

			if (high_quality) {
				/* Bilinear interpolation. */

				x2min = (int) x2;
				y2min = (int) y2;
				x2max = x2min + 1;
				y2max = y2min + 1;

				GET_VALUES (r00, g00, b00, a00, x2min, y2min);
				GET_VALUES (r01, g01, b01, a01, x2max, y2min);
				GET_VALUES (r10, g10, b10, a10, x2min, y2max);
				GET_VALUES (r11, g11, b11, a11, x2max, y2max);

				fx = x2 - x2min;
				fy = y2 - y2min;

				INTERPOLATE (r, r00, r01, r10, r11, fx, fy);
				INTERPOLATE (g, g00, g01, g10, g11, fx, fy);
				INTERPOLATE (b, b00, b01, b10, b11, fx, fy);
				INTERPOLATE (a, a00, a01, a10, a11, fx, fy);

				pixel = CAIRO_RGBA_TO_UINT32 (r, g, b, a);
				memcpy (p_new2, &pixel, sizeof (guint32));
			}
			else {
				/* Nearest neighbor */

				x2min = GDOUBLE_ROUND_TO_INT (x2);
				y2min = GDOUBLE_ROUND_TO_INT (y2);

				GET_VALUES (p_new2[CAIRO_RED],
					    p_new2[CAIRO_GREEN],
					    p_new2[CAIRO_BLUE],
					    p_new2[CAIRO_ALPHA],
					    x2min,
					    y2min);
			}

			p_new2 += 4;
			x += 1.0;
		}

		p_new += new_rowstride;
		y += 1.0;
	}

	out:

	cairo_surface_mark_dirty (rotated);
	cairo_surface_destroy (image_with_background);

#undef INTERPOLATE
#undef GET_VALUES

	return rotated;
}