[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

microsoft.public.dotnet.framework.drawing

Creating Transparent Image from Two Bitmaps

Paul Welter

12/9/2004 10:23:00 PM

Hi,

I need some help in how to get started with creating a transparent image
from two bitmaps. The first image is the image to display, the second image
is a mask of the first image for the area that should be transparent. How
do I combine the two images to form a gif or tiff that has the mask as an
alpha channel for what is transparent in a single image?

thanks
Paul


3 Answers

Bob Powell

12/10/2004 5:02:00 PM

0

Creating the image is not difficult, storing it is. As far as I know only
the PNG encoder retains full colour and alpha information.

As to the method of doing this, I think that you could use LockBits to
enable access o the array of pixel values for both images, scan both of them
using a y by x scan and detect the colour key in the mask using it to set
the alpha in the original. I used this method to create image vignettes in
an article I wrote a few months ago. See the code below my signature for
some ideas.

--
Bob Powell [MVP]
Visual C#, System.Drawing

Find great Windows Forms articles in Windows Forms Tips and Tricks
http://www.bobpowell.net/tips...

Answer those GDI+ questions with the GDI+ FAQ
http://www.bobpowell.net/f...

All new articles provide code in C# and VB.NET.
Subscribe to the RSS feeds provided and never miss a new article.

----------------------------------------------------------------------------
--------
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace WellFormed
{
/// <summary>
/// Summary description for Class1.
/// </summary>
public class GradientPictureBox : Control
{
#region Enumerations

public enum GradientStyles
{
Rectangular,
Elliptical
}

#endregion

#region Fields and properties

Image _internalImage;

bool _dirty;

Image _image;
public Image Image
{
get{return _image;}
set{
_image=value;
_dirty=true;
Refresh();
}
}

GradientStyles _style;
public GradientStyles Style
{
get{return _style;}
set{
_style=value;
_dirty=true;
Refresh();
}
}

Blend _blend;
public Blend Blend
{
get{return _blend;}
set{
_blend=value;
_dirty=true;
Refresh();
}
}

float _angle;
public float Angle
{
get{return _angle;}
set{
_angle=value;
_dirty=true;
Refresh();
}
}

bool _maintainAspectRatio;
public bool MaintainAspectRatio
{
get{return _maintainAspectRatio;}
set{
_maintainAspectRatio=value;
_dirty=true;
Refresh();
}
}


#endregion

public GradientPictureBox()
{
this.SetStyle(ControlStyles.SupportsTransparentBackColor |
ControlStyles.AllPaintingInWmPaint |
ControlStyles.UserPaint ,true);
this.BackColor=Color.Transparent;
}

public override void Refresh()
{
if(Parent!=null)
{
Rectangle rc=new Rectangle(this.Location,this.Size);
Parent.Invalidate(rc,true);
}
Invalidate();
}


protected override CreateParams CreateParams
{
get
{
CreateParams cp=base.CreateParams;
cp.ExStyle|=0x20; //WS_EX_TRANSPARENT
return cp;
}
}

protected override void OnPaintBackground(PaintEventArgs pevent)
{
//Don't paint the background
}


protected override void OnPaint(PaintEventArgs e)
{
if(_image==null)
return;

if(_dirty)
{
if(this._internalImage!=null)
_internalImage.Dispose();
_internalImage=null;
//Create an image that fits the control
_internalImage=new
Bitmap(this.Width,this.Height,PixelFormat.Format32bppArgb);
//Draw the original to the internal image
Graphics g=Graphics.FromImage(_internalImage);
g.InterpolationMode=InterpolationMode.HighQualityBicubic;
g.DrawImage(this._image,new
Rectangle(0,0,_internalImage.Width,_internalImage.Height),0,0,_image.Width,_
image.Height,GraphicsUnit.Pixel);
g.Dispose();
//Now create the gradient that will become the alpha pattern...
Bitmap gbm=new
Bitmap(this.Width,this.Height,PixelFormat.Format32bppArgb);
g=Graphics.FromImage(gbm);
switch(this._style)
{
case GradientStyles.Rectangular:
LinearGradientBrush lgb=new LinearGradientBrush(this.ClientRectangle,
Color.Black,
Color.White,
this._angle,
false);
if(this.Blend!=null)
lgb.Blend=this.Blend;
g.FillRectangle(lgb,this.ClientRectangle);
g.Dispose();
lgb.Dispose();
break;
case GradientStyles.Elliptical:
GraphicsPath pth=new GraphicsPath();
pth.AddEllipse(this.ClientRectangle);
PathGradientBrush pgb=new PathGradientBrush(pth);
pgb.CenterColor=Color.White;
pgb.SurroundColors=new Color[]{Color.Black};
if(this.Blend!=null)
pgb.Blend=this.Blend;
g.FillEllipse(pgb,this.ClientRectangle);
g.Dispose();
pgb.Dispose();
break;
}
//The Gradient Bitmap gbm now contains a monochrome image with the
correct values
//We transfer these values to the internal image using the LockBits
method.

BitmapData
bmd1=((Bitmap)_internalImage).LockBits(this.ClientRectangle,ImageLockMode.Wr
iteOnly,_internalImage.PixelFormat);
BitmapData
bmd2=gbm.LockBits(this.ClientRectangle,ImageLockMode.ReadOnly,gbm.PixelForma
t);

//For maximum speed we use unsafe data pointers to access the byte
arrays
unsafe
{
for(int y=0; y<gbm.Height; y++)
{
byte* destRowPtr=(byte*)bmd1.Scan0.ToPointer()+(bmd1.Stride*y);
byte* srcRowPtr=(byte*)bmd2.Scan0.ToPointer()+(bmd2.Stride*y);
for(int x=0; x<gbm.Width; x++)
{
//One of the componet colours is used to update the alpha of the
destination
destRowPtr[(x*4)+3]=srcRowPtr[x*4];
}
}
}// /unsafe

//tidy up
((Bitmap)_internalImage).UnlockBits(bmd1);
gbm.UnlockBits(bmd2);
gbm.Dispose();
}

e.Graphics.DrawImageUnscaled(_internalImage,0,0);

base.OnPaint (e);
}

protected override void OnMove(EventArgs e)
{
Refresh();
base.OnMove (e);
}


protected override void OnSizeChanged(EventArgs e)
{
if(this._image==null)
return;

if(this._maintainAspectRatio)
{
float f=(float)_image.Height/(float)_image.Width;
this.Size=new Size(this.Width,(int)(f*this.Width));
}

this._dirty=true;

base.OnSizeChanged (e);
}
}
}

----------------------------------------------------------------------------
--------



"Paul Welter" <loresoft@msdn.nospam.com> wrote in message
news:uW8Bw2j3EHA.3336@TK2MSFTNGP11.phx.gbl...
> Hi,
>
> I need some help in how to get started with creating a transparent image
> from two bitmaps. The first image is the image to display, the second
image
> is a mask of the first image for the area that should be transparent. How
> do I combine the two images to form a gif or tiff that has the mask as an
> alpha channel for what is transparent in a single image?
>
> thanks
> Paul
>
>


Robby

12/13/2004 4:51:00 AM

0


Another way of doing this uses the ImageAttributes.SetRemapTable with an
associated ColorMap array and the Graphics.DrawImage method.

The first thing we need to do is load both bitmaps into Bitmap objects.

Dim picture As New Bitmap(<file name>|<image object>)
Dim mask as New Bitmap(<file name>|<image object>)

To continue we need to know the colors that represent transparent and
opaque. If the color representing transparent is not in the original image
or is not Color.Transparent then we do not have to recolor it. We create a
ColorMap array with one entry if we do not have to recolor the color
representing transparent or two entries if we do need to recolor that color.
Next set the opaque color transparent and if nessesary the color
representing transparent to some color not Color.Transparent and not in the
original picture. In this example the opaque color is black and the
transparent color is white in the transparent mask. After setting up the
ColorMap array we attach it to an ImageAttributes object selecting that the
recoloring apply to the bitmap.

Dim recolor() As ColorMap = {New ColorMap(), _
New ColorMap()}
'Recolor opaque to transparent
recolor(0).OldColor = Color.Black
recolor(0).NewColor = Color.Transparent
'Recolor transparent to Magenta
recolor(1).OldColor = Color.White
recolor(1).NewColor = Color.Magenta
'Attach recolorings
Dim ia As New ImageAttribitues()
ia.SetRemapTable(recolor, ColorAdjustType.Bitmap)

We now need a blank canvus on which to paint the recolored mask. It is best
to make this the same size as the mask and to Clear it with
Color.Transparent. Then the paint the new mask to it.

Dim recoloredMask As New Bitmap(mask.Width, _
mask.Height)
Dim grRecolored As Graphics = Graphics.FromImage( _
DirectCast(recoloredMask, Image))
grRecolored.Clear(Color.Transparent)
'Paint recolored mask
grRecolored.DrawImage(DirectCast(mask, Image), _
New Rectangle(0, 0, mask.Width, mask.Height), _
0, 0, mask.Width, mask.Height, _
GraphicsUnit.Pixel, ia)
grRecolored.Dispose()

Now we need to paint the recolored mask on to the original picture. You can
always do a save with a new file name to preserve both the original and the
masked image.

grRecolored = Graphics.FromImage( _
DirectCast(picture, Image))
'Paint the recolored mask onto the original
grRecolored.DrawImage( _
DirectCast(recoloredMask, Image),
New Rectangle(0, 0, _
recoloredMask.Width, _
recoloredMask.Height))
grRecolored.Dispose()

Finally we recolor the color representing transparent to Color.Transparent.
We once again need a blank canvus to do this.

'Recolor transparent color to real transparent
ReDim recolor(0)
recolor(0).OldColor = Color.Magenta
recolor(0).NewColor = Color.Transparent
ia.SetRemapTable(recolor, ColorAdjustType.Bitmap)
'New canvus
Dim maskedPicture As New Bitmap( _
picture.Width, picture.Height)
grRecolored = Graphics.FromImage( _
DirectCast(maskedPicture , Image))
grRecolored.Clear(Color.Transparent)
'Paint masked picture
grRecolored.DrawImage(DirectCast(picture, Image), _
New Rectangle(0, 0, picture.Width, _
picture.Height), 0, 0, picture.Width, _
picture.Height, GraphicsUnit.Pixel, ia)
grRecolored.Dispose()

Remember that the color that you choose to represent transparent in the
recolored mask must not appear in the picture or you will have unwanted
pixels (or entire regions) set to transparent that you do not want
transparent. I have tested this on a .jpg file using a 24bit .bmp the same
size as the transparent mask and it works as expected. I suggest that you
always use a .bmp as the transparent mask as I have found the compression in
other formats blurs the edges of the transparency shapes.

It should be fairly easy to convert this to C# as the only VB specific
statement is the ReDim on recolor at the end.

Hope this helps

Robby

Edmund : R ~ gmail : com



"Paul Welter" <loresoft@msdn.nospam.com> wrote in message
news:uW8Bw2j3EHA.3336@TK2MSFTNGP11.phx.gbl...
> Hi,
>
> I need some help in how to get started with creating a transparent image
> from two bitmaps. The first image is the image to display, the second
> image is a mask of the first image for the area that should be
> transparent. How do I combine the two images to form a gif or tiff that
> has the mask as an alpha channel for what is transparent in a single
> image?
>
> thanks
> Paul
>


Robby

12/13/2004 5:14:00 AM

0


Typos

(1)
Dim ia As New ImageAttribitues()
*should be
Dim ia As ImageAttributes = New ImageAttributes()

(2)
'Paint the recolored mask onto the original
grRecolored.DrawImage( _
DirectCast(recoloredMask, Image),
*should be
'Paint the recolored mask onto the original
grRecolored.DrawImage( _
DirectCast(recoloredMask, Image), _

(3)
ReDim recolor(0)
*should be
ReDim recolor(0)
recolor(0) = New ColorMap()


Robby

Edmund : R ~ gmail : com

"Robby" <edmund@not.my.email.com> wrote in message
news:uQqQL9M4EHA.3708@TK2MSFTNGP14.phx.gbl...
>
> Another way of doing this uses the ImageAttributes.SetRemapTable with an
> associated ColorMap array and the Graphics.DrawImage method.
>
> The first thing we need to do is load both bitmaps into Bitmap objects.
>
> Dim picture As New Bitmap(<file name>|<image object>)
> Dim mask as New Bitmap(<file name>|<image object>)
>
> To continue we need to know the colors that represent transparent and
> opaque. If the color representing transparent is not in the original
> image or is not Color.Transparent then we do not have to recolor it. We
> create a ColorMap array with one entry if we do not have to recolor the
> color representing transparent or two entries if we do need to recolor
> that color. Next set the opaque color transparent and if nessesary the
> color representing transparent to some color not Color.Transparent and not
> in the original picture. In this example the opaque color is black and
> the transparent color is white in the transparent mask. After setting up
> the ColorMap array we attach it to an ImageAttributes object selecting
> that the recoloring apply to the bitmap.
>
> Dim recolor() As ColorMap = {New ColorMap(), _
> New ColorMap()}
> 'Recolor opaque to transparent
> recolor(0).OldColor = Color.Black
> recolor(0).NewColor = Color.Transparent
> 'Recolor transparent to Magenta
> recolor(1).OldColor = Color.White
> recolor(1).NewColor = Color.Magenta
> 'Attach recolorings
> Dim ia As New ImageAttribitues()
> ia.SetRemapTable(recolor, ColorAdjustType.Bitmap)
>
> We now need a blank canvus on which to paint the recolored mask. It is
> best to make this the same size as the mask and to Clear it with
> Color.Transparent. Then the paint the new mask to it.
>
> Dim recoloredMask As New Bitmap(mask.Width, _
> mask.Height)
> Dim grRecolored As Graphics = Graphics.FromImage( _
> DirectCast(recoloredMask, Image))
> grRecolored.Clear(Color.Transparent)
> 'Paint recolored mask
> grRecolored.DrawImage(DirectCast(mask, Image), _
> New Rectangle(0, 0, mask.Width, mask.Height), _
> 0, 0, mask.Width, mask.Height, _
> GraphicsUnit.Pixel, ia)
> grRecolored.Dispose()
>
> Now we need to paint the recolored mask on to the original picture. You
> can always do a save with a new file name to preserve both the original
> and the masked image.
>
> grRecolored = Graphics.FromImage( _
> DirectCast(picture, Image))
> 'Paint the recolored mask onto the original
> grRecolored.DrawImage( _
> DirectCast(recoloredMask, Image),
> New Rectangle(0, 0, _
> recoloredMask.Width, _
> recoloredMask.Height))
> grRecolored.Dispose()
>
> Finally we recolor the color representing transparent to
> Color.Transparent. We once again need a blank canvus to do this.
>
> 'Recolor transparent color to real transparent
> ReDim recolor(0)
> recolor(0).OldColor = Color.Magenta
> recolor(0).NewColor = Color.Transparent
> ia.SetRemapTable(recolor, ColorAdjustType.Bitmap)
> 'New canvus
> Dim maskedPicture As New Bitmap( _
> picture.Width, picture.Height)
> grRecolored = Graphics.FromImage( _
> DirectCast(maskedPicture , Image))
> grRecolored.Clear(Color.Transparent)
> 'Paint masked picture
> grRecolored.DrawImage(DirectCast(picture, Image), _
> New Rectangle(0, 0, picture.Width, _
> picture.Height), 0, 0, picture.Width, _
> picture.Height, GraphicsUnit.Pixel, ia)
> grRecolored.Dispose()
>
> Remember that the color that you choose to represent transparent in the
> recolored mask must not appear in the picture or you will have unwanted
> pixels (or entire regions) set to transparent that you do not want
> transparent. I have tested this on a .jpg file using a 24bit .bmp the
> same size as the transparent mask and it works as expected. I suggest
> that you always use a .bmp as the transparent mask as I have found the
> compression in other formats blurs the edges of the transparency shapes.
>
> It should be fairly easy to convert this to C# as the only VB specific
> statement is the ReDim on recolor at the end.
>
> Hope this helps
>
> Robby
>
> Edmund : R ~ gmail : com
>
>
>
> "Paul Welter" <loresoft@msdn.nospam.com> wrote in message
> news:uW8Bw2j3EHA.3336@TK2MSFTNGP11.phx.gbl...
>> Hi,
>>
>> I need some help in how to get started with creating a transparent image
>> from two bitmaps. The first image is the image to display, the second
>> image is a mask of the first image for the area that should be
>> transparent. How do I combine the two images to form a gif or tiff that
>> has the mask as an alpha channel for what is transparent in a single
>> image?
>>
>> thanks
>> Paul
>>
>
>