Create Bitmap from a Byte Array of Pixel Data

Create Bitmap from a byte array of pixel data

  1. Its safe if you marshal.copy data rather than setting scan0 (directly or via that overload of BitMap()). You don't want to keep managed objects pinned, this will constrain the garbage collector.
  2. If you copy, perfectly safe.
  3. The input array is managed and can be moved by the GC, scan0 is an unmanaged pointer that would get out of date if the array moved. The Bitmap object itself is managed but sets the scan0 pointer in Windows via a handle.
  4. ImageLockMode.UserInputBuffer is? Apparently it can be passed to LockBits, maybe it tells Bitmap() to copy the input array data.

Example code to create a greyscale bitmap from array:

    var b = new Bitmap(Width, Height, PixelFormat.Format8bppIndexed);

ColorPalette ncp = b.Palette;
for (int i = 0; i < 256; i++)
ncp.Entries[i] = Color.FromArgb(255, i, i, i);
b.Palette = ncp;

var BoundsRect = new Rectangle(0, 0, Width, Height);
BitmapData bmpData = b.LockBits(BoundsRect,
ImageLockMode.WriteOnly,
b.PixelFormat);

IntPtr ptr = bmpData.Scan0;

int bytes = bmpData.Stride*b.Height;
var rgbValues = new byte[bytes];

// fill in rgbValues, e.g. with a for loop over an input array

Marshal.Copy(rgbValues, 0, ptr, bytes);
b.UnlockBits(bmpData);
return b;

Creating a BitMap Image out of a Byte[] Array consisting of PixelData in Visual C#

  1. Use Format8bppIndexed and set the obvious palette

    Bitmap ImageFromArray(byte[] arr, int width, int height)
    {
    var output = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
    var rect = new Rectangle(0, 0, width, height);
    var bmpData = output.LockBits(rect,ImageLockMode.WriteOnly, output.PixelFormat);
    var ptr = bmpData.Scan0;
    if (bmpData.Stride != width)
    throw new InvalidOperationException("Cant copy directly if stride mismatches width, must copy line by line");
    Marshal.Copy(arr, 0, ptr, width*height);
    output.UnlockBits(bmpData);
    var palEntries = new Color[256];
    var cp = output.Palette;
    for (int i = 0; i < 256; i++)
    cp.Entries[i] = Color.FromArgb(i, i, i);
    output.Palette = cp;
    return output;
    }
  2. Set PictureBox.SizeMode to StretchImage. You'll probably need that.

How to create bitmap from byte array?

Guys thank you for your help. I think all of this answers works. However i think my byte array contains raw bytes. That's why all of those solutions didnt work for my code.

However i found a solution. Maybe this solution helps other coders who have problem like mine.

static byte[] PadLines(byte[] bytes, int rows, int columns) {
int currentStride = columns; // 3
int newStride = columns; // 4
byte[] newBytes = new byte[newStride * rows];
for (int i = 0; i < rows; i++)
Buffer.BlockCopy(bytes, currentStride * i, newBytes, newStride * i, currentStride);
return newBytes;
}

int columns = imageWidth;
int rows = imageHeight;
int stride = columns;
byte[] newbytes = PadLines(imageData, rows, columns);

Bitmap im = new Bitmap(columns, rows, stride,
PixelFormat.Format8bppIndexed,
Marshal.UnsafeAddrOfPinnedArrayElement(newbytes, 0));

im.Save("C:\\Users\\musa\\Documents\\Hobby\\image21.bmp");

This solutions works for 8bit 256 bpp (Format8bppIndexed). If your image has another format you should change PixelFormat .

And there is a problem with colors right now. As soon as i solved this one i will edit my answer for other users.

*PS = I am not sure about stride value but for 8bit it should be equal to columns.

And also this function Works for me.. This function copies 8 bit greyscale image into a 32bit layout.

