Stealth Rabbi
Stealth Rabbi

Reputation: 10346

Create a PNG from an array of bytes

I have a 1 dimensional array of bytes, with separate values for A, R, G, and B, and I know the height and width of the expected image. How can I encode this data and save it as a PNG?

Upvotes: 6

Views: 12012

Answers (4)

Peter Wentworth
Peter Wentworth

Reputation: 1

I suggest it is better to look for a platform-independent solution that doesn't depend on building a desktop image or a Bitmap (neither GDI+ Bitmap nor WPF WriteableBitmap). BigGustave (available on NuGet) did the trick for me. https://github.com/EliotJones/BigGustave It creates the PNGs directly.

Upvotes: 0

Slashy
Slashy

Reputation: 1881

Here's a faster solution using Unsafe pointers and LockBits

    public unsafe Bitmap Retreive(byte[] values)
    {
        Bitmap bmp = new Bitmap(Width, Height); //enter your width and height here.
        BitmapData bmData = bmp.LockBits(new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, bmp.PixelFormat);
        IntPtr scan0 = bmData.Scan0;
        int stride = bmData.Stride;
        int nWidth = bmp.Width;
        int nHeight = bmp.Height;

        for (int y = 0; y < nHeight; y++)
        {
            //define the pointers inside the first loop for parallelizing
            byte* p = (byte*)scan0.ToPointer();
            p += y * stride;

            for (int x = 0; x < nWidth; x++)
            {
                //fill as  the values stored in you byte array;
                p[0] = values[0];// R component.
                p[1] = values[1];// G component.
                p[2] = values[2];// B component.
                p[3] = values[3];// Alpha component.
                p += 4;
            }
        }

        bmp.UnlockBits(bmData);
        return bmp;
    }

Just fill the p[] values like they stored in your array.

Goodluck.

Upvotes: 0

user1027167
user1027167

Reputation: 4458

byte[] data = new byte[] {
    255, 255, 000, 000,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 000, 000, 
    255, 255, 255, 255,  255, 255, 000, 000,  255, 255, 255, 255,  255, 255, 000, 000,  255, 255, 255, 255, 
    255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 000, 000,  255, 255, 255, 255,  255, 255, 255, 255, 
    255, 255, 255, 255,  255, 255, 000, 000,  255, 255, 255, 255,  255, 255, 000, 000,  255, 255, 255, 255, 
    255, 255, 000, 000,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 000, 000 
  };

  Bitmap bmp = new Bitmap(5, 5);
  for (int y = 0; y < 5; ++y)
    for (int x = 0; x < 5; ++x)
    {
      int offset = y * 5 * 4 + x * 4;
      bmp.SetPixel(x, y, Color.FromArgb(data[offset], data[offset + 1], data[offset + 2], data[offset + 3]));
    }
  bmp.Save(@"c:\tmp.png");
}

If the values in your array are ordered this way: B G R A B G R A B G R A ... you could use the following code, which should be faster:

byte[] data = new byte[] {
  // B    G    R    A     B    G    R    A     B    G    R    A
      0,   0, 255, 255,    0,   0,   0, 255,    0, 255,   0, 255,
      0,   0,   0, 255,    0, 255,   0, 255,  255, 255, 255, 255,
      0, 255,   0, 255,    0,   0,   0, 255,  255,   0,   0, 255
  };
  int width = 3;
  int height = 3;

  Bitmap bmp = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
  var bitmapData = bmp.LockBits(new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.WriteOnly, bmp.PixelFormat);
  Marshal.Copy(data, 0, bitmapData.Scan0, data.Length);
  bmp.UnlockBits(bitmapData);
  bmp.Save(@"c:\tmp.png");

This image should look like this: enter image description here

Upvotes: 5

ispiro
ispiro

Reputation: 27723

You can use a Bitmap and Bitmap.SetPixel().

Then save the Bitmap as png using ImageFormat.Png . Also, you might have to make sure that the Bitmap format maintains transparency .

(See the other answer here for a faster way than SetPixel.)

EDIT

Perhaps WPF can use the array directly. (I don't have much experience with it.)

Upvotes: 4

Related Questions