2010-12-05 3 views
4

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

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

Итак:

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

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

+0

Несмотря на то, что, в частности, ссылки на GIF-серверы, такая же таблица таблицы цветов, вероятно, применяется ... http://support.microsoft.com/kb/319061 немного экспериментировал с кодом при выполнении чего-то очень похожего. – 2010-12-05 03:08:05

ответ

0

Оказывается, что я был в состоянии пристроить Неиндексированные растрового изображения и преобразования с использованием 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

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

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

Для чтения PNG

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

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

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); 

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

Смежные вопросы