如何快速获取bitmap 像素的像素矩阵

57388人阅读
BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height),
ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
int stride = bmData.S
System.IntPtr Scan0 = bmData.Scan0;
byte * p = (byte *)(void *)Scan0;
int nOffset = stride - b.Width*3;
int nWidth = b.Width * 3;
for(int y=0;y&b.H++y)
for(int x=0; x & nW ++x )
p[0] = (byte)(255-p[0]);
b.UnlockBits(bmData);
BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height),
ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
int stride = bmData.S
System.IntPtr Scan0 = bmData.Scan0;
byte * p = (byte *)(void *)Scan0;
int nOffset = stride - b.Width*3;
byte red, green,
for(int y=0;y&b.H++y)
for(int x=0; x & b.W ++x )
blue = p[0];
green = p[1];
red = p[2];
p[0] = p[1] = p[2] = (byte)(.299 * red + .587 * green + .114 * blue);
b.UnlockBits(bmData);
if (nBrightness & -255 || nBrightness & 255)
BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width,
b.Height), ImageLockMode.ReadWrite,
PixelFormat.Format24bppRgb);
int stride = bmData.S
System.IntPtr Scan0 = bmData.Scan0;
&int nVal = 0;
byte * p = (byte *)(void *)Scan0;
int nOffset = stride - b.Width*3;
int nWidth = b.Width * 3;
for(int y=0;y&b.H++y)
for(int x=0; x & nW ++x )
nVal = (int) (p[0] + nBrightness);
if (nVal & 0) nVal = 0;
if (nVal & 255) nVal = 255;
p[0] = (byte)nV
b.UnlockBits(bmData);
image to byte[]& MemoryStream ms=new MemoryStream();&&&byte[] imagedata=&&&pictureBox1.Image.Save(ms,System.Drawing.Imaging.ImageFormat.Gif );&&&imagedata=ms.GetBuffer ();byte[] to image& ms = New IO.MemoryStream(by)&&img = Drawing.Image.FromStream(ms)
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:3758721次
积分:34787
积分:34787
排名:第124名
原创:58篇
转载:1368篇
评论:375条
(1)(10)(1)(4)(3)(14)(27)(17)(5)(34)(24)(17)(25)(43)(8)(24)(1)(10)(1)(2)(2)(12)(1)(5)(12)(13)(9)(1)(5)(107)(21)(35)(2)(4)(11)(21)(3)(8)(2)(4)(3)(12)(6)(4)(9)(20)(10)(39)(24)(2)(59)(32)(34)(13)(44)(150)(56)(50)(41)(24)(95)(34)(3)(8)(43)(35)(27)
<a href="/article怎么得到一张bmp图片的像素数组 - ITeye问答
具体也就是怎么用 getRGB(int startX, int startY, int w, int h, int[] rgbArray, int offset, int scansize)
这个方法& 最好给个例子&& 而且最好是 存到Byte数组中&&&
注:api我已经看过了&& 希望能得到一个用这个函数的例子&&
采纳的答案
上述代码是
1,读取一个bmp文件,把bmp的所有像素用rgbArray存储起来,
2,然后取其中一个像素点(x0,y0),把它构造成一个Color对象,
3,构造一个类型一样的BufferedImage imgOut,把像素矩阵rgbArray写到BufferedImage,
4,把imgOut写入文件
&& 这个Color对象有getRed,getBlue,getBlack方法,可以分别获取这个像素在三个颜色分量上的灰度值。
int的rgb(4 byte)共有四个信息,rgb的格式是0xFFFFFFFF,分别表示 alpha 信息:R分量:G分量:B分量,各占8bit。所以你所谓的byte数组不知道是什么情况,一个byte是无法存储一个像素的。
public static void main(String[] args) {
OutputStream output =
// read bmp
BufferedImage img = ImageIO.read(new File("F:/temp/1.bmp"));
int imageType = img.getType();
int w = img.getWidth();
int h = img.getHeight();
int startX = 0;
int startY = 0;
int offset = 0;
int scansize =
// rgb的数组
int[] rgbArray = new int[offset + (h - startY) * scansize
+ (w - startX)];
img.getRGB(startX, startY, w, h, rgbArray, offset, scansize);
int x0 = w / 2;
int y0 = h / 2;
int rgb = rgbArray[offset + (y0 - startY) * scansize
+ (x0 - startX)];
Color c = new Color(rgb);
System.out.println("中间像素点的rgb:" + c);
// create and save to bmp
File out = new File("F:/temp/2.bmp");
if (!out.exists())
out.createNewFile();
output = new FileOutputStream(out);
BufferedImage imgOut = new BufferedImage(w, h, imageType);
imgOut.setRGB(startX, startY, w, h, rgbArray, offset, scansize);
ImageIO.write(imgOut, "bmp", output);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (output != null)
output.close();
} catch (IOException e) {
已解决问题
未解决问题opencv中如何获取原始像素数组
请教下根据打开图像的路径读图srcimage=&cvLoadImage(FilePath)后怎样获取原始像素数组?谢谢各位
回复讨论(解决方案)
直接Mat&img&=&imread(&lena.jpg&)读取即可:
-12:45&&&[]
已知处理后的像素数组为:color(100,100)
如何利用GdipDrawImageRectI&Graphics,&Bitmap,&5,&30,&bmW,&bmH&&函数
或者其他函数将color
00:29&&&[]
现在我通过相机采集到了原始像素数组(320&256),图像是16位的,即2个字节代表一个像素。
如何将像素数组转换为BMP,或者将像素数组赋值给Mat(OpenCV2.&)及IplImg(OpenCV1.&)。
回复讨论(解决方案)
每一个像素应该
19:28&&&[]
我需要动态画一些特殊的图形,例如函数曲线。我的想法是建立一个二维像素数组,像素格式为红绿蓝透明0xRRGGBBAA,我先在像素数组中画图形,然后把数组拷贝到纹理中,最后把纹理渲染出来。
我刚刚接触DX9,还不太清楚纹理的数据格式,请问怎样把像素数组拷贝到纹理中去?
回复讨论(解决方案
16:34&&&[]
;&int&imageLength)
闯入一个图片的byte数组,生成一个图片对象。
ARGB数组&不是我获取的rgb像素数组吗?
ARGB数组&不是我获取的rgb像素数组吗?
是的,就只通过getRGB获取的整型数组
谢谢大哥了,我终于
-15:50&&&[]
比如现在有一个图像路径C:\\TEST.JPG文件,我通过处理得到这个图片的像素BYTE*&image1,我经过滤波器处理平滑又得到了一个新的像素值BYTE*&image2,我想问下如何把image2绘制出来!!
回复讨论(解决方案)
应该将象素数组image2使用
-11:33&&&[]
} //获取位图像素数组
Color&coclient[]; //定义客户区位图数组
Bitmap&*bitmap6=::new&Bitmap((HBITMAP)::GetCurrentObject(hActiveDC,&nbsp
-11:57&&&[]
,分析bitmapheader获取位图信息,载入位图数据
方法2、直接将位图当做资源载入进来然后获取位图像素信息
BITMAPINFO&*&pBmpI
BYTE&*&pBmpD
BITMAPFILEHEADER&nbsp
14:11&&&[]
怎么没发现WPF下画像素点的函数,不可能不能画像素点吧?100w个像素点坐标数组,怎么快速画出来呢?
回复讨论(解决方案)
在WPF中有个Path类,你可以通过这个去画图,详情你可以参考这篇MSDN文档:
-09:20&&&[]
BMP图像的像素数据是从
//左下角:由左往右,由上往下逐行扫描的
&&&&&&&&&&&&&&&&int&L1=0
-12:25&&&[]
1、像素数组是程序计算好的,已经行4字节对齐
2、像素数据被修改后需要重新显示,即一个像素数组会被多次使用
回复讨论(解决方案)
如果你的数据完全符合BMP的标准,使用SetDIBitsToDevice(不缩放显示)&和&StretchDIBits(缩放)子哦最为
-19:08&&&[]
如题,百度了一下,有一篇文章是用GetBitmapBits函数拷贝CBitmap中的像素数据,修改完副本后,再用SetBitmapBits函数将副本覆盖进去。
感觉这个拷贝操作会影响效率,请问,用什么方法可以直接用指针引用像素数据并进行修改?
回复讨论(解决方案)
-18:23&&&[]一.Bitmap类
Bitmap对象封装了GDI+中的一个位图,此位图由图形图像及其属性的像素数据组成.因此Bitmap是用于处理由像素数据定义的图像的对象.该类的主要方法和属性如下:
1. GetPixel方法和SetPixel方法:获取和设置一个图像的指定像素的颜色.
2. PixelFormat属性:返回图像的像素格式.
3. Palette属性:获取和设置图像所使用的颜色调色板.
4. Height Width属性:返回图像的高度和宽度.
5.&LockBits方法和UnlockBits方法:分别锁定和解锁系统内存中的位图像素.在基于像素点的图像处理方法中使用LockBits和UnlockBits是一个很好的方式,这两种方法可以使我们指定像素的范围来控制位图的任意一部分,从而消除了通过循环对位图的像素逐个进行处理,每调用LockBits之后都应该调用一次UnlockBits.(16.6.15Useful)
二.BitmapData类
BitmapData对象指定了位图的属性
1. Height属性:被锁定位图的高度.
2. Width属性:被锁定位图的高度.
3. PixelFormat属性:数据的实际像素格式.
4. Scan0属性:被锁定数组的首字节地址,如果整个图像被锁定,则是图像的第一个字节地址.
5. Stride属性:步幅,也称为扫描宽度.
& & & & & & & & & & & & & & & & & & & &图不错,比较好理解(16.6.15)
如上图所示,数组的长度并不一定等于图像像素数组的长度,还有一部分未用区域,这涉及到位图的,系统要保证每行的字节数必须为4的倍数.
三.Graphics类
Graphics对象是GDI+的关键所在,许多对象都是由Graphics类表示的,该类定义了绘制和填充图形对象的方法和属性,一个应用程序只要需要进行绘制或着色,它就必须使用Graphics对象.
四.Image类
  这个类提供了位图和元文件操作的函数.Image类被声明为abstract,也就是说Image类不能实例化对象,而只能做为一个基类
1.FromFile方法:它根据输入的文件名产生一个Image对象,它有两种函数形式:
public static Image FromFile(string filename);
public static Image FromFile(string filename, bool useEmbeddedColorManagement);
2.FromHBitmap方法:它从一个windows句柄处创建一个bitmap对象,它也包括两种函数形式:
public static bitmap fromhbitmap(intptr hbitmap);
public static bitmap fromhbitmap(intptr hbitmap, intptr hpalette);
3. FromStream方法:从一个数据流中创建一个image对象,它包含三种函数形式:
public static image fromstream(stream stream);
public static image fromstream(stream stream, bool useembeddedcolormanagement);
fromstream(stream stream, bool useembeddedcolormanagement, bool validateimagedata);
有了上面的了解,我们便可以开始利用C#做图像处理,下面介绍几种方法:
一.&&&打开、保存、显示图像
privateBitmap srcBitmap = null;
privateBitmap showBitmap = null;
//打开文件
privatevoid menuFileOpen_Click(object sender, EventArgs e)
OpenFileDialog openFileDialog = newOpenFileDialog();
openFileDialog.Filter = @"Bitmap文件(*.bmp)|*.bmp|Jpeg文件(*.jpg)|*.jpg|所有合适文件(*.bmp,*.jpg)|*.*.jpg";
openFileDialog.FilterIndex = 3;
openFileDialog.RestoreDirectory = true;
if (DialogResult.OK == openFileDialog.ShowDialog())
srcBitmap = (Bitmap)Bitmap.FromFile(openFileDialog.FileName, false);
showBitmap = srcB
this.AutoScroll = true;
this.AutoScrollMinSize =
newSize((int)(showBitmap.Width), (int)(showBitmap.Height));
this.Invalidate();
//保存图像文件
privatevoid menuFileSave_Click(object sender, EventArgs e)
if (showBitmap != null)
SaveFileDialog saveFileDialog = newSaveFileDialog();
saveFileDialog.Filter =
@"Bitmap文件(*.bmp)|*.bmp|Jpeg文件(*.jpg)|*.jpg|所有合适文件(*.bmp,*.jpg)|*.*.jpg";
saveFileDialog.FilterIndex = 3;
saveFileDialog.RestoreDirectory = true;
if (DialogResult.OK == saveFileDialog.ShowDialog())
ImageFormat format = ImageFormat.J
switch (Path.GetExtension(saveFileDialog.FileName).ToLower())
case".jpg":
format = ImageFormat.J
case".bmp":
format = ImageFormat.B
MessageBox.Show(this, "Unsupported image format was specified", "Error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
showBitmap.Save(saveFileDialog.FileName,format );
catch (Exception)
MessageBox.Show(this, "Failed writing image file", "Error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
c#中将bitmap或者image保存为清晰的gif
在c#中默认可以讲bitmap保存为gif等格式,但是这种保存方法保存的gif会严重失真,正常情况下的代码:
1 System.Drawing.Bitmap b = new System.Drawing.Bitmap(&c://original_image.gif&);&2&  System.Drawing.Image thmbnail = b.GetThumbnailImage(100,75,null,new IntPtr());&3&  thmbnail.Save(&c://thumnail.gif&, System.Drawing.Imaging.ImageFormat.Gif);&
一个批量处理图片的软件,包括各种处理方式,处理效果,但是在保存为gif的时候出现了问题,在网上查了很久也没有发现一个可用的改善gif图片质量的方法,找到了一个解决办法,保存出来的gif容量大减,但是效果基本符合常规这中方法就是就是&Octree&&。
&Octree&&算法允许我们插入自己的算法来量子化我们的图像。
一个好的&颜色量子化&算法应该考虑在两个像素颗粒之间填充与这两个像素颜色相近的过渡颜色,提供更多可视颜色空间。
Morgan Skinner提供了很好的&Octree&&算法代码,大家可以下载参考使用。
  使用OctreeQuantizer很方便:
System.Drawing.Bitmap b = new System.Drawing.Bitmap(&c://original_image.gif&);
 System.Drawing.Image thmbnail = b.GetThumbnailImage(100,75,null,new IntPtr());
 OctreeQuantizer quantizer = new OctreeQuantizer ( 255 , 8 ) ;
 using ( Bitmap quantized = quantizer.Quantize ( thmbnail ) )
   quantized.Save(&c://thumnail.gif&, System.Drawing.Imaging.ImageFormat.Gif);
 OctreeQuantizer grayquantizer = new GrayscaleQuantizer ( ) ;
 using ( Bitmap quantized = grayquantizer.Quantize ( thmbnail ) )
   quantized.Save(&c://thumnail.gif&, System.Drawing.Imaging.ImageFormat.Gif);
你可以点击这里下载类的文件(项目文件),根据我的试用,只需要两个类文件(OctreeQuantizer.cs,Quantizer.cs)即可运行,将这两个类文件的namespace改成你项目的名称就行,还有,需要在不安全编译的方式下编译,右击项目名称,在生成选项卡里选择"允许不安全代码"即可
&&&&//窗口重绘,在窗体上显示图像,重载Paint
privatevoid frmMain_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
if (showBitmap != null)
Graphics g = e.G
g.DrawImage(showBitmap, newRectangle(this.AutoScrollPosition.X, this.AutoScrollPosition.Y ,
(int)(showBitmap.Width), (int)(showBitmap.Height)));
privatevoid menu2Gray_Click(object sender, EventArgs e)
if (showBitmap == null) return;
showBitmap = RGB2Gray(showBitmap);//下面都以RGB2Gray为例
this.Invalidate();
二.&&&提取像素法
&&&&&&这种方法简单易懂,但相当耗时,完全不可取.
publicstaticBitmap RGB2Gray(Bitmap srcBitmap)
Color srcC
int wide = srcBitmap.W
int height = srcBitmap.H
for (int y = 0; y & y++)
for (int x = 0; x & x++)
//获取像素的RGB颜色值
srcColor = srcBitmap.GetPixel(x, y);
byte temp = (byte)(srcColor.R * .299 + srcColor.G * .587 + srcColor.B * .114);
//设置像素的RGB颜色值
srcBitmap.SetPixel(x, y, Color.FromArgb(temp, temp, temp));
return srcB
三.&&&内存法
这是比较常用的方法
publicstaticBitmap RGB2Gray(Bitmap srcBitmap)
int wide = srcBitmap.W
int height = srcBitmap.H
Rectangle rect = newRectangle(0, 0, wide, height);
//将Bitmap锁定到系统内存中,获得BitmapData
BitmapData srcBmData = srcBitmap.LockBits(rect,
ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
//创建Bitmap
Bitmap dstBitmap = CreateGrayscaleImage(wide, height);//这个函数在后面有定义
BitmapData dstBmData = dstBitmap.LockBits(rect,
ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
//位图中第一个像素数据的地址。它也可以看成是位图中的第一个扫描行
System.IntPtr srcPtr = srcBmData.Scan0;
System.IntPtr dstPtr = dstBmData.Scan0;
//将Bitmap对象的信息存放到byte数组中
int src_bytes = srcBmData.Stride *
byte[] srcValues = newbyte[src_bytes];
int dst_bytes = dstBmData.Stride *
byte[] dstValues = newbyte[dst_bytes];
//复制GRB信息到byte数组
System.Runtime.InteropServices.Marshal.Copy(srcPtr, srcValues, 0, src_bytes);
System.Runtime.InteropServices.Marshal.Copy(dstPtr, dstValues, 0, dst_bytes);
//根据Y=0.299*R+0.114*G+0.587B,Y为亮度
for (int i = 0; i & i++)
for (int j = 0; j & j++)
//只处理每行中图像像素数据,舍弃未用空间
//注意位图结构中RGB按BGR的顺序存储
int k = 3 *
byte temp = (byte)(srcValues[i * srcBmData.Stride + k + 2] * .299
+ srcValues[i * srcBmData.Stride + k + 1] * .587
+ srcValues[i * srcBmData.Stride + k] * .114);
dstValues[i * dstBmData.Stride + j] =
System.Runtime.InteropServices.Marshal.Copy(dstValues, 0, dstPtr, dst_bytes);
//解锁位图
srcBitmap.UnlockBits(srcBmData);
dstBitmap.UnlockBits(dstBmData);
return dstB
四&&指针法
C/C++的习惯,不是C#的特点
publicstaticBitmap RGB2Gray(Bitmap srcBitmap)
int wide = srcBitmap.W
int height = srcBitmap.H
Rectangle rect = newRectangle(0, 0, wide, height);
BitmapData srcBmData = srcBitmap.LockBits(rect,
ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
Bitmap dstBitmap = CreateGrayscaleImage(wide, height);
BitmapData dstBmData = dstBitmap.LockBits(rect,
ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
System.IntPtr srcScan = srcBmData.Scan0;
System.IntPtr dstScan = dstBmData.Scan0;
Unsafe //启动不安全代码
byte* srcP = (byte*)(void*) srcS
byte* dstP = (byte*)(void*) dstS
int srcOffset = srcBmData.Stride - wide * 3;
int dstOffset = dstBmData.Stride -
byte red, green,
for (int y = 0; y & y++)
for (int x = 0; x & x++, srcP += 3, dstP++)
blue = srcP [0];
green = srcP [1];
red = srcP [2];
* dstP = (byte)(.299 * red + .587 * green + .114 * blue);
srcP += srcO
dstP += dstO
srcBitmap.UnlockBits(srcBmData);
dstBitmap.UnlockBits(dstBmData );
return dstB
五.&&&矩阵法
并不是什么新方法,只是将图像数据分做R,G,B三个矩阵(二维数组)存储,类似MATLAB的习惯.
publicstaticbool GetRGB(Bitmap Source, outint[,] R, outint[,] G, outint[,] B)
int iWidth = Source.W
int iHeight = Source.H
Rectangle rect = newRectangle(0, 0, iWidth, iHeight);
System.Drawing.Imaging.BitmapData bmpData = Source.LockBits(rect,
System.Drawing.Imaging.ImageLockMode.ReadWrite, Source.PixelFormat);
IntPtr iPtr = bmpData.Scan0;
int iBytes = iWidth * iHeight * 3;
byte[] PixelValues = new byte[iBytes];
System.Runtime.InteropServices.Marshal.Copy(iPtr, PixelValues, 0, iBytes);
Source.UnlockBits(bmpData);
R = newint[iHeight, iWidth];
G = newint[iHeight, iWidth];
B = newint[iHeight, iWidth];
int iPoint = 0;
for (int i = 0; i & iH i++)
for (int j = 0; j & iW j++)
B[i, j] = Convert.ToInt32(PixelValues[iPoint++]);
G[i, j] = Convert.ToInt32(PixelValues[iPoint++]);
R[i, j] = Convert.ToInt32(PixelValues[iPoint++]);
return true;
catch (Exception)
publicstaticBitmap FromRGB(int[,] R, int[,] G, int[,] B)
int iWidth = G.GetLength(1);
int iHeight = G.GetLength(0);
Bitmap Result = newBitmap(iWidth, iHeight,
System.Drawing.Imaging.PixelFormat.Format24bppRgb);
Rectangle rect = newRectangle(0, 0, iWidth, iHeight);
System.Drawing.Imaging.BitmapData bmpData = Result.LockBits(rect,
System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
IntPtr iPtr = bmpData.Scan0;
int iStride = bmpData.S
int iBytes = iWidth * iHeight * 3;
byte[] PixelValues = newbyte[iBytes];
int iPoint = 0;
for (int i = 0; i & iH i++)
for (int j = 0; j & iW j++)
int iG = G[i, j];
int iB = B[i, j];
int iR = R[i, j];
PixelValues[iPoint] = Convert.ToByte(iB);
PixelValues[iPoint + 1] = Convert.ToByte(iG);
PixelValues[iPoint + 2] = Convert.ToByte(iR);
iPoint += 3;
System.Runtime.InteropServices.Marshal.Copy(PixelValues, 0, iPtr, iBytes);
Result.UnlockBits(bmpData);
publicstaticbool GetGray(Bitmap srcBitmap, outbyte [,] gray)
Bitmap tempB
if (srcBitmap.PixelFormat != PixelFormat.Format8bppIndexed)
tempBitmap = ImageProcess.Image.Gray(srcBitmap);
tempBitmap = srcB
int wide = tempBitmap.W
int height = tempBitmap.H
gray = newbyte [height, wide];
BitmapData gbmData = tempBitmap.LockBits(newRectangle(0, 0, wide, height),
ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
System.IntPtr ScanG = gbmData.Scan0;
int gOffset = gbmData.Stride -
byte* g = (byte*)(void*)ScanG;
for (int y = 0; y & y++)
for (int x = 0; x & x++, g++)
gray[y ,x ] =*g;
tempBitmap.UnlockBits(gbmData);
Public static Bitmap FromGray(byte [,] Gray)
int iWidth = Gray.GetLength(1);
int iHeight = Gray.GetLength(0);
Bitmap dstBitmap = ImageProcess.Image.CreateGrayscaleImage(iWidth, iHeight);
BitmapData gbmData = dstBitmap.LockBits(newRectangle(0, 0, iWidth, iHeight),
ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
System.IntPtr ScanG = gbmData.Scan0;
int gOffset = gbmData.Stride - iW
byte* g = (byte*)(void*)ScanG;
for (int i = 0; i & iH i++)
for (int j = 0; j & iW j++)
*g=(byte )Gray[i, j] ;
dstBitmap.UnlockBits(gbmData);
return dstB
///&summary&
/// Create and initialize grayscale image
///&/summary&
publicstaticBitmap CreateGrayscaleImage( int width, int height )
// create new image
Bitmap bmp = newBitmap( width, height, PixelFormat.Format8bppIndexed );
// set palette to grayscale
SetGrayscalePalette( bmp );
// return new image
///&summary&
/// Set pallete of the image to grayscale
///&/summary&
publicstaticvoid SetGrayscalePalette( Bitmap srcImg )
// check pixel format
if ( srcImg.PixelFormat != PixelFormat.Format8bppIndexed )
thrownewArgumentException( );
// get palette
ColorPalette cp = srcImg.P
// init palette
for ( int i = 0; i & 256; i++){
cp.Entries[i] = Color.FromArgb( i, i, i );
srcImg.Palette =
C#数字图像处理的3种典型方法(精简版)
C#数字图像处理有3种典型方法:提取像素法、内存法、指针法。其中提取像素法使用的是GDI+中的Bitmap.GetPixel和Bitmap.SetPixel方法;内存法是通过LockBits方法来获取位图的首地址,从而把图像数据直接复制到内存中进行处理;指针法与内存法相似,但该方法直接应用指针对位图进行操作,由于在默认情况下,C#不支持指针运算,所以该方法只能在unsafe关键字所标记的代码块中使用。以一幅真彩色图像的灰度化为例,下面代码分别展现了这3种方法的使用,方便大家学习图像处理的基本技巧。
(1) 像素提取法
if (curBitmap != null)
Color curC
for (int i = 0; i & curBitmap.W i++)
for (int j = 0; j & curBitmap.H j++)
curColor = curBitmap.GetPixel(i, j);
gray = (int)(0.3 * curColor.R + 0.59 * curColor.G * 0.11 * curColor.B);
curBitmap.SetPixel(i, j, curColor);
(2) 内存法
if (curBitmap != null)
int width = curBitmap.W
int height = curBitmap.H
int length = height * 3 *
RGB = new byte[length];
BitmapData data = curBitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
System.IntPtr Scan0 = data.Scan0;
System.Runtime.InteropServices.Marshal.Copy(Scan0, RGB, 0, length);
double gray = 0;
for (int i = 0; i & RGB.L i=i+3)
gray = RGB[i + 2] * 0.3 + RGB[i + 1] * 0.59 + RGB[i] * 0.11;
RGB[i + 2] = RGB[i + 1] = RGB[i] = (byte)
System.Runtime.InteropServices.Marshal.Copy(RGB, 0, Scan0, length);
curBitmap.UnlockBits(data);
(3) 指针法
if (curBitmap != null)
int width = curBitmap.W
int height = curBitmap.H
BitmapData data = curBitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
System.IntPtr Scan0 = data.Scan0;
int stride = data.S
System.Runtime.InteropServices.Marshal.Copy(Scan0, RGB, 0, length);
byte* p = (byte*)Scan0;
int offset = stride - width * 3;
double gray = 0;
for (int y = 0; y & y++)
for (int x = 0; x & x++)
gray = 0.3 * p[2] + 0.59 * p[1] + 0.11 * p[0];
p[2] = p[1] = p[0] = (byte)
curBitmap.UnlockBits(data);
在以上3种方法中,提取像素法能直观的展示图像处理过程,可读性很好,但效率最低,并不适合做图像处理方面的工程应用;内存法把图像直接复制到内存中,直接对内存中的数据进行处理,速度明显提高,程序难度也不大;指针法直接应用指针来对图像进行处理,所以速度最快。
简单图片处理函数代码(C#)
一、生成图片并实现颜色渐变效果&
Response.Clear();&&&& Bitmap imgOutput = new Bitmap(100, 50);&&&& Graphics gic = Graphics.FromImage(imgOutput);
gic.Clear(Color.BlueViolet);&&&& gic.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiA&&&& gic.DrawString("渐变图形", new Font("黑体",16,FontStyle.Italic),
new SolidBrush(Color.White),new PointF(2,2));&&&& gic.FillRectangle(new System.Drawing.Drawing2D.LinearGradientBrush(new Point(0,0),
new Point(100,50), Color.FromArgb(0,0,0,0),
Color.FromArgb(255,255,255,255)),0,0,100,50);
&&& imgOutput.Save(Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg);&&&& gic.Dispose();&&&& imgOutput.Dispose();&&&& Response.End();&二、对图片进行反转&&&& System.Drawing.Image drawimage = System.Drawing.Image.FromFile(photopath);//photopath表示图片的物理地址&&&& drawimage.RotateFlip(RotateFlipType.Rotate270FlipNone);&&&& if(File.Exists(photopath))&&&& {&&&&&&&&& File.SetAttributes(photopath,FileAttributes.Normal);&&&&&&&&& File.Delete(photopath);&&&& }&&&& drawimage.Save(photopath,System.Drawing.Imaging.ImageFormat.Jpeg);&&&& drawimage.Dispose();&三、对图片进行缩放&&&& System.Drawing.Image drawimage = System.Drawing.Image.FromFile(photopath);&&&& Bitmap imgOutput = new Bitmap(drawimage,60,30);&&&& imgOutput.Save(newphotppath, System.Drawing.Imaging.ImageFormat.Jpeg);&&&& imgOutput.Dispose();&&&&&& Response.End();&其他还有一些画线、画矩形、画圆等的函数和方法都可以在System.Drawing中找到;
本文的实例是一个数字图像处理的应用程序,它完成的功能包括对图像颜色的翻转、对图像进行灰度处理和对图像进行增亮处理。该程序对图像进行处理部分的代码包含在一个专门的Filters类里面,通过调用该类里的静态成员函数,我们就可以实现相应的图像处理功能了。为实现图像处理,我们要对图像进行逐个象素处理。我们知道图像是由一个个的象素点组成的,对一幅图像的每个象素进行了相应的处理,最后整个图像也就处理好了。在这个过程中,我们只需对每个象素点进行相应的处理,在处理过程中却不需要考虑周围象素点对其的影响,所以相对来说程序的实现就变得简单多了。
  由于GDI+中的BitmapData类不提供对图像内部数据的直接访问的方法,我们唯一的办法就是使用指针来获得图像的内部数据,这时我们就得运用unsafe这个关键字来指明函数中访问图像内部数据的代码块了。在程序中,我还运用了打开文件和保存文件等选项,以使我们的辛勤劳动不付之东流。
  二.程序的实现:
Invert()、Gray()、Brightness()等三个函数均包含在Filters类里面,
Invert()函数的算法如下:
public static bool Invert(Bitmap b)
BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height),
ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
int stride = bmData.S
System.IntPtr Scan0 = bmData.Scan0;
byte * p = (byte *)(void *)Scan0;
int nOffset = stride - b.Width*3;
int nWidth = b.Width * 3;
for(int y=0;y&b.H++y)
for(int x=0; x & nW ++x )
p[0] = (byte)(255-p[0]);
b.UnlockBits(bmData);
return true;
该函数以及后面的函数的参数都是Bitmap类型的,它们传值的对象就是程序中所打开的图像文件了。该函数中的BitmapData类型的bmData包含了图像文件的内部信息,bmData的Stride属性指明了一条线的宽度,而它的Scan0属性则是指向图像内部信息的指针。本函数完成的功能是图像颜色的翻转,实现的方法即用255减去图像中的每个象素点的值,并将所得值设置为原象素点处的值,对每个象素点进行如此的操作,只到整幅图像都处理完毕。函数中的unsafe代码块是整个函数的主体部分,首先我们取得图像内部数据的指针,然后设置好偏移量,同时设置nWidth为b.Width*3,因为每个象素点包含了三种颜色成分,对每个象素点进行处理时便要进行三次处理。接下来运用两个嵌套的for循环完成对每个象素点的处理,处理的核心便是一句:p[0] = (byte)(255-p[0]);。在unsafe代码块后,便可运用b.UnlockBits(bmData)进行图像资源的释放。函数执行成功,最后返回true值。注:由于是要编译不安全代码,所以得将项目属性页中的"允许不安全代码块"属性设置为true,
Gray()函数的算法如下:
public static bool Gray(Bitmap b)
BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height),
ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
int stride = bmData.S
System.IntPtr Scan0 = bmData.Scan0;
byte * p = (byte *)(void *)Scan0;
int nOffset = stride - b.Width*3;
byte red, green,
for(int y=0;y&b.H++y)
for(int x=0; x & b.W ++x )
blue = p[0];
green = p[1];
red = p[2];
p[0] = p[1] = p[2] = (byte)(.299 * red + .587 * green + .114 * blue);
b.UnlockBits(bmData);
return true;
本函数完成的功能是对图像进行灰度处理,我们的基本想法可是将每个象素点的三种颜色成分的值取平均值。然而由于人眼的敏感性,这样完全取平均值的做法的效果并不好,所以在程序中我取了三个效果最好的参数:.299,.587,.114。不过在这里要向读者指明的是,在GDI+中图像存储的格式是BGR而非RGB,即其顺序为:Blue、Green、Red。所以在for循环内部一定要设置好red、green、blue等变量的值,切不可颠倒。函数执行成功后,同样返回true值。
Brightness()函数的算法如下:
public static bool Brightness(Bitmap b, int nBrightness)
if (nBrightness & -255 || nBrightness & 255)
return false;
BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width,
b.Height), ImageLockMode.ReadWrite,
PixelFormat.Format24bppRgb);
int stride = bmData.S
System.IntPtr Scan0 = bmData.Scan0;
int nVal = 0;
byte * p = (byte *)(void *)Scan0;
int nOffset = stride - b.Width*3;
int nWidth = b.Width * 3;
for(int y=0;y&b.H++y)
for(int x=0; x & nW ++x )
nVal = (int) (p[0] + nBrightness);
if (nVal & 0) nVal = 0;
if (nVal & 255) nVal = 255;
p[0] = (byte)nV
b.UnlockBits(bmData);
return true;
本函数完成的功能是对图像进行增亮处理,它比上面两个函数多了一个增亮参数-nBrightness,该参数由用户输入,范围为-255~255。在取得了增亮参数后,函数的unsafe代码部分对每个象素点的不同颜色成分进行逐个处理,即在原来值的基础上加上一个增亮参数以获得新的值。同时代码中还有一个防止成分值越界的操作,因为RGB成分值的范围为0~255,一旦超过了这个范围就要重新设置。函数最后执行成功后,同样得返回true值。
  该函数实现的程序效果如下:
  首先,我们把图像增亮的参数设置为100(其范围为-255~255),然后执行效果如下,读者也可尝试其他的参数值。
  三.小结:
  本文通过一个简单的实例向大家展现了用Visual C#以及GDI+完成数字图像处理的基本方法,通过实例,我们不难发现合理运用新技术不仅可以大大简化我们的编程工作,还可以提高编程的效率。不过我们在运用新技术的同时也得明白掌握基本的编程思想才是最主要的,不同的语言、不同的机制只是实现的具体方式不同而已,其内在的思想还是相通的。对于上面的例子,掌握了编写图像处理函数的算法,用其他的方式实现也应该是可行的。同时,在上面的基础上,读者不妨试着举一反三,编写出更多的图像处理的函数来,以充实并完善这个简单的实例。
image to byte[]
MemoryStream ms=new MemoryStream();
byte[] imagedata=null;
pictureBox1.Image.Save(ms,System.Drawing.Imaging.ImageFormat.Gif );
imagedata=ms.GetBuffer ();
byte[] to image
ms = New IO.MemoryStream(by)
img = Drawing.Image.FromStream(ms)
阅读(...) 评论()

我要回帖

更多关于 ios bitmap 矩阵 的文章

 

随机推荐