2

我有以下图像(已放置图像的屏幕抓图,因为它的大小超过 2 MB - 可以从https://drive.google.com/file/d/1rC2QQBzMhZ8AG5Lp5PyrpkOxwlyP9QaE/view?usp=下载原始图像分享

在此处输入图像描述

我正在使用BitmapDecoder类读取图像并使用 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配色方案。我尝试使用以下代码设置颜色配置文件,但这会导致此错误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);
     }
4

1 回答 1

2

图像位是相同的。这是一个元数据问题。此图像文件包含大量元数据(Xmp、Adobe、未知等),此元数据包含两个颜色配置文件/空间/上下文

  1. ProPhoto RG(通常在 C:\WINDOWS\system32\spool\drivers\color\ProPhoto.icm 中找到)
  2. sRGB IEC61966-2.1(通常在 WINDOWS\system32\spool\drivers\color\sRGB Color Space Profile.icm 中找到)

出现此问题的原因是目标文件中的两个上下文顺序可能因某种原因而不同。图像查看器既可以不使用颜色配置文件(Paint、Pain3D、Paint.NET、IrfanView 等),也可以使用(根据我的经验)文件中的最后一个颜色配置文件(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)配置文件意味着它可以显示......以两种或多种方式。

在这种奇怪的情况下,您必须确定您首选的颜色配置文件是什么。

于 2021-12-03T13:41:17.620 回答