Png设置透明
想做一个小工具现在有张Png图片,有粉红色背景
打算把粉红色设置为透明颜色
设置为透明后,如果能根据剩下的不透明的截图,把多余的透明去掉,就更好了
--------------------编程问答-------------------- 如果能根据剩下的不透明的截图,把多余的透明去掉
这里我理解的是把源图一部分没图像的去掉?
我写了三个方法,你参考一下,还有各个方法执行所消耗的时间(Stopwatch)
//托管
public Bitmap ToTransparentPng1(Bitmap source, Rectangle dest, Color transparentColor)
{
if (source == null) return null;
Rectangle src = new Rectangle(0, 0, source.Width, source.Height);
src.Intersect(dest);
if (src != dest)
{
throw new ArgumentOutOfRangeException();
}
Bitmap newBitmap = new Bitmap(dest.Width, dest.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
for (int y = dest.Y; y < dest.Bottom; y++)
{
for (int x = dest.X; x < dest.Right; x++)
{
Color srcColor = source.GetPixel(x,y);
if (srcColor != transparentColor)
{
newBitmap.SetPixel(x - dest.X, y-dest.Y, srcColor);
}
}
}
return newBitmap;
}
//指针
public Bitmap ToTransparentPng2(Bitmap source, Rectangle dest, Color transparentColor)
{
if (source == null) return null;
Rectangle src = new Rectangle(0,0,source.Width,source.Height);
src.Intersect(dest);
if (src != dest)
{
throw new ArgumentOutOfRangeException();
}
Bitmap newBitmap=new Bitmap(dest.Width,dest.Height,System.Drawing.Imaging.PixelFormat.Format32bppArgb);
BitmapData sourceData = source.LockBits(new Rectangle(0, 0, source.Width, source.Height),ImageLockMode.ReadOnly,source.PixelFormat);
BitmapData destData = newBitmap.LockBits(new Rectangle(0,0,newBitmap.Width,newBitmap.Height),ImageLockMode.ReadWrite,newBitmap.PixelFormat);
unsafe
{
for (int x = dest.X; x < dest.Right; x++)
{
for (int y = dest.Y; y < dest.Bottom; y++)
{
byte* pS = (byte*)sourceData.Scan0 + x * 4 + y*sourceData.Stride;
byte* pD = (byte*)destData.Scan0 + (x - dest.X) * 4 + (y-dest.Y)*destData.Stride;
byte B = *(pS + 0);
byte G = *(pS + 1);
byte R = *(pS + 2);
byte A = *(pS + 3);
if (Color.FromArgb(A, R, G, B) != transparentColor)
{
*(pD + 0) = B;
*(pD + 1) = G;
*(pD + 2) = R;
*(pD + 3) = 255;
}
}
}
newBitmap.UnlockBits(destData);
source.UnlockBits(sourceData);
}
return newBitmap;
}
//非托管
public Bitmap ToTransparentPng3(Bitmap source, Rectangle dest, Color transparentColor)
{
if (source == null) return null;
Rectangle src = new Rectangle(0, 0, source.Width, source.Height);
src.Intersect(dest);
if (src != dest)
{
throw new ArgumentOutOfRangeException();
}
BitmapData sourceData = source.LockBits(new Rectangle(0, 0, source.Width, source.Height), ImageLockMode.ReadOnly, source.PixelFormat);
byte[] buffer = new byte[source.Width * sourceData.Stride];
Marshal.Copy(sourceData.Scan0, buffer, 0, buffer.Length);
Bitmap newBitmap = new Bitmap(dest.Width, dest.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
BitmapData destData = newBitmap.LockBits(new Rectangle(0, 0, newBitmap.Width, newBitmap.Height), ImageLockMode.ReadOnly, newBitmap.PixelFormat);
byte[] newBuffer = new byte[newBitmap.Width * destData.Stride];
for (int i = 0; i < newBuffer.Length; i += 4)
{
byte B = buffer[i + dest.X + 0];
byte G = buffer[i + dest.X + 1];
byte R = buffer[i + dest.X + 2];
byte A = buffer[i + dest.X + 3];
if (Color.FromArgb(A, R, G, B) != transparentColor)
{
newBuffer[i + 0] = B;
newBuffer[i + 1] = G;
newBuffer[i + 2] = R;
newBuffer[i + 3] = 255;
}
}
Marshal.Copy(newBuffer,0,destData.Scan0,newBuffer.Length);
newBitmap.UnlockBits(destData);
source.UnlockBits(sourceData);
return newBitmap;
}
Bitmap ToTransparentPngX(Bitmap source, Rectangle dest, Color transparentColor)
其中参数信息:
source:源图
dest:想要透明化的目标区域
transparentColor:颜色键 --------------------编程问答-------------------- 再加一种方法
--------------------编程问答-------------------- 方法4第10行到14行换成下面的代码就避免源图被修改,用一张临时位图做透明化
public Bitmap ToTransparentPng4(Bitmap source, Rectangle dest, Color transparentColor)
{
if (source == null) return null;
Rectangle src = new Rectangle(0, 0, source.Width, source.Height);
src.Intersect(dest);
if (src != dest)
{
throw new ArgumentOutOfRangeException();
}
Bitmap newBitmap = new Bitmap(dest.Width, dest.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
source.MakeTransparent(transparentColor);
Graphics g = Graphics.FromImage(newBitmap);
g.DrawImage(source, new Rectangle(0, 0, dest.Width, dest.Height), dest, GraphicsUnit.Pixel);
g.Dispose();
return newBitmap;
}
--------------------编程问答-------------------- PNG图片要做透明背景还是什么? --------------------编程问答--------------------
Bitmap temp = (Bitmap)source.Clone();
temp.MakeTransparent(transparentColor);
Bitmap newBitmap = new Bitmap(dest.Width, dest.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
Graphics g = Graphics.FromImage(newBitmap);
g.DrawImage(temp, new Rectangle(0, 0, dest.Width, dest.Height), dest, GraphicsUnit.Pixel);
g.Dispose();
temp.Dispose();
背景还要透明干什么呢?背景是固定的。
假设资源里边的前景图片错了,那么用程序处理一遍,重新保存为资源图片就行了。谁也不会没完没了地把图片变为透明的。 --------------------编程问答-------------------- 我上面写的方法三错了(如果想返回源图某区域像素对应不上),这里修改下
--------------------编程问答--------------------
public Bitmap ToTransparentPng3(Bitmap source, Rectangle dest, Color transparentColor)
{
if (source == null) return null;
Rectangle src = new Rectangle(0, 0, source.Width, source.Height);
src.Intersect(dest);
if (src != dest)
{
throw new ArgumentOutOfRangeException();
}
BitmapData sourceData = source.LockBits(new Rectangle(0, 0, source.Width, source.Height), ImageLockMode.ReadOnly, source.PixelFormat);
byte[] buffer = new byte[source.Height * sourceData.Stride];
Marshal.Copy(sourceData.Scan0, buffer, 0, buffer.Length);
Bitmap newBitmap = new Bitmap(dest.Width, dest.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
BitmapData destData = newBitmap.LockBits(new Rectangle(0, 0, newBitmap.Width, newBitmap.Height), ImageLockMode.ReadOnly, newBitmap.PixelFormat);
byte[] newBuffer = new byte[newBitmap.Height * destData.Stride];
int targetId = (dest.X + dest.Y * source.Width) * 4;
for (int i = 0; i < newBuffer.Length; i += 4)
{
int offset = targetId + i + (sourceData.Stride - destData.Stride) * (i / destData.Stride);
byte B = buffer[offset + 0];
byte G = buffer[offset + 1];
byte R = buffer[offset + 2];
byte A = buffer[offset + 3];
if (Color.FromArgb(A, R, G, B) != transparentColor)
{
newBuffer[i + 0] = B;
newBuffer[i + 1] = G;
newBuffer[i + 2] = R;
newBuffer[i + 3] = 255;
}
}
Marshal.Copy(newBuffer, 0, destData.Scan0, newBuffer.Length);
newBitmap.UnlockBits(destData);
source.UnlockBits(sourceData);
return newBitmap;
}
我表达得不好,只有1楼是做游戏的才知道我想干什么 --------------------编程问答-------------------- 不知道要的是不是这种效果,参考下
//将Image类型的图片转换为Bitmap
Bitmap bitmap = new Bitmap(this.SkinBack);
//判断要透明的颜色不等于透明,否则不处理,免得浪费资源
if (SkinTrankColor != Color.Transparent)
{
//MakeTransparent函数透明指定颜色
bitmap.MakeTransparent(SkinTrankColor);
}
//End完毕
补充:.NET技术 , C#