繁体   English   中英

将 bitmap (rgb) 与 TIFF (cmyk) 连接,而不将 cmyk 转换为 rgb

[英]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 的质量,所以我认为最好不要进行任何转换,保持原始并合并。 无论如何,这只是一个猜测,其他选项也可以考虑。 请问有人能解释一下我的情况吗?

请参阅下面从 cmyk 转换为 rgb 前后的 tiff 图像比较。 CMYK(左)和后来转换为 RGB(右)的 TIFF 图像的比较

我不知道 TIFF 格式的任何容量可以同时具有两个不同的色彩空间。 由于您正在处理 CMYK,我认为这是您要保留的。

如果是这样,这样做的步骤是:

  1. 加载 CMYK 图像 A(使用BitmapDecoder
  2. 加载 RGB 图像 B(使用BitmapDecoder
  3. 使用所需的颜色配置文件将图像 B 转换为 CMYK(使用FormatConvertedBitmap
  4. 如果需要,确保图像 B 的像素格式与 A 匹配(使用FormatConvertedBitmap
  5. 将 memory 中的两者合成为字节数组(使用CopyPixels ,然后 memory 操作,然后从内存中新建 bitmap )
  6. 将合成保存到新的 CMYK TIFF 文件(使用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 以获取原件。)

图像 A(CMYK): 图片 1 - CMYK、白色、深黑色

图像 B (RGB): 图像 B - RGB、白色、黑色

结果(CMYK): 图像结果 - 完全保持 CMYK 的 RGB,RGB 改变。

要使两张图像重叠,一张图像必须具有某种透明度的概念。 遮罩就是其中的一个示例,您可以在其中选择特定的颜色值来表示“透明”。 遮罩的缺点是遮罩不能很好地处理混叠的源图像。 为此,您会想要做一个 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);
}

示例图像 B: RGB 叠加图像

示例 output: CMYK 叠加输出

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM