去年書いた
yipuran-core/ScriptExecutor.java at master · yipuran/yipuran-core · GitHub
このメソッド
public static int runStream(Supplier<String>, Supplier<Collection<String>>
, Consumer<InputStream>, BiConsumer<String, Throwable>)
public static int runStream(Supplier<String>, Consumer<InputStream>, BiConsumer<String, Throwable>)
このプロセス起動、プロセスの標準出力を Consumer<InputStream>で受信した処理をラムダ式で、
そしてプロセスが要求する入力を Supplier<Collection<String>> ラムダ式で与えるという方法は
いろんな拡がり可能性があるようだ。
PythonでPDF作成→Javaで受け取り→Wicket AJAXダウンロード - Oboe吹きプログラマの黙示録
改善する→「JavaからProcess起動で Python 実行して PDF を作らせる。」 - Oboe吹きプログラマの黙示録
JavaからProcess起動で Python 実行して PDF を作らせる。 - Oboe吹きプログラマの黙示録
↑ここまでは、単に Python にPDFを作らせる仕事をさせてそれを受け取るのだが、
画像系の処理でも同じことができるはずだ。
QRコード、バーコードを作成するくらいだったら、すでに Java の世界でも
https://github.com/zxing/zxing を使えば、Python使わなくても良いだろう。
でも、画像加工処理となってくると、ちょっとJavaじゃ辛い。良いのが見当たらないのだ。
前の投稿でも書いた Python に処理させて結果をバイナリの標準出力させれば、
Consumer<InputStream> での処理が成立する。
import sys import io
io.BytesIO() オブジェクトに求めたい結果を出力して
getvalue() → sys.stdout.buffer.write でバイト単位出力
ができれば良いのである。
Python PILLOW 画像加工を処理するサンプル
Java Wicket で作成する Webページで画像加工前の画像をHTML img タグで表示と
Python PILLOW による簡単な加工結果を同様のHTML img タグで表示させる
(...同様のHTML img タグで表示 → 何、訳わからんことを!と思うかもしれないが
そこが、Java Wicket を使って可能な面白さのところです。)
Pythonのコード:img_convert.jpg
引数で加工する画像ファイルPATHを受け取って、
白黒変換、ガウシアンブラー(ガウスぼかし)、リサイズします
# -*- coding: UTF-8 -*- from PIL import Image, ImageFilter import io import sys argv = sys.argv img = Image.open(argv[1]) img2 = img.convert('L').filter(ImageFilter.GaussianBlur()).resize((120, 120),Image.LANCZOS) po = io.BytesIO(); img2.save(po, format='JPEG') sys.stdout.buffer.write(po.getvalue())
↑ format= の指定がないとダメです。
Webページ表示する HTMLソースです。wicket:id タグの方が加工前で
加工後は、Wicket の SharedResource で取得して表示するので、wicket:id が有りません。
<!-- 加工前の画像 --> <div> <img wicket:id="lena" alt="lena" style="width: 120px;height: 120px"> </div> <!-- 加工後の画像 --> <div> <img src="lenaConvertImage"> </div>
Wicket と
https://github.com/yipuran/yipuran-core/blob/master/src/main/java/org/yipuran/util/process/ScriptExecutor.java
を使用して書く Webページ Java です。
以下をPageクラスのコンストラクタ内で実行します。
sdir_path + "/img_convert.py" が、実行するPythonの指定で、getimagePath()が加工対象画像ファイルのパスです。
queue(new Image("lena", new PackageResourceReference(SamplePage.class, "lena.png"))); int sts = ScriptExecutor.runStream(()->"python " + sdir_path + "/img_convert.py " + getimagePath() , inst->{ try(ByteArrayOutputStream out = new ByteArrayOutputStream()){ inst.transferTo(out); out.flush(); getApplication().getSharedResources().add("lena_convert" , new ByteArrayResource("image/jpeg", out.toByteArray())); ((WebApplication)getApplication()) .mountResource("lenaConvertImage", new SharedResourceReference("lena_convert")); }catch(Exception ex){ throw new RuntimeException(ex); } }, (e, x)->{ logger.error(e); logger.error(x.getMessage(), x); });
Python 加工したデータを標準出力から InputStream → ByteArrayOutputStream
→ メモリ上でWicket の共有リソースとするのです。
Webページの表示は、、
Webページコンストラクタで Python プロセス起動して結果受けるまでは
表示が待たされる作りです。凄い遅いと予測したが、思ったより遅くなかった。