Context: I have a program that gets the ArGB of any image. Throws it into a Color ARGBFormat = Color.FromArgb(alpha, red, green, blue); Now I would like to put that into a PictureBox. I do not have a complete Pixel Array (It is more or less scattered).
Code:
Bitmap bmp = new Bitmap(ImagePath);
Rectangle bmpRec = new Rectangle(0, 0, bmp.Width, bmp.Height); //Creates Rectangle for holding picture
BitmapData bmpData = bmp.LockBits(bmpRec, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); //Gets the Bitmap data
IntPtr Pointer = bmpData.Scan0;
int DataBytes = Math.Abs(bmpData.Stride) * bmp.Height; //Gets array size
byte[] rgbValues = new byte[DataBytes]; //Creates array
Marshal.Copy(Pointer, rgbValues, 0, DataBytes); //Copies of out memory
StringBuilder EveryPixel = new StringBuilder(" ");
int PixelSize = 4;
Color ARGBFormat;
Bitmap ImageOut = new Bitmap(bmp.Width, bmp.Height);
unsafe
{
for (int y = 0; y < bmpData.Height; y++)
{
byte* row = (byte*)bmpData.Scan0 + (y * bmpData.Stride);
for (int x = 0; x < bmpData.Width; x++)
{
int offSet = x * PixelSize;
// read pixels
byte blue = row[offSet];
byte green = row[offSet + 1];
byte red = row[offSet + 2];
byte alpha = row[offSet + 3];
ARGBFormat = Color.FromArgb(alpha, red, green, blue);
ImageOut.SetPixel(x, y, ARGBFormat); //Slow
EveryPixel.Append(ARGBFormat);
}
}
}
I want to use that code that I have been working on ^ to be displayed into a PictureBox without using SetPixels. I want to use LockBits as it is the most optimize method.
Here you go
initialization code before the loop
BitmapData bitmapData = ImageOut.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
byte[] pixels = new byte[bmp.Width * bmp.Height * 4]; //4 means 1 byte for each a r g b
IntPtr ptr = bitmapData.Scan0;
Marshal.Copy(ptr , pixels, 0, pixels.Length);
update the pixels within the loop
pixels[offSet] = blue;
pixels[offSet + 1] = green;
pixels[offSet + 2] = red;
pixels[offSet + 3] = alpha;
finally to cleanup the code
bitmapData.UnlockBits();
so for me code look like
unsafe
{
BitmapData bitmapData = ImageOut.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
byte[] pixels = new byte[bmp.Width * bmp.Height * 4]; //4 means 1 byte for each a r g b
IntPtr ptr = bitmapData.Scan0;
Marshal.Copy(ptr , pixels, 0, pixels.Length);
for (int y = 0; y < bmpData.Height; y++)
{
byte* row = (byte*)bmpData.Scan0 + (y * bmpData.Stride);
for (int x = 0; x < bmpData.Width; x++)
{
int offSet = x * PixelSize;
// read pixels
byte blue = row[offSet];
byte green = row[offSet + 1];
byte red = row[offSet + 2];
byte alpha = row[offSet + 3];
//copy to target
pixels[offSet] = blue;
pixels[offSet + 1] = green;
pixels[offSet + 2] = red;
pixels[offSet + 3] = alpha;
}
}
bitmapData.UnlockBits();
}
//set to picturebox
pictureBox.Image = ImageOut;
I hope this work for you.
Related
When using DiffSetPixel it's adding the different pixels to the new bitmap diffBM when i'm using the second method DiffLockBits it's adding the different pixels to the existing bitmap.
what i want to do is in the first method the DiffSetPixel to be able to add the different pixels to existing bitmap any existing bitmap and not only to the diffBM and in the DiffLockBits i want to add it also to the diffBM.
and in both methods i want to be able to change the different pixels colors for example to red or green or any color and not only grayscale.
DiffSetPixel method
public static Bitmap DiffSetPixel(Bitmap src1, Bitmap src2, int x1, int y1, int x2, int y2, int width, int height)
{
Bitmap diffBM = new Bitmap(width, height, PixelFormat.Format24bppRgb);
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
//Get Both Colours at the pixel point
Color col1 = src1.GetPixel(x1 + x, y1 + y);
Color col2 = src2.GetPixel(x2 + x, y2 + y);
// Get the difference RGB
int r = 0, g = 0, b = 0;
r = Math.Abs(col1.R - col2.R);
g = Math.Abs(col1.G - col2.G);
b = Math.Abs(col1.B - col2.B);
// Invert the difference average
int dif = 255 - ((r + g + b) / 3);
// Create new grayscale RGB colour
Color newcol = Color.FromArgb(dif,dif,dif);
diffBM.SetPixel(x, y, newcol);
}
}
return diffBM;
}
DiffLockBits method
public static Bitmap DiffLockBits(Bitmap bmp1 , Bitmap bmp2)
{
Bitmap diffBM = new Bitmap(bmp1.Width, bmp1.Height, PixelFormat.Format24bppRgb);
//Lock bitmap's bits to system memory
Rectangle rect = new Rectangle(0, 0, bmp1.Width, bmp1.Height);
BitmapData bmpData = bmp1.LockBits(rect, ImageLockMode.ReadWrite, bmp1.PixelFormat);
Rectangle rect1 = new Rectangle(0, 0, bmp2.Width, bmp2.Height);
BitmapData bmpData1 = bmp2.LockBits(rect1, ImageLockMode.ReadWrite, bmp2.PixelFormat);
//Scan for the first line
IntPtr ptr = bmpData.Scan0;
IntPtr ptr1 = bmpData1.Scan0;
//Declare an array in which your RGB values will be stored
int bytes = Math.Abs(bmpData.Stride) * bmp1.Height;
byte[] rgbValues = new byte[bytes];
int bytes1 = Math.Abs(bmpData1.Stride) * bmp2.Height;
byte[] rgbValues1 = new byte[bytes1];
//Copy RGB values in that array
Marshal.Copy(ptr, rgbValues, 0, bytes);
Marshal.Copy(ptr1, rgbValues1, 0, bytes1);
for (int i = 0; i < rgbValues.Length; i += 3)
{
if (rgbValues[i] != rgbValues1[i])
{
//Set RGB values in a Array where all RGB values are stored
byte gray = (byte)(rgbValues[i] * .21 + rgbValues[i + 1] * .71 + rgbValues[i + 2] * .071);
rgbValues[i] = rgbValues[i + 1] = rgbValues[i + 2] = gray;
}
}
//Copy changed RGB values back to bitmap
Marshal.Copy(rgbValues, 0, ptr, bytes);
//Unlock the bits
bmp1.UnlockBits(bmpData);
bmp2.UnlockBits(bmpData1);
return bmp1;
}
I am using mvfox-igc camera sdk for getting images from that camera my problem is that i have byte array of mono8 image and i want to convert that pixel data into 24bit image my programming language
can anybody help me please my code looks like this but is is not doing its work properly
processedBitmap = new Bitmap(data.request.imageWidth.read(),data.request.imageHeight.read(),PixelFormat.Format24bppRgb);
unsafe
{
BitmapData bitmapData = processedBitmap.LockBits(new Rectangle(0, 0, processedBitmap.Width, processedBitmap.Height), ImageLockMode.ReadWrite, processedBitmap.PixelFormat);
int bytesPerPixel = System.Drawing.Bitmap.GetPixelFormatSize(processedBitmap.PixelFormat) / 8;
int heightInPixels = bitmapData.Height;
int widthInBytes = bitmapData.Width * bytesPerPixel;
byte* PtrFirstPixel = (byte*)bitmapData.Scan0;
byte* firstby = (byte*)data.request.imageData.read();
int indexx=0;
Parallel.For(0, heightInPixels, y =>
{
byte* currentLine = PtrFirstPixel + (y * bitmapData.Stride);
for (int x = 0; x < widthInBytes; x = x + bytesPerPixel)
{
currentLine[x] = firstby[indexx];//((byte*)data.request.imageData.read())[0];//(byte)oldBlue;
currentLine[x + 1] = firstby[indexx];//((byte*)data.request.imageData.read())[0];//(byte)oldGreen;
currentLine[x + 2] = firstby[indexx];//((byte*)data.request.imageData.read())[0];//(byte)oldRed;
indexx = indexx + 1;
}
});
processedBitmap.UnlockBits(bitmapData);
processedBitmap.Save("bmp.jpg");
I have as input a Ushort array of image data. Other inputs are gathered here, such as the 'Width, Height'. The ushort array also carries a Min and Max values, that I want to use, those are stored in 'io_current'.
I want to return a Format8ppIndexed Bitmap, and I have this code but what am I doing wrong?:
private Bitmap CreateBitmap(ushort[,] pixels16)
{
int width = pixels16.GetLength(1);
int height = pixels16.GetLength(0);
Bitmap bmp = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format8bppIndexed);
BitmapData bmd = bmp.LockBits(new Rectangle(0, 0, width, height),
System.Drawing.Imaging.ImageLockMode.ReadOnly, bmp.PixelFormat);
// This 'unsafe' part of the code populates the bitmap bmp with data stored in pixel16.
// It does so using pointers, and therefore the need for 'unsafe'.
unsafe
{
//int pixelSize = 4;
int i, j; //, j1; //, i1;
byte b;
ushort sVal;
double lPixval;
//The array has max and min constraints
int distance = io_current.MaximumValue - io_current.MinimumValue;
for (i = 0; i < bmd.Height; ++i)
{
byte* row = (byte*)bmd.Scan0 + (i * bmd.Stride);
//i1 = i * bmd.Height;
for (j = 0; j < bmd.Width; ++j)
{
sVal = (ushort)(pixels16[i, j]);
lPixval = ((sVal - io_current.MinimumValue) * 255) / distance; // Convert to a 255 value range
//lPixval = ((sVal - io_current.MinimumValue) / distance) * 255;
//lPixval = 255 - lPixval; //invert the value
if (lPixval > 255) lPixval = 255;
if (lPixval < 0) lPixval = 0;
b = (byte)(lPixval);
//j1 = j * pixelSize; //Pixelsize is one
row[j] = b; // Just one in 8bpp
//Not necessary for format8bppindexed
//row[j1] = b; // Red
//row[j1 + 1] = b; // Green
//row[j1 + 2] = b; // Blue
//row[j1 + 3] = 255; //No Alpha channel in 24bit
}
}
}
bmp.UnlockBits(bmd);
return bmp;
}
I'm getting a Black screen, or a one color screen. Basically no usable data is returned. Obviously from the comments. I tried to convert this from 24bit bitmap code and thought it would be easy.
I am trying to get all the pixels from a set image using LockBits and iterating through every pixel via for. But i am getting incorrect pixels. I exhilarate more in a second.
Code:
Bitmap bmp = new Bitmap(ImagePath);
pictureBox1.Image = bmp;
Rectangle bmpRec = new Rectangle(0, 0,
bmp.Width, bmp.Height); // Creates Rectangle for holding picture
BitmapData bmpData = bmp.LockBits(bmpRec,
ImageLockMode.ReadWrite,
PixelFormat.Format32bppArgb); // Gets the Bitmap data
IntPtr Pointer = bmpData.Scan0; // Set pointer
int DataBytes = Math.Abs(bmpData.Stride) * bmp.Height; // Gets array size
byte[] rgbValues = new byte[DataBytes]; // Creates array
Marshal.Copy(Pointer, rgbValues, 0, DataBytes); // Copies of out memory
StringBuilder Pix = new StringBuilder(" ");
// pictureBox1.Image = bmp;
StringBuilder EachPixel = new StringBuilder("");
for (int i = 0; i < bmpData.Width; i++)
{
for (int j = 0; j < bmpData.Height; j++)
{
var pixel = rgbValues[i + j * Math.Abs(bmpData.Stride)];
Pix.Append(" ");
Pix.Append(Color.FromArgb(pixel));
}
}
Now I have created a 2x2 pixel image of pure blue. My output should be
255 0 0 255 255 0 0 255 255 0 0 255 255 0 0 255
(A R G B)
but i get something like
Color [A=0, R=0, G=0, B=255] Color [A=0, R=0, G=0, B=255] Color [A=0, R=0, G=0, B=0] Color [A=0, R=0, G=0, B=0]
Where am I going wrong? Sorry if I can't explain exactly whats wrong. Basically the pixel output is incorrect and doesn't match up with the input bmp.
I'm not sure what exactly you're trying to do here... I think you misunderstand how Scan0 and Stride work. Scan0 is a pointer to the beginning of the image in memory. Stride is the length of each row in memory in bytes. You've already locked the image into memory with bmp.LockBits, you don't have to Marshal it.
Bitmap bmp = new Bitmap(ImagePath);
BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
StringBuilder sb = new StringBuilder();
unsafe
{
for (int y = 0; y < bmp.Height; y++)
{
byte* row = (byte*)bmpData.Scan0 + (y * bmpData.Stride);
for (int x = 0; x < bmp.Width; x++)
{
byte B = row[(x * 4)];
byte G = row[(x * 4) + 1];
byte R = row[(x * 4) + 2];
byte A = row[(x * 4) + 3];
sb.Append(String.Format("{0} {1} {2} {3} ", A, R, G, B);
}
}
}
Fixed the problem by changing what and how it outputs.
I now use Color ARGB = Color.FromArgb(A, R, G, B) I also now use a pixel array.
byte B = row[(x * 4)];
byte G = row[(x * 4) + 1];
byte R = row[(x * 4) + 2];
byte A = row[(x * 4) + 3];
I am trying to extract R G B values from a pixel in the following code:
for ( int i=0; i < pixeldata.length; i++)
{
IntPtr ptr = bmd.Scan0+i;
byte* pixel = (byte*)ptr;
//here is the problem :O
float r = pixel[1];
float g = pixel[2];
float b = pixel[3];
}
....
where bmd is an array of pixels data:
BitmapData bmd = source.LockBits(rect, ImageLockMode.ReadOnly, source.PixelFormat);
and source is the Bitmap of my input, which is an image.
I am trying to avoid the use of Color object. I have already done that and it works, I want to use this other way, but the issue is that ptr is a number and I have to extract the R G B from it.
This is the solution that gives you the right answer.
Bitmap source = new Bitmap(image);
Rectangle rect = new Rectangle(0, 0, source.Width, source.Height);
BitmapData bmd = source.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
int totalPixels = rect.Height * rect.Width;
int[] pixelData = new int[totalPixels];
for (int i = 0; i < totalPixels; i++)
{
byte* pixel = (byte*)bmd.Scan0;
pixel = pixel + (i * 4);
byte b = pixel[0];
byte g = pixel[1];
byte r = pixel[2];
int luma = (int)(r * 0.3 + g * 0.59 + b * 0.11);
pixelData[i] = luma;
}
If you have a format that stores R, G, and B as one byte each linearly in memory in that order, the code to extract the RGB values should look like
byte r = pixel[0];
byte g = pixel[1];
byte b = pixel[2];
Note that the index offset begins at 0, and that the values returned are byte not float (though you can certainly cast if you wish).
Additionally you would have to increment i by 3 rather than 1 because 3 adjacent bytes represent a single pixel.
You would be wise to test that source.PixelFormat indeed uses the format you are assuming.
You also have to compile with the /unsafe switch in order to use pointers in C#.
UPDATE
Per #Don's comment as well as your own, the order in linear memory would be ABGR. That means the code would be:
for ( int i=0; i < pixeldata.length; i+=4)
{
IntPtr ptr = bmd.Scan0+i;
byte* pixel = (byte*)ptr;
byte a = pixel[0]; // You can ignore if you do not need alpha.
byte b = pixel[1];
byte g = pixel[2];
byte r = pixel[3];
}
Ok, this was interesting, and I have written some code to play with. Assuming that your image has pixels in format Format24bppRgb (more info about formats here: http://msdn.microsoft.com/en-us/library/system.drawing.imaging.pixelformat.aspx). This format store B, G, R values in 24 bits one after another.
Below code which will parse some d:\\24bits.bmp image from your hard drive and creates new identical one "d:\\24bits_1.bmp" using information B, G, R information from bytes array of first image data.
unsafe private static void TestBMP()
{
Bitmap bmp = new Bitmap("d:\\24bits.bmp");
// Ensure that format is Format24bppRgb.
Console.WriteLine(bmp.PixelFormat);
Bitmap copyBmp = new Bitmap(bmp.Width, bmp.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
// Copy all pixels of initial image for verification.
int pixels = bmp.Height * bmp.Width;
Color[,] allPixels = new Color[bmp.Height, bmp.Width];
for (int i = 0; i < bmp.Height; i++)
for (int j = 0; j < bmp.Width; j++)
allPixels[i, j] = bmp.GetPixel(j, i);
// Lock the bitmap's bits.
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
System.Drawing.Imaging.BitmapData bmpData =
bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadOnly,
bmp.PixelFormat);
IntPtr ptr = bmpData.Scan0;
byte* stream = (byte*)ptr;
for (int y = 0; y < bmp.Height; y++)
for (int x = 0; x < bmp.Width; x++)
{
int byteIndex = y * bmpData.Stride + x * 3;
byte r = stream[byteIndex + 2];
byte g = stream[byteIndex + 1];
byte b = stream[byteIndex];
Color c = allPixels[y, x];
if (r != c.R || g != c.G || b != c.B)
{
Console.WriteLine("This should never appear");
}
copyBmp.SetPixel(x, y, Color.FromArgb(255, r, g, b));
}
// Save new image. It should be the same as initial one.
copyBmp.Save("d:\\24bits_1.bmp");
}