Power Appsを助ける"ちょいコード"としてのPython

Power Appsだからきっと超ローコードなものを・・・と期待していた方にはごめんなさい。

本投稿では、Pythonで書いた Azure Functionsを利用して、Power Appsのアプリに役立ててみたという内容をご紹介します。

# 作ったもの

Power Appsのアプリに用意されているペン入力のコントロールで書いた絵をアニメーションGIFに変換するようなアプリを作ってみました。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">できました！！！！！<br>ペン入力からGIF作成するPower Apps <a href="https://t.co/minFEeUNlv">pic.twitter.com/minFEeUNlv</a></p>&mdash; Hiro (@mofumofu_dance) <a href="https://twitter.com/mofumofu_dance/status/1328299069530206213?ref_src=twsrc%5Etfw">November 16, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

Pythonで書いたAzure Functionsはこのアプリのうち、複数のPNG画像からアニメーションGIFを生成する部分を担っています。（表には出てこないですが）

下図のようなイメージです。Power AppsからはAzure API Managementを経由してAzure Functions に複数枚の画像が渡されます。
FunctionsではPython Pillowのライブラリを利用して、画像からGIFへの変換を行っています。
最後にPower Appsに結果をかえして完了です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/84855f7c-f022-e9fa-5c1b-a62d9ae71014.png)

これを実現するために書いたコードは10数行といったところです。

```python

import logging
from io import BytesIO
import azure.functions as func
from PIL import Image
import base64
import json
def main(req: func.HttpRequest) -> func.HttpResponse:
    logging.info('Python HTTP trigger function processed a request.')
    req_body = req.get_json()
    imgs = req_body.get('images')
    logging.info(len(imgs))
    frames =[]

    for i in range(len(imgs)):
        data = imgs[i].get('imguri')
        frames.append(Image.open(BytesIO(base64.b64decode(data))))
    
    frames[0].save('/tmp/tmpgif.gif',
               format='GIF',
               append_images=frames[1:],
               save_all=True,
               duration=req_body.get('duration'),
               loop=0)
    with open("/tmp/tmpgif.gif",'rb') as f1:
        b64_img = base64.b64encode(f1.read())

        resp={"data":"data:image/gif;base64,"+str(b64_img)[2:len(str(b64_img))-1]}
        
    return func.HttpResponse(
                     json.dumps(resp),
        mimetype="application/json",
             status_code=200
        )

```
たったこれだけ！

# ローコードを支援する"ちょいコード"

ローコードのアプリ・ワークフロー開発では制限や制約がたくさんある中で、ある程度決まった枠組みの中で効率よく開発を行いことになります。
特にPower AppsやPower Automateの場合には、ビジネスユーザーも(市民)開発者としてターゲットにしているため、Excelの関数くらいの式でアプリやワークフローが作成できてしまいます。

これはとても素晴らしいことですが、得意不得意もあり、特に画像やメディアの加工系は3rd PartyのAPIに頼らなければいけないケースが多くあります。
今回作ったような画像→アニメーションGIFへの変換も、標準では提供されていませんし、3rd PartyのAPIもPower Appsから直接実行できるものには存在しませんでした。


**じゃあ作ればいいじゃない**


こういう、Power Appsの標準機能の組み合わせでカバーしきれない機能をAPIとして提供するためにAzure Functionsはとても有効です。
とりわけ、Power Appsが苦手なメディアの加工処理は、Pythonで多くのライブラリが利用できます。

しかもこのくらいの量だと、9割コピペで賄えます・・・。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/388493d5-a6c1-8c91-bb0d-5c7acdc6f9f5.png)
んー。もはやどこを書いたのか怪しいレベル。

さらに追い風というわけではありませんが、Microsoft Teams でつくるPower Appsでは、Azure API Managementを通じて追加されたカスタムコネクターが無料です！
こういうAzureのサービスをうまく、ちょっとだけ利用して、アプリの幅を広げるというのもアリかもしれません。


# References

- [Azure Functions Python developer guide](https://docs.microsoft.com/en-us/azure/azure-functions/functions-reference-python)
- [複数の画像からgifアニメーションを作る](https://blog.fantom.co.jp/2019/12/28/make-gif-animation-from-multiple-images/)
- [Azure API Management で Project Oakdale 環境にカスタムコネクターを追加する](https://mofumofupower.hatenablog.com/entry/apim_oakdale)
- [#PowerApps のJSON関数を利用した写真の一括登録](https://qiita.com/h-nagao/items/1e89e16fe59d458bd4d1)