private void LoadImage(WriteableBitmap bitmap) { if (bitmap.PixelWidth != 0 && bitmap.PixelHeight != 0) { this.loadedBitmap = bitmap; CartoonGenTaskData task_data = new CartoonGenTaskData(); task_data.radius = this.gaussianRadius; task_data.threshold = this.cartoonThreshold; task_data.width = bitmap.PixelWidth; task_data.height = bitmap.PixelHeight; task_data.pixels = bitmap.Pixels; this.cartoonGeneratorWorker.RunWorkerAsync(task_data); this.GenerationProgressIndicator.IsVisible = true; } }
private void StartCartoonGenerator() { if (this.scaledBitmap != null) { try { CartoonGenTaskData task_data = new CartoonGenTaskData(); task_data.radius = this.gaussianRadius; task_data.threshold = this.cartoonThreshold; task_data.width = this.scaledBitmap.PixelWidth; task_data.height = this.scaledBitmap.PixelHeight; task_data.pixels = this.scaledBitmap.Pixels; this.cartoonGeneratorWorker.RunWorkerAsync(task_data); this.GenerationProgressIndicator.IsVisible = true; } catch (Exception) { // Ignore } } }
private void cartoonGeneratorWorker_DoWork(object sender, DoWorkEventArgs e) { int radius = (e.Argument as CartoonGenTaskData).radius; int threshold = (e.Argument as CartoonGenTaskData).threshold; int width = (e.Argument as CartoonGenTaskData).width; int height = (e.Argument as CartoonGenTaskData).height; int[] pixels = (e.Argument as CartoonGenTaskData).pixels; // Make Gaussian blur of original image, if applicable int[] blur_pixels = pixels.Clone() as int[]; if (radius != 0) { int[] tab = { 14, 10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 }; int alpha = (radius < 1) ? 16 : (radius > 17) ? 1 : tab[radius - 1]; int r1 = 0; int r2 = height - 1; int c1 = 0; int c2 = width - 1; int[] rgba = new int[4]; for (int col = c1; col <= c2; col++) { int s = r1 * width + col; for (int i = 0; i < 4; i++) { rgba[i] = ((blur_pixels[s] >> (i * 8)) & 0xFF) << 4; } s += width; for (int j = r1; j < r2; j++, s += width) { int p = 0; for (int i = 0; i < 4; i++) { p = p | ((((rgba[i] += ((((blur_pixels[s] >> (i * 8)) & 0xFF) << 4) - rgba[i]) * alpha / 16) >> 4) & 0xFF) << (i * 8)); } blur_pixels[s] = p; } } for (int row = r1; row <= r2; row++) { int s = row * width + c1; for (int i = 0; i < 4; i++) { rgba[i] = ((blur_pixels[s] >> (i * 8)) & 0xFF) << 4; } s++; for (int j = c1; j < c2; j++, s++) { int p = 0; for (int i = 0; i < 4; i++) { p = p | ((((rgba[i] += ((((blur_pixels[s] >> (i * 8)) & 0xFF) << 4) - rgba[i]) * alpha / 16) >> 4) & 0xFF) << (i * 8)); } blur_pixels[s] = p; } } for (int col = c1; col <= c2; col++) { int s = r2 * width + col; for (int i = 0; i < 4; i++) { rgba[i] = ((blur_pixels[s] >> (i * 8)) & 0xFF) << 4; } s -= width; for (int j = r1; j < r2; j++, s -= width) { int p = 0; for (int i = 0; i < 4; i++) { p = p | ((((rgba[i] += ((((blur_pixels[s] >> (i * 8)) & 0xFF) << 4) - rgba[i]) * alpha / 16) >> 4) & 0xFF) << (i * 8)); } blur_pixels[s] = p; } } for (int row = r1; row <= r2; row++) { int s = row * width + c2; for (int i = 0; i < 4; i++) { rgba[i] = ((blur_pixels[s] >> (i * 8)) & 0xFF) << 4; } s--; for (int j = c1; j < c2; j++, s--) { int p = 0; for (int i = 0; i < 4; i++) { p = p | ((((rgba[i] += ((((blur_pixels[s] >> (i * 8)) & 0xFF) << 4) - rgba[i]) * alpha / 16) >> 4) & 0xFF) << (i * 8)); } blur_pixels[s] = p; } } } // Apply Cartoon filter byte[] src_buf = new byte[width * height * 4]; byte[] dst_buf = new byte[width * height * 4]; for (int i = 0; i < blur_pixels.Length; i++) { byte[] color = BitConverter.GetBytes(blur_pixels[i]); src_buf[i * 4] = color[2]; src_buf[i * 4 + 1] = color[1]; src_buf[i * 4 + 2] = color[0]; src_buf[i * 4 + 3] = color[3]; } int offset; int blue_g, green_g, red_g; int blue, green, red; bool exceeds_threshold; for (int y = 1; y < height - 1; y++) { for (int x = 1; x < width - 1; x++) { offset = y * width * 4 + x * 4; blue_g = Math.Abs(src_buf[offset - 4] - src_buf[offset + 4]); blue_g += Math.Abs(src_buf[offset - width * 4] - src_buf[offset + width * 4]); offset++; green_g = Math.Abs(src_buf[offset - 4] - src_buf[offset + 4]); green_g += Math.Abs(src_buf[offset - width * 4] - src_buf[offset + width * 4]); offset++; red_g = Math.Abs(src_buf[offset - 4] - src_buf[offset + 4]); red_g += Math.Abs(src_buf[offset - width * 4] - src_buf[offset + width * 4]); if (blue_g + green_g + red_g > threshold) { exceeds_threshold = true; } else { offset -= 2; blue_g = Math.Abs(src_buf[offset - 4] - src_buf[offset + 4]); offset++; green_g = Math.Abs(src_buf[offset - 4] - src_buf[offset + 4]); offset++; red_g = Math.Abs(src_buf[offset - 4] - src_buf[offset + 4]); if (blue_g + green_g + red_g > threshold) { exceeds_threshold = true; } else { offset -= 2; blue_g = Math.Abs(src_buf[offset - width * 4] - src_buf[offset + width * 4]); offset++; green_g = Math.Abs(src_buf[offset - width * 4] - src_buf[offset + width * 4]); offset++; red_g = Math.Abs(src_buf[offset - width * 4] - src_buf[offset + width * 4]); if (blue_g + green_g + red_g > threshold) { exceeds_threshold = true; } else { offset -= 2; blue_g = Math.Abs(src_buf[offset - 4 - width * 4] - src_buf[offset + 4 + width * 4]); blue_g += Math.Abs(src_buf[offset + 4 - width * 4] - src_buf[offset - 4 + width * 4]); offset++; green_g = Math.Abs(src_buf[offset - 4 - width * 4] - src_buf[offset + 4 + width * 4]); green_g += Math.Abs(src_buf[offset + 4 - width * 4] - src_buf[offset - 4 + width * 4]); offset++; red_g = Math.Abs(src_buf[offset - 4 - width * 4] - src_buf[offset + 4 + width * 4]); red_g += Math.Abs(src_buf[offset + 4 - width * 4] - src_buf[offset - 4 + width * 4]); if (blue_g + green_g + red_g > threshold) { exceeds_threshold = true; } else { exceeds_threshold = false; } } } } offset -= 2; if (exceeds_threshold) { blue = 0; green = 0; red = 0; } else { blue = src_buf[offset]; green = src_buf[offset + 1]; red = src_buf[offset + 2]; } blue = (blue > 255 ? 255 : (blue < 0 ? 0 : blue)); green = (green > 255 ? 255 : (green < 0 ? 0 : green)); red = (red > 255 ? 255 : (red < 0 ? 0 : red)); dst_buf[offset] = (byte)blue; dst_buf[offset + 1] = (byte)green; dst_buf[offset + 2] = (byte)red; dst_buf[offset + 3] = src_buf[offset + 3]; } } int[] cartoon_pixels = new int[pixels.Length]; for (int i = 0; i < cartoon_pixels.Length; i++) { cartoon_pixels[i] = (dst_buf[i * 4 + 3] << 24) | (dst_buf[i * 4] << 16) | (dst_buf[i * 4 + 1] << 8) | dst_buf[i * 4 + 2]; } CartoonGenTaskData task_data = new CartoonGenTaskData(); task_data.radius = radius; task_data.threshold = threshold; task_data.width = width; task_data.height = height; task_data.pixels = cartoon_pixels; e.Result = task_data; }