public static void SeparateAlphaChannel(byte[] png, out byte[] rgb, out byte[] alpha) { MemoryStream s = new MemoryStream(png); Bitmap bmp = new Bitmap(s); MemoryStream rgbStream = new MemoryStream(bmp.Width * bmp.Height * 3); MemoryStream alphaStream = new MemoryStream(bmp.Width * bmp.Height); bool hasAlpha = false; switch (bmp.PixelFormat) { case PixelFormat.Format24bppRgb: // 8 bits per channel, no alpha SeparateAlphaChannel_LockBits(bmp, rgbStream, alphaStream); hasAlpha = false; break; case PixelFormat.Canonical: case PixelFormat.Format32bppArgb: // 8 bits per channel, with alpha SeparateAlphaChannel_LockBits(bmp, rgbStream, alphaStream); hasAlpha = true; break; case PixelFormat.Format32bppRgb: // 8 bits per channel, with an unused alpha byte SeparateAlphaChannel_LockBits(bmp, rgbStream, alphaStream); hasAlpha = false; break; default: // Do it the slow way SeparateAlphaChannel_GetPixel(bmp, rgbStream, alphaStream); hasAlpha = true; break; } rgbStream.Seek(0, SeekOrigin.Begin); alphaStream.Seek(0, SeekOrigin.Begin); rgb = Compression.Compress(rgbStream).GetBuffer(); alpha = hasAlpha ? Compression.Compress(alphaStream).GetBuffer() : null; // A quick performance test with a release build gave these results. // Generally the LockBits method out-performed the GetPixel method // by a factor of three or four. // // Image size Iterations LockBits GetPixel // 50 x 66 1 0.001 0.002 // 50 x 66 10 0.006 0.020 // 50 x 66 100 0.067 0.215 // 50 x 66 1000 0.645 2.151 // 100 x 132 1 0.002 0.007 // 100 x 132 10 0.022 0.080 // 100 x 132 100 0.219 0.831 // 100 x 132 1000 2.193 8.370 // 150 x 198 1 0.005 0.017 // 150 x 198 10 0.051 0.214 // 150 x 198 100 0.487 1.826 // 150 x 198 1000 4.909 18.398 // // int[] iterations = { 1, 10, 100, 1000 }; // foreach(int iteration in iterations) // { // System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch(); // timer.Start(); // for(int x = 0; x < iteration; ++x) // { // byte[] r; // byte[] a; // Image.SeparateAlphaChannel(bits, out r, out a); // } // timer.Stop(); // string msg = $"{size.Width} x {size.Height} run {iteration} times: {timer.Elapsed:mmss\\.fff}\r\n"; // File.AppendAllText(@"c:\users\ciaran\desktop\getpixel.txt", msg); // System.Diagnostics.Debugger.Log(0, null, msg); // } // // In these tests I commented out compression calls so that I just measured // the channel separation stuff. }