使c#保存一个16位的位图,不需要位域压缩

本文关键字:位图 不需要 压缩 位域 16位 一个 保存 | 更新日期: 2023-09-27 18:18:33

当我做一个

b.Save(outputFilename, ImageFormat.Bmp);

,其中b是一个16位的位图,它被保存为位域压缩。如何在不使用任何压缩的情况下使c#保存?

这是我对@Ben Voigt发布的链接所做的:

ImageCodecInfo myImageCodecInfo;
Encoder myEncoder ;
EncoderParameter myEncoderParameter;
EncoderParameters myEncoderParameters;
myEncoder = Encoder.Compression;
myImageCodecInfo = GetEncoderInfo("image/bmp");
myEncoderParameters = new EncoderParameters(1);
myEncoderParameter = new EncoderParameter(myEncoder, 
                     (long)EncoderValue.CompressionNone);
myEncoderParameters.Param[0] = myEncoderParameter;
b.Save(outputFilename, myImageCodecInfo, myEncoderParameters );

当我传递一个8位的位图时,没有使用压缩。但是当我传递一个16位RGB位图时,它仍然使用位域压缩。

使c#保存一个16位的位图,不需要位域压缩

windows中的位图表示DIB。

"设备无关位图(DIB)是一种用于定义各种颜色分辨率的设备无关位图的格式。dib的主要目的是允许位图从一个设备移动到另一个设备(因此,名称中与设备无关的部分)。DIB是一种外部格式,与设备相关的位图相反,后者在系统中作为位图对象出现(由应用程序创建…)。DIB通常以元文件(通常使用StretchDIBits()函数)、BMP文件和剪贴板(CF_DIB数据格式)的形式传输。"

正如我们在评论中已经讨论过的,BITFIELDS压缩只用于16位和32位的dib,并且简单地描述了数据是如何打包的。在16位DIB的情况下,它可以定义绿色通道的分辨率(即5:6:5或5:5:5),而对于32位DIB,它定义数据是否以RGB或BGR顺序存储(以及,当使用BMIHv4/5报头时,是否使用alpha通道)。

这样做只有一个原因。这是为了保持BMP与设备无关,这是关于格式与它可能使用的设备无关。所以这意味着,它总是保存在DIB格式根据Windows !

EncoderParameters codecParams = new EncoderParameters(1);
codecParams.Param[0] = new EncoderParameter(Encoder.Quality, 100L); 
b.Save(outputFilename, myImageCodecInfo, codecparams ); 

Save函数有一个接受EncoderParameters参数的过载,通过它可以控制压缩

参见http://msdn.microsoft.com/en-us/library/ytz20d80.aspx和http://msdn.microsoft.com/en-us/library/system.drawing.imaging.encoder.compression.aspx

看来你真正需要的不是"保存一个16位的位图而不进行位域压缩",而是避免有损压缩。

问题是16位的位图格式本质上使用位域,(像5位的红色,6位的绿色,另外5位的蓝色,)所以一些信息将丢失,如果原始图像的像素格式比16位宽。现在最常用的图像格式是RGB格式,它每像素使用8位,所以它需要3 × 8 = 24位每像素。你根本无法将24位的信息塞进16位;有些东西会掉下来,这是生活的事实。

因此,只要需要16位图,您的问题就无法解决。唯一的解决方法是避免使用16位的位图。

注意:

即使你指定了"不压缩",仍然使用位场压缩的原因是因为位场压缩并不是真正的压缩;它只是一个像素格式,所以它应该被称为"位场格式"而不是"位场压缩"。RLE是一种真正的(尽管极其简单)压缩方法。

RLE代表"行长编码",其工作原理如下:将长度为N的一系列相同的像素值替换为数字N,然后再出现一次像素值。因此,RLE是绝对无损的。