最近项目开发, 要用到线程中对图像进行缩放和二值化处理

为了省事, 图像缩放用的WICImage.ImagingFactory接口, 二值化用的是bitmap.PixelFormat := pf1bit后直接bitmap.Canvas.Draw(0, 0, wicimage)(这么做是因为bitmap在处理透明通道时会强制变为黑色, 而项目需要为白色, 所以只能draw)

运行时发现, 经常性的出现图像数据丢失, 经过排查发现数据丢失都是出现在wicimage向bitmap做数据转换时出现的

跟踪源码, 发现wicimage中的数据处理全部使用32位RGBA格式, 与外部进行图像对象交换时, 都要先吧数据存放到一个bitmap中, 再转换为其他格式

但是, 由于TBitmap不是线程安全的, 在线程中进行绘画操作要先canvas.lock才行, 而wicimage没有相关处理, 所以, 问题出现了

解决方案是, 自己吧wicimage中, 转换为中间bitmap的方法复制出来成为独立函数, 直接吧数据输出到目的bitmap, 省略draw那一步

这样就可以自己在外面随意控制bitmap的lock了

其实还有更好的办法是, 直接吧wicimage数据输出为1bit的位图, 但是我没搞定, 只要不是1bit的都可以, 唯独1bit的总是失败, 所以还是使用默认的32bit外面再使用bitmap的PixelFormat做转换了

代码如下:

function WICBitmap2Bitmap(AWICBitmap: IWICBitmap; ABMP: TBitmap): Boolean;
var
nLWicBitmap: IWICBitmapSource;
nStride: Cardinal;
nBuffer: array of Byte;
nBitmapInfo: TBitmapInfo;
nWidth, nHeight: UInt32;
begin
Result := False;
if AWICBitmap = nil then
Exit;
if ABMP = nil then
Exit; AWICBitmap.GetSize(nWidth, nHeight);
nStride := nWidth * ;
SetLength(nBuffer, nStride * nHeight); WICConvertBitmapSource(GUID_WICPixelFormat32bppBGRA, AWICBitmap, nLWicBitmap);
nLWicBitmap.CopyPixels(nil, nStride, Length(nBuffer), @nBuffer[]); FillChar(nBitmapInfo, sizeof(nBitmapInfo), );
with nBitmapInfo.bmiHeader do
begin
biSize := SizeOf(nBitmapInfo);
biWidth := nWidth;
biHeight := -nHeight;
biPlanes := ;
biBitCount := ;
end; with ABMP do
begin
PixelFormat := pf32bit;
SetSize(nWidth, nHeight);
{DC par not used (ABMP.Canvas.Handle) since Usage = DIB_RGB_COLORS}
SetDIBits(, Handle, , nHeight, @nBuffer[], nBitmapInfo, DIB_RGB_COLORS);
AlphaFormat := afDefined;
end;
Result := True;
end; function Bitmap2WICBitmap(ABMP: TBitmap; var AWICBitmap: IWicBitmap): Boolean;
var
nPixelFormat: TGUID;
nBitmapInfo: TBitmapInfo;
nBuffer: array of byte;
nWidth, nHeight: Int32;
begin
Result := False; if ABMP.AlphaFormat = afDefined then
nPixelFormat := GUID_WICPixelFormat32bppBGRA
else
nPixelFormat := GUID_WICPixelFormat32bppBGR; ABMP.PixelFormat := pf32bit; nWidth := ABMP.Width;
nHeight := ABMP.Height; SetLength(nBuffer, nWidth * * nHeight); FillChar(nBitmapInfo, sizeof(nBitmapInfo), );
with nBitmapInfo.bmiHeader do
begin
biSize := SizeOf(nBitmapInfo);
biWidth := nWidth;
biHeight := -nHeight;
biPlanes := ;
biBitCount := ;
end;
// Forces evaluation of Bitmap.Handle before Bitmap.Canvas.Handle
GetDIBits(ABMP.Canvas.Handle, ABMP.Handle, , nHeight, @nBuffer[],
nBitmapInfo, DIB_RGB_COLORS); TWICImage.ImagingFactory.CreateBitmapFromMemory(nWidth, nHeight, nPixelFormat,
nWidth * , Length(nBuffer), @nBuffer[], AWICBitmap);
end;

