Crop the image to rounded corners with pythonista

environment

iOS 13.3 pythonista3 ver. 3.2

Motivation

When I was making an iOS home screen-like app with pythonista, I wanted to crop the icon image to rounded corners, so I researched various things.

Directory structure

It is assumed that you are executing with the following structure.

root/  ├ icons/  └ exe/    └ iconEditor.py

Program body

iconEditor.py



from PIL import Image, ImageDraw, ImageFilter
import photos
import pathlib

def crop_center(pil_img, crop_width, crop_height):
	img_width, img_height = pil_img.size
	return pil_img.crop((
		(img_width - crop_width) // 2,
		(img_height - crop_height) // 2,
		(img_width + crop_width) // 2,
		(img_height + crop_height) // 2
		))

def crop_max_square(pil_img):
	return crop_center(pil_img, min(pil_img.size), min(pil_img.size))

def make(pil_img, r=100, fil=True):
	mask = DrawBack(pil_img, r)
	if fil:
		mask = mask.filter(ImageFilter.SMOOTH)
	result = pil_img.copy()
	result.putalpha(mask)

	return result


def DrawBack(img, r=100):
	#Draw a rounded square[3]Refer to. Rather, it's almost a copy.
	mask = Image.new("L", img.size, 0)
	draw = ImageDraw.Draw(mask)
	rx = r
	ry = r
	fillcolor = "#ffffff"
	draw.rectangle((0,ry)+(mask.size[0]-1,mask.size[1]-1-ry), fill=fillcolor)
	draw.rectangle((rx,0)+(mask.size[0]-1-rx,mask.size[1]-1), fill=fillcolor)
	draw.pieslice((0,0)+(rx*2,ry*2), 180, 270, fill=fillcolor)
	draw.pieslice((0,mask.size[1]-1-ry*2)+(rx*2,mask.size[1]-1), 90, 180, fill=fillcolor)
	draw.pieslice((mask.size[0]-1-rx*2,mask.size[1]-1-ry*2)+
	(mask.size[0]-1,mask.size[1]-1), 0, 180, fill=fillcolor)
	draw.pieslice((mask.size[0]-1-rx*2,0)+
	(mask.size[0]-1,ry*2), 270, 360, fill=fillcolor)
	return mask

	
def iconGenerate(iconpath, r=100):
	im = Image.open(iconpath)
	
	newname = ''.join(['../icons/', str(pathlib.Path(iconpath).stem), '.PNG'])
	thumb_width = 300

	im_square = crop_max_square(im).resize((thumb_width, thumb_width), Image.LANCZOS)
	im_thumb = make(im_square, r, False)
	im_thumb.save(newname)
	return im_thumb
	
if __name__ == '__main__':
	temp = pathlib.Path('../icons')
	for p in temp.iterdir():
		print('・' + p.name)
	
	isfin = False
	while not(isfin):
		print('which file?(if new, input new)')
		fname = input()
		
		if fname == 'new':
			asset = photos.pick_asset(title='Pick a image', multi=False)
			try:
				image = asset.get_image()
				print('Input new name with .png or .PNG')
				newname = input('newname : ')
				image.save('../icons/'+newname)
				fname = newname
				
			except AttributeError:
				#This error occurs because it is none if no selection is made
				print('Nothing chosen.')
				continue
			
		try:
			r = int(input('r : '))
			im = iconGenerate('../icons/'+fname, r)
			print('Success!')
			im.show()
			isfin = True

		except Exception as e:
			print(e)
			print('Some Error Occored')

		print('Exit?(y / n)')
		ans = input()
		isfin = False if ans == 'n' else True
		## End while
	print('Exit this file.')

About each function

crop_center(pil_img, crop_width, crop_height) crop_max_square(pil_img)

Copy and paste from Site in reference [1].

make(pil_img, r=100, fil=True)

pil_img: PIL image object r: Radius of the rounded circle part? ?? fil: Presence or absence of filter. You may not need it.

Based on the mask_circle_transparent function of Site in Reference [2], the mask is simplified and rounded.

DrawBack(img, r=100) img: PIL image object r: Radius of the rounded circle part?

This is a functionalized version of the program of Site in Reference [3]. For the convenience of creating a square image called an icon image, radii rx and ry use r with equal values.

iconGenerate(iconpath, r=100) iconpath: Path to the storage location of the image you want to use r: Radius of the rounded circle part?

The main part of this program.


im = Image.open(iconpath)
	
newname = ''.join(['../icons/', str(pathlib.Path(iconpath).stem), '.PNG'])
thumb_width = 300

First, create a PIL image object from the path and decide on a save name. Creating a Path object with pathlib.Path (iconpath), stem extracts only the filename (without the extension) from the path. I cast it with str and join it with join.

thumb_width determines the length of one side of the square. The variable names used on the sites [1] and [2] are used as they are.


im_square = crop_max_square(im).resize((thumb_width, thumb_width), Image.LANCZOS)
im_thumb = make(im_square, r, False)

