Jump to content

How to make GIF image transparent on windows form app

- - - - -

  • Please log in to reply
14 replies to this topic

#1
Doctor

Doctor

    Newbie

  • Members
  • PipPip
  • 23 posts
Hi, again me ..

I got transparent image saved in GIF format, and I want to put this image on other image. The problem is that this gif image is not transparet anymore when I use picturebox or pannel. I also set BackColor to transparent, but it not works :S ... here example:

Posted Image

That white background needs to be transparent .. how can I do that?

I'm using Microsoft Visual C# 2010 Express

#2
Alexander

Alexander

    It's Science!

  • Moderators
  • 4,118 posts
  • Location:Vancouver, Eh! Cleverness: 200
Is there an option to set the white to be the transparent colour?
Be sure to read the updated FAQ! || Health is achieved through the same 10,000 steps.
If a suggested code/method fails, informing us is less important than telling us why or what errors occurred.

#3
Doctor

Doctor

    Newbie

  • Members
  • PipPip
  • 23 posts
I already set BackColor to transparent ... so there is no other options where can I find white ... so no.

#4
zoranh

zoranh

    Programming Professional

  • Members
  • PipPipPipPipPip
  • 207 posts
Try this:
Bitmap bmp = new Bitmap(101, 101);

Color backColor = Color.YellowGreen;
Color foreColor = Color.DarkRed;

Brush backBrush = new SolidBrush(backColor);
Brush foreBrush = new SolidBrush(foreColor);

Rectangle rect = new Rectangle(0, 0, 101, 101);

using (Graphics gr = Graphics.FromImage(bmp))
{

    gr.FillRectangle(backBrush, rect);
    gr.FillEllipse(foreBrush, rect);

}

bmp.Save("circle.bmp", ImageFormat.Bmp);

bmp.MakeTransparent(backColor);
bmp.Save("circle.gif", ImageFormat.Gif);

Bitmap newBmp = new Bitmap(201, 201);

using (Graphics gr = Graphics.FromImage(newBmp))
{

    Rectangle newRect = new Rectangle(0, 0, 201, 201);
    gr.FillRectangle(backBrush, newRect);

    newRect = new Rectangle(15, 15, 171, 171);
    gr.FillRectangle(foreBrush, newRect);

    gr.DrawImage(newBmp, new Point(0, 0));
    gr.DrawImage(newBmp, new Point(0, 101));
    gr.DrawImage(newBmp, new Point(101, 0));
    gr.DrawImage(newBmp, new Point(101, 101));

}

newBmp.Save("circle1.bmp", ImageFormat.Bmp);

Edited by zoranh, 05 October 2010 - 04:11 AM.
Added code for "circle1.bmp"


#5
zoranh

zoranh

    Programming Professional

  • Members
  • PipPipPipPipPip
  • 207 posts
This code works fine when operating in memory. However, it seems that saving GIF with transparent color to a file doesn't work correctly. There are many texts about that problem on the Internet, but I've not found good answer to question - only saying that saving transparent GIF doesn't work in .NET Framework. There are couple of code samples stating that they're solving the issue, but I think they're not solving anything.

#6
zoranh

zoranh

    Programming Professional

  • Members
  • PipPipPipPipPip
  • 207 posts
Same thing works perfect with PNG format. This format was designed to overcome limitations of GIF, plus the problems caused by the fact that GIF seems to be the proprietary format due to proprietary LZW compression it uses.

Check out this code:
Bitmap bmp = new Bitmap(101, 101);

Color backColor = Color.YellowGreen;
Color foreColor = Color.DarkRed;

Brush backBrush = new SolidBrush(backColor);
Brush foreBrush = new SolidBrush(foreColor);

Rectangle rect = new Rectangle(0, 0, 101, 101);

using (Graphics gr = Graphics.FromImage(bmp))
{

    gr.FillRectangle(backBrush, rect);
    gr.FillEllipse(foreBrush, rect);

}

bmp.Save("circle.bmp", ImageFormat.Bmp);

bmp.MakeTransparent(backColor);
bmp.Save("circle.png", ImageFormat.Png);

Bitmap newBmp = new Bitmap(201, 201);

Image loadedImg = Image.FromFile("circle.png", true);

using (Graphics gr = Graphics.FromImage(newBmp))
{

    Rectangle newRect = new Rectangle(0, 0, 201, 201);
    gr.FillRectangle(backBrush, newRect);

    newRect = new Rectangle(15, 15, 171, 171);
    gr.FillRectangle(foreBrush, newRect);

    gr.DrawImage(loadedImg, new Point(0, 0));
    gr.DrawImage(loadedImg, new Point(0, 101));
    gr.DrawImage(loadedImg, new Point(101, 0));
    gr.DrawImage(loadedImg, new Point(101, 101));

}

