views:

566

answers:

2

I've got two 16x16 RGB/A .ICO icon files, each loaded into a separate System.Drawing.Icon object.

How would you create a new Icon object containing the merge of the two icons (one overlaid on top of the other)?


Edit:
I probably wasn't too clear, I don't want to blend two images into each other, I want to overlay one icon on top of another.

I should add that the icons already contain transparent parts and I do not need any transparent "blending" to make both icons visible. What I need is to overlay the non-transparent pixels of one icon over the top of another icon. The transparent pixels should let the background icon show through.

For example, look at the stackoverflow icon. It has some areas that are grey and orange, and some areas that are totally transparent. Imagine you want to overlay the SO icon on top of the Firefox icon. You would see the greys and oranges of the SO icon in full colour, and where the SO icon is transparent, you would see those parts of the Firefox icon.

+3  A: 

EDIT

re: your comment: For starters... my image aren't black & transparent. They are black and white... both are set to 0.6f (60%) opacity so where there's a black on black (>100% black) or white on white (>100% white) it's look fine, but for the overlaps you'll have 60% white black mix which gives you the Gray color... what you could do is create 2 seperate ImageAttributes and tweak the opacities seperately to see if you can get the expected output (see altered code). It'll be have differently if your images have transparent sections.

took some code from here

The trick is to Draw each image with a transparency so that they can be seen through each other. Not specific to Icons so this should work for any image type. You can ToBitmap() your icons first to get them as Image Objects afaik.

Merged & Overlaid

    using(Image a = Image.FromFile("1.png"))
    using(Image b = Image.FromFile("2.png"))
    using (var bitmap = new Bitmap(200, 200))
    using (var canvas = Graphics.FromImage(bitmap))
    {
        Rectangle r = new Rectangle(new Point(0, 0), new Size(200, 200));
        ColorMatrix cmxPic = new ColorMatrix();
            cmxPic.Matrix33 = 1.0f;

            ImageAttributes iaPic = new ImageAttributes();
            iaPic.SetColorMatrix(cmxPic, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);

            ColorMatrix cmxPic2 = new ColorMatrix();
            cmxPic2.Matrix33 = 0.5f;

            ImageAttributes iaPic2 = new ImageAttributes();
            iaPic2.SetColorMatrix(cmxPic2, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);


            canvas.InterpolationMode = InterpolationMode.HighQualityBicubic;
            canvas.DrawImage(a, r, 0, 0, 200, 200, GraphicsUnit.Pixel, iaPic);
            canvas.DrawImage(b, r, 0, 0, 200, 200, GraphicsUnit.Pixel, iaPic2);
        canvas.Save();

        bitmap.Save("output.png", ImageFormat.Png);
    }
Eoin Campbell
Thanks, this is almost there but it doesn't quite work as I expected... in your example the Output.png does not show either set of lines clearly. Where there is black on black, it's OK, and where there is transparent on transparent, it's OK. But where there's black on transparent or vice versa it's turned grey. I expected it to be solid black gridlines throughout. I tried changing the transparency but it didn't help... any ideas?
demoncodemonkey
I'll update the answer slightly...
Eoin Campbell
Thanks for your help, turned out it was simpler than we both thought :)
demoncodemonkey
+2  A: 

Here's the final function I came up with. It was simpler than I thought...
Thanks to Eoin Campbell for doing the hard work.

public Icon AddIconOverlay(Icon originalIcon, Icon overlay)
{
    Image a = originalIcon.ToBitmap();
    Image b = overlay.ToBitmap();
    Bitmap bitmap = new Bitmap(16, 16);
    Graphics canvas = Graphics.FromImage(bitmap);
    canvas.DrawImage(a, new Point(0, 0));
    canvas.DrawImage(b, new Point(0, 0));
    canvas.Save();
    return Icon.FromHandle(bitmap.GetHicon());
}
demoncodemonkey