zoukankan      html  css  js  c++  java
  • 线程中WICImage与Bitmap数据转换

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

    为了省事, 图像缩放用的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 * 4;
      SetLength(nBuffer, nStride * nHeight);
    
      WICConvertBitmapSource(GUID_WICPixelFormat32bppBGRA, AWICBitmap, nLWicBitmap);
      nLWicBitmap.CopyPixels(nil, nStride, Length(nBuffer), @nBuffer[0]);
    
      FillChar(nBitmapInfo, sizeof(nBitmapInfo), 0);
      with nBitmapInfo.bmiHeader do
      begin
        biSize := SizeOf(nBitmapInfo);
        biWidth := nWidth;
        biHeight := -nHeight;
        biPlanes := 1;
        biBitCount := 32;
      end;
    
      with ABMP do
      begin
        PixelFormat := pf32bit;
        SetSize(nWidth, nHeight);
        {DC par not used (ABMP.Canvas.Handle) since Usage = DIB_RGB_COLORS}
        SetDIBits(0, Handle, 0, nHeight, @nBuffer[0], 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 * 4 * nHeight);
    
      FillChar(nBitmapInfo, sizeof(nBitmapInfo), 0);
      with nBitmapInfo.bmiHeader do
      begin
        biSize := SizeOf(nBitmapInfo);
        biWidth := nWidth;
        biHeight := -nHeight;
        biPlanes := 1;
        biBitCount := 32;
      end;
      // Forces evaluation of Bitmap.Handle before Bitmap.Canvas.Handle
      GetDIBits(ABMP.Canvas.Handle,  ABMP.Handle, 0, nHeight, @nBuffer[0],
        nBitmapInfo, DIB_RGB_COLORS);
    
      TWICImage.ImagingFactory.CreateBitmapFromMemory(nWidth, nHeight, nPixelFormat,
        nWidth * 4, Length(nBuffer), @nBuffer[0], AWICBitmap);
    end;
  • 相关阅读:
    pom.xml配置文件内容记录
    如何做出一个博客网站
    PHP中cookie和session的区别
    PHP链接mysql 出现:由于目标计算机积极拒绝,无法连接
    DOM增删操作(创建删除表格)
    DOM增删操作(select动态增加和删除以及清空)
    DOM增删改操作
    DOM操作表格
    SSD性能测试
    我的配置单
  • 原文地址:https://www.cnblogs.com/lzl_17948876/p/6668764.html
Copyright © 2011-2022 走看看