I've parsed an image with the following code
Bitmap img = (Bitmap)Bitmap.FromFile("file.jpg");
And after saved so
img.Save("file2.jpg");
I did not modify anything, but looking on diff of the both images, I see that the new one is different. How I can fix that? I want to keep the colors
Related
I want to compare two images and then generate and save an image that will show all the differences that has been found,
for example:
I am using ImageMagick: https://magick.codeplex.com/
But they don't have full documentation for C#.
I found only: http://www.imagemagick.org/Usage/compare/
This code for example show value from 0-1 that represent how similar the pictures are:
MagickImage img1 = new MagickImage(#"C:\test\Image1.jpg");
MagickImage img2 = new MagickImage(#"C:\test\Image2.jpg");
double diff = img1.Compare(img2,new ErrorMetric());
But how can I compare the images using ImageMagick and then save the result as shown in the example above and in their website?
Update:
With the help of dlemstra I wrote the following code and I generate images that suppose to show the difference as in the example above.
MagickImage img1 = new MagickImage(#"C:\test\Image1.jpg");
MagickImage img2 = new MagickImage(#"C:\test\Image2.jpg");
MagickImage img3 = new MagickImage(#"C:\test\Image3.jpg");
MagickImage img4 = new MagickImage(#"C:\test\DiffImage.jpg");
MagickImage img5 = new MagickImage(#"C:\test\DiffImage.jpg");
var imgDiff = new MagickImage();
img1.Compare(img2, new ErrorMetric(), imgDiff);
imgDiff.Write(#"C:\test\Diff4.jpg");
img1.Compare(img3, new ErrorMetric(), imgDiff);
imgDiff.Write(#"C:\test\Diff5.jpg");
img1.Compare(img4, new ErrorMetric(), imgDiff);
imgDiff.Write(#"C:\test\Diff6.jpg");
img5.Compare(img4, new ErrorMetric(), imgDiff);
imgDiff.Write(#"C:\test\Diff7.jpg");
The Strange results are: When I compare the following two images with the marked only difference:
This is the result that I get (And not as the example above from "imageMagick"
You will need to use one of the other overloads of the Compare method for this. The example below demonstrates how to do this:
using (var img1 = new MagickImage(#"C:\test\Image1.jpg"))
{
using (var img2 = new MagickImage(#"C:\test\Image2.jpg"))
{
using (var imgDiff = new MagickImage())
{
double diff = img1.Compare(img2, new ErrorMetric(), imgDiff);
imgDiff.Write(#"C:\test\Diff-Image1-Image2.jpg");
}
}
}
But when you are working with jpeg images (they are lossy) you probably also want to set the ColorFuzz on the first image:
img1.ColorFuzz = new Percentage(5); // adjust this value for your situation
This will make it so that pixels that are almost the same will also match.
Lessons Learned:
Wanted to add some important notes so others hopefully avoid the pitfalls which I ran into when testing out ImageMagick (or any compare tool) for the first time.
Beware of editing in Windows Paint in general.
Don’t edit a *.png with a transparent background in Windows paint and expect a good compare. Windows Paint doesn’t handle transparent background and the png you edited in Paint will now have a white background. The Image will look exactly the same to the naked eye but the image comparers know better.
If you have SnagIt, this is a better tool for making edits to an image when you want to put a image compare tool to the test.
Conclusion:
The code written by #dlemstra does work as expected. Just make sure that when you are testing out the first time that the second image (which you modified) didn’t get unintentionally modified by the image editor that you use. This is a general warning for when you are testing out any image compare tool for the first time to see if you want to use it or not.
Examples:
Example 1: Transparent png + Windows Paint
Downloading a transparent image, making and edit to it in Paint which unintentionally also changes background to white instead of transparent.
Just by opening, then saving the second image in Paint without making any edits to the image will cause the diff to look like this:
I couldn’t figure out what was going on until I compared with Beyond Compare:
Example 2: Complex *.jpg + Windows Paint
Windows Paint was also not good at keeping complex images identical between saves:
The big red areas were changes I had made, but the thin outlines of the roses were changes that Windows Paint made to the picture
Even when I made no changes at all and just open, saved and closed the second image in Paint (and the original image was an image which had also been saved in Paint), Paint still made undesired edits to the picture (dark red dots in image):
I then had an original image which had been saved in Paint and copied this image, opened the second image in snagIt, saved the second image in snagit, and then closed the image and compared the two images (which should have been identical). However, it seemed that snagIt made it’s own modifications to the original ‘Paint saved’ image:
Lastly, I copied the ‘Snagit saved’ image, opened this second image also in SnagIt, made an edit to the second image, saved the image in SnagIt and then closed the image. SnagIt did not make any modifications to this image and the compare showed exactly what I expected:
Lastly:
Most information you find about ImageMagick pertains to using it via the command line. You can add the Magick.Net nuget to your C# project in Visual Studio by installing it via the NuGet Package Manager
I am new to C#, I am using Visual Studo 2010, I have an image that needs to be displayed on a picturebox.
I tried many different methods. All the methods results in some unwanted pixels to appear along with image.
I have tried
picturebox.Image = Image.FromFile("bird.png");
result->
the image is displayed but with the stray white/black pixels at random places.
I also tried creating a bitmap of same size and drawing the image onto the bitmap and then assigning the bitmap to the picture box.Image. Still those unwanted pixels are visible.
I have tried clearing the picture box image (filling it with white or transparent) and then assigning the image, still same error occurs.
PS: this doesn't happen for all the images only certain images show this behaviour.
any help would be great
Code:
Image org = Bitmap.FromFile("bird.png");
Bitmap final = new Bitmap(org.Width,org.Height);
using (Graphics g = Graphics.FromImage(final))
{
g.DrawImage(org,0,0,GraphicsUnit.Pixel);
}
picturebox.Image = final;
if i use final.save("picture.png"). The "picuture.png" does not have that wrong pixels, it happens only when i use picture box to display it.
Please find the images attached defect orginal
PS: its not because of different fileformat (orginal and defect)
It was an TransperancyKey issue resolved by setting it to Default.
I posted this question earlier but I have modified my code to a simple algorithm and I still have the same issue as before:
I created a picturebox which, when an effect is selected, it will then change the image in the picturebox using the color matrix.
The issues I'm having is if I choose another effect when one is selected the old effect will not disappear, instead it will just stay there and be underneath the new effect selected. The effects I'm using is sepia and greyscale for now, but can anyone help me so that once one effect is selected, the old effect is cleared rather than them just stacking up on one another. "
The key here is to cache the originalImage in a non-volatile area. For example, load it up into a hidden pictureBox that you don't touch.
When you want to apply an effect, copy the originalImage over into a displayImage picturebox and then apply the effect.
It also looks like you are setting your image to the image that is there. I am not sure but this may be taking into account what you have already set. For example when you set
Image originalImage = pictureBox.Image;
This may be taking the image you have displayed along with any effects you have already applied and setting that as your image to be modified. Like I said I am unsure of this since I can't test it at the moment.
EDIT
The following works for me:
Replace
Bitmap originalImage = (Bitmap)displayPictureBox.Image;
originalImage = (Bitmap)pictureBox.Image.Clone();
With
Image therealoriginalimage = Image.FromFile(#"C:\Users\Me\Desktop\testimg.png");
Bitmap originalImage = (Bitmap)therealoriginalimage;
As both answers mention it looks like you are setting your original image = what is currently in the picture box.
The above code is a quick fix so you can see exactly what was happening. You should modify this and have the originalimage saved as a varible as soon as your app starts. It will be much cleaner than the example above that sets the image each time you call the method
Alright guys last little bit of this project I'll ask for help on I promise.
So I go to load the images, works fine however I notice upon loading that the dimensions of the image have been scaled down in the y to 300 (all are a constant value of 433) and up or down from their original width to 600.
I'm using the following method to load them
foreach (string file in Directory.EnumerateFiles(imagePath, "*.JPG"))
{
Image contents = Image.FromFile(file);
treesImage[count] = contents;
count++;
}
and this is the resulting image when I have it loaded.
http://i.stack.imgur.com/Q40kK.png
As you can see the image below the red rectangle is quite small
Any help would be appreciated. If you require any more information please post below and I'll make sure to edit the original question with the relevant information as soon as humanly possible.
EDIT: I am using a simple windows form application and not another graphical framework for my own reasons.
Thanks in advance :)
I'll assume you are using a PictureBox control to display the image.
When someone chooses a tree from your map, you obviously set the PictureBox Image property to the image object referenced by the index in the array. Use the Image object to set the ClientSize of the PictureBox control.
...
Image img = treesImage[idx];
MyPictureBox.SizeMode = PictureBoxSizeMode.Normal;
MyPictureBox.ClientSize = new Size(img.Width,img.Height);
MyPictureBox.Image = img;
...
Alternately you can define one size for your PictureBox and force all the images to be scaled to that size by setting the control SizeMode property to StretchImage declaratively.
I would recommend that you create a simple class (MyImageInfo for example) that would store the Path, Width, and Height of the images found in your first function into a list and then just as before when a user clicks to view an image you set the width and height of the PictureBox and then call the LoadAsync(path) method to get the image. then you aren't storing all images in memory at once, just as you need them since it doesn't look like this requires a lot of quick jumping from image to image.
I have the following:
A headline (text)
A tagline (text)
A background image (url to this image)
I need to set these dynamically together in an image, and then store it as a PNG file. All of this happens in a web service which sends some kind of stream back.
I would love to be able to style this with CSS, as it would be nice to add some CSS effects to the picture. If that is not possible, it is fine as well.
So far I've thought about using the Bitmap class, and then insert my things dynamically. This is definetely one way to go, but I would really prefer some more design-friendly way like CSS.
What is the prefered way to do this? Any experiences?
Check out System.Drawing.Graphics.
Bitmap bmp = new Bitmap(500, 500);
using (Graphics g = Graphics.FromImage(bmp)) {
g.Clear(Color.Black);
// ...
}
You can then call Image.Save (bmp.Save(...)) to save the image to disk or even to a MemoryStream.
The answer from Angelo Geels will let you create a dynamic bitmap in your code. If you need more flexibility then you might want to use the SVG format instead, and possibly render it as a PNG file if you absolutely need that format.
SVG is an XML based image format where you define a viewport and shapes that should be drawn into it. It is vector based so the images can be scaled up and down to any size.
It should be quite easy to write an ASP.Net Http Handler that outputs an SVG xml file with some dynamic content based on user input. An even easier option would be to serve static SVG files that your designers create, but then you might as well serve static PNG files.
If you want to use the SVG approach for its flexibility but still need to output PNG's then you can use the SVG.Net library to read the SVG file and then use the SvgDocument.Draw method to draw the image to a Bitmap object that can then be written out as a PNG file.