C#下怎样处理并保存单色格式PNG图片?

C#下怎样处理并保存单色格式PNG图片?  用微软自带的画图,打开一个已经存在的单色PNG图片文件,然后复制图像粘贴上去,做点反色或其他处理再保存,可以得到黑白单色PNG图片;但是,如果有很多黑底白字的图片要想改成白纸黑字的单色PNG格式保存这就很麻烦了,譬如2,3百张BMP或JPG图片用来保存只有白纸黑字的书页真是浪费。可是,有些索引格式图像如单色位图,或者单色PNG,如果用C#的Graphics类处理之后,保存文件只能得

大家好,又见面了,我是你们的朋友全栈君。 

用微软自带的画图,打开一个已经存在的单色PNG图片文件,然后复制图像粘贴上去,做点反色或其他处理再保存,可以得到黑白单色PNG图片;但是,如果有很多黑底白字的图片要想改成白纸黑字的单色PNG格式保存这就很麻烦了,譬如2,3百张BMP或JPG图片用来保存只有白纸黑字的书页真是浪费。可是,有些索引格式图像如单色位图,或者单色PNG,如果用C#的Graphics类处理之后,保存文件只能得到非索引色格式或者GIF格式,若想以原格式保存文件似乎没有直接方便的方法可用,不得已只能用自己的代码一点一点去写像。

    以下代码,参考网上找了些的,加上实际证得:(注释并不是必需要的,有些编写代码过程中的记录,或者为了方便说明)

using System;

using System.Drawing;

using System.Drawing.Imaging;

using System.Runtime.InteropServices;

//打开任一索引色的或者非索引色的图像

Image img=Image.FromFile(“r.bmp”);

ImageAttributes ta=new ImageAttributes();

/* 下面用Graphics类改变像点颜色,是靠ImageAttributes来把

* 彩色变成灰度,或者颠倒黑白,发现用矩阵处理还是很方便的

*/

//如实际发现几个简单又好用的矩阵:

/* float[][] mm=new float[][]{ //彩色变灰度的矩阵

     new float[]{0.4f, 0.4f, 0.4f, 0, 0},

     new float[]{0.3f, 0.3f, 0.3f, 0, 0},

     new float[]{0.3f, 0.3f, 0.3f, 0, 0},

     new float[]{0,    0,    0,    1, 0},

     new float[]{0,    0,    0,    0, 1}

};

float[][] mm1=new float[][]{ //彩色反相的矩阵

     new float[]{0,    0.3f, 0.5f, 0, 0},

     new float[]{0.5f, 0.3f, 0.5f, 0, 0},

     new float[]{0.5f, 0.4f, 0,    0, 0},

     new float[]{0,    0,    0,    1, 0},

     new float[]{0,    0,    0,    0, 1}

};

*/

float[][] mm2=new float[][]{ //彩色变反相灰度的矩阵

     new float[]{-0.4f, -0.4f, -0.4f, 0, 0},

     new float[]{-0.3f, -0.3f, -0.3f, 0, 0},

     new float[]{-0.3f, -0.3f, -0.3f, 0, 0},

     new float[]{1,     1,     1,     1, 0},

     new float[]{0,     0,     0,     0, 1}

};

ColorMatrix cmt=new ColorMatrix(mm2);

ta.SetColorMatrix(cmt);

/* //如果确知图像里仅有纯黑白二色,也可用ColorMap来反相,它可逐色改变

ColorMap map1=new ColorMap();

map1.OldColor=Color.Black;

map1.NewColor=Color.White;

ColorMap map2=new ColorMap();

map2.OldColor=Color.White;

map2.NewColor=Color.Black;

ta.SetRemapTable(new ColorMap[]{map1,map2},ColorAdjustType.Bitmap);

*/

/* 有的图像比如索引格式的位图或GIF是无法创建Graphics的,

* 需要新建一非索引色位图取得Graphics对象以便做画或改变像点颜色。

*/

Bitmap bmp=new Bitmap(img.Width,img.Height);

Graphics g=Graphics.FromImage(bmp);

g.DrawImage(img,new Rectangle(0,0,bmp.Width,bmp.Height),0,0,img.Width,img.Height,GraphicsUnit.Pixel,ta);

//g.DrawString(“Foxit PDF Reader”,new Font(“宋体”,8),new SolidBrush(Color.White),0,0);

g.Dispose();

/* 在如下构造图像数据之前,也可以先创建一单色位图并锁定数据,

* 利用它现成的Stride简单计算出实际每行有效数据之后的填充字节数,而且可

* 在下面循环里直接写点Marshal.WriteByte(dt.Scan0,k,val);而不用数组拷贝

*/

//以下,把反相或者涂画后的像点数据每一行的每8点简单合并成1byte存储

int midrgb=Color.FromArgb(128,128,128).ToArgb();

int stride;//简单公式((width/8)+3)&(~3)

stride = (bmp.Width%8)==0 ? (bmp.Width/8) : (bmp.Width/8)+1;

stride = (stride%4)==0 ? stride : ((stride/4)+1)*4;

int k=bmp.Height*stride;

byte[] buf=new byte[k];

