|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionIf you have an image file and need to create a reflection (left, right, above, or below) with a gradient fade out, this simple utility can help you. The C# code that does the work may help you too. If you want something more powerful, consider Gimp, which is free, very powerful, and comes with source code, but has a steep learning curve. BackgroundI needed a simple utility to quickly and easily create a reflection of an image file and assumed someone had already done this. Indeed Fco. Xavier Marin had (see CodeProject CreditsAn excellent source of information on the issues related to manipulating Bitmaps can be found on BobPowell.net. There you will find detailed explanations of things like how and when to use functions like LockBits, so I will not repeat it here. The files in this project's Images folder are the same as those in Fco. Xavier Marin Using the CodeIf you have Visual Studio 2005, then you should be able to use the project source code "out of the box" -- simply build and run. It is reasonably documented. A side benefit of the code for Bitmap/Image newbies is it has simple examples of how to create a Bitmap, how to color it and change the alpha value of each pixel, etc. You can find the source code in VVX_ImageTools.cs, which is included in the project. You will undoubtedly find that you can build a better UI or write better code. WARNING: Unsafe Code AheadManaged code can be used to manipulate Bitmaps. But it can be a little too slow. To get the job done a little faster, the code in VVX_ImageTools.cs uses "unsafe" code in two methods -- For this code to compile in Visual Studio 2005, in the Project menu select Properties > Build and then check "Allow Unsafe Code". Code for Converting a Bitmap to a Format32bppArgb Pixel FormatIn order for gradient fade-out to work, lower resolution (i.e., less than public bool DoConvertToFormat32bppArgb(Bitmap bmpSrc, ref Bitmap bmpTgt)
{
bool bRet = false;
try
{
PixelFormat pixFmtSrc = bmpSrc.PixelFormat;
PixelFormat pixFmtTgt = PixelFormat.Format32bppArgb;
if (pixFmtSrc != PixelFormat.Format32bppRgb)
{
int iWidth = bmpSrc.Width;
int iHeight = bmpSrc.Height;
// create a bitmap with the same size but desired format
bmpTgt = new Bitmap(bmpSrc.Width, bmpSrc.Height, pixFmtTgt);
//Ref: http://www.bobpowell.net/lockingbits.htm
// lock all the bits
Rectangle rc = new Rectangle(0, 0, iWidth, iHeight);
BitmapData bmdTgt = bmpTgt.LockBits(rc, ImageLockMode.ReadOnly, pixFmtTgt);
unsafe
{
//NOTE: For this to work in VS2005, in Project > Properties > Build
// you must check "Allow Unsafe Code"
//--- loop through each scan line and COPY each pixel from current
// format to desired format, e.g., Format32bppRgb
int PixelSize = 4;
for (int y = 0; y < bmdTgt.Height; y++)
{
byte* row = (byte*)bmdTgt.Scan0 + (y * bmdTgt.Stride);
for (int x = 0; x < bmdTgt.Width; x++)
{
//---get the color from the source
Color clr = bmpSrc.GetPixel(x, y);
//---set color attributes in the target
// Each of the 4 bytes of this 32-bit pixel must be set
int xRef = x * PixelSize;
row[xRef + 0] = clr.B;
row[xRef + 1] = clr.G;
row[xRef + 2] = clr.R;
if (mbMakeTransparent && (clr == this.mColorToMakeTransparent))
row[xRef + 3] = 0; // 0 is 100% transparent
else
row[xRef + 3] = 255; // 255 is 100% opaque
}
}
}
//now unlock all the bits we locked earlier
bmpTgt.UnlockBits(bmdTgt);
}
bRet = true;
}
catch (Exception ex)
{
this.msErrorMsg += this.msEOL + ex.ToString();
bRet = false;
}
return bRet;
}
Automatically Upgrades Low Resolution ImagesIf the source file opened is not 32-bits per pixel, i.e. ARGB compatible, the image is automatically "upgraded" using the method shown above and then saved with a modified extension. For example, if you open a 24-bit RGB image file, say test.bmp, then it will be saved as test.bmp.32bppArgb.png. The code that does this is shown below: if (bmpReflection.PixelFormat != PixelFormat.Format32bppArgb)
{
DoConvertToFormat32bppArgb(bmpOriginal, ref bmpReflection);
if (true)
{
string sConvertedFile = msFile+".32bppArgb.png";
this.SaveAs(bmpReflection, sConvertedFile);
this.DoUpdateErrorMsg(sConvertedFile + " will work faster!");
}
bmpReflection.RotateFlip(this.menRotateFlipType);
}
This approach works best for my needs. However, if you don't like it, either change the ' Code for Saving a Bitmap with Different File Typespublic bool SaveBitmap(Bitmap bmp, string sOutputFilename)
{
bool bRet = false;
try
{
FileInfo fiOutputFile = new FileInfo(sOutputFilename);
//determine the image format from the file name
ImageFormat imgFmtWant = ImageFormat.Png;
switch (fiOutputFile.Extension.ToUpper())
{
case ".BMP" : imgFmtWant = ImageFormat.Bmp; break;
case ".EMF" : imgFmtWant = ImageFormat.Emf; break;
case ".EXF" :
case ".EXIF": imgFmtWant = ImageFormat.Exif; break;
case ".GIF" : imgFmtWant = ImageFormat.Gif; break;
case ".ICO" : imgFmtWant = ImageFormat.Icon; break;
case ".JPG" :
case ".JPEG": imgFmtWant = ImageFormat.Jpeg; break;
case ".PNG" : imgFmtWant = ImageFormat.Png; break;
case ".TIF" :
case ".TIFF": imgFmtWant = ImageFormat.Tiff; break;
case ".WMF" : imgFmtWant = ImageFormat.Wmf; break;
default: // none of the above, so add PNG to the name
sOutputFilename += ".png";
this.DoUpdateErrorMsg("WARNING: Output file name modified;
Extension '.png' added.");
break;
}
bmp.Save(sOutputFilename, imgFmtWant);
bRet = true;
}
catch (Exception ex)
{
this.msErrorMsg += this.msEOL + ex.ToString();
bRet = false;
}
return bRet;
}
History
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||