AWS Lambdaで地理院地図の画像を取得し、S3バケットに保存する(staticmap)
AWS Lambdaで任意地点の地図画像の作成を試してみました。
任意地点付近の地図画像が欲しくなるときって、ありますよね。というわけで、AWS Lambdaで任意地点の地図画像の作成を試してみました。
おすすめの方
- 任意地点付近の地図画像を作成したい方
- AWS Lambdaで任意地点付近の地図画像を作成したい方
- 画像の右下にテキスト文字を表示したい方
地図について
国土地理院の地理院地図を利用します。
なお、地理院地図を利用する場合は、利用規約を確認し従ってください。
フォントファイルを用意する
本記事では、IPAexフォントで試してみます。
Lambdaをデプロイする
sam init
sam init \
--runtime python3.11 \
--name lambda-staticmap-sample \
--app-template hello-world \
--no-tracing \
--no-application-insights \
--structured-logging \
--package-type Zip
SAMテンプレート
LambdaとS3バケットを作成します。
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: lambda-staticmap-sample
Globals:
Function:
Timeout: 10
LoggingConfig:
LogFormat: JSON
Resources:
Bucket:
Type: AWS::S3::Bucket
Properties:
BucketName: blog-lambda-staticmap-sample-bucket
HelloWorldFunction:
Type: AWS::Serverless::Function
Properties:
FunctionName: blog-lambda-staticmap-sample-function
CodeUri: hello_world/
Handler: app.lambda_handler
Runtime: python3.11
Policies:
- arn:aws:iam::aws:policy/AmazonS3FullAccess
Environment:
Variables:
BUCKET_NAME: !Ref Bucket
Architectures:
- x86_64
MemorySize: 256
HelloWorldFunctionLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub /aws/lambda/${HelloWorldFunction}
requirements.txt
staticmap
Lambdaコード
任意地点の緯度経度において指定のズームレベルの画像を取得し、右下に権利表記のテキストを表示し、画像をS3バケットに保存します。
import os
import boto3
from staticmap import StaticMap
from PIL import Image, ImageDraw, ImageFont
from dataclasses import dataclass
@dataclass
class Location:
name: str
latitude: float
longitude: float
zoom: int = 16
TARGET_LOCATIONS = [
Location(
# 東京駅
name="tokyo",
latitude=35.681382,
longitude=139.7673068,
),
Location(
# 名古屋駅
name="nagoya",
latitude=35.1706431,
longitude=136.8816945,
),
Location(
# 新大阪駅
name="shinosaka",
latitude=34.7338219,
longitude=135.5014056,
),
]
WIDTH = 800
HEIGHT = 600
COPYRIGHT_TEXT = "地理院タイルを加工して作成"
COPYRIGHT_FONT_SIZE = 14
FONT_FILE_NAME = "ipaexg.ttf"
BUCKET_NAME = os.environ["BUCKET_NAME"]
s3 = boto3.client("s3")
def lambda_handler(event, context):
for location in TARGET_LOCATIONS:
# 地図画像を作成する
image = create_map_image(location)
# 画像を/tmpに保存する
output_file_name = f"{location.name}.png"
output_file_path = os.path.join("/tmp", output_file_name)
image.save(output_file_path)
# S3にアップロードする
s3.upload_file(output_file_path, BUCKET_NAME, output_file_name)
def create_map_image(location):
# https://maps.gsi.go.jp/development/ichiran.html#std
map = StaticMap(
WIDTH,
HEIGHT,
url_template="https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png",
)
image = map.render(
zoom=location.zoom,
center=[
location.longitude,
location.latitude,
],
)
font = ImageFont.truetype(FONT_FILE_NAME, COPYRIGHT_FONT_SIZE)
draw = ImageDraw.Draw(image)
# テキストボックスのエリアを取得
left, top, right, bottom = draw.textbbox(
(WIDTH - 5, HEIGHT - 5),
COPYRIGHT_TEXT,
font=font,
anchor="rs", # 右下寄せ
)
# テキストボックスのエリアを白で塗りつぶす
draw.rectangle((left - 5, top - 5, right + 5, bottom + 5), fill="white")
# テキストを描画する
draw.text(
(WIDTH - 5, HEIGHT - 5),
COPYRIGHT_TEXT,
font=font,
fill="black",
anchor="rs", # 右下寄せ
)
return image
フォントファイル(ipaexg.ttf)をLambdaコードと同じディレクトリに格納する
└── hello_world
├── __init__.py
├── app.py
├── ipaexg.ttf
└── requirements.txt
デプロイ
sam build --use-container
sam deploy \
--region ap-northeast-1 \
--stack-name lambda-staticmap-sample-stack
Lambdaを実行し、S3バケットの画像を確認する
Lambdaを実行する
aws lambda invoke \
--function-name blog-lambda-staticmap-sample-function \
output.txt
S3バケットを確認する
3つの画像がありました。
画像を確認する
バッチリでした。
作成した地図画像を掲載したいのですが、利用規約的に駄目だと判断しているので、本記事への掲載はしません。(複製または使用の申請が必要になる認識です。)