You've built a fancy new photo uploader into your app and in less than 10 minutes after rolling it to production someone uploads a bunch of photos and they are sideways, upside down, or even worse... backwards. Welcome to the internet where phones are able to upload directly from their photo gallery. It's fine, we can fix this.

Fixing Photo RotatioN

$Image = new Imagick($Filename);
$Orientation = $Image->GetImageOrientation();
This is how we ask about the orientation of the image. The value it returns matches up with a series of Imagick::ORIENTATION_ constants that tell you things like Top Left, Right Top, Bottom Right, Left Bottom... etc. What this Top Left Right Bottom system is trying to tell us is how to read it. Regardless of what you think the rotation of an photo may be, they are read like a book (in languages like English) from the top left corner, to the right, then down to the next line on the left when hitting the edge. The first word tells us what edge the X axis is aligned to, and the second word tells us what edge the Y axis is aligned to. In this context we mean "reading the image" is understanding where (0,0) pixel is "really" located, even though it may not "really" be.
A Top Left, Imagick::ORIENTATION_TOPLEFT, is "Normal" and no correction of the image is needed. If we have an image that says it is oriented Right Top, Imagick::ORIENTATION_RIGHTTOP we need to -pretend- that if we were reading this image that the Right Top corner should be treated as if it was actually the Top Left corner. How do we do that?
Turn your head clockwise 90 deg. The Right Top corner becomes the Top Left corner and the text is easier to read. Now to correct your head you need to rotate it 90deg anti-clockwise and that is the value used to correct the photo.
$Image = new Imagick($Filename);
$Orientation = $Image->GetImageOrientation();

if($Orientation === Imagick::ORIENTATION_RIGHTTOP) {
	$Image->RotateImage('#000000',-90);
}
Bottom Right means you'd have to turn your head upside down 180deg to read it (-180 to correct), and Left Bottom, all the way around 270deg (or 90deg anti-clockwise) to read it (-270 or 90 to correct).

Fixing Flipped Photos

All of that told us how to understand images that are just rotated but there is one more issue, and that is the damned selfie camera. In addition to potentially rotating an image, selfie cams see you like a mirror but then save the photo with a note that you need to flip it - the final image would be seen how someone watching and laughing while you're taking a selfie sees you (ocularly, at least).
When an image is flagged Top Right this is the clue this photo is backwards. The X axis is aligned to the top edge just like Top Left, but the Y axis is now on the right edge. Without the correction we will likely see in our app the left version above, when the goal is to be seeing the right version.
$Image = new Imagick($Filename);
$Orientation = $Image->GetImageOrientation();

if($Orientation === Imagick::ORIENTATION_TOPRIGHT) {
	$Image->FlopImage();
}
Right Bottom would mean that you would need to turn your head 90deg clockwise again and still use a mirror. Bottom Left upside down and with a mirror. Left Top then -90deg and with a mirror.

PUtting it Together

To correct all of these photos they (might) need a rotation. After rotating, they (might) need to be flipped. Here is the final code for reading an image and deciding the process of correcting its orientation to appear correctly. Note these values expect my code to be rotating the photo before flipping it, for no real good reason, that is just what I did.
$Image = new Imagick($Filename);
$Flop = FALSE;
$Rotate = 0;

// determine the orientation of the image.

switch($Image->GetImageOrientation()) {
	case Imagick::ORIENTATION_TOPLEFT:
		$Rotate = 0;
	break;
	case Imagick::ORIENTATION_RIGHTTOP:
		$Rotate = -90;
	break;
	case Imagick::ORIENTATION_BOTTOMRIGHT:
		$Rotate = 180;
	break;
	case Imagick::ORIENTATION_LEFTBOTTOM:
		$Rotate = 90;
	break;

	case Imagick::ORIENTATION_TOPRIGHT:
		$Flop = TRUE;
		$Rotate = 0;
	break;
	case Imagick::ORIENTATION_RIGHTBOTTOM:
		$Flop = TRUE;
		$Rotate = -90;
	break;
	case Imagick::ORIENTATION_BOTTOMLEFT:
		$Flop = TRUE;
		$Rotate = 180;
	break;
	case Imagick::ORIENTATION_LEFTTOP:
		$Flop = TRUE;
		$Rotate = 90;
	break;
}

// handle any rotation needed.

if($Rotate !== 0)
$Image->RotateImage('#000000',$Rotate);

// mirror image if needed.

if($Flop === TRUE)
$Image->FlopImage();

// then force a normal orientation and overwrite.

$Image->SetImageOrientation(Imagick::ORIENTATION_TOPLEFT);
$Image->WriteImage($Filename);
Although personally this is the version of it I shipped, using a falling switch instead.
switch($Image->GetImageOrientation()) {
	case Imagick::ORIENTATION_TOPRIGHT:
		$Flop = TRUE;
	case Imagick::ORIENTATION_TOPLEFT:
		$Rotate = 0;
	break;

	case Imagick::ORIENTATION_RIGHTBOTTOM:
		$Flop = TRUE;
	case Imagick::ORIENTATION_RIGHTTOP:
		$Rotate = -90;
	break;

	case Imagick::ORIENTATION_BOTTOMLEFT:
		$Flop = TRUE;
	case Imagick::ORIENTATION_BOTTOMRIGHT:
		$Rotate = 180;
	break;

	case Imagick::ORIENTATION_LEFTTOP:
		$Flop = TRUE;
	case Imagick::ORIENTATION_LEFTBOTTOM:
		$Rotate = 90;
	break;
}
The final result running it on those test images:

Resources