[{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]