JPEGEncoder Windows 媒体成像不遵守图像的颜色配置文件

JPEGEncoder Windows Media Imaging not honoring color profile of Image

我有下面的图片(因为它的大小超过 2 MB,所以放了一张图片的屏幕截图 - 原件可以从 https://drive.google.com/file/d/1rC2QQBzMhZ8AG5Lp5PyrpkOxwlyP9QaE/view?usp=sharing

下载

我正在使用 BitmapDecoder class 读取图像并使用 JPEG 编码器保存它。 这会导致以下图像变色和褪色。

var frame = BitmapDecoder.Create(new Uri(inputFilePath, UriKind.RelativeOrAbsolute),BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.None).Frames[0];
    var encoder = new JpegBitmapEncoder();    
     encoder.Frames.Add(frame);
     using (var stream = File.OpenWrite(outputFilePath))
     {
     encoder.Save(stream);
     }

图像使用 PhotoShop RGB 颜色 scheme.I 尝试使用以下代码设置颜色配置文件,但这会导致此错误 The designated BitmapEncoder does not support ColorContexts

encoder.ColorContexts = frame.ColorContexts;

更新: 克隆图像似乎可以解决问题。但是当我使用以下代码调整图像大小时进行转换时,颜色配置文件不会保留

Transform transform = new ScaleTransform(width / frame.Width * 96 / frame.DpiX, height / frame.Height * 96 / frame.DpiY, 0, 0); 
     var copy = BitmapFrame.Create(frame);
     var resized = BitmapFrame.Create(new 
     TransformedBitmap(copy, transform));          
     encoder.Frames.Add(resized);
     using (var stream = File.OpenWrite(outputFilePath))
     {
     encoder.Save(stream);
     }

图像位相同。这是一个元数据问题。此图像文件包含大量元数据(Xmp、Adobe、未知等)并且此元数据包含两个 color profiles/spaces/contexts:

  1. ProPhoto RG(通常在 C:\WINDOWS\system32\spool\drivers\color\ProPhoto.icm 中找到)
  2. sRGB IEC61966-2.1(通常出现在WINDOWS\system32\spool\drivers\color\sRGB颜色SpaceProfile.icm)

出现此问题是因为由于某种原因,目标文件中的两个上下文顺序可能不同。图像查看器可以不使用颜色配置文件(Paint、Pain3D、Paint.NET、IrfanView 等),或者使用(根据我的经验)文件中的 last 颜色配置文件(Windows 照片查看器、Photoshop 等)。

如果您克隆框架,您可以解决您的问题,即:

var frame = BitmapDecoder.Create(new Uri(inputFilePath, UriKind.RelativeOrAbsolute),BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.None).Frames[0];
var encoder = new JpegBitmapEncoder();    
var copy = BitmapFrame.Create(frame);
encoder.Frames.Add(copy);
using (var stream = File.OpenWrite(outputFilePath))
{
    encoder.Save(stream);
}

在这种情况下,订单将按原样保留。

如果您重新创建框架或以任何方式对其进行转换,则可以像这样复制元数据和颜色上下文:

var ctxs = new List<ColorContext>();
ctxs.Add(frame.ColorContexts[1]); // or just remove this
ctxs.Add(frame.ColorContexts[0]); // first color profile is ProPhoto RG, make sure it's last
var resized = BitmapFrame.Create(new TransformedBitmap(frame, transform), frame.Thumbnail, (BitmapMetadata)frame.Metadata, ctxs.AsReadOnly());
var encoder = new JpegBitmapEncoder();
encoder.Frames.Add(resized);
using (var stream = File.OpenWrite("resized.jpg"))
{
    encoder.Save(stream);
}

请注意,具有不止一种颜色上下文的图像是痛苦的(恕我直言,不应创建/保存)。颜色配置文件用于确保正确显示,因此与一个图像关联的两个或更多(相当冲突!sRGB 与 ProPhoto)配置文件意味着它可以以两种或更多方式显示......

在这种奇怪的情况下,您必须确定您喜欢的颜色配置文件。