It possible get cutout of image data.
If I know:
byte[] ImageData;
int width;
int height;
Basically I try find how get inner section of image from byte[] source.
For example I have image which is w: 1000px and h: 600px. And I want byte[] middle section 200*200px in byte[].
First of all you need to know how many bytes in your array represent one pixel. The following assumes that you have an RGB image with 3 bytes per pixel.
Then, the array-index of the first byte that represents the top-left corner of your cutout is represented as
int i = y * w + x
where y is the y-coordinate of the cutout, w is the width of the entire image and x is the x coordinate of the cutout.
Then, you can do as follows:
// cw: The width of the cutout
// ch: The height of the cutout
// x1/y1: Top-left corner coordinates
byte[] cutout = new byte[cw * ch * 3]; // Byte array that takes the cutout bytes
for (int cy = y1; cy < y2; cy++)
{
int i = cy * w + x1;
int dest = (cy - y1) * cw * 3;
Array.Copy(imagebytes, i, cutout, dest, cw * 3);
}
This iterates from the first to the last row to be cut out. Then, in i, it calculates the index of the first byte of the row in the image that should be cutout. In dest it calculates the index in cutout to which the bytes should be copied.
After that it copies the bytes for the current row to be cut out into cutout at the specified position.
I have not tested this code, really, but something like that should work. Also, please note that there's currently no range checking - you need to make sure that the location and dimensions of the cutout are really within the bounds of the image.
If you can convert it to an an image first, you can use this code I found on Bytes.Com
The following code works for me. It loads a .gif, draws the 30 x 30
section of the gif into an offscreen bitmap, and then draws the scaled
image into a picturebox.
System.Drawing.Image img=... create the image from the bye array ....
Graphics g1 = pictureBox1.CreateGraphics();
g1.DrawImage(img, 0, 0, img.Width, img.Height);
g1.Dispose();
Graphics g3 = Graphics.FromImage(bmp);
g3.DrawImageUnscaled(img, 0, 0, bmp.Width, bmp.Height);
Graphics g2 = pictureBox2.CreateGraphics();
g2.DrawImageUnscaled(bmp, 0, 0, bmp.Width, bmp.Height);
g2.Dispose();
g3.Dispose();
img.Dispose();
You can use this question to turn your byte[] into an image : Convert a Byte array to Image in c# after modifying the array
Related
Hi I'm trying to crop images that users upload onto my site into a square. I have already tried a few solutions posted on this website, namely http://stackoverflow.com/questions/5222711/image-resize-in-c-sharp-algorith-to-determine-resize-dimensions-height-and-wi and WebImage Crop To Square. However, although these solutions convert the image into a square, they add large areas of transparency on the top and bottom of the image, which is not what I want since these images will be used as profile images.
This is the code I have always used in my websites:
public Bitmap MakeSquarePhoto(Bitmap bmp, int size)
{
try
{
Bitmap res = new Bitmap(size, size);
Graphics g = Graphics.FromImage(res);
g.FillRectangle(new SolidBrush(Color.White), 0, 0, size, size);
int t = 0, l = 0;
if (bmp.Height > bmp.Width)
t = (bmp.Height - bmp.Width) / 2;
else
l = (bmp.Width - bmp.Height) / 2;
g.DrawImage(bmp, new Rectangle(0, 0, size, size), new Rectangle(l, t, bmp.Width - l * 2, bmp.Height - t * 2), GraphicsUnit.Pixel);
return res;
}
catch { }
}
To crop an image without adding large patches of transparency to the top and bottom, you are going to have to cut off part of the sides. Without seeing the code it should be something along the lines of cutting off (width-height)/2 pixels from each side.
My professor kind of "challenged me" to create an application that draws pixel by pixel an image converted in Bitmap, where it's data is saved in some sort of binary that I can't wrap my head around.
Here's the example given to me:
const byte image[]={
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
ect ect ect
Now, if the byte data type saves numbers that go from 0 to 255, how is this possible? In the sample code that I was given, there is also the use of "Word" data type but in my IDE it seems like it doesn't exist.
I already wrote the code that converts any image given in input into a bitmap:
FileStream fs = new FileStream(openFileDialog1.FileName, FileMode.Open, FileAccess.Read); //Path is image location
Byte[] bindata = new byte[Convert.ToInt32(fs.Length)];
fs.Read(bindata, 0, Convert.ToInt32(fs.Length));
Bitmap bmp;
using (var ms = new MemoryStream(bindata))
{
bmp = new Bitmap(ms);
}
pictureBox1.Image = bmp; //For now, I just display the converted image on screen
Now I suppose that the next step is to draw the image byte per byte, but I can't get my head around this binary thing and the word data type.. Any kind of help is appreciated :)
if you just want to draw a bitmap pixel at a time, you can do something like this:
Bitmap b = new Bitmap(10, 10);
b.SetPixel(0, 0, Color.Black);
b.SetPixel(1, 3, Color.Red);
pictureBox1.Image = b;
You can just copy your bytes to the Bitmap's memory buffer itself.
BitmapData bufferData = buffer.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
for (int x = 0; x < width; x++)
for (int y = 0; y < height; y++)
bufferData.SetPixel(x, y, CELL_DEAD);
buffer.UnlockBits(bufferData);
//////////
public static unsafe void SetPixel(BitmapData data, int x, int y, byte pixel)
{
*((byte*)data.Scan0 + y * data.Stride + x) = pixel;
}
I've used it as unsafe but you can play your magic with IntPtr. Of course, you must play your own with width-height synchronization.
UPD: set PixelFormat with care. PixelFormat.Format8bppIndexed is what you need if your colors are in default 256-color palette or you want to define your own palette.
I have three array of byte stored three colors (Red, Green, Blue), how can I display this array in picture box in c#, and type of file is bitmap file for image
byte[,] R=new byte[width, height];
byte[,] G=new byte[width, height];
byte[,] B=new byte[width, height];
these three array are not empty ,there are data stored in each array.
You mean:
Bitmap bmp = new Bitmap(width,height);
for(int i=0;i<width;i++)
for(int j=0;j<height;j++) {
SetPixel(i,j,Color.FromArgb(R[i,j],G[i,j],B[i,j]));
}
picturebox.image=bmp;
You have to build a single byte array from the data, which isn't going to be very fast since you have to interleave the data. Basically, you'd do something like this:
var bytes= new byte[width * height * 4];
for (var x = 0; x < width; x++)
for (var y = 0; y < height; y ++)
{
bytes[(x + y * width) * 4 + 1] = R[x, y];
bytes[(x + y * width) * 4 + 2] = G[x, y];
bytes[(x + y * width) * 4 + 3] = B[x, y];
}
And you can then use the byte array to create a bitmap, like this:
var bmp = new Bitmap(width, height);
var data = bmp.LockBits(new Rectangle(0, 0, width, height), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb)
Marshal.Copy(bytes, 0, data.Scan0, width * height * 4);
bmp.UnlockBits(data);
Note that you should ensure that bmp.UnlockBits is always called, so you should probably put it in a finally block.
This isn't necessarily the best or fastest way, but that depends on your needs anyway :)
If you're really going for the fastest way, you'd probably use unsafe code (not because it's faster by itself, but rather because the .NET Bitmap is not natively-managed - it's a managed wrapper for an unmanaged bitmap). You'd allocate the memory for the byte array on the unmanaged heap, then you'd fill in the data and create a bitmap using the constructor that takes an IntPtr scan0 as a parameter. If done correctly, it should avoid unnecessary array boundary checks, as well as unnecessary copying.
I have the following code which takes an array of bytes which i generated and writes them out to this bitmap. If i set the pixel format to Format4bppIndexed, then i get a readable image repeating width wise 4 times, if i set it to Format1bppIndexed(which is the correct setting) then i get one big unreadable image.
The image was a decoded Jbig2 image , i know the bytes are correct i can't seem to figure out how to get it into a 1bpp readable format.
Does anyone have any advice on that matter
Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format1bppIndexed);
//Create a BitmapData and Lock all pixels to be written
BitmapData bmpData = bitmap.LockBits(
new Rectangle(0, 0, bitmap.Width, bitmap.Height),
ImageLockMode.WriteOnly, bitmap.PixelFormat);
//Copy the data from the byte array into BitmapData.Scan0
Marshal.Copy(newarray, 0, bmpData.Scan0, newarray.Length);
//Unlock the pixels
bitmap.UnlockBits(bmpData);
The following may work although, if I remember correctly, Stride sometimes has an effect and a simple block-copy won't suffice (line by line must be used instead).
Bitmap bitmap = new Bitmap(
width,
height,
System.Drawing.PixelFormat.Format16bppGrayScale
);
To handle the Stride you'd want:
BitmapData^ data = bitmap->LockBits(oSize,
ImageLockMode::ReadOnly, bitmap->PixelFormat);
try {
unsigned char *pData = (unsigned char *)data->Scan0.ToPointer();
for( int x = 0; x < bmpImage->Width; ++x )
{
for( int y = 0; y < bmpImage->Height; ++y )
{
// Note: Stride is data width of scan line rounded up
// to 4 byte boundary.
// Requires use of Stride, not (width * pixelWidth)
int ps = y*bmpImage->Width*(nBitsPerPixel / 8)
+ x * (nBitsPerPixel / 8);
int p = y * data->Stride + x * (nBitsPerPixel / 8);
Byte lo = newarray[ps + 1];
Byte hi = newarray[ps + 0];
pData[p + 1] = lo;
pData[p + 0] = hi;
}
}
} finally {
bmpImage->UnlockBits(data);
}
Note: This was written in C++/CLI. Let me know if you need C# equivalents for any of the operations here. (Also, I pulled it from a read from bitmap rather than a write to bitmap so it may yet be a bit rough, but should hopefully give you the idea...)
I figured this out Although i'm still not sure why it should matter.
Based on this stackoverflow posting How can I load the raw data of a 48bpp image into a Bitmap?
I used the WPF classes instead of the GDI and wrote the code like this
var bitmap = new WriteableBitmap(width, height, 96, 96, System.Windows.Media.PixelFormats.BlackWhite, null);
bitmap.WritePixels(new System.Windows.Int32Rect(0, 0, width, height), newarray, stride, 0);
MemoryStream stream3 = new MemoryStream();
var encoder = new TiffBitmapEncoder ();
encoder.Frames.Add(BitmapFrame.Create(bitmap));
encoder.Save(stream3);
This correctly creates the image.
If anyone has any insight into why this might be the case please comment below
The port which now mostly works(lots of cleanup code) was based on a java implementation of JPedal Big2 Decoder to .NET. If anyone knows anyone interested send them here
https://github.com/devteamexpress/JBig2Decoder.NET
MSDN reference: [1] http://msdn.microsoft.com/en-us/library/5ey6h79d.aspx#Y1178
From the link it says that the first argument will "specifies the portion of the Bitmap to lock" which I set to be a smaller part of the Bitmap (Bitmap is 500x500, my rectangle is (0,0,50,50)) however the returned BitmapData has stride of 1500 (=500*3) so basically every scan will still scan through the whole picture horizontally. However, what I want is only the top left 50x50 part of the bitmap.
How does this work out?
The stride will always be of the full bitmap, but the Scan0 property will be different according to the start point of the lock rectangle, as well as the Height and Width of the BitmapData.
The reason for that is that you will still need to know the real bit-width of the bitmap, in order to iterate over the rows (add stride to address).
A simple way to go about it would be:
var bitmap = new Bitmap(100, 100);
var data = bitmap.LockBits(new Rectangle(0, 0, 10, 10),
ImageLockMode.ReadWrite,
bitmap.PixelFormat);
var pt = (byte*)data.Scan0;
var bpp = data.Stride / bitmap.Width;
for (var y = 0; y < data.Height; y++)
{
// This is why real scan-width is important to have!
var row = pt + (y * data.Stride);
for (var x = 0; x < data.Width; x++)
{
var pixel = row + x * bpp;
for (var bit = 0; bit < bpp; bit++)
{
var pixelComponent = pixel[bit];
}
}
}
bitmap.UnlockBits(data);
So it is basically really just locking the whole bitmap, but giving you a pointer to the top-left pixel of the rectangle in the bitmap, and setting the scan's width and height appropriately.