private unsafe byte[] BitmapToRawIndexed(Bitmap source, int maxColors, out byte[][] palette) { Bitmap img = source; byte[] destination = new byte[img.Width * img.Height]; // If this is not a 32-bit ARGB bitmap, convert it to one if (img.PixelFormat != System.Drawing.Imaging.PixelFormat.Format32bppArgb) { Bitmap newImage = new Bitmap(img.Width, img.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb); using (System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(newImage)) { g.DrawImage(img, 0, 0, img.Width, img.Height); } img = newImage; } // Quantize the image WuQuantizer quantizer = new WuQuantizer(); m_palette = quantizer.CreatePalette(img, maxColors); img = (Bitmap)quantizer.QuantizeImage(img, m_palette); // Copy over the data to the destination. We need to use Stride in this case, as it may not // always be equal to Width. BitmapData bitmapData = img.LockBits(new Rectangle(0, 0, img.Width, img.Height), ImageLockMode.ReadOnly, img.PixelFormat); byte *pointer = (byte *)bitmapData.Scan0; for (int y = 0; y < bitmapData.Height; y++) { for (int x = 0; x < bitmapData.Width; x++) { destination[(y * img.Width) + x] = pointer[(y * bitmapData.Stride) + x]; } } img.UnlockBits(bitmapData); // Copy over the palette palette = new byte[maxColors][]; for (int i = 0; i < maxColors; i++) { palette[i] = new byte[4]; palette[i][3] = img.Palette.Entries[i].A; palette[i][2] = img.Palette.Entries[i].R; palette[i][1] = img.Palette.Entries[i].G; palette[i][0] = img.Palette.Entries[i].B; } return(destination); }