 |
|
|
 |
|
 |
After being a lurker here for a while, and getting many good ideas, like "Iconits", Here is a small contribution. A partial update to the original code, which I think helps clarify what it does, and simplifies it.
When I found Iconits, I thought it was neat, but had several issues with it, which are improved here; 1) The alpha shading didn't seem right, and was really slow and/or unsafe. You can delete the whole "Alpha.cs" business now. 2) Names of properties improved to be more meaningful. 3) System.Component model attributes added to the properties to group them together in the properties pane (and dropped "Blur" - why would you use that?). 4) Started renaming other things to be accurate - like "Icon", which is now "Image" (and the whole class name, for that matter)...
Thanks to the original poster, and all who added to it over the months. I found it in Jan '07 and thought I would post this update (about half-way along its transformation to becoming "production code") for all to enjoy!
This class is still not polished, but I wanted to post it while there was still enough of it left to be recognized as "Iconits".
Anyhow, put this class in your project, drop one on your form, set an icon and some sizes and you will see it does the same thing Icontits does.
// Started with code and ideas from the "Iconits" project at // http://www.codeproject.com/cs/miscctrl/Iconits.asp // Then tried to use it and realized it needed work... // See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/_gdiplus_using_a_color_matrix_to_set_alpha_values_in_images_usecsharp.asp // Now it is totally different... and only about half-way done.
using System; using System.Collections; using System.ComponentModel; using System.Drawing; using System.Windows.Forms; using System.Drawing.Drawing2D; using System.Drawing.Imaging;
namespace UsedToBeIconits { public partial class PuffyImage : UserControl { private System.Windows.Forms.Timer drawingTimer; private System.Windows.Forms.ToolTip t = new ToolTip();
private Bitmap bitmap; private Bitmap dblbuffer; private Graphics dbufGraphics;
private int imwidth, imheight; private double curwidth, curheight; private double addx, addy;
private int flag; private bool enter;
// Set up the ColorMatix values changing all pixel Alpha values static float[][] _matrixItemsActive ={ new float[] {1, 0, 0, 0, 0}, new float[] {0, 1, 0, 0, 0}, new float[] {0, 0, 1, 0, 0}, new float[] {0, 0, 0, 1.00f, 0}, // 100% alpha (1.00f) new float[] {0, 0, 0, 0, 1} }; static float[][] _matrixItemsDim ={ new float[] {1, 0, 0, 0, 0}, new float[] {0, 1, 0, 0, 0}, new float[] {0, 0, 1, 0, 0}, new float[] {0, 0, 0, 0.75f, 0}, // 75% alpha new float[] {0, 0, 0, 0, 1} }; static float[][] _matrixItemsDimmer ={ new float[] {1, 0, 0, 0, 0}, new float[] {0, 1, 0, 0, 0}, new float[] {0, 0, 1, 0, 0}, new float[] {0, 0, 0, 0.50f, 0}, // 50% alpha new float[] {0, 0, 0, 0, 1} }; static float[][] _matrixItemsDimmest ={ new float[] {1, 0, 0, 0, 0}, new float[] {0, 1, 0, 0, 0}, new float[] {0, 0, 1, 0, 0}, new float[] {0, 0, 0, 0.25f, 0}, // 25% alpha new float[] {0, 0, 0, 0, 1} };
ColorMatrix[] _colorMatrix = { new ColorMatrix(_matrixItemsActive), new ColorMatrix(_matrixItemsDim), new ColorMatrix(_matrixItemsDimmer), new ColorMatrix(_matrixItemsDimmest) };
// We will use an array of ImageAttributes with those ColorMatrices... ImageAttributes[] _imageAttributes;
// TODO - make this obvious that it is a 4 image animation. // Add events for enter/leave/click/double-click... public PuffyImage() { // There will be four different alpha levels... _imageAttributes = new ImageAttributes[4]; for (int ii = 0; ii < 4; ii++) { _imageAttributes[ii] = new ImageAttributes();
_imageAttributes[ii].SetColorMatrix( _colorMatrix[ii], ColorMatrixFlag.Default, ColorAdjustType.Bitmap); }
dblbuffer = new Bitmap(Width, Height, PixelFormat.Format32bppArgb); dbufGraphics = Graphics.FromImage(dblbuffer);
SizeWhenIdle = new Size(Width / 2, Height / 2);
InitializeComponent();
this.drawingTimer = new System.Windows.Forms.Timer(this.components);
this.drawingTimer.Interval = 10; this.drawingTimer.Tick += new System.EventHandler(this.timer1_Tick);
this.BackColor = System.Drawing.SystemColors.Control; this.Name = "BalloonButton"; this.SizeWhenActive = new System.Drawing.Size(160, 128); this.Paint += new System.Windows.Forms.PaintEventHandler(this.Iconits_Paint); this.MouseEnter += new System.EventHandler(this.Iconits_MouseEnter); this.MouseLeave += new System.EventHandler(this.Iconits_MouseLeave); }
private void Iconits_Paint(object sender, System.Windows.Forms.PaintEventArgs e) { draw(3); }
private void calc() { curwidth = imwidth; curheight = imheight;
addx = (double)(Width - imwidth) / 10; addy = (double)(Height - imheight) / 10; }
private void draw(int state) { int st; // normal = 3 (dimmest)... 2, 1, 0 (active, original image)
st = state;
if (bitmap == null) return;
dbufGraphics.Clear(((this.Parent == null) || (this.BackColor != Color.Transparent)) ? this.BackColor : this.Parent.BackColor);
Rectangle rb = new Rectangle( (int)((double)Width - curwidth) / 2, (int)((double)Height - curheight) / 2, (int)curwidth, (int)curheight);
// take out the "draw one-of-four-bmps..."
// Draw the bitmap image using different Alpha values, defined in imageAtt[] dbufGraphics.DrawImage( bitmap, rb, // destination rectangle 0.0f, // source rectangle x 0.0f, // source rectangle y bitmap.Width, // source rectangle width bitmap.Height, // source rectangle height GraphicsUnit.Pixel, _imageAttributes[st]);
#if (DEBUG) dbufGraphics.DrawRectangle(Pens.Goldenrod, rb); // idle size #endif
using (Graphics g = this.CreateGraphics()) { g.DrawImageUnscaled(dblbuffer, 0, 0); #if (DEBUG) Rectangle r = this.ClientRectangle; r.Inflate(-1, -1); g.DrawRectangle(System.Drawing.Pens.Green, r); // active (full quality) size #endif } }
private void timer1_Tick(object sender, System.EventArgs e) { if (enter) { if (curwidth < Width) curwidth += addx;
if (curheight < Height) curheight += addy;
if (curwidth >= Width && curheight >= Height) drawingTimer.Enabled = false;
flag++; } else { if (curwidth > imwidth) curwidth -= addx;
if (curheight > imheight) curheight -= addy;
if (curwidth <= imwidth && curheight <= imheight) drawingTimer.Enabled = false;
flag--; }
if (flag > 9) draw(0); else if (flag > 6) draw(1); else if (flag > 3) draw(2); else draw(3); }
private void Iconits_MouseEnter(object sender, System.EventArgs e) { enter = true; drawingTimer.Enabled = true; }
private void Iconits_MouseLeave(object sender, System.EventArgs e) { enter = false; drawingTimer.Enabled = true; }
[Category("Settings")] [Description("Basic image for your Iconit")] public Bitmap Image { // was "Icon" get { return bitmap; } set { bitmap = value;
calc(); draw(3); } }
[Category("Settings")] [Description("Maximum size for your image (set to the native size)")] public new Size SizeWhenActive { // Was "Size" get { return new Size(Width, Height); } set { Width = ((Size)value).Width; Height = ((Size)value).Height; calc(); draw(3); } }
[Category("Settings")] [Description("Minimum size for your image (when it is idle and dim)")] public Size SizeWhenIdle { // Was "IconSize" get { return new Size(imwidth, imheight); } set { imwidth = ((Size)value).Width; imheight = ((Size)value).Height; if (imwidth > Width) imwidth = Width; if (imheight > Height) imheight = Height; calc(); draw(3); } }
public string TooltipText { get { return t.GetToolTip(this); } set { t.SetToolTip(this, value); } }
protected override void OnVisibleChanged(EventArgs e) { base.OnVisibleChanged(e); if (this.Visible == true) draw(3); }
} // End-of-class
} // End-of-namespace
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Blackholeat:
You may want to add the following line to the constructor:
this.components = new System.ComponentModel.Container();
Otherwise, "Anyhow, put this class in your project, drop one on your form, set an icon and some sizes and you will see it does the same thing Icontits does." can be taken literally. You can only use one Iconit(puffy image) control without the above line.
Thanks for the simplification.
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
 |
|
 |
Probably basic - I figure that the icons are in the resource file but how does view them, add more, change them, etc?
thanks Ralph
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
 |
|
 |
Please find updated source for Alpha.cs/Iconit.cs. I fixed most of the logical oddities, included all interresting patches/fixes found in others posts. I apologize because I didn't explicitely surrounded everyone contribution with its author name.
Notice the #if (DEBUG) that draws black boxes around bitmaps. That helps to show what happens when the component is drawn at runtime.
Don't define DEBUG or remove code between #if DEBUG / #endif to get rid of black boxes.
Hope you will find this useful !
using System; using System.Drawing; using System.Drawing.Imaging;
namespace ITS.Windows.Forms { public class Alpha { private static int min(int val) { return (val<0?0:val); }
public static void setAlpha(Bitmap bmp, int alpha) { Color col;
for (int i=0;i for (int j=0;j { col=bmp.GetPixel(i,j); if (col.A>0) bmp.SetPixel(i,j,Color.FromArgb(min(col.A-alpha),col.R,col.G,col.B)); } }
public static void returnAlpha2(ref Bitmap bmp, int alpha, ref Bitmap bmpModify) { Color col;
for (int i=0;i for (int j=0;j { col=bmp.GetPixel(i,j); if (col.A>0) bmpModify.SetPixel(i,j,Color.FromArgb(min(col.A-alpha),col.R,col.G,col.B)); } } /// /// Adjusts the alpha level of the given bitmap /// by a given amount. /// /// The bitmap to adjust alpha of. /// The alpha level to adjust by. /// A new bitmap, copied from the original, but with adjusted alpha. /// The alpha parameter can be positive or negative, by the amount /// of adjustment desired. The value should be in the range of -255 to 255. public static unsafe void returnAlpha(ref Bitmap bmp, int alpha, ref Bitmap modifiedBmp) { // Don't process bitmaps that don't have an alpha channel if (bmp.PixelFormat != PixelFormat.Format24bppRgb && bmp.PixelFormat != PixelFormat.Format32bppArgb) throw new ArgumentException();
// Lock the original bitmap and get its data GraphicsUnit gu = GraphicsUnit.Pixel; RectangleF rectF = bmp.GetBounds(ref gu); Rectangle rect = Rectangle.Round(rectF); BitmapData bmpData = bmp.LockBits(rect, ImageLockMode.ReadOnly, bmp.PixelFormat);
// Lock the copy bitmap and get its data rectF = modifiedBmp.GetBounds(ref gu); rect = Rectangle.Round(rectF); BitmapData copyData = modifiedBmp.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
// Create pointers for reading and writing the bitmaps byte* oPx = (byte*)bmpData.Scan0; byte* cPx = (byte*)copyData.Scan0; byte b, a;
for (int y=0; y { for (int x=0; x { // NOTE: Scanlines in a .NET bitmap usually order pixels in // little-endian order, or "reverse" from the common way of // thinking about them. That means, instead of ARGB, its BGRA.
// Copy color values from original to copy *cPx = *oPx; // Blue *(cPx+1) = *(oPx+1); // Green *(cPx+2) = *(oPx+2); // Red
// Retrieve base alpha value from original bitmap if (bmpData.PixelFormat == PixelFormat.Format32bppArgb) { // Get alpha component if original bitmap is 32bit b = *(oPx+3); } else { // Get the color average if the original bitmap is 24bit b = (byte)((*cPx + *(cPx+1) + *(cPx+2)) / 3); }
// Set the alpha value for the bitmap copy a = 0; if (b > 0) { // Get alpha value clamped in range 0-255 a = (byte)Math.Min(255, Math.Max(0, b-alpha)); // NOTE: To directly set the alpha value of each pixel, rather than adjust. This // requires that the alpha parameter have a range of 0 to 255, rather than -255 to 255. // a = (byte)Math.Min(255, Math.Max(0, alpha)); // Clamp alpha value, 0-255 }
// Record the alpha value in the bitmap copy *(cPx+3) = a;
// Advance pointers to the next pixel cPx += 4;
if (bmpData.PixelFormat == PixelFormat.Format24bppRgb) oPx += 3; else oPx += 4; }
// NOTE: A .NET Bitmap always uses up the same amount of memory, // regardless of its bit depth (8bit images are a little different). // Each row of pixels in a bitmap will always use up 'width*4' bytes, // so a 24bit bitmap will have an extra 'width' bytes of unused space // for each row. A 16bit bitmap will have an extra 'width*2' bytes // of unused space. This must be taken into account when advancing // pointers while doing operations on image pixels.
// Advance the original bitmap pointer by any leftover // bytes for the current row if the bitmap is 24 bits. if (bmpData.PixelFormat == PixelFormat.Format24bppRgb) oPx += bmpData.Width; } // Unlock the bitmap data in memory, allowing the GC to properly // collect their memory when they are no longer used modifiedBmp.UnlockBits(copyData); bmp.UnlockBits(bmpData); } } }
using System; using System.Collections; using System.ComponentModel; using System.Drawing; using System.Windows.Forms; using System.Drawing.Drawing2D; using System.Drawing.Imaging;
namespace ITS.Windows.Forms { public class Iconits : System.Windows.Forms.UserControl { private System.ComponentModel.IContainer components; private System.Windows.Forms.Timer timer1; private System.Windows.Forms.ToolTip t=new ToolTip();
private Bitmap[] bmp; private Bitmap dblbuffer; private Graphics dbufGraphics;
private int imwidth,imheight; private double curwidth,curheight; private double addx,addy;
private int flag; private bool enter;
private bool blur = true;
public Iconits() { bmp = new Bitmap[4];
dblbuffer = new Bitmap(Width,Height,PixelFormat.Format32bppArgb); dbufGraphics = Graphics.FromImage(dblbuffer);
IconSize = new Size(Width/2,Height/2);
InitializeComponent(); }
/// /// Clean up any resources being used. /// protected override void Dispose( bool disposing ) { if( disposing ) { if(components != null) { components.Dispose(); } } base.Dispose( disposing ); }
#region Component Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { this.components = new System.ComponentModel.Container(); this.timer1 = new System.Windows.Forms.Timer(this.components); // // timer1 // this.timer1.Interval = 10; this.timer1.Tick += new System.EventHandler(this.timer1_Tick); // // Iconits // this.BackColor = System.Drawing.SystemColors.Control; this.Name = "Iconits"; this.Size = new System.Drawing.Size(160, 128); this.Paint += new System.Windows.Forms.PaintEventHandler(this.Iconits_Paint); this.MouseEnter += new System.EventHandler(this.Iconits_MouseEnter); this.MouseLeave += new System.EventHandler(this.Iconits_MouseLeave); } #endregion
private void Iconits_Paint(object sender, System.Windows.Forms.PaintEventArgs e) { draw(3); }
private void calc() { curwidth = imwidth; curheight = imheight;
addx = (double)(Width-imwidth)/10; addy = (double)(Height-imheight)/10; }
private void draw(int state) { int st;
if (blur) st=state; else st=0;
if (bmp[st] == null) return;
dbufGraphics.Clear(((this.Parent == null) || (this.BackColor != Color.Transparent)) ? this.BackColor : this.Parent.BackColor);
Rectangle rb = new Rectangle( (int)((double)Width-curwidth)/2, (int)((double)Height-curheight)/2, (int)curwidth, (int)curheight);
dbufGraphics.DrawImage(bmp[st], rb);
#if (DEBUG) dbufGraphics.DrawRectangle(Pens.Black, rb); #endif
using (Graphics g = this.CreateGraphics()) { g.DrawImageUnscaled(dblbuffer,0,0); #if (DEBUG) Rectangle r = this.ClientRectangle; r.Inflate(-1,-1); g.DrawRectangle(System.Drawing.Pens.Black,r); #endif } }
private void timer1_Tick(object sender, System.EventArgs e) { if (enter) { if (curwidth < Width) curwidth += addx;
if (curheight < Height) curheight += addy;
if (curwidth >= Width && curheight >= Height) timer1.Enabled = false;
flag++; } else { if (curwidth > imwidth) curwidth -= addx;
if (curheight > imheight) curheight -= addy;
if (curwidth <= imwidth && curheight <= imheight) timer1.Enabled = false;
flag--; }
if (flag>9) draw(0); else if (flag>6) draw(1); else if (flag>3) draw(2); else draw(3); }
private void Iconits_MouseEnter(object sender, System.EventArgs e) { enter = true; timer1.Enabled = true; }
private void Iconits_MouseLeave(object sender, System.EventArgs e) { enter = false; timer1.Enabled = true; }
public Bitmap Icon { get { return bmp[0]; } set { bmp[0]=value;
for (int i = 1 ; i < 4 ; i++) { if (bmp[i] != null) bmp[i].Dispose(); bmp[i] = new Bitmap(bmp[0].Width,bmp[0].Height,PixelFormat.Format32bppArgb); } if (bmp[0] != null) { Alpha.returnAlpha(ref bmp[0], 60, ref bmp[1]); Alpha.returnAlpha(ref bmp[0], 120, ref bmp[2]); Alpha.returnAlpha(ref bmp[0], 180, ref bmp[3]); }
calc(); draw(3); } }
public new Size Size { get { return new Size(Width,Height); } set { Width = ((Size)value).Width; Height = ((Size)value).Height; calc(); draw(3); } }
public Size IconSize { get { return new Size(imwidth,imheight); } set { imwidth = ((Size)value).Width; imheight = ((Size)value).Height; if (imwidth > Width) imwidth = Width; if (imheight > Height) imheight = Height; calc(); draw(3); } }
public bool Blur { get { return blur; } set { blur=value; if (!blur) { bmp[1].Dispose(); bmp[2].Dispose(); bmp[3].Dispose(); } else { for (int i = 1 ; i < 4 ; i++) { if (bmp[i] != null) bmp[i].Dispose(); bmp[i] = new Bitmap(Width,Height,PixelFormat.Format32bppArgb); } if (bmp[0] != null) { Alpha.returnAlpha(ref bmp[0], 60, ref bmp[1]); Alpha.returnAlpha(ref bmp[0], 120, ref bmp[2]); Alpha.returnAlpha(ref bmp[0], 180, ref bmp[3]); } } } }
public string About { get { return "Iconits 0.1.1 - ITS Informatics Surabaya, author: Yojana Hanif"; } }
public string TooltipText { get { return t.GetToolTip(this); } set { t.SetToolTip(this,value); } } protected override void OnVisibleChanged(EventArgs e) { base.OnVisibleChanged(e); if (this.Visible == true) draw(3); } } }
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hello Lehlu,
All of your 'for' loops in Alpha.cs are incomplete! Just thought I'd let you know, seems like they've been cut off.
Cheers,
-M
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hi all,
it seems that the application still uses more and more memory if one moves the mouse over the icons. Some threads below there is an advice in Thread 'Very nice but...' but it seems it's not added to current solution. It would be great if someone could be so kind to post the updated code here. Many thanks!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
 |
Great job! Exactly what I was looking for! Many thanks!!
Just one short idea: When the icons are small there is much free space between the icons. Would it be possible to dynamically create the free space as soon as the user moves the mouse over an icon? So if there is no mouse pointer at the icon, all icons are next to each other in 32x32. As soon as the mouse points on one icon, all other icons are moved to the left and right so there is enough space to display the bigger icon. Would this be possible?
Nevertheless 5 points for this brillant piece of code!
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
 |
There was a little bug, after hide/show of the parent forms which contains the iconit, the iconit wasnt redrawed and it generated a GDI+ exception.
Adding this override to Iconits.cs will resolve the problem 
protected override void OnVisibleChanged(EventArgs e) { base.OnVisibleChanged(e); if (this.Visible == true) { g = this.CreateGraphics(); draw(3); } }
-- Everything is possible, even the impossible! ^_^
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hi, First, this simple control is really nice.
Ok, if you change the BackColor of a Iconit to, let's say, Transparent, because you want it to appear with its parent backcolor, when you move the mouse in and out the control, all of the bitmaps displayed during the process remain on screen. If you minimize the window or switch to another and back, the display is ok again.
I fixed this with a simple change in this line:
private void draw(int state) { ... // OLD LINE: g2.Clear(this.BackColor); g2.Clear(((this.Parent == null) || (this.BackColor != Color.Transparent)) ? this.BackColor : this.Parent.BackColor); ... }
This way, if you want your Iconit to inherit its parent backcolor just set the Iconit's backcolor to Transparent. You won't have to change backcolor for every Iconit if you decide to change your container backcolor (e.g. a Form). In case you need your Iconit with a different backcolor than the container's, well, just set the backcolor for your iconit.
Have a nice day.
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
 |
If I use this component in the forms which is not rectangle( set the TransparencyKey) , it can't work properly . How can I fix this problem ?
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
 |
|
 |
Hi Hanifku,
Really enjoyed this, and I hope we'll see a new version soon incorporating the comments on speeding it up.
best, Bill
"The greater the social and cultural distances between people, the more magical the light that can spring from their contact." Milan Kundera in Testaments Trahis
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
I think this piece of code is great. I just found the following behavior which is kind of interesting:
When you hover the mouse and the icon is resized and is showing full color and you click or double click, nothing happens. Good.
If you do the same, wait until the tooltip shows up, and then click or double click, the icon loses its color.
Anyway, this is a really cool control. Congrats!!!
A.G
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hi,the click event handler you need to add in by each of it for your iconit button.
inside the windows Designer generate form code, each iconits button you use need to add. let say..
this.iconits7.Click += new System.EventHandler(this.iconits_Click);
private void iconits_Click(object sender, System.EventArgs e) { /*MessageBox.Show("TEST Iconit Click");*/ ///****Your Code follow//// ////// } I do realize that, but nothing affect much for me since if user click already, The other's action they concentrate on....
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
What I noticed is that the Tooltip stops showing after the first time you click on the Iconit. Once clicked, the tooltip won't show up again.
Ideas?
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
I noticed your routeen to update the alpha of the bitmap is using a slower method (actually, about the slowest there is). Here is a significantly faster version of your routeen. It uses an unsafe code function, which allows the use of pointers. This function will adjust the original alpha by the input alpha amount. Since it uses pointers to directly edit the memory of the copied bitmap, it is hundreds of times faster than using the GetPixel/SetPixel method of GDI+. In fact, GDI+ essentially does the first and last parts of my function (locking pixels, finding the pixel in memory, reading/writing it, and unlocking), every time you call GetPixel or SetPixel. By using an unsafe function with pointers, you eliminate the repetitive locking/seeking/unlocking of pixel data in memory, which greatly improves performance.
/// <summary> /// Adjusts the alpha level of the given bitmap /// by a given amount. /// </summary> /// <param name="bmp">The bitmap to adjust alpha of.</param> /// <param name="alpha">The alpha level to adjust by.</param> /// <returns>A new bitmap, copied from the original, but with adjusted alpha.</returns> /// <remarks>The alpha parameter can be positive or negative, by the amount /// of adjustment desired. The value should be in the range of -255 to 255.</remarks> public unsafe Bitmap returnAlpha(Bitmap bmp, int alpha) { // Don't process bitmaps that don't have an alpha channel if (bmp.PixelFormat != PixelFormat.Format24bppRgb && bmp.PixelFormat != PixelFormat.Format32bppArgb) throw new ArgumentException();
// Copy the bitmap Bitmap bmpCopy = new Bitmap(bmp.Width, bmp.Height, PixelFormat.32bppArgb);
// Lock the original bitmap and get its data GraphicsUnit gu = GraphicsUnit.Pixel; RectangleF rectF = bmp.GetBounds(ref gu); Rectangle rect = Rectangle.Round(rectF); BitmapData bmpData = bmp.LockBits(rect, ImageLockMode.Read, bmp.PixelFormat);
// Lock the copy bitmap and get its data rectF = bmpCopy.GetBounds(ref gu); rect = Rectangle.Round(rectF); BitmapData copyData = bmpCopy.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
// Create pointers for reading and writing the bitmaps byte* oPx = (byte*)bmpData.Scan0; byte* cPx = (byte*)copyData.Scan0; uint black = 255; byte b, a;
for (int y=0; y<bmpData.Height; y++) { for (int x=0; x<bmpData.Width; x++) { // NOTE: Scanlines in a .NET bitmap usually order pixels in // little-endian order, or "reverse" from the common way of // thinking about them. That means, instead of ARGB, its BGRA.
// Copy color values from original to copy *cPx = *oPx; // Blue *(cPx+1) = *(oPx+1); // Green *(cPx+2) = *(oPx+2); // Red
// Retrieve base alpha value from original bitmap if (bmpData.PixelFormat == PixelFormat.Format32bppArgb) { // Get alpha component if original bitmap is 32bit b = *(oPx+3); } else { // Get the color average if the original bitmap is 24bit b = (byte)((*cPx + *(cPx+1) + *(cPx+2)) / 3); }
// Set the alpha value for the bitmap copy a = 0; if (b > 0) { a = (byte)Math.Min(255, Math.Max(0, b-alpha)); // Get alpha value clamped in range 0-255 // NOTE: To directly set the alpha value of each pixel, rather than adjust. This // requires that the alpha parameter have a range of 0 to 255, rather than -255 to 255. // a = (byte)Math.Min(255, Math.Max(0, alpha)); // Clamp alpha value, 0-255 }
// Record the alpha value in the bitmap copy *(cPx+3) = a;
// Advance pointers to the next pixel cPx += 4;
if (bmpData.PixelFormat == PixelFormat.Format24bppRgb) oPx += 3; else oPx += 4; }
// NOTE: A .NET Bitmap always uses up the same amount of memory, // regardless of its bit depth (8bit images are a little different). // Each row of pixels in a bitmap will always use up 'width*4' bytes, // so a 24bit bitmap will have an extra 'width' bytes of unused space // for each row. A 16bit bitmap will have an extra 'width*2' bytes // of unused space. This must be taken into account when advancing // pointers while doing operations on image pixels.
// Advance the original bitmap pointer by any leftover // bytes for the current row if the bitmap is 24 bits. if (bmpData.PixelFormat == PixelFormat.Format24bppRgb) oPx += bmpData.Width; }
// Unlock the bitmap data in memory, allowing the GC to properly // collect their memory when they are no longer used copyBmp.UnlockBits(copyData); bmp.UnlockBits(bmpData);
// Return the alpha-adjusted image return copyBmp; }
-- modified at 23:23 Thursday 20th April, 2006
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
For some reason, CodeProject is stripping whitespace from my code. Sorry for it being all packed together.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
I've tested your method, it's fanstastic. Just in case people donn't, above Jon Rista method need to add
using System.Drawing.Imaging;
******************************************
I alterred the iconits.cs few place to remove those resources killer
namespace alterred { public class Iconits : System.Windows.Forms.UserControl { private System.ComponentModel.IContainer components; private System.Windows.Forms.Timer timer1; private System.Windows.Forms.ToolTip t=new ToolTip(); Bitmap[] bmp; int flag; bool enter; Graphics g,g2;
int imwidth,imheight; double curwidth,curheight; double addx,addy; Bitmap dblbuffer; bool blur=true;
public Iconits() { InitializeComponent(); bmp=new Bitmap[4]; for (int i=0;i<4;i++) bmp[i]=new Bitmap(Width,Height); dblbuffer=new Bitmap(Width,Height); //<---**Since this line and the bmp already initialized //<---**Remove those on other method. g2=Graphics.FromImage(dblbuffer); //<---** This line move from the draw method.
IconSize=new Size(Width/2,Height/2); g=this.CreateGraphics(); }
protected override void Dispose( bool disposing ) { if( disposing ) { if(components != null) { components.Dispose(); } } base.Dispose( disposing ); }
#region Component Designer generated code private void InitializeComponent() { this.components = new System.ComponentModel.Container(); this.timer1 = new System.Windows.Forms.Timer(this.components); // // timer1 // this.timer1.Interval = 10; this.timer1.Tick += new System.EventHandler(this.timer1_Tick); // // Iconits // this.BackColor = System.Drawing.SystemColors.Control; this.Name = "Iconits"; this.Size = new System.Drawing.Size(160, 128); this.Paint += new System.Windows.Forms.PaintEventHandler(this.Iconits_Paint); this.MouseEnter += new System.EventHandler(this.Iconits_MouseEnter); this.MouseLeave += new System.EventHandler(this.Iconits_MouseLeave); //this.Click += new System.EventHandler(this.Click)
} #endregion
private void Iconits_Paint(object sender, System.Windows.Forms.PaintEventArgs e) { draw(3); }
private void calc() { curwidth=imwidth; curheight=imheight;
addx=(double)(Width-imwidth)/10; addy=(double)(Height-imheight)/10; }
private void draw(int state) { int st; //Graphics g2;
if (blur) st=state; else st=0;
//g2=Graphics.FromImage(dblbuffer); <---**Remove this line g2.Clear(this.BackColor); g2.DrawImage(bmp[st],(int)((double)Width-curwidth)/2,(int)((double)Height-curheight)/2,(int)curwidth,(int)curheight); g.DrawImageUnscaled(dblbuffer,0,0); }
private void timer1_Tick(object sender, System.EventArgs e) { if (enter) { if (curwidth { curwidth+=addx; }
if (curheight { curheight+=addy; }
//if (curwidth>=Width&&curheight>=Height) timer1.Stop(); if (curwidth>=Width&&curheight>=Height) timer1.Enabled = false; //<---***I use enable & disable instead start or stop. flag++; } else { if (curwidth>imwidth) { curwidth-=addx; }
if (curheight>imheight) { curheight-=addy; }
//if (curwidth<=imwidth&&curheight<=imheight) timer1.Stop(); if (curwidth<=imwidth&&curheight<=imheight) timer1.Enabled = false;
flag--; }
if (flag>9) draw(0); else if (flag>6) draw(1); else if (flag>3) draw(2); else draw(3); }
private void Iconits_MouseEnter(object sender, System.EventArgs e) { enter=true; //timer1.Start(); timer1.Enabled=true; }
private void Iconits_MouseLeave(object sender, System.EventArgs e) { enter=false; //timer1.Start(); timer1.Enabled = true; }
public Bitmap Icon { get { return bmp[0]; } set { //for (int i=0;i<4;i++) //<--**Remove duplicate work // bmp[i]=new Bitmap(Width,Height); //dblbuffer=new Bitmap(Width,Height);
bmp[0]=value; alpha.returnAlpha3(ref bmp[0],60, ref bmp[1]); //<---**Here I write the method to use ref alpha.returnAlpha3(ref bmp[0],120,ref bmp[2]); alpha.returnAlpha3(ref bmp[0],180,ref bmp[3]); draw(0); } }
public new Size Size { get { return new Size(Width,Height); } set { Width = ((Size)value).Width; Height= ((Size)value).Height; if (Width>160) { //MessageBox.Show("Width cannot exceed 160 :p"); Width=160; } if (Height>128) { //MessageBox.Show("Height cannot exceed 128 :p"); Height=128; } calc(); } }
public Size IconSize { get { return new Size(imwidth,imheight); } set { imwidth=((Size)value).Width; imheight=((Size)value).Height; if (imwidth>Width) imwidth=Width; if (imheight>Height) imheight=Height; calc(); } }
public bool Blur { get { return blur; } set { blur=value; if (!blur) { bmp[1].Dispose(); bmp[2].Dispose(); bmp[3].Dispose(); } else { //---**Here I write the method to use ref alpha.returnAlpha3(ref bmp[0], 60 ,ref bmp[1]); alpha.returnAlpha3(ref bmp[0], 120 ,ref bmp[2]); alpha.returnAlpha3(ref bmp[0], 180 ,ref bmp[3]);
} } }
public string About { get { return "Iconits 0.1.0 - ITS Informatics Surabaya, author: Yojana Hanif. Jayoscar Modify Abit"; } }
public string TooltipText { get { return t.GetToolTip(this); } set { t.SetToolTip(this,value); } } } }
This part on the alpha.cs public static void returnAlpha2(ref Bitmap bmp, int alpha, ref Bitmap bmpModify) { Color col; //Bitmap bmp2=new Bitmap(bmp);
for (int i=0;i for (int j=0;j { col=bmp.GetPixel(i,j); if (col.A>0) bmpModify.SetPixel(i,j,Color.FromArgb(min(col.A-alpha),col.R,col.G,col.B)); } //return bmp2; } Well, everyone give some feedback see how this change you feel. Comment/suggestion welcome.
-- modified at 7:02 Friday 21st April, 2006
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Another quick note, if you use the alphatizing routeen I wrote. You will need to enable unsafe code blocks in your projects properties, otherwise it won't compile.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|