public void SaveBitmap(string fileName, int width, int height, byte[] imageData)
{

byte[] data = new byte[width * height * 4];

int o = 0;

for (int i = 0; i < width * height; i++)
{
byte value = imageData[i];

data[o++] = value;
data[o++] = value;
data[o++] = value;
data[o++] = 0;
}

unsafe
{
fixed (byte* ptr = data)
{

using (Bitmap image = new Bitmap(width, height, width * 4,
PixelFormat.Format32bppRgb, new IntPtr(ptr)))
{

image.Save(Path.ChangeExtension(fileName, ".jpg"));
}
}
}
}

Android byte array to Bitmap How to

I've been using it like below in one of my projects and so far it's been pretty solid. I'm not sure how picky it is as far as it not being compressed as a PNG though.

byte[] bytesImage;
Bitmap bmpOld; // Contains original Bitmap
Bitmap bmpNew;

ByteArrayOutputStream baoStream = new ByteArrayOutputStream();
bmpOld.compress(Bitmap.CompressFormat.PNG, 100, baoStream);
bytesImage = baoStream.toByteArray();
bmpNew = BitmapFactory.decodeByteArray(bytesImage, 0, bytesImage.length);

edit: I've adapted the code from this post to use RGB, so the code below should work for you. I haven't had a chance to test it yet so it may need some adjusting.

Byte[] bytesImage = {0,1,2, 0,1,2, 0,1,2, 0,1,2};
int intByteCount = bytesImage.length;
int[] intColors = new int[intByteCount / 3];
int intWidth = 2;
int intHeight = 2;
final int intAlpha = 255;
if ((intByteCount / 3) != (intWidth * intHeight)) {
throw new ArrayStoreException();
}
for (int intIndex = 0; intIndex < intByteCount - 2; intIndex = intIndex + 3) {
intColors[intIndex / 3] = (intAlpha << 24) | (bytesImage[intIndex] << 16) | (bytesImage[intIndex + 1] << 8) | bytesImage[intIndex + 2];
}
Bitmap bmpImage = Bitmap.createBitmap(intColors, intWidth, intHeight, Bitmap.Config.ARGB_8888);

Creating a bitmap from RGB array in C#, result image difference?

I think I found the answer.
Because I didn't aware of BitmapData.Stride attribute. Someone has a answer here.

My modified save function is here:

    private static void MySaveBMP(byte[] buffer, int width, int height)
{
Bitmap b = new Bitmap(width, height, PixelFormat.Format24bppRgb);

Rectangle BoundsRect = new Rectangle(0, 0, width, height);
BitmapData bmpData = b.LockBits(BoundsRect,
ImageLockMode.WriteOnly,
b.PixelFormat);

IntPtr ptr = bmpData.Scan0;

// add back dummy bytes between lines, make each line be a multiple of 4 bytes
int skipByte = bmpData.Stride - width*3;
byte[] newBuff = new byte[buffer.Length + skipByte*height];
for (int j = 0; j < height; j++)
{
Buffer.BlockCopy(buffer, j * width * 3, newBuff, j * (width * 3 + skipByte), width * 3);
}

// fill in rgbValues
Marshal.Copy(newBuff, 0, ptr, newBuff.Length);
b.UnlockBits(bmpData);
b.Save(@"D:\myPic.bmp", ImageFormat.Bmp);
}

Another solution is that, I change the PixelFormat to Format32bppPArgb, and change bytesPerPixel to 4. So I don't need to bother with the 4-bytes scan line format.

creating a java bitmap image from a 3d byte array which contains 3 channel pixel information

Some part of the question isn't clear to me like you want to rotate the image or not(the 480x360 to 360x480 part).

So, I am assuming the following things:

(1) you've a proper byte array called data which holds the data as you've described

(2) and you need to create an bitmap from the data

(3) and you can rotate the image if necessary(i.e. this following code doesn't rotate image)

  • the following code is not tested. But it should get you on the right track.
int width = 480;
int height = 360;

int alpha = 1; // change alpha as necessary

Bitmap bmp = Bitmap.createBitmap(width, height, Config.ARGB_8888);

for(int x=0; x<width; x++) {
for(int y=0; y<height; y++) {
int red = data[0][x][y];
int green = data[1][x][y];
int blue = data[2][x][y];

int color = Color.argb(alpha, red, green, blue);

bmp.setPixel(x, y, color);
}
}



Related Topics



Leave a reply



Submit