I have been trying to create a grayscale bitmap which it's pixels are filled by my own array of colors. This two dimensional array comes from a process that gets and manipulates every single pixel of an colored image. In other words i am trying to prepare a method to convert a colored one to it's grayscale.
This is How i get the pixel's values and calculate the average
for (var i = 0; i < SharedImg.ImgBitmap.Width;i++)
{
for (var j = 0; j < SharedImg.ImgBitmap.Height; j++)
{
var pix= SharedImg.ImgBitmap.GetPixel(i, j);
var red = (int) pix.R;
var green = (int) pix.G;
var blue = (int) pix.B;
var avrg = (red + green + blue)/3;
var rgb = Color.FromArgb(avrg, avrg, avrg);
arrColors[i, j] = rgb;
}
}
Now it fills the new bitmap with the array
var imgBitmap=new Bitmap(width,height,PixelFormat.Format16bppGrayScale);
for(var i=0 ; i<width;i++)
for (var j = 0; j < height; j++)
{
try
{
imgBitmap.SetPixel(i, j, arrColors[i, j]);
}
catch (Exception exception)
{
mainForm.UpdateNewLine(new SystemResponse(){Color = Color.Red,State = exception.ToString()});
}
}
When it reaches the SetPixel method it throws an ArgumentException.
Any idea or tip ?
Related
i try to take surf algorithm in matlab and to convert it in c#.
The algorithm in matlab returns array of coordinates. The size of the array is [10,4].
In c# i wrote a code that doesnt returns the right information in the array.
Am i missed something when i converted this code?
private static void Main(string[] args)
{
Bitmap img1 = new Bitmap(Image.FromFile(#"C:\Users\cbencham\source\repos\3.jpg"));
Bitmap img2 = new Bitmap(Image.FromFile(#"C:\Users\cbencham\source\repos\4.jpg"));
//Get image dimensions
int width = img1.Width;
int height = img1.Height;
//Declare the double array of grayscale values to be read from "bitmap"
double[,] im1 = new double[width, height];
//Loop to read the data from the Bitmap image into the double array
int i, j;
for (i = 0; i < width; i++)
{
for (j = 0; j < height; j++)
{
Color pixelColor = img1.GetPixel(i, j);
double b = pixelColor.GetBrightness(); //the Brightness component
//Note that rows in C# correspond to columns in MWarray
im1.SetValue(b, i, j);
}
}
//Get image dimensions
width = img2.Width;
height = img2.Height;
//Declare the double array of grayscale values to be read from "bitmap"
double[,] im2 = new double[width, height];
//Loop to read the data from the Bitmap image into the double array
for (i = 0; i < width; i++)
{
for (j = 0; j < height; j++)
{
Color pixelColor = img2.GetPixel(i, j);
double b = pixelColor.GetBrightness(); //the Brightness component
//Note that rows in C# correspond to columns in MWarray
im2.SetValue(b, i, j);
}
}
MLApp.MLApp matlab = new MLApp.MLApp();
matlab.Execute(#"cd C:\Users\cbencham\source\repos");
object result = null;
matlab.Feval("surf", 1, out result, im1, im2);
// TODO: convert result to double Array [10,4]
for (i = 0; i < 10; i++)
{
for (j = 0; j < 4; j++)
{
Console.Write(arr[i, j]);
}
Console.WriteLine();
}
Console.ReadLine();
}
}
}
You can't convert an object array to a double array. But for your purpose you don't need to. You just need to cast it to and object array and print its contents.
var arr = result as object[,];
or
if (result is object[,] arr)
{
for (i = 0; i < arr.GetLength(0); i++)
{
for (j = 0; j < arr.GetLength(1); j++)
{
Console.Write(arr[i, j]);
}
Console.WriteLine();
}
Console.ReadLine();
}
I am trying to create a simple image format, which writes for every pixel the argb color to a file, I used this code to get and set all
List<Color> pixels = new List<Color>();
Bitmap img = new Bitmap("*imagePath*");
for (int i = 0; i < img.Width; i++)
{
for (int j = 0; j < img.Height; j++)
{
Color pixel = img.GetPixel(i,j);
pixels.Add(pixel);
}
}
from:
How can I read image pixels' values as RGB into 2d array?
And then I write every pixel on a new line:
foreach(Color p in pixels)
{
streamWriter.WriteLine(p.ToArgb)
}
streamWriter.Close();
and then if I try to read it:
OpenFileDialog op = new OpenFileDialog();
op.ShowDialog();
StreamReader sr = new StreamReader(op.FileName);
int x = 1920;
int y = 1080;
Bitmap img = new Bitmap(x,y);
for (int i = 0; i < img.Width; i++)
{
string rl = sr.ReadLine();
for (int j = 0; j < img.Height; j++)
{
img.SetPixel(i, j, Color.FromArgb(Int32.Parse(rl)));
}
}
pictureBox1.Image = img;
but from this bmp file,
I get this output:
does someone knows how to fix this?
thanks in advance.
When you write the pixels, you are writing each one in a separate line. However, when reading, you are reading a single line per column, and then using that same color value for every row of the column.
instead, call ReadLine inside the innermost loop.
for (int i = 0; i < img.Width; i++)
{
for (int j = 0; j < img.Height; j++)
{
string rl = sr.ReadLine();
img.SetPixel(i, j, Color.FromArgb(Int32.Parse(rl)));
}
}
Needless to add, this image format is incredibly inefficient in terms of space, and in it's current implementation also in read and write performance. You would be wise to use it only as a learning exercise.
I wanted to split a splitted string in C#.
Basically, I want to save an image in a form of numbers, here are the code to save it to a number in C# using GetPixel
TextWriter textWriter = new StreamWriter(fileName);
for (int x = 0; x < bmp.Width; x++)
{
for (int y = 0; y < bmp.Height; y++)
{
Color pixel = bmp.GetPixel(x, y);
textWriter.Write(pixel.R + "," + pixel.G + "," + pixel.B + " ");
}
}
and here is a possible result: 252,255,192 252,255,192 252,255,192.
The pixel is separated by a space, and the rgb is separated by a comma.
the problem is when i tried to convert this again into an image, here is my current code to get the rgb of a pixel.
TextReader textReader = new StreamReader(fileName);
string allLine = textReader.ReadLine();
string[] splitPixel = allLine.Split(' ');
string[] splitRGB = null;
for (int i=0; i<splitPixel.Length; i++) {
splitRGB[i] = splitPixel[i].Split(',');
}
and here is the code to set the pixel color
for (int x = 0; x < bmp.Width; x++)
{
for (int y = 0; y < bmp.Height; y++)
{
byte tempR, tempG, tempB = 0;
tempR = Convert.ToByte(splitRGB[x]);
tempG = Convert.ToByte(splitRGB[x+1]);
tempB = Convert.ToByte(splitRGB[x+2]);
Color pixel = Color.FromArgb(tempR,tempG,tempB);
bmp.SetPixel(x, y, pixel);
}
}
Right now it's only telling me this error "Cannot implicitly convert type 'string[]' to 'string'" for the
splitRGB[i] = splitPixel[i].Split(',')
string[] splitPixel = allLine.Split(' ');
string[] splitRGB = new string[splitPixel.Length * 3];
for (int i=0; i<splitRGB.Length; i+=3) {
string[] splitted = splitPixel[i].Split(',');
splitRGB[i] = splitted[0];
splitRGB[i + 1] = splitted[1];
splitRGB[i + 2] = splitted[2];
}
EDIT: Here is a better version:
You should save the width and height of your image in the file (ie: 2x2 images have the same file format as 4*1 images), here I suggest that you save them in the first line as width height
using (TextReader textReader = new StreamReader(fileName)){
string sizeLine = textReader.ReadLine();
if (sizeLine == null)
throw new /*UnexpectedData*/Exception("invalid file!");
string[] widthHeightStr = sizeLine.Split(' ');
if (widthHeightStr.Length != 2)
throw new /*UnexpectedData*/Exception("invalid file!");
int width = int.Parse(widthHeightStr[0]);
int height = int.Parse(widthHeightStr[1]);
string pixelsLine = textReader.ReadLine();
if (onlyLine == null)
throw new /*UnexpectedData*/Exception("invalid file!");
string[] splitPixel = pixelsLine.Split(' ');
var bmp = new Bitmap(width, height);
for (int i=0; i<splitPixel.Length; i++) {
string[] splitted = splitPixel[i].Split(',');
if (splitted.Length != 3)
throw new /*UnexpectedData*/Exception("invalid file!");
int tempR = int.Parse(splitted[0]);
int tempG = int.Parse(splitted[1]);
int tempB = int.Parse(splitted[2]);
Color pixel = Color.FromArgb(tempR,tempG,tempB);
bmp.SetPixel(i / width, i % width, pixel);
}
}
EDIT:
using (TextWriter textWriter = new StreamWriter(fileName){
textWriter.WriteLine(bmp.Width + " " + bmp.Height);
for (int x = 0; x < bmp.Width; x++)
{
for (int y = 0; y < bmp.Height; y++)
{
Color pixel = bmp.GetPixel(x, y);
textWriter.Write(pixel.R + "," + pixel.G + "," + pixel.B + " ");
}
}
}
the error is simply explained you are trying to put an array (since split returns an array) in a string since splitRGB[i] is a string where as splitRGB[] = splitPixel[i].Split(','); or splitRGB[i][] = splitPixel[i].Split(','); <- where splitRGB[][] = new splitRGB[10][3] would work
so your code:
for (int i=0; i<splitPixel.Length; i++)
{
splitRGB[i] = splitPixel[i].Split(',');
}
if you want to put an array in a array you need multi-dimensional arrays like so:
string[][] splitRGB = new string[splitPixel.Length][3];
and the for loop to get your RGB values in
for (int i=0; i
for (int x = 0; x < bmp.Width; x++)
{
for (int y = 0; y < bmp.Height; y++)
{
byte tempR, tempG, tempB = 0;
tempR = Convert.ToByte(splitRGB[x][0]);
tempG = Convert.ToByte(splitRGB[x][1]);
tempB = Convert.ToByte(splitRGB[x][2]);
Color pixel = Color.FromArgb(tempR,tempG,tempB);
bmp.SetPixel(x, y, pixel);
}
}
the changes are very subtle and i've got the feeling i have made a mistake my self (i never use multi dimensional arrays i create arrays of structs or classes as much as i can)
Since i dont know what you do with the bitmap,i present you with another way to get the bitmap data to file and back in one go(you can split this to acomodate your needs).
I replace setPixel and GetPixel because they are too slow of a way to access the data,this will provide much faster outcome:
//assume you have a class member variable of type bitmap called sourceBitmap.
BitmapData sourceData = sourceBitmap.LockBits(new Rectangle(0, 0,
sourceBitmap.Width, sourceBitmap.Height),
ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
byte[] pixelBuffer = new byte[sourceData.Stride * sourceData.Height];
Marshal.Copy(sourceData.Scan0, pixelBuffer, 0, pixelBuffer.Length);
sourceBitmap.UnlockBits(sourceData);
File.WriteAllBytes(#"C:\..\..\test.txt", pixelBuffer);
//here is where you can split the code...
byte[] fs = File.ReadAllBytes(#"C:\..\..\test.txt");
Bitmap resultBitmap = new Bitmap(sourceBitmap.Width, sourceBitmap.Height);
BitmapData resultData = resultBitmap.LockBits(new Rectangle(0, 0,
resultBitmap.Width, resultBitmap.Height),
ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
Marshal.Copy(fs, 0, resultData.Scan0, fs.Length);
resultBitmap.UnlockBits(resultData);
pictureBox1.Image = resultBitmap;
I want to convert an image into a multidimensional array with 0's and 1's.
The image would be:
I wan't to store this image into an array with 'black' being stored as 1 and 'white' being stored as 0 in the array. The array would be of 8 rows and 6 columns:
int[,] imgArray = new int[8,6];
Is there a way to achieve this in C#?
If you are using a Bitmap, you can populate the array like this:
var bitmap = new Bitmap(#"C:\MyImage.png");
var imgArray = new int[bitmap.Width,bitmap.Height];
var blackArgb = Color.Black.ToArgb();
var whiteArgb = Color.White.ToArgb();
for (var i = 0; i < bitmap.Width; ++i)
{
for (var j = 0; j < bitmap.Height; ++j)
{
var pixelCol = bitmap.GetPixel(i, j);
if (pixelCol.ToArgb() == blackArgb)
{
imgArray[i, j] = 1;
}
else if (pixelCol.ToArgb() == whiteArgb)
{
imgArray[i, j] = 0;
}
else
throw new InvalidOperationException("Pixel color must be black or white");
}
}
I am writing a class for printing bitmaps to a portable bluetooth printer in Android via Mono For Android. My class is used to obtain the pixel data from the stream so that is can be sent to the printer in the correct format. Right now the class is simple, it just reads the height, width, and bits per pixel.
Using the offset it reads and returns the pixel data to the printer. Right now I am just working with 1 bit per pixel black and white images. The bitmaps I am working with are in Windows format.
Here is the original image:
Here is the result of printing, the first image is without any transformation. And the second one is the result of modifying the BitArray with the following code:
BitArray bits = new BitArray(returnBytes);
BitArray flippedBits = new BitArray(bits);
for (int i = 0, j = bits.Length - 1; i < bits.Length; i++, j--)
{
flippedBits[i] = bits[j];
}
My Question is:
How do I flip the image vertically when I am working with a byte array. I am having trouble finding the algorithm for doing this, all examples seem to suggest using established graphics libraries which I cannot use.
Edit:
My Bitmap is saved in a 1 dimensional array, with the first rows bytes, then the second, third, etc.
You need to do something like this:
BitArray bits = new BitArray(returnBytes);
BitArray flippedBits = new BitArray(bits);
for (int i = 0; i < bits.Length; i += width) {
for (int j = 0, k = width - 1; j < width; ++j, --k) {
flippedBits[i + j] = bits[i + k];
}
}
If you need to mirror picture upside-down, use this code:
BitArray bits = new BitArray(returnBytes);
BitArray flippedBits = new BitArray(bits);
for (int i = 0, j = bits.Length - width; i < bits.Length; i += width, j -= width) {
for (int k = 0; k < width; ++k) {
flippedBits[i + k] = bits[j + k];
}
}
For the format with width*height bits in row order, you just need to view the bit array as a two-dimensional array.
for(int row = 0; row < height; ++row) {
for(int column = 0; column < width; ++column) {
flippedBits[row*width + column] = bits[row*width + (width-1 - column)];
}
}
It would be a bit more complicated if there were more than one bit per pixel.
You need to use two loops, the first to iterate over all the rows and the second to iterate the pixels inside each row.
for (int y = 0; y < height; y++)
{
int row_start = (width/8) * y;
int flipped_row = (width/8) * (height-1 - y);
for (int x = 0; x < width/8; x++)
{
flippedBits[flipped_row+x] = bits[row_start+x];
}
}