8

As the question implies, when I load an image into a pictureBox (using dialog box), it doesn't appear as its original look. in this screen shoot, the image on the left is the one I loaded into the pictureBox (on the right).

Trying to know what causes this I draw an image using Paint app and rotated it using Windows Photo Viewer, the rotated image loaded as it is (rotated), that is it, some pictures are just fine loaded, and others are rotated! and I can't figure out why?! enter image description here

mshwf
  • 7,009
  • 12
  • 59
  • 133
  • 1
    Photo-viewer rotates JPGs by tweaking the EXIF data - it doesn't actually change the pixel data. I guess the picture-box doesn't check the EXIF orientation of JPGs. Other formats like BMP and PNG don't have EXIF, so photo-viewer actually modifies the pixel-data when rotating them. – Blorgbeard Aug 21 '16 at 21:19

3 Answers3

12

When you view an image in Windows Photo Viewer, it automatically corrects image orientation if it has an Exif orientation data. PictureBox doesn't have built-in support for such functionality. You can create a custom PictureBox which shows images correctly even if they have orientation data:

using System.Linq;
using System.Windows.Forms;
using System.Drawing;
using System.ComponentModel;
public class MyPictureBox : PictureBox
{
    private void CorrectExifOrientation(Image image)
    {
        if (image == null) return;
        int orientationId = 0x0112;
        if (image.PropertyIdList.Contains(orientationId))
        {
            var orientation = (int)image.GetPropertyItem(orientationId).Value[0];
            var rotateFlip = RotateFlipType.RotateNoneFlipNone;
            switch (orientation)
            {
                case 1: rotateFlip = RotateFlipType.RotateNoneFlipNone; break;
                case 2: rotateFlip = RotateFlipType.RotateNoneFlipX; break;
                case 3: rotateFlip = RotateFlipType.Rotate180FlipNone; break;
                case 4: rotateFlip = RotateFlipType.Rotate180FlipX; break;
                case 5: rotateFlip = RotateFlipType.Rotate90FlipX; break;
                case 6: rotateFlip = RotateFlipType.Rotate90FlipNone; break;
                case 7: rotateFlip = RotateFlipType.Rotate270FlipX; break;
                case 8: rotateFlip = RotateFlipType.Rotate270FlipNone; break;
                default: rotateFlip = RotateFlipType.RotateNoneFlipNone; break;
            }
            if (rotateFlip != RotateFlipType.RotateNoneFlipNone)
            {
                image.RotateFlip(rotateFlip);
                image.RemovePropertyItem(orientationId);
            }
        }
    }
    [Localizable(true)]
    [Bindable(true)]
    public new Image Image
    {
        get { return base.Image; }
        set { base.Image = value; CorrectExifOrientation(value); }
    }
}
Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
  • If you use `MyPictureBox` instead of `PictureBox` the rotation will be fixed automatically. Also you can manually use `CorrectExifOrientation` method on an image and put the image in a `PictureBox`. Let me know if you have any question about the answer :) – Reza Aghaei Sep 01 '16 at 21:14
9

Without the original image data, it's impossible to say for sure what going on. But it's clear that at some point, some software involved in the processing of the image has used the EXIF orientation property to rotate the image, rather than actually modifying the image data itself. This may be Photo Viewer or some other tool that handled the photo at some point.

Here is code you can use to detect the orientation of the image, as recorded in the EXIF data by the camera that took the picture:

static ImageOrientation GetOrientation(this Image image)
{
    PropertyItem pi = SafeGetPropertyItem(image, 0x112);

    if (pi == null || pi.Type != 3)
    {
        return ImageOrientation.Original;
    }

    return (ImageOrientation)BitConverter.ToInt16(pi.Value, 0);
}

// A file without the desired EXIF property record will throw ArgumentException.
static PropertyItem SafeGetPropertyItem(Image image, int propid)
{
    try
    {
        return image.GetPropertyItem(propid);
    }
    catch (ArgumentException)
    {
        return null;
    }
}

where:

