Replacing a color C# - 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);
}

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

changing pixel color in 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.

C# PixelComparison between images

I'm trying to compare between 2 images,actually 2 screen shots i took from my destkop. These are the images
I wanted to check for changed pixels,so this is a simple method i wrote:
private void ProcessPixels(Bitmap bmp1,Bitmap bmp2)
{
for (int y = 0; y < bmp1.Height; y++)
{
for (int x = 0; x < bmp1.Width; x++)
{
if (bmp1.GetPixel(x, y) != bmp2.GetPixel(x, y))
bmp1.SetPixel(x, y, Color.Black);
}
}
}
As a result, i got somthing i wasn't really expecting for,the majority of the changed pixels changed changed to black pixel as i expected,but there were some pixels which didnt change to black...(even though they look different between the 2 images,but maybe they're just look equal but there not?)
This is the result image:
For example you can see in the opened windows start menu,that some pixels remain the same,and in the edges there also some odd parts.
Maybe i'm missing few pixels on the loop?
I would appreciate any help.
Thanks.

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.

Getting a Colour Scheme from an Image

I want to develop a basic tool like the one featured here. I will be taking screenshots of a number of web pages and from there I wish to take the top five most popular colours and from there somehow decide whether the colours are a good match.
I want to write this tool in C# and after a bit of research I discovered lockbits. My first idea was to take an image and then get the colour of each pixel, but I am unsure as to whether this will give me the results I desire and how to make six lists of the most popular colours.
Can anyone here provide advice as to how I would create a program to do something similar to the program above, that will take in an image and will select the top five colours used in the image?
Well.. Use a thumbnail image (16x16, 32x32 etc) and select from it the colors like
updated code:
private void button1_Click(object sender, EventArgs e)
{
int thumbSize = 32;
Dictionary<Color, int> colors = new Dictionary<Color, int>();
Bitmap thumbBmp =
new Bitmap(pictureBox1.BackgroundImage.GetThumbnailImage(
thumbSize, thumbSize, ThumbnailCallback, IntPtr.Zero));
//just for test
pictureBox2.Image = thumbBmp;
for (int i = 0; i < thumbSize; i++)
{
for (int j = 0; j < thumbSize; j++)
{
Color col = thumbBmp.GetPixel(i, j);
if (colors.ContainsKey(col))
colors[col]++;
else
colors.Add(col, 1);
}
}
List<KeyValuePair<Color, int>> keyValueList =
new List<KeyValuePair<Color, int>>(colors);
keyValueList.Sort(
delegate(KeyValuePair<Color, int> firstPair,
KeyValuePair<Color, int> nextPair)
{
return nextPair.Value.CompareTo(firstPair.Value);
});
string top10Colors = "";
for (int i = 0; i < 10; i++)
{
top10Colors += string.Format("\n {0}. {1} > {2}",
i, keyValueList[i].Key.ToString(), keyValueList[i].Value);
flowLayoutPanel1.Controls[i].BackColor = keyValueList[i].Key;
}
MessageBox.Show("Top 10 Colors: " + top10Colors);
}
public bool ThumbnailCallback() { return false; }
alt text http://lh3.ggpht.com/_1TPOP7DzY1E/S0uZ6GGD4oI/AAAAAAAAC5k/3Psp1cOCELY/s800/colors.png
The easiest way, as you said is:
Read in each pixel and store them in
a collection.
The top five colours used would be
the values that occur the most.
That's how I'd have ago at first trying something like this.
To further this work, you could take in colour ranges, so using RGB values (Red, Green, Blue) assign a colour to a certain approximation of colour.
For example, say that same image was used, the light blue values would get stored together, then an average could be taken of these to give the most common (yet average) light blue in the scene.
Repeat for the other pixels.
As for the scaling - the example website uses dull/bright values. A simple scale value could be used. Consider a medium red in RGB:
0.7, 0.0, 0.0
You could scale this by adding/multiplying a value. Keep the values within the limit of 0 to 1 however. As for what the scaling value should be, experimant. The higher it is, the duller/brighter the colour will become.
This is an example of how to create a histogram (or a frequency table in another words) where you can take a look on the details on how to go about processing the image.
But my main recommendation is not to use RGB (unless the website you're looking at has mostly plain colors), but use HSB instead. The "H" (hue) component will give you a better indication of the colors used no matter how bright or dark they are.

Categories