Image operationes

Image operation cases: 1.Add text to image; 2.Resize multiple images.

Case 1: Add a number on the picture

Question: Put a red number on the upper right corner of your profile picture, similar to the effect of numbers of unread messages.

Steps:

  • Get the path and name of image.

Here I use sys.argv() to get the path and name of the image.

import sys

if __name__ == '__main__':
    add_number(sys.argv[1]) 

Remember that sys.argv[0] is the name of the script. sys.argv[1] is what I needed

  • Get the path of image

I use a regular expression to describe then path, then save it into “path” viable.

pattern = re.compile('(.*\/).*')
    path = re.findall(pattern,path_file)[0]
    
'''The idea is to capture all the content to the last slash by using (.*\/) 
and discard the rest .*. '''

  • Add a text to image

PIL have a methode as below:

ImageDraw.Draw.text(xy, text, fill=None, font=None, anchor=None)

We need to find a font for our text. It takes me a while to find a useable font file in my Macbook.

/System/Library/Fonts/Apple Symbols.ttf

Here is the complete code:

from PIL import Image
from PIL import ImageFont
from PIL import ImageDraw 
import sys
import re

def add_number(path_file):
    '''
    Get a file with its path as arguments of function "add_number",
     use draw.txt to add a txt on to the image, 
     and save the new image to the same location.
     '''
    im = Image.open(path_file)
    
    pattern = re.compile('(.*\/).*')
    path = re.findall(pattern,path_file)[0]
    # get a jpeg file
    font = ImageFont.truetype('/System/Library/Fonts/Apple Symbols.ttf', 50) 
    #get a font type file,and size 
    draw = ImageDraw.Draw(im) 
    #get a draw object
    w,h = im.size 
    draw.text((w-50,0), "8", (255,0,0), font=font)
    # locate "8" at right-up corner
    im.save((path+"add number.jpeg"), "jpeg") 

if __name__ == '__main__':
    add_number(sys.argv[1]) 

The result looks like this:

test

Case 2: Resize all pictures in a folder

Question: There is a folder, have a lot of photos, resize them into no more than the size of iPhone5 resolution.

Steps:

  • What does iPhone5 resolution means?

640*1136 pixel (or smaller)

  • How to keep the original width/height ratio of pictures when resize them.

    • We don’t need to resize it if the picture is smaller than 640*1136.
    • Because we also don’t want to change the width/height ratio of pictures. So we need to resize according to the bigger diffrence between height and width.
  rate = max(img.size[0]/640.0 if img.size[0] > 640 else 0, img.size[1]/1136.0 if img.size[1] > 1136 else 0)
  • Get all image files from a folder

We defined a function called “run” to use os.walk to go through all the path of given folder, and get all image fils for function “process_image” to resize.

 def run(directory): #get all pictures from folder
    '''
    Get "directory" as arguments of function "run",
     find all image file which have their type in "img_types" , 
     call function "process_image" to resize them.
     '''
    img_types = ['.png','.jpeg','.bmp','.JPG']
    for root, dirs, files in os.walk(directory):
        for name in files:
            if os.path.splitext(name)[1] in img_types:
                img_file = img.open(directory+"/" + name)
                process_image(img_file,os.path.splitext(name),directory)
  • Resize all pictures and save them

Function “process_image” takes image them selves, their names and their pathes as prameters, resize images by using “thumbnail “, then save them.

Here is the complete code:

from PIL import Image as img
import os
import os.path
import sys

def run(directory): #get all pictures from folder
    '''
    Get "directory" as arguments of function "run",
     find all image file which have their type in "img_types" , 
     call function "process_image" to resize them.
     '''
    img_types = ['.png','.jpeg','.bmp','.JPG']
    for root, dirs, files in os.walk(directory):
        for name in files:
            if os.path.splitext(name)[1] in img_types:
                img_file = img.open(directory+"/" + name)
                process_image(img_file,os.path.splitext(name),directory)

def process_image(img,name,directory): # resize pics to 640*1136(or smaller)
    '''
    Get "img", "name"and "directory" as arguments of function "process_image",
     resize images to 640*1136 or smaller, and keep their own w/h ratio.
     save new images to the same directory with "_resize" added to their old name.
     '''
    img_w,img_h = img.size
    rate = max(img_w/640.0 if img_w > 640 else 0, img_h/1136.0 if img_h > 1136 else 0)
    # get a rate for resize
    if rate:
        img.thumbnail((img_w/rate, img_h/rate))
    img.save(directory+ name[0]+"_resize"+".jpeg", "jpeg")            

if __name__ == '__main__':
    run(sys.argv[1])   
May 18, 2017