Wrong image width and height when read it with C# - c#

I've got a strange problem. There is an image. Unfortunately it's too big to show it in question. But you can download it. If you can't do it from OneDrive this is another way.
This image seems to be ordinary, but it's not.
When we open properties we will see this:
We need to keep in mind dimensions of this picture: Width is 3000px and Height is 4000px. It looks correct because image is portret.
Then lets try to read it with C#:
private static void TestImage()
{
using (FileStream file1 = new FileStream("DSC_2446.JPG", FileMode.Open))
{
Console.WriteLine("DSC_2446.JPG :");
using (var img1 = System.Drawing.Image.FromStream(file1))
{
Console.WriteLine($" Width = {img1.Width}");
Console.WriteLine($" Height = {img1.Height}");
}
}
Console.Read();
}
And in results we see some magic!!!
So I've got completely wrong values. Values are switched between properties.
Does someone know why it can happens and how to detect/fix this behavior?

The problem is the EXIF version. You can use this site to get the real data https://exif.tools/meta/Exif-Version/0231 and you will see
Also according to this Post you can get your image's orientation by
var orientation = (int)img1.GetPropertyItem(274).Value[0];
//orientation = 6
the value 6 means rotate 90 degrees.
There is the reference of the value 6. https://exiftool.org/TagNames/EXIF.html

Related

Need to obtain HorizontalResolution and VerticalResolution in SkiaSharp

I am trying to scale a picture by SkiaSharp and got the following code:
Stream pictureStream = GetPictureStream(filename);
using var skImageStream = new SKManagedStream(pictureStream);
using var skPicture = SKPicture.Deserialize(skImageStream);
var width = skPicture.CullRect.Width / skPicture.HorizontalResolution * 72;
var height = skPicture.CullRect.Height / skPicture.VerticalResolution * 72;
I am looking for a way to obtain HorizontalResolution and VerticalResolution from skPicture or anything else in SkiaSharp but I failed to find a solution. SKPicture, SKCanvas, and SKBitmap, do not have such a property.
Could you please suggest a solution for this problem?
This answer is per Maku's comment made above: SKPicture is just a recording of drawing commands, it's not an image until drawn. And resolution is just a metadata of images to indicate print size.

GameCard value recognition gives wrong result with AForge.NET

Actually I'm using AForge.NET to recognize suit and value from a gamecard.
Here is a snippet where I decide which suit/value is there:
public static CardTemplateIdentifier GetBestMatchingIdentifier(this List<CardTemplateIdentifier> templates, Bitmap bitmap)
{
float maxSimilar = 0f;
CardTemplateIdentifier result = null;
foreach (var template in templates)
{
// Identify similarity between template and bmp
ExhaustiveTemplateMatching tm = new ExhaustiveTemplateMatching(0);
TemplateMatch[] matchings = tm.ProcessImage(bitmap, template.Sample);
// If the currently tested template fits better than the best one so far,
// set the value as the identified card value
if (matchings.Length > 0 && matchings[0].Similarity > maxSimilar)
{
maxSimilar = matchings[0].Similarity;
result = template;
}
}
return result;
}
CardTemplateIdentifier contains a list with all possible cards and their comparism sample.
...
Now If trying to recognize the images, I can not rely on this being reliably recognized: Sometimes the scaling of the images differs from the one I made the sample. Or the font has got less thicknes, see example below:
I think I'm on the wrong way to detect the values from the images. Is there a better or convience way how to solve this problem?

How to adjust jpeg quality with Magick.Net

I am trying to set the image quality of two images appended to one another to 10% and resize the images to 40x40.
using (var images = new MagickImageCollection {designFile, swatchFile})
{
MagickImage sprite = images.AppendHorizontally();
sprite.Format = MagickFormat.Jpeg;
sprite.SetOption(MagickFormat.Jpeg, "quality", "10%");
sprite.SetOption(MagickFormat.Jpeg, "size", "40x40"); ;
sprite.Write(spriteFile);
}
Unfortunately the SetOption and Format calls don't seem to be affecting the file that is written to sprite.Write()?
The method SetOption is the same as -define in ImageMagick. And this method will be renamed to SetDefine in the next release. The following resizes your image to 40x40 and uses a quality of 10%.
using (MagickImage sprite = images.AppendHorizontally())
{
sprite.Format = MagickFormat.Jpeg;
sprite.Quality = 10;
sprite.Resize(40, 40);
sprite.Write(spriteFile);
}
If you need more help feel free to post another question here: https://magick.codeplex.com/discussions

How to use the autorotate plugin in ImageResizer

How do I use the AutoRotate plugin in a c# console application? I thought I'd be able to do something like settings.AutoRotate = true; like I can change the fit mode to use the seam carving plugin.
I've tried settings.Add("autorotate","true") to the keycollection, as well as other keynames AutoRotate and autoRotate.
I'm using it in a simple method.
new AutoRotate().Install(ImageResizer.Configuration.Config.Current);
...
protected static Image ResizeImage(Image image, double scaleFactor)
{
var settings = new ResizeSettings
{
Scale = ScaleMode.Both,
Width = (int)Math.Floor(Image.Width * scaleFactor),
Height = (int)Math.Floor(Image.Height * scaleFactor),
Mode = FitMode.None,
Format = "png"
};
settings.Set("autorotate", "true");
return ImageBuilder.Current.Build(image, settings, true);
}
After a lot of research, I've found the error that I'm making, and reveals a nice little "hidden feature" of .Net!
When an image is read into the Bitmap object, the meta data is erased, so, by accepting an Image object, the data about the orientation is lost and auto rotate doesn't kick in. So, passing the image filename instead of the image object, and my code above above works!
Thanks guys!

Writeablebitmap.SaveJpeg is rotating my image -90 degrees

I'm using the following code to get a picture from the the MediaLibrary on the phone and resize it. In the emulator it is working fine but it is rotating it -90 degrees when I try it on a real phone.
The 4th parameter for SaveJpeg is orientation and the tooltip says
"This parameter is not currently used by this method. Use a value of 0 as a placeholder."
The same thing happens if I pass 0,1,-1. Seems like it might actually be implemented on the phone and not in the emulator, but I don't know what to pass.
public byte[] GetPhoto(string photoName, int width, int height)
{
using (var ml = new Microsoft.Xna.Framework.Media.MediaLibrary())
{
using(Stream stream = (from p in ml.Pictures where p.Name == photoName select p).FirstOrDefault().GetImage())
{
//load the stream into a WriteableBitmap so it can be resized
using(MemoryStream outstream = new MemoryStream())
{
PictureDecoder.DecodeJpeg(stream).SaveJpeg(outstream, width, height, 0, 85);
return outstream.ToArray();
}
}
}
}
Also I just noticed that the sample pictures on the phone are not having this problem, just the ones I've taken.
I don't think the EXIF data for orientation is read by WP7 (happy to be corrected as I've only tried when the CTP SDK was out). However, you can manually rotate your picture using this method. An alternative, which I haven't tried, could be to get the image's rotate transform and rotate it 90 degrees. Transform rotations may work out to be quicker than manually shifting all the pixels of the writeable bitmap.

Categories