pixel* Cartoon(pixel* image, int lines, int colors, int width, int height, pixel* output) { int i, length; length = width * height; pixel* copy = pixel_copy(image, width, height); Sobel_Edges(image, 0, 0, width, height, output); // custom threshold for multiplication for(i = 0; i < length; i++) { pixel oldPixel = output[i]; if(oldPixel.red > lines) oldPixel.red = oldPixel.blue = oldPixel.green = 0; else oldPixel.red = oldPixel.blue = oldPixel.green = 1; output[i] = oldPixel; } Posterize(copy, colors, width, height, copy); for(i = 0; i < length; i++) { pixel outputPixel = output[i]; pixel copyPixel = copy[i]; outputPixel.red *= copyPixel.red; outputPixel.blue *= copyPixel.blue; outputPixel.green *= copyPixel.green; output[i] = outputPixel; } free(copy); return output; }
pixel* Fast_Edges(pixel* image, int threshold, int width, int height, pixel* output) { int i, j, a, b, sum; int length = width * height; short quick_mask[3][3] = { {-1, 0, -1}, { 0, 4, 0}, {-1, 0, -1} }; pixel* copy = pixel_copy(image, width, height); RGB_to_Gray_PixelArray(image, width, height, copy); for(i=1; i<height-1; i++) { for(j=1; j<width-1; j++) { sum = 0; for(a=-1; a<2; a++) { for(b=-1; b<2; b++) { sum = sum + copy[(i*width)+(a*width)+j+b].red * quick_mask[a+1][b+1]; } } if(sum < 0) sum = 0; if(sum > 255) sum = 255; pixel newPixel; newPixel.red = newPixel.green = newPixel.blue = sum; newPixel.alpha = 255; output[i*width + j] = newPixel; } } // threshold Threshold(output, threshold, width, height, output); free(copy); return output; }
static void despeckle_median (guchar *src, guchar *dst, gint width, gint height, gint bpp, gint radius, gboolean preview) { guint progress; guint max_progress; gint x, y; gint input_radius = radius; gint pos; gint ymin; gint ymax; gint xmin; gint xmax; memset (&histogram, 0, sizeof(histogram)); progress = 0; max_progress = width * height; if (! preview) gimp_progress_init(_("Despeckle")); for (y = 0; y < height; y++) { x = 0; ymin = MAX (0, y - radius); ymax = MIN (height - 1, y + radius); xmin = MAX (0, x - radius); xmax = MIN (width - 1, x + radius); hist0 = 0; histrest = 0; hist255 = 0; histogram_clean (&histogram); histogram.xmin = xmin; histogram.ymin = ymin; histogram.xmax = xmax; histogram.ymax = ymax; add_vals (&histogram, src, width, bpp, histogram.xmin, histogram.ymin, histogram.xmax, histogram.ymax); for (x = 0; x < width; x++) { const guchar *pixel; ymin = MAX (0, y - radius); /* update ymin, ymax when radius changed (FILTER_ADAPTIVE) */ ymax = MIN (height - 1, y + radius); xmin = MAX (0, x - radius); xmax = MIN (width - 1, x + radius); update_histogram (&histogram, src, width, bpp, xmin, ymin, xmax, ymax); pos = (x + (y * width)) * bpp; pixel = histogram_get_median (&histogram, src + pos); if (filter_type & FILTER_RECURSIVE) { del_val (&histogram, src, width, bpp, x, y); pixel_copy (src + pos, pixel, bpp); add_val (&histogram, src, width, bpp, x, y); } pixel_copy (dst + pos, pixel, bpp); /* * Check the histogram and adjust the diameter accordingly... */ if (filter_type & FILTER_ADAPTIVE) { if (hist0 >= radius || hist255 >= radius) { if (radius < input_radius) radius++; } else if (radius > 1) { radius--; } } } progress += width; if (! preview && y % 32 == 0) gimp_progress_update ((gdouble) progress / (gdouble) max_progress); } if (! preview) gimp_progress_update (1.0); }