環境
- Ubuntu 22.04 LTS
埋め込む
draw.io を使うと、png に埋め込みができ、それを再編集できます。どうやっているのかな?
エクスポートした png を qiita に貼って
上の png をダウンロード、drawio で開く
chunk
「Canvas から生成した PNG 画像に独自の情報を埋め込む | GREE Engineering」
https://labs.gree.jp/blog/2013/12/8594/
を読むと、PNG はチャンクとしてデータを管理していて、独自チャンクなどとして自由に情報が格納できることがわかります。
「PNG: Chunk by Chunk — PyPNG 0.0.20 documentation」
https://pypng.readthedocs.io/en/latest/chunk.html
では、定義された18種類のチャンクがリストされています。
先の drawio で作成した png ファイルについて、
「PNG file chunk inspector」
https://www.nayuki.io/page/png-file-chunk-inspector
これでチェックすると、以下のように表示されました。
オレオレチャンクタイプではなく、tExt チャンクを使っているようです。
「PNG Specification: Chunk Specifications」
https://www.w3.org/TR/PNG-Chunks.html
では、tExt チャンクについて以下のように説明されています。
Textual information that the encoder wishes to record with the image can be stored in tEXt chunks. Each tEXt chunk contains a keyword and a text string, in the format:
Keyword: 1-79 bytes (character string)
Null separator: 1 byte
Text: n bytes (character string)
The keyword and text string are separated by a zero byte (null character). Neither the keyword nor the text string can contain a null character. Note that the text string is not null-terminated (the length of the chunk is sufficient information to locate the ending). The keyword must be at least one character and less than 80 characters long. The text string can be of any length from zero bytes up to the maximum permissible chunk size less the length of the keyword and separator.
Any number of tEXt chunks can appear, and more than one with the same keyword is permissible.The keyword indicates the type of information represented by the text string. The following keywords are predefined and should be used where appropriate:
PNG Specification: Chunk Specifications
python プログラム でテキストを埋め込む
元にしたもの
「linux - Insert a text chunk into a png image - Stack Overflow」
https://stackoverflow.com/questions/9036152/insert-a-text-chunk-into-a-png-image
こちらに投稿されているサンプルコード
import png
TEXT_CHUNK_FLAG = b'tEXt'
def generate_chunk_tuple(type_flag, content):
return tuple([type_flag, content])
def generate_text_chunk_tuple(str_info):
type_flag = TEXT_CHUNK_FLAG
return generate_chunk_tuple(type_flag, bytes(str_info, 'utf-8'))
def insert_text_chunk(target, text, index=1):
if index < 0:
raise Exception('The index value {} less than 0!'.format(index))
reader = png.Reader(filename=target)
chunks = reader.chunks()
chunk_list = list(chunks)
print(chunk_list[0])
print(chunk_list[1])
print(chunk_list[2])
chunk_item = generate_text_chunk_tuple(text)
chunk_list.insert(index, chunk_item)
with open(target, 'wb') as dst_file:
png.write_chunks(dst_file, chunk_list)
def _insert_text_chunk_to_png_test():
src = r'E:\temp\png\register_05.png'
insert_text_chunk(src, 'just for test!')
テスト
上記に以下を足します。
src = r'icon.png'
insert_text_chunk(src, 'just for test!')
pypng モジュールをインストールします。
$ sudo pip install pypng
カレントディレクトリに icon.png を置いて、実行します。
$ python chunkpng.py
チェック
「PNG file chunk inspector」
https://www.nayuki.io/page/png-file-chunk-inspector
こちらでうまくいったかどうか確認してみます。
埋め込まれているみたいですね!
「Missing null separator」は、キーワードとテキストが分離されていないためのエラーです。
python プログラムでテキストを取り出す
先のプログラムは2番めのチャンクに埋め込んでいました。ここでは固定した場所からテキストを取り出してみます。
import png
def decode_text_chunk(target, index=1):
if index < 0:
raise Exception('The index value {} less than 0!'.format(index))
reader = png.Reader(filename=target)
chunks = reader.chunks()
chunk_list = list(chunks)
print(chunk_list[1])
src = r'icon.png'
decode_text_chunk(src)
コレを実行すると、以下のように取り出せました。
(b'tEXt', b'just for test!')