Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is TImage rotating my image?

Writing a mobile application - it's pulling images from a secure website, and shown below (the first image) pulls incorrectly (notice web version vs mobile version), the second image shows correctly on the website, but Delphi TImage is rotating it for some reason and I can't figure out why. Rotate is set to 0 and "Fit" is set on the TImage component.

Thoughts?

enter image description here

Why does it rotate like this

like image 831
Zack Burns Avatar asked Jan 12 '17 17:01

Zack Burns


2 Answers

Jpeg and Tiff have Exif (Exchangeable image file format) metadata that specify image orientation (among other data).

It's not that "TImage rotating my image". the TImage is not handling the Exif orientation metadata. Ideally, TImage should auto-rotate the image according to the orientation metadata, but it does not. You need to read the Exif orientation property and rotate the image accordingly.

The Exif tag "Orientation" (0x0112) spec is:

1 = Horizontal (normal) 
2 = Mirror horizontal 
3 = Rotate 180 
4 = Mirror vertical 
5 = Mirror horizontal and rotate 270 CW 
6 = Rotate 90 CW 
7 = Mirror horizontal and rotate 90 CW 
8 = Rotate 270 CW

You can use some free Exif components such TExif/NativeJpg/CCR Exif, and rotate your image if needed according to the orientation tag.

Here is an example using GDI+ (VCL/Windows) e.g:

uses GDIPAPI, GDIPOBJ;

procedure TForm1.Button1Click(Sender: TObject);
var
  GPImage: TGPImage;
  GPGraphics: TGPGraphics;
  pPropItem: PPropertyItem;
  BufferSize: Cardinal;
  Orientation: Byte;
  RotateType: TRotateFlipType;
  Bitmap: TBitmap;
begin
  GPImage := TGPImage.Create('D:\Test\image.jpg');
  try
    BufferSize := GPImage.GetPropertyItemSize(PropertyTagOrientation);
    if BufferSize > 0 then
    begin
      GetMem(pPropItem, BufferSize);
      try
        GDPImage.GetPropertyItem(PropertyTagOrientation, BufferSize, pPropItem);
        Orientation := PByte(pPropItem.value)^;
        case Orientation of
          1: RotateType := RotateNoneFlipNone; // Horizontal - No rotation required
          2: RotateType := RotateNoneFlipX;
          3: RotateType := Rotate180FlipNone;
          4: RotateType := Rotate180FlipX;
          5: RotateType := Rotate90FlipX;
          6: RotateType := Rotate90FlipNone;
          7: RotateType := Rotate270FlipX;
          8: RotateType := Rotate270FlipNone;
        else
          RotateType := RotateNoneFlipNone; // Unknown rotation?
        end;
        if RotateType <> RotateNoneFlipNone then
          GPImage.RotateFlip(RotateType);
        Bitmap := TBitmap.Create;
        try
          Bitmap.Width := GPImage.GetWidth;
          Bitmap.Height := GPImage.GetHeight;
          Bitmap.Canvas.Lock;
          try
            GPGraphics := TGPGraphics.Create(Bitmap.Canvas.Handle);
            try
              GPGraphics.DrawImage(GPImage, 0, 0, GPImage.GetWidth, GPImage.GetHeight);
              Image1.Picture.Assign(Bitmap);              
            finally
              GPGraphics.Free;
            end;
          finally
            Bitmap.Canvas.Unlock;
          end;    
        finally
          Bitmap.Free;
        end;
      finally
        FreeMem(pPropItem);
      end;
    end;
  finally
    GPImage.Free
  end;
end;
like image 91
kobik Avatar answered Oct 23 '22 21:10

kobik


The Exif specification defines an Orientation Tag to indicate the orientation of the camera relative to the captured scene. Some apps can therefore auto-rotate the image corresponding to this EXIF-Flag. I would guess that your web-version does this auto-rotate. TImage does it not.

like image 7
Andreas Avatar answered Oct 23 '22 20:10

Andreas