static gboolean process (GeglOperation *operation, void *out_buf, glong n_pixels, const GeglRectangle *roi, gint level) { GeglChantO *o = GEGL_CHANT_PROPERTIES (operation); gfloat *out_pixel = out_buf; gfloat color1[4]; gfloat color2[4]; gint x, y; gfloat dx, dy; gfloat length = dist (o->x1, o->y1, o->x2, o->y2); gegl_color_get_pixel (o->color1, babl_format ("RGBA float"), color1); gegl_color_get_pixel (o->color2, babl_format ("RGBA float"), color2); x= roi->x; y= roi->y; dx = (o->x2-o->x1)/length; dy = (o->y2-o->y1)/length; while (n_pixels--) { gfloat v; gint c; if (length == 0.0) v = 0.5; else { v = (dx * x + dy * y) / length; if (v < 0.0) v = 0.0; else if (v>1.0) v = 1.0; } for (c=0;c<4;c++) out_pixel[c]=color1[c] * v + color2[c] * (1.0-v); out_pixel += 4; /* update x and y coordinates */ if (++x>=roi->x + roi->width) { x=roi->x; y++; } } return TRUE; }
static gboolean process (GeglOperation *operation, void *out_buf, glong n_pixels, const GeglRectangle *roi, gint level) { GeglProperties *o = GEGL_PROPERTIES (operation); gfloat *out_pixel = out_buf; gfloat color1[4], color2[4], length, dx, dy; dx = o->end_x - o->start_x; dy = o->end_y - o->start_y; length = dx * dx + dy * dy; if (GEGL_FLOAT_IS_ZERO (length)) { memset (out_buf, 0, n_pixels * sizeof(float) * 4); } else { gfloat vec0 = dx / length; gfloat vec1 = dy / length; gint x, y; gegl_color_get_pixel (o->start_color, babl_format ("R'G'B'A float"), color1); gegl_color_get_pixel (o->end_color, babl_format ("R'G'B'A float"), color2); for (y = roi->y; y < roi->y + roi->height; ++y) { for (x = roi->x; x < roi->x + roi->width; ++x) { gint c; gfloat v = vec0 * (x - o->start_x) + vec1 * (y - o->start_y); if (v > 1.0f - GEGL_FLOAT_EPSILON) v = 1.0f; if (v < 0.0f + GEGL_FLOAT_EPSILON) v = 0.0f; for (c = 0; c < 4; c++) out_pixel[c] = color1[c] * v + color2[c] * (1.0f - v); out_pixel += 4; } } } return TRUE; }
static gboolean checkerboard_cl_process (GeglOperation *operation, cl_mem out_tex, size_t global_worksize, const GeglRectangle *roi, gint level) { GeglProperties *o = GEGL_PROPERTIES (operation); const Babl *out_format = gegl_operation_get_format (operation, "output"); const size_t gbl_size[2] = {roi->width, roi->height}; const size_t gbl_offs[2] = {roi->x, roi->y}; cl_int cl_err = 0; float color1[4]; float color2[4]; if (!cl_data) { const char *kernel_name[] = {"kernel_checkerboard", NULL}; cl_data = gegl_cl_compile_and_build (checkerboard_cl_source, kernel_name); if (!cl_data) return TRUE; } gegl_color_get_pixel (o->color1, out_format, color1); gegl_color_get_pixel (o->color2, out_format, color2); cl_err = gegl_cl_set_kernel_args (cl_data->kernel[0], sizeof(cl_mem), &out_tex, sizeof(color1), &color1, sizeof(color2), &color2, sizeof(cl_int), &o->x, sizeof(cl_int), &o->y, sizeof(cl_int), &o->x_offset, sizeof(cl_int), &o->y_offset, NULL); CL_CHECK; cl_err = gegl_clEnqueueNDRangeKernel (gegl_cl_get_command_queue (), cl_data->kernel[0], 2, gbl_offs, gbl_size, NULL, 0, NULL, NULL); CL_CHECK; return FALSE; error: return TRUE; }
static gboolean process (GeglOperation *operation, void *in_buf, void *out_buf, glong n_pixels, const GeglRectangle *roi, gint level) { GeglProperties *o = GEGL_PROPERTIES (operation); const Babl *format = babl_format ("R'G'B'A float"); gfloat color[4]; gint x; gfloat *in_buff = in_buf; gfloat *out_buff = out_buf; gegl_color_get_pixel (o->color, format, color); for (x = 0; x < n_pixels; x++) { color_to_alpha (color, in_buff, out_buff); in_buff += 4; out_buff += 4; } return TRUE; }
static void prepare (GeglOperation *operation) { GeglProperties *o = GEGL_PROPERTIES (operation); const Babl *format = babl_format ("RGBA float"); GeglRectangle *whole_region; AlParamsType *params; if (! o->user_data) o->user_data = g_slice_new0 (AlParamsType); params = (AlParamsType *) o->user_data; whole_region = gegl_operation_source_get_bounding_box (operation, "input"); if (whole_region) { params->a = 0.5 * whole_region->width; params->b = 0.5 * whole_region->height; params->c = MIN (params->a, params->b); params->asqr = params->a * params->a; params->bsqr = params->b * params->b; params->csqr = params->c * params->c; } gegl_color_get_pixel (o->background_color, format, params->bg_color); gegl_operation_set_format (operation, "input", format); gegl_operation_set_format (operation, "output", format); }
static gboolean process (GeglOperation *operation, void *out_buf, glong n_pixels, const GeglRectangle *roi, gint level) { GeglProperties *o = GEGL_PROPERTIES (operation); gfloat *out_pixel = out_buf; gfloat color1[4]; gfloat color2[4]; gfloat length = dist (o->start_x, o->start_y, o->end_x, o->end_y); gegl_color_get_pixel (o->start_color, babl_format ("R'G'B'A float"), color1); gegl_color_get_pixel (o->end_color, babl_format ("R'G'B'A float"), color2); if (GEGL_FLOAT_IS_ZERO (length)) { gegl_memset_pattern (out_buf, color2, sizeof(float) * 4, n_pixels); } else { gint x, y; for (y = roi->y; y < roi->y + roi->height; ++y) { for (x = roi->x; x < roi->x + roi->width; ++x) { gint c; gfloat v = dist (x, y, o->start_x, o->start_y) / length; if (v > 1.0f - GEGL_FLOAT_EPSILON) v = 1.0f; for (c = 0; c < 4; c++) out_pixel[c] = color1[c] * v + color2[c] * (1.0f - v); out_pixel += 4; } } } return TRUE; }
static void prepare (GeglOperation *operation) { GeglProperties *o = GEGL_PROPERTIES (operation); const Babl *format = babl_format ("R'G'B'A float"); const Babl *colorformat = babl_format ("R'G'B' float"); CeParamsType *params; gfloat color_in[3]; gfloat color_out[3]; gint chan; if (o->user_data == NULL) o->user_data = g_slice_new0 (CeParamsType); params = (CeParamsType*) o->user_data; gegl_color_get_pixel (o->from_color, colorformat, &color_in); gegl_color_get_pixel (o->to_color, colorformat, &color_out); params->min[0] = CLAMP (color_in[0] - o->red_threshold, 0.0, 1.0) - GEGL_FLOAT_EPSILON; params->max[0] = CLAMP (color_in[0] + o->red_threshold, 0.0, 1.0) + GEGL_FLOAT_EPSILON; params->min[1] = CLAMP (color_in[1] - o->green_threshold, 0.0, 1.0) - GEGL_FLOAT_EPSILON; params->max[1] = CLAMP (color_in[1] + o->green_threshold, 0.0, 1.0) + GEGL_FLOAT_EPSILON; params->min[2] = CLAMP (color_in[2] - o->blue_threshold, 0.0, 1.0) - GEGL_FLOAT_EPSILON; params->max[2] = CLAMP (color_in[2] + o->blue_threshold, 0.0, 1.0) + GEGL_FLOAT_EPSILON; for (chan = 0; chan < 3; chan++) params->color_diff[chan] = color_out[chan] - color_in[chan]; gegl_operation_set_format (operation, "input", format); gegl_operation_set_format (operation, "output", format); }
static gboolean cl_process (GeglOperation *operation, cl_mem in, cl_mem out, size_t global_worksize, const GeglRectangle *roi, gint level) { GeglProperties *o = GEGL_PROPERTIES (operation); gfloat color[4]; gegl_color_get_pixel (o->color, babl_format ("R'G'B'A float"), color); if (!cl_data) { const char *kernel_name[] = {"cl_color_to_alpha",NULL}; cl_data = gegl_cl_compile_and_build (color_to_alpha_cl_source, kernel_name); } if (!cl_data) return TRUE; else { cl_int cl_err = 0; cl_float4 f_color; f_color.s[0] = color[0]; f_color.s[1] = color[1]; f_color.s[2] = color[2]; f_color.s[3] = color[3]; cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 0, sizeof(cl_mem), (void*)&in); CL_CHECK; cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 1, sizeof(cl_mem), (void*)&out); CL_CHECK; cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 2, sizeof(cl_float4),(void*)&f_color); CL_CHECK; cl_err = gegl_clEnqueueNDRangeKernel(gegl_cl_get_command_queue (), cl_data->kernel[0], 1, NULL, &global_worksize, NULL, 0, NULL, NULL); CL_CHECK; } return FALSE; error: return TRUE; }
/** * Process the gegl filter * @param operation the given Gegl operation * @param input the input buffer. * @param output the output buffer. * @param result the region of interest. * @param level the level of detail * @return True, if the filter was successfull applied. */ static gboolean process (GeglOperation *operation, GeglBuffer *input, GeglBuffer *output, const GeglRectangle *result, gint level) { GeglProperties *o = GEGL_PROPERTIES (operation); const Babl *input_format = gegl_buffer_get_format (input); const int bytes_per_pixel = babl_format_get_bytes_per_pixel (input_format); /** * src_buf, dst_buf: * Input- and output-buffers, containing the whole selection, * the filter should be applied on. * * src_pixel, dst_pixel: * pointers to the current source- and destination-pixel. * Using these pointers, the reading and writing can be delayed till the * end of the loop. Hence src_pixel can also point to background_color if * necessary. */ guint8 *src_buf, *dst_buf, *src_pixel, *dst_pixel, background_color[bytes_per_pixel]; /** * (x, y): Position of the pixel we compute at the moment. * (width, height): Dimensions of the lens * pixel_offset: For calculating the pixels position in src_buf / dst_buf. */ gint x, y, width, height, pixel_offset, projected_pixel_offset; /** * Further parameters that are needed to calculate the position of a projected * further pixel at (x, y). */ gfloat a, b, c, asqr, bsqr, csqr, dx, dy, dysqr, projected_x, projected_y, refraction_index; gboolean keep_surroundings; width = result->width; height = result->height; refraction_index = o->refraction_index; keep_surroundings = o->keep_surroundings; gegl_color_get_pixel (o->background_color, input_format, background_color); a = 0.5 * width; b = 0.5 * height; c = MIN (a, b); asqr = a * a; bsqr = b * b; csqr = c * c; /** * Todo: We might want to change the buffers sizes, as the memory consumption * could be rather large.However, due to the lens, it might happen, that one pixel from the * images center gets stretched to the whole image, so we will still need * at least a src_buf of size (width/2) * (height/2) * 4 to be able to * process one quarter of the image. */ src_buf = gegl_malloc (width * height * bytes_per_pixel); dst_buf = gegl_malloc (width * height * bytes_per_pixel); gegl_buffer_get (input, result, 1.0, input_format, src_buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); for (y = 0; y < height; y++) { /* dy is the current pixels distance (in y-direction) of the lenses center */ dy = -((gfloat)y - b + 0.5); /** * To determine, whether the pixel is within the elliptical region affected * by the lens, we furthermore need the squared distance. So we calculate it * once for each row. */ dysqr = dy * dy; for (x = 0; x < width; x++) { /* Again we need to calculate the pixels distance from the lens dx. */ dx = (gfloat)x - a + 0.5; /* Given x and y we can now determine the pixels offset in our buffer. */ pixel_offset = (x + y * width) * bytes_per_pixel; /* As described above, we only read and write image data once. */ dst_pixel = &dst_buf[pixel_offset]; if (dysqr < (bsqr - (bsqr * dx * dx) / asqr)) { /** * If (x, y) is inside the affected region, we can find its projected * position, calculate the projected_pixel_offset and set the src_pixel * to where we want to copy the pixel-data from. */ find_projected_pos (asqr, bsqr, csqr, dx, dy, refraction_index, &projected_x, &projected_y); projected_pixel_offset = ( (gint)(-projected_y + b) * width + (gint)( projected_x + a) ) * bytes_per_pixel; src_pixel = &src_buf[projected_pixel_offset]; } else { /** * Otherwise (that is for pixels outside the lens), we could either leave * the image data unchanged, or set it to a specified 'background_color', * depending on the user input. */ if (keep_surroundings) src_pixel = &src_buf[pixel_offset]; else src_pixel = background_color; } /** * At the end, we can copy the src_pixel (which was determined above), to * dst_pixel. */ memcpy (dst_pixel, src_pixel, bytes_per_pixel); } } gegl_buffer_set (output, result, 0, gegl_buffer_get_format (output), dst_buf, GEGL_AUTO_ROWSTRIDE); gegl_free (dst_buf); gegl_free (src_buf); return TRUE; }
static gboolean process (GeglOperation *operation, GeglBuffer *input, GeglBuffer *output, const GeglRectangle *roi, gint level) { GeglRectangle src_rect; GeglRectangle *whole_region; GeglProperties *o = GEGL_PROPERTIES (operation); GeglOperationAreaFilter *op_area; op_area = GEGL_OPERATION_AREA_FILTER (operation); whole_region = gegl_operation_source_get_bounding_box (operation, "input"); if (gegl_operation_use_opencl (operation)) if (cl_process (operation, input, output, roi)) return TRUE; if (o->size_x * o->size_y < SQR (ALLOC_THRESHOLD_SIZE)) { gfloat background_color[4]; gfloat *input_buf = g_new (gfloat, (CHUNK_SIZE + o->size_x * 2) * (CHUNK_SIZE + o->size_y * 2) * 4); gfloat *output_buf = g_new (gfloat, SQR (CHUNK_SIZE) * 4); gint i, j; gegl_color_get_pixel (o->background, babl_format("RaGaBaA float"), background_color); for (j = 0; (j-1) * CHUNK_SIZE < roi->height; j++) for (i = 0; (i-1) * CHUNK_SIZE < roi->width; i++) { GeglRectangle chunked_result; GeglRectangle chunked_sizes; chunked_result = *GEGL_RECTANGLE (roi->x + i * CHUNK_SIZE, roi->y + j * CHUNK_SIZE, CHUNK_SIZE, CHUNK_SIZE); gegl_rectangle_intersect (&chunked_result, &chunked_result, roi); if (chunked_result.width < 1 || chunked_result.height < 1) continue; src_rect = chunked_result; src_rect.x -= op_area->left; src_rect.y -= op_area->top; src_rect.width += op_area->left + op_area->right; src_rect.height += op_area->top + op_area->bottom; gegl_buffer_get (input, &src_rect, 1.0, babl_format ("RaGaBaA float"), input_buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_CLAMP); gegl_rectangle_copy (&chunked_sizes, &chunked_result); chunked_sizes.x = 0; chunked_sizes.y = 0; set_rectangle (output_buf, &chunked_sizes, &chunked_sizes, chunked_result.width, background_color, GEGL_PIXELIZE_NORM_INFINITY); pixelize (input_buf, output_buf, &chunked_result, &src_rect, whole_region, o); gegl_buffer_set (output, &chunked_result, 0, babl_format ("RaGaBaA float"), output_buf, GEGL_AUTO_ROWSTRIDE); } g_free (input_buf); g_free (output_buf); } else { gegl_buffer_set_color (output, roi, o->background); pixelize_noalloc (input, output, roi, whole_region, o); } return TRUE; }
static gboolean cl_process (GeglOperation *operation, GeglBuffer *input, GeglBuffer *output, const GeglRectangle *roi) { const Babl *in_format = babl_format ("RaGaBaA float"); const Babl *out_format = babl_format ("RaGaBaA float"); gint err; gfloat bg_color[4]; gint norm; GeglOperationAreaFilter *op_area = GEGL_OPERATION_AREA_FILTER (operation); GeglProperties *o = GEGL_PROPERTIES (operation); GeglRectangle *image_extent; GeglBufferClIterator *i = gegl_buffer_cl_iterator_new (output, roi, out_format, GEGL_CL_BUFFER_WRITE); gint read = gegl_buffer_cl_iterator_add_2 (i, input, roi, in_format, GEGL_CL_BUFFER_READ, op_area->left, op_area->right, op_area->top, op_area->bottom, GEGL_ABYSS_CLAMP); gint aux = gegl_buffer_cl_iterator_add_aux (i, roi, in_format, op_area->left, op_area->right, op_area->top, op_area->bottom); gegl_color_get_pixel (o->background, babl_format ("RaGaBaA float"), bg_color); norm = 0; norm = o->norm == GEGL_PIXELIZE_NORM_EUCLIDEAN ? 1 : norm; norm = o->norm == GEGL_PIXELIZE_NORM_INFINITY ? 2 : norm; image_extent = gegl_operation_source_get_bounding_box (operation, "input"); while (gegl_buffer_cl_iterator_next (i, &err) && !err) { err = cl_pixelize(i->tex[read], i->tex[aux], i->tex[0], &i->roi[read], &i->roi[0], o->size_x, o->size_y, o->ratio_x, o->ratio_y, bg_color, norm, image_extent); if (err) { gegl_buffer_cl_iterator_stop (i); break; } } return !err; }
static void set_rectangle_noalloc (GeglBuffer *output, GeglRectangle *rect, GeglRectangle *rect_shape, GeglColor *color, GeglPixelizeNorm norm) { if (norm == GEGL_PIXELIZE_NORM_INFINITY) { GeglRectangle rect2; gegl_rectangle_intersect (&rect2, rect, rect_shape); gegl_buffer_set_color (output, &rect2, color); } else { GeglBufferIterator *gi; gint c, x, y; gfloat col[4]; gfloat center_x, center_y; gfloat shape_area = rect_shape->width * rect_shape->height; center_x = rect_shape->x + rect_shape->width / 2.0f; center_y = rect_shape->y + rect_shape->height / 2.0f; gegl_color_get_pixel (color, babl_format ("RaGaBaA float"), col); gi = gegl_buffer_iterator_new (output, rect, 0, babl_format ("RaGaBaA float"), GEGL_ACCESS_WRITE, GEGL_ABYSS_CLAMP); while (gegl_buffer_iterator_next (gi)) { gfloat *data = (gfloat*) gi->data[0]; GeglRectangle roi = gi->roi[0]; switch (norm) { case (GEGL_PIXELIZE_NORM_EUCLIDEAN): for (y = 0; y < roi.height; y++) for (x = 0; x < roi.width; x++) if (SQR ((x + roi.x - center_x) / (gfloat) rect_shape->width) + SQR ((y + roi.y - center_y) / (gfloat) rect_shape->height) <= 1.0f) for (c = 0; c < 4; c++) data [4 * (y * roi.width + x) + c] = col[c]; break; case (GEGL_PIXELIZE_NORM_MANHATTAN): for (y = 0; y < roi.height; y++) for (x = 0; x < roi.width; x++) if (fabsf (x + roi.x - center_x) * rect_shape->height + fabsf (y + roi.y - center_y) * rect_shape->width < shape_area) for (c = 0; c < 4; c++) data [4 * (y * roi.width + x) + c] = col[c]; break; case (GEGL_PIXELIZE_NORM_INFINITY): break; } } } }
static gboolean process (GeglOperation *op, void *in_buf, void *out_buf, glong samples, const GeglRectangle *roi, gint level) { GeglChantO *o = GEGL_CHANT_PROPERTIES (op); guint8 * GEGL_ALIGNED in_pixel; guint8 * GEGL_ALIGNED out_pixel; guint8 colorFrom[4]; guint8 colorTo[4]; guint8 threshold[4]; guint8 delta[4]; in_pixel = in_buf; out_pixel = out_buf; gegl_color_get_pixel (o->start_color, babl_format ("RGBA u8"), colorFrom); gegl_color_get_pixel (o->end_color, babl_format ("RGBA u8"), colorTo); threshold[0] = o->red_threshold; threshold[1] = o->blue_threshold; threshold[2] = o->green_threshold; for (glong i = 0; i < samples; i++) { if (in_pixel[0] >= CLAMP (colorFrom[0] - threshold[0], 0, 255) && in_pixel[0] <= CLAMP (colorFrom[0] + threshold[0], 0, 255) && in_pixel[1] >= CLAMP (colorFrom[1] - threshold[1], 0, 255) && in_pixel[1] <= CLAMP (colorFrom[1] + threshold[1], 0, 255) && in_pixel[2] >= CLAMP (colorFrom[2] - threshold[2], 0, 255) && in_pixel[2] <= CLAMP (colorFrom[2] + threshold[2], 0, 255)) { delta[0] = in_pixel[0] > colorFrom[0] ? in_pixel[0] - colorFrom[0] : colorFrom[0] - in_pixel[0]; delta[1] = in_pixel[1] > colorFrom[1] ? in_pixel[1] - colorFrom[1] : colorFrom[1] - in_pixel[1]; delta[2] = in_pixel[2] > colorFrom[2] ? in_pixel[2] - colorFrom[2] : colorFrom[2] - in_pixel[2]; out_pixel[0] = CLAMP (colorTo[0] + delta[0], 0, 255); out_pixel[1] = CLAMP (colorTo[1] + delta[1], 0, 255); out_pixel[2] = CLAMP (colorTo[2] + delta[2], 0, 255); } else { out_pixel[0] = in_pixel[0]; out_pixel[1] = in_pixel[1]; out_pixel[2] = in_pixel[2]; } out_pixel[3] = in_pixel[3]; in_pixel += 4; out_pixel += 4; } return TRUE; }
static gboolean checkerboard_process (GeglOperation *operation, void *out_buf, glong n_pixels, const GeglRectangle *roi, gint level) { GeglProperties *o = GEGL_PROPERTIES (operation); const Babl *out_format = gegl_operation_get_format (operation, "output"); gint pixel_size = babl_format_get_bytes_per_pixel (out_format); guchar *out_pixel = out_buf; void *color1 = alloca(pixel_size); void *color2 = alloca(pixel_size); gint y; const gint x_min = roi->x - o->x_offset; const gint y_min = roi->y - o->y_offset; const gint x_max = roi->x + roi->width - o->x_offset; const gint y_max = roi->y + roi->height - o->y_offset; const gint square_width = o->x; const gint square_height = o->y; if (level) return checkerboard_process_simple (operation, out_buf, n_pixels, roi, level); gegl_color_get_pixel (o->color1, out_format, color1); gegl_color_get_pixel (o->color2, out_format, color2); for (y = y_min; y < y_max; y++) { gint x = x_min; void *cur_color; /* Figure out which box we're in */ gint tilex = TILE_INDEX (x, square_width); gint tiley = TILE_INDEX (y, square_height); if ((tilex + tiley) % 2 == 0) cur_color = color1; else cur_color = color2; while (x < x_max) { /* Figure out how long this stripe is */ gint count; gint stripe_end = (TILE_INDEX (x, square_width) + 1) * square_width; stripe_end = stripe_end > x_max ? x_max : stripe_end; count = stripe_end - x; gegl_memset_pattern (out_pixel, cur_color, pixel_size, count); out_pixel += count * pixel_size; x = stripe_end; if (cur_color == color1) cur_color = color2; else cur_color = color1; } } return TRUE; }
static gboolean checkerboard_process_simple (GeglOperation *operation, void *out_buf, glong n_pixels, const GeglRectangle *roi, gint level) { gint factor = 1 << level; GeglProperties *o = GEGL_PROPERTIES (operation); const Babl *out_format = gegl_operation_get_format (operation, "output"); gint pixel_size = babl_format_get_bytes_per_pixel (out_format); guchar *out_pixel = out_buf; void *color1 = alloca(pixel_size); void *color2 = alloca(pixel_size); gint x = roi->x; /* initial x */ gint y = roi->y; /* and y coordinates */ gegl_color_get_pixel (o->color1, out_format, color1); gegl_color_get_pixel (o->color2, out_format, color2); while (n_pixels--) { gint nx,ny; if ((x - o->x_offset) < 0) { nx = div (x - o->x_offset + 1, o->x / factor).quot; } else { nx = div (x - o->x_offset, o->x / factor).quot; } if ((y - o->y_offset) < 0) { ny = div (y - o->y_offset + 1, o->y / factor).quot; } else { ny = div (y - o->y_offset, o->y / factor).quot; } /* shift negative cell indices */ nx -= (x - o->x_offset) < 0 ? 1 : 0; ny -= (y - o->y_offset) < 0 ? 1 : 0; if ( (nx+ny) % 2 == 0) memcpy (out_pixel, color1, pixel_size); else memcpy (out_pixel, color2, pixel_size); out_pixel += pixel_size; /* update x and y coordinates */ x++; if (x>=roi->x + roi->width) { x=roi->x; y++; } } return TRUE; }
gdouble * gegl_color_get_components (GeglColor *color, GValue *value, gint *components_length) { Babl *format; if (G_TYPE_POINTER == G_VALUE_TYPE(value)) format = g_value_get_pointer (value); else { *components_length = 0; return NULL; } if (!color || !format) { *components_length = 0; return NULL; } else { gint components = babl_format_get_n_components (format); gint bpp = babl_format_get_bytes_per_pixel (format); const Babl *comp_type = babl_format_get_type (format, 0); gdouble *result = g_new (gdouble, components); *components_length = components; if (comp_type == babl_type ("u8")) { int i; guint8 *pixel_buf = alloca (bpp * components); gegl_color_get_pixel (color, format, pixel_buf); for (i = 0; i < components; ++i) result[i] = pixel_buf[i]; } else if (comp_type == babl_type ("u16")) { int i; guint16 *pixel_buf = alloca (bpp * components); gegl_color_get_pixel (color, format, pixel_buf); for (i = 0; i < components; ++i) result[i] = pixel_buf[i]; } else if (comp_type == babl_type ("u32")) { int i; guint32 *pixel_buf = alloca (bpp * components); gegl_color_get_pixel (color, format, pixel_buf); for (i = 0; i < components; ++i) result[i] = pixel_buf[i]; } else if (comp_type == babl_type ("float")) { int i; float *pixel_buf = alloca (bpp * components); gegl_color_get_pixel (color, format, pixel_buf); for (i = 0; i < components; ++i) result[i] = pixel_buf[i]; } else if (comp_type == babl_type ("double")) { gegl_color_get_pixel (color, format, result); } else { g_free (result); *components_length = 0; } return result; } }
static gboolean cl_process (GeglOperation *operation, cl_mem in_tex, cl_mem out_tex, size_t global_worksize, const GeglRectangle *roi, gint level) { GeglChantO *o = GEGL_CHANT_PROPERTIES (operation); gfloat scale; gfloat radius0, radius1; gint roi_x, roi_y,x; gint midx, midy; GeglRectangle *bounds = gegl_operation_source_get_bounding_box (operation, "input"); gfloat length = hypot (bounds->width, bounds->height)/2; gfloat rdiff; gfloat cost, sint; gfloat color[4]; scale = bounds->width / (1.0 * bounds->height); scale = scale * (o->proportion) + 1.0 * (1.0-o->proportion); scale *= aspect_to_scale (o->squeeze); length = (bounds->width/2.0); if (scale > 1.0) length /= scale; gegl_color_get_pixel (o->color, babl_format ("RGBA float"), color); for (x=0; x<3; x++) /* premultiply */ color[x] *= color[3]; radius0 = o->radius * (1.0-o->softness); radius1 = o->radius; rdiff = radius1-radius0; if (fabs (rdiff) < 0.0001) rdiff = 0.0001; midx = bounds->x + bounds->width * o->x; midy = bounds->y + bounds->height * o->y; roi_x = roi->x; roi_y = roi->y; /* constant for all pixels */ cost = cos(-o->rotation * (G_PI*2/360.0)); sint = sin(-o->rotation * (G_PI*2/360.0)); if (!cl_data) { const char *kernel_name[] = {"vignette_cl",NULL}; cl_data = gegl_cl_compile_and_build (vignette_cl_source, kernel_name); } if (!cl_data) return TRUE; { const size_t gbl_size[2] = {roi->width, roi->height}; gint shape = (gint) o->shape; gfloat gamma = o->gamma; cl_int cl_err = 0; cl_float4 f_color; f_color.s[0] = color[0]; f_color.s[1] = color[1]; f_color.s[2] = color[2]; f_color.s[3] = color[3]; cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 0, sizeof(cl_mem), (void*)&in_tex); CL_CHECK; cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 1, sizeof(cl_mem), (void*)&out_tex); CL_CHECK; cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 2, sizeof(cl_float4),(void*)&f_color); CL_CHECK; cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 3, sizeof(cl_float), (void*)&scale); CL_CHECK; cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 4, sizeof(cl_float), (void*)&cost); CL_CHECK; cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 5, sizeof(cl_float), (void*)&sint); CL_CHECK; cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 6, sizeof(cl_int), (void*)&roi_x); CL_CHECK; cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 7, sizeof(cl_int), (void*)&roi_y); CL_CHECK; cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 8, sizeof(cl_int), (void*)&midx); CL_CHECK; cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 9, sizeof(cl_int), (void*)&midy); CL_CHECK; cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 10, sizeof(cl_int), (void*)&shape); CL_CHECK; cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 11, sizeof(cl_float), (void*)&gamma); CL_CHECK; cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 12, sizeof(cl_float), (void*)&length); CL_CHECK; cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 13, sizeof(cl_float), (void*)&radius0); CL_CHECK; cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 14, sizeof(cl_float), (void*)&rdiff); CL_CHECK; cl_err = gegl_clEnqueueNDRangeKernel(gegl_cl_get_command_queue (), cl_data->kernel[0], 2, NULL, gbl_size, NULL, 0, NULL, NULL); CL_CHECK; } return FALSE; error: return TRUE; }
static gboolean process (GeglOperation *operation, void *out_buf, glong n_pixels, const GeglRectangle *roi, gint level) { GeglChantO *o = GEGL_CHANT_PROPERTIES (operation); gfloat *out_pixel = out_buf; gfloat color1[4]; gfloat color2[4]; gint x = roi->x; /* initial x */ gint y = roi->y; /* and y coordinates */ gegl_color_get_pixel (o->color1, babl_format ("RGBA float"), color1); gegl_color_get_pixel (o->color2, babl_format ("RGBA float"), color2); while (n_pixels--) { gint nx,ny; if ((x - o->x_offset) < 0) { nx = div (x - o->x_offset + 1, o->x).quot; } else { nx = div (x - o->x_offset, o->x).quot; } if ((y - o->y_offset) < 0) { ny = div (y - o->y_offset + 1, o->y).quot; } else { ny = div (y - o->y_offset, o->y).quot; } /* shift negative cell indices */ nx -= (x - o->x_offset) < 0 ? 1 : 0; ny -= (y - o->y_offset) < 0 ? 1 : 0; if ( (nx+ny) % 2 == 0) { out_pixel[0]=color1[0]; out_pixel[1]=color1[1]; out_pixel[2]=color1[2]; out_pixel[3]=color1[3]; } else { out_pixel[0]=color2[0]; out_pixel[1]=color2[1]; out_pixel[2]=color2[2]; out_pixel[3]=color2[3]; } out_pixel += 4; /* update x and y coordinates */ x++; if (x>=roi->x + roi->width) { x=roi->x; y++; } } return TRUE; }
static gboolean process (GeglOperation *operation, GeglBuffer *input, GeglBuffer *output, const GeglRectangle *result, gint level) { GeglChantO *o = GEGL_CHANT_PROPERTIES (operation); LensValues lens; GeglRectangle boundary; gint i, j; gfloat *src_buf, *dst_buf; gfloat background[4]; boundary = *gegl_operation_source_get_bounding_box (operation, "input"); lens = lens_setup_calc (o, boundary); src_buf = g_new0 (gfloat, SQR (MAX_WH) * 4); dst_buf = g_new0 (gfloat, SQR (CHUNK_SIZE) * 4); gegl_color_get_pixel (o->background, babl_format ("RGBA float"), background); for (j = 0; (j-1) * CHUNK_SIZE < result->height; j++) for (i = 0; (i-1) * CHUNK_SIZE < result->width; i++) { GeglRectangle chunked_result; GeglRectangle area; gint x, y; chunked_result = *GEGL_RECTANGLE (result->x + i * CHUNK_SIZE, result->y + j * CHUNK_SIZE, CHUNK_SIZE, CHUNK_SIZE); gegl_rectangle_intersect (&chunked_result, &chunked_result, result); if (chunked_result.width < 1 || chunked_result.height < 1) continue; area = get_required (&boundary, &chunked_result, operation); clamp_area (&area, lens.centre_x, lens.centre_y); gegl_buffer_get (input, &area, 1.0, babl_format ("RGBA float"), src_buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_CLAMP); for (y = chunked_result.y; y < chunked_result.y + chunked_result.height; y++) for (x = chunked_result.x; x < chunked_result.x + chunked_result.width; x++) { lens_distort_func (src_buf, dst_buf, &area, &chunked_result, &boundary, &lens, x, y, input, background); } gegl_buffer_set (output, &chunked_result, 0, babl_format ("RGBA float"), dst_buf, GEGL_AUTO_ROWSTRIDE); } g_free (dst_buf); g_free (src_buf); return TRUE; }
static gboolean process (GeglOperation *operation, GeglBuffer *input, GeglBuffer *output, const GeglRectangle *result, gint level) { GeglChantO *o = GEGL_CHANT_PROPERTIES (operation); GeglOperationAreaFilter *op_area = GEGL_OPERATION_AREA_FILTER (operation); GeglRectangle boundary = get_effective_area (operation); GeglRectangle extended; const Babl *format = babl_format ("RGBA float"); GRand *gr = g_rand_new_with_seed (o->seed); gfloat color[4]; gint cols, rows, num_tiles, count; gint *random_indices; gfloat *dst_buf; gfloat *buf; Polygon poly; gint i; extended.x = CLAMP (result->x - op_area->left, boundary.x, boundary.x + boundary.width); extended.width = CLAMP (result->width + op_area->left + op_area->right, 0, boundary.width); extended.y = CLAMP (result->y - op_area->top, boundary.y, boundary.y + boundary.width); extended.height = CLAMP (result->height + op_area->top + op_area->bottom, 0, boundary.height); dst_buf = g_new0 (gfloat, extended.width * extended.height * 4); gegl_color_get_pixel (o->bg_color, format, color); i = extended.width * extended.height; buf = dst_buf; while (i--) { buf[0] = color[0]; buf[1] = color[1]; buf[2] = color[2]; buf[3] = color[3]; buf += 4; } cols = (result->width + o->tile_size - 1) / o->tile_size; rows = (result->height + o->tile_size - 1) / o->tile_size; num_tiles = (rows + 1) * (cols + 1); random_indices = g_new0 (gint, num_tiles); for (i = 0; i < num_tiles; i++) random_indices[i] = i; randomize_indices (num_tiles, random_indices, gr); for (count = 0; count < num_tiles; count++) { gint i, j, ix, iy; gdouble x, y, width, height, theta; i = random_indices[count] / (cols + 1); j = random_indices[count] % (cols + 1); x = j * o->tile_size + (o->tile_size / 4.0) - g_rand_double_range (gr, 0, (o->tile_size /2.0)) + result->x; y = i * o->tile_size + (o->tile_size / 4.0) - g_rand_double_range (gr, 0, (o->tile_size /2.0)) + result->y; width = (o->tile_size + g_rand_double_range (gr, -o->tile_size / 8.0, o->tile_size / 8.0)) * o->tile_saturation; height = (o->tile_size + g_rand_double_range (gr, -o->tile_size / 8.0, o->tile_size / 8.0)) * o->tile_saturation; theta = g_rand_double_range (gr, 0, 2 * G_PI); polygon_reset (&poly); polygon_add_point (&poly, -width / 2.0, -height / 2.0); polygon_add_point (&poly, width / 2.0, -height / 2.0); polygon_add_point (&poly, width / 2.0, height / 2.0); polygon_add_point (&poly, -width / 2.0, height / 2.0); polygon_rotate (&poly, theta); polygon_translate (&poly, x, y); ix = CLAMP (x, boundary.x, boundary.x + boundary.width - 1); iy = CLAMP (y, boundary.y, boundary.y + boundary.height - 1); gegl_buffer_sample (input, ix, iy, NULL, color, format, GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE); fill_poly_color (&poly, &extended, &boundary, dst_buf, color); } gegl_buffer_set (output, &extended, 0, format, dst_buf, GEGL_AUTO_ROWSTRIDE); g_free (dst_buf); g_free (random_indices); g_free (gr); return TRUE; }
static gboolean process (GeglOperation *operation, void *in_buf, void *out_buf, glong n_pixels, const GeglRectangle *roi, gint level) { GeglChantO *o = GEGL_CHANT_PROPERTIES (operation); gfloat *in_pixel = in_buf; gfloat *out_pixel = out_buf; gfloat scale; gfloat radius0, radius1; gint x, y; gint midx, midy; GeglRectangle *bounds = gegl_operation_source_get_bounding_box (operation, "input"); gfloat length = hypot (bounds->width, bounds->height)/2; gfloat rdiff; gfloat cost, sint; gfloat costy, sinty; gfloat color[4]; scale = bounds->width / (1.0 * bounds->height); scale = scale * (o->proportion) + 1.0 * (1.0-o->proportion); scale *= aspect_to_scale (o->squeeze); length = (bounds->width/2.0); if (scale > 1.0) length /= scale; gegl_color_get_pixel (o->color, babl_format ("RGBA float"), color); for (x=0; x<3; x++) /* premultiply */ color[x] *= color[3]; radius0 = o->radius * (1.0-o->softness); radius1 = o->radius; rdiff = radius1-radius0; if (fabs (rdiff) < 0.0001) rdiff = 0.0001; midx = bounds->x + bounds->width * o->x; midy = bounds->y + bounds->height * o->y; x = roi->x; y = roi->y; /* constant for all pixels */ cost = cos(-o->rotation * (G_PI*2/360.0)); sint = sin(-o->rotation * (G_PI*2/360.0)); /* constant per scanline */ sinty = sint * (y-midy) - midx; costy = cost * (y-midy) + midy; while (n_pixels--) { gfloat strength = 0.0; gfloat u, v; #if 0 u = cost * (x-midx) - sint * (y-midy) + midx; v = sint * (x-midx) + cost * (y-midy) + midy; /* optimized out of innerscanline loop */ #endif u = cost * (x-midx) - sinty; v = sint * (x-midx) + costy; if (length == 0.0) strength = 0.0; else { switch (o->shape) { case GEGl_VIGNETTE_SHAPE_CIRCLE: strength = hypot ((u-midx) / scale, v-midy); break; case GEGl_VIGNETTE_SHAPE_SQUARE: strength = MAX(ABS(u-midx) / scale, ABS(v-midy)); break; case GEGl_VIGNETTE_SHAPE_DIAMOND: strength = ABS(u-midx) / scale + ABS(v-midy); break; } strength /= length; strength = (strength-radius0) / rdiff; } if (strength<0.0) strength = 0.0; if (strength>1.0) strength = 1.0; if (o->gamma > 0.9999 && o->gamma < 2.0001) strength *= strength; /* fast path for default gamma */ else if (o->gamma != 1.0) strength = powf(strength, o->gamma); /* this gamma factor is * very expensive.. */ out_pixel[0]=in_pixel[0] * (1.0-strength) + color[0] * strength; out_pixel[1]=in_pixel[1] * (1.0-strength) + color[1] * strength; out_pixel[2]=in_pixel[2] * (1.0-strength) + color[2] * strength; out_pixel[3]=in_pixel[3] * (1.0-strength) + color[3] * strength; out_pixel += 4; in_pixel += 4; /* update x and y coordinates */ if (++x>=roi->x + roi->width) { x=roi->x; y++; sinty = sint * (y-midy) - midx; costy = cost * (y-midy) + midy; } } return TRUE; }