AWS Lambdaで地理院地図の画像を取得し、S3バケットに保存する(staticmap)

AWS Lambdaで地理院地図の画像を取得し、S3バケットに保存する(staticmap)

AWS Lambdaで任意地点の地図画像の作成を試してみました。
Clock Icon2025.05.21

任意地点付近の地図画像が欲しくなるときって、ありますよね。というわけで、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つの画像がありました。

01_s3

画像を確認する

バッチリでした。

作成した地図画像を掲載したいのですが、利用規約的に駄目だと判断しているので、本記事への掲載はしません。(複製または使用の申請が必要になる認識です。)

参考

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.