以下是针对提供的C#代码的详细注释和解释,结合Halcon库的功能和代码结构进行说明:
**代码整体结构**
该代码是一个基于Halcon库的条码扫描类`GeneralBarcodeScan`,支持单台或双台相机的条码检测,并通过回调接口返回结果。主要功能包括:
-
相机初始化与图像采集。
-
条码检测模型配置(静区、容错等)。
-
单/双相机图像处理与条码识别。
-
资源管理(释放相机、图像对象等)。
**关键代码注释**
**1. 类定义与成员变量**
```csharp
public class GeneralBarcodeScan : IDisposable
{
private string mLastErrorMsg; // 存储最后的错误信息
private ICcdCallback mCallback; // 相机回调接口,用于处理扫描到的条码数据
private HTuple mHvAcqHandle; // 第一台相机的句柄
private HTuple mHvAcqHandle2; // 第二台相机的句柄
private HObject mHoImage; // 存储第一台相机捕获的图像
private HObject mHoImage2; // 存储第二台相机捕获的图像
// ... 其他窗口相关变量 ...
}
```
-
**功能**:定义类的成员变量,包括相机句柄、图像对象、错误信息和回调接口。
-
**关键点**:`HTuple`是Halcon中常用的参数传递类型,`HObject`用于存储图像数据。
**2. 构造函数与资源初始化**
```csharp
public GeneralBarcodeScan()
{
mHvAcqHandle = new HTuple(); // 初始化相机句柄
mHvAcqHandle2 = new HTuple();
HOperatorSet.GenEmptyObj(out mHoImage); // 创建空图像对象
HOperatorSet.GenEmptyObj(out mHoImage2);
// 设置系统默认图像大小为512x512
HOperatorSet.SetSystem("width", 512);
HOperatorSet.SetSystem("height", 512);
// 初始化第二个窗口的尺寸为0
mWndWidth2 = 0;
mWndHeight2 = 0;
}
```
-
**功能**:初始化类成员变量,并设置Halcon的默认图像尺寸。
-
**关键函数**:
-
`GenEmptyObj`:创建空的`HObject`对象。
-
`SetSystem`:设置Halcon系统参数(如默认图像尺寸)。
**3. 相机打开与初始化方法**
```csharp
public bool OpenImageAcq(HWindow hHalconWnd, int wndWidth, int wndHeight, int deviceQty)
{
this.mHPreviewWnd = hHalconWnd; // 设置显示窗口
this.mWndWidth = wndWidth;
this.mWndHeight = wndHeight;
// ... 省略部分代码 ...
// 获取相机设备信息
HOperatorSet.InfoFramegrabber("GigEVision2", "device", out hvDeviceInfo, out hvDeviceInfoValues);
if (hvDeviceInfoValues.Length == 0) // 检查设备是否存在
{
this.mLastErrorMsg = "获取不到相机设备";
return false;
}
// 打开第一台相机
HOperatorSet.OpenFramegrabber("GigEVision2", 0, 0, 0, 0, 0, 0, "progressive",
-1, "default", -1, "false", "default", hvDeviceInfoValues.TupleSelect(0), 0, -1, out mHvAcqHandle);
// 设置相机超时参数
HOperatorSet.SetFramegrabberParam(mHvAcqHandle, "grab_timeout", 2000);
HOperatorSet.GrabImageStart(mHvAcqHandle, -1); // 开始异步图像采集
// ... 双相机处理逻辑 ...
return true;
}
```
-
**功能**:打开相机并初始化参数,支持单/双相机配置。
-
**关键函数**:
-
`OpenFramegrabber`:通过GigE Vision协议连接相机。
-
`GrabImageStart`:开始异步图像采集(`-1`表示连续采集)。
-
**参数说明**:
-
`"GigEVision2"`:指定相机协议类型。
-
`hvDeviceInfoValues.TupleSelect(0)`:选择第一个检测到的相机设备。
**4. 相机关闭与资源释放**
```csharp
public void CloseImageAcq()
{
if (this.mHoImage != null)
{
this.mHoImage.Dispose(); // 释放图像对象
this.mHoImage = null;
}
if (this.mHvAcqHandle != null)
{
HOperatorSet.CloseFramegrabber(this.mHvAcqHandle); // 关闭相机
this.mHvAcqHandle.Dispose();
this.mHvAcqHandle = null;
}
// ... 处理第二个相机和窗口 ...
}
```
-
**功能**:释放相机句柄、图像对象和窗口资源。
-
**关键函数**:
-
`CloseFramegrabber`:关闭相机连接。
-
`Dispose`:释放Halcon对象资源。
**5. 条码扫描核心逻辑(单相机)**
```csharp
public void StartScanBarcode(int qty)
{
List<string> barcodeList = new List<string>();
HObject hoImage; // 当前捕获的图像
HTuple hvBarCodeHandle; // 条码检测模型句柄
// ... 省略部分代码 ...
// 创建条码检测模型并配置参数
HOperatorSet.CreateBarCodeModel(new HTuple("quiet_zone"), new HTuple("true"), out hvBarCodeHandle);
HOperatorSet.SetBarCodeParam(hvBarCodeHandle, "majority_voting", "true"); // 启用多数表决
HOperatorSet.SetBarCodeParam(hvBarCodeHandle, "element_size_variable", "true"); // 允许模块尺寸变化
// 捕获图像并检测条码
HOperatorSet.GrabImageAsync(out hoImage, mHvAcqHandle, -1); // 异步获取图像
HOperatorSet.FindBarCode(hoImage, out hoSymbolRegions, hvBarCodeHandle, "Code 128", out hvDecodedDataStrings);
// 处理检测结果
for (int i = 0; i < hvDecodedDataStrings.Length; i++)
{
barcodeList.Add(hvDecodedDataStrings[i]); // 存储解码后的条码数据
}
// 释放资源并触发回调
if (mCallback != null) mCallback.FoundBarcode(barcodeList); // 通知回调函数
}
```
-
**功能**:捕获图像并检测Code 128条码,通过回调返回结果。
-
**关键步骤**:
-
**创建检测模型**:`CreateBarCodeModel`配置静区检测。
-
**设置参数**:启用多数表决(减少误检)、允许模块尺寸变化(适应变形条码)。
-
**图像采集**:`GrabImageAsync`异步获取单张图像。
-
**条码检测**:`FindBarCode`返回解码结果。
-
**参数解释**:
-
`quiet_zone`:检测条码周围的空白区域,提升稳定性。
-
`majority_voting`:通过多条扫描线投票选择最终解码结果。
**6. 双相机拼接与检测**
```csharp
public void StartScanBarcodeBy2Device(bool reverse)
{
HObject hoImage, hoImage2, hoImages; // 两台相机的图像
// ... 省略部分代码 ...
// 捕获并拼接图像
HOperatorSet.GrabImageAsync(out hoImage, mHvAcqHandle, -1);
HOperatorSet.GrabImageAsync(out hoImage2, mHvAcqHandle2, -1);
if (reverse) // 根据参数决定拼接顺序
{
HOperatorSet.ConcatObj(hoImages, hoImage2, out hoImages);
HOperatorSet.ConcatObj(hoImages, hoImage, out hoImages);
}
else
{
HOperatorSet.ConcatObj(hoImages, hoImage, out hoImages);
HOperatorSet.ConcatObj(hoImages, hoImage2, out hoImages);
}
HOperatorSet.TileImages(hoImages, out hoObjectsConcat, 2, "horizontal"); // 水平拼接
// 执行检测(后续步骤与单相机相同)
}
```
-
**功能**:同时捕获双相机图像并拼接,再进行条码检测。
-
**关键函数**:
-
`ConcatObj`:合并图像对象。
-
`TileImages`:将图像拼接成单个图像(`horizontal`表示水平方向)。
-
**参数`reverse`**:控制图像拼接的顺序(是否反转双相机的顺序)。
**7. 窗口适配与显示**
```csharp
private HTuple[] GetDisplayRect(int wndWidth, int wndHeight, int imageWidth, int imageHeight)
{
// 计算图像在窗口中的显示区域,保持比例
double widthRatio = (double)imageWidth / wndWidth;
double heightRatio = (double)imageHeight / wndHeight;
HTuple row1, column1, row2, column2;
if (widthRatio >= heightRatio) // 宽度占优,以宽度比例缩放
{
row1 = -(wndHeight * widthRatio - imageHeight) / 2;
column1 = 0;
row2 = row1 + wndHeight * widthRatio;
column2 = column1 + wndWidth * widthRatio;
}
else // 高度占优,以高度比例缩放
{
row1 = 0;
column1 = -(wndWidth * heightRatio - imageWidth) / 2;
row2 = row1 + wndHeight * heightRatio;
column2 = column1 + wndWidth * heightRatio;
}
return new HTuple[] { row1, column1, row2, column2 };
}
```
-
**功能**:根据窗口尺寸计算图像显示区域,保持图像比例。
-
**实现逻辑**:
-
计算宽高比,选择占优方向进行缩放。
-
调整显示区域的坐标,确保图像居中显示。
**关键函数与参数说明**
**Halcon函数**
| 函数名 | 功能 | 参数示例 |
|--------|------|----------|
| `OpenFramegrabber` | 打开相机 | `"GigEVision2"`, 设备标识符 |
| `GrabImageAsync` | 异步抓取图像 | `out HObject`, 相机句柄 |
| `CreateBarCodeModel` | 创建条码检测模型 | `'quiet_zone'`, `'true'` |
| `FindBarCode` | 检测图像中的条码 | `'Code 128'` |
| `TileImages` | 拼接图像 | `'horizontal'` |
**参数解释**
| 参数名 | 作用 |
|--------|------|
| `quiet_zone` | 启用条码周围空白区域检测 |
| `majority_voting` | 启用多条扫描线投票机制 |
| `element_size_variable` | 允许条码模块尺寸变化(适应变形条码) |
| `start_stop_tolerance` | 设置起始符/终止符的容错级别 |
**代码优势与注意事项**
**优势**
-
**资源管理**:通过`IDisposable`接口确保相机和图像对象的正确释放。
-
**双相机支持**:可扩展至多相机协同检测,提升检测范围。
-
**条码检测优化**:通过静区和容错参数提升鲁棒性。
**注意事项**
- **相机配置**:
-
需确保相机型号与`GigEVision2`协议兼容。
-
网络配置(如IP地址)需提前设置。
- **资源泄漏风险**:
- 必须在`using`块或`Dispose()`中调用`CloseImageAcq()`。
- **性能优化**:
- 双相机拼接可能增加处理时间,需根据场景调整。
**典型使用流程**
```csharp
// 1. 初始化类并设置回调
var scanner = new GeneralBarcodeScan();
scanner.setCallback(new MyCcdCallback());
// 2. 打开相机(假设单相机)
scanner.OpenImageAcq(window, 1280, 720, 1);
// 3. 开始检测
scanner.StartScanBarcode(1);
// 4. 关闭资源
scanner.Dispose();
```
通过以上注释和解释,开发者可以清晰理解代码功能、参数含义及实现逻辑。
cs
using HalconDotNet; // 引用 Halcon 图像处理库
using Hggit.Hwodc.Common; // 引用其他库
using System; // 引用系统库
using System.Collections.Generic; // 引用集合类库
using System.Linq; // 引用 LINQ 查询库
using System.Text; // 引用字符串处理类库
using System.Threading.Tasks; // 引用异步任务处理库
namespace Hggit.Hwodc.Halcon
{
public class GeneralBarcodeScan : IDisposable
{
private string mLastErrorMsg; // 保存最后的错误信息
private ICcdCallback mCallback; // 相机回调接口,用于处理扫描到的条形码
/// <summary>
/// 相机句柄,用于相机图像捕获
/// </summary>
private HTuple mHvAcqHandle;
/// <summary>
/// 第二个相机句柄
/// </summary>
private HTuple mHvAcqHandle2;
/// <summary>
/// 捕获的图像对象
/// </summary>
private HObject mHoImage;
/// <summary>
/// 第二个捕获的图像对象
/// </summary>
private HObject mHoImage2;
/// <summary>
/// 窗口的宽度
/// </summary>
private int mWndWidth;
/// <summary>
/// 窗口的高度
/// </summary>
private int mWndHeight;
/// <summary>
/// Halcon 图像显示窗口
/// </summary>
private HWindow mHPreviewWnd;
/// <summary>
/// Halcon 图像显示窗口内部句柄
/// </summary>
HTuple mHvWindowHandle;
/// <summary>
/// 第二个窗口宽度
/// </summary>
private int mWndWidth2;
/// <summary>
/// 第二个窗口高度
/// </summary>
private int mWndHeight2;
/// <summary>
/// 第二个窗口的句柄
/// </summary>
HTuple mHvWindowHandle2;
public void Dispose()
{
// 清理资源,关闭相机及图像对象
CloseImageAcq();
}
public GeneralBarcodeScan()
{
// 初始化相机句柄和图像对象
mHvAcqHandle = new HTuple();
mHvAcqHandle2 = new HTuple();
HOperatorSet.GenEmptyObj(out mHoImage);
HOperatorSet.GenEmptyObj(out mHoImage2);
// 设置系统默认图像大小
HOperatorSet.SetSystem("width", 512);
HOperatorSet.SetSystem("height", 512);
mWndWidth2 = 0;
mWndHeight2 = 0;
}
public void setCallback(ICcdCallback callback)
{
// 设置回调接口
this.mCallback = callback;
}
/// <summary>
/// 打开相机并初始化图像采集
/// </summary>
/// <returns>返回是否成功打开相机</returns>
public bool OpenImageAcq(HWindow hHalconWnd, int wndWidth, int wndHeight, int deviceQty)
{
this.mHPreviewWnd = hHalconWnd;
this.mWndWidth = wndWidth;
this.mWndHeight = wndHeight;
// 检查操作系统是否为 Windows,设置线程安全
if (HalconAPI.isWindows)
HOperatorSet.SetSystem("use_window_thread", "true");
HTuple hvDeviceInfo;
HTuple hvDeviceInfoValues;
// 获取相机设备信息
HOperatorSet.InfoFramegrabber("GigEVision2", "device", out hvDeviceInfo, out hvDeviceInfoValues);
// 如果没有设备信息,返回错误
if (hvDeviceInfoValues.Length == 0)
{
this.mLastErrorMsg = "获取不到相机设备";
return false;
}
// 检查是否有两个相机设备
if (deviceQty == 2)
{
if (hvDeviceInfoValues.Length < 2)
{
this.mLastErrorMsg = "只检测到了一个相机设备!";
return false;
}
}
// 打开第一个相机
HOperatorSet.OpenFramegrabber("GigEVision2", 0, 0, 0, 0, 0, 0, "progressive",
-1, "default", -1, "false", "default", hvDeviceInfoValues.TupleSelect(0), 0, -1, out mHvAcqHandle);
// 设置相机参数
HOperatorSet.SetFramegrabberParam(mHvAcqHandle, "grab_timeout", 2000);
HOperatorSet.GrabImageStart(mHvAcqHandle, -1);
// 打开第二个相机(如果有)
if (deviceQty == 2)
{
HOperatorSet.OpenFramegrabber("GigEVision2", 0, 0, 0, 0, 0, 0, "progressive",
-1, "default", -1, "false", "default", hvDeviceInfoValues.TupleSelect(1), 0, -1, out mHvAcqHandle2);
HOperatorSet.SetFramegrabberParam(mHvAcqHandle2, "grab_timeout", 2000);
HOperatorSet.GrabImageStart(mHvAcqHandle2, -1);
}
// 关闭之前打开的窗口
if (HDevWindowStack.IsOpen())
{
var hvWnd = HDevWindowStack.Pop();
while (hvWnd != null)
{
HOperatorSet.CloseWindow(hvWnd);
}
}
// 打开显示窗口并设置窗口句柄
HOperatorSet.OpenWindow(0, 0, wndWidth, wndHeight, hHalconWnd, "visible", "", out this.mHvWindowHandle);
HDevWindowStack.Push(mHvWindowHandle);
return true;
}
public void CloseImageAcq()
{
// 清理相机和图像资源
if (HalconAPI.isWindows)
HOperatorSet.SetSystem("use_window_thread", "true");
if (this.mHoImage != null)
{
this.mHoImage.Dispose();
this.mHoImage = null;
}
if (this.mHvWindowHandle != null)
{
this.mHvWindowHandle.Dispose();
this.mHvWindowHandle = null;
}
if (this.mHvAcqHandle != null)
{
HOperatorSet.CloseFramegrabber(this.mHvAcqHandle);
this.mHvAcqHandle.Dispose();
this.mHvAcqHandle = null;
}
if (mHoImage2 != null)
{
this.mHoImage2.Dispose();
this.mHoImage2 = null;
}
if (this.mHvWindowHandle2 != null)
{
this.mHvWindowHandle2.Dispose();
this.mHvWindowHandle2 = null;
}
if (this.mHvAcqHandle2 != null)
{
HOperatorSet.CloseFramegrabber(this.mHvAcqHandle2);
this.mHvAcqHandle2.Dispose();
this.mHvAcqHandle2 = null;
}
}
public string GetLastErrorMsg()
{
// 获取最后的错误信息
return this.mLastErrorMsg;
}
public void GrabImage()
{
// 异步捕获图像并显示在窗口
HObject hoImage;
HTuple imageWidth;
HTuple imageHeight;
if (HalconAPI.isWindows)
HOperatorSet.SetSystem("use_window_thread", "true");
HOperatorSet.GrabImageAsync(out hoImage, mHvAcqHandle, -1);
HOperatorSet.GetImageSize(hoImage, out imageWidth, out imageHeight);
if (HDevWindowStack.IsOpen())
{
HTuple[] displayRect = GetDisplayRect(mWndWidth, mWndHeight, imageWidth, imageHeight);
HOperatorSet.SetPart(HDevWindowStack.GetActive(), displayRect[0], displayRect[1], displayRect[2], displayRect[3]);
}
if (HDevWindowStack.IsOpen())
{
HOperatorSet.DispImage(hoImage, HDevWindowStack.GetActive());
}
if (hoImage != null)
{
hoImage.Dispose();
}
if (imageWidth != null)
{
imageWidth.Dispose();
}
if (imageHeight != null)
{
imageHeight.Dispose();
}
}
public void StartScanBarcode(int qty)
{
// 执行条形码扫描
List<string> barcodeList = new List<string>();
HObject hoImage;
HObject hoObjectsConcat;
HObject hoSymbolRegions;
HTuple hvBarCodeHandle;
HTuple imageWidth;
HTuple imageHeight;
HTuple hvWindowHandle;
int wndWidth, wndHeight;
if (qty == 1)
{
// 如果是单台相机,使用第一个相机窗口和尺寸
wndWidth = this.mWndWidth;
wndHeight = this.mWndHeight;
hvWindowHandle = this.mHvWindowHandle;
}
else
{
// 如果是双台相机,使用第二个相机窗口和尺寸
wndWidth = this.mWndWidth2;
wndHeight = this.mWndHeight2;
hvWindowHandle = this.mHvWindowHandle2;
}
HTuple hvDecodedDataStrings;
// 创建空对象,用于存放图像和检测到的条形码区域
HOperatorSet.GenEmptyObj(out hoObjectsConcat);
HOperatorSet.GenEmptyObj(out hoSymbolRegions);
// 创建条形码检测模型,指定条形码检测的类型
HOperatorSet.CreateBarCodeModel("quiet_zone", "true", out hvBarCodeHandle);
// 设置条形码检测的参数
HOperatorSet.SetBarCodeParam(hvBarCodeHandle, "majority_voting", "true"); // 启用多数投票
HOperatorSet.SetBarCodeParam(hvBarCodeHandle, "element_size_variable", "true"); // 启用可变元素大小
HOperatorSet.SetBarCodeParam(hvBarCodeHandle, "start_stop_tolerance", "low"); // 设置开始/停止容差为低
// 根据相机数量,选择相应的相机进行图像捕获
if (qty == 1)
{
// 如果只有一台相机,捕获图像
HOperatorSet.GrabImageAsync(out hoImage, mHvAcqHandle, -1);
}
else
{
// 如果有两台相机,捕获两台相机的图像
HOperatorSet.GrabImageAsync(out hoImage, mHvAcqHandle, -1);
}
// 获取图像的尺寸
HOperatorSet.GetImageSize(hoImage, out imageWidth, out imageHeight);
// 根据窗口尺寸和图像尺寸,计算显示区域
if (HDevWindowStack.IsOpen())
{
HTuple[] displayRect = GetDisplayRect(wndWidth, wndHeight, imageWidth, imageHeight);
HOperatorSet.SetPart(hvWindowHandle, displayRect[0], displayRect[1], displayRect[2], displayRect[3]);
}
// 显示捕获的图像
if (HDevWindowStack.IsOpen())
{
HOperatorSet.DispImage(hoImage, hvWindowHandle);
}
// 执行条形码查找
HOperatorSet.FindBarCode(hoImage, out hoSymbolRegions, hvBarCodeHandle,
"Code 128", out hvDecodedDataStrings);
// 显示条形码区域
if (HDevWindowStack.IsOpen())
{
HOperatorSet.DispRegion(hoSymbolRegions, hvWindowHandle);
}
// 将找到的条形码数据加入列表
for (int i = 0; i < hvDecodedDataStrings.Length; i++)
{
string item = hvDecodedDataStrings[i];
barcodeList.Add(string.Copy(item));
}
// 释放资源
if (hoObjectsConcat != null)
{
hoObjectsConcat.Dispose();
}
if (hoSymbolRegions != null)
{
hoSymbolRegions.Dispose();
}
if (hvBarCodeHandle != null)
{
hvBarCodeHandle.Dispose();
}
if (hoImage != null)
{
hoImage.Dispose();
}
if (imageWidth != null)
{
imageWidth.Dispose();
}
if (imageHeight != null)
{
imageHeight.Dispose();
}
if (hvDecodedDataStrings != null)
{
hvDecodedDataStrings.Dispose();
}
// 调用回调函数,将条形码数据返回
if (mCallback != null)
{
mCallback.FoundBarcode(barcodeList);
}
}
public void StartScanBarcodeBy2Device(bool revease)
{
// 使用两台相机进行条形码扫描
List<string> barcodeList = new List<string>();
HObject hoImage;
HObject hoImage2;
HObject hoImages;
HObject hoObjectsConcat;
HObject hoSymbolRegions;
HTuple hvBarCodeHandle;
HTuple imageWidth;
HTuple imageHeight;
HTuple hvWindowHandle;
int wndWidth, wndHeight;
// 设置第一个相机的窗口尺寸
wndWidth = this.mWndWidth;
wndHeight = this.mWndHeight;
hvWindowHandle = this.mHvWindowHandle;
HTuple hvDecodedDataStrings;
// 创建空对象,用于存放图像和检测到的条形码区域
HOperatorSet.GenEmptyObj(out hoImage);
HOperatorSet.GenEmptyObj(out hoImage2);
HOperatorSet.GenEmptyObj(out hoImages);
HOperatorSet.GenEmptyObj(out hoObjectsConcat);
HOperatorSet.GenEmptyObj(out hoSymbolRegions);
// 创建条形码检测模型
HOperatorSet.CreateBarCodeModel("quiet_zone", "true", out hvBarCodeHandle);
// 设置条形码检测的参数
HOperatorSet.SetBarCodeParam(hvBarCodeHandle, "majority_voting", "true");
HOperatorSet.SetBarCodeParam(hvBarCodeHandle, "element_size_variable", "true");
HOperatorSet.SetBarCodeParam(hvBarCodeHandle, "start_stop_tolerance", "low");
// 捕获第一台相机的图像
HOperatorSet.GrabImageAsync(out hoImage, mHvAcqHandle, -1);
// 捕获第二台相机的图像
HOperatorSet.GrabImageAsync(out hoImage2, mHvAcqHandle2, -1);
// 根据 `revease` 参数的值,决定图像的拼接顺序
if (revease)
{
HOperatorSet.ConcatObj(hoImages, hoImage2, out hoImages);
HOperatorSet.ConcatObj(hoImages, hoImage, out hoImages);
}
else
{
HOperatorSet.ConcatObj(hoImages, hoImage, out hoImages);
HOperatorSet.ConcatObj(hoImages, hoImage2, out hoImages);
}
// 将两台相机的图像拼接在一起
HOperatorSet.TileImages(hoImages, out hoObjectsConcat, 2, "horizontal");
// 获取拼接后的图像尺寸
HOperatorSet.GetImageSize(hoObjectsConcat, out imageWidth, out imageHeight);
// 根据窗口尺寸和图像尺寸,计算显示区域
if (HDevWindowStack.IsOpen())
{
HTuple[] displayRect = GetDisplayRect(wndWidth, wndHeight, imageWidth, imageHeight);
HOperatorSet.SetPart(hvWindowHandle, displayRect[0], displayRect[1], displayRect[2], displayRect[3]);
}
// 显示拼接后的图像
if (HDevWindowStack.IsOpen())
{
HOperatorSet.DispImage(hoObjectsConcat, hvWindowHandle);
}
// 执行条形码查找
HOperatorSet.FindBarCode(hoObjectsConcat, out hoSymbolRegions, hvBarCodeHandle,
"Code 128", out hvDecodedDataStrings);
// 显示条形码区域
if (HDevWindowStack.IsOpen())
{
HOperatorSet.DispRegion(hoSymbolRegions, hvWindowHandle);
}
// 将找到的条形码数据加入列表
for (int i = 0; i < hvDecodedDataStrings.Length; i++)
{
string item = hvDecodedDataStrings[i];
barcodeList.Add(string.Copy(item));
}
// 释放资源
if (hoObjectsConcat != null)
{
hoObjectsConcat.Dispose();
}
if (hoImages != null)
{
hoImages.Dispose();
}
if (hoSymbolRegions != null)
{
hoSymbolRegions.Dispose();
}
if (hvBarCodeHandle != null)
{
hvBarCodeHandle.Dispose();
}
if (hoImage != null)
{
hoImage.Dispose();
}
if (hoImage2 != null)
{
hoImage2.Dispose();
}
if (imageWidth != null)
{
imageWidth.Dispose();
}
if (imageHeight != null)
{
imageHeight.Dispose();
}
if (hvDecodedDataStrings != null)
{
hvDecodedDataStrings.Dispose();
}
// 调用回调函数,将条形码数据返回
if (mCallback != null)
{
mCallback.FoundBarcode(barcodeList);
}
}
/// <summary>
/// 计算显示区域的矩形,以适应图像与窗口的大小比例
/// </summary>
/// <param name="wndWidth">窗口宽度</param>
/// <param name="wndHeight">窗口高度</param>
/// <param name="imageWidth">图像宽度</param>
/// <param
/// <summary>
/// 计算显示区域的矩形,以适应图像与窗口的大小比例
/// </summary>
/// <param name="wndWidth">窗口宽度</param>
/// <param name="wndHeight">窗口高度</param>
/// <param name="imageWidth">图像宽度</param>
/// <param name="imageHeight">图像高度</param>
/// <returns>显示区域矩形</returns>
private HTuple[] GetDisplayRect(int wndWidth, int wndHeight, int imageWidth, int imageHeight)
{
// 计算图像与窗口的宽高比例
double widthRatio = (1.0) * imageWidth / wndWidth;
double heightRatio = (1.0) * imageHeight / wndHeight;
HTuple row1, colume1, row2, colume2;
// 如果图像的宽度比高度占优,则以宽度比例为主
if (widthRatio >= heightRatio)
{
row1 = -(1.0) * (wndHeight * widthRatio - imageHeight) / 2;
colume1 = 0;
row2 = row1 + wndHeight * widthRatio;
colume2 = colume1 + wndWidth * widthRatio;
}
else
{
// 否则,以高度比例为主
row1 = 0;
colume1 = -(1.0) * (wndWidth * heightRatio - imageWidth) / 2;
row2 = row1 + wndHeight * heightRatio;
colume2 = colume1 + wndWidth * heightRatio;
}
// 返回显示区域的四个坐标点(行列)
return new HTuple[] { row1, colume1, row2, colume2 };
}
}
}