惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Recent Announcements
Recent Announcements
博客园 - Franky
博客园 - 三生石上(FineUI控件)
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Apple Machine Learning Research
Apple Machine Learning Research
云风的 BLOG
云风的 BLOG
人人都是产品经理
人人都是产品经理
博客园 - 【当耐特】
L
LangChain Blog
Stack Overflow Blog
Stack Overflow Blog
H
Help Net Security
爱范儿
爱范儿
罗磊的独立博客
博客园_首页
美团技术团队
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
月光博客
月光博客
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
量子位
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 叶小钗
V
Visual Studio Blog
T
Tailwind CSS Blog

jdhao's digital space

Conversion between base64 and OpenCV or PIL Image 腾讯云对象存储博客图床开启 CDN 加速(不需要购买额外域名) Search and Replace in Multiple Files in Vim/Neovim Change Table Column Width in LaTeX Image or Table Side by Side in LaTeX LaTeX 并排显示图像或表格 Firenvim: Neovim inside Your Browser Content inside HTML tags missing in Latest Hugo? Creating Markdown Front Matter with Ultisnips Labelme JSON 标注格式转 voc XML 格式 Nifty Nvim Techniques That Make My Life Easier -- Series 6 macOS 下如何为视频制作字幕 Running Command Asynchronously inside Neovim Resolving Merge Conflict after Git Stash Pop Pylint: command not found? A Hands-on Experience with Neovim's Built-in LSP Support How to Convert PDF to Images with Imagemagick 互联网上常用缩略语集锦 File Backup in Neovim Converting PDF Pages to Images with Poppler Nifty Nvim Techniques That Make My Life Easier -- Series 5 Neovim Configuration for System-wide Use How to sort a list of tuple or list in Python -- lambda or itemgetter? Building A Vim Statusline from Scratch 人类第一颗原子弹爆炸始末 Distributed Training in PyTorch with Horovod Learning Expect Programming Essential Knowledge about SSH Nifty LaTeX Techniques -- Series 1 更改 Adsense 邮寄地址,重新寄送 PIN
JPEG Image Orientation and Exif
2019-07-31 · via jdhao's digital space

The other day I came across a strange bug during work. My colleagues gave me some photographs taken with a smartphone. On their machines (Windows 7), all the photos were shown correctly in landscape mode. However, when I checked those photos, I found that some of those photos were shown in portrait mode (rotated 90 or 270 degrees) or upside-down (rotated 180 degrees).

I was curious what happened and learned about Exif and all its related stuff.

How Does Exif Orientation Work#

What is Exif#

Exif (Exchangeable image file format) is a protocol to store various meta-information about the images taken by digital cameras. Exif are stored along with the actual image data. Some of the meta info in Exif includes camera maker, shutter speed, focal length, orientation, shooting time etc. These meta info is called tags and each tag has a specific tag number decided by the Exif format standard. A comprehensive list of tags and their related informations can be found here.

Here, we are interested in the orientation meta info. When we are taking photos with a camera, we may not always hold the camera in such a position that the camera top corresponds to top of the scene. Image below from this blog illustrates this idea clearly:

But no matter how you are holding the camera, if you check the image on your computer, the image is shown in correct orientation. This has something to do with Exif orientation flag. When you are holding the camera with non-upright position, the raw photo you take is stored as a rotated image. The digital device (be a smartphone or digital camera) has a sensor to record the orientation of the camera and writes that information into orientation flag in Exif.

The Exif orientation flag can have nine different values from 1 to 91. The image2 below shows eight of them:

Typically, you will only get flag 1, 8, 3, 6 for digital photos. Flag 2, 7, 4, 5 represent mirrored and rotated version of images.

Why Are My Images Wrongly Displayed?#

When you use a photo viewer to check the image on your computer, if the photo viewer can read the Exif info and respects that info, it will automatically rotate the raw image based on the orientation info. The end result is that you can see the correctly-oriented photo no matter how it is actually stored.

Now come to the issue in the beginning of this post. According to this article, Windows systems before Windows 8 does not take into account the Exif orientation flag and show the images as is, i.e., the raw, un-rotated images are shown instead of the properly rotated images. Since the images my colleagues gave me are shown correctly on their Windows 7 machine, we can draw a conclusion that the raw images are in correct orientation. Somehow, the smartphone is reporting the wrong orientation flags for some of the photos. When I show these photos on my Windows 10 machine, since Windows 10 respects the orientation flag, some of the images will be shown as rotated due to the false orientation flag.

On the other hand, if you see correct photo on Windows 10 but rotated one on a Windows 7 machine, that is because the raw image is in rotated position and Windows 7 does not respect the orientation info in Exif.

Read and Write Exif Info#

IrfanView#

IrfanView is a great image viewer on Windows, which respects the image Exif info. To view the image Exif info, open an image and click Image -> Information. If the image contains Exif info, you can then click the EXIF info button at the bottom left of the popup window to check the image Exif info.

Disable Auto-rotate for IrfanView#

By default, IrfanView respects the Exif info and will auto-rotate the image based on its orientation flag. To disable this behavior, go to Options -> Properties/Settings, click JPG/PCD/GIF and uncheck the box Auto-rotate image according to EXIF info (if available).

Pillow and Exif Info#

If you read an image with Pillow and show it or save it again, Pillow will not respect the Exif orientation tag. You may see such issues here and here. There is a pull request to address this issue, which has been merged now.

Pillow is able to read the image Exif info, but it is not able to edit the Exif info. A sample script to show the image Exif info is shown below:

from PIL import Image
from PIL. from PIL.ExifTags import TAGS

img = Image.open('test.jpg')

exif = img.getexif()

for k, v in exif.items():
    print('{}: {}'.format(TAGS[k], v))

In the above script, We use the Image.getexif()3 to retrieve the image Exif info. TAGS is a dictionary mapping the tag number to a descriptive name.

Piexif#

The Python package piexif can be used to both read and write the image Exif info.

Based on the example on its documentation site, I show an example of change the image Exif orientation flag and save a new image using the new Exif info.

from PIL import Image
import piexif

img = Image.open('test.jpg')
if "exif" in img.info:
    exif_dict = piexif.load(img.info['exif'])

if piexif.ImageIFD.Orientation in exif_dict['0th']:
    exif_dict['0th'][pixeif.ImageIFD.Orientation] = 3

    # quick and dirty work around to avoid type error
    exif_dict['Exif'][41729] = b'1'

    exif_bytes = piexif.dump(exif_dict)

img.save('new_img.jpg', exif=exif_bytes)

The primary info of Exif are stored in the 0th key of exif_dict, which is also a Python dictionary. It seems that piexif did not check the value type of the Exif dict so that we may encounter ValueError when we try to dump the exif_dict. After reading the source code of piexif, I use the following line of code to work around this issue just for now.

exif_dict['Exif'][41729] = b'1'

After that, you should be able to dump the exif_dict without errors.

References#