当前位置:编程学习 > C#/ASP.NET >>

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:颜色键 --------------------编程问答-------------------- 再加一种方法

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;
}
--------------------编程问答-------------------- 方法4第10行到14行换成下面的代码就避免源图被修改,用一张临时位图做透明化

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();
--------------------编程问答-------------------- PNG图片要做透明背景还是什么? --------------------编程问答--------------------
引用 4 楼 dylike 的回复:
PNG图片要做透明背景还是什么?


背景还要透明干什么呢?背景是固定的。

假设资源里边的前景图片错了,那么用程序处理一遍,重新保存为资源图片就行了。谁也不会没完没了地把图片变为透明的。 --------------------编程问答-------------------- 我上面写的方法三错了(如果想返回源图某区域像素对应不上),这里修改下

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;
}
--------------------编程问答--------------------
引用 4 楼 dylike 的回复:
PNG图片要做透明背景还是什么?


引用 4 楼 dylike 的回复:
Quote: 引用 5 楼 sp1234 的回复:

PNG图片要做透明背景还是什么?


背景还要透明干什么呢?背景是固定的。

假设资源里边的前景图片错了,那么用程序处理一遍,重新保存为资源图片就行了。谁也不会没完没了地把图片变为透明的。


我表达得不好,只有1楼是做游戏的才知道我想干什么 --------------------编程问答-------------------- 不知道要的是不是这种效果,参考下

//将Image类型的图片转换为Bitmap
Bitmap bitmap = new Bitmap(this.SkinBack);
//判断要透明的颜色不等于透明,否则不处理,免得浪费资源
if (SkinTrankColor != Color.Transparent)
{
    //MakeTransparent函数透明指定颜色
    bitmap.MakeTransparent(SkinTrankColor);
}
//End完毕
补充:.NET技术 ,  C#
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,