How to remove the background of an image with an clippingPath using a pipeline in Graphicsmill?

186 Views Asked by At

I have a large image (at least 200 MB and up to 2 GB) with a clipping path. I want to apply the clipping path to remove the background. The only solution (ConvertClippingPathToMask) I have found so far uses a Bitmap, which loads the entire image into memory and throws an OutOfMemoryException.

    /// <summary>
    /// Converts clipping path to alpha channel mask
    /// </summary>
    private static void ConvertClippingPathToMask()
    {
        using (var reader = new JpegReader("../../../../_Input/Apple.jpg"))
        using (var bitmap = reader.Frames[0].GetBitmap()) // I can get rid of this line by using reader instead of bitmap in the next line, but then the OOM will throw in the next line.
        using (var maskBitmap = new Bitmap(bitmap.Width, bitmap.Height, PixelFormat.Format8bppGrayscale, new GrayscaleColor(0)))
        using (var graphics = maskBitmap.GetAdvancedGraphics())
        {
            var graphicsPath = reader.ClippingPaths[0].CreateGraphicsPath(reader.Width, reader.Height);

            graphics.FillPath(new SolidBrush(new GrayscaleColor(255)), Path.Create(graphicsPath));

            bitmap.Channels.SetAlpha(maskBitmap);

            bitmap.Save("../../../../_Output/ConvertClippingPathToMask.png");
        }
    }

By this approach a bitmap is always necessary to get the graphics object, which then applies the clipping path.

Actually, I don't even need the maskBitmap in Memory because I can use a separate reader for setAlpha, but then: How do I create the maskBitmap without a bitmap to create the graphics object from?

2

There are 2 best solutions below

1
On BEST ANSWER

The proper way is to use the Pipeline API:

using (var reader = new JpegReader("ImageWithPath.jpg"))
using (var gc = new GraphicsContainer(reader))
using (var ig = new ImageGenerator(gc, PixelFormat.Format8bppGrayscale, RgbColor.Black))
using (var setAlpha = new Aurigma.GraphicsMill.Transforms.SetAlpha())
{
    using (var gr = gc.GetGraphics())
    {
        var path = reader.ClippingPaths[0].CreateGraphicsPath(reader.Width, reader.Height);
        gr.FillPath(new SolidBrush(RgbColor.White), Aurigma.GraphicsMill.AdvancedDrawing.Path.Create(path));
    }

    setAlpha.AlphaSource = ig;

    Pipeline.Run(reader + setAlpha + "output.png");
}
0
On

For the sake of completeness:
This solutions by Fedor from Aurigma.Forums covers some cases, which Eugenes solution does not.

using (var reader = ImageReader.Create("../../../PathForTest.tif"))
using (var maskGen = new ImageGenerator(reader.Width, reader.Height, PixelFormat.Format8bppGrayscale, RgbColor.Black))
using (var drawer = new Drawer())
using (var bitmap = new Bitmap())
{
    var graphicsPath = Aurigma.GraphicsMill.AdvancedDrawing.Path.Create(reader.ClippingPaths[0], reader.Width, reader.Height);

    drawer.Draw += (sender, e) =>
    {
        e.Graphics.FillPath(new SolidBrush(new GrayscaleColor(255)), graphicsPath);
    };

    using (var setAlpha = new SetAlpha(maskGen + drawer))
    {
        (reader + setAlpha + bitmap).Run();
        bitmap.Save("../../../result.tif");
    }
}