커뮤니티에서 더 이상 Python 2를 더 이상 지원하지 않습니다. Python 2 앱을 Python 3로 마이그레이션하는 것이 좋습니다.

Python 2용 Images API 개요

App Engine은 전용 이미지 서비스를 사용하여 이미지 데이터를 조작할 수 있는 기능을 제공합니다. 이미지 서비스는 이미지를 조작하고, 여러 이미지를 단일 이미지로 합성하고, 이미지 형식을 변환하고, 형식, 너비, 높이, 색상 값 히스토그램과 같은 이미지 메타데이터를 제공할 수 있습니다.

이미지 서비스는 앱에서 직접 이미지 데이터를 받거나 Google Cloud Storage 값을 사용할 수 있습니다. (이미지 서비스는 Cloud Blobstore 값도 사용할 수 있지만 Cloud Storage를 사용하는 것이 좋습니다.)

Cloud Storage와 Cloud Blobstore에 저장되는 이미지는 해당 서비스의 최대 허용 값까지 가능합니다. 변환된 이미지는 앱으로 직접 반환되며 크기가 32MB 미만이어야 합니다.

Python 2에서 이미지 변환

다음 예는 Cloud Datastore에서 이미지 데이터를 로드한 후 이미지 서비스를 사용하여 크기를 조절하고 JPEG 이미지로 브라우저에 반환합니다.

from google.appengine.api import images
from google.appengine.ext import ndb

import webapp2

class Photo(ndb.Model):
    title = ndb.StringProperty()
    full_size_image = ndb.BlobProperty()

class Thumbnailer(webapp2.RequestHandler):
    def get(self):
        if self.request.get("id"):
            photo = Photo.get_by_id(int(self.request.get("id")))

            if photo:
                img = images.Image(photo.full_size_image)
                img.resize(width=80, height=100)
                img.im_feeling_lucky()
                thumbnail = img.execute_transforms(output_encoding=images.JPEG)

                self.response.headers['Content-Type'] = 'image/jpeg'
                self.response.out.write(thumbnail)
                return

        # Either "id" wasn't provided, or there was no image with that ID
        # in the datastore.
        self.error(404)

Images API 외에도 Python Imaging Library(PIL)에 제공된 변환을 Python 2.7 앱에서 사용할 수 있습니다. app.yaml 파일의 libraries 섹션에서 라이브러리를 선언하기만 하면 됩니다. 그러나 개발 서버를 사용하는 로컬 환경에서 PIL을 사용하려면 로컬에 pillow 또는 PIL을 다운로드하고 설치해야 합니다.

사용 가능한 이미지 변환

이미지 서비스는 이미지의 크기 조절, 회전, 뒤집기, 자르기를 수행하고 사진을 보정할 수 있습니다. 또한 여러 이미지를 단일 이미지로 합성할 수 있습니다.

크기 조절

가로 세로 비율을 동일하게 유지하면서 이미지 크기를 조절할 수 있습니다. 크기가 조절된 이미지의 너비 또는 높이는 4,000픽셀을 초과할 수 없습니다.

회전

이미지를 90도 간격으로 회전할 수 있습니다.

수평으로 뒤집기

이미지를 수평으로 뒤집을 수 있습니다.

수직으로 뒤집기

이미지를 수직으로 뒤집을 수 있습니다.

자르기

제공된 경계 상자로 이미지를 자를 수 있습니다.

I'm Feeling Lucky

'I'm Feeling Lucky' 변환은 이미지의 어두운 색과 밝은 색을 보정하고, 색상을 조정하고, 대비를 최적화합니다.

이미지 형식

서비스에 JPEG, PNG, WEBP, GIF(애니메이션 GIF 포함), BMP, TIFF, ICO 형식의 이미지 데이터를 입력할 수 있습니다. 변환된 이미지는 JPEG, WEBP, PNG 형식으로 반환될 수 있습니다.

입력 형식과 출력 형식이 서로 다른 경우 서비스는 변환을 수행하기 전에 입력 데이터를 출력 형식으로 변환합니다.

이미지 변환

이미지 서비스는 변환할 이미지의 소스로 Google Cloud Storage 또는 Blobstore의 값을 사용할 수 있습니다. 이미지를 변환하는 방법에는 두 가지가 있습니다.

  1. Image() 클래스를 사용하면 자르기, 뒤집기, 회전과 같은 간단한 이미지 변환을 수행할 수 있습니다.
  2. get_serving_url()을 사용하면 이미지 크기 조절 및 자르기를 동적으로 수행할 수 있으므로 서버에 이미지를 여러 가지 크기로 저장할 필요가 없습니다. 이 메서드는 이미지를 제공하는 URL을 반환하고 이미지에 대한 변환은 이 URL에 인코딩됩니다. 이 함수는 이미지가 변경되지 않는다고 가정합니다. 따라서 URL을 가져온 후에 이미지를 수정하면 URL을 사용할 때 예기치 않은 결과가 발생할 수 있습니다.

Image() 클래스 사용

이미지 크기가 Cloud Storage 또는 Blobstore에서 허용하는 최대 크기보다 작은 경우, Cloud Storage 또는 Blobstore의 이미지를 변환할 수 있습니다. 변환 결과는 앱에 직접 반환되며 API 응답 한도인 32MB를 초과할 수 없습니다.

Python 2에서 Cloud Storage 또는 Blobstore의 이미지를 변환하려면 Image 생성자의 image_data 인수를 이미지 데이터로 설정하는 대신 blob_key 인수를 값이 이미지인 Blobstore 키로 설정합니다. API의 나머지 동작에는 차이가 없습니다. execute_transforms() 메서드는 변환 결과를 반환하거나 결과가 최대 크기인 32MB보다 크면 LargeImageError 오류가 발생합니다.

