feat(scanQRcode): add center crop zoom and bilinear sampling for preview
新增扫码预览的中心裁切放大功能,支持自定义裁切比例,同时使用双线性插值提升画面缩放质量
This commit is contained in:
parent
807f940cfb
commit
15c502c959
@ -36,6 +36,11 @@ namespace Kill.UI.Pages
|
|||||||
public int scanResolutionWidth = 1080;
|
public int scanResolutionWidth = 1080;
|
||||||
[Tooltip("扫描处理线程数")]
|
[Tooltip("扫描处理线程数")]
|
||||||
public bool useAsyncScan = true;
|
public bool useAsyncScan = true;
|
||||||
|
|
||||||
|
[Header("中心裁切放大")]
|
||||||
|
[Tooltip("截取画面中心区域的比例(0-1),值越小放越大,推荐0.55~0.7")]
|
||||||
|
[Range(0.3f, 1.0f)]
|
||||||
|
public float centerCropRatio = 0.65f;
|
||||||
|
|
||||||
[Header("自动对焦")]
|
[Header("自动对焦")]
|
||||||
[Tooltip("启用自动对焦")]
|
[Tooltip("启用自动对焦")]
|
||||||
@ -264,42 +269,67 @@ namespace Kill.UI.Pages
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 从相机画面裁切并旋转,生成预览画面
|
/// 从相机画面裁切并旋转,生成预览画面
|
||||||
|
/// 支持中心裁切放大:只截取画面中心区域,放大到预览尺寸
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void CutAndRotateCameraFrame(int camW, int camH, int targetW, int targetH)
|
private void CutAndRotateCameraFrame(int camW, int camH, int targetW, int targetH)
|
||||||
{
|
{
|
||||||
// 相机横向 1920x1080,需要顺时针旋转90度变成 1080x1920
|
// 相机横向 1920x1080,需要顺时针旋转90度变成 1080x1920
|
||||||
// 预览框横向 1080x680
|
// 预览框横向 1080x680
|
||||||
// 从旋转后的 1080x1920 中截取中间 1080x680 区域
|
// 从旋转后的 1080x1920 中截取中间区域并放大
|
||||||
|
|
||||||
// 计算裁切区域(在原始相机画面上的坐标)
|
// 计算中心裁切区域大小(基于 centerCropRatio)
|
||||||
// 旋转后高度是 camW(1920),需要截取 targetH(680) 高度
|
int sourceCropH = Mathf.Max(1, Mathf.RoundToInt(camW * centerCropRatio));
|
||||||
// 从中间截取:起始Y = (1920 - 680) / 2 = 620
|
int sourceCropW = Mathf.Max(1, Mathf.RoundToInt(camH * centerCropRatio));
|
||||||
int cropY = (camW - targetH) / 2; // 620
|
int cropY = (camW - sourceCropH) / 2;
|
||||||
|
int cropX = (camH - sourceCropW) / 2;
|
||||||
|
|
||||||
|
// 计算缩放比例
|
||||||
|
float scaleY = (float)sourceCropH / targetH;
|
||||||
|
float scaleX = (float)sourceCropW / targetW;
|
||||||
|
|
||||||
// 获取相机像素数据
|
// 获取相机像素数据
|
||||||
Color32[] cameraPixels = webCamTexture.GetPixels32();
|
Color32[] cameraPixels = webCamTexture.GetPixels32();
|
||||||
Color32[] targetPixels = new Color32[targetW * targetH];
|
Color32[] targetPixels = new Color32[targetW * targetH];
|
||||||
|
|
||||||
// 顺时针旋转90度并裁切
|
// 顺时针旋转90度 + 中心裁切 + 缩放
|
||||||
// 原始坐标 (x, y) -> 顺时针旋转90度后 (y, camW-1-x)
|
// 目标像素 (x, y) 对应源坐标:
|
||||||
// 目标 (x, y) 对应源:
|
// srcX = cropY + (targetH-1-y) * scaleY (裁切区域内纵向缩放)
|
||||||
// srcX = cropY + y (在裁切区域内纵向移动)
|
// srcY = cropX + x * scaleX (裁切区域内横向缩放)
|
||||||
// srcY = x (横向直接对应,不翻转)
|
|
||||||
for (int y = 0; y < targetH; y++)
|
for (int y = 0; y < targetH; y++)
|
||||||
{
|
{
|
||||||
for (int x = 0; x < targetW; x++)
|
for (int x = 0; x < targetW; x++)
|
||||||
{
|
{
|
||||||
// 目标像素在预览图中的位置 (x, y)
|
float srcX = cropY + (targetH - 1 - y) * scaleY;
|
||||||
// 对应原始相机中的位置
|
float srcY = cropX + x * scaleX;
|
||||||
int srcX = cropY + (targetH - 1 - y); // 从裁切区域底部开始,向上取像素(修复上下颠倒)
|
|
||||||
int srcY = x; // 横向直接对应
|
|
||||||
|
|
||||||
if (srcX >= 0 && srcX < camW && srcY >= 0 && srcY < camH)
|
// 双线性插值采样
|
||||||
{
|
int sx = (int)srcX;
|
||||||
int srcIndex = srcY * camW + srcX;
|
int sy = (int)srcY;
|
||||||
int dstIndex = y * targetW + x;
|
float fx = srcX - sx;
|
||||||
targetPixels[dstIndex] = cameraPixels[srcIndex];
|
float fy = srcY - sy;
|
||||||
}
|
int sx1 = Mathf.Min(sx + 1, camW - 1);
|
||||||
|
int sy1 = Mathf.Min(sy + 1, camH - 1);
|
||||||
|
|
||||||
|
int idx00 = sy * camW + sx;
|
||||||
|
int idx10 = sy * camW + sx1;
|
||||||
|
int idx01 = sy1 * camW + sx;
|
||||||
|
int idx11 = sy1 * camW + sx1;
|
||||||
|
|
||||||
|
Color32 c00 = cameraPixels[idx00];
|
||||||
|
Color32 c10 = cameraPixels[idx10];
|
||||||
|
Color32 c01 = cameraPixels[idx01];
|
||||||
|
Color32 c11 = cameraPixels[idx11];
|
||||||
|
|
||||||
|
float r = (1-fx)*(1-fy)*c00.r + fx*(1-fy)*c10.r + (1-fx)*fy*c01.r + fx*fy*c11.r;
|
||||||
|
float g = (1-fx)*(1-fy)*c00.g + fx*(1-fy)*c10.g + (1-fx)*fy*c01.g + fx*fy*c11.g;
|
||||||
|
float b = (1-fx)*(1-fy)*c00.b + fx*(1-fy)*c10.b + (1-fx)*fy*c01.b + fx*fy*c11.b;
|
||||||
|
|
||||||
|
targetPixels[y * targetW + x] = new Color32(
|
||||||
|
(byte)Mathf.Clamp(r, 0, 255),
|
||||||
|
(byte)Mathf.Clamp(g, 0, 255),
|
||||||
|
(byte)Mathf.Clamp(b, 0, 255),
|
||||||
|
255
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user