热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

位图的LockBits()作为C#中的不同格式?

如何解决《位图的LockBits()作为C#中的不同格式?》经验,为你挑选了1个好方法。

我最近在一个答案中偶然发现了一个问题,该问题是关于在C#中将位图格式转换为24位RGB:更快地复制图像以更改其PixelFormat,其中选定的答案指出以下内容:

另一种方法是在没有alpha通道的情况下锁定位,然后将内存复制到新的位图

并提供以下代码作为示例(为简便起见,已简化):

public static Bitmap RemoveAlphaChannel(Bitmap bitmap) {
    Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
    Bitmap bitmapDest = new Bitmap(bitmap.Width, bitmap.Height, PixelFormat.Format24bppRgb);
    BitmapData data = bitmap.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
    BitmapData dataDest = bitmapDest.LockBits(rect, ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);
    int bitmapSize = data.Stride * data.Height;
    Buffer.MemoryCopy(dataDest.Scan0, data.Scan0, bitmapSize, bitmapSize);
    bitmap.UnlockBits(data);
    bitmapDest.UnlockBits(dataDest);
    return bitmapDest;
}

让我们使用此功能将32位ARGB图像转换为24位RGB。我有以下问题:

    如何将32位位图锁定为24位,为什么允许?

    现在,原始位图中每个像素的RGB分量如何邻接?Alpha组件去哪儿了?步幅怎么了?

    将位图的位锁定为其他格式是否会导致在后台创建位图的副本

Hans Passant.. 5

这只是GDI +提供的便利。重要的是,使用一种与您要应用的特定算法配合得很好的格式来访问像素通常更方便,更快捷。

32bppPArgb格式最好是使位图尽可能快地呈现到屏幕上,它与视频帧缓冲区格式兼容,因此不需要转换。典型渲染速度比任何其他像素格式快10倍。但是PArgb很难在代码中进行操作。R,G和B通道值已由alpha值校正,您必须再次将其除以恢复原始RGB值。要求使用Argb格式可以一举解决。

同样,24bppRgb格式很尴尬,您必须使用a byte*来访问像素通道。这要求每个像素3次内存访问,从而大大降低了代码速度。要求使用32bppArgb可以int*更快地使用,并允许您忽略步幅。

这些转换没有什么特别复杂的。但是它们不是免费的,GDI +必须完成分配临时存储并来回转换像素值的工作。我使用1000 x 1000位图和ImageLockMode.ReadWrite在pokey笔记本电脑上对其进行了分析:

32bppArgb => 32bppArgb  : 0.002 msec
32bppPArgb => 32bppArgb : 5.6 msec
32bppArgb => 24bppRgb   : 5.6 msec
32bppPArgb => 24bppRgb  : 5.6 msec

我使用memcpy()在相同的32bppArgb 1000 x 1000位图上进行复制时,在RemoveAlphaChannel()方法上测量了perf。对于所需的单个ImageLockMode.ReadOnly像素转换,我得到2.8毫秒,对于副本,我得到了2.8毫秒。GDI +提供的Graphics.DrawImage()速度约为完成速度的两倍,耗时9.3毫秒。



1> Hans Passant..:

这只是GDI +提供的便利。重要的是,使用一种与您要应用的特定算法配合得很好的格式来访问像素通常更方便,更快捷。

32bppPArgb格式最好是使位图尽可能快地呈现到屏幕上,它与视频帧缓冲区格式兼容,因此不需要转换。典型渲染速度比任何其他像素格式快10倍。但是PArgb很难在代码中进行操作。R,G和B通道值已由alpha值校正,您必须再次将其除以恢复原始RGB值。要求使用Argb格式可以一举解决。

同样,24bppRgb格式很尴尬,您必须使用a byte*来访问像素通道。这要求每个像素3次内存访问,从而大大降低了代码速度。要求使用32bppArgb可以int*更快地使用,并允许您忽略步幅。

这些转换没有什么特别复杂的。但是它们不是免费的,GDI +必须完成分配临时存储并来回转换像素值的工作。我使用1000 x 1000位图和ImageLockMode.ReadWrite在pokey笔记本电脑上对其进行了分析:

32bppArgb => 32bppArgb  : 0.002 msec
32bppPArgb => 32bppArgb : 5.6 msec
32bppArgb => 24bppRgb   : 5.6 msec
32bppPArgb => 24bppRgb  : 5.6 msec

我使用memcpy()在相同的32bppArgb 1000 x 1000位图上进行复制时,在RemoveAlphaChannel()方法上测量了perf。对于所需的单个ImageLockMode.ReadOnly像素转换,我得到2.8毫秒,对于副本,我得到了2.8毫秒。GDI +提供的Graphics.DrawImage()速度约为完成速度的两倍,耗时9.3毫秒。


推荐阅读
  • 本文整理了Java面试中常见的问题及相关概念的解析,包括HashMap中为什么重写equals还要重写hashcode、map的分类和常见情况、final关键字的用法、Synchronized和lock的区别、volatile的介绍、Syncronized锁的作用、构造函数和构造函数重载的概念、方法覆盖和方法重载的区别、反射获取和设置对象私有字段的值的方法、通过反射创建对象的方式以及内部类的详解。 ... [详细]
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • STM32 IO口模拟串口通讯
    转自:http:ziye334.blog.163.comblogstatic224306191201452833850647前阵子,调项目时需要用到低波 ... [详细]
  • 网上有很多解决android加载bitmap内存溢出的方法,搜了一圈做下整理总结。项目里需求是拍摄多图之后上传,部分手机会内存溢出。常用一种解决方法:即将载入的图片缩小,这种方式以牺牲图片的质量为代价 ... [详细]
  • BitMap的原理和实现方法
    这篇文章主要介绍“BitMap的原理和实现方法”,在日常操作中,相信很多人在BitMap的原理和实现方法问题上存在疑惑,小编查阅了各式资料,整理出简 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • 配置IPv4静态路由实现企业网内不同网段用户互访
    本文介绍了通过配置IPv4静态路由实现企业网内不同网段用户互访的方法。首先需要配置接口的链路层协议参数和IP地址,使相邻节点网络层可达。然后按照静态路由组网图的操作步骤,配置静态路由。这样任意两台主机之间都能够互通。 ... [详细]
  • 海马s5近光灯能否直接更换为H7?
    本文主要介绍了海马s5车型的近光灯是否可以直接更换为H7灯泡,并提供了完整的教程下载地址。此外,还详细讲解了DSP功能函数中的数据拷贝、数据填充和浮点数转换为定点数的相关内容。 ... [详细]
  • 本文介绍了Swing组件的用法,重点讲解了图标接口的定义和创建方法。图标接口用来将图标与各种组件相关联,可以是简单的绘画或使用磁盘上的GIF格式图像。文章详细介绍了图标接口的属性和绘制方法,并给出了一个菱形图标的实现示例。该示例可以配置图标的尺寸、颜色和填充状态。 ... [详细]
  • 本文讨论了在VMWARE5.1的虚拟服务器Windows Server 2008R2上安装oracle 10g客户端时出现的问题,并提供了解决方法。错误日志显示了异常访问违例,通过分析日志中的问题帧,找到了解决问题的线索。文章详细介绍了解决方法,帮助读者顺利安装oracle 10g客户端。 ... [详细]
  • 合并列值-合并为一列问题需求:createtabletab(Aint,Bint,Cint)inserttabselect1,2,3unionallsel ... [详细]
  • 流数据流和IO流的使用及应用
    本文介绍了流数据流和IO流的基本概念和用法,包括输入流、输出流、字节流、字符流、缓冲区等。同时还介绍了异常处理和常用的流类,如FileReader、FileWriter、FileInputStream、FileOutputStream、OutputStreamWriter、InputStreamReader、BufferedReader、BufferedWriter等。此外,还介绍了系统流和标准流的使用。 ... [详细]
  • 本文介绍了使用C++Builder实现获取USB优盘序列号的方法,包括相关的代码和说明。通过该方法,可以获取指定盘符的USB优盘序列号,并将其存放在缓冲中。该方法可以在Windows系统中有效地获取USB优盘序列号,并且适用于C++Builder开发环境。 ... [详细]
  • 要点:假如有10亿元素,全部数据读进内存,占用1000000000*4102410241024≈3.725G,爆炸!解决方法:bitmap算法,每一位都能 ... [详细]
author-avatar
chunjhyy6668787
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有