Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JPEG artifacts removal in C#

I am building a website for a club that is part of a mother organisation. I am downloading (leeching ;) ) the images that where put on profile pages of the mother organisation to show on my own page. But their website has a nice white background, and my website has a nice gray gradient on the background. This does not match nicely. So my idea was to edit the images before saving them to my server.

I am using GDI+ to enhance my images, and when I use the method MakeTransparent of Bitmap, it does work, and it does do what its supposed to do, but I still have these white jpeg artifacts all over the place. The artifacts makes the image so bad, I am better off not making the image transparent and just leaving it white, but thats really ugly on my own website. I can always at a nice border with a white background of course, but I rather change the background to transparent.

So I was wondering if and how I can remove some simple JPEG artifacts in C#. Has anyone ever done this before?

Thanks for your time.

Example image:

TB-5404

Transformed image:

TB-5404 transformed

like image 500
Arcturus Avatar asked Aug 02 '09 14:08

Arcturus


People also ask

How long does JPEG artifacts removal take?

Remove JPEG artifacts after compression here: Processing will take 1-20 sec.

What is a JPEG artifact?

JPEG artifacts are caused by compression when an image is saved in the . jpg format. Each time an image is saved in this format it is compressed and “non-essential” data is discarded. The result of compression is that an image can suffer from blockiness, mosquito noise (around edges) and color degradation.

How can compression artifacts be prevented?

To prevent compression artifacts, shoot in RAW and use non-destructive post-processing techniques when editing. If shooting directly to JPEG, use the camera's highest image quality setting (JPEG Fine, for example). Compress your footage as little as possible while staying under the 4GB limit.


1 Answers

Well, I attempted something that is far from perfect, but I figure it might be useful to someone else.

I have gotten to:

alt text

Problems encountered: the shadows are far enough from 'off white' that its difficult to auto convert them, and even if you did the shadow would still be in the image itself. The glare off the top... hub thing, is also closer to off white then the anti aliased bits. There are three to seven spots of white in the image which aren't connected to any of the primary corners; and finally there's still a bit of white on the edges (could probably get rid of it by tweaking the code, but not without taking off part of the glare top.

C# inefficient code:

    static void Main()
    {
        Bitmap bmp=new Bitmap("test.jpg");

        int width = bmp.Width;
        int height = bmp.Height;
        Dictionary<Point, int> currentLayer = new Dictionary<Point, int>();
        currentLayer[new Point(0, 0)] = 0;
        currentLayer[new Point(width - 1, height - 1)] = 0;
        while (currentLayer.Count != 0)
        {
            foreach (Point p in currentLayer.Keys)
                bmp.SetPixel(p.X, p.Y, Color.Black);
            Dictionary<Point, int> newLayer = new Dictionary<Point, int>();
            foreach (Point p in currentLayer.Keys)
                foreach (Point p1 in Neighbors(p, width, height))
                    if (Distance(bmp.GetPixel(p1.X, p1.Y), Color.White) < 40)
                        newLayer[p1] = 0;
            currentLayer = newLayer;
        }

        bmp.Save("test2.jpg");
    }

    static int Distance(Color c1, Color c2)
    {
        int dr = Math.Abs(c1.R - c2.R);
        int dg = Math.Abs(c1.G - c2.G);
        int db = Math.Abs(c1.B - c2.B);
        return Math.Max(Math.Max(dr, dg), db);
    }

    static List<Point> Neighbors(Point p, int maxX, int maxY)
    {
        List<Point> points=new List<Point>();
        if (p.X + 1 < maxX) points.Add(new Point(p.X + 1, p.Y));
        if (p.X - 1 >= 0) points.Add(new Point(p.X - 1, p.Y));
        if (p.Y + 1 < maxY) points.Add(new Point(p.X, p.Y + 1));
        if (p.Y - 1 >= 0) points.Add(new Point(p.X, p.Y - 1));
        return points;
    }

The code works by starting with two points; setting them to black, and then checking to see if any neighbors near them are near white; if they are they're added to a list which is then executed against. Eventually it runs out of white pixels to change.

As an alternative, you might want to consider redesigning the site to use a white background.

like image 71
CoderTao Avatar answered Sep 28 '22 17:09

CoderTao