C#加快Bitmap的访问速度
在对Bitmap图片操作的时候,有时需要用到获取或设置像素颜色方法:GetPixel 和 SetPixel,
如果直接对这两个方法进行操作的话速度很慢,这里我们可以通过把数据提取出来操作,然后操作完在复制回去可以加快访问速度
其实对Bitmap的访问还有两种方式,一种是内存法,一种是指针法
1、内存法
这里定义一个类LockBitmap,通过把Bitmap数据拷贝出来,在内存上直接操作,操作完成后在拷贝到Bitmap中
public class LockBitmap
{
Bitmap source = null;
IntPtr Iptr = IntPtr.Zero;
BitmapData bitmapData = null; public byte[] Pixels { get; set; }
public int Depth { get; private set; }
public int Width { get; private set; }
public int Height { get; private set; } public LockBitmap(Bitmap source)
{
this.source = source;
} /// <summary>
/// Lock bitmap data
/// </summary>
public void LockBits()
{
try
{
// Get width and height of bitmap
Width = source.Width;
Height = source.Height; // get total locked pixels count
int PixelCount = Width * Height; // Create rectangle to lock
Rectangle rect = new Rectangle(, , Width, Height); // get source bitmap pixel format size
Depth = System.Drawing.Bitmap.GetPixelFormatSize(source.PixelFormat); // Check if bpp (Bits Per Pixel) is 8, 24, or 32
if (Depth != && Depth != && Depth != )
{
throw new ArgumentException("Only 8, 24 and 32 bpp images are supported.");
} // Lock bitmap and return bitmap data
bitmapData = source.LockBits(rect, ImageLockMode.ReadWrite,
source.PixelFormat); // create byte array to copy pixel values
int step = Depth / ;
Pixels = new byte[PixelCount * step];
Iptr = bitmapData.Scan0; // Copy data from pointer to array
Marshal.Copy(Iptr, Pixels, , Pixels.Length);
}
catch (Exception ex)
{
throw ex;
}
} /// <summary>
/// Unlock bitmap data
/// </summary>
public void UnlockBits()
{
try
{
// Copy data from byte array to pointer
Marshal.Copy(Pixels, , Iptr, Pixels.Length); // Unlock bitmap data
source.UnlockBits(bitmapData);
}
catch (Exception ex)
{
throw ex;
}
} /// <summary>
/// Get the color of the specified pixel
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns></returns>
public Color GetPixel(int x, int y)
{
Color clr = Color.Empty; // Get color components count
int cCount = Depth / ; // Get start index of the specified pixel
int i = ((y * Width) + x) * cCount; if (i > Pixels.Length - cCount)
throw new IndexOutOfRangeException(); if (Depth == ) // For 32 bpp get Red, Green, Blue and Alpha
{
byte b = Pixels[i];
byte g = Pixels[i + ];
byte r = Pixels[i + ];
byte a = Pixels[i + ]; // a
clr = Color.FromArgb(a, r, g, b);
}
if (Depth == ) // For 24 bpp get Red, Green and Blue
{
byte b = Pixels[i];
byte g = Pixels[i + ];
byte r = Pixels[i + ];
clr = Color.FromArgb(r, g, b);
}
if (Depth == )
// For 8 bpp get color value (Red, Green and Blue values are the same)
{
byte c = Pixels[i];
clr = Color.FromArgb(c, c, c);
}
return clr;
} /// <summary>
/// Set the color of the specified pixel
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <param name="color"></param>
public void SetPixel(int x, int y, Color color)
{
// Get color components count
int cCount = Depth / ; // Get start index of the specified pixel
int i = ((y * Width) + x) * cCount; if (Depth == ) // For 32 bpp set Red, Green, Blue and Alpha
{
Pixels[i] = color.B;
Pixels[i + ] = color.G;
Pixels[i + ] = color.R;
Pixels[i + ] = color.A;
}
if (Depth == ) // For 24 bpp set Red, Green and Blue
{
Pixels[i] = color.B;
Pixels[i + ] = color.G;
Pixels[i + ] = color.R;
}
if (Depth == )
// For 8 bpp set color value (Red, Green and Blue values are the same)
{
Pixels[i] = color.B;
}
}
}
使用:先锁定Bitmap,然后通过Pixels操作颜色对象,最后释放锁,把数据更新到Bitmap中
string file = @"C:\test.jpg";
Bitmap bmp = new Bitmap(Image.FromFile(file)); LockBitmap lockbmp = new LockBitmap(bmp);
//锁定Bitmap,通过Pixel访问颜色
lockbmp.LockBits(); //获取颜色
Color color = lockbmp.GetPixel(, ); //从内存解锁Bitmap
lockbmp.UnlockBits();
2、指针法
这种方法访问速度比内存法更快,直接通过指针对内存进行操作,不需要进行拷贝,但是在C#中直接通过指针操作内存是不安全的,所以需要在代码中加入unsafe关键字,在生成选项中把允许不安全代码勾上,才能编译通过
这里定义成PointerBitmap类
public class PointBitmap
{
Bitmap source = null;
IntPtr Iptr = IntPtr.Zero;
BitmapData bitmapData = null; public int Depth { get; private set; }
public int Width { get; private set; }
public int Height { get; private set; } public PointBitmap(Bitmap source)
{
this.source = source;
} public void LockBits()
{
try
{
// Get width and height of bitmap
Width = source.Width;
Height = source.Height; // get total locked pixels count
int PixelCount = Width * Height; // Create rectangle to lock
Rectangle rect = new Rectangle(, , Width, Height); // get source bitmap pixel format size
Depth = System.Drawing.Bitmap.GetPixelFormatSize(source.PixelFormat); // Check if bpp (Bits Per Pixel) is 8, 24, or 32
if (Depth != && Depth != && Depth != )
{
throw new ArgumentException("Only 8, 24 and 32 bpp images are supported.");
} // Lock bitmap and return bitmap data
bitmapData = source.LockBits(rect, ImageLockMode.ReadWrite,
source.PixelFormat); //得到首地址
unsafe
{
Iptr = bitmapData.Scan0;
//二维图像循环 }
}
catch (Exception ex)
{
throw ex;
}
} public void UnlockBits()
{
try
{
source.UnlockBits(bitmapData);
}
catch (Exception ex)
{
throw ex;
}
} public Color GetPixel(int x, int y)
{
unsafe
{
byte* ptr = (byte*)Iptr;
ptr = ptr + bitmapData.Stride * y;
ptr += Depth * x / ;
Color c = Color.Empty;
if (Depth == )
{
int a = ptr[];
int r = ptr[];
int g = ptr[];
int b = ptr[];
c = Color.FromArgb(a, r, g, b);
}
else if (Depth == )
{
int r = ptr[];
int g = ptr[];
int b = ptr[];
c = Color.FromArgb(r, g, b);
}
else if (Depth == )
{
int r = ptr[];
c = Color.FromArgb(r, r, r);
}
return c;
}
} public void SetPixel(int x, int y, Color c)
{
unsafe
{
byte* ptr = (byte*)Iptr;
ptr = ptr + bitmapData.Stride * y;
ptr += Depth * x / ;
if (Depth == )
{
ptr[] = c.A;
ptr[] = c.R;
ptr[] = c.G;
ptr[] = c.B;
}
else if (Depth == )
{
ptr[] = c.R;
ptr[] = c.G;
ptr[] = c.B;
}
else if (Depth == )
{
ptr[] = c.R;
ptr[] = c.G;
ptr[] = c.B;
}
}
}
}
使用方法这里就不列出来了,跟上面的LockBitmap类似
以上图片由“图斗罗”提供
C#加快Bitmap的访问速度的更多相关文章
- 加快Bitmap的访问速度
引言 在对Bitmap图片操作的时候,有时需要用到获取或设置像素颜色方法:GetPixel 和 SetPixel, 如果直接对这两个方法进行操作的话速度很慢,这里我们可以通过把数据提取出来操作,然后操 ...
- .net 反射访问私有变量和私有方法 如何创建C# Closure ? C# 批量生成随机密码,必须包含数字和字母,并用加密算法加密 C#中的foreach和yield 数组为什么可以使用linq查询 C#中的 具名参数 和 可选参数 显示实现接口 异步CTP(Async CTP)为什么那样工作? C#多线程基础,适合新手了解 C#加快Bitmap的访问速度 C#实现对图片文件的压
以下为本次实践代码: using System; using System.Collections.Generic; using System.ComponentModel; using System ...
- Apache 使用gzip、deflate 压缩页面加快网站访问速度
Apache 使用gzip 压缩页面加快网站访问速度 介绍: 网页压缩来进一步提升网页的浏览速度,它完全不需要任何的成本,只不过是会让您的服务器CPU占用率稍微提升一两个百分点而已或者更少. 原理 ...
- [技术博客]使用CDN加快网站访问速度
[技术博客]使用CDN加快网站访问速度 2s : most users are willing to wait 10s : the limit for keeping the user's atten ...
- 2-12-配置squid代理服务器加快网站访问速度
本节所讲内容: squid服务器常见概念 squid服务器安装及相关配置文件 实战:配置squid正向代理服务器 实战:配置透明squid代理提升访问速度 实战:配置squid反向代理加速度内网web ...
- maven中央仓库访问速度太慢的解决办法
方法一:修改settings.xml eclipse中集成的maven的settings.xml文件,找了半年也没找到,我们放弃eclipse中的maven,下一个最新的maven,并在eclipse ...
- Nginx——使用 Nginx 提升网站访问速度【转载+整理】
原文地址 本文是写于 2008 年,文中提到 Nginx 不支持 Windows 操作系统,但是现在它已经支持了,此外还支持 FreeBSD,Solaris,MacOS X~ Nginx(" ...
- 使用 Nginx 提升网站访问速度
使用 Nginx 提升网站访问速度 http://www.ibm.com/developerworks/cn/web/wa-lo-nginx/ Nginx 简介 Nginx ("engine ...
- 使用PHP和GZip压缩网站JS/CSS文件加速网站访问速度
使用PHP和GZip压缩网站JS/CSS文件加速网站访问速度 一些泛WEB 2.0网站为了追求用户体验,可能会大量使用CSS和JS文件.这就导致在服务器带宽一定的情况下,多用户并发访问速度变慢.如何加 ...
随机推荐
- 经常使用的Hql语句
// HQL: Hibernate Query Language. // 特点: // >> 1,与SQL类似.SQL中的语法基本上都能够直接使用. // >> 2.SQL查询 ...
- mybatis 使用注解实现多参数传递
若映射器中的方法只有一个参数,则在对应的SQL语句中,可以采用#{参数名}的方式来引用此参数,以前的例子多属于此类.但这种方法却不适用于需要传递多个参数的情况,今天就来介绍如何使用注解传递多个参数 一 ...
- C++语言基础(1)-命名空间
一个中大型软件往往由多名程序员共同开发,会使用大量的变量和函数,当有两个人都同时定义了一个名字相同的全局变量或函数的时候,若是把他们的代码整合在一块编译,此时编译器就会提示变量或函数重复定义,C++为 ...
- NGINX扩展
https://github.com/cuber/ngx_http_google_filter_module
- TCP/IP笔记(一)网络基础知识
计算机与网络发展 计算机自诞生伊始,经历了一系列演变与发展.大型通用机计算机.超级计算机.小型机.个人电脑.工作站.便携式电以及现如今的智能手机终端都是这一过程的产物.它们性能逐年增强,价格却逐年下降 ...
- 中移苏研DCOS实践之路完整篇
一.实践背景 1.1现网生产系统存在的问题 在中国移动内部各省市公司,由于技术迭代.设备更新的原因,设备繁杂,有x86server .VMware虚拟机.OpenStack虚拟机以及不同厂商的物理机( ...
- 面向Internet的编程
面向Internet的编程 1994年秋天我返回工作时,这个公司的景象已经完全改变.他们决定Oak语言——跨平台的.安全的.易传输的代码——时理想的面向Internet的语言.同时他们在制作名为Web ...
- 用VS2010进行CMAKE的时候“LINK : fatal error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏”
由于要编译LTP,LTP在MINGW下又不能编译,所以忍痛安装了VS2010+CMAKE. 由于VS在本科时候虐我千百遍,所以一直心存阴影... 转入正题,当cmake的时候, 它提示 “LINK : ...
- eclipse 解决编译出现GBK或UTF8 编码错误的方法
eclipse由于开源所以支持了比较杂的编码方式,而这些一个工程导入时添加了不少的外来程序,由于不是同一工程一次编码带来了其中含有GBK和 UTF8 UTF16 ASCII等文件编译时就会出现错 ...
- C++ RTTI的应用
先看下方的代码,我们所处的context在<<< void* pX = (void*)pGiven; >>>处,只知道上面这些类的信息和pX指针,怎么判断pX指向对 ...