2

My scenario:

  • I have one color background image JPG.
  • I have one black text on white background JPG.
  • Both images are the same size (height and width)

I want to overlay the image with black text and white background over the color background image, i.e. the white background becomes transparent to see the color background beneath it.

How can I do this with GDI in C#?

Thanks!

Bryan Denny
  • 27,363
  • 32
  • 109
  • 125

3 Answers3

2

Thanks to GalacticCowboy I was able to come up with this solution:

using (Bitmap background = (Bitmap)Bitmap.FromFile(backgroundPath))
{
     using (Bitmap foreground = (Bitmap)Bitmap.FromFile(foregroundPath))
     {
          // check if heights and widths are the same
          if (background.Height == foreground.Height & background.Width == foreground.Width)
          {
               using (Bitmap mergedImage = new Bitmap(background.Width, background.Height))
               {
                    for (int x = 0; x < mergedImage.Width; x++)
                    {
                         for (int y = 0; y < mergedImage.Height; y++)
                         {
                              Color backgroundPixel = background.GetPixel(x, y);
                              Color foregroundPixel = foreground.GetPixel(x, y);
                              Color mergedPixel = Color.FromArgb(backgroundPixel.ToArgb() & foregroundPixel.ToArgb());
                              mergedImage.SetPixel(x, y, mergedPixel);
                          }
                    }
                    mergedImage.Save("filepath");
               }

          }
     }
}

Works like a charm. Thanks!

Community
  • 1
  • 1
Bryan Denny
  • 27,363
  • 32
  • 109
  • 125
1

If the images are the same size, iterate over them and "AND" the colors for each pixel. For the white pixels, you should get the color of the other image, and for the black ones you should get black.

If they're not the same size, scale first.

I'm making this up off the top of my head, but something like:

Color destColor = Color.FromArgb(pixel1.ToArgb() & pixel2.ToArgb());
GalacticCowboy
  • 11,663
  • 2
  • 41
  • 66
  • This might work, both images are the same size. Can you provide a quick code snippet or a link to one? – Bryan Denny Jul 01 '09 at 21:09
  • You cannot AND color objects directly, you will need to AND the component values. – Ed S. Jul 01 '09 at 21:28
  • Thanks, I used this to come up with a solution: http://stackoverflow.com/questions/1071374/merging-jpgs-with-gdi-in-c/1074302#1074302 – Bryan Denny Jul 02 '09 at 13:23
  • You AND a Color object with an int. FromArgb returns a "Color", ToArgb return an int. – Ed S. Jul 07 '09 at 00:41
  • @Ed - I still don't see what you're seeing. Please read my code and tell me EXACTLY how I'm not doing EXACTLY what you say I need to do??????? – GalacticCowboy Jul 07 '09 at 01:44
  • PS - I know exactly what error you think I made; I'm just trying to point out that you mis-read my code and are complaining about an error that DOES NOT EXIST. – GalacticCowboy Jul 07 '09 at 18:08
1

There exist easier and faster way. You should use ImageAttributes when you draw image that must be partially visible.

Image BackImage = Image.FromFile(backgroundPath);
using (Graphics g = Graphics.FromImage(BackImage))
{
    using (ForeImage = Image.FromFile(foregroundPath))
    {   
        ImageAttributes imageAttr = new ImageAttributes();
        imageAttr.SetColorKey(Color.FromArgb(245, 245, 245), Color.FromArgb(255, 255, 255),
            ColorAdjustType.Default);
        g.DrawImage(ForeImage, new Rectangle(0, 0, BackImage.Width, BackImage.Height),
            0, 0, BackImage.Width, BackImage.Height, GraphicsUnit.Pixel, imageAttr);
    }
}

SetColorKey method will make color from specified range transparent, so you can make your white bitmap pixels transparent, including all pixels that are affected to jpeg compression artefacts.

arbiter
  • 9,447
  • 1
  • 32
  • 43
  • I haven't tried this, so I could be wrong, but a typical drawback of using a transparent color like this is that you get a sharp edge at the cut-over from transparent to opaque that would be softened if using another approach. – GalacticCowboy Jul 07 '09 at 01:57
  • I haven't tried it too, this snippet was written from head. But what I supposed to say, is that DrawImage has a lot of possibilities using ImageAttributes, so the authors task can be correctly done (after some additional investigation from his side) without slow pixel by pixel composition – arbiter Jul 07 '09 at 08:38
  • I guess it comes down to desired outcome - processing speed vs. image quality. I tried your approach and it is significantly faster (0.1 seconds vs. about 2 seconds, for 800x600 images) but there is a lot of noise around the edges of the text that gets blended away using my approach. – GalacticCowboy Jul 07 '09 at 18:12