PIL
PIL이란?
- 파이썬 이미지 처리 라이브러리
- 이미지 분석 및 처리를 쉽게 할 수 있는 라이브러리(Python Imaging Library, PIL)가 있는데 바로
pillow
모듈
- 다양한 이미지 파일 형식을 지원하며 강력한 이미지 처리와 그래픽 기능을 제공하는 이미지 프로세싱 라이브러리의 한 종류
주요 기능
- 픽셀 단위의 조작
- 마스킹 및 투명도 제어
- 흐림, 윤곽 보정, 윤곽 검출 등의 이미지 필터
- 선명도, 밝기, 명암, 색 등의 화상 조정
- 이미지에 텍스트 추가
- 기타 여러 가지
이미지 출력
Image
클래스의 Image.open()
함수를 사용하면 이미지를 불러올 수 있음
show()
함수를 사용하면 기본 이미지를 보는 프로그램이 자동으로 실행
from PIL import Image
img = Image.open(sample)
img.show()
이미지 속성 확인
- 이미지의 크기, 이름, 모드, 가로 & 세로 길이 등의 정보 확인 가능
from PIL import Image
img = Image.open(sample)
print(f'이미지 파일 이름: {img.filename}')
print(f'이미지 파일 형식: {img.format}')
print(f'이미지 용량: {img.size}')
print(f'이미지 색상 모드: {img.mode}')
print(f'이미지 너비: {img.width}')
print(f'이미지 높이: {img.height}')
이미지 크기 변경
- 이미지 크기는
resize()
함수를 사용하여 변경
from PIL import Image
img = Image.open(sample)
resize_img = img.resize((800, 800))
resize_img.save(resize_sample)
img = Image.open(sample)
(width, height) = (img.width//2, img.height//2)
resize_img = img.resize((width, heith))
resize_img.save(resize_sample)
이미지 자르기
- 이미지를 자르기 위해서는
crop()
함수를 사용
crop()
함수의 인자값은 튜플 자료형으로 4개이며 왼쪽, 위, 오른쪽, 아래 순으로 값을 대입
crop((left, upper, right, lower))
from PIL import Image
img = Image.open(sample)
cropped_img = img.crop((100, 100, 200, 200))
cropped_img.show()
이미지 회전
- Image 클래스의 rotate() 함수를 사용하면 이미지를 원하는 각도만큼 회전 가능
from PIL import Image
img = Image.open(sample)
img.rotate(45).show()
OSError
OSError: image file is truncated
해결 방법
LOAD_TRUNCATED_IMAGES
- 위 변수를
True
로 바꿔주면 에러 없이 동작할 수 있음
PIL
의 ImageFile.py
를 들어가면 해당 변수가 default
값이 False
로 설정되어 있는데, True
로 바꾸면 truncated image
도 로드하겠다는 설정을 하는 것
from PIL import (
Image,
ImageFile,
)
ImageFile.LOAD_TRUNCATED_IMAGES = True
try:
image = Image.open(sample)
image = image.convert('RGB')
...
finally:
ImageFile.LOAD_TRUNCATED_IMAGES = False
try-except
- 이미지를 로드에 성공했지만 해당 이미지가 잘린 이미지라는 것을 확인하려면 어떻게 해야 할까?
- 로드를 하려면 이미지를 읽을 수 없는 부분을 무시하고 지나가는 것인데, 잘렸다는 것을 어떻게 확인할 수 있을까?
pillow
를 통해 확인할 수 있는 방법은 try-except
- 일단 에러를 내고
except
에서 OSError
를 캐치해서 처리
truncated image
는 open
시에는 에러가 발생하지 않기 때문에 에러가 생길 수 있는 부분부터 try-except
에 넣어줌
from PIL import (
Image,
ImageFile,
)
image = Image.open(sample)
try:
image = image.convert('RGB')
...
except OSError as e:
...
이미지 파일의 구조를 이용
- 이미지 파일의 구조를 이용해
truncated
여부를 찾는 방법
LOAD_TRUNCATED_IMAGES
는 글로벌 변수이기 때문에 여러 스레드에서 해당 변수를 계속 True
에서False
로 바꿔줄 경우 thread-safe
하지 않음
- JPG, JPEG, PNG 파일의 경우 파일의 구조가 정해져있고, 이미지 파일의 끝과 시작을 나타내는 바이트 값이 고정되어 있음
- 이 고정된 값의 이름을 JPEG, JPG는 EOI (End Of Image), PNG는 IEND라고 함
- 만약 이미지가 JPG(JPEG)면, EOI(0xff 0xd9)로 끝나야 함
- 만약 이미지가 PNG면, IEND(49 45 4e 44 ae 42 60 82)로 끝나야 함
- 그런데
truncated file
의 경우 이 값이 고정된 값과 다르게 나타나게 됨
from PIL import Image
from io import BytesIO
image = Image.new("RGB",(64,48))
bytes = BytesIO()
image.save(bytes, format="JPEG")
buff = bytes.getbuffer()
print(buff[-2:].hex())
>>> ffd9
from PIL import Image
from io import BytesIO
image = Image.new("RGB",(64,48))
bytes = BytesIO()
image.save(bytes, format="PNG")
buff = bytes.getbuffer()
print(buff[-8:].hex())
>>> 49454e44ae426082
- 기존에 있는 이미지를 가져와 검사하는 경우
truncated image
는 save()
하게 되면 에러 발생