LoginSignup
1
0

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

Last updated at Posted at 2023-07-21

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

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

ここから、先の規定に基づいて png を作る拡張を作りました。(開発中です。)

と書きましたが、今回はその前段階としてのマクロを解説します。

環境

  • Ubuntu 20.04 LTS
  • コンバート対象 LibreOffice Draw ファイル

~/.config/libreoffice/4/user/Scripts/python

このディレクトリに以下を配置します。

  • drawFromEmbPng.py LibreOffice用マクロ
  • makeandclipboard.sh LibreOfficeから呼び出すヘルパースクリプト
  • fileconv.py LibreOffice ファイルを json テキストに埋め込む Python プログラム ヘルパースクリプトで使用
  • makeembpng.py png ファイルに fileconv.py で作った json を埋め込むプログラム ヘルパースクリプトで使用

drawFromEmbPng.py

from com.sun.star.beans import PropertyValue
import subprocess
CTX = uno.getComponentContext()
SM = CTX.getServiceManager()

def call_dispatch(doc, url, args=()):
    frame = doc.getCurrentController().getFrame()
    dispatch = create_instance('com.sun.star.frame.DispatchHelper')
    dispatch.executeDispatch(frame, url, '', 0, args)
    return

def create_instance(name, with_context=False):
    if with_context:
        instance = SM.createInstanceWithContext(name, CTX)
    else:
        instance = SM.createInstance(name)
    return instance

def makeEmbPng():
    # export png from selected object
    properties=[]
    p=PropertyValue()
    p.Name='FilterName'
    p.Value='calc_png_Export'
    properties.append(p)
    p2=PropertyValue()
    p2.Name='SelectionOnly'
    p2.Value=True
    properties.append(p2)
    docsource = XSCRIPTCONTEXT.getDocument()
    docsource.storeToURL('file:///tmp/embpngsource.png',tuple(properties))
    # copy from current draw file
    call_dispatch(docsource, '.uno:Copy')
    # paste to new draw file
    desktop = create_instance('com.sun.star.frame.Desktop', True)
    path = 'private:factory/sdraw'
    docdist = desktop.loadComponentFromURL(path, '_default', 0, ())
    call_dispatch(docdist, '.uno:Paste')
    # save new draw file to /tmp
    docdist.storeAsURL(convertToURL( "/tmp/embpngsource.odg"),())
    docdist.dispose
    subprocess.call("/home/nanbuwks/.config/libreoffice/4/user/Scripts/python/makeandclipboard.sh" )

# https://wiki.openoffice.org/wiki/Danny.OOo.OOoLib.py (LGPL License)
#------------------------------------------------------------
#   General Utility functions
#------------------------------------------------------------
def convertToURL( cPathname ):
    """Convert a Windows or Linux pathname into an OOo URL."""
    if len( cPathname ) > 1:
        if cPathname[1:2] == ":":
            cPathname = "/" + cPathname[0] + "|" + cPathname[2:]
    cPathname = cPathname.replace( "\\", "/" )
    cPathname = "file://" + cPathname
    return cPathname


makeandclipboard.sh

#!/bin/bash
cd `dirname $0`
mkdir /tmp/embeddedpng
python fileconv.py /tmp/embpngsource.odg > /tmp/embpngtxt.txt
python makeembpng.py /tmp/embpngsource.png /tmp/embpngtxt.txt /tmp/embeddedpng/embeddedpng.png
sleep 1
nautilus /tmp/embeddedpng/embeddedpng.png

fileconv.py

import json
import base64
import os
import sys

filepath = sys.argv[1]
filename = os.path.basename(filepath)
# 拡張子を取得
type = os.path.splitext(filename)[1][1:]


data = {}
with open(filepath, mode='rb') as file:
    img = file.read()
data['type'] = type
data['filename'] = filename
data['file'] = base64.encodebytes(img).decode('utf-8')
print(json.dumps(data))


makeembpng.py


import png
import shutil
import sys
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, textfile, index=1):
    f = open(textfile, 'r')
    data = f.read()
    f.close()
    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)

    chunk_item = generate_text_chunk_tuple(keyword+data)
    chunk_list.insert(index, chunk_item)

    with open(target, 'wb') as dst_file:
        png.write_chunks(dst_file, chunk_list)

#pngsrc = '/tmp/pngSource.png'
# txtsrc = r'/tmp/embtxt.txt'
#pngdst = '/tmp/embeddedpng/embeddedpng.png'
pngsrc = sys.argv[1]
txtsrc = sys.argv[2]
pngdst = sys.argv[3]
keyword = "Embedded Source\0"
# pngsrc から pngdst にコピーする
shutil.copyfile(pngsrc, pngdst)
# pngdst に txtsrc を埋め込む
insert_text_chunk(pngdst, txtsrc)

設定方法

各ファイルを配置します。

drawFromEmbPng.py

     subprocess.call("/home/nanbuwks/.config/libreoffice/4/user/Scripts/python/makeandclipboard.sh" )

を各自の環境に合わせて変更します。

makeandclipboard.sh に実行権をつけておきます。

「PNG にテキストを埋め込む」
https://qiita.com/nanbuwks/items/969642abde48bb272c25
の「python プログラム でテキストを埋め込む」を参照して、pypng をインストールします。

使い方

Draw 描画を作り、エクスポートしたいオブジェクトを選択します。
image.png
「ツール」-「マクロ」-「マクロを実行」で「マイマクロ」の「drawFromEmbPng」-「makeEmbPng」を選んで「実行」

image.png

すると、ファイルマネージャが開いて embeddedpng が開きます。
image.png

それを Qiita や GitHub 、その他もろもろに貼ります。
embeddedpng.png

(Qiita画像アップロードに問題があり、治り次第画像を登録します。→ 2023/7/21 どうやら画像アップロード上限に達していたようです。対応して画像を貼り直しました。)

貼った png は、
「PNG に編集ソースファイルを埋め込んで再編集可能にする その2」
https://qiita.com/nanbuwks/items/efdd7e909c588281cf1a
にあるヘルパーアプリケーションを使って元 odg を復元できます。

想定問答

Windowsは? Macは?

Linux 版もまだまだ未完成です。Linux 版でアップデートを重ねた後、Windows / Mac の対応を進めます。

oxt 形式の拡張じゃないの?

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

いいね! 勝手に応用したいな!

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

関連投稿

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

PNG にテキストを埋め込む
https://qiita.com/nanbuwks/items/969642abde48bb272c25
Qiita に画像を貼る方法
https://qiita.com/nanbuwks/items/e0c9f02c1b556dde140a
LibreOffice マクロ:Pythonでのプログラム例集
https://qiita.com/nanbuwks/items/1f25e8839089eaefd6d4
LibreOffice マクロを Ubuntu + Python で作る
https://qiita.com/nanbuwks/items/77d5707b9a2507972676
Python で LibreOffice 拡張をステップバイステップで作ってみる
https://qiita.com/nanbuwks/items/53861bac26c521c4b549

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0