- PR -

FileUploadで取得した画像を縮小して保存するには

1
投稿者投稿内容
しろくま
常連さん
会議室デビュー日: 2004/10/15
投稿数: 35
投稿日時: 2005-03-11 12:48
いつもお世話になります。
PCからアップした画像を携帯から見れるようにサイズや画像形式を変更して保存を行いたいのですがどのようにすればよろしいのでしょうか
FileUploadのサンプル(以下のソース)でこのようにフォームから値を取得しているのを見かけるのですが、縮小を行うにはさらに、BufferedImage に値を渡さないといけない?(このあたりからよくわかっていません)と思うのですが...

try {
// アップロードされたファイル情報をFileItemオブジェクトのリストとして取得
List objLst=objDfu.parseRequest(request);
Iterator objItr=objLst.iterator();
// リストから順にファイルデータを取り出し、「/WEB-INF/data/元のファイル名」の形式でアップロードファイルを保存
while(objItr.hasNext()){
FileItem objFi=(FileItem)objItr.next();
if(!objFi.isFormField()){
// アップロードファイルの元ファイル名を取得
String strNam=objFi.getName();
if(strNam!=null && !strNam.equals("")){
strNam=(new File(strNam)).getName();
objFi.write(new File(path + "/" + strNam));
}

単純にサーバー上にファイル書き出すならば、このままでよいのですが。
目的までは遠い道のりですが何かヒントをお願いします。
takamaro
大ベテラン
会議室デビュー日: 2004/10/12
投稿数: 100
投稿日時: 2005-03-12 03:11
これってCommons FileUploadを使ってるのですよね?
直接アップロード時にサイズ(縦横比?圧縮比?)変更をする、
って訳じゃないですよね!?
(もしそうならややこしい事になりそうな気も。。。w)
そうじゃなく単純に保存された画像ファイルの変更であるならば、
JREのバージョンによってやり方は異なってくるでしょうね。
1.4以上ならImageI/Oを使えば比較的楽に出来るのではないかと
思います(1.4以上でも扱えるファイル形式に違いがあるかも、、)
やり方は私がとやかく言うよりは、、

http://www5.airnet.ne.jp/sakuraba/java/laboratory/JDK1.4/Graphics/ImageIO/ImageIO.html

を参考に(というか、ここを流して読んだ程度の知識しかないもので、、汗)
んで、ここを読んで解からない事があったら再度補足の投稿をしてみて下さい。
(たぶん)協力できると思いますので。
しろくま
常連さん
会議室デビュー日: 2004/10/15
投稿数: 35
投稿日時: 2005-03-15 10:38
レスありがとうございます。あまりにも低レベルな質問なのでレスがつかないかと心配していました。
ご提示されたURLをもとに試行錯誤した結果なんとか縮小した画像を保存することができました。ただ、.tmpファイルが消えずにいたり(毎回ではないですが)してます。
ここで、さらに質問なんですが縮小を行う場合に、元画像に対して1/nのような指定ではなく、縦サイズを指定したら縦横比を自動で算出して縮小みたいなことは無理でしょうか。
よろしくお願いいたします。
takamaro
大ベテラン
会議室デビュー日: 2004/10/12
投稿数: 100
投稿日時: 2005-03-15 23:54
引用:

しろくまさんの書き込み (2005-03-15 10:38) より:

ここで、さらに質問なんですが縮小を行う場合に、元画像に対して1/nのような指定ではなく、縦サイズを指定したら縦横比を自動で算出して縮小みたいなことは無理でしょうか。


以下「Java in the Box」さんより引用

コード:

BufferedImage image = reader.read(0);
shrinkImage = new BufferedImage(image.getWidth()/10, image.getHeight()/10,
image.getType());
AffineTransformOp atOp = new AffineTransformOp(AffineTransform.getScaleInstance(0.1, 0.1), null);
atOp.filter(image, shrinkImage);


この部分の事でしょうか?
私も詳しくはないので、他に適切な方法があるやもしれませんが、上記の方法論の
延長で対策を考えてみたいとおもいます。
要するに、飽くまでも1/nの指定で要件を満たせないか、という事です。

java.awt.geom.AffineTranceform#getScaleInstance(double sx, double sy)

上記のメソッドの引数、sx,syを同値にすることで縮小の縦横比は均一になりますよね。
今回は、縦サイズに合わせたいわけですから縮小後の(指定)縦サイズを「h」とした場合、


sx = (double)h /(元画像の縦サイズ);
sy = sx;

という事になるはずです(取り敢えず精度に関しては置いておくとして、、)
そうなると、自然と縮小後の(指定)横サイズ「w」も決まってきますよね。

w = (int)((元画像の横サイズ) * sy);

これで得られた、w,hを「結果格納用」のBufferedImageのコンストラクタwidth,height
に用いれば上手く行きそうな気がしますが、どうでしょう(試してないので怪しいですがw)
しろくま
常連さん
会議室デビュー日: 2004/10/15
投稿数: 35
投稿日時: 2005-03-18 09:34
引用:

takamaroさんの書き込み (2005-03-15 23:54) より:
要するに、飽くまでも1/nの指定で要件を満たせないか、という事です。

java.awt.geom.AffineTranceform#getScaleInstance(double sx, double sy)

上記のメソッドの引数、sx,syを同値にすることで縮小の縦横比は均一になりますよね。
今回は、縦サイズに合わせたいわけですから縮小後の(指定)縦サイズを「h」とした場合、


sx = (double)h /(元画像の縦サイズ);
sy = sx;

という事になるはずです(取り敢えず精度に関しては置いておくとして、、)
そうなると、自然と縮小後の(指定)横サイズ「w」も決まってきますよね。

w = (int)((元画像の横サイズ) * sy);

これで得られた、w,hを「結果格納用」のBufferedImageのコンストラクタwidth,height
に用いれば上手く行きそうな気がしますが、どうでしょう(試してないので怪しいですがw)



この方法で、目的の動作は行えました。市販のアプリ見たいに都合のいいモノを期待してはダメですね。
一応、数種類の縮小画像の保存は行えました。
ですが、前回書き込みをしました.tmpファイルが消えない症状ですが
いろいろと試行錯誤しているのですが、どうしてこのようになるのか分かりません。
HTMLからの読み込みが複数件(今は2画像でテスト)あるのが悪いのか、単に私の知識が乏しいのか(間違いなくこちらですが)。

コード:
    try {
      List objLst=objDfu.parseRequest(request);
      Iterator objItr=objLst.iterator();
      while(objItr.hasNext()){
        FileItem objFi=(FileItem)objItr.next();
        if(!objFi.isFormField()){
          String strNam=objFi.getName();
          if(strNam!=null && !strNam.equals("")){
            strNam=Common.generateName(;
            BufferedImage image = ImageIO.read(objFi.getInputStream());

            // 元画像の出力
//          objFi.write(new File(path + "/" + strNam));

            shrinkImage    = new BufferedImage(pt1x, pt1y, image.getType());
            shrinkImage2   = new BufferedImage(pt2x, pt2y, image.getType());
            shrinkImage3   = new BufferedImage(pt3x, pt3y, image.getType());

            // 縮小タイプ1画像の出力
            AffineTransformOp atOp    = new AffineTransformOp(AffineTransform.getScaleInstance(((double)pt1x/image.getWidth()), ((double)pt1y/image.getHeight())), null);
            atOp.filter(image, shrinkImage);
            ImageIO.write(shrinkImage, "jpg", new File(path + "/" + strNam + "1.jpg"));

            // 縮小タイプ2画像の出力
            AffineTransformOp atOp2   = new AffineTransformOp(AffineTransform.getScaleInstance(((double)pt2x/image.getWidth()), ((double)pt2y/image.getHeight())), null);
            atOp2.filter(image, shrinkImage2);
            ImageIO.write(shrinkImage2, "jpg", new File(path + "/" + strNam + "2.jpg"));

            // 縮小タイプ3画像の出力
            AffineTransformOp atOp3   = new AffineTransformOp(AffineTransform.getScaleInstance(((double)pt3x/image.getWidth()), ((double)pt3y/image.getHeight())), null);
            atOp3.filter(image, shrinkImage3);
            ImageIO.write(shrinkImage3, "jpg", new File(path + "/" + strNam + "3.jpg"));

          }
    System.out.println( "Name: " + objFi.getName() );
    System.out.println();
        }else{
    System.out.println( "String: " + objFi.getString() );    
    System.out.println();
		}



この状態ですと、.tmpファイルが消えません。
コメントになっている元画像の出力を行うと、.tmpは消えますが、2件目画像の読み込みでエラーになってしまうのです。

コード:




ログを掲載しようと思って今実行したら、エラーが出ない...
もうちょっと、試してみます。
takamaro
大ベテラン
会議室デビュー日: 2004/10/12
投稿数: 100
投稿日時: 2005-03-19 00:49
うーん、良くは分かりませんけど、これ(*.tmpファイル)って
Commons FileUploadライブラリ側の問題なんじゃないですか?
画像データであるとか何とか関係無しに。
(一度も使った事無いもんで、仕組みとかよーわからんのですが)

取り敢えず、FileItemのインスタンスの使用を終えた時点で、
org.apache.commons.fileupload.FileItem#delete()メソッド
でも呼び出してみたら如何でしょうか。

どうも上記の処理が提示されたソース内に見受けられないのが
気になりました。
1

スキルアップ/キャリアアップ(JOB@IT)