You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Delphi版ZXing DLL的高性能bitmap跨边界封送方案咨询

内存流方案性能评估

  • 你预估的封送开销确实存在:将TBitmap写入内存流需要做全量像素数据拷贝,每秒3次的调用频率下如果是1080P分辨率,单次拷贝大概是几毫秒级别,虽然不至于完全不可用,但属于无意义的性能浪费。
  • 额外开销还包括内存流的内存分配、释放成本,如果使用压缩流格式开销还会进一步升高。

Windows平台最优跨DLL Bitmap传递方案

直接传递原生GDI位图句柄+位图参数是性能最高的实现,全程不需要做全量像素数据拷贝,封送开销几乎为0,实现逻辑如下:

  1. 主程序侧仅需要向DLL传递三个参数:HBITMAP位图句柄、位图宽度、位图高度
  2. 如果DLL用Delphi开发,可以直接将传入的HBITMAP绑定到DLL本地的TBitmap对象,仅需一行代码LocalBmp.Handle := 传入的HBITMAP,没有任何像素拷贝操作
  3. 如果DLL用其他语言开发,直接调用Windows API GetObject读取位图头信息,再调用GetBitmapBits读取像素数据即可

优化后代码示例

主程序侧调用代码

// 提前声明DLL导出函数,用stdcall调用约定保证跨模块兼容
function ScanBitmap(hBmp: HBITMAP; bmpWidth, bmpHeight: Integer): PChar; stdcall; external 'YourZXingDll.dll';

procedure TForm1.BarCodeTimerTimer(Sender: TObject);
var
  scanRes: PChar;
begin
  // 直接传HBITMAP和尺寸参数,无全量数据拷贝
  scanRes := ScanBitmap(_bmp.Handle, _bmp.Width, _bmp.Height);
  if scanRes <> nil then
  begin
    // 处理返回的条码结果
    // 注意按约定释放返回的字符串内存
    StrDispose(scanRes);
  end;
end;

DLL侧实现代码

// DLL侧导出函数实现
function ScanBitmap(hBmp: HBITMAP; bmpWidth, bmpHeight: Integer): PChar; stdcall;
var
  dllBmp: TBitmap;
  readResult: TZXingReadResult; // 自定义的ZXing扫描结果类
begin
  Result := nil;
  dllBmp := TBitmap.Create;
  try
    // 直接绑定句柄,无像素拷贝
    dllBmp.Handle := hBmp;
    readResult := _scanManager.Scan(dllBmp);
    if readResult <> nil then
    begin
      // 按约定分配返回字符串内存,由主程序负责释放
      Result := StrAlloc(Length(readResult.Text) + 1);
      StrPCopy(Result, readResult.Text);
      FreeAndNil(readResult);
    end;
  finally
    // 仅释放TBitmap对象,不会释放传入的HBITMAP,资源所有权归属主程序
    dllBmp.Free;
  end;
end;

注意事项

  • 提前约定好HBITMAP的所有权:DLL侧不要调用DeleteObject释放传入的HBITMAP,资源完全由主程序管理
  • 如果需要兼容不同像素格式的位图,可以额外传递像素位深参数,或者DLL侧直接读取位图头信息判断即可
  • 该方案性能开销几乎可忽略,哪怕是每秒几十次的调用频率也完全可以承载,比内存流方案性能高至少一个数量级

内容的提问来源于stack exchange,提问作者Paul

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 10:33:02