Как создать 8 bpp BMP в Magick.NET? - PullRequest
4 голосов
/ 20 сентября 2019

Использование Magick.NET-Q8-AnyCPU.Я хочу преобразовать существующее изображение TIFF в изображение BMP в оттенках серого 8 bpp.Я пробовал это:

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, и когда я выберу там Bit Depth: 8-bit, тогда новое изображение будет правильно отображать 8-битную глубину в свойствах файла.

Итак, Paint.NET создает правильные 8-битовый растрКак это сделать с помощью Magick.NET?

Ответы [ 2 ]

1 голос
/ 24 сентября 2019

Проводник Windows отображает все сжатые BMP-файлы как 32-битные, в отличие от их фактической глубины в битах.

Я не знаю, это ошибка или нет, но я немного ближе, чтобы назвать это ошибкой.

Потому что;после создания файла BMP 8bpp с вашим кодом, когда я открывал файл с помощью двоичного редактора, в структуре заголовка растрового изображения я увидел, что значение поля бит на пиксель (блоки 28-29) было 8, как и должно быть.Кроме того, следующий байт 01 (смещение 30) означает, что данные, сжатые с помощью кодирования по длине прогона , который представляет собой простой алгоритм сжатия данных без потерь.

8bpp bmp hex

Таким образом, я могу сказать, что нет проблем с изображением, которое вы создали с помощью Magick.NET, это, конечно, файл BMP-образа 8bpp, но сжатый.

В отличие от настроек по умолчанию в Magick.NET, Paint.NET создает несжатые BMP-файлы, поэтому вы видите разную глубину в битах из-за странности Windows Explorer.

Чтобы это исправить, вы можете отключитьсжатие, поэтому значение битовой глубины, отображаемое в диалоговом окне свойств, будет ожидаемым значением.

image.Settings.Compression = CompressionMethod.NoCompression;
byte[] result = image.ToByteArray(MagickFormat.Bmp);
1 голос
/ 23 сентября 2019

Кажется, это невозможно.Ни 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. * 1011 проблем нет.*

var original = @"D:\tmp\0.tif";
var copy = @"D:\tmp\0.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 бит.

...