from google.appengine.api import images
from google.appengine.ext import blobstore

import webapp2

class Thumbnailer(webapp2.RequestHandler):
    def get(self):
        blob_key = self.request.get("blob_key")
        if blob_key:
            blob_info = blobstore.get(blob_key)

            if blob_info:
                img = images.Image(blob_key=blob_key)
                img.resize(width=80, height=100)
                img.im_feeling_lucky()
                thumbnail = img.execute_transforms(output_encoding=images.JPEG)

                self.response.headers['Content-Type'] = 'image/jpeg'
                self.response.out.write(thumbnail)
                return

        # Either "blob_key" wasn't provided, or there was no value with that ID
        # in the Blobstore.
        self.error(404)

get_serving_url() 사용

Images API 외에도 Python Imaging Library(PIL)에 제공된 변환을 Python 2.7 앱에서 사용할 수 있습니다. 이를 사용하려면 app.yaml 파일의 libraries 섹션에서 라이브러리를 선언합니다.

개발 서버에서 PIL을 사용하려면 로컬에 pillow 또는 PIL을 다운로드하고 설치해야 합니다.

get_serving_url() 메서드를 사용하면 Cloud Storage 또는 Blobstore에 저장된 이미지의 고정된 전용 URL을 생성할 수 있습니다. 예를 들면 다음과 같습니다.

url = images.get_serving_url(
    blob_key, size=150, crop=True, secure_url=True)

생성된 URL은 애플리케이션과 분리되어 있는 고도로 최적화된 이미지 제공 인프라를 사용합니다. 이미지는 앱과 독립적으로 제공되므로 부하가 발생하지 않으며 비용 효율성이 매우 높습니다. 이 메서드가 반환하는 URL은 항상 공개적으로 액세스할 수 있지만 추측은 불가능합니다.

URL 제공을 중지하려면 delete_serving_url() 함수를 사용하여 해당 URL을 삭제합니다.

이 메소드는 지정된 크기와 자르기 인수로 인코딩된 URL을 반환합니다. 인수를 지정하지 않으면 다음과 같이 이미지의 기본 URL을 반환합니다.

http://lhx.ggpht.com/randomStringImageId

URL에 인수를 지정하여 동적으로 이미지 크기를 조정하고 자를 수 있습니다. 사용 가능한 인수는 다음과 같습니다.

  • =sxx: 여기서 xx는 이미지에서 가장 긴 변의 길이(픽셀 단위)를 나타내는 0~2,560 사이의 정수입니다. 예를 들어 =s32를 추가하면 이미지의 가장 긴 변이 32픽셀이 되도록 크기가 조절됩니다.
  • =sxx-c: 여기서 xx는 잘린 이미지 크기(픽셀 단위)를 나타내는 0~2,560 사이의 정수입니다. -c는 이미지를 자르도록 시스템에 지시합니다.
# Resize the image to 32 pixels (aspect-ratio preserved)
http://lhx.ggpht.com/randomStringImageId=s32

# Crop the image to 32 pixels
http://lhx.ggpht.com/randomStringImageId=s32-c

이미지 및 개발 서버

개발 서버는 로컬 머신을 사용하여 이미지 서비스 기능을 수행합니다.

Python 개발 서버는 PIL(Python Imaging Library)을 사용하여 이미지 서비스를 시뮬레이션합니다. 이 라이브러리는 Python 표준 라이브러리 또는 SDK에 포함되어 있지 않으므로 별도로 설치해야 합니다. pillow fork도 작동합니다. 적절한 PIL 디코더 플러그인이 설치된 경우에만 WEBP 이미지 형식이 지원됩니다.

삭제 시 유의사항

Cloud Storage 또는 Blobstore에 저장된 이미지의 제공을 중지하려면 delete_serving_url() 함수를 호출합니다.

제공된 URL을 통해 이미지에 액세스할 수 있으므로 Cloud Storage 또는 Blobstore에서 이미지를 직접 삭제하면 안 됩니다.

URL을 만든 애플리케이션이 사용 중지 또는 삭제되면 기본 이미지가 그대로 남아있더라도 제공 URL은 더 이상 작동하지 않습니다.

할당량, 한도, 가격

현재는 Images API를 사용해도 추가적인 비용이 발생하지 않습니다. App Engine 가격 페이지를 참조하세요.

각 Images API 요청은 Image Manipulation API 호출 할당량으로 계산됩니다. 앱은 API를 한 번 호출하여 한 이미지에 여러 가지 변환을 수행할 수 있습니다.

이미지 서비스로 전송된 데이터는 (Images) API에 전송된 데이터 할당량으로 계산됩니다. 이미지 서비스에서 수신된 데이터는 (Images) API에서 수신된 데이터 할당량으로 계산됩니다.

이미지의 각 변환은 변환 실행 할당량으로 계산됩니다.

자세한 내용은 할당량을 참조하세요. Google Cloud Console 할당량 세부정보 탭에서 앱의 현재 할당량 사용량을 확인할 수 있습니다.

할당량 외에도 이미지 서비스 사용 시 다음과 같은 한도가 적용됩니다.

한도 용량
서비스로 전송하는 이미지의 최대 데이터 크기 32MB
서비스가 전송하는 이미지의 최대 데이터 크기 32MB
서비스와 주고받는 이미지의 최대 크기 50메가픽셀