312 lines
12 KiB
C#
312 lines
12 KiB
C#
using HPPH;
|
||
using ImageMagick;
|
||
using ImageMagick.Formats;
|
||
using System.Drawing;
|
||
using System.Drawing.Imaging;
|
||
using System.Text;
|
||
|
||
namespace XPrint.Image.Tools
|
||
{
|
||
public class CmykImageTool
|
||
{
|
||
private static XmpProfile? _xmpProfile = null;
|
||
static CmykImageTool()
|
||
{
|
||
string channelName = "White";
|
||
// 构建包含 Adobe 标准命名空间的 XML
|
||
var xml = $@"
|
||
<x:xmpmeta>
|
||
<rdf:RDF>
|
||
<rdf:Description rdf:about=''>
|
||
<photoshop:ChannelNames>
|
||
<rdf:Bag>
|
||
<rdf:li>Alpha</rdf:li>
|
||
<rdf:li>${channelName}</rdf:li>
|
||
</rdf:Bag>
|
||
</photoshop:ChannelNames>
|
||
</rdf:Description>
|
||
</rdf:RDF>
|
||
</x:xmpmeta>;";
|
||
var data = Encoding.UTF8.GetBytes(xml);
|
||
_xmpProfile = new XmpProfile(data);
|
||
|
||
}
|
||
public static bool IsCmykImage(string imagePath)
|
||
{
|
||
using (var image = new MagickImage(imagePath))
|
||
{
|
||
// 检查颜色空间是否为 CMYK
|
||
return image.ColorSpace == ColorSpace.CMYK;
|
||
}
|
||
}
|
||
|
||
/// <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))
|
||
{
|
||
// 配置大端字节序
|
||
var writeSettings = new TiffWriteDefines();
|
||
writeSettings.Endian = Endian.MSB;//大端模式,兼容性好些
|
||
image.MetaChannelCount = 1;
|
||
|
||
//if (!image.HasAlpha)
|
||
//{
|
||
// image.Alpha(AlphaOption.On);
|
||
//}
|
||
|
||
//var profileBim = image.Get8BimProfile();
|
||
//if (profileBim != null)
|
||
//{
|
||
// var data = profileBim.ToByteArray();
|
||
// File.WriteAllBytes(@"D:\8bim", data);
|
||
//}
|
||
|
||
|
||
//if (!string.IsNullOrWhiteSpace(iccProfileName) && !string.IsNullOrWhiteSpace(iccProfilePath))
|
||
//{
|
||
// // 加载ICC配置文件
|
||
// var profile = new ColorProfile(File.ReadAllBytes(iccProfilePath));
|
||
// image.SetProfile(profile);
|
||
//}
|
||
//else
|
||
//{
|
||
// var profile = new ExifProfile();
|
||
// profile.SetValue(ExifTag.Copyright, "Anole");
|
||
// profile.SetValue(ExifTag.ImageDescription, "");
|
||
// image.SetProfile(profile);
|
||
//}
|
||
//var value5 = profileBim.Values.ElementAt(5);
|
||
|
||
//profileBim.Values.Append(new EightBimValue { });
|
||
//foreach (var p in pro?.Values!)
|
||
//{
|
||
// Console.WriteLine(p.Name);
|
||
//}
|
||
//Console.WriteLine("ICC配置文件已成功应用");
|
||
|
||
//image.Comment = """
|
||
// <?xml version="1.0" encoding="utf-16"?>
|
||
// <ChannelNames xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
||
// <Channel Index="0" Name="C" />
|
||
// <Channel Index="1" Name="M" />
|
||
// <Channel Index="2" Name="Y" />
|
||
// <Channel Index="3" Name="K" />
|
||
// <Channel Index="4" Name="A" />
|
||
// <Channel Index="5" Name="W" />
|
||
// </ChannelNames>
|
||
// """;
|
||
// 添加输入和输出配置
|
||
image.SetProfile(ColorProfile.ColorMatchRGB);
|
||
//image.SetProfile(new ColorProfile(@"D:\sRGB2014.icc"));
|
||
//image.SetProfile(new ColorProfile(@"D:\JapanColor2001Coated.icc"));
|
||
|
||
if (!string.IsNullOrWhiteSpace(iccProfilePath))
|
||
{
|
||
// 加载ICC配置文件
|
||
var profile = new ColorProfile(iccProfilePath);
|
||
//var icc = imageKele.GetProfile("icc")!;
|
||
image.SetProfile(profile);
|
||
}
|
||
else
|
||
{
|
||
image.SetProfile(ColorProfile.USWebCoatedSWOP);
|
||
}
|
||
|
||
// 确保图像为CMYK模式
|
||
if (image.ColorSpace != ColorSpace.CMYK)
|
||
{
|
||
image.ColorSpace = ColorSpace.CMYK;
|
||
}
|
||
|
||
|
||
var channels = image.Channels;
|
||
ushort[] area;
|
||
var pixels = image.GetPixels();
|
||
bool hasAlpha = image.HasAlpha;
|
||
if (hasAlpha)
|
||
{
|
||
image.Alpha(AlphaOption.On);
|
||
image.MetaChannelCount = 0;
|
||
var areaAlpha = pixels.GetArea(0, 0, image.Width, image.Height)!;
|
||
|
||
image.Alpha(AlphaOption.Off);
|
||
image.MetaChannelCount = 1;
|
||
area = pixels.GetArea(0, 0, image.Width, image.Height)!;
|
||
// 遍历每个像素,根据Alpha值设置White通道
|
||
for (int i = 0; i < areaAlpha.Length; i += 5)
|
||
{
|
||
// 获取原始图像的Alpha值
|
||
ushort alpha = areaAlpha[i + 4];
|
||
|
||
var c = area[i];
|
||
var m = area[i + 1];
|
||
var y = area[i + 2];
|
||
var k = area[i + 3];
|
||
|
||
if (c > 0 || m > 0 || y > 0 || k > 0)
|
||
{
|
||
// 根据Alpha值设置White通道:透明区域(Alpha=0)设为黑色,不透明区域设为白色
|
||
ushort whiteValue = (ushort)(alpha == 0 ? 0 : 65535);
|
||
area[i + 4] = whiteValue;
|
||
}
|
||
else
|
||
{
|
||
area[i + 4] = 0;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
image.Alpha(AlphaOption.Off);
|
||
area = pixels.GetArea(0, 0, image.Width, image.Height)!;
|
||
// 遍历每个像素,根据Alpha值设置White通道
|
||
for (int i = 0; i < area.Length; i += 5)
|
||
{
|
||
var c = area[i];
|
||
var m = area[i + 1];
|
||
var y = area[i + 2];
|
||
var k = area[i + 3];
|
||
|
||
if (c > 0 || m > 0 || y > 0 || k > 0)
|
||
{
|
||
area[i + 4] = 65535;
|
||
}
|
||
else
|
||
{
|
||
area[i + 4] = 0;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
if (hasAlpha)
|
||
{
|
||
image.MetaChannelCount = 1;
|
||
}
|
||
pixels.SetPixels(area);
|
||
|
||
//var channels = image.Channels;
|
||
|
||
//whiteChannel.Composite(image, CompositeOperator.Copy, Channels.CMYK);
|
||
|
||
|
||
|
||
//if (!string.IsNullOrWhiteSpace(iccProfileName) && !string.IsNullOrWhiteSpace(iccProfilePath))
|
||
//{
|
||
// // 加载ICC配置文件
|
||
// var profile = new ColorProfile(File.ReadAllBytes(iccProfilePath));
|
||
// image.SetProfile(profile);
|
||
//}
|
||
//image.SetProfile(ColorProfile.USWebCoatedSWOP);
|
||
//var bimProfile = image.Get8BimProfile();
|
||
|
||
string bimFileName = "8bim";
|
||
//if (hasAlpha)
|
||
//{
|
||
// bimFileName = "8bim_alpha";
|
||
//}
|
||
var bimData = File.ReadAllBytes(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"assets/{bimFileName}"));
|
||
var profileBim = new EightBimProfile(image, bimData);
|
||
|
||
//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.Alpha(AlphaOption.Remove);
|
||
profileBim.SetExifProfile(image.GetExifProfile());
|
||
profileBim.SetIptcProfile(image.GetIptcProfile());
|
||
profileBim.SetXmpProfile(image.GetXmpProfile());
|
||
image.SetProfile(profileBim);
|
||
|
||
profileBim.GetExifProfile()?.CreateThumbnail();
|
||
|
||
|
||
//image.Compose = CompositeOperator.Overlay;
|
||
|
||
image.Settings.Compression = CompressionMethod.LZW;
|
||
image.SetCompression(CompressionMethod.LZW);//LZW压缩避免竖线问题
|
||
//writeSettings.Alpha = TiffAlpha.Associated;
|
||
// 保存
|
||
image.Write(outputPath);
|
||
|
||
//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;
|
||
//}
|
||
pixels.Dispose();
|
||
}
|
||
}
|
||
|
||
//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);
|
||
// }
|
||
//}
|
||
}
|
||
}
|