changing pixel color in C# - c#

hello i'm working on program that read whole image and change the color of green line to red line for example i have this image and i want the c# program get the green pixels and convert it to red
i tried this code : `
public Bitmap ReadImgPixel(Bitmap img)
{
Bitmap pic = new Bitmap(img,img.Width,img.Height);
int a1 = img.Width;
int a2 = img.Height;
System.Drawing.Color[,] pixels = new System.Drawing.Color[a1,a2];
for (int i = 0;i< img.Width ; i++)
{
for(int j=0; j < img.Height; j++)
{
System.Drawing.Color pxl = img.GetPixel(i, j);
if (pxl != System.Drawing.Color.White)
{
pic.SetPixel(i, j, System.Drawing.Color.Red);
}
}
}
return pic;
}
but the result was the whole image is changing to red how to fix it !!

Have you tried debugging (you could have easily found out why all pixels turned red)? Your whole picture turns red because the if statement is always true.
The reason this happens is because you are comparing structs. However, your pixel name will not say White (what you are comparing to), but it will contain a string with the hex value of your color (e.g. ffffff). So it is never equal, because the objects are different. Therefore, since you want to see if the ARGB values are the same, you have to compare these.
Change your statement to this to compare the ARGB values:
if (pxl.ToArgb() != Color.White.ToArgb())
Also make sure you check Cody Gray's comment, since your code is absolutely not efficient. If efficiency is important to you, try a different approach, but that's outside the scope of this question.

Related

C# How to keep 1 range of colors in a bitmap?

So in c# I have an image in a bitmap with different colors in it. Now i'm trying to only keep one single range of colors in the image and all the others can be removed (turn them into white pixels). Now the color I want to extract is yellow but just comparing the pixels their color with Color.Yellow won't suffice since the pixels can have different shades of yellow so I'm guessing I sort of need to filter out all the other colors but I can't seem to figure out on how to do it.
I've read something about convolution but I don't see a way to implement this directly into the program.
Is there a way that makes this possible that I only keep the color yellow and it's diffent shades in the image?
Thanks in advance.
Here is a fast and simple solution.
It uses a function, which will plug-in with a post you can find here.
This is the function:
public Color ToWhiteExceptYellow(Color c, int range)
{
float hueC = c.GetHue();
float e = 1.5f * range; // you can adapt this nuumber
float hueY = Color.Yellow.GetHue();
float delta = hueC - hueY;
bool ok = (Math.Abs(delta) < e);
//if (!ok) { ok = (Math.Abs(360 + delta) < e); } // include these lines ..
//if (!ok) { ok = (Math.Abs(360 - delta) < e); } // for reddish colors!
return ok ? c : Color.White;
}
It works well with yellow but as color hues is a wraparound number it will need more code to work with the wrap point color (red). I have included two lines to help out.
To make it work change these lines in the linked post:
// pick one of our filter methods
ModifyHue hueChanger = new ModifyHue(ToWhiteExceptYellow);
..and..
// we pull the bitmap from the image
Bitmap bmp = new Bitmap( (Bitmap)pictureBox1.Image); // create a copy
..and..
c = hueChanger(c, trackBar1.Value); // insert a number you like, mine go from 1-10
..and..:
// we need to re-assign the changed bitmap
pictureBox2.Image = (Bitmap)bmp; // show in a 2nd picturebox
Don't forget to include the delegate:
public delegate Color ModifyHue(Color c, int ch);
and the using clause:
using System.Drawing.Imaging;
Note that one ought to dispose of the old content to avoid leaking the images, maybe like so:
Bitmap dummy = (Bitmap )pictureBox2.Image;
pictureBox2.Image = null;
if (dummy != null) dummy.Dispose;
// now assign the new image!
Let's see it at work:
Feel free to expand on this. You could change the function's signature to include a target color and add ranges for brightness and/or saturation..
very vague definition,
if i understood what you want to do, i'd do it like this:
Iterate over every pixel of the bitmap and compare it to the yellow range (if outside - assign white value)
Convert every pixels RGB value to CMYK (search online for a conversion formula) [Y = (1-Blue-Black) / (1-Black)]
Assign white value if YellowMin
Convolution wont help you, it acts in spacial domain not in color

How can I can the integer value (range 0-255) of a grayscale image pixel

Hi I want to get the integer values (0-255 range) of a gray scale image ....this code shows me the R,G,B values not one value..how can i get it?
Bitmap temp1 = image1;
for (int i = 0; i < temp1.Height; i++)
{
for (int j = 0; j < temp1.Width; j++)
{
Color cl = new Color();
cl = temp1.GetPixel(i, j);
}
}
just read the properties R or G or B, any of them will have the same value.
var intValue = cl.R;
If your source image is greyscale and you just want the level of greyness, just pick any of the three components. They will be equal.
If your source image is color but you want to get the grey equivalent, you can convert your color to a grey value in the range 0..255 by blending the red, green and blue color components together. The blending factors are different because the human eye has different sensitivity to the three primary colors. For fun, try varying the factors (e.g. use 0.3333 for each) and see what the result looks like.
Color cl = c.GetPixel(i, j); // No need to separately allocate a new Color()
int greyValue = (int)((cl.R * 0.3) + (cl.G * 0.59) + (cl.B * 0.11));
Color grey = Color.FromArgb(cl.A, greyValue, greyValue, greyValue);
Note that it is quite slow to loop through a larger Bitmap, using GetPixel() on each pixel. There are much faster techniques available.
UPDATE
Here's an example image with different scaling factors for R, G, and B applied. The image will always be greyscaled because the same numeric value is used for each RGB component in the modified image, but the relative lightness does change. The middle image uses scaling factors suitable for the human eye. Note how blue areas in the original image seem oversaturated in the rightmost version.
There are multiple ways to get grayscale from RGB.
A common way is to do (R+G+B)/3
Others are computing some luminance Luminance measure (Lab, YUV, HSV)

Reduce the gray scale bit representation of a pixel in C#

I am sorry if the question in the header is not descriptive enough. But, basically what my problem is the following.
I am taking Bitmap and making it gray scale. It works nice if i do not reduce the number of bits and I still use 8 bits. However, the point of the hw I have is to show how the image changes when I reduce the number of bits holding the information. In the example bellow I am reducing the binary string to 4 bits and then rebuilding the image again. The problem is that the image becomes black. I think is because the image has mostly gray values (in the 80's range) and when I am reducing the binary string I am left with black image only. It seems to me that i heave to check for lower and high gray scale values and then make the more light-gray go to white and dark gray go to black. In the end with 1 bit representation I should only have black and white image.Any idea how can i do that separation?
Thanks
Bitmap bmpIn = (Bitmap)Bitmap.FromFile("c:\\test.jpg");
var grayscaleBmp = MakeGrayscale(bmpIn);
public Bitmap MakeGrayscale(Bitmap original)
{
//make an empty bitmap the same size as original
Bitmap newBitmap = new Bitmap(original.Width, original.Height);
for (int i = 0; i < original.Width; i++)
{
for (int j = 0; j < original.Height; j++)
{
//get the pixel from the original image
Color originalColor = original.GetPixel(i, j);
//create the grayscale version of the pixel
int grayScale = (int)((originalColor.R * .3) + (originalColor.G * .59)
+ (originalColor.B * .11));
//now turn it into binary and reduce the number of bits that hold information
byte test = (byte) grayScale;
string binary = Convert.ToString(test, 2).PadLeft(8, '0');
string cuted = binary.Remove(4);
var converted = Convert.ToInt32(cuted, 2);
//create the color object
Color newColor = Color.FromArgb(converted, converted, converted);
//set the new image's pixel to the grayscale version
newBitmap.SetPixel(i, j, newColor);
}
}
return newBitmap;
}
As mbeckish said, it is easier and much faster to use ImageAttributes.SetThreshold.
One way to do it manually is to get the median value of the grayscale pixels in the image, and use that for the threshold between black and white.

Replacing a color C#

I'm working on a program to generate a bitmap, which first generates a river in a blue color( Color.Blue). Now to test if the program can actually check for the same colors, so that I can replace it, I created a function that replaces the Color.Blue with Color.Yellow. The problem is that when I generate the Bitmap with the river, and then try to replace it with the other color, it can't seem to recognize the blue color, and for that matter replace it either. This is a really weird bug, and I can't seem to figure exactly what goes wrong. And I'm pretty sure it generates the river in the correct color.
Here is my color replacement code:
The "river" variable is equal to Color.Blue.
private void button2_Click(object sender, EventArgs e)
{
for (int x = 0; x < 20; x++) {
for (int y = 0; y < 20; y++) {
Color tempCol = city.GetPixel(x, y);
if (tempCol == river) {
city.SetPixel(x, y, Color.Yellow);
}
}
}
pictureBox1.Image = city;
MessageBox.Show("Done");
}
The problem is in how you compare the colors. If you look at the documentation, it says:
This structure only does comparisons with other Color structures. To
compare colors based solely on their ARGB values, you should use the
ToArgb method. This is because the Equals and Equality members
determine equivalency using more than just the ARGB value of the
colors.
For example, Black and FromArgb(0,0,0) are not considered
equal, since Black is a named color and FromArgb(0,0,0) is not.
A better comparison is thus:
if (tempCol.ToArgb() == river.ToArgb())
{
city.SetPixel(x, y, Color.Yellow);
}

How to find Black Pixel locations

I'm working on a strange project. I have access to a laser cutter that I am using to make stencils (from metal). I can use coordinates to program the machine to cut a certain image, but what I was wondering was: how can I write a program that would take a scanned image that was black and white, and give me the coordinates of the black areas? I don't mind if it gives every pixel even though I need only the outer lines, I can do that part.
I've searched for this for a while, but the question has so many words with lots of results such as colors and pixels, that I find tons of information that isn't relevant. I would like to use C++ or C#, but I can use any language including scripting.
I used GetPixel in C#:
public List<String> GetBlackDots()
{
Color pixelColor;
var list = new st<String>();
for (int y = 0; y < bitmapImage.Height; y++)
{
for (int x = 0; x < bitmapImage.Width; x++)
{
pixelColor = bitmapImage.GetPixel(x, y);
if (pixelColor.R == 0 && pixelColor.G == 0 && pixelColor.B == 0)
list.Add(String.Format("x:{0} y:{1}", x, y));
}
}
return list;
}
If we assume that the scanned image is perfectly white and perfectly black with no in-between colors, then we can just take the image as an array of rgb values and simply scan for 0 values. If the value is 0, it must be black right? However, the image probably won't be perfectly black, so you'll want some wiggle room.
What you do then would look something like this:
for(int i = 0; i < img.width; i++){
for(int j = 0; j < img.height; j++){
// 20 is an arbitrary value and subject to your opinion and need.
if(img[i][j].color <= 20)
//store i and j, those are your pixel location
}
}
Now if you use C#, it'll be easy to import most image formats, stick em in an array, and get your results. But if you want faster results, you'd be better off with C++.
This shortcut relies completely on the image values being very extreme. If large areas of your images are really grey, then the accuracy of this approach is terrible.
While there are many solutions in many languages, I'll outline a simple solution that I would probably use myself. There is a imaging great library for Python called PIL (Python Imaging Library - http://www.pythonware.com/products/pil/) which could accomplish what you need very easily.
Here's an example of something that might help you get started.
image = Image.open("image.png")
datas = image.getdata()
for item in datas:
if item[0] < 255 and item[1] < 255 and item[2] < 255 :
// THIS PIXEL IS NOT WHITE
Of course that will count any pixel that is not completely white, you might want to add some padding so pixels which are not EXACTLY white also get picked up as being white. You'll also have to keep track of which pixel you are currently looking at.

Categories