本文主要介绍:获取图片的灰度/修改彩色图片为黑白图片/修改图片的对比度
Bitmap类:Bitmap对象封装了一个GDI+的位图,此位图由图形图像的像素,以及其属性组成。用于处理由像素数据定义的图像的对象,包括如下属性和方法
1.GetPixel方法和SetPixel方法:用于获取和设置图像的指定像素的颜色
2.PixelFormat属性:返回图像的像素格式
3.Palette属性:获取和设置图像所使用的颜色调色板
4.Height/Width属性:返回图像的高度和宽度
5.LockBits方法和UnlockBits是一个很好的方法这种方法可以使我们指定像素的范围来控制位图的任一部分,从而避免对位图的像素逐个进行处理,每调用一次LockBits都要调用UnlockBits进行解锁
BitmapData类:
1.Height/Width属性:被锁定位图的高度/宽度属性
2.PixelsFormat属性:数据实际像素格式
3.Scan0属性:被锁定数组的首字节地址,如果整个图像被锁定,则是图像的第一个字节地址
4.Stride属性:步幅,也称为扫描宽度
private string path=Application.StartupPath;
private byte[] mappdata;
private void button1_Click(object sender,EventArgs e)
{
Image img=null;
Bitmap map=null;
//读取对应图片
using(FileStream fs=new FileStream(path+"\\1.png",FileMode.Open))
{
img=Image.FromStream(fs);
}
map=(Bitmap)img;
//将图片转换为黑白图片
ChangeToGrayImg(map);
//GetImageGrayData(map);
//Bitmap map1=ChangeImageGrayOnPixel(map,10);
//Bitmap map2=ChangeImageGrayOnMemory(map,100);
//Bitmap map3=ChangeImageGrayOnPixel(map,10);
}
//修改图片为黑白的三种算法
private void ChangeToGrayImg(Bitmap map)
{
int w=map.Width;
int h=map.Height;
Color pixel;
for(int x=0;x<w;x++)
{
for(int y=0;y<h;y++)
{
pixel=map.GetPixel(x,y);
int r=pixel.R;
int g=pixel.G;
int b=pixel.B;
int result=0;
int itype=2;
switch(itype)
{
case 0://平均值法
result=((r+g+b)/3);
break;
case 1://最大值法
result=r>g?r:g;
result=result>b?result:b;
break;
case 2://加权平均值法
result=((int)(0.7*r)+(int)(0.2*g)+(int)(0.1*b));
break;
}
map.SetPixel(x,y,Color.FromArgb(result,result,result));
}
}
//转换完成之后保存图片,这里没有重构,下面几个方法也能用
MemoryStream ms=new MemoryStream();
map.Save(ms,ImageFormat.Bmp);
ms.Seek(0,SeekOrigin.Begin);
byte[] buffer=new byte[ms.Length];
ms.Read(buffer,0,buffer.Length);
ms.Dispose();
using(FileStream fs=new FileStream(path+"\\111.bmp",FileMode.CreateNew,FileAccess.Write))
{
fs.Write(buffer,0,buffer.Length);
}
}
//根据图片获得图片的灰度数组
private void GetImageGrayData(Bitmap map)
{
BitmapData bmpData=map.LockBits(new Rectangle(0,0,map.Width,map.Height),ImageLockMode.ReadOnly,PixelFormat.Format8bppIndexed);
//获取扫描线的宽度
int stride=bmpData.Stride;
//显示宽度与扫描线宽度的间隙
int offset=stride.Width;
//获取bmpData的内存起始位置
IntPtr iptr=bmpData.Scan0;
//用stride宽度,表示这是内存区域的大小
int scanBytes=stride*map.Height;
//为目标分配内存
mapdata=new byte[scanBytes];
//copy内存中的数据到目标数组中
System.Runtime.InteropServices.Marshal.Copy(iptr,mapdata,0,scanBytes);
}
//基于像素和基于内存修改图片的对比度
//1.基于像素修改图片的对比度
public Bitmap ChangeImageGrayOnPixel(Bitmap bitmap,int degree/*对比度的加深比例*/)
{
Color curColor;
int grayR,grayG,grayB;
double Deg=(100.0+degree)/100.0;
for(int i=0;i<bitmap.Width;i++)
{
for(int j=0;j<bitmap.Height;j++)
{
curColor=bitmap.GetPixel(i,j);
grayR=Convert.ToInt16((((curColor.R/255.0-0.5)*Deg+0.5))*255);
grayG=Convert.ToInt16((((curColor.G/255.0-0.5)*Deg+0.5))*255);
grayB=Convert.ToInt16((((curColor.B/255.0-0.5)*Deg+0.5))*255);
if(grayR<0)
grayR=0;
else if(grayR>255)
grayR=255;
if(grayG<0)
grayG=0;
else if(grayG>255)
grayG=255;
if(grayB<0)
grayB=0;
else if(grayB>255)
grayB=255;
bitmap.SetPixel(i,j,Color.FromArgb(grayR,grayG,grayB));
}
}
return bitmap;
}
//2.基于内存修改图片的对比度
public unsafe Bitmap ChangeImageGrayOnMemory(Bitmap bitmap,int degree)
{
if(bitmap==null)
{
return null;
}
double Deg=(100+degree)/100.0;
int width=bitmap.Width;
int height=bitmap.Height;
int length=height*3*width;
byte[] RGB=new byte[length];
BitmapData data=bitmap.LockBits(new Rectangle(0,0,width,height),ImageLockMode.ReadWrite,PixelFormat.Format24bppRgb);
IntPtr Scan0=data.Scan0;
System.Runtime.InteropServices.Marshal.Copy(Scan0,RGB,0,length);
double gray=0;
for(int i=0;i<RGB.Length;i+=3)
{
for(int j=0;j<3;j++)
{
gray=(((RGB[i+j]/255.0-0.5)*Deg+0.5))*255.0;
if(gray>255)
{
gray=255;
}
else if(gray<0)
{
gray=0;
}
RGB[i+j]=(byte)gray;
}
}
System.Runtime.InteropServices.Marshal.Copy(RGB,0,Scan0,length);
bitmap.UnlockBits(data);
return bitmap;
}