Display RAW RGB byte array in PictureBox in WinForms app - c#

I have an .rgb file that I attached. It is a valid rgb file that I verified through other software. As far as I understand this is a raw RGB data file.
I need to load the file into byte[] and display it in PictureBox.
From all my searches here I came to this solution that seems correct and that works for others. Unfortunately it displays nothing for me:
string imgPath = Path.Combine(mInstallPath, "squirrel-720x576x50.rgb\\squirrel-720x576x50.rgb");
byte[] imageData = File.ReadAllBytes(imgPath);
using (var bmp = new Bitmap(width, height, PixelFormat.Format24bppRgb))
{
BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0,
bmp.Width,
bmp.Height),
ImageLockMode.WriteOnly,
bmp.PixelFormat);
Marshal.Copy(imageData, 0, bmpData.Scan0, width * height * 3);//imageData.Length);
//bmpSource.CopyPixels((Int32Rect.Empty, bmpData.Scan0, bmpData.Height * bmpData.Stride, bmpData.Stride);
bmp.UnlockBits(bmpData);
pictureBox.Image = bmp;
}
Any ideas why nothing is displayed in my pictureBox ?

Related

Playback raw video frames in C# Win Forms application

How can I playback and save selected raw video frames from raw video data (in .rgb or .raw).
Raw uncompressed video data is 320 x 240 in grayscale format with 1 byte/pixel and just 30 fps.
But how can I view multiple the frames in 30 FPS?
Can I use DirectShow or a similar API? And what is the best resource to get started? I looked at FFPMEG but I want to avoid showing compressed frames as this it is for scientific application.
So far I have been able to view one frame from a raw video data (in .rgb) using this code in C# .NET for Win Forms using a Picture Box control.
But not sure how to do multiple frames and perhaps have a seeking control.
byte[] imageData = File.ReadAllBytes("output.rgb");
Console.WriteLine("imageDataLen=" + imageData.Length);
int width = 320;
int height = 240;
var bmp = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
//bmp = (Bitmap) ConvertToGrayScale(bmp);
ColorPalette pal = bmp.Palette;
for (int i = 0; i <= 255; i++)
{
// create greyscale color table
pal.Entries[i] = Color.FromArgb(i, i, i);
}
bmp.Palette = pal;
BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0,
bmp.Width,
bmp.Height),
ImageLockMode.WriteOnly,
bmp.PixelFormat);
Marshal.Copy(imageData, 0, bmpData.Scan0, width * height);
bmp.UnlockBits(bmpData);
pictureBox1.SizeMode = PictureBoxSizeMode.AutoSize;
pictureBox1.Image = bmp;

Bitmap array format in C#

I have following code to create bitmap using array with data*
//Here create the Bitmap to the know height, width and format
Bitmap bmp = new Bitmap( 5,7,PixelFormat.Format1bppIndexed);
//Create a BitmapData and Lock all pixels to be written
BitmapData bmpData = bmp.LockBits(
new Rectangle(0, 0, bmp.Width, bmp.Height),
ImageLockMode.WriteOnly, bmp.PixelFormat);
//Copy the data from the byte array into BitmapData.Scan0
Marshal.Copy(data, 0, bmpData.Scan0, data.Length);
//Unlock the pixels
bmp.UnlockBits(bmpData);
bmp.Save("BitMapIcon.bmp",ImageFormat.Bmp);
My input array (data ) :
byte[5] data = {0xff,0xff,0xff,0xff,0xff}
Question :
Can array of data* for bitmap input have only valu of each pixel (in this
format it is 0 and 1 ) ?
Why passing array of 0xff value some of
pixel are not black ?
Can width size be less than 1 byte ?
You have two issues:
First, the default palette for the indexed format uses 0 for black and 1 for white. So your code is actually trying to initialize a white bitmap, not a black one
Second, and more to the point of your question, is that you are not fully initializing the bitmap. This relates to your third question: the width of the bitmap is allowed to have less than 1 byte's worth of pixels, but the bitmap data itself could require more than that for a single scan line of the bitmap.
Indeed, due to the alignment requirements of a bitmap, your bitmap's "stride" is 4 bytes. So you need 28 bytes total in order to fully initialize the bitmap.
This code will initialize the bitmap the way you want:
//Here create the Bitmap to the know height, width and format
Bitmap bmp = new Bitmap(5, 7, PixelFormat.Format1bppIndexed);
//Create a BitmapData and Lock all pixels to be written
BitmapData bmpData = bmp.LockBits(
new Rectangle(0, 0, bmp.Width, bmp.Height),
ImageLockMode.WriteOnly, bmp.PixelFormat);
//Copy the data from the byte array into BitmapData.Scan0
byte[] data = new byte[bmpData.Stride * bmpData.Height];
for (int i = 0; i < data.Length; i++)
{
data[i] = 0xff;
}
Marshal.Copy(data, 0, bmpData.Scan0, data.Length);
//Unlock the pixels
bmp.UnlockBits(bmpData);
Use 0x00 instead of 0xff if you actually wanted black pixels.

