The other day, I was working with images which need me to use image EXIF rotation to show in right orientation. Which leads me to read about EXIF, so here are my notes about the same.

What is EXIF Exchange image file format is a protocol whose initial definition was produced by Japan Electronic Industries Development Association(JEIDA). It stores the various meta information of the images taken by a digital camera, which is stored as tag and value. There are many tags but for my problem Orientation (rotation) tag is of interest. The orientation tag value can be from 1 to 8 which signifies different meanings according to the position of the camera while taking the image.

EXIF Meta information from GIMP Image metadata from GIMP tool

Different Rotation EXIF rotation helps the image viewer application to show the image in the right orientation if it's compatible with the EXIF metadata. Window users might have noticed that before Window 8 image shown is without rotation, but after Window 8 all images are shown in their right orientation because of the compatibility with EXIF.

Different Rotation Above image is taken from this blog

EXIF Orientation Tag Value Row Column
1 Top Left Side
3 Bottom Right Side
6 Right Side Top
8 Left Side Bottom

What Problem I have and how EXIF meta helpful So, the issue I am trying to solve is that we need to show the user's uploaded images that can have a different orientation, to fix this we need to rotate images which can be achieved at the server or the browser side. Working with Python makes it easy to handle the image with the help of Pillow library.

Image with rotation 3 Image with different rotation

from PIL import Image

rotation_dict = {3: 180, 6: 270, 8: 90}
image =
exif_data = image._getexif()
if exif_data:
    rotation_degree = rotation_dict.get(exif_data.get(EXIF_ORIENTATION_TAG))
    if rotation_degree:
        image_file = image_file.rotate(rotation_degree)

This also can be achieved with CSS image-orientation which can be used with mostly all browser

/* keyword values */
image-orientation: none;
image-orientation: from-image; /* Use EXIF data from the image */

/* Global values */
image-orientation: inherit;
image-orientation: initial;
image-orientation: revert;
image-orientation: unset;

At last, I go with the CSS solution, which solves our use case with the least effort/code changes.


#100DaysToOffload #TIL

A data class is a class containing data only, from Python3.7 we can define a data class with the help of decorator @dataclass, which build the class with the basic functionality like __init__ , __repr__, __eq__ and more special methods.

Let see how to define your data class with the decorator @dataclass

from dataclasses import dataclass

class Batch:
    sku: int
    name: str
    qty: int

>>> Batch(1, 'desk', 100)
Batch(sku=1, name='desk', qty=100)

We can also add the default value to the data class, which works exactly as if we do in the __init__ method of regular class. As you have noticed in the above we have defined the fields with type hints, which is kind of mandatory thing in the data class, if you do not do it will not take the field in your data class.

class Batch:
    sku: int = 1
    name: str = 'desk'
    qty: int = 100

# if you don't want to explicity type the fields you can use any
from typing import Any
class AnyBatch:
    sku: Any
    name: Any = 'desk'
    qty: Any = 100

If you want to define mutable default value in data class, it can be done with the help of default_factory and field. Field() is used to customize each field in data class, different parameter that can be passed to field are default_factory, compare, hash, init, you can check about them over here

from dataclasses import dataclass, field
from typing import List

class Batch:
    sku: int
    name: str
    qty: int = 0
    creator: List[str] = field(default_factory=<function/mutable value>)

Immutable Data Class we can also define our data class as immutable by setting frozen=True, which basically means we cannot assign value to the fields after creation

class Batch:
    sku: int
    name: str
    qty: int = 0

>>> b = Batch(12, 'desk', 100)
>>> b.qty 
>>> b.qty = 90
dataclasses.FrozenInstanceError: cannot assign to field 'qty'

Data class saves us from writing boilerplate code, help us to focus on logic, this new feature of Python3.7 is great, so what waiting for go and right some data classes.


#100DaysToOffload #Python #DataClass #TIL #DGPLUG