[{PageViewPlugin}]
[Dev Record GeoPicPlugin], [GeoPicPlugin]

!!!Abstract
画像ファイルをアップロードするときにファイルサイズを小さくしたい。

!!!Topics
!!やりたいこと
*GeoPicPluginでファイルサイズを抑えた写真ファイルのアップロードをしたい。ただし、本当に制限したいファイルサイズも指定したい。例えば、50Mのファイルはダメとか。

!!記録
*まずファイルの扱いをフローにしたい。
|アップロードボタンが押されてから、まず、サーバにファイルがアップロードされて、そのあとEXIFを読み取るのが今回のプログラムかな。保存のタイミングはどこか。
|GeoPicServlet.upload()の175ライン当たりにparseRequestというのがあり、ここで”本当に制限したいファイルサイズ”のチェックがされる。
|GeoPicServlet.upload()の250ラインあたりに(FileItem)actualFileオブジェクトができている。そこから情報を吸い出しているようだ。InputStreamもそこからいつでも得られる。このInputStreamからEXIFなどを吸い出して、Fileを更新して一次フォルダに保管しておいて、ファイルアップロードを実行するときには一次保管したファイルのInputStreamを渡す。
|315行あたりにthis.executeUpload(,InputStream in,)とある。
|467行あたりにm_engine.getAttachmentManager().storeAttachment(att, data);とある。
|AttachmentManagerの574行目にm_provider.putAttachmentData( att, in )がある。これは、WikiAttachmentProviderというInterface Classに定義されているメソッド。実態はどこだ?org.apache.wiki.providersパッケージの中にいくつかある。
|この(InputStream)dataを圧縮後のファイルに置き換えるということか。
*一時的にファイルを保存したい。
|TOMCAT_HOMEの下にtempフォルダがあって、そこにアップロードするファイルが一時的に保存されている。プロパティのworkDirを使っているところを探そう。m_engine.getWorkDir()で取れるっぽい。そこに淡々と保存するか。で、そのファイルを開いて、InputStreamをつくるか。
*一時ファイルの削除
|もし一時ファイルに保存したとしたら、それを消すのはいつ?tempFile.deleteOnExit()	
*画像ファイルからEXIF情報を削除するのはApache Commons Imaging[1]かな。
|in は InputStream、Outは、InputStreamってできる?一度Tempファイルで保存か。サンプルを見よう[4].
*画像のファイルサイズの圧縮ができるAPIはあるか?
|ImageIOってなんだろう[2]。いくつかサンプルが[3]。BufferredImageが便利。しかしImageオブジェクトをBufferredImageにキャストしようとしたらエラーがでた。同じ問題に当たった人も[5]
*なんとPNGってEXIF情報保存できないんだ。。。tiffにするか。いやApache Commons Imagingでは、TIFFはEXIFに対応していないように見える[6]。そうするとPNGにして、メタデータは、書誌情報として保存か。本当にそれでいい?ImageIOを使った方法[8]をちょっと調べたうえでやろう。JPEGに越したことはない。
*ファイル形式結論はJPEGで。
Apache Commons Imaging を使った場合。実は、JPEGの保存について、Imagingが対応していない[6]ためエラーorg.apache.commons.imaging.ImageWriteException: This image format (Jpeg-Custom) cannot be written.がでる。
{{{
	Imaging.writeImage(buffered, tempImageFile, ImageFormats.JPEG, null);
}}}
ImageIOでやるとこうなる。画質が指定できないのが玉に傷だが、シンプルだ。
{{{
	ImageIO.write(buffered, "jpeg", tempImageFile);
}}}
*なんか写真が180度回転して表示される。どうしたものか。EXIFにあるらしい、Orientationの情報をもとに回転させたほうがいいのかな。同じ問題に当たった人も[7]。EXIFのOrientationの値をゲットすると、3とかがでてきた。これは180度回転しているものらしい[9]。graphics2Dのrotateメソッドを使おう。
*ファイルサイズを選択するリストを最初Disableにしないと。(結局選択させないことに)
*Reziseをチェックしないのに動いちゃった。それはまずい。(結局全部リサイズすることに)
*ResizeをするとEXIFが消えるような気がする。当たり前なのだが。EXIF情報をコピーするとかできるのか?(結局全部消すことに)
*ファイルをいじるところをまとめたほうがいいと思う。(一回で済ませた)
**回転する(EXIF次第)
**Resizeする(必ずやる)
**EXIFを取得する(必ずやる)
**EXIF情報を付加する(やらないことにした)
**EXIF情報を削除する(回転などをやるとあえてコピーしないと消える。コピーの処理はやらないことにした)
*JPEG以外でアップロードされた場合どうするか。いまは、JPEGがPNGで保存。JPEGの時だけ動くようにしたい。(OK)
*JPEGでもアップロードできないファイルがある。Invalid marker found in entropy dataという.ImageReadExceptionがでる。まだこれで解決するかわからないけど、Apacheでも議論があって1.0-alpha2で解決されているという[10]。2020年5月7日時点では、Mavenレポジトリから呼べないのだけど。Githubのレポジトリから最新版をクローンして、コンパイルして1.0-alpha2のJARをゲットして、JSPWikiのWEB-INFのlibフォルダに入れて解決。
*ResizeしないとRotateされない。→もう面倒だから全部Resizeだ。
*ん?JPEGのファイルで、全体に赤とか、黄色とかがかかる現象が。試しにPNG形式で保存しようとしても、同じ結果だ。つまり、ImageIO.writeは悪くない。getScaledInstanceを飛ばしてみても結果は同じ。ここもあまり悪くなさそう。orientationValueが3か6以外の画像も同じ現象が起きたから、graphics2D.rotateも関係なさそうだ。graphics2D.drawImage()を飛ばしても結果は変わらない。Imaging.getBufferedImage(in)が怪しい。ここで得られたBufferedImageをそのままImageIO.writeしても結果は変わらない。ここは、Imaging.getBufferedImage(in)をImageIO.read(in)に代替して、解決
*iphoneだと90度回転がありうる。Orientation Valueとしては、6。この時、widthとheightが入れ替わることおよびその回転の中心座標に注意。
|orientation value|回転角度(°)|幅|高さ|回転の中心座標|
|1|0|width|height|回転しない|
|3|180 deg|width|height|(width/2, height/2)|
|6|90 deg|height|width|(height/2, height/2)|

!!!Referece
#[#1][http://commons.apache.org/proper/commons-imaging/]
#[#2][https://qiita.com/oohira/items/be99b3c8f025d04a5541]
#[#3]エンジニアの入り口, 2018.04.13,【入門者向け】Javaにおける画像の扱い方を分かり易く解説, [https://eng-entrance.com/java-image]
#[#4][http://commons.apache.org/proper/commons-imaging/sampleusage.html]
#[#5][https://stackoverflow.com/questions/13605248/java-converting-image-to-bufferedimage]
#[#6][http://commons.apache.org/proper/commons-imaging/formatsupport.html]
#[#7][http://mumumu.github.io/blog/2013/05/15/rotate-image-depending-on-exif-orientation-value/]
#[#8]@oohira, 2017年4月16日, JavaでJPEG画像の保存品質を変更する, [https://qiita.com/oohira/items/be99b3c8f025d04a5541]
#[#9]EXIF Tags, [https://exiftool.org/TagNames/EXIF.html]
#[#10]2019年6月9日, Invalid marker found in entropy data, [https://issues.apache.org/jira/browse/IMAGING-134]