Jpegs incorrectly rotated when importing with imager

Viewed 50

I was working on a project that involved reading many jpeg images into R and combining them into a single plot. However, there are some images that would be rotated incorrectly after import. This is what I see if I open the file on my computer

Sample image with correct orientation

But when I read the image into R, it's rotated. Here's a reproducible example with a link to the sample image

library(imager)
url <- "https://raw.githubusercontent.com/MrFlick/readexif/main/inst/extdata/LookUp.jpg"
download.file(url, "sample.jpg", mode="wb")
img <- load.image("sample.jpg")
plot(img)

Image after import, rotated

(note that the problem does NOT occur if you read the version of the image that's downloaded from imgur url <- "https://i.stack.imgur.com/7pS4x.jpg")

How can I correctly read such images into R without "fixing" each one individually?

1 Answers

The problem is that the jpeg file has a metadata attribute which most computers and web browsers pay attention to, but imager::load.image does not. (Same goes for jpeg::readJPEG as well).

The specific metadata for rotation comes from the Exif Orientation tag. The Orientation tag can have one of 8 values indicating a different rotation/reflection.

effects of different orientation values
(image source: https://www.impulseadventure.com/photo/exif-orientation.html)

So in order to correctly "fix" the image, you need to determine the orientation from the Exif metadata in the file. There is an existing package on CRAN to read Exif data called exifr but that package has a dependency on a Perl tool. I created a new package to read the Exif data using only R called readexif. So, however you like, you need to extract the correct orientation value and adjust the image accordingly. Here's a wrapper function that can help

library(imager)
load_image <- function(path, orientation) {
  pic <- load.image(path)
  if (missing(orientation)) {
    # remotes::install_github("MrFlick/readexif")
    orientation <- readexif::exif_value(path, "Orientation", fill_value=1)
  }
  if (orientation %in% 3:4) {
    pic <- mirror(pic, "y")
  } else if (orientation %in% 5:6) {
    pic <- imrotate(pic, 90)
  } else if (orientation %in% 7:8) {
    pic <- imrotate(pic, -90)
  }
  if (orientation %in% c(2, 3, 5, 7)) {
    pic <- mirror(pic, "x")
  }
  pic
}

So we can now read the file with the correct orientation

img <- load_image("sample.jpg")
plot(img)

Sample image read with correct orientation

The problem doesn't happen when using the imgur version because it seems the imgur website strips out all the Exif metadata and properly rotates the image for you.

Related