C#中如何实现Bitmap图像处理加速
发表于:2026-10-31 作者:千家信息网编辑
千家信息网最后更新 2026年10月31日,这篇文章主要讲解了"C#中如何实现Bitmap图像处理加速",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"C#中如何实现Bitmap图像处理加速"吧!B
千家信息网最后更新 2026年10月31日C#中如何实现Bitmap图像处理加速
这篇文章主要讲解了"C#中如何实现Bitmap图像处理加速",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"C#中如何实现Bitmap图像处理加速"吧!
BitmapData类
BitmapData类专门用于位图处理,与Bitmap的不同点在于,它使用指针直接修改内存,而Bitmap是使用SetPixel()方法间接修改颜色,因此其效率远远超过SetPixel()
传统代码
以灰度处理为例,为了便于演示,此处的灰度算法采用 Gray=(R+G+B) / 3
private void Gray_Tradition(){ for(int i = 0; i < bitmap.Width; i++) { for(int j = 0; j < bitmap.Height; j++) { Color color = bitmap.GetPixel(i, j); int RGB = (color.R + color.G + color.B) / 3; bitmap.SetPixel(i, j, Color.FromArgb(255, RGB, RGB, RGB)); } }}使用BitmapData的代码
private void Gray_BitmapData(){ int width = bitmap.Width, height = bitmap.Height;//图片的宽度和高度 //在内存中以读写模式锁定Bitmap BitmapData bitmapData = bitmap.LockBits( new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); //图片像素点数组的长度,由于一个像素点占了3个字节,所以要乘上3 int size = width * height * 3; //缓冲区数组 byte[] srcArray = new byte[size]; //获取第一个像素的地址 IntPtr ptr = bitmapData.Scan0; //把像素值复制到缓冲区 Marshal.Copy(ptr, srcArray, 0, size); int p; for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { //定位像素点位置 p = j * width * 3 + i * 3; //计算灰度值 byte color = (byte)((srcArray[p] + srcArray[p + 1] + srcArray[p + 2]) / 3); srcArray[p] = srcArray[p + 1] = srcArray[p + 2] = color; } } //从缓冲区复制回BitmapData Marshal.Copy(srcArray, 0, ptr, size); //从内存中解锁 bitmap.UnlockBits(bitmapData);}效率对比
代码
private void onTest(){ double t1, t2; Stopwatch watch = new Stopwatch(); watch.Start(); Gray_BitmapData(); watch.Stop(); t1 = watch.Elapsed.TotalMilliseconds; watch.Reset(); watch.Start(); Gray_Tradition(); watch.Stop(); t2 = watch.Elapsed.TotalMilliseconds; MessageBox.Show("BitmapData=" + (long)t1 + "\nTradition=" + (long)t2);}图片信息
耗时

可以看到传统方法的耗时是使用BitmapData方法的106倍,需要整整14秒,而BitmapData仅用了0.1秒
GPU加速
使用CUDA生成dll后,可以在GPU上高效处理图像,但是这种方式需要使用dll,而且异常繁琐,因此只适合对效率有极高要求时使用
生成Dll
#include "cuda_runtime.h"#include "device_launch_parameters.h" #include#include __global__ void DoInKernel(byte* o, int num){ int i = blockIdx.x * blockDim.x + threadIdx.x; if (i >= num) return; byte* ori = o + i * 3; ori[0] = ori[1] = ori[2] = (ori[0] + ori[1] + ori[2]) / 3;} extern "C" _declspec(dllexport) void Gray(byte * oriArray, int num) { int size = num * 3 * sizeof(byte); byte* dev_ori; //在GPU上分配内存 cudaMalloc((void**)&dev_ori, size); //把数组复制到显存 cudaMemcpy(dev_ori, oriArray, size, cudaMemcpyHostToDevice); //计算 DoInKernel << > > (dev_ori, num); //从显存复制到内存 cudaMemcpy(oriArray, dev_ori, size, cudaMemcpyDeviceToHost); //释放 cudaFree(dev_ori);}
实际上GPU的thread和block数量应该根据实际数组大小来动态调整,但是这里为了演示方便,直接定义1024个线程
调用Dll
[DllImport("CUDA.dll", EntryPoint = "Gray", CallingConvention = CallingConvention.Cdecl)]public static extern void Gray(IntPtr ori, int num);此时不需要定义缓冲区数组了,可以直接把数据复制到显存中使用
private void Gray_GPU(){ int width = bitmap.Width, height = bitmap.Height;//图片的宽度和高度 //在内存中以读写模式锁定Bitmap BitmapData bitmapData = bitmap.LockBits( new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); //图片像素点数组的长度,由于一个像素点占了3个字节,所以要乘上3 int size = width * height * 3; //获取第一个像素的地址 IntPtr ptr = bitmapData.Scan0; Gray(ptr, width * height); //从内存中解锁 bitmap.UnlockBits(bitmapData); pictureBox1.Refresh();}耗时
由于加载dll需要时间,因此第二次执行的耗时才是真正的GPU执行时间

仅用了34毫秒
感谢各位的阅读,以上就是"C#中如何实现Bitmap图像处理加速"的内容了,经过本文的学习后,相信大家对C#中如何实现Bitmap图像处理加速这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!
像素
处理
内存
数组
图像
图片
图像处理
C#
缓冲区
缓冲
代码
效率
方法
显存
灰度
学习
传统
内容
地址
字节
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
广东万易互联网科技有限公司惠州分公司
广州淘业互联网络科技
美国互联网保险保险科技
科技互联网项目
互联网科技公司税收优惠
工业互联网科技新基建
互联网科技社
互联网 科技创业
银优互联网科技有限公司
互联网科技缩写
融贸通互联网科技
中国互联网金融科技基金
科技与互联网哪个更好
互联网企业和科技型企业
湖南一路畅行互联网科技
广西互联网科技孵化中心
锡山区互联网智能科技产品供应
四川互联网展示科技馆设计
互联网相关科技技术
武汉亿视互联网科技有限公司
互联网和科技创新
济南和联互联网科技有限公司
成都玖崟互联网科技有限公司乐商圈怎么样
互联网企业和科技型企业
互联网和黑科技的看法
中国航天科技大学国际工业互联网
青岛科技大学互联网大赛研究生
上海钢联属于互联网科技股吗
优雇互联网科技有限公司
宁波允成互联网科技有限公司