[英]Concatenate a bitmap (rgb) with a TIFF (cmyk) without converting cmyk to rgb
我正在开发一个应用程序来连接 RGB 格式的 bitmap 图像和 CMYK 格式的 TIFF。 我尝试过使用 System.Drawing 和 System.Windows.Media 命名空间。
问题是两个库都尝试在合并之前将我的 TIFF 图像转换为 RGB,这会导致图像质量下降。
据我了解,他们总是在处理之前将图像转换为 RGB 的原因是因为这两个库是出于渲染意图而这样做的。
我不需要渲染任何东西,只需将两张照片合并并保存到磁盘,仅此而已。
我应该怎么做才能实现我的目标? 显然,我不想失去 TIFF 的质量,所以我认为最好不要进行任何转换,保持原始并合并。 无论如何,这只是一个猜测,其他选项也可以考虑。 请问有人能解释一下我的情况吗?
我不知道 TIFF 格式的任何容量可以同时具有两个不同的色彩空间。 由于您正在处理 CMYK,我认为这是您要保留的。
如果是这样,这样做的步骤是:
BitmapDecoder
)BitmapDecoder
)FormatConvertedBitmap
)FormatConvertedBitmap
)CopyPixels
,然后 memory 操作,然后从内存中新建 bitmap )TiffBitmapEncoder
)WIC (System.Media)应该可以做到这一点。
这样做的一个例子( github )可以写成:
BitmapFrame LoadTiff(string filename)
{
using (var rs = File.OpenRead(filename))
{
return BitmapDecoder.Create(rs, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad).Frames[0];
}
}
// Load, validate A
var imageA = LoadTiff("CMYK.tif");
if (imageA.Format != PixelFormats.Cmyk32)
{
throw new InvalidOperationException("imageA is not CMYK");
}
// Load, validate, convert B
var imageB = LoadTiff("RGB.tif");
if (imageB.PixelHeight != imageA.PixelHeight)
{
throw new InvalidOperationException("Image B is not the same height as image A");
}
var imageBCmyk = new FormatConvertedBitmap(imageB, imageA.Format, null, 0d);
// Merge
int width = imageA.PixelWidth + imageB.PixelWidth,
height = imageA.PixelHeight,
bytesPerPixel = imageA.Format.BitsPerPixel / 8,
stride = width * bytesPerPixel;
var buffer = new byte[stride * height];
imageA.CopyPixels(buffer, stride, 0);
imageBCmyk.CopyPixels(buffer, stride, imageA.PixelWidth * bytesPerPixel);
var result = BitmapSource.Create(width, height, imageA.DpiX, imageA.DpiY, imageA.Format, null, buffer, stride);
// save to new file
using (var ws = File.Create("out.tif"))
{
var tiffEncoder = new TiffBitmapEncoder();
tiffEncoder.Frames.Add(BitmapFrame.Create(result));
tiffEncoder.Save(ws);
}
它保持 CMYK 图像的颜色准确性,并使用系统颜色配置文件转换 RGB。 这可以在 Photoshop 中进行验证,显示每个字母和丰富的黑色都保持了它们的原始值。 (请注意,imgur 确实转换为具有可疑颜色处理的 png - 检查 github 以获取原件。)
要使两张图像重叠,一张图像必须具有某种透明度的概念。 遮罩就是其中的一个示例,您可以在其中选择特定的颜色值来表示“透明”。 遮罩的缺点是遮罩不能很好地处理混叠的源图像。 为此,您会想要做一个 Alpha 通道 - 但跨色彩空间混合将具有挑战性。 ( Github )
// Load, validate A
var imageA = LoadTiff("CMYK.tif");
if (imageA.Format != PixelFormats.Cmyk32)
{
throw new InvalidOperationException("imageA is not CMYK");
}
// Load, validate, convert B
var imageB = LoadTiff("RGBOverlay.tif");
if (imageB.PixelHeight != imageA.PixelHeight
|| imageB.PixelWidth != imageA.PixelWidth)
{
throw new InvalidOperationException("Image B is not the same size as image A");
}
var imageBBGRA = new FormatConvertedBitmap(imageB, PixelFormats.Bgra32, null, 0d);
var imageBCmyk = new FormatConvertedBitmap(imageB, imageA.Format, null, 0d);
// Merge
int width = imageA.PixelWidth, height = imageA.PixelHeight;
var stride = width * (imageA.Format.BitsPerPixel / 8);
var bufferA = new uint[width * height];
var bufferB = new uint[width * height];
var maskBuffer = new uint[width * height];
imageA.CopyPixels(bufferA, stride, 0);
imageBBGRA.CopyPixels(maskBuffer, stride, 0);
imageBCmyk.CopyPixels(bufferB, stride, 0);
for (int i = 0; i < bufferA.Length; i++)
{
// set pixel in bufferA to the value from bufferB if mask is not white
if (maskBuffer[i] != 0xffffffff)
{
bufferA[i] = bufferB[i];
}
}
var result = BitmapSource.Create(width, height, imageA.DpiX, imageA.DpiY, imageA.Format, null, bufferA, stride);
// save to new file
using (var ws = File.Create("out_overlay.tif"))
{
var tiffEncoder = new TiffBitmapEncoder();
tiffEncoder.Frames.Add(BitmapFrame.Create(result));
tiffEncoder.Save(ws);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.