for(int j=0;j<bmp.Height;j++){

     k=j*stride;//因图像宽度不同、有的可能有填充字节需要跳越

     int x=0,ab=0;

     for(int i=0;i<bmp.Width;i++){

         //从灰度变单色(下法如果直接从彩色变单色效果不太好,不过反相也可以在这里控制)

         if ((bmp.GetPixel(i,j)).ToArgb() > midrgb) ab=ab*2+1; else ab=ab*2;

         x++;

         if(x==8){

             buf[k++]=(byte)ab;

             ab=0;

             x=0;

         }

     }

     if(x>0){

         //循环实现:剩余有效数据不满1字节的情况下须把它们移往字节的高位部分

         for(int t=x;t<8;t++)ab=ab*2;

         buf[k++]=(byte)ab;

     }

}

Bitmap bb=new Bitmap(img.Width,img.Height,PixelFormat.Format1bppIndexed);

BitmapData dt=bb.LockBits(new Rectangle(0,0,bb.Width,bb.Height),ImageLockMode.ReadWrite,bb.PixelFormat);

Marshal.Copy(buf,0,dt.Scan0,buf.Length);

bb.UnlockBits(dt);

//bb.MakeTransparent(Color.White);

/* 如果需要生成透明的单色图像,必须根据背景颜色不同,在此指定不同颜色为透明。

* 但是带透明的PNG不再是单色PNG格式,文件尺寸也更大一些。

* 在此是以原图黑底白字的为例,因为经过上面反相以后背景已变成白色,所以这里

* 指定了白色为透明色;反之应当指定黑色为透明。

* 注意:如果原图是透明背景白字的,等同黑底白字,这段代码全部不需要修改,可

* 以反相输出透明背景黑字的。但是,如果原图是透明背景黑字的,上面就不能用矩

* 阵做反相,否则由于变成全黑而最后输出无字透明;

* 因此,只需Graphics那里改成不使用ImageAttribute参数的DrawImage画出白色背景

* 黑字,然后这里不用改变就仍然输出原样的透明背景黑字;

* 如果一定要求把它反相成透明背景白字的(一般也没有这种需要),只要在上面循环

* 里注释着从灰度变单色的地方把if条件的>号改成<号,这里改成指定黑色为透明即可。

*/

//保存时若不指定第2参数,单色位图默认地被以单色PNG格式保存。虽然是单色像素格式,

//不影响保存为GIF文件或者非索引色图片,只不过GIF不能指定透明色,否则全黑。

bb.Save(“w.png”,ImageFormat.Png);

bb.Dispose();

bmp.Dispose();

img.Dispose();

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/162700.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 已成功刷新dns解析缓存后怎么操作_刷新dns缓存的命令

    已成功刷新dns解析缓存后怎么操作_刷新dns缓存的命令步骤一、首先按住键盘win+R组合键,打开了一个运行窗口,之后在运行窗口上输入“CMD”命令,执行该命令即可打开命令提示符窗口了。步骤二、然后在命令提示符上线查看下你的电脑上的dns缓存的全部信息,输入“ipconfig/displaydns”即可查询dns缓存信息了。之后在输入“ipconfig/flushdns”命令敲回车键即可将你本机上的dns缓存清空了。当然如果你不信的话,可以重新输入“ipconfig/displaydns”查询dnd缓存就能知道是否清空了本机dns缓存信息了。运行:ip

  • 软件性能测试知识汇总[通俗易懂]

    软件性能测试知识汇总[通俗易懂]一软件性能概述1.软件性能的概念:软件性能是与软件功能相对应的一种非常重要的非功能特性,表明了软件系统对时间及时性及资源经济性的要求。2.不同角色对软件性能的理解(1)从系统用户角度看软件性

  • 图解Golang的GC算法「建议收藏」

    图解Golang的GC算法「建议收藏」虽然Golang的GC自打一开始,就被人所诟病,但是经过这么多年的发展,Golang的GC已经改善了非常多,变得非常优秀了。以下是GolangGC算法的里程碑:v1.1STWv1.3MarkSTW,Sweep并行v1.5三色标记法v1.8hybridwritebarrier经典的GC算法有三种:引用计数(referencecounting)、标记-清扫(mar…

  • 什么是协程「建议收藏」

    什么是协程「建议收藏」来自:程序员小灰(微信号:chengxuyuanxiaohui)—————第二天—————————————————什么是进程和线程有一定基础的小伙伴们肯定都知道进程和线程。进程是什么呢?直白地讲,进程就是应用程序的启动实例。比如我们运行一个游戏,打开一个软件,就是开启了一个进程。进程拥有代码和打开的文件资源、数据资…

  • MCMC采样_MCMC认证

    MCMC采样_MCMC认证MCMC(一)蒙特卡罗方法MCMC(二)马尔科夫链MCMC(三)MCMC采样和M-H采样MCMC(四)Gibbs采样在MCMC(三)MCMC采样和M-H采样中,我们讲到了M-H采样已经可以很好

  • 前端的浅拷贝和深拷贝区别_解构赋值是深拷贝还是浅拷贝

    前端的浅拷贝和深拷贝区别_解构赋值是深拷贝还是浅拷贝一、浅拷贝和深拷贝的区别数据都是存储在内存当中,而我们调用数据的时候都是通过地址来调用数据。对于浅拷贝来说,比如一个数组,只要我们修改了一个拷贝数组,那么原数组也会改变!vara=[0,1,2,3,4];varb=a;console.log(b);//[0,1,2,3,4]console.log(a);//[0,1,…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号