Annoying non-rotating picture frame

Big Ben upside-down

If you got a cheap Chinese Picture Frame, you have probably noticed that half your pictures are upside-down, or rotated left or right.

It happens even if the pictures are shown correctly on your computer, so if you got loads of pictures on your frame, it can be quite a hassle to figure out which files are orientated wrong.

The cause of this is the EXIF attribute which stores the correct orientation of the picture. Or rather that most Picture Frames ignores this attribute, probably because they do not have the CPU power to rotate the picture anyway.

The easiest fix is to run this PowerShell script on all your pictures – it will read the EXIF attribute and actually rotate the picture so your Picture frame does not have to.

Have fun!


2020-04-11: Updated: Now the script also resizes images (while maintaining aspect ratio) so your huge images won’t fill up your picture frame (remember to keep a copy of the images if you need them in full resolution)

# 20200411 Gert Lynge. Source: http://www.dabbler.dk
#
[System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") > $null

function Get-EXIFRotationAttribute($FilePath) {
# Returns:
# 1 = "Horizontal"
# 3 = "Rotate 180 degrees"
# 6 = "Rotate 90 degrees clockwise"
# 8 = "Rotate 270 degrees clockwise"
  $WiaImage = New-Object -ComObject Wia.ImageFile
  $WiaImage.LoadFile($FilePath)
  if($WiaImage.Properties.Exists("274")) {
    return ($WiaImage.Properties.Item("274").Value)
  }
  return -1
}

function RotateClockwise-JpegImage($Degrees,$FilePath) {
  $Image = [System.Drawing.image]::FromFile( $FilePath )
  switch($Degrees) {
    90  { $Image.rotateflip("Rotate90FlipNone") }
    180 { $Image.rotateflip("Rotate180FlipNone") }
    270 { $Image.rotateflip("Rotate270FlipNone") }
  }
  $Image.save($FilePath)
  $Image.Dispose()
  Write-Host -ForegroundColor Yellow "$FilePath rotated $Degrees degrees clockwise"
}

function ResizeImage() {
    param([String]$ImagePath, [Int]$Quality = 90, [Int]$targetSize, [String]$OutputLocation)
 
    Add-Type -AssemblyName "System.Drawing"
 
    $img = [System.Drawing.Image]::FromFile($ImagePath)
 
    $CanvasWidth = $targetSize
    $CanvasHeight = $targetSize
 
    #Encoder parameter for image quality
    $ImageEncoder = [System.Drawing.Imaging.Encoder]::Quality
    $encoderParams = New-Object System.Drawing.Imaging.EncoderParameters(1)
    $encoderParams.Param[0] = New-Object System.Drawing.Imaging.EncoderParameter($ImageEncoder, $Quality)
 
    # get codec
    $Codec = [System.Drawing.Imaging.ImageCodecInfo]::GetImageEncoders() | Where {$_.MimeType -eq 'image/jpeg'}
 
    #compute the final ratio to use
    $ratioX = $CanvasWidth / $img.Width;
    $ratioY = $CanvasHeight / $img.Height;
 
    $ratio = $ratioY
    if ($ratioX -le $ratioY) {
        $ratio = $ratioX
    }

    if ($ratio -ne 1) { 
      $newWidth = [int] ($img.Width * $ratio)
      $newHeight = [int] ($img.Height * $ratio)
 
      $bmpResized = New-Object System.Drawing.Bitmap($newWidth, $newHeight)
      $graph = [System.Drawing.Graphics]::FromImage($bmpResized)
      $graph.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::HighQualityBicubic
 
      $graph.Clear([System.Drawing.Color]::White)
      $graph.DrawImage($img, 0, 0, $newWidth, $newHeight)
 
      #save to file
      $img.Dispose()
      $bmpResized.Save($OutputLocation, $Codec, $($encoderParams))
      $bmpResized.Dispose()
      
      Write-Host -ForegroundColor Yellow "$FilePath scaled to $newWidth * $newHeight"
    }
}

function Rotate-JpegImages($ImagePath) {
  write-host -ForegroundColor Yellow "Checking for jpg/jpeg images that needs rotation in path $ImagePath (including subdirectories)..."
  $JpegFiles = get-childitem -Recurse -Path "$ImagePath\*" -File -Include @("*.jpg","*.jpeg")
  ForEach($JpegFile IN $JpegFiles) {
    $FilePath = Join-Path -Path $ImagePath -ChildPath $JpegFile.Name

    $EXIFRotationAttribute = Get-EXIFRotationAttribute $FilePath
    switch($EXIFRotationAttribute) {
      6 { RotateClockwise-JpegImage 90 $FilePath }
      3 { RotateClockwise-JpegImage 180 $FilePath }
      8 { RotateClockwise-JpegImage 270 $FilePath }
    }

    ResizeImage -ImagePath $FilePath -targetSize 1280 -OutputLocation $FilePath

  }
}

# Rotate all images on D: (including files in subdirectories)
clear
Rotate-JpegImages "D:\"