gpt4 book ai didi

c# - 为什么在 WPF 中将 BitmapSource 保存为 bmp、jpeg 和 png 时得到完全不同的结果

转载 作者:太空狗 更新时间:2023-10-29 21:30:57 25 4
gpt4 key购买 nike

我编写了一个小工具类,用于将 BitmapSource 对象保存到图像文件中。图像文件可以是 bmp、jpeg 或 png。这是代码:

public class BitmapProcessor
{
public void SaveAsBmp(BitmapSource bitmapSource, string path)
{
Save(bitmapSource, path, new BmpBitmapEncoder());
}

public void SaveAsJpg(BitmapSource bitmapSource, string path)
{
Save(bitmapSource, path, new JpegBitmapEncoder());
}

public void SaveAsPng(BitmapSource bitmapSource, string path)
{
Save(bitmapSource, path, new PngBitmapEncoder());
}

private void Save(BitmapSource bitmapSource, string path, BitmapEncoder encoder)
{
using (var stream = new FileStream(path, FileMode.Create))
{
encoder.Frames.Add(BitmapFrame.Create(bitmapSource));
encoder.Save(stream);
}
}
}

三种 Save 方法中的每一种都有效,但我在使用 bmp 和 jpeg 时得到了意想不到的结果。如果我使用 WPF Image 控件在屏幕上显示 BitmapSource,Png 是唯一能够精确再现我所看到的内容的格式。

结果如下:


BMP - 太暗

too dark http://img822.imageshack.us/img822/7403/terrainbmp.png


JPEG - 太饱和

too saturated http://img816.imageshack.us/img816/8127/terrainjpeg.jpg


PNG - 正确

correct http://img810.imageshack.us/img810/6243/terrainpng.png


为什么不同的文件类型会得到完全不同的结果?

我应该注意到,我的示例中的 BitmapSource 使用 0.1 的 alpha 值(这就是它看起来非常不饱和的原因),但它应该可以以任何图像格式显示结果颜色。我知道如果我使用 HyperSnap 之类的工具进行屏幕截图,无论我保存到什么文件类型,它看起来都是正确的。


这是保存为 bmp 的 HyperSnap 屏幕截图:

correct http://img815.imageshack.us/img815/9966/terrainbmphypersnap.png

如您所见,这不是问题,因此 WPF 的图像编码器肯定有一些奇怪的地方。

我设置有误吗?我错过了什么吗?

最佳答案

我个人认为看到您所看到的并不奇怪。 BMP 和 JPG 不支持不透明度,而 PNG 支持。

以这段代码为例,它在图像中创建了一个部分透明的蓝色矩形。

WriteableBitmap bm = new WriteableBitmap( 100, 100, 96, 96, PixelFormats.Pbgra32, null );
bm.Lock();

Bitmap bmp = new Bitmap( bm.PixelWidth, bm.PixelHeight, bm.BackBufferStride, System.Drawing.Imaging.PixelFormat.Format32bppArgb, bm.BackBuffer );
using( Graphics g = Graphics.FromImage( bmp ) ) {
var color = System.Drawing.Color.FromArgb( 20, System.Drawing.Color.Blue);
g.FillRectangle(
new System.Drawing.SolidBrush( color ),
new RectangleF( 0, 0, bmp.Width, bmp.Height ) );
}

bmp.Save( @".\000_foo.bmp", System.Drawing.Imaging.ImageFormat.Bmp );
bmp.Save( @".\000_foo.jpg", System.Drawing.Imaging.ImageFormat.Jpeg );
bmp.Save( @".\000_foo.png", System.Drawing.Imaging.ImageFormat.Png );

bmp.Dispose();

bm.AddDirtyRect( new Int32Rect( 0, 0, bm.PixelWidth, bm.PixelHeight ) );
bm.Unlock();

new BitmapProcessor().SaveAsBmp( bm, @".\foo.bmp" );
new BitmapProcessor().SaveAsJpg( bm, @".\foo.jpg" );
new BitmapProcessor().SaveAsPng( bm, @".\foo.png" );

PNG 格式始终有效,无论是 System.Drawing 还是 WPF 编码器。 JPG 和 BMP 编码器不起作用。它们显示一个实心的蓝色矩形。

这里的关键是我没有在图像中指定背景颜色。如果没有背景颜色,图像将无法以不支持 alpha channel (BMP/JPG) 的格式正确呈现。加上一行代码:

g.Clear( System.Drawing.Color.White );
g.FillRectangle(
new System.Drawing.SolidBrush( color ),
new RectangleF( 0, 0, bmp.Width, bmp.Height ) );

我的图像有背景颜色,因此不支持 alpha channel 的编码器可以确定每个像素的输出颜色。现在我所有的图像看起来都是正确的。

在您的情况下,您应该使用指定背景颜色的 RenderTargetBitmap 控件,或者在渲染图像时绘制背景颜色。

仅供引用,您的第 3 方打印屏幕工作的原因是最终透明颜色在该点具有背景颜色(在具有背景颜色的窗口上)。但是在 WPF 内部,您正在处理没有一组的元素;在元素上使用 RTB 不会继承其各种父元素的属性,例如背景颜色。

关于c# - 为什么在 WPF 中将 BitmapSource 保存为 bmp、jpeg 和 png 时得到完全不同的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3041935/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com