Generating a Random JPG Image From Console Application

I have an API that takes the base64string of an image of size 80x20(either JPG, PNG or GIF) and stores in database. In order to test this API I have to generate a random base64string which can be converted into a real image when decoded.
I have find the example here which seems to work with WPF application. How to use the same for a console application?
A variety of methods should work. How about the following:
public static string GenerateBase64ImageString()
{
// 1. Create a bitmap
using (Bitmap bitmap = new Bitmap(80, 20, PixelFormat.Format24bppRgb))
{
// 2. Get access to the raw bitmap data
BitmapData data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.WriteOnly, bitmap.PixelFormat);
// 3. Generate RGB noise and write it to the bitmap's buffer.
// Note that we are assuming that data.Stride == 3 * data.Width for simplicity/brevity here.
byte[] noise = new byte[data.Width * data.Height * 3];
new Random().NextBytes(noise);
Marshal.Copy(noise, 0, data.Scan0, noise.Length);
bitmap.UnlockBits(data);
// 4. Save as JPEG and convert to Base64
using (MemoryStream jpegStream = new MemoryStream())
{
bitmap.Save(jpegStream, ImageFormat.Jpeg);
return Convert.ToBase64String(jpegStream.ToArray());
}
}
}
Just be sure to add a reference to System.Drawing.

BitmapSource.Create switches RGB values

I am loading pixels from a file onto an array of bytes using this code:
Bitmap bmp = new Bitmap(filename);
var rect = new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height);
BitmapData bmpData = bmp.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
IntPtr ptr = bmpData.Scan0;
int numBytes = bmpData.Stride * bmp.Height;
byte[] rgbValues = new byte[numBytes];
Marshal.Copy(ptr, rgbValues, 0, numBytes);
I am pretty sure that this is not the problem.
After I have loaded the file, I want to display manipulate the colors and then display in a WPF window.
So I create a bitmap source with the following line:
BitmapSource img = BitmapSource.Create(width, height, 96, 96, PixelFormats.Rgb24, null, pixels, stride);
The problem is that the red bytes are switched with the green bytes.
It is similar to this - Why color changes when save a BitmapSource to Bitmap for PixelFormat.Format48bppRgb? -
but i don't know how to fix it.
Then you may use PixelFormats.Bgr24 instead of PixelFormats.Rgb24 to create the BitmapSource.
var img = BitmapSource.Create(
width, height, 96, 96, PixelFormats.Bgr24, null, pixels, stride);

Pixelbox shows error image on valid bitmap

I have a wired probly. I recieve pixel data from a web control (Awesomium).
I want to display the bipmap in a PictureBox.
using (System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(viewPortX, viewPortY, System.Drawing.Imaging.PixelFormat.Format32bppArgb))
{
BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.WriteOnly, bmp.PixelFormat);
BitmapSurface bmpSurface = (BitmapSurface)htmlHolder.Surface;
bmpSurface.CopyTo(bmpData.Scan0, bmpSurface.RowSpan, 4, false, false);
bmp.UnlockBits(bmpData);
bmp.Save("result.jpg", ImageFormat.Jpeg);
pictureBox.Load(result.jpg);
}
This works fine. The bitmap is diaplayed.
If I change
bmp.Save("result.jpg", ImageFormat.Jpeg);
pictureBox.Load(result.jpg);
to
pictureBox.Image = bmp;
then the eror image is shown in the PictureBox.
Any idea what's is wrong?
Greetings
Clemens Hoffmann
because you destroy bmp object before it get's loaded into picturebox. using statement dispose image created within it's range.

Categories