PNG に編集ソースファイルを埋め込んで再編集可能にする その2

「PNG に編集ソースファイルを埋め込んで再編集可能にする その1」
https://qiita.com/nanbuwks/items/1af5b5ec87ebbe2a7712

では LibreOffice を使って、 Qiita に貼った png ファイルに編集ソースを埋め込む仕組みを解説しました。


> 開発中のヘルパーアプリはその2以降で解説します。

と書きましたが、今回は png ファイルから元ファイルを復元するためのヘルパーアプリを python で作成しました。

# 環境 

- Ubuntu 20.04 LTS


# Python プログラム

```python

#!/usr/bin/env python3
import json
import base64
import sys
import subprocess
import datetime
import platform
import os
import png


tempdir = '/tmp'
now = datetime.datetime.now()
pf = platform.system()
if pf == 'Windows':
    tempdir = os.environ['TEMP']
    dir = tempdir+"\\embpng"+now.strftime('%Y%m%d%H%M%S%f' )+"\\"
    os.makedirs(dir)
elif pf == 'Darwin':
    dir = tempdir+"/embpng"+now.strftime('%Y%m%d%H%M%S%f' )+"/"
    os.makedirs(dir)
elif pf == 'Linux':
    dir = tempdir+"/embpng"+now.strftime('%Y%m%d%H%M%S%f' )+"/"
    os.makedirs(dir)


reader = png.Reader(filename=sys.argv[1])
chunks = reader.chunks()
chunk_list = list(chunks)
find = 0
for item in chunk_list:
    if ( ord('t') == item[0][0] and ord('E') == item[0][1] and ord('X') == item[0][2] and ord('t') == item[0][3]  ):
        if ( 0 == item[1][15] ):
            if  ( "Embedded Source" == item[1][0:15].decode('utf-8')):
                di=json.loads(item[1][16:].decode('utf-8'))
                find=1
                break
if ( 0 == find ):
    print ("no embedded png")
    exit()
#embpngchunk=chunk_list[1]
#di=json.loads(embpngchunk[1].decode('utf-8'))
#print(di)
#with open(sys.argv[1]) as f:
#    di = json.load(f)
#print(di['filename'])  
#print(di['file'])  
#print(base64.b64decode(di['file']).decode('utf-8'))
with open(dir+di['filename'], 'wb') as fo:
    fo.write(base64.b64decode(di['file']))
if pf == 'Windows':
    subprocess.Popen(["start",  dir ], shell=True)
elif pf == 'Darwin':
    subprocess.Popen(['open', dir ])
elif pf == 'Linux':
    subprocess.Popen(['open', dir ])

```




実行にあたり、png ライブラリが必要になります。
```
$ sudo pip install pypng
```

以下の png ファイルを使って試してみましょう。

![embeddedpng.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/6c31f800-65fb-6dd8-7957-af8695db185a.png)

(2023/07/21 00:24現在 Qiitaに画像が貼れなくなっているみたいです。復旧次第貼ります。→ 2023/07/21 22:31 貼れました!)

これをダウンロードします。ファイル名が長くなるので`testpng.png`とでも名前を点けて保存しましょう。

https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/6c31f800-65fb-6dd8-7957-af8695db185a.png

先の python プログラムを、`testpng.png` を指定して実行します。
```
./decodeembpng.py testpng.png

```
復元したLibreOfficeファイルが表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/2ef9b700-818d-6dfa-5c7f-27cfa9b50178.png)

これを開くと、中身が編集できます。(下図はファイル名が異なっていますが、Qiitaの不具合のため画像が貼れず、昔の画像を使いまわしています。)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/dd91f9dc-9540-d4cc-d781-2abb223262cf.png)

# 想定問答


## Windowsは? Macは?

一応、Windows / Mac の場合を想定して分岐コードを書いてますが、検証がまだです。


## GUIじゃないの?

「その5」あたりで・・・

## どうして LibreOffice 拡張じゃないの?

埋め込み PNG の作成 は LibreOffice 拡張を用いてますが、復元は LibreOffice 以外のソースも行えるように考え、独立したアプリケーションとしました。LibreOffice 以外にも、回路CADや 分子構造式でもできるようにしていきたいと考えています。

## どうしてファイルをファイルマネージャで表示するだけなの? ファイルを直接開かないの?

セキュリティリスクのため、一旦ファイルに落とすようにしています。

## draw.io/diaglams.net の埋め込み png と紛らわしい

ヘルパーアプリのバージョンアップで、対応の予定です。

## いいね! 勝手に使いたいな!

この形式のライセンスはPublicDomein としています
ファイルフォーマットは「PNG に編集ソースファイルを埋め込んで再編集可能にする その1」
https://qiita.com/nanbuwks/items/1af5b5ec87ebbe2a7712
にあります。
ご活用ください。



# 関連投稿

今回のプログラムは、以下の調査を元に作成しています。

PNG にテキストを埋め込む
https://qiita.com/nanbuwks/items/969642abde48bb272c25
Qiita に画像を貼る方法
https://qiita.com/nanbuwks/items/e0c9f02c1b556dde140a
python でエスケープ文字の入った JSON からコンテンツを復元する
https://qiita.com/nanbuwks/items/8a15ff646edc0e3aba7f