Search code examples
pythondjangosorl-thumbnail

Sorl-thumbnail generates black lines and undesired crops


I'm using Sorl Thumbnail 12.4a1, Pillow 4.0.0 in a django project

It works fine for most images but for some of them I run into unexpected behaviour.

The original image is portrait jpg 765x1110

After running this code: get_thumbnail('/media/ryzsUIKZVUc.jpg', '464', upscale=False)

I receive a 464x320 image with black background on it's left and right and cropped on top and bottom

this is the original: https://www.dropbox.com/s/ia7906ec19xjhro/ryzsUIKZVUc.jpg?dl=0

and this is the result: https://www.dropbox.com/s/adgut5zkw4xln6e/62b2439654a00312defafddb862eda9b.jpg?dl=0

p.s. tried to upload the original here as an image but it was automatically converted to portrait.. could it mean something?


Solution

  • The frame appears because of the exif tag. The size of the image is not correctly determined.

    You can see this using exiftool:

    $ exiftool ryzsUIKZVUc.jpg 
    ExifTool Version Number         : 10.10
    File Name                       : ryzsUIKZVUc.jpg
    Directory                       : .
    File Size                       : 210 kB
    File Modification Date/Time     : 2017:03:30 12:33:51+03:00
    File Access Date/Time           : 2017:03:30 12:33:55+03:00
    File Inode Change Date/Time     : 2017:03:30 12:33:51+03:00
    File Permissions                : rw-rw-r--
    File Type                       : JPEG
    File Type Extension             : jpg
    MIME Type                       : image/jpeg
    JFIF Version                    : 1.01
    Comment                         : CREATOR: gd-jpeg v1.0 (using IJG JPEG v62), quality = 99.
    Exif Byte Order                 : Big-endian (Motorola, MM)
    Processing Software             : Windows Photo Editor 10.0.10011.16384
    Orientation                     : Rotate 270 CW
    Software                        : Windows Photo Editor 10.0.10011.16384
    Modify Date                     : 2017:03:07 09:28:15
    Date/Time Original              : 2017:03:07 09:27:46
    Create Date                     : 2017:03:07 09:27:46
    Sub Sec Time Original           : 00
    Sub Sec Time Digitized          : 00
    Color Space                     : sRGB
    Padding                         : (Binary data 2060 bytes, use -b option to extract)
    Compression                     : JPEG (old-style)
    X Resolution                    : 96
    Y Resolution                    : 96
    Resolution Unit                 : inches
    Thumbnail Offset                : 4608
    Thumbnail Length                : 8169
    About                           : uuid:faf5bdd5-ba3d-11da-ad31-d33d75182f1b
    Creator Tool                    : Windows Photo Editor 10.0.10011.16384
    Image Width                     : 1110
    Image Height                    : 765
    Encoding Process                : Baseline DCT, Huffman coding
    Bits Per Sample                 : 8
    Color Components                : 3
    Y Cb Cr Sub Sampling            : YCbCr4:2:0 (2 2)
    Image Size                      : 1110x765
    Megapixels                      : 0.849
    Create Date                     : 2017:03:07 09:27:46.00
    Date/Time Original              : 2017:03:07 09:27:46.00
    Thumbnail Image                 : (Binary data 8169 bytes, use -b option to extract)
    

    Or use PIL

    >>> from PIL import Image
    >>> from PIL.ExifTags import TAGS
    >>> 
    >>> im = Image.open('ryzsUIKZVUc.jpg')
    >>> exif = im._getexif()
    >>> data = {}
    >>> 
    >>> for tag, value in exif.items():
    ...     decoded = TAGS.get(tag, tag)
    ...     data[decoded] = value
    ... 
    >>> 
    >>> data['Orientation']
    8
    

    To fix this, you can before generating a preview, (rotate image) save the picture without this tag.

    For example,

    def orient(image_path):
        """ Check are this img oriented """
        img = Image.open(image_path)
        # check is has exif data
        if not hasattr(img, '_getexif') or img._getexif() is None:
            return
        # if has information - try rotate img
        orientation = img._getexif().get(0x112)
        rotate_values = {3: 180, 6: 270, 8: 90}
        if orientation in rotate_values:
            img = img.rotate(rotate_values[orientation], expand=True)
        img.save(image_path, quality=100)
    

    Or easier, change the settings THUMBNAIL_ORIENTATION = False. In this case, the image simply stops rotating. And no more black lines are created.