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;
            }
        }
Exemple #2
0
        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
                }
            }
        }
Exemple #3
0
        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;
        }