newBmp.Save("circle1.bmp", ImageFormat.Bmp);
newBmp.Save("circle1.png", ImageFormat.Png);
It saves the image with transparency color into PNG file, then loads that file and uses the image as a partially transparent pasted on top of another image. Since transparent parts of the image do not cover the second image, it proves that PNG file was actually saved correctly.

Also note that PNG format is better than GIF - images are sharper than in GIF, there is no dithering, but still small in size.

#7
Doctor

Doctor

    Newbie

  • Members
  • PipPip
  • 23 posts
Thanks for all your posts zoranh, but I still dont get it :S

This code that you posted creates image with 4 cycles and a square in the middle ... what can I do it with?
Maybe we understand wrong. I already have image saved in GIF, and I also save it into png and tried with both ...

here is the origianl image from 1st post:
Posted Image

This image already have transparent background .. the problem is, when I use PictureBox to insert it on form it looses transparent background ...
Actually the background changes to the color of the main form background.

Posted Image

at the end I want to have last picture ... now it stops at 2nd

#8
zoranh

zoranh

    Programming Professional

  • Members
  • PipPipPipPipPip
  • 207 posts
In that case, I think you shouldn't use the PictureBox, but rather draw directly on background image.

Check out this modified code:
Bitmap bmp = new Bitmap(101, 101);

Color backColor = Color.YellowGreen;
Color rectangleBackColor = Color.Brown;
Color foreColor = Color.DarkRed;

Brush backBrush = new SolidBrush(backColor);
Brush rectangleBackBrush = new SolidBrush(rectangleBackColor);
Brush foreBrush = new SolidBrush(foreColor);

Rectangle rect = new Rectangle(0, 0, 101, 101);

using (Graphics gr = Graphics.FromImage(bmp))
{

    gr.FillRectangle(backBrush, rect);
    gr.FillEllipse(foreBrush, rect);

}

//bmp.Save("circle.bmp", ImageFormat.Bmp);

bmp.MakeTransparent(backColor);
//bmp.Save("circle.png", ImageFormat.Png);

Bitmap newBmp = new Bitmap(201, 201);

//Image loadedImg = Image.FromFile("circle.png", true);

using (Graphics gr = Graphics.FromImage(newBmp))
{

    Rectangle newRect = new Rectangle(0, 0, 201, 201);
    gr.FillRectangle(backBrush, newRect);

    newRect = new Rectangle(15, 15, 171, 171);
    gr.FillRectangle(rectangleBackBrush, newRect);

    gr.DrawImage(bmp, new Point(0, 0));
    gr.DrawImage(bmp, new Point(0, 101));
    gr.DrawImage(bmp, new Point(101, 0));
    gr.DrawImage(bmp, new Point(101, 101));

}

//newBmp.Save("circle1.bmp", ImageFormat.Bmp);
newBmp.Save("circle1.png", ImageFormat.Png);
It's drawing inner rectangle in a different color just to show that four circles are drawn with their rectangular background being transparent. I would use this technique to draw transparent image on a background, rather than using PictureBox.

#9
Doctor

Doctor

    Newbie

  • Members
  • PipPip
  • 23 posts
OK, I'm trying to do something:

Bitmap myBitmap = new Bitmap("xxxxxxxxxxx\\Pictures\\iso.png");
Graphics g = Graphics.FromImage(myBitmap);
g.DrawImage(myBitmap, 100, 100, 100, 100);

I just want to draw simple image .... I tried with that code, but nothing happens.
Maybe parameters at g.DrawImage are wrong?? How can I draw that image on form?

#10
zoranh

zoranh

    Programming Professional

  • Members
  • PipPipPipPipPip
  • 207 posts
You can't use Graphics object created from myBitmap to draw - in that case you're drawing the bitmap over itself, effectively doing nothing. I'll try to provide you tomorrow a sample code which works with Form.

#11
zoranh

zoranh

    Programming Professional

  • Members
  • PipPipPipPipPip
  • 207 posts
Here is a test application which demonstrates how to work with transparent images in picture box.
using System;
using System.Threading;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;

namespace Test
{

    class Program
    {

        static Image GetBackImage()
        {

            Bitmap bmp = new Bitmap(400, 200);

            using (Graphics g = Graphics.FromImage(bmp))
            {

                g.FillRectangle(Brushes.LightSteelBlue, new Rectangle(0, 0, bmp.Width, bmp.Height));

                for (int i = 5; i < bmp.Height; i += 20)
                    for (int j = 5; j < bmp.Width; j += 20)
                        g.FillRectangle(Brushes.DarkBlue, new Rectangle(j, i, 10, 10));
            }

            // Alterntively, load image from file

            return bmp;

        }

