XPrintServer/XPrint.Image/Tools/ChannelImageTool.cs
2025-12-22 16:20:26 +08:00

179 lines
7.1 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using HPPH;
using ImageMagick;
using ImageMagick.Formats;
using Pipelines.Sockets.Unofficial.Arenas;
using SixLabors.ImageSharp.PixelFormats;
using System.Drawing;
using System.Drawing.Imaging;
using System.Text;
using System.Threading.Tasks;
namespace XPrint.Image.Tools
{
public class ChannelImageTool
{
/// <summary>
/// 分色接口
/// </summary>
/// <param name="inputPath">输入图片路径</param>
/// <param name="outputPath">输出图片路径</param>
/// <param name="iccProfileName">icc名称</param>
/// <param name="iccProfilePath">icc文件路径</param>
public static void SplitColor(string inputPath, string outputPath, string iccProfilePath = "")
{
using (var image = new MagickImage(inputPath)
{
ColorSpace = ColorSpace.sRGB // 若需与 CMYK 工作流对接,改为 CMYK 并与源一致
})
{
//var profileBim1 = image.Get8BimProfile();
//if (profileBim1 != null)
//{
// var data = profileBim1.ToByteArray();
// File.WriteAllBytes(@"D:\8bim_white_channel", data);
//}
// 配置大端字节序
var writeSettings = new TiffWriteDefines();
writeSettings.Endian = Endian.MSB;//大端模式,兼容性好些
image.Alpha(AlphaOption.On);
image.MetaChannelCount = 0;
ushort[] area;
var pixels = image.GetPixels();
var areaAlpha = pixels.GetArea(0, 0, image.Width, image.Height)!;
image.Alpha(AlphaOption.Off);
image.MetaChannelCount = 1;
var pixels2 = image.GetPixels();
area = pixels2.GetArea(0, 0, image.Width, image.Height)!;
// 遍历每个像素根据Alpha值设置White通道
for (int i = 0; i < areaAlpha.Length; i += 4)
{
// 获取原始图像的Alpha值
ushort alpha = areaAlpha[i + 3];
var r = area[i];
var g = area[i + 1];
var b = area[i + 2];
// 2. 计算白色墨量通过RGB值计算灰度值灰度越高白色墨量越多
// 公式gray = 0.299*R + 0.587*G + 0.114*B适配16位范围
double grayValue = 0.299 * r + 0.587 * g + 0.114 * b;
ushort whiteInkAmount = (ushort)Math.Clamp(grayValue, 0, 65535); // 确保在0~65535范围内
// 3. 黑色填充深度 = 白色墨量(墨量越多,黑色越深)
// 将白色墨量直接映射到目标通道i+4值越高表示黑色越深
area[i + 3] = whiteInkAmount;
}
pixels2.SetPixels(area);
string bimFileName = "8bim_white_channel";
var bimData = File.ReadAllBytes(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"assets/{bimFileName}"));
var profileBim = new EightBimProfile(image, bimData);
//image.Alpha(AlphaOption.Remove);
profileBim.SetExifProfile(image.GetExifProfile());
profileBim.SetIptcProfile(image.GetIptcProfile());
profileBim.SetXmpProfile(image.GetXmpProfile());
image.SetProfile(profileBim);
profileBim.GetExifProfile()?.CreateThumbnail();
image.Settings.Compression = CompressionMethod.LZW;
image.SetCompression(CompressionMethod.LZW);//LZW压缩避免竖线问题
//writeSettings.Alpha = TiffAlpha.Associated;
// 保存
// 4. 保存结果
image.Write(outputPath);
Console.WriteLine($"填充完成,结果已保存至:{outputPath}");
//}
//var profileBim = image.Get8BimProfile()!;
//profileBim.GetExifProfile()?.RemoveThumbnail();
//File.WriteAllBytes(@$"D:\{bimFileName}", profileBim.ToByteArray());
//if (bimProfile != null)
//{
// var exifProfile = bimProfile.GetExifProfile();
// var xmpProfile = bimProfile.GetXmpProfile();
// var iptcProfile = bimProfile.GetIptcProfile();
// profileBim.SetExifProfile(exifProfile);
// profileBim.SetIptcProfile(iptcProfile);
// profileBim.SetXmpProfile(xmpProfile);
//}
//image.Compose = CompositeOperator.Overlay;
//var channelNames = new Dictionary<int, string>
//{
// { 0, "C" }, // 假设通道索引1对应红色
// { 1, "M" },
// { 2, "Y" },
// { 3, "K" },
// { 4, "A" },
// { 5, "W" }
//};
//TiffModifier.RenameCustomChannels(@"D:\2.tiff", Path.Combine(Path.GetDirectoryName(outputPath)!, "3.tif"), channelNames);
// 创建包含 4 个自定义通道的图像
//using (System.Drawing.Image imageA = new Bitmap(new MemoryStream(image.ToByteArray())))
//{
// var items = imageA.PropertyItems;
//}
}
}
//private static string AddCustomXmpChannelName(string xmpXml, string channelName)
//{
// // 注意:此方法需要根据实际 XMP 结构和命名空间调整
// // 示例:添加自定义命名空间 "mychannel"
// if (!xmpXml.Contains("xmlns:mychannel"))
// {
// xmpXml = xmpXml.Replace("<rdf:RDF",
// "<rdf:RDF xmlns:mychannel=\"http://example.com/channel/\"");
// }
// // 添加或更新 ChannelName 属性
// string channelProperty = $"<mychannel:ChannelName>{channelName}</mychannel:ChannelName>";
// int insertPos = xmpXml.IndexOf("</rdf:RDF>");
// if (insertPos > 0)
// {
// xmpXml = xmpXml.Insert(insertPos, channelProperty);
// }
// return xmpXml;
//}
//public static void GenerateMultiPageCmykTiff(MagickImage[] imagePages, string outputPath)
//{
// using (var images = new MagickImageCollection())
// {
// for (int i = 0; i < imagePages.Length; i++)
// {
// //设置dpi
// //imagePages[i].Density = new Density(300.00, 300.00);
// images.Add(imagePages[i]);
// }
// // 配置大端字节序
// var writeSettings = new WriteTiffBigEndianDefines();
// // 保存多页
// images.Write(outputPath, writeSettings);
// }
//}
}
}