matlabでpng画像をbase64経由のエンコード・デコード

やりかた

主に2つある,基本的には上で事足りるよね…?

matlab純正関数を使う

matlab.net.base64encodematlab.net.base64decodeを直で叩く

jp.mathworks.com

jp.mathworks.com

そもそも画像データを読み込んで云々という動作させるには工夫が必要,データと型の扱いとか…

org.apacheを拝借する

org.apache.commons.codec.binary.base64インスタンス化する

weblabo.oscasierra.net

ただなんでJavaのライブラリが使えているのかよくわからん,R2022aで動いたけどこれはおま環かもしれないので要注意
あとmatlabとの食い合わせが悪いかもしれないので工夫が必要

使用例

やること

  • htmlData URI Schemeを出す
    • Chromeなら見れるはず
  • encode/decodeで元のファイルを復元する
  • そのままslackのwebhookにも送りつけてみる
    • typeにはmrkdwnを指定する
    • 試したい人はapiを用意してね
clear;


imgUrl = 'test.png';

fid = fopen(imgUrl);
fbt = fread(fid);
fclose(fid);


% With Apache
base64Coder = org.apache.commons.codec.binary.Base64;
fbtB64apa = uint8(base64Coder.encode(uint8(fbt)));
fbtB64apaChr = char(fbtB64apa.');
revfbtapa = double(typecast(base64Coder.decode(fbtB64apa),'uint8'));

newfid=fopen('test1Apache.png','w+');
fwrite(newfid,revfbtapa);
fclose(newfid);

% With Matlab
fbtB64matChr = matlab.net.base64encode(uint8(fbt));
revfbtmat = double(matlab.net.base64decode(fbtB64matChr).');

newfid=fopen('test1Matlab.png','w+');
fwrite(newfid,revfbtmat);
fclose(newfid);


% html base64 uri data scheme
html = '<head></head><body><img src="data:image/png;base64,'+string(fbtB64apaChr)+'"></body>'; % easy html style

newfid=fopen('test1.html','w+');
fwrite(newfid,html);
fclose(newfid);


% try to send Slack webhook
url = 'https://hooks.slack.com/services/xxx/yyy/zzz'; % your Webhook API url

content.type="html";
content.text = '<img src="data:image/png;base64,'+string(fbtB64apaChr)+'">'; % easy markdown style

payload = jsonencode(content);
options = weboptions('CharacterEncoding','UTF-8','UserAgent','matlab_simulink','Timeout',8);

webwrite(url,payload,options);

どうなるか

こうなれば良い,matlabapacheで結果が一致するはず

htmlはブラウザで画像が見えていればOK
フォルダを見て画像が復元されていればOK

slackはクッソ長い文字列しか見えない,そもそもData URI Schemeに非対応か,もしくは文字数制限でインタプリタが動作しないか…
やはりどうしても画像投稿用のAPIを使う必要があるらしいな?

matlabの問題点

自前でuint8(binary)しないとダメ,内部で変換してくれるらしいのだが恐らくtypecast(binary,'uint8')をされている
画像データの読み込み時にdoublearrayになるので,それをcastしながらdecodeしてはいけない

apacheの問題点

恐らくちゃんとしたバイナリ列を返してくれるが,matlab側がint8で受け取るためオーバーフローみたいになる
ここではuint8castする必要がある