im_thumb.save(newname)
return im_thumb

im_square crops the image to a square. See [1] and [2]. The corners are covered with im_thumb. Then I save it and return the image.

if \ _ \ _ name \ _ \ _ =='\ _ \ _ main \ _ \ _'The following part

I think it's a slapstick, but I will explain the behavior when the entire program is copied and operated.


temp = pathlib.Path('../icons')
for p in temp.iterdir():
	print('・' + p.name)

The path of the file in the save location is generated by the Path object, and the files in that folder are listed. isfin is a variable that terminates the while loop if True.


if fname == 'new':
			asset = photos.pick_asset(title='Pick a image', multi=False)
			try:
				image = asset.get_image()
				print('Input new name with .png or .PNG')
				newname = input('newname : ')
				image.save('../icons/'+newname)
				fname = newname
				
			except AttributeError:
				#This error occurs because it is none if no selection is made
				print('Nothing chosen.')
				continue

Select the image to be applied next by referring to the list.

If you choose directly from the photo app, type new.

If you enter new, the photo will be displayed. It may not be displayed unless it is a recently saved photo. In general


asset = photos.pick_asset(title='Pick a image', multi=False)
try:
	image = asset.get_image()

except AttributeError:
	print('Nothing chosen.')

image.save(path)

By doing so, you can save the image in the path specified by the program.


r = int(input('r : '))
im = iconGenerate('../icons/'+fname, r)
print('Success!')
im.show()
isfin = True

print('Exit?(y / n)')
ans = input()
isfin = False if ans == 'n' else True

Converts the image with the entered file name and saves it. It will be displayed after conversion to the console with im.show (). (Verification) After that, ask if you want to convert again, and if you answer something other than n, you will enter the while loop again.

Postscript

If you have any bugs that occurred using this program, please leave a comment. Isn't it better to do this in terms of readability? Please also actively comment such as! I'm not very good at it, so I'd love to hear your feedback.

References

[1] Crop a part of the image with Python, Pillow (crop / crop) [2] Create square and circular thumbnail images at once with Python and Pillow [3] About image processing: Draw rounded squares using Pillow

Recommended Posts

Crop the image to rounded corners with pythonista
How to crop the lower right part of the image with Python OpenCV
How to crop an image with Python + OpenCV
The road to Pythonista
Convert the image in .zip to PDF with Python
Dot according to the image
I tried to find the entropy of the image with python
Try blurring the image with opencv2
Convert PDF to image with ImageMagick
I tried to process the image in "sketch style" with OpenCV
Consider the speed of processing to shift the image buffer with numpy.ndarray
I tried to process the image in "pencil style" with OpenCV
HTML email with image to send with python
Image classification with Keras-From preprocessing to classification test-
Image display taken with the built-in ISIGHT
Play around with the pythonista3 ui module
Introduction to Python Image Inflating Image inflating with ImageDataGenerator
Try to image the elevation data of the Geographical Survey Institute with Python
[Image recognition] How to read the result of automatic annotation with VoTT
Add images to iOS photos with Pythonista
Right-click the image → realize "Compress with TinyPNG"
I tried playing with the image with Pillow
Match the colorbar to the figure with matplotlib
Try to generate an image with aliasing
The road to compiling to Python 3 with Thrift
Sample to convert image to Wavelet with Python
How to publish a blog on Amazon S3 with the static Blog engine'Pelican'for Pythonista
Former image processing engineer tried to solve Saizeriya's spot the difference with OpenCV
How to display in the entire window when setting the background image with tkinter
I want to crop the image along the contour instead of the rectangle [python OpenCV]
Mouse over Matplotlib to display the corresponding image
Try to solve the fizzbuzz problem with Keras
I tried "smoothing" the image with Python + OpenCV
Log in to the remote server with SSH
Try adding fisheye lens distortion to the image
The easiest way to get started with Django
How to specify the NIC to scan with amazon-dash
Convert PDF to image (JPEG / PNG) with Python
I tried "differentiating" the image with Python + OpenCV
I tried to save the data with discord
The easiest way to synthesize speech with python
Try to solve the man-machine chart with Python
Specify the Python executable to use with virtualenv
I wanted to play with the Bezier curve
How to try the friends-of-friends algorithm with pyfof
Say hello to the world with Python with IntelliJ
I tried to correct the keystone of the image
Determine the numbers in the image taken with the webcam
Detect folders with the same image in ImageHash
I tried "binarizing" the image with Python + OpenCV
The easiest way to use OpenCV with python
Mathematics memorandum to keep up with the field # 1
Route guidance to iPhone photography location with Pythonista
Introduction to Python with Atom (on the way)
Save the object to a file with pickle
Mathematics memorandum to keep up with the field # 2
How to Learn Kaldi with the JUST Corpus
Try to make client FTP fastest with Pythonista
Post an article with an image to WordPress with Python
Mathematics memorandum to keep up with the field # 3
Display the image after Data Augmentation with Pytorch