Beispiel #1
0
CoglPipeline *
_st_create_shadow_pipeline (StShadow    *shadow_spec,
                            CoglTexture *src_texture)
{
    ClutterBackend *backend = clutter_get_default_backend ();
    CoglContext *ctx = clutter_backend_get_cogl_context (backend);

    static CoglPipeline *shadow_pipeline_template = NULL;

    CoglPipeline *pipeline;
    CoglTexture *texture;
    guchar *pixels_in, *pixels_out;
    gint width_in, height_in, rowstride_in;
    gint width_out, height_out, rowstride_out;

    g_return_val_if_fail (shadow_spec != NULL, NULL);
    g_return_val_if_fail (src_texture != NULL, NULL);

    width_in  = cogl_texture_get_width  (src_texture);
    height_in = cogl_texture_get_height (src_texture);
    rowstride_in = (width_in + 3) & ~3;

    pixels_in  = g_malloc0 (rowstride_in * height_in);

    cogl_texture_get_data (src_texture, COGL_PIXEL_FORMAT_A_8,
                           rowstride_in, pixels_in);

    pixels_out = blur_pixels (pixels_in, width_in, height_in, rowstride_in,
                              shadow_spec->blur,
                              &width_out, &height_out, &rowstride_out);
    g_free (pixels_in);

    texture = COGL_TEXTURE (cogl_texture_2d_new_from_data (ctx, width_out, height_out,
                            COGL_PIXEL_FORMAT_A_8,
                            rowstride_out,
                            pixels_out,
                            NULL));

    g_free (pixels_out);

    if (G_UNLIKELY (shadow_pipeline_template == NULL))
    {
        CoglContext *ctx =
            clutter_backend_get_cogl_context (clutter_get_default_backend ());

        shadow_pipeline_template = cogl_pipeline_new (ctx);

        /* We set up the pipeline to blend the shadow texture with the combine
         * constant, but defer setting the latter until painting, so that we can
         * take the actor's overall opacity into account. */
        cogl_pipeline_set_layer_combine (shadow_pipeline_template, 0,
                                         "RGBA = MODULATE (CONSTANT, TEXTURE[A])",
                                         NULL);
    }

    pipeline = cogl_pipeline_copy (shadow_pipeline_template);
    cogl_pipeline_set_layer_texture (pipeline, 0, texture);
    cogl_object_unref (texture);
    return pipeline;
}
CoglHandle
_st_create_shadow_material (StShadow   *shadow_spec,
                            CoglHandle  src_texture)
{
  static CoglHandle shadow_material_template = COGL_INVALID_HANDLE;

  CoglHandle  material;
  CoglHandle  texture;
  guchar     *pixels_in, *pixels_out;
  gint        width_in, height_in, rowstride_in;
  gint        width_out, height_out, rowstride_out;

  g_return_val_if_fail (shadow_spec != NULL, COGL_INVALID_HANDLE);
  g_return_val_if_fail (src_texture != COGL_INVALID_HANDLE,
                        COGL_INVALID_HANDLE);

  width_in  = cogl_texture_get_width  (src_texture);
  height_in = cogl_texture_get_height (src_texture);
  rowstride_in = (width_in + 3) & ~3;

  pixels_in  = g_malloc0 (rowstride_in * height_in);

  cogl_texture_get_data (src_texture, COGL_PIXEL_FORMAT_A_8,
                         rowstride_in, pixels_in);

  pixels_out = blur_pixels (pixels_in, width_in, height_in, rowstride_in,
                            shadow_spec->blur,
                            &width_out, &height_out, &rowstride_out);
  g_free (pixels_in);

  texture = cogl_texture_new_from_data (width_out,
                                        height_out,
                                        COGL_TEXTURE_NONE,
                                        COGL_PIXEL_FORMAT_A_8,
                                        COGL_PIXEL_FORMAT_A_8,
                                        rowstride_out,
                                        pixels_out);

  g_free (pixels_out);

  if (G_UNLIKELY (shadow_material_template == COGL_INVALID_HANDLE))
    {
      shadow_material_template = cogl_material_new ();

      /* We set up the material to blend the shadow texture with the combine
       * constant, but defer setting the latter until painting, so that we can
       * take the actor's overall opacity into account. */
      cogl_material_set_layer_combine (shadow_material_template, 0,
                                       "RGBA = MODULATE (CONSTANT, TEXTURE[A])",
                                       NULL);
    }

  material = cogl_material_copy (shadow_material_template);

  cogl_material_set_layer (material, 0, texture);

  cogl_handle_unref (texture);

  return material;
}
Beispiel #3
0
/**
 * _st_create_shadow_cairo_pattern:
 * @shadow_spec: the definition of the shadow
 * @src_pattern: surface pattern for which we create the shadow
 *               (must be a surface pattern)
 *
 * This is a utility function for creating shadows used by
 * st-theme-node.c; it's in this file to share the gaussian
 * blur implementation. The usage of this function is quite different
 * depending on whether shadow_spec->inset is %TRUE or not. If
 * shadow_spec->inset is %TRUE, the caller should pass in a @src_pattern
 * which is the <i>inverse</i> of what they want shadowed, and must take
 * care of the spread and offset from the shadow spec themselves. If
 * shadow_spec->inset is %FALSE then the caller should pass in what they
 * want shadowed directly, and this function takes care of the spread and
 * the offset.
 */