/// <summary>
/// Possible EXIF orientation values describing clockwise
/// rotation of the captured image due to camera orientation.
/// </summary>
/// <remarks>Reverse/undo these transformations to display an image correctly</remarks>
public enum ImageOrientation
{
    /// <summary>
    /// Image is correctly oriented
    /// </summary>
    Original = 1,
    /// <summary>
    /// Image has been mirrored horizontally
    /// </summary>
    MirrorOriginal = 2,
    /// <summary>
    /// Image has been rotated 180 degrees
    /// </summary>
    Half = 3,
    /// <summary>
    /// Image has been mirrored horizontally and rotated 180 degrees
    /// </summary>
    MirrorHalf = 4,
    /// <summary>
    /// Image has been mirrored horizontally and rotated 270 degrees clockwise
    /// </summary>
    MirrorThreeQuarter = 5,
    /// <summary>
    /// Image has been rotated 270 degrees clockwise
    /// </summary>
    ThreeQuarter = 6,
    /// <summary>
    /// Image has been mirrored horizontally and rotated 90 degrees clockwise.
    /// </summary>
    MirrorOneQuarter = 7,
    /// <summary>
    /// Image has been rotated 90 degrees clockwise.
    /// </summary>
    OneQuarter = 8
}

The GetOrientation() method above is written as an extension method, but of course you can call it as a plain static method. Either way, just pass it the Bitmap object you've just opened from a file, and it will return the EXIF orientation stored in the file, if any.

With that in hand, you can rotate the image according to your needs.

Peter Duniho
  • 68,759
  • 7
  • 102
  • 136
0

I load my image from the file explorer to the pictureBox like this:

private void btnBrowse_Click ( object sender, EventArgs e ) {
    using( OpenFileDialog openFile = new OpenFileDialog() ) {
        openFile.Title = "Select image for [user]";
        openFile.Filter = "Image files (*.jpg, *.jpeg, *.jpe, *.jfif, *.png)|*.jpg; *.jpeg; *.jpe; *.jfif; *.png|All files (*.*)|*.*";

        if( openFile.ShowDialog() == DialogResult.OK ) {
            //image validation
            try {
                Bitmap bmp = new Bitmap( openFile.FileName );//to validate the image
                if( bmp != null ) {//if image is valid
                    pictureBox1.Load( openFile.FileName );//display selected image file
                    pictureBox1.Image.RotateFlip( Rotate( bmp ) );//display image in proper orientation
                    bmp.Dispose();
                }
            } catch( ArgumentException ) {
                MessageBox.Show( "The specified image file is invalid." );
            } catch( FileNotFoundException ) {
                MessageBox.Show( "The path to image is invalid." );
            }
        }
    }
}

This is the method for displaying the images proper orientation:

//Change Image to Correct Orientation When displaying to PictureBox
public static RotateFlipType Rotate ( Image bmp ) {
    const int OrientationId = 0x0112;
    PropertyItem pi = bmp.PropertyItems.Select( x => x )
                                .FirstOrDefault( x => x.Id == OrientationId );
    if( pi == null )
        return RotateFlipType.RotateNoneFlipNone;

    byte o = pi.Value[ 0 ];

    //Orientations
    if( o == 2 ) //TopRight
        return RotateFlipType.RotateNoneFlipX;
    if( o == 3 ) //BottomRight
        return RotateFlipType.RotateNoneFlipXY;
    if( o == 4 ) //BottomLeft
        return RotateFlipType.RotateNoneFlipY;
    if( o == 5 ) //LeftTop
        return RotateFlipType.Rotate90FlipX;
    if( o == 6 ) //RightTop
        return RotateFlipType.Rotate90FlipNone;
    if( o == 7 ) //RightBottom
        return RotateFlipType.Rotate90FlipY;
    if( o == 8 ) //LeftBottom
        return RotateFlipType.Rotate90FlipXY;

    return RotateFlipType.RotateNoneFlipNone; //TopLeft (what the image looks by default) [or] Unknown
}

These are my references:

Code reference (I modified the accepted answer): https://stackoverflow.com/a/42972969/11565087

Visual reference (found in the comments[I don't know how to link a comment here]) : http://csharphelper.com/blog/2016/07/read-an-image-files-exif-orientation-data-in-c/

paraJdox1
  • 805
  • 9
  • 23