以下是针对提供的C#代码的详细注释和解释,结合Halcon库的功能和代码结构进行说明:
---
### **代码整体结构**
该代码是一个基于Halcon库的条码扫描类`GeneralBarcodeScan`,支持单台或双台相机的条码检测,并通过回调接口返回结果。主要功能包括:
1. 相机初始化与图像采集。
2. 条码检测模型配置(静区、容错等)。
3. 单/双相机图像处理与条码识别。
4. 资源管理(释放相机、图像对象等)。
---
### **关键代码注释**
#### **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条码,通过回调返回结果。
- **关键步骤**:
1. **创建检测模型**:`CreateBarCodeModel`配置静区检测。
2. **设置参数**:启用多数表决(减少误检)、允许模块尺寸变化(适应变形条码)。
3. **图像采集**:`GrabImageAsync`异步获取单张图像。
4. **条码检测**:`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` | 设置起始符/终止符的容错级别 |
---
### **代码优势与注意事项**
#### **优势**
1. **资源管理**:通过`IDisposable`接口确保相机和图像对象的正确释放。
2. **双相机支持**:可扩展至多相机协同检测,提升检测范围。
3. **条码检测优化**:通过静区和容错参数提升鲁棒性。
#### **注意事项**
1. **相机配置**:
- 需确保相机型号与`GigEVision2`协议兼容。
- 网络配置(如IP地址)需提前设置。
2. **资源泄漏风险**:
- 必须在`using`块或`Dispose()`中调用`CloseImageAcq()`。
3. **性能优化**:
- 双相机拼接可能增加处理时间,需根据场景调整。
---
### **典型使用流程**
```csharp
// 1. 初始化类并设置回调
var scanner = new GeneralBarcodeScan();
scanner.setCallback(new MyCcdCallback());
// 2. 打开相机(假设单相机)
scanner.OpenImageAcq(window, 1280, 720, 1);
// 3. 开始检测
scanner.StartScanBarcode(1);
// 4. 关闭资源
scanner.Dispose();
```
通过以上注释和解释,开发者可以清晰理解代码功能、参数含义及实现逻辑。
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 };}}
}