cairo_pattern_t *
_st_create_shadow_cairo_pattern (StShadow        *shadow_spec,
                                 cairo_pattern_t *src_pattern)
{
    static cairo_user_data_key_t shadow_pattern_user_data;
    cairo_t *cr;
    cairo_surface_t *src_surface;
    cairo_surface_t *surface_in;
    cairo_surface_t *surface_out;
    cairo_pattern_t *dst_pattern;
    guchar          *pixels_in, *pixels_out;
    gint             width_in, height_in, rowstride_in;
    gint             width_out, height_out, rowstride_out;
    cairo_matrix_t   shadow_matrix;
    int i, j;

    g_return_val_if_fail (shadow_spec != NULL, NULL);
    g_return_val_if_fail (src_pattern != NULL, NULL);

    cairo_pattern_get_surface (src_pattern, &src_surface);

    width_in  = cairo_image_surface_get_width  (src_surface);
    height_in = cairo_image_surface_get_height (src_surface);

    /* We want the output to be a color agnostic alpha mask,
     * so we need to strip the color channels from the input
     */
    if (cairo_image_surface_get_format (src_surface) != CAIRO_FORMAT_A8)
    {
        surface_in = cairo_image_surface_create (CAIRO_FORMAT_A8,
                     width_in, height_in);

        cr = cairo_create (surface_in);
        cairo_set_source_surface (cr, src_surface, 0, 0);
        cairo_paint (cr);
        cairo_destroy (cr);
    }
    else
    {
        surface_in = cairo_surface_reference (src_surface);
    }

    pixels_in = cairo_image_surface_get_data (surface_in);
    rowstride_in = cairo_image_surface_get_stride (surface_in);

    pixels_out = blur_pixels (pixels_in, width_in, height_in, rowstride_in,
                              shadow_spec->blur,
                              &width_out, &height_out, &rowstride_out);
    cairo_surface_destroy (surface_in);

    /* Invert pixels for inset shadows */
    if (shadow_spec->inset)
    {
        for (j = 0; j < height_out; j++)
        {
            guchar *p = pixels_out + rowstride_out * j;
            for (i = 0; i < width_out; i++, p++)
                *p = ~*p;
        }
    }

    surface_out = cairo_image_surface_create_for_data (pixels_out,
                  CAIRO_FORMAT_A8,
                  width_out,
                  height_out,
                  rowstride_out);
    cairo_surface_set_user_data (surface_out, &shadow_pattern_user_data,
                                 pixels_out, (cairo_destroy_func_t) g_free);

    dst_pattern = cairo_pattern_create_for_surface (surface_out);
    cairo_surface_destroy (surface_out);

    cairo_pattern_get_matrix (src_pattern, &shadow_matrix);

    if (shadow_spec->inset)
    {
        /* For inset shadows, offsets and spread radius have already been
         * applied to the original pattern, so all left to do is shift the
         * blurred image left, so that it aligns centered under the
         * unblurred one
         */
        cairo_matrix_translate (&shadow_matrix,
                                (width_out - width_in) / 2.0,
                                (height_out - height_in) / 2.0);
        cairo_pattern_set_matrix (dst_pattern, &shadow_matrix);
        return dst_pattern;
    }

    /* Read all the code from the cairo_pattern_set_matrix call
     * at the end of this function to here from bottom to top,
     * because each new affine transformation is applied in
     * front of all the previous ones */

    /* 6. Invert the matrix back */
    cairo_matrix_invert (&shadow_matrix);

    /* 5. Adjust based on specified offsets */
    cairo_matrix_translate (&shadow_matrix,
                            shadow_spec->xoffset,
                            shadow_spec->yoffset);

    /* 4. Recenter the newly scaled image */
    cairo_matrix_translate (&shadow_matrix,
                            - shadow_spec->spread,
                            - shadow_spec->spread);

    /* 3. Scale up the blurred image to fill the spread */
    cairo_matrix_scale (&shadow_matrix,
                        (width_in + 2.0 * shadow_spec->spread) / width_in,
                        (height_in + 2.0 * shadow_spec->spread) / height_in);

    /* 2. Shift the blurred image left, so that it aligns centered
     * under the unblurred one */
    cairo_matrix_translate (&shadow_matrix,
                            - (width_out - width_in) / 2.0,
                            - (height_out - height_in) / 2.0);

    /* 1. Invert the matrix so we can work with it in pattern space
     */
    cairo_matrix_invert (&shadow_matrix);

    cairo_pattern_set_matrix (dst_pattern, &shadow_matrix);

    return dst_pattern;
}
Beispiel #4
0
void UnsharpUnit::process_package(LoadPackage *package)
{
	UnsharpPackage *pkg = (UnsharpPackage*)package;
//	int w = server->src->get_w();
//	int h = server->src->get_h();
	int color_model = server->src->get_color_model();
	int components = BC_CModels::components(color_model);
	double *cmatrix = 0;
	int cmatrix_length = 0;
	int padded_y1 = pkg->y1;
	int padded_y2 = pkg->y2;

	cmatrix_length = calculate_convolution_matrix(
		plugin->config.radius, 
		&cmatrix);


	if(padded_y2 < server->src->get_h())
	{
		padded_y2 += cmatrix_length / 2;
		padded_y2 = MIN(server->src->get_h(), padded_y2);
	}
	if(padded_y1 > 0)
	{
		padded_y1 -= cmatrix_length / 2;
		padded_y1 = MAX(0, padded_y1);
	}

	int padded_rows = padded_y2 - padded_y1;

	if(!temp || temp->get_h() != padded_rows)
	{
		delete temp;
		temp = 0;
	}

	if(!temp)
	{
		temp = new VFrame;
		temp->set_use_shm(0);
		temp->reallocate(0,
			-1,
			0,
			0,
			0,
			server->src->get_w(),
			padded_rows,
			components == 3 ? BC_RGB_FLOAT : BC_RGBA_FLOAT,
			-1);
	}

	float *temp_in = new float[MAX(temp->get_w(), padded_rows) * components];
	float *temp_out = new float[MAX(temp->get_w(), padded_rows) * components];

// Blur rows
	for(int i = padded_y1; i < padded_y2; i++)
	{
		get_row(temp_in, server->src, i);
		blur_pixels(cmatrix, 
			cmatrix_length,
			temp_in,
			temp_out,
			temp->get_w(),
			components);
// printf("UnsharpUnit::process_package %d %p %p %p %d %d\n", 
// __LINE__, 
// temp, 
// temp->get_rows()[0], 
// temp_out,
// i - padded_y1,
// temp->get_bytes_per_line());
		memcpy(temp->get_rows()[i - padded_y1],
		 	temp_out,
			temp->get_bytes_per_line());
	}

//Now we're 100% floating point.  Blur the columns
	for(int i = 0; i < temp->get_w(); i++)
	{
		get_column(temp_in, temp, i);
		blur_pixels(cmatrix,
			cmatrix_length,
			temp_in,
			temp_out,
			padded_rows,
			components);
		put_column(temp_out, temp, i);
	}


//printf("%f %f %d\n", plugin->config.radius,plugin->config.amount, plugin->config.threshold);


#define UNSHARPEN(type, components, max) \
{ \
	float threshold = (float)plugin->config.threshold * max / 0xff; \
	float amount = plugin->config.amount; \
 \
	for(int i = pkg->y1; i < pkg->y2; i++) \
	{ \
		float *blurry_row = (float*)temp->get_rows()[i - padded_y1]; \
		type *orig_row = (type*)server->src->get_rows()[i]; \
		for(int j = 0; j < server->src->get_w(); j++) \
		{ \
			for(int k = 0; k < components; k++) \
			{ \
				float diff = *orig_row - *blurry_row; \
				if(fabsf(2 * diff) < threshold) \
					diff = 0; \
				float value = *orig_row + amount * diff; \
				if(sizeof(type) == 4) \
					*orig_row = (type)value; \
				else \
					*orig_row = (type)CLIP(value, 0, max); \
				blurry_row++; \
				orig_row++; \
			} \
		} \
	} \
}

// Apply unsharpening
	switch(color_model)
	{
		case BC_RGB888:
		case BC_YUV888:
			UNSHARPEN(unsigned char, 3, 0xff);
			break;
		case BC_RGBA8888:
		case BC_YUVA8888:
			UNSHARPEN(unsigned char, 4, 0xff);
			break;
		case BC_RGB_FLOAT:
			UNSHARPEN(float, 3, 1.0);
			break;
		case BC_RGBA_FLOAT:
			UNSHARPEN(float, 4, 1.0);
			break;
		case BC_YUV161616:
			UNSHARPEN(uint16_t, 3, 0xffff);
			break;
		case BC_YUVA16161616:
			UNSHARPEN(uint16_t, 4, 0xffff);
			break;
	}

	delete [] temp_in;
	delete [] temp_out;
	delete [] cmatrix;
}