        static Image GetForeImage()
        {

            Bitmap bmp = new Bitmap(30, 30);
            Rectangle r = new Rectangle(0, 0, bmp.Width, bmp.Height);

            using (Graphics g = Graphics.FromImage(bmp))
            {

                g.FillRectangle(Brushes.White, r);
                g.FillEllipse(Brushes.DarkRed, r);

                bmp.MakeTransparent(Color.White);

            }

            // Alterntively, load image from file

            return bmp;

        }

        static Form CreateForm(ref PictureBox picBox)
        {

            Form f = new Form();

            f.Text = "Image test";
            f.FormBorderStyle = FormBorderStyle.FixedDialog;
            f.Size = new Size(500, 500);
            f.MinimizeBox = true;
            f.MaximizeBox = false;
            f.ControlBox = true;

            picBox = new PictureBox();
            picBox.BorderStyle = BorderStyle.None;

            _backImage = GetBackImage();
            picBox.Size = _backImage.Size;
            picBox.Image = _backImage;

            picBox.Left = (f.ClientRectangle.Width - picBox.Width) / 2;
            picBox.Top = (f.ClientRectangle.Height - picBox.Height) / 2;

            f.Controls.Add(picBox);

            return f;

        }

        static Image CombineImages(Image back, Image fore, PointF pf)
        {

            Image combined = back.Clone() as Image;

            using (Graphics g = Graphics.FromImage(combined))
            {
                g.DrawImage(fore, pf);
            }

            return combined;

        }

        delegate void SetImageDelegate(PictureBox pb, Image img);

        static void SetImage(PictureBox pb, Image img)
        {
            pb.Image = img;
        }

        static void TimerEllapsed(object state)
        {

            lock (_sync)
            {

                if (_foreImage == null)
                    _foreImage = GetForeImage();

                int steps = 200;
                float height = (_backImage.Height + _foreImage.Height) * _iteration / (float)steps - _foreImage.Height;
                float width = (_backImage.Width + _foreImage.Width) * _iteration / (float)steps - _foreImage.Width;

                _iteration = (_iteration + 1) % steps;

                Image img = CombineImages(_backImage, _foreImage, new PointF(width, height));

                PictureBox pb = state as PictureBox;

                pb.BeginInvoke(new SetImageDelegate(SetImage), pb, img);

            }

        }

        static void Main(string[] args)
        {

            _form = CreateForm(ref _pictureBox);

            _form.HandleCreated += new EventHandler(FormHandleCreated);

            _form.ShowDialog();

        }

        static void FormHandleCreated(object sender, EventArgs e)
        {
            _timer = new System.Threading.Timer(new TimerCallback(TimerEllapsed), _pictureBox, 20, 20);
        }

        static Image _backImage;

        static Image _foreImage;

        static int _iteration;

        static object _sync = new object();

        static System.Threading.Timer _timer;

        static Form _form;

        static PictureBox _pictureBox;

    }

}
In this code, specific background image is kept aside and it's used to create new image which is set to PictureBox each time when picture has to be changed. At any time, PictureBox has its own image set and nobody is drawing over it.

Before compiling this code, add references to System.Drawing and System.Windows.Forms libraries.

Attached is the compiled executable, hopefully without viruses.

EDIT: Added thread safety. PictureBox is now updated on control's thread rather than thread executing timer.

Attached Files


Edited by zoranh, 08 October 2010 - 12:10 PM.
Added thread safety.


#12
Doctor

Doctor

    Newbie

  • Members
  • PipPip
  • 23 posts
Thanks zoranh.
Here is the code that I needed :)

namespace debug_app

{

  public partial class Form1 : Form

  {

    private Bitmap ozadje;

    private Bitmap iso;

    private Bitmap skupaj;




        public Form1()

    {

      InitializeComponent();

      ozadje = new Bitmap("C:\\Users\\Tilen\\Documents\\Visual Studio 2010\\Projects\\Test\\Test\\bin\\Debug\\Pictures\\bg0.jpg");

      iso = new Bitmap("C:\\Users\\Tilen\\Documents\\Visual Studio 2010\\Projects\\Test\\Test\\bin\\Debug\\Pictures\\iso.gif");

      Graphics g = Graphics.FromImage(ozadje);

      g.DrawImage(iso, 50, 48);

      pictureBox1.Image = ozadje;

    } 

  }

}

Now here is another problem ... how can I detect when user click on "iso" image which is drawn in "ozadje" image? (event handler or something .. ?)

Edit:

private Rectangle rectA = new Rectangle(50, 48, 300, 300);


private void Form1_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)

        {

          Point mousePt = new Point(e.X, e.Y);


          if (rectA.Contains(mousePt)) MessageBox.Show("lol");

        }

I found this on google ... but its not working ..




1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users