In a nutshell the purpose of the following code is to resize an image based on the target size and the multiplier (1x, 2x, 3x). This works fine except for some reason I haven't determined some images are being rotated.
public void ResizeImage(TargetSize targetSize, ResizeMultiplier multiplier, Stream input, Stream output)
{
using (var image = Image.FromStream(input))
{
// Calculate the resize factor
var scaleFactor = targetSize.CalculateScaleFactor(image.Width, image.Height);
scaleFactor /= (int)multiplier; // Enum is effectively named constant with a value of 1, 2, or 3
var newWidth = (int)Math.Floor(image.Width / scaleFactor);
var newHeight = (int)Math.Floor(image.Height / scaleFactor);
using (var newBitmap = new Bitmap(newWidth, newHeight))
{
using (var imageScaler = Graphics.FromImage(newBitmap))
{
imageScaler.CompositingQuality = CompositingQuality.HighQuality;
imageScaler.SmoothingMode = SmoothingMode.HighQuality;
imageScaler.InterpolationMode = InterpolationMode.HighQualityBicubic;
var imageRectangle = new Rectangle(0, 0, newWidth, newHeight);
imageScaler.DrawImage(image, imageRectangle);
newBitmap.Save(output, image.RawFormat);
}
}
}
}
// Class definition for the class used in the method above
public class TargetSize
{
/// <summary>
/// The _width
/// </summary>
private readonly int _width;
/// <summary>
/// The _height
/// </summary>
private readonly int _height;
/// <summary>
/// Initializes a new instance of the <see cref="TargetSize"/> class.
/// </summary>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
public TargetSize(int width, int height)
{
_height = height;
_width = width;
}
/// <summary>
/// Calculates the scale factor.
/// </summary>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
/// <returns></returns>
public decimal CalculateScaleFactor(int width, int height)
{
// Scale proportinately
var heightScaleFactor = decimal.Divide(height, _height);
var widthScaleFactor = decimal.Divide(width, _width);
// Use the smaller of the two as the final scale factor so the image is never undersized.
return widthScaleFactor > heightScaleFactor ? heightScaleFactor : widthScaleFactor;
}
}
// NUnit integration test case I'm using to exercise the above code
[Test]
public void ResizeImage_Persistant_Single()
{
// Read the image from disk
using (var fileStream = File.OpenRead(@"TestDatadog.jpg"))
{
using (var outputStream = new MemoryStream())
{
// Call the resize image method detailed above. ResizeMultiplier.Medium casts to 2.
_sut.ResizeImage(new TargetSize(200, 200), ResizeMultiplier.Medium, fileStream, outputStream);
using (var newImage = Image.FromStream(outputStream))
{
// Save the resized image to disk
newImage.Save(@"TestDataImageResizerTests.ResizeImage_Persistant_Single.jpg");
}
}
}
}
For instance this image:
is scaled appropriately but this image:
is flipped upside down. It is worth mentioning that the image also appeared to be upside down when it was in the preview pane to upload it to this site. That fact (which I obviously just discovered) strongly makes me think something is funny with the image. Regardless my code needs to handle it.
Imgur "fixed" the file above (because it doesn't rotate now when I run it through my code) so I uploaded it to Google Drive. If you right click on the image (in FireFox I haven't tested other browsers) and click Save Image As... then the image doesn't rotate with my code above. If you click the download button in the header then the image does rotate with my code.... Here is another copy of the dog image that flips 180 degrees with my code. All of this is very bizarre, and I don't know what I'm doing wrong...
To be clear my goal is to resize the image without rotating the image.
Edits based on comments:
An image that rotates/flips will do so consistently, and in the same manner. For example this dog picture will always flip 180 degrees. Some pictures will lay on their side (rotate 90 or 270 degrees). I've verified that the newWidth
,newHeight
, scaleFactor
, targetSize
(private variables), and image.Height/image.Width
variables are all positive when the dog picture flips 180 degrees.
I don't believe this is an artifact of a particular tool. I see the rotation via; the preview in Windows Explorer, Windows Image Viewer, the stock Macintosh image viewer, FireFox, etc. The issue was actually brought to my attention by an iOS dev in my company who saw it in our app. I think too many tools are seeing this for it to be a viewer problem.
See Question&Answers more detail:
os