如何在 Magick.NET 中创建 8 bpp BMP?
How to create 8 bpp BMP in Magick.NET?
使用Magick.NET-Q8-AnyCPU。我想将现有的 TIFF 图像转换为灰度 8 bpp BMP 图像。我试过这个:
byte[] input = <existing TIFF image>;
using (var image = new MagickImage(input))
{
image.Grayscale();
image.ColorType = ColorType.Palette;
image.Depth = 8;
image.Quantize(new QuantizeSettings() { Colors = 256, DitherMethod = DitherMethod.No });
byte[] result = image.ToByteArray(MagickFormat.Bmp);
return result;
}
在 FastStone Viewer 中,图像被报告为 8 位,但是在文件属性 > 详细信息中,图像被报告为位深度:32。我在这里需要它是 8。我可以在 Paint.NET 中转换此图像,当我在那里选择位深度:8 位时,新图像将在文件属性中正确显示 8 位深度。
因此,Paint.NET 创建了正确的 8 位位图。如何使用 Magick.NET?
看来这不可能。 image.Depth = 8
和 image.BitDepth(8)
都不起作用。
可能是根在:
// ImageMagick.MagickImage.NativeMethods.X{ver.}
[DllImport("Magick.Native-Q8-x{ver.}.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void MagickImage_SetBitDepth(IntPtr Instance, UIntPtr channels, UIntPtr value);
或
// ImageMagick.MagickImage.NativeMethods.X{ver.}
[DllImport("Magick.Native-Q8-x{ver.}.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void MagickImage_WriteStream(IntPtr Instance, IntPtr settings, ReadWriteStreamDelegate writer, SeekStreamDelegate seeker, TellStreamDelegate teller, ReadWriteStreamDelegate reader, out IntPtr exception);
看起来它不能创建 8 位 .bmp
,虽然 .png
没有问题。
var original = @"D:\tmp[=12=].tif";
var copy = @"D:\tmp[=12=].bmp";
using (var image = new MagickImage(original))
{
image.Grayscale();
image.ColorType = ColorType.Palette;
image.Quantize(new QuantizeSettings() { Colors = 256, DitherMethod = DitherMethod.No });
byte[] result = image.ToByteArray(MagickFormat.Png8);
File.WriteAllBytes(copy, result);
}
Console.WriteLine("Press 'Enter'..."); // one have 8 bits .png here
Console.ReadLine();
using (var image = new MagickImage(copy))
{
byte[] result = image.ToByteArray(MagickFormat.Bmp3);
File.WriteAllBytes(copy, result);
} // but ends up with 32 bits .bmp again here
我也注意到
image.Quantize(new QuantizeSettings() { Colors = 16, DitherMethod = DitherMethod.No });
产生 4 位结果。逐渐增加给出 32 位,但永远不会是 8 位。
Windows 资源管理器将所有 压缩的 BMP 文件显示为 32 位,这与其实际位深度相反。
我不知道这是不是错误,但我更接近于将其称为错误。
因为;用你的代码创建一个 8bpp BMP 文件后,当我用二进制编辑器打开文件时,在位图头结构中我看到每像素字段值的位数(块 28-29)是 8
因为它必须是.此外,下一个字节 01
(偏移量 30)表示使用 Run-length encoding 压缩的数据,这是一种直接的无损数据压缩算法。
因此,我可以说你用Magick.NET制作的图像没有问题,它肯定是一个8bpp的BMP图像文件,但是压缩了。
与 Magick.NET 的默认设置不同,似乎 Paint.NET 生成未压缩的 BMP 文件,这就是为什么您会因为 Windows Explorer 的怪异而看到不同的位深度。
要解决此问题,您可以禁用压缩,这样属性对话框中显示的位深度值将是您期望的值。
image.Settings.Compression = CompressionMethod.NoCompression;
byte[] result = image.ToByteArray(MagickFormat.Bmp);
使用Magick.NET-Q8-AnyCPU。我想将现有的 TIFF 图像转换为灰度 8 bpp BMP 图像。我试过这个:
byte[] input = <existing TIFF image>;
using (var image = new MagickImage(input))
{
image.Grayscale();
image.ColorType = ColorType.Palette;
image.Depth = 8;
image.Quantize(new QuantizeSettings() { Colors = 256, DitherMethod = DitherMethod.No });
byte[] result = image.ToByteArray(MagickFormat.Bmp);
return result;
}
在 FastStone Viewer 中,图像被报告为 8 位,但是在文件属性 > 详细信息中,图像被报告为位深度:32。我在这里需要它是 8。我可以在 Paint.NET 中转换此图像,当我在那里选择位深度:8 位时,新图像将在文件属性中正确显示 8 位深度。
因此,Paint.NET 创建了正确的 8 位位图。如何使用 Magick.NET?
看来这不可能。 image.Depth = 8
和 image.BitDepth(8)
都不起作用。
可能是根在:
// ImageMagick.MagickImage.NativeMethods.X{ver.}
[DllImport("Magick.Native-Q8-x{ver.}.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void MagickImage_SetBitDepth(IntPtr Instance, UIntPtr channels, UIntPtr value);
或
// ImageMagick.MagickImage.NativeMethods.X{ver.}
[DllImport("Magick.Native-Q8-x{ver.}.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void MagickImage_WriteStream(IntPtr Instance, IntPtr settings, ReadWriteStreamDelegate writer, SeekStreamDelegate seeker, TellStreamDelegate teller, ReadWriteStreamDelegate reader, out IntPtr exception);
看起来它不能创建 8 位 .bmp
,虽然 .png
没有问题。
var original = @"D:\tmp[=12=].tif";
var copy = @"D:\tmp[=12=].bmp";
using (var image = new MagickImage(original))
{
image.Grayscale();
image.ColorType = ColorType.Palette;
image.Quantize(new QuantizeSettings() { Colors = 256, DitherMethod = DitherMethod.No });
byte[] result = image.ToByteArray(MagickFormat.Png8);
File.WriteAllBytes(copy, result);
}
Console.WriteLine("Press 'Enter'..."); // one have 8 bits .png here
Console.ReadLine();
using (var image = new MagickImage(copy))
{
byte[] result = image.ToByteArray(MagickFormat.Bmp3);
File.WriteAllBytes(copy, result);
} // but ends up with 32 bits .bmp again here
我也注意到
image.Quantize(new QuantizeSettings() { Colors = 16, DitherMethod = DitherMethod.No });
产生 4 位结果。逐渐增加给出 32 位,但永远不会是 8 位。
Windows 资源管理器将所有 压缩的 BMP 文件显示为 32 位,这与其实际位深度相反。
我不知道这是不是错误,但我更接近于将其称为错误。
因为;用你的代码创建一个 8bpp BMP 文件后,当我用二进制编辑器打开文件时,在位图头结构中我看到每像素字段值的位数(块 28-29)是 8
因为它必须是.此外,下一个字节 01
(偏移量 30)表示使用 Run-length encoding 压缩的数据,这是一种直接的无损数据压缩算法。
因此,我可以说你用Magick.NET制作的图像没有问题,它肯定是一个8bpp的BMP图像文件,但是压缩了。
与 Magick.NET 的默认设置不同,似乎 Paint.NET 生成未压缩的 BMP 文件,这就是为什么您会因为 Windows Explorer 的怪异而看到不同的位深度。
要解决此问题,您可以禁用压缩,这样属性对话框中显示的位深度值将是您期望的值。
image.Settings.Compression = CompressionMethod.NoCompression;
byte[] result = image.ToByteArray(MagickFormat.Bmp);