·
This commit is contained in:
parent
4969d78386
commit
db9a40846d
@ -15,5 +15,11 @@ namespace XPrint.Production.Business.Entities
|
||||
/// 订单状态
|
||||
/// </summary>
|
||||
public OrderStatus Status { get; set; } = OrderStatus.None;
|
||||
|
||||
[JsonPropertyName("startTime")]
|
||||
public DateTime? StartTime { get; set; } = null;
|
||||
|
||||
[JsonPropertyName("endTime")]
|
||||
public DateTime? EndTime { get; set; } = null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,7 +11,7 @@ namespace XPrint.Production.Business.ImageLogic.Conf
|
||||
public string ProductionImageFolder { get; set; } = "";
|
||||
public int Dpi { get; set; } = 300;
|
||||
|
||||
public float ProductionHeight { get; set; } = 650;//单位:MM
|
||||
public float ProductionHeight { get; set; } = 590;//单位:MM
|
||||
public LocalConfigure() { }
|
||||
|
||||
}
|
||||
|
||||
@ -29,6 +29,19 @@ namespace XPrint.Production.Business.ImageLogic.Enitites
|
||||
public float MaskHeight { get; set; }
|
||||
|
||||
|
||||
[Key("maskProductX")]
|
||||
public float MaskProductX { get; set; }
|
||||
|
||||
[Key("maskProductY")]
|
||||
public float MaskProductY { get; set; }
|
||||
|
||||
[Key("maskProductWidth")]
|
||||
public float MaskProductWidth { get; set; }
|
||||
|
||||
[Key("maskProductHeight")]
|
||||
public float MaskProductHeight { get; set; }
|
||||
|
||||
|
||||
[Key("canvasWidth")]
|
||||
public uint CanvasWidth { get; set; }
|
||||
|
||||
|
||||
@ -57,7 +57,7 @@ namespace XPrint.Production.Business.ImageLogic
|
||||
}
|
||||
var printWidth = ImageTool.MMToPxWithDpi(413.91f, dpi); //打印正反面的宽度
|
||||
var printHeight = ImageTool.MMToPxWithDpi(productionHeight, dpi); //打印正反面的高度 原来是650
|
||||
var printRuleHeight = ImageTool.MMToPxWithDpi(650, dpi); //打印正反面的高度 原来是650
|
||||
//var printRuleHeight = ImageTool.MMToPxWithDpi(590, dpi); //打印正反面的高度 原来是650
|
||||
var printSpace = ImageTool.MMToPxWithDpi(185.087f, dpi); //打印水平间距
|
||||
|
||||
var productCanvasWidth = (printWidth + printSpace) * 3; //三连张正反面
|
||||
@ -70,10 +70,12 @@ namespace XPrint.Production.Business.ImageLogic
|
||||
// ThreadCount = Environment.ProcessorCount
|
||||
//};
|
||||
|
||||
var horOffset = ImageTool.MMToPxWithDpi(7f, dpi); //打印正反面的宽度
|
||||
var productCanvas = new MagickImage(MagickColors.Transparent, (uint)productCanvasWidth, (uint)productCanvasHeight);
|
||||
//productCanvas.SetCompression(CompressionMethod.NoCompression);
|
||||
//SetImageProperty(productCanvas);
|
||||
//int currentY = 0;
|
||||
//uint limitHandleSize = 30000;
|
||||
//for (int i = 0; i < 3; i++)
|
||||
//Parallel.For(0, info.CanvasInfos.Length, (idx) =>
|
||||
Parallel.For(0, infos.Count, (idx) =>
|
||||
@ -86,13 +88,36 @@ namespace XPrint.Production.Business.ImageLogic
|
||||
currentX = (printWidth + printSpace) * (currentIndx + printIndex);
|
||||
}
|
||||
//var canvasInfo = info.CanvasInfos[idx];
|
||||
|
||||
|
||||
var canvasInfo = info.CanvasInfos[0];//正面测试
|
||||
float scale = printRuleHeight / canvasInfo.MaskHeight;
|
||||
float destOffsetX = (canvasInfo.MaskWidth - canvasInfo.CanvasWidth) * scale * 0.5f;
|
||||
float destOffsetY = (canvasInfo.MaskHeight - canvasInfo.CanvasHeight) * scale * 0.5f;
|
||||
|
||||
using var drawCanvas = new MagickImage(MagickColors.Transparent, (uint)printWidth, (uint)printRuleHeight);
|
||||
|
||||
//float scaleX1 = canvasInfo.MaskWidth / canvasInfo.MaskProductWidth;
|
||||
//float scaleY1 = canvasInfo.MaskHeight / canvasInfo.MaskProductHeight;
|
||||
|
||||
//float scaleX = printWidth / canvasInfo.MaskProductWidth;
|
||||
float heightScale1 = printHeight / canvasInfo.MaskProductHeight;
|
||||
float heightScale2 = printHeight / canvasInfo.MaskHeight;
|
||||
|
||||
float widthScale1 = printWidth / canvasInfo.MaskProductWidth;
|
||||
float widthScale2 = printWidth / canvasInfo.MaskWidth;
|
||||
|
||||
|
||||
//float offsetY = (canvasInfo.MaskProductHeight - canvasInfo.MaskHeight) * scaleY2;
|
||||
float destOffsetX1 = (canvasInfo.MaskWidth - canvasInfo.CanvasWidth) * widthScale2 * 0.5f;
|
||||
float destOffsetY1 = (canvasInfo.MaskHeight - canvasInfo.CanvasHeight) * heightScale2 * 0.5f;
|
||||
|
||||
//float destOffsetX2 = (canvasInfo.MaskProductWidth - canvasInfo.CanvasWidth) * heightScale2 * 0.5f;
|
||||
//float destOffsetY2 = (canvasInfo.MaskProductHeight - canvasInfo.CanvasHeight) * heightScale2 * 0.5f;
|
||||
|
||||
int cropX = (int)((canvasInfo.MaskProductX - canvasInfo.MaskX) * widthScale2);
|
||||
int cropY = (int)((canvasInfo.MaskProductY - canvasInfo.MaskY) * heightScale2);// (int)((canvasInfo.MaskProductY - canvasInfo.MaskY) * heightScale2);
|
||||
|
||||
uint cropWidth = (uint)(canvasInfo.MaskProductWidth * widthScale2);
|
||||
uint cropHeight = (uint)(canvasInfo.MaskProductHeight * heightScale2);
|
||||
|
||||
using var drawCanvas = new MagickImage(MagickColors.Transparent, (uint)printWidth, (uint)printHeight);
|
||||
//SetImageProperty(drawCanvas);
|
||||
|
||||
//MagickImage? maskImage = null;
|
||||
@ -105,8 +130,36 @@ namespace XPrint.Production.Business.ImageLogic
|
||||
{
|
||||
|
||||
var imgInfo = canvasInfo.Images[j];
|
||||
|
||||
//uint resizeWidth = (uint)imgInfo.OriginWidth;
|
||||
//uint resizeHeight = (uint)imgInfo.OriginHeight;
|
||||
//if (resizeWidth > limitHandleSize || resizeHeight > limitHandleSize)
|
||||
//{
|
||||
// if (resizeWidth > resizeHeight)
|
||||
// {
|
||||
// resizeWidth = limitHandleSize;
|
||||
// resizeHeight = (uint)(imgInfo.OriginHeight * (resizeWidth / (float)imgInfo.OriginWidth));
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// resizeHeight = limitHandleSize;
|
||||
// resizeWidth = (uint)(imgInfo.OriginWidth * (resizeHeight / (float)imgInfo.OriginHeight));
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
//var settings = new MagickReadSettings
|
||||
//{
|
||||
// Width = resizeWidth, // 目标宽度
|
||||
// Height = resizeHeight, // 目标高度
|
||||
//};
|
||||
|
||||
//using var image = new MagickImage(imgInfo.DataBuffer, settings);
|
||||
using var image = new MagickImage(imgInfo.DataBuffer);
|
||||
|
||||
image.AutoOrient();//修复手机拍的图片的方向问题
|
||||
// 方法1:alpha通道阈值处理(消除半透明)
|
||||
|
||||
//SetImageProperty(image);
|
||||
image.BackgroundColor = MagickColors.Transparent;
|
||||
|
||||
@ -167,10 +220,10 @@ namespace XPrint.Production.Business.ImageLogic
|
||||
}
|
||||
|
||||
|
||||
float destX = imgInfo.X * scale;
|
||||
float destY = imgInfo.Y * scale;
|
||||
float destWidth = imgInfo.Width * scale;
|
||||
float destHeight = imgInfo.Height * scale;
|
||||
float destX = imgInfo.X * heightScale2;
|
||||
float destY = imgInfo.Y * heightScale2;
|
||||
float destWidth = imgInfo.Width * heightScale2;
|
||||
float destHeight = imgInfo.Height * heightScale2;
|
||||
|
||||
//float cropedWidth = destWidth;
|
||||
//float cropedHeight = destHeight;
|
||||
@ -185,23 +238,30 @@ namespace XPrint.Production.Business.ImageLogic
|
||||
//}
|
||||
|
||||
BatchImageCombiner.CopyRegion(image, drawCanvas, 0, 0, image.Width, image.Height,
|
||||
(int)(destOffsetX + destX), (int)(destOffsetY + destY), (uint)destWidth, (uint)destHeight);
|
||||
(int)(destOffsetX1 + destX), (int)(destOffsetY1 + destY), (uint)destWidth, (uint)destHeight);
|
||||
|
||||
}
|
||||
|
||||
|
||||
uint orginWidth = drawCanvas.Width;
|
||||
if (printHeight != printRuleHeight)
|
||||
{
|
||||
drawCanvas.Scale((uint)(drawCanvas.Width * (printHeight / printRuleHeight)), (uint)printHeight);
|
||||
}
|
||||
//计算偏移,以便居中
|
||||
uint offset = orginWidth - drawCanvas.Width;
|
||||
uint orginHeight = drawCanvas.Height;
|
||||
|
||||
drawCanvas.Crop(new MagickGeometry(cropX, cropY, cropWidth, cropHeight));
|
||||
//drawCanvas.Resize(orginWidth, orginHeight);
|
||||
int offset = 0;
|
||||
//if (printHeight != printRuleHeight)
|
||||
//{
|
||||
// drawCanvas.Scale((uint)(drawCanvas.Width * (printHeight / printRuleHeight)), (uint)printHeight);
|
||||
// //计算偏移,以便居中
|
||||
// offset = (int)orginWidth - (int)drawCanvas.Width;
|
||||
//}
|
||||
|
||||
//if (maskImage != null)
|
||||
//{
|
||||
// //maskImage.AutoOrient();
|
||||
// //if (maskWidth != 0 && maskHeight != 0)
|
||||
// //if (maskProductWidth != 0 && maskProductHeight != 0)
|
||||
// //{
|
||||
// // drawCanvas.Crop((uint)(currentStartX + maskWidth), (uint)maskHeight);
|
||||
// // drawCanvas.Crop((uint)(currentStartX + maskProductWidth), (uint)maskProductHeight);
|
||||
// //}
|
||||
|
||||
// float destWidth = maskImage.Width * scale;
|
||||
@ -212,7 +272,7 @@ namespace XPrint.Production.Business.ImageLogic
|
||||
// maskImage.Dispose();
|
||||
//}
|
||||
BatchImageCombiner.CopyRegion(drawCanvas, productCanvas, 0, 0, drawCanvas.Width, drawCanvas.Height,
|
||||
(int)(currentX + offset), 0, (uint)printWidth, (uint)printHeight);
|
||||
(int)(currentX + offset - horOffset), 0, (uint)printWidth, (uint)printHeight, true);
|
||||
//}
|
||||
});
|
||||
|
||||
|
||||
@ -3,6 +3,9 @@ using ImageMagick;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Threading.Channels;
|
||||
using System.Threading.Tasks;
|
||||
using XPrint.Production.Business.ImageLogic.Enitites;
|
||||
|
||||
namespace XPrint.Production.Business.ImageLogic
|
||||
@ -13,7 +16,7 @@ namespace XPrint.Production.Business.ImageLogic
|
||||
private readonly uint _totalWidth;
|
||||
private readonly uint _totalHeight;
|
||||
private static string _tempDirectory = null!;
|
||||
private bool _isFirstImage = true;
|
||||
//private bool _isFirstImage = true;
|
||||
private MagickImage canvas = null!;
|
||||
|
||||
|
||||
@ -43,7 +46,14 @@ namespace XPrint.Production.Business.ImageLogic
|
||||
{
|
||||
if (Directory.Exists(_tempDirectory))
|
||||
{
|
||||
Directory.Delete(_tempDirectory, true);
|
||||
try
|
||||
{
|
||||
Directory.Delete(_tempDirectory, true);
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -95,7 +105,7 @@ namespace XPrint.Production.Business.ImageLogic
|
||||
/// <param name="destHeight">目标区域高度(可缩放)</param>
|
||||
public static void CopyRegion(MagickImage sourceImage, MagickImage destImage,
|
||||
int srcX, int srcY, uint srcWidth, uint srcHeight,
|
||||
int destX, int destY, uint destWidth, uint destHeight)
|
||||
int destX, int destY, uint destWidth, uint destHeight, bool handlePngEdge = false)
|
||||
{
|
||||
|
||||
if (srcX > 0 || srcY > 0 || srcWidth < sourceImage.Width || srcHeight < sourceImage.Height)
|
||||
@ -112,6 +122,15 @@ namespace XPrint.Production.Business.ImageLogic
|
||||
// 确保目标尺寸正确应用
|
||||
sourceImage.Resize(destGeometry);
|
||||
|
||||
sourceImage.Alpha(AlphaOption.On); // 确保alpha通道开启
|
||||
//sourceImage.Threshold(new Percentage(50), Channels.Alpha); // alpha通道50%阈值
|
||||
if (handlePngEdge)
|
||||
{
|
||||
//var mask = GetImageMask(sourceImage);
|
||||
sourceImage = CompositeAsMaskedThreshold(sourceImage);
|
||||
//mask.Dispose();
|
||||
}
|
||||
|
||||
// 4. 将裁剪并缩放后的区域粘贴到目标图像
|
||||
destImage.Composite(sourceImage, destX, destY, CompositeOperator.Over);
|
||||
sourceImage.Dispose();
|
||||
@ -119,6 +138,545 @@ namespace XPrint.Production.Business.ImageLogic
|
||||
// $"拷贝到目标图像位置({destX},{destY}),尺寸为({destWidth},{destHeight})");
|
||||
}
|
||||
|
||||
|
||||
//private static MagickImage GetImageMask(MagickImage src)
|
||||
//{
|
||||
// // 1. 复制原图作为边缘检测的基础
|
||||
// var edge = src.Clone();
|
||||
|
||||
// // 2. 转换为灰度图并检测边缘(突出边缘区域)
|
||||
// edge.ColorSpace = ColorSpace.Gray;
|
||||
// edge.Edge(1); // 检测1像素宽的边缘
|
||||
// edge.Threshold(new Percentage(10)); // 强化边缘为黑白二值图(边缘为白色)
|
||||
|
||||
// //// 3. 将边缘图作为掩码,仅对边缘区域的Alpha通道应用阈值
|
||||
// //var mask = edge.Clone();
|
||||
// //// 掩码反转:让边缘区域为白色(需要处理的区域),内部为黑色(保留)
|
||||
// //mask.Negate();
|
||||
// // 对原图Alpha通道应用阈值,但仅影响掩码中的白色区域(边缘)
|
||||
// //src.Threshold(new Percentage(50), Channels.Alpha, mask);
|
||||
// return (edge as MagickImage)!;
|
||||
//}
|
||||
|
||||
public static MagickImage CompositeAsMaskedThreshold(MagickImage src)//, MagickImage mask)
|
||||
{
|
||||
// 1. 确保图像有Alpha通道
|
||||
if (!src.HasAlpha)
|
||||
src.Alpha(AlphaOption.On);
|
||||
|
||||
// 2. 提取原始Alpha通道(强制转为MagickImage具体类)
|
||||
var originalAlpha = (MagickImage)src.Clone();
|
||||
originalAlpha.Alpha(AlphaOption.Extract);
|
||||
//originalAlpha.Write(@"D:\67890.tif");
|
||||
|
||||
// 3. 生成边缘掩码(仅边缘过渡区域)
|
||||
var edgeMask = CreateEdgeMask(originalAlpha);
|
||||
|
||||
//originalAlpha.Alpha(AlphaOption.On);
|
||||
// ------------------- 核心修改:处理edgeMask为Alpha透明指示掩码 -------------------
|
||||
// 3.1 反转edgeMask:白色边缘(255)→ 0(透明指示),黑色背景(0)→ 255(不透明指示)
|
||||
//edgeMask.Negate(); // 官方Negate方法:反转颜色(255-x),一行实现
|
||||
edgeMask.Depth = 8;// 3.2 确保edgeMask是8位灰度(与Alpha通道深度匹配,避免复合异常)
|
||||
edgeMask.ColorSpace = ColorSpace.Gray;
|
||||
// 2. 关键:开启Alpha通道(透明的前提,若已有则不影响)
|
||||
edgeMask.Alpha(AlphaOption.On);
|
||||
|
||||
//// 3.2 二值化:确保只有纯白(255)和纯黑(0),避免灰色干扰
|
||||
//edgeMask.Threshold(new Percentage(95)); // 95%阈值:>242的像素视为白色(255)
|
||||
// // 3.3 反转Alpha掩码:白色(255)→0(透明),黑色(0)→255(不透明)
|
||||
|
||||
|
||||
|
||||
// 4. 对边缘区域的半透明像素进行阈值化
|
||||
var edgeProcessedAlpha = (MagickImage)originalAlpha.Clone();
|
||||
edgeProcessedAlpha.Threshold(new Percentage(50)); // 边缘半透明转透明
|
||||
|
||||
// 5. 仅在边缘掩码区域应用处理(手动控制替换范围)
|
||||
ApplyMaskedComposite(originalAlpha, edgeProcessedAlpha, edgeMask);
|
||||
|
||||
//originalAlpha.Write(@"D:\12345.tif");
|
||||
|
||||
//edgeMask.Write(@"D:\edge_mask.tif");
|
||||
// 6. 写回优化后的Alpha通道
|
||||
src.Composite(edgeProcessedAlpha, CompositeOperator.CopyAlpha, Channels.Alpha);
|
||||
|
||||
edgeProcessedAlpha.Dispose();
|
||||
edgeMask.Dispose();
|
||||
originalAlpha.Dispose();
|
||||
|
||||
return src;
|
||||
}
|
||||
|
||||
/// <summary>仅在掩码区域应用复合操作(优化版:批量像素+指针操作)</summary>
|
||||
private static void ApplyMaskedComposite(MagickImage target, MagickImage source, MagickImage mask)
|
||||
{
|
||||
uint width = target.Width;
|
||||
uint height = target.Height;
|
||||
uint totalPixels = width * height; // 总像素数(避免循环内重复计算)
|
||||
|
||||
// 关键:一次性获取目标、源、掩码的整幅图像像素数组(ushort[])
|
||||
using var targetPixels = target.GetPixels();
|
||||
using var sourcePixels = source.GetPixels();
|
||||
using var maskPixels = mask.GetPixels();
|
||||
var targetArea = targetPixels.GetArea(0, 0, width, height); // 目标像素数组(16位)
|
||||
var sourceArea = sourcePixels.GetArea(0, 0, width, height); // 源像素数组(16位)
|
||||
var maskArea = maskPixels.GetArea(0, 0, width, height); // 掩码像素数组(16位,实际存0/255)
|
||||
|
||||
// 用unsafe指针直接操作内存(跳过托管API的安全检查和方法调用开销)
|
||||
unsafe
|
||||
{
|
||||
fixed (ushort* pTarget = targetArea)
|
||||
fixed (ushort* pSource = sourceArea)
|
||||
fixed (ushort* pMask = maskArea)
|
||||
{
|
||||
ushort* targetPtr = pTarget;
|
||||
ushort* sourcePtr = pSource;
|
||||
ushort* maskPtr = pMask;
|
||||
|
||||
// 单循环遍历所有像素(替代嵌套x/y循环,减少计算量)
|
||||
for (int i = 0; i < totalPixels; i++)
|
||||
{
|
||||
// 掩码为白色(255)的区域才替换(掩码是8位转16位,255保持不变)
|
||||
if (*maskPtr == 255)
|
||||
{
|
||||
*targetPtr = *sourcePtr; // 直接复制源像素到目标
|
||||
}
|
||||
|
||||
// 指针自增(按内存顺序连续访问,最大化CPU缓存命中率)
|
||||
targetPtr++;
|
||||
sourcePtr++;
|
||||
maskPtr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 将修改后的像素数组写回目标图像
|
||||
targetPixels.SetArea(0, 0, width, height, targetArea!);
|
||||
}
|
||||
|
||||
/// <summary>生成边缘掩码:标记不透明→透明的过渡区域(修正版)</summary>
|
||||
private static MagickImage CreateEdgeMask(MagickImage alphaChannel)
|
||||
{
|
||||
// 转换为8位灰度图(确保边缘检测精度)
|
||||
using var alpha8 = ConvertTo8Bit(alphaChannel);
|
||||
|
||||
// 二值化:区分不透明(>5% Alpha)和透明区域(≤5%)
|
||||
// 调整阈值:若边缘半透明较浅,可降低至3%(更敏感)
|
||||
using var binaryAlpha = (MagickImage)alpha8.Clone();
|
||||
binaryAlpha.Threshold(new Percentage(5));
|
||||
|
||||
// 保存二值化结果,验证是否有白色区域(不透明区域)
|
||||
//binaryAlpha.Write(@"D:\binary_alpha.png");
|
||||
|
||||
//// 手动膨胀和腐蚀(生成边缘过渡带)
|
||||
//// 膨胀/腐蚀半径1像素,确保边缘宽度合适
|
||||
//using var dilated = ManualDilate(binaryAlpha);
|
||||
//dilated.Write(@"D:\dilated.png"); // 保存膨胀结果
|
||||
//using var eroded = ManualErode(binaryAlpha);
|
||||
//eroded.Write(@"D:\eroded.png"); // 保存腐蚀结果
|
||||
|
||||
// 核心修正:用像素级减法计算边缘(膨胀 - 腐蚀 = 边缘)
|
||||
|
||||
using var dilated = MorphologyDilate((binaryAlpha.Clone() as MagickImage)!);
|
||||
|
||||
//dilated.Write(@"D:\dilated.png"); // 保存膨胀结果
|
||||
|
||||
using var eroded = MorphologyErode((binaryAlpha.Clone() as MagickImage)!);
|
||||
//eroded.Write(@"D:\eroded.png"); // 保存腐蚀结果
|
||||
|
||||
var edgeMask = (MagickImage)dilated.Clone();
|
||||
SubtractImages(edgeMask, eroded); // 替代自定义的SubtractImages(edgeMask, eroded)
|
||||
|
||||
|
||||
//edgeMask.Write(@"D:\edge_mask.png");
|
||||
// 增强边缘掩码:确保边缘为纯白(255),非边缘纯黑(0)
|
||||
edgeMask.Threshold(new Percentage(50)); // 阈值50%过滤噪点
|
||||
return edgeMask;
|
||||
}
|
||||
|
||||
/// <summary>旧版本兼容:用IMorphologySettings实现腐蚀(Morphology方法需传设置对象)</summary>
|
||||
private static MagickImage MorphologyErode(MagickImage input)
|
||||
{
|
||||
var eroded = (MagickImage)input.Clone();
|
||||
|
||||
// 1. 手动创建3x3矩形内核(适配无预定义内核的旧版本)
|
||||
// 3x3全1矩阵:代表邻域内所有像素参与计算(与手动3x3邻域逻辑一致)
|
||||
//double[][] kernelMatrix =
|
||||
//[
|
||||
// [1, 1, 1],
|
||||
// [1, 1, 1],
|
||||
// [1, 1, 1]
|
||||
//];
|
||||
//Kernel rectangleKernel = Kernel.Rectangle;// new Kernel(kernelMatrix, normalize: true); // normalize=true确保计算正确
|
||||
|
||||
// 2. 构造IMorphologySettings实例(用MorphologySettings实现类)
|
||||
IMorphologySettings morphologySettings = new MorphologySettings
|
||||
{
|
||||
Method = MorphologyMethod.Erode, // 操作类型:腐蚀
|
||||
Kernel = Kernel.Rectangle, // 核心:3x3矩形内核
|
||||
Iterations = 1 // 迭代1次(腐蚀1像素)
|
||||
};
|
||||
|
||||
// 3. 调用Morphology方法(传入设置对象)
|
||||
eroded.Morphology(morphologySettings);
|
||||
|
||||
// 4. 确保输出格式正确(避免效果异常)
|
||||
eroded.ColorSpace = ColorSpace.Gray; // 灰度单通道
|
||||
eroded.Depth = 8; // 8位深度(与binaryAlpha匹配)
|
||||
|
||||
return eroded;
|
||||
}
|
||||
|
||||
/// <summary>配套:用IMorphologySettings实现膨胀</summary>
|
||||
private static MagickImage MorphologyDilate(MagickImage input)
|
||||
{
|
||||
var dilated = (MagickImage)input.Clone();
|
||||
|
||||
// 1. 同样创建3x3矩形内核
|
||||
//double[][] kernelMatrix =
|
||||
// [
|
||||
// [1, 1, 1],
|
||||
// [1, 1, 1],
|
||||
// [1, 1, 1]
|
||||
// ];
|
||||
//Kernel rectangleKernel = Kernel.Rectangle;// new Kernel(kernelMatrix, normalize: true);
|
||||
|
||||
// 2. 构造设置对象(仅Method改为Dilate)
|
||||
IMorphologySettings morphologySettings = new MorphologySettings
|
||||
{
|
||||
Method = MorphologyMethod.Dilate, // 操作类型:膨胀
|
||||
Kernel = Kernel.Rectangle,
|
||||
Iterations = 1
|
||||
};
|
||||
|
||||
// 3. 调用Morphology
|
||||
dilated.Morphology(morphologySettings);
|
||||
|
||||
// 4. 格式校准
|
||||
dilated.ColorSpace = ColorSpace.Gray;
|
||||
dilated.Depth = 8;
|
||||
|
||||
return dilated;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>手动实现图像减法(a = a - b,确保边缘掩码正确)</summary>
|
||||
private static void SubtractImages(MagickImage a, MagickImage b)
|
||||
{
|
||||
int width = (int)a.Width;
|
||||
int height = (int)a.Height;
|
||||
using var aPixels = a.GetPixels();
|
||||
using var bPixels = b.GetPixels();
|
||||
var aArea = aPixels.GetArea(0, 0, (uint)width, (uint)height);
|
||||
var bArea = bPixels.GetArea(0, 0, (uint)width, (uint)height);
|
||||
|
||||
unsafe
|
||||
{
|
||||
fixed (ushort* pA = aArea, pB = bArea)
|
||||
{
|
||||
ushort* aPtr = pA;
|
||||
ushort* bPtr = pB;
|
||||
for (int i = 0; i < width * height; i++)
|
||||
{
|
||||
// 减法后取非负结果(确保边缘为正值)
|
||||
*aPtr = (ushort)Math.Max(*aPtr - *bPtr, 0);
|
||||
aPtr++;
|
||||
bPtr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
aPixels.SetArea(0, 0, (uint)width, (uint)height, aArea!);
|
||||
}
|
||||
|
||||
/// <summary>将Alpha通道转为8位灰度(解决16位类型问题)</summary>
|
||||
private static MagickImage ConvertTo8Bit(MagickImage input)
|
||||
{
|
||||
var output = (MagickImage)input.Clone();
|
||||
output.ColorSpace = ColorSpace.Gray; // 确保灰度单通道
|
||||
output.Depth = 8; // 强制8位深度
|
||||
//output.Write(@"D:\alpha8_official.png");
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
//// 反射获取内部像素数组(复用之前的实现)
|
||||
//private static ushort[]? GetInternalPixelArray(IPixelCollection<ushort> pixels)
|
||||
//{
|
||||
// try
|
||||
// {
|
||||
// var field = pixels.GetType().GetField("_pixels", BindingFlags.NonPublic | BindingFlags.Instance)
|
||||
// ?? pixels.GetType().GetField("data", BindingFlags.NonPublic | BindingFlags.Instance)
|
||||
// ?? pixels.GetType().GetField("m_pixels", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
|
||||
// return field?.GetValue(pixels) as ushort[];
|
||||
// }
|
||||
// catch
|
||||
// {
|
||||
// return null;
|
||||
// }
|
||||
//}
|
||||
|
||||
//// 1. 批量读取像素到缓冲区(unsafe指针版,零API调用)
|
||||
//private static unsafe void ReadPixelsToBuffer(IPixelCollection<ushort> inputPixels, ushort[] inputBuffer, int width, int height)
|
||||
//{
|
||||
// // 反射获取内部像素数组(核心:绕过GetPixel)
|
||||
// ushort[] internalPixels = GetInternalPixelArray(inputPixels)!;
|
||||
// if (internalPixels == null)
|
||||
// {
|
||||
// FallbackReadPixels(inputPixels, inputBuffer, width, height); // 降级方案
|
||||
// return;
|
||||
// }
|
||||
|
||||
// // 固定内部数组和输入缓冲区,获取指针
|
||||
// fixed (ushort* pInternal = internalPixels, pBuffer = inputBuffer)
|
||||
// {
|
||||
// ushort* srcPtr = pInternal; // 源:内部像素数组指针
|
||||
// ushort* destPtr = pBuffer; // 目标:输入缓冲区指针
|
||||
|
||||
// // 按行复制(利用内存连续性,最大化缓存效率)
|
||||
// int rowSize = width * sizeof(ushort); // 一行的字节数
|
||||
// for (int y = 0; y < height; y++)
|
||||
// {
|
||||
// // 计算当前行的起始指针(直接地址偏移,无乘法运算)
|
||||
// ushort* srcRow = srcPtr + y * width;
|
||||
// ushort* destRow = destPtr + y * width;
|
||||
|
||||
// // 批量复制一行数据(比逐像素快3-5倍)
|
||||
// Buffer.MemoryCopy(
|
||||
// srcRow, // 源地址
|
||||
// destRow, // 目标地址
|
||||
// rowSize, // 目标剩余字节数
|
||||
// rowSize // 复制字节数
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
//// 4. 批量写入输出缓冲区(unsafe指针版,零API调用)
|
||||
//private static unsafe void WritePixelsFromBuffer(IPixelCollection<ushort> outputPixels, ushort[] outputBuffer, int width, int height)
|
||||
//{
|
||||
// // 反射获取内部像素数组
|
||||
// ushort[] internalPixels = GetInternalPixelArray(outputPixels)!;
|
||||
// if (internalPixels == null)
|
||||
// {
|
||||
// FallbackWritePixels(outputPixels, outputBuffer, width, height); // 降级方案
|
||||
// return;
|
||||
// }
|
||||
|
||||
// // 固定内部数组和输出缓冲区,获取指针
|
||||
// fixed (ushort* pInternal = internalPixels, pBuffer = outputBuffer)
|
||||
// {
|
||||
// ushort* destPtr = pInternal; // 目标:内部像素数组指针
|
||||
// ushort* srcPtr = pBuffer; // 源:输出缓冲区指针
|
||||
|
||||
// // 按行复制
|
||||
// int rowSize = width * sizeof(ushort);
|
||||
// for (int y = 0; y < height; y++)
|
||||
// {
|
||||
// ushort* srcRow = srcPtr + y * width;
|
||||
// ushort* destRow = destPtr + y * width;
|
||||
|
||||
// // 批量复制一行数据
|
||||
// Buffer.MemoryCopy(srcRow, destRow, rowSize, rowSize);
|
||||
// }
|
||||
// }
|
||||
|
||||
// // 同步数据到图像(部分版本需要)
|
||||
// SyncPixelCollection(outputPixels);
|
||||
//}
|
||||
|
||||
//// 同步数据(复用之前的实现)
|
||||
//private static void SyncPixelCollection(IPixelCollection<ushort> pixels)
|
||||
//{
|
||||
// try
|
||||
// {
|
||||
// pixels.GetType().GetMethod("Sync", BindingFlags.NonPublic | BindingFlags.Instance)?.Invoke(pixels, null);
|
||||
// }
|
||||
// catch { }
|
||||
//}
|
||||
|
||||
//// 降级方案(原优化版嵌套循环)
|
||||
//private static void FallbackReadPixels(IPixelCollection<ushort> inputPixels, ushort[] inputBuffer, int width, int height)
|
||||
//{
|
||||
// for (int y = 0; y < height; y++)
|
||||
// {
|
||||
// int rowStartIndex = y * width;
|
||||
// IPixel<ushort>? pixel = null;
|
||||
// for (int x = 0; x < width; x++)
|
||||
// {
|
||||
// pixel = inputPixels.GetPixel(x, y);
|
||||
// inputBuffer[rowStartIndex + x] = pixel[0];
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
//private static void FallbackWritePixels(IPixelCollection<ushort> outputPixels, ushort[] outputBuffer, int width, int height)
|
||||
//{
|
||||
// for (int y = 0; y < height; y++)
|
||||
// {
|
||||
// int rowStartIndex = y * width;
|
||||
// IPixel<ushort>? pixel = null;
|
||||
// for (int x = 0; x < width; x++)
|
||||
// {
|
||||
// pixel = outputPixels.GetPixel(x, y);
|
||||
// pixel[0] = outputBuffer[rowStartIndex + x];
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
//// 自定义非泛型unsafe委托(处理byte*指针)
|
||||
//private unsafe delegate byte NeighborhoodProcessor(byte* neighbors);
|
||||
|
||||
///// <summary>高性能邻域处理(带数据验证)</summary>
|
||||
//private unsafe static MagickImage ProcessNeighborhood(MagickImage input, NeighborhoodProcessor processFunc)
|
||||
//{
|
||||
// var output = (MagickImage)input.Clone();
|
||||
|
||||
// int width = (int)input.Width;
|
||||
// int height = (int)input.Height;
|
||||
// int pixelCount = width * height;
|
||||
|
||||
// // 1. 明确指定泛型<ushort>,避免类型不匹配
|
||||
// using var inputPixels = input.GetPixelsUnsafe();
|
||||
// using var outputPixels = output.GetPixelsUnsafe();
|
||||
// //// 预分配输入/输出缓冲区
|
||||
// //ushort[] inputBuffer = new ushort[pixelCount];
|
||||
// ushort[] outputBuffer = new ushort[pixelCount];
|
||||
|
||||
// //// 1. 关键:用 GetPixelsUnsafe<ushort>() 获取非托管像素集合(指定泛型ushort)
|
||||
// //// 用 using 包裹,确保非托管内存自动释放
|
||||
// //using var inputPixelCollection = input.GetPixelsUnsafe();
|
||||
// //// 2. 调用 GetArea() 批量读取像素数据为 ushort[](无需提前 new 数组)
|
||||
// var inputBuffer = inputPixels.GetArea(0, 0, input.Width, input.Height)!;
|
||||
// // 6. 验证inputBuffer并写入
|
||||
// //ValidateBuffer(inputBuffer, "inputBuffer", pixelCount); // 验证处理后有非0值
|
||||
|
||||
|
||||
// // 3. 预计算3x3邻域偏移量(确保width是int)
|
||||
// int[] offsets = new int[9];
|
||||
// int offsetIndex = 0;
|
||||
// for (int dy = -1; dy <= 1; dy++)
|
||||
// {
|
||||
// for (int dx = -1; dx <= 1; dx++)
|
||||
// {
|
||||
// offsets[offsetIndex++] = dy * width + dx;
|
||||
// }
|
||||
// }
|
||||
|
||||
// // 4. 栈上分配邻域内存
|
||||
// byte* neighborsPtr = stackalloc byte[9];
|
||||
|
||||
// // 5. 指针操作与数据验证
|
||||
// fixed (ushort* pInput = inputBuffer, pOutput = outputBuffer)
|
||||
// {
|
||||
// ushort* inputPtr = pInput;
|
||||
// ushort* outputPtr = pOutput;
|
||||
|
||||
// for (int i = 0; i < pixelCount; i++)
|
||||
// {
|
||||
// int x = i % width;
|
||||
// int y = i / width;
|
||||
|
||||
// // 填充邻域并验证
|
||||
// FillNeighbors(neighborsPtr, inputPtr, i, offsets, x, y, width, height);
|
||||
|
||||
// // 处理并验证结果
|
||||
// byte processResult = processFunc(neighborsPtr);
|
||||
// //if (i < 10) // 打印前10个结果
|
||||
// // Console.WriteLine($"i={i}, processResult={processResult}");
|
||||
// *outputPtr++ = (ushort)processResult;
|
||||
// }
|
||||
// }
|
||||
|
||||
// outputPixels.SetArea(0, 0, (uint)width, (uint)height, outputBuffer);
|
||||
// // 6. 验证outputBuffer并写入
|
||||
// //ValidateBuffer(outputBuffer, "outputBuffer", pixelCount); // 验证处理后有非0值
|
||||
|
||||
// output.Write(@"D:\777888999.tif");
|
||||
|
||||
// return output;
|
||||
//}
|
||||
|
||||
//// 辅助:验证缓冲区是否非全0
|
||||
//private static void ValidateBuffer(ushort[] buffer, string bufferName, int pixelCount)
|
||||
//{
|
||||
// for (int i = 0; i < pixelCount; i++)
|
||||
// {
|
||||
// if (buffer[i] != 0)
|
||||
// {
|
||||
// Console.WriteLine($"{bufferName} 数据正常(第{i}个值:{buffer[i]})");
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
// throw new InvalidDataException($"{bufferName} 全为0!请检查上游数据传递");
|
||||
//}
|
||||
|
||||
//// 辅助:填充邻域并打印调试信息
|
||||
//private static unsafe void FillNeighbors(byte* neighborsPtr, ushort* inputPtr, int i, int[] offsets, int x, int y, int width, int height)
|
||||
//{
|
||||
// for (int k = 0; k < 9; k++)
|
||||
// {
|
||||
// int neighborIndex = i + offsets[k];
|
||||
// int nx = x + (offsets[k] % width);
|
||||
// int ny = y + (offsets[k] / width);
|
||||
// bool isInBounds = nx >= 0 && nx < width && ny >= 0 && ny < height;
|
||||
|
||||
// if (isInBounds)
|
||||
// {
|
||||
// neighborsPtr[k] = (byte)inputPtr[neighborIndex];
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// neighborsPtr[k] = 0;
|
||||
// }
|
||||
|
||||
// //// 打印前10个像素的邻域数据
|
||||
// //if (i < 10)
|
||||
// // Console.WriteLine($"i={i}, k={k}: neighborIndex={neighborIndex}, nx={nx}, ny={ny}, val={neighborsPtr[k]}");
|
||||
// }
|
||||
//}
|
||||
|
||||
//// 处理函数(复用)
|
||||
//private unsafe static byte GetMaxNeighbor(byte* neighbors)
|
||||
//{
|
||||
// byte max = 0;
|
||||
// for (int i = 0; i < 9; i++)
|
||||
// if (neighbors[i] > max) max = neighbors[i];
|
||||
// return max;
|
||||
//}
|
||||
|
||||
//private unsafe static byte GetMinNeighbor(byte* neighbors)
|
||||
//{
|
||||
// byte min = 255;
|
||||
// for (int i = 0; i < 9; i++)
|
||||
// if (neighbors[i] < min) min = neighbors[i];
|
||||
// return min;
|
||||
//}
|
||||
|
||||
//// 调用方法
|
||||
//private unsafe static MagickImage ManualDilate(MagickImage input) => ProcessNeighborhood(input, GetMaxNeighbor);
|
||||
//private unsafe static MagickImage ManualErode(MagickImage input) => ProcessNeighborhood(input, GetMinNeighbor);
|
||||
|
||||
|
||||
//// 取数组最大值
|
||||
//private static byte Max(byte[] values)
|
||||
//{
|
||||
// byte max = 0;
|
||||
// foreach (var v in values)
|
||||
// if (v > max) max = v;
|
||||
// return max;
|
||||
//}
|
||||
|
||||
//// 取数组最小值
|
||||
//private static byte Min(byte[] values)
|
||||
//{
|
||||
// byte min = 255;
|
||||
// foreach (var v in values)
|
||||
// if (v < min) min = v;
|
||||
// return min;
|
||||
//}
|
||||
|
||||
///// <summary>
|
||||
///// 基于中心点旋转图像角度,保持原始尺寸
|
||||
///// </summary>
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@ -84,6 +84,12 @@ namespace XPrint.Production.Controls
|
||||
}
|
||||
}
|
||||
|
||||
public void ResetQueueStatus()
|
||||
{
|
||||
Btn_JoinQueue.Text = "加入生产队列";
|
||||
Btn_JoinQueue.Type = AntdUI.TTypeMini.Primary;
|
||||
}
|
||||
|
||||
private void OrderItem_Load(object sender, EventArgs e)
|
||||
{
|
||||
_ = InitControlsInfo();
|
||||
@ -145,15 +151,22 @@ namespace XPrint.Production.Controls
|
||||
|
||||
public async Task RemoveSelf()
|
||||
{
|
||||
ProductionQueueHandler.RemoveProductioningData(this);
|
||||
ProductionQueueHandler.RemoveOrderItemData(this);
|
||||
await ProductionQueueHandler.OrderInfoApi.ProductionBatchDelete([SyncInfo.Id.ToString()]);
|
||||
await ProductionQueueHandler.RemoveItemOssFiles(SyncInfo);//移除OSS上的文件
|
||||
await Invoke(async () =>
|
||||
try
|
||||
{
|
||||
this.Dispose();
|
||||
await ProductionQueueHandler.ReloadItems();
|
||||
});
|
||||
ProductionQueueHandler.RemoveProductioningData(this);
|
||||
ProductionQueueHandler.RemoveOrderItemData(this);
|
||||
await ProductionQueueHandler.OrderInfoApi.ProductionBatchDelete([SyncInfo.Id.ToString()]);
|
||||
await ProductionQueueHandler.RemoveItemOssFiles(SyncInfo);//移除OSS上的文件
|
||||
await Invoke(async () =>
|
||||
{
|
||||
this.Dispose();
|
||||
await ProductionQueueHandler.ReloadItems();
|
||||
});
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
AntdUI.Message.error(ParentForm!, "移除异常:" + ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private void PicBox_SceneImage_Click(object sender, EventArgs e)
|
||||
|
||||
30
XPrint.Production/MainForm.Designer.cs
generated
30
XPrint.Production/MainForm.Designer.cs
generated
@ -44,6 +44,8 @@
|
||||
Input_ProductionHeight = new AntdUI.InputNumber();
|
||||
Lbl_MM = new Label();
|
||||
Btn_Refresh = new AntdUI.Button();
|
||||
DatePickerRange = new AntdUI.DatePickerRange();
|
||||
Lbl_Date = new Label();
|
||||
((System.ComponentModel.ISupportInitialize)PicBox_QRCode).BeginInit();
|
||||
SuspendLayout();
|
||||
//
|
||||
@ -199,8 +201,8 @@
|
||||
Input_ProductionHeight.Radius = 0;
|
||||
Input_ProductionHeight.Size = new Size(191, 41);
|
||||
Input_ProductionHeight.TabIndex = 16;
|
||||
Input_ProductionHeight.Text = "650";
|
||||
Input_ProductionHeight.Value = new decimal(new int[] { 650, 0, 0, 0 });
|
||||
Input_ProductionHeight.Text = "590";
|
||||
Input_ProductionHeight.Value = new decimal(new int[] { 590, 0, 0, 0 });
|
||||
Input_ProductionHeight.ValueChanged += Input_ProductionHeight_ValueChanged;
|
||||
//
|
||||
// Lbl_MM
|
||||
@ -224,12 +226,33 @@
|
||||
Btn_Refresh.Type = AntdUI.TTypeMini.Primary;
|
||||
Btn_Refresh.Click += Btn_Refresh_Click;
|
||||
//
|
||||
// DatePickerRange
|
||||
//
|
||||
DatePickerRange.Anchor = AnchorStyles.Top | AnchorStyles.Right;
|
||||
DatePickerRange.Location = new Point(478, 41);
|
||||
DatePickerRange.Name = "DatePickerRange";
|
||||
DatePickerRange.Size = new Size(343, 56);
|
||||
DatePickerRange.TabIndex = 20;
|
||||
//
|
||||
// Lbl_Date
|
||||
//
|
||||
Lbl_Date.Anchor = AnchorStyles.Top | AnchorStyles.Right;
|
||||
Lbl_Date.AutoSize = true;
|
||||
Lbl_Date.ForeColor = SystemColors.ControlLightLight;
|
||||
Lbl_Date.Location = new Point(354, 57);
|
||||
Lbl_Date.Name = "Lbl_Date";
|
||||
Lbl_Date.Size = new Size(118, 24);
|
||||
Lbl_Date.TabIndex = 21;
|
||||
Lbl_Date.Text = "选择列表日期";
|
||||
//
|
||||
// MainForm
|
||||
//
|
||||
AutoScaleDimensions = new SizeF(11F, 24F);
|
||||
AutoScaleMode = AutoScaleMode.Font;
|
||||
BackColor = Color.FromArgb(39, 41, 47);
|
||||
ClientSize = new Size(1898, 1024);
|
||||
Controls.Add(Lbl_Date);
|
||||
Controls.Add(DatePickerRange);
|
||||
Controls.Add(Btn_Refresh);
|
||||
Controls.Add(Lbl_MM);
|
||||
Controls.Add(Input_ProductionHeight);
|
||||
@ -246,6 +269,7 @@
|
||||
Controls.Add(Lbl_Production_Dict);
|
||||
Controls.Add(PicBox_QRCode);
|
||||
Controls.Add(Btn_Configure);
|
||||
MinimumSize = new Size(1920, 1080);
|
||||
Name = "MainForm";
|
||||
Text = "生产端";
|
||||
FormClosed += MainForm_FormClosed;
|
||||
@ -272,5 +296,7 @@
|
||||
private AntdUI.InputNumber Input_ProductionHeight;
|
||||
private Label Lbl_MM;
|
||||
private AntdUI.Button Btn_Refresh;
|
||||
private AntdUI.DatePickerRange DatePickerRange;
|
||||
private Label Lbl_Date;
|
||||
}
|
||||
}
|
||||
|
||||
@ -54,7 +54,7 @@ namespace XPrint.Production
|
||||
|
||||
InitQRCode();
|
||||
ProductionQueueHandler.CheckProdcutionDirectoryExist(this);
|
||||
listTimer.Interval = 5000;
|
||||
listTimer.Interval = 10000;
|
||||
listTimer.Elapsed += ListTimer_Elapsed;
|
||||
listTimer.Start();
|
||||
|
||||
@ -128,6 +128,10 @@ namespace XPrint.Production
|
||||
MessageBox.Show("配置文件错误,请重新配置存储路径等相关参数");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ProductionQueueHandler.LocalConfigure.ProductionHeight = (float)Input_ProductionHeight.Value;
|
||||
}
|
||||
}
|
||||
|
||||
private void InitQRCode()
|
||||
@ -156,7 +160,7 @@ namespace XPrint.Production
|
||||
return;
|
||||
}
|
||||
|
||||
if (isLoadingListData)
|
||||
if (isLoadingListData && !isForceRefresh)
|
||||
{
|
||||
Page_Order.Current = beforePage;
|
||||
return;
|
||||
@ -164,7 +168,10 @@ namespace XPrint.Production
|
||||
|
||||
isLoadingListData = true;
|
||||
|
||||
await Task.Delay(500);
|
||||
//if (!isForceRefresh)
|
||||
//{
|
||||
// await Task.Delay(500);
|
||||
//}
|
||||
|
||||
beforePage = page;
|
||||
PageResult<OrderInfo>? infoResult = null;
|
||||
@ -174,12 +181,14 @@ namespace XPrint.Production
|
||||
{
|
||||
Page = page,
|
||||
PageSize = ProductionQueueHandler.PageSize,
|
||||
Status = OrderStatus.Paid
|
||||
Status = OrderStatus.Paid,
|
||||
StartTime = (DatePickerRange.Value != null && DatePickerRange.Value!.Length > 0) ? DatePickerRange.Value[0] : null,
|
||||
EndTime = (DatePickerRange.Value != null && DatePickerRange.Value!.Length > 1) ? DatePickerRange.Value[1].AddDays(1).AddMicroseconds(-1) : null,
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
AntdUI.Message.error(this, "ɾ³ý×ÊԴʧ°Ü:" + ex.Message);
|
||||
AntdUI.Message.error(this, "GetOrderInfoList Error:" + ex.Message);
|
||||
}
|
||||
|
||||
if (infoResult == null && !isForceRefresh)
|
||||
@ -206,18 +215,15 @@ namespace XPrint.Production
|
||||
{
|
||||
Page_Order.Current = 1;
|
||||
}
|
||||
else
|
||||
for (int i = 0; i < infoResult?.Data.Count; i++)
|
||||
{
|
||||
for (int i = 0; i < infoResult?.Data.Count; i++)
|
||||
{
|
||||
var info = infoResult.Data[i];
|
||||
var orderItem = new OrderItem(info);
|
||||
ProductionQueueHandler.Enqueue(ProductionQueueHandler.ProductionQueue, orderItem);
|
||||
}
|
||||
|
||||
Page_Order.Total = (int)infoResult?.Total!;
|
||||
ReloadOrderItems(infoResult.PageSize, page, isForceRefresh);
|
||||
var info = infoResult.Data[i];
|
||||
var orderItem = new OrderItem(info);
|
||||
ProductionQueueHandler.Enqueue(ProductionQueueHandler.ProductionQueue, orderItem);
|
||||
}
|
||||
|
||||
Page_Order.Total = (int)infoResult?.Total!;
|
||||
ReloadOrderItems(infoResult.PageSize, page, isForceRefresh);
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
@ -329,7 +335,7 @@ namespace XPrint.Production
|
||||
}
|
||||
await SyncImage(page);
|
||||
}
|
||||
catch(Exception ex)
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("Disposed,Error:", ex.Message);
|
||||
}
|
||||
@ -360,13 +366,16 @@ namespace XPrint.Production
|
||||
{
|
||||
ListPanel_Orders.Controls.Remove(removeItems[i]);
|
||||
}
|
||||
|
||||
items.Reverse();
|
||||
for (int i = 0; i < items.Count; i++)
|
||||
{
|
||||
if (ListPanel_Orders.Controls.Find(items[i].Name, true).Length == 0)
|
||||
{
|
||||
var item = items[i];
|
||||
|
||||
ListPanel_Orders.Controls.Add(item);
|
||||
ListPanel_Orders.Controls.SetChildIndex(item, 0);
|
||||
//ListPanel_Orders.Controls.SetChildIndex(item, 0);
|
||||
}
|
||||
}
|
||||
//ListPanel_Orders.ScrollBar!.ValueY = beforeScrollTop;
|
||||
@ -405,7 +414,13 @@ namespace XPrint.Production
|
||||
|
||||
private async void Btn_Refresh_Click(object sender, EventArgs e)
|
||||
{
|
||||
await SyncImage(1, true);
|
||||
if (isLoadingListData)
|
||||
{
|
||||
return;
|
||||
}
|
||||
await Task.Delay(500);
|
||||
//Page_Order.Current = 1;
|
||||
await SyncImage(Page_Order.Current, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -229,16 +229,17 @@ namespace XPrint.Production
|
||||
try
|
||||
{
|
||||
imageCreation.Create(infos, LocalConfigure.Dpi, productionImageFile, LocalConfigure.ProductionHeight, printIndex);//暂时只支持tif
|
||||
|
||||
|
||||
//await RemoveItemOssFiles(syncImageInfo);//移除OSS上的文件
|
||||
await form.Invoke(async () =>
|
||||
form.Invoke(() =>
|
||||
{
|
||||
for (int i = 0; i < removeItems.Count; i++)
|
||||
{
|
||||
RemoveOrderItem(removeItems[i]);//从分页数据中移除
|
||||
removeItems[i].ResetQueueStatus();
|
||||
//RemoveOrderItem(removeItems[i]);//从分页数据中移除
|
||||
}
|
||||
AntdUI.Message.success(form, $"生产图 {productionImageFile} 生成成功!");
|
||||
await ReloadDataEvent?.Invoke()!;
|
||||
//await ReloadDataEvent?.Invoke()!;
|
||||
});
|
||||
infos.Clear();//清空这组的生产队列
|
||||
removeItems.Clear();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user