线程中WICImage与Bitmap数据转换的更多相关文章

  1. Android中如何将Bitmap byte裸数据转换成Bitmap图片int数据

    Android中如何将Bitmap byte裸数据转换成Bitmap图片int数据 2014-06-11 10:45:14   阅读375次 我们在JNI中处理得到的BMP图片Raw数据,我们应该如何 ...

  2. Android 实现在线程中联网

    其实我们要牢记的是,对数据流的操作都是阻塞的,在一般情况下,我们是不需要考虑这个问题的,但是在Android 实现联网的时候,我们必须考虑到这个问题.比如:从网络上下载一张图片: Java代码: pu ...

  3. 老问题:Android子线程中更新UI的3种方法

    在Android项目中经常有碰到这样的问题,在子线程中完成耗时操作之后要更新UI,下面就自己经历的一些项目总结一下更新的方法: 方法一:用Handler 1.主线程中定义Handler: Handle ...

  4. 【多线程补充】SimpleDateFormat非线程安全与线程中、线程组中异常的处理

    1.SimpleDateFormat非线程安全的问题 类SimpleDateFormat主要负责日期的转换与格式化,但在多线程环境中,使用此类容易造成数据转换及处理的不正确,因为SimpleDateF ...

  5. Android中高效的显示图片之二——在非UI线程中处理图片

    在“加载大图”文章中提到的BitmapFactory.decode*方法,如果源数据是在磁盘.网络或其它任何不是在内存中的位置,那么它都不应该在UI线程中执行.因为它的加载时间不可预测且依赖于一系列因 ...

  6. 线程中更新ui方法汇总

    一.为何写作此文   你是不是经常看到很多书籍中说:不能在子线程中操作ui,不然会报错.你是不是也遇到了如下的疑惑(见下面的代码): @Override protected void onCreate ...

  7. Android子线程中更新UI的4种方法

    方法一:用Handler 1.主线程中定义Handler: Handler mHandler = new Handler() { @Override public void handleMessage ...

  8. 在非UI线程中自制Dispatcher

    在C#中,Task.Run当然是一个很好的启动新并行任务的机制,但是因为使用这个方法时,每次新的任务都会在一个新的线程中(其实就是线程池中的线程)运行 这样会造成某些情形下现场调度的相对困难,即使我隔 ...

  9. 线程中调用python win32com

    在python的线程中,调用win32com.client.Dispatch 调用windows下基于COM组件的应用接口, 需要在调用win32com.client.Dispatch前,调用pyth ...

随机推荐

  1. cmd获取python返回值

    test.py代码如下: import urllib2 import sys try: f = urllib2.urlopen('http://www.baidu.com/',timeout = 10 ...

  2. winwebmail设置能用foxmail收发邮件

    域名解析注意 1.首先做A记录解析: 主机名处:输入 mail IP地址处:输入IP地址 2.做MX记录: 主机名处: 大都保持空输入,什么也不用输入   TTL:默认就可以了,不需要改动 优先级:一 ...

  3. commons-pool与commons-pool2连接池(Hadoop连接池)

    commons-pool和commons-pool2是用来建立对象池的框架,提供了一些将对象池化必须要实现的接口和一些默认动作.对象池化之后可以通过pool的概念去管理其生命周期,例如对象的创建,使用 ...

  4. Django安装Xadmin步骤

    在Django中安装Xadmin替换原始的admin,下面介绍两种方法安装 第一种方法:pip安装 第一步: 直接pip安装xadmin pip install xadmin pip会同时安装上面三个 ...

  5. 【Spring】浅谈spring推荐构造器注入

    一.前言 ​ Spring框架对Java开发的重要性不言而喻,其核心特性就是IOC(Inversion of Control, 控制反转)和AOP,平时使用最多的就是其中的IOC,我们通过将组件交由S ...

  6. C#常用的字符串处理方法

    1.Replace(替换字符):public string Replace(char oldChar,char newChar);在对象中寻找oldChar,如果寻找到,就用newChar将oldCh ...

  7. 【转】Gvim配置(Windows and Linux)for C++|gvim编译运行c/c++程序

    转载地址:http://blog.csdn.net/onepiecehuiyu/article/details/8934366 http://mawenhao19930620.blog.163.com ...

  8. shell编程/字库裁剪(2)——编程过程

    版权申明:本文为博主窗户(Colin Cai)原创,欢迎转帖.如要转贴,必须注明原文网址 http://www.cnblogs.com/Colin-Cai/p/7704085.html 作者:窗户 Q ...

  9. zabbix自动截图留档_python版

    1 背景     每个DB Server都有zabbix监控,除了异常情况的报警信息外,也会在日检.周检.月检等工作中用到zabbix的监控数据,对zabbix监控数据会做两种处理:1 数据分析(环比 ...

  10. Windows下使用nginx搭建反向代理服务器

    反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时 ...