Преобразовать 24-битное изображение в памяти в индексированный цвет - PullRequest
2 голосов
/ 08 апреля 2009

У меня есть изображение, которое я создал в памяти как Format24bppRgb.

Я сохраняю это как PNG, и это 24 КБ.

Если я сохраню то же изображение в фотошопе, что и 24-битный PNG, он получится примерно того же размера, но если я сохраню его как 8-битный PNG только с 32 цветами, он уменьшится до 5 КБ.

Как создать индексированную версию файла PNG с помощью C # / GDI + / System.Drawing?

Мне трудно найти ответы на этот вопрос, которые не относятся только к изображениям в градациях серого или требуют внешней библиотеки. это не возможно в GDI + как есть?

Ответы [ 3 ]

2 голосов
/ 09 апреля 2009

В итоге я использовал FreeImageAPI DLL с оболочкой C #. Я стараюсь избегать сторонних библиотек, но не думаю, что есть другой выбор. Кажется, довольно стандартная и хорошо используемая библиотека.

В моем случае у меня есть System.Drawing.Image объект 'image', который был создан динамически - который я хочу сохранить в выходной поток HttpContext в виде сжатого изображения. Обратите внимание, что Image не имеет необходимого метода GetHbitmap(), но Bitmap имеет.

// convert image to a 'FreeImageAPI' image
var fiBitmap = FreeImageAPI.FreeImageBitmap.FromHbitmap((image as Bitmap).GetHbitmap());
fiBitmap.ConvertColorDepth(FreeImageAPI.FREE_IMAGE_COLOR_DEPTH.FICD_08_BPP);

// see http://stackoverflow.com/questions/582766
MemoryStream ms = new MemoryStream();
fiBitmap.Save(ms, FreeImageAPI.FREE_IMAGE_FORMAT.FIF_PNG, FreeImageAPI.FREE_IMAGE_SAVE_FLAGS.PNG_Z_BEST_COMPRESSION);
context.HttpContext.Response.OutputStream.Write(ms.ToArray(), 0, (int)ms.Length);

Мое растровое изображение размером 24 КБ теперь составляет всего 9 КБ: -)

Подсказка: Убедитесь, что в вашей корзине есть как 'FreeImageNET', так и 'FreeImage', когда вы запускаете их. В настоящее время примеры проектов C # содержат ссылку на «Library.DLL», которая, по-видимому, отсутствует в их zip-файле. Использование FreeImageNET.dll и FreeImage.dll работает, хотя. Вы получите досадную ошибку "файл не найден", если не понимаете, что FreeImageNet! = FreeImage!

1 голос
/ 20 марта 2015

Вы можете сделать это с помощью nQuant (который можно установить с помощью nuget или см. Ссылки ниже). В следующем примере изображение на диске преобразуется и будет легко адаптировано к вашим потребностям.

    public static bool TryNQuantify(string inputFilename, string outputFilename)
    {
        var quantizer = new nQuant.WuQuantizer();
        var bitmap = new Bitmap(inputFilename);
        if (bitmap.PixelFormat != System.Drawing.Imaging.PixelFormat.Format32bppArgb)
        {
            ConvertTo32bppAndDisposeOriginal(ref bitmap);
        }

        try
        {
            using (var quantized = quantizer.QuantizeImage(bitmap))
            {
                quantized.Save(outputFilename, System.Drawing.Imaging.ImageFormat.Png);
            }
        }
        catch
        {
            return false;
        }
        finally
        {
            bitmap.Dispose();
        }
        return true;
    }

    private static void ConvertTo32bppAndDisposeOriginal(ref Bitmap img)
    {
        var bmp = new Bitmap(img.Width, img.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
        using (var gr = Graphics.FromImage(bmp))
            gr.DrawImage(img, new Rectangle(0, 0, img.Width, img.Height));
        img.Dispose();
        img = bmp;
    }

Для получения дополнительной информации см .:

0 голосов
/ 09 апреля 2009

Вы пытаетесь конвертировать 16777216 цветов до 32. Это нетривиальная проблема, и есть много способов сделать это, каждый из которых имеет свои плюсы и минусы. Это не то, что вам часто нужно делать, тем более что полноцветные дисплеи стали вездесущими.

Эта статья Microsoft содержит некоторую информацию о файлах GIF, которые также должны иметь отношение к PNG.

http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q319061

...