Самый простой способ объединить несколько изображений PNG8 в .NET - PullRequest
4 голосов
/ 05 декабря 2010

Я пытаюсь объединить кучу 8-битных изображений PNG в большее изображение PNG в C #.Как ни странно, это кажется особенно трудным.

Поскольку Graphics не поддерживает индексированный цвет, вы не можете его использовать, поэтому я попытался создать неиндексированный битовый образ (используя Graphics) и преобразовать его в индексированный цвет.битовая карта.Преобразование в порядке, но я не могу понять, как установить палитру выходного изображения.По умолчанию используется некоторая предопределенная палитра, которая имеет мало общего с тем, что я ищу.

Итак:

Есть ли способ управления палитрой растровых изображений?Или есть другой метод (например, System.Windows.Media.Imaging.WriteableBitmap), который может это поддерживать?

Re: WriteableBitmap: Кажется, я не могу найти в Интернете никаких примеров того, как можно было бы объединить PNG в этом контексте, или даже если есть смысл попытаться сделать это.

Ответы [ 2 ]

0 голосов
/ 05 декабря 2010

Оказывается, я смог создать неиндексированное растровое изображение и преобразовать его с помощью PngBitmapEncoder, например:

    byte[] ConvertTo8bpp(Bitmap sourceBitmap)
    {
        // generate a custom palette for the bitmap (I already had a list of colors
        // from a previous operation
        Dictionary<System.Drawing.Color, byte> colorDict = new Dictionary<System.Drawing.Color, byte>(); // lookup table for conversion to indexed color
        List<System.Windows.Media.Color> colorList = new List<System.Windows.Media.Color>(); // list for palette creation
        byte index = 0;
        unchecked
        {
            foreach (var cc in ColorsFromPreviousOperation)
            {
                colorDict[cc] = index++;
                colorList.Add(cc.ToMediaColor());
            }
        }
        System.Windows.Media.Imaging.BitmapPalette bmpPal = new System.Windows.Media.Imaging.BitmapPalette(colorList);

        // create the byte array of raw image data
        int width = sourceBitmap.Width;
        int height = sourceBitmap.Height;
        int stride = sourceBitmap.Width;
        byte[] imageData = new byte[width * height];

        for (int x = 0; x < width; ++x)
            for (int y = 0; y < height; ++y)
            {
                var pixelColor = sourceBitmap.GetPixel(x, y);
                imageData[x + (stride * y)] = colorDict[pixelColor];
            }

        // generate the image source
        var bsource = BitmapSource.Create(width, height, 96, 96, PixelFormats.Indexed8, bmpPal, imageData, stride);

        // encode the image
        PngBitmapEncoder encoder = new PngBitmapEncoder();
        encoder.Interlace = PngInterlaceOption.Off;
        encoder.Frames.Add(BitmapFrame.Create(bsource));

        MemoryStream outputStream = new MemoryStream();
        encoder.Save(outputStream);

        return outputStream.ToArray();
    }

Плюс метод расширения помощника:

    public static System.Windows.Media.Color ToMediaColor(this System.Drawing.Color color)
    {
        return new System.Windows.Media.Color()
        {
            A = color.A,
            R = color.R,
            G = color.G,
            B = color.B
        };
    }

Примечание для осторожных: кажется, что PngBitmapEncoder на самом деле сокращает число bpp с 8 до 4, когда может. Например, когда я тестирую с 6 цветами, вывод PNG только 4-битный. Когда я использую более насыщенное изображение, оно 8-битное. Выглядит как функция до сих пор ... хотя было бы неплохо, если бы у меня был явный контроль над ней.

0 голосов
/ 05 декабря 2010

Отказ от ответственности, я работаю на Atalasoft.

Наш продукт, DotImage Photo , является бесплатным и может сделать это.

Чтобы прочитать PNG

 AtalaImage img = new AtalaImage("image.png");

Для преобразования в 24 bpp

 img = img.GetChangedPixelFormat(newPixelFormat);

Создайте изображение нужного вам размера

 AtalaImage img2 = new AtalaImage(width, height, color);

использовать OverlayCommand для наложения img на img2

 OverlayCommand cmd = new OverlayCommand(img);
 cmd.Apply(img2, point);

Для сохранения

 img2.Save("new.png", new PngEncoder(), null);

Если вам нужна помощь, прокомментируйте этот ответ или оставьте запись на форуме.

...