• 締切済み

Image を90度回転して、新しいImageを作成するには?

Image データがあったとして、それを90度回転させた別のImageを作成したいのですが、すごく時間がかかります。 もっといいやり方があると思うのですが、ネットで調べても方法が見つかりませんでした。 今採用しているのは下記のようなやり方です。 もっと短時間でImage作成できる、良い方法をご教授頂けないでしょうか? PixelGrabber pg_f = new PixelGrabber(oldimg, 0, 0, oldw, oldh, old_pixel, 0, oldw); try{ pg_f.grabPixels(); } catch (InterruptedException e){ return null; } int trans = ~0x00000000; for (int x = 0; x < oldw; x++) { for (int y = 0; y < oldh; y++) { new_pixel[y + (newh - x - 1) * neww] = old_pixel[x + oldw * y] & trans; } } Image new_img = Toolkit.getDefaultToolkit().createImage(new MemoryImageSource(neww, newh, new_pixel, 0, neww)); MediaTracker mediaTracker = new MediaTracker(frame); mediaTracker.addImage(new_img, 0); try { mediaTracker.waitForID(0); } catch (InterruptedException ie) { System.err.println(ie); System.exit(1); }

みんなの回答

  • Bonjin
  • ベストアンサー率43% (418/971)
回答No.3

Javaではイメージ加工(移動、回転、伸縮)を行うためにAffineTransformというクラスが用意されています。

全文を見る
すると、全ての回答が全文表示されます。
  • noocyte
  • ベストアンサー率58% (171/291)
回答No.2

Java には詳しくないので,PixelGrabber や MediaTracker が何で, 何をしているのかよく知りませんが,時間がかかっているのは 画像の回転を行っている2重ループの部分だと思います. (そのことは確認しましたか? その部分と,それ以外の部分の実行時間は計ってみましたか?) 以下,その前提でとりあえずすぐ思いつく改良案を書きます. (1) まず,最初に思いつくのは,trans=~0 で & を取っているのが無駄. trans に別の値を入れる予定がなければ削除. (2) 次に思いつくのは,配列の添字の1次式を毎回計算しているのが効率悪い. 乗算を使わず加算だけで行えるように添字の計算方法を変更した方がよい. (3) 読み出し側の old_pixel[] の要素のアクセス順序がとびとびなので, キャッシュの効きが悪い.要素が順番にアクセスされるよう, xとyのループを入れ替えてみては? (書き込み側の new_pixel[] のアクセス順序はどうなんだといわれると, 確かにそれも考慮する必要はあるが,それをやろうとするとかなり面倒に なりそうなので,とりあえず考慮しないことにする.) int i = 0; int j = neww * newh; for(int y = 0; y < oldh; y++, j++) { int k = j; for(int x = 0; x < oldw; x++, i++) { k -= neww; new_pixel[k] = old_pixel[i]; } } これでどうでしょうか?

noname#58274
質問者

補足

ありがとうございます。 説明不足でした。 時間の大半は、下記の部分でかかっております。 なので、ロジック改善による大幅な改善は見込めないと思っております。 PixelGrabber pg_f = new PixelGrabber(oldimg, 0, 0, oldw, oldh, old_pixel, 0, oldw); try{ pg_f.grabPixels(); } catch (InterruptedException e){ return null; }

全文を見る
すると、全ての回答が全文表示されます。
  • cdsdasds
  • ベストアンサー率52% (114/217)
回答No.1

一般に図形操作は細かいノウハウが実行時間に影響しますから、この際フリーのユーティリティをシステムコールして使うとかではだめなのでしょうか。

noname#58274
質問者

補足

フリーのユーティリティで、Javaから使えるようなもの等紹介頂けないでしょうか?

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • Javaで画素

    Javaについて質問したいことがあります。 Javaでjpgの白黒画像を読み取った後、画像の一番上にある黒画素のY座標を求めたいのですが、うまくいきません。ちなみに、下が現在作っているプログラムです。 どうすれば一番上にある黒画素のY座標を求める事が出来るのでしょうか? 教えてください。お願いします。 import java.awt.*; import java.applet.*; import java.awt.image.MemoryImageSource; import java.awt.image.PixelGrabber; import java.awt.image.*; import java.awt.Graphics; public class image5 extends Applet { Image img; int img_width, img_height; public void init(){ img = getImage(getDocumentBase(), "test.jpg"); } public void paint(Graphics g){ img_width = img.getWidth(this); img_height = img.getHeight(this); g.drawImage(img, 0, 0, this); int pixels[] = new int[img_width * img_height]; PixelGrabber pg = new PixelGrabber(img, 0, 0, img_width, img_height, pixels, 0, img_width); try{ pg.grabPixels(); }catch(InterruptedException e){ System.err.println("interrupted waiting for pixels!"); return; } int tx = 0; int ty = 0; int ti = 0; int maxY = 0; for(ty = 0; ty < img_height; ty++){ while(ti < 1){ for(tx = 0; tx < img_width; tx++){ if((pixels[ty * img_width + tx] & 255) > 128){ maxY = ty; ti++; } } } } } }

  • 意味がわかりません

    このようなプログラムがあるのですが少し意味がわからなくて困っています。わかる方解説などお願いしますm(_ _)m try{mt.waitForAll(); } catch( InterruptedException e ) { } int w = img.getWidth(this); int h = img.getHeight(this); int[] pixels = new int[w * h]; int[] epixels = new int[w * h]; int[] uepixels = new int[w * h]; int scan = w; int offset = 0; PixelGrabber pg = new PixelGrabber(img,0,0,w,h,pixels,0,scan); try{pg.grabPixels(); } catch(InterruptedException e) { ; }

    • ベストアンサー
    • Java
  • なぜエラーになるのかがわかりません?(長文です。)

    下記のクラス(Panel_Middle)内でパネル(pnlFd)を作成してます。しかし、メインフォームからこのクラスの"CreateMainPanel"関数を呼ぶと "pnlFd.setBounds(new Rectangle(5, 5, 110, 38));" の後に"java.lang.NullPointerException "とエラーが出ます。色々考えたのですが、理由がわかりません。 public class Panel_Middle extends Panel{ Panel_Main pnlFd = new Panel_Main("A.gif","B.gif"); Image im; //CONSTRUCT public Panel_Middle(String img) { im = Toolkit.getDefaultToolkit().getImage(img); //MediaTracker画像入力監視 MediaTracker mt = new MediaTracker(this); mt.addImage(im, 0); try { mt.waitForID(0); } catch (InterruptedException e) { } } //Print public void paint(Graphics g) { if (g.drawImage(im, 0, 0, this) != true) { System.out.println("ng"); } } public void CreateMainPanel(){   this.add(pnlFd, null); pnlFd.setBounds(new Rectangle(5, 5, 110, 38)); pnlFd.setImageInit(); } }

    • ベストアンサー
    • Java
  • 画像読み込みのエラー処理

    画像を表示するアプレットのソースです。 ファイル名はstrで設定します。 Image img; String str; str = "xx.jpg"; img = getImage(getDocumentBase(), str); if (img.equals(null)) { mydbg("001"); } else { mydbg("002"); } //strがでたらめで、そのパスの画像が存在しなくても //getImage()は成功するんですか?実験してみるとそのようでした。 //その画像が存在しない場合、この下のソースでmydbg("003");が //実行されるはずなのに実行されません。 //画像が存在しない場合のエラー処理のよいソースを教えてください。 MediaTracker mt = new MediaTracker(this); mt.addImage(img, 0); try { mt.waitForID(0); repaint(); } catch (Exception e) { mydbg("003"); }

    • ベストアンサー
    • Java
  • 作ったクラスにイベントを追加するには?

    パネルを継承したクラスを作りました(パネルA)。 そのパネルAをメインフレームに作成しました。 作ったパネルAの上にサブパネルBを作りました。 サブパネルのイベントを書きたいのですがコードは作ったクラス内に書けないのでしょうか? 例)下記が作ったパネル継承クラスです。この中でpnlSubを作っているのです。で、このpnlSubのクリックイベントを書きたいのですが、どのようにイベントを用意すればよいのでしょう? package ### import java.awt.*; public class PanelA extends Panel{ Image im; Panel pnlSub = new Panel(); //CONSTRUCT public PanelA(String img) { im = Toolkit.getDefaultToolkit().getImage(img); //MediaTracker画像入力監視 MediaTracker mt = new MediaTracker(this); mt.addImage(im, 0); try { mt.waitForID(0); } catch (InterruptedException e) { } //パネル(pnlVolume)設定 this.add(pnlVolume, null); pnlSub.setBackground(Color.red); pnlSub.setBounds(new Rectangle(5, 8, 108, 5)); } //Print public void paint(Graphics g) { if (g.drawImage(im, 0, 0, this) != true) { System.out.println("ng"); } } }

    • ベストアンサー
    • Java
  • JAVAの初歩でとても悩んでます・・

    JAVAについての質問があります。とても困ってます・・。初心者の自分にもわかるようそれぞれの番号に対しての説明をしていただけると嬉しいです。 ちょっと長いのですが、例文があったのでそれを書いておきます。 (1)「メディアストラッカー」 (2)「スレッド」 (3)「インプリメント」 (4)myMt.waitForID(0) (5)myMT.checkID(0) (6)myTh = null; import java.applet.*; import java.awt.*; public class Lesson19 extends Applet implements Runnable{ Image[] myImg; int myNo; MediaTracker myMt; //メディアトラッカーオブジェクト Thread myTh; //スレッド public void init() { int count; myImg = new Image[3]; myNo = 0; myMt = new MediaTracker(this); myTh = null; for (count = 0; count < 3; count++) { myImg[count] = getImage(getDocumentBase(), "image" + count + ".gif"); myMt.addImage(myImg[count], 0); } } public void start(){ if (myTh == null) { myTh= new Thread(this); myTh.start(); } } public void run() { try { myMt.waitForID(0); } catch(InterruptedException e) {} while (true) { myNo = myNo + 1; if (myNo== 3) myNo = 0; try { myTh.sleep(1000); } catch(InterruptedException e) {} repaint(); } } public void paint(Graphics g) { if (myMt.checkID(0)) g.drawImage(myImg[myNo], 80, 80, this); g.drawString("image" + myNo, 75, 50); } }

    • ベストアンサー
    • Java
  • ピクセル情報について

    画像を読み込んでピクセル情報を取得して、 R.G.B値を操作しようとして次の様にプログラムを組みました。 (抜粋ですみません) pg = new PixelGrabber(img1,0,0,width,height,pixel,0,width); try { pg.grabPixels(); System.out.println("pg ok"); //デバッグ表示用 } catch(InterruptedException e) { System.out.println(e); } for(int i=0; i<width*height; i++) { int pix = pixel[i]; int red = 0xff & (pix >> 16); int green = 0xff & (pix >> 8); int blue = 0xff & pix; red += uppoint; green += uppoint; blue += uppoint; pixel[i] = (0xff000000 | red<<16 | green<<8 | blue); } 旨く動けばR.G.B値にuppoint分の数値が足されるはずなんですが、エラーがでてしまいます。 何処が悪いのか判らなくて困っています。 どなたか教えていただけないでしょうか?

  • 画像がうまく表示されない。

    アプレットを作っています。 左クリックすると、次の画像へ進む、といった処理を実装したのですが、1回は次の画像へ進むのですが、2回目以降が進みません(しかも、「1.jpg」から「2.jpg」へ進めたいのですが、何故か「1.jpg」から「10.jpg」にいってしまいます。)以下が現在のコードです。 余分な部分は削除しました。よろしくお願いします。 public class Main extends Applet implements MouseListener, Runnable{ Image nowImage, nextImage; static int i; MediaTracker mt = new MediaTracker(this); MediaTracker mt2 = new MediaTracker(this); int yousosu,w,h; Thread thread; static float alpha; static boolean runflag = true; static boolean flag = true; static int j = 1; Image buf; Graphics ct; int sleeptime = 300; Image img; Vector imgs = new Vector(); public void init(){ i = 0; thread = new Thread(this); yousosu = Integer.parseInt(getParameter("NumImage"));//配列(画像)の要素数 for(int t = 0; t < yousosu; t++){ img = getImage(getDocumentBase(),"imagesyukusyo/" + t+1 + ".JPG"); imgs.addElement(img); img = null; } int kazu = imgs.size(); addMouseListener(this); w = getSize().width; h = getSize().height; buf = createImage(w,h);//バッファ取得 //*******最初の画像のロード******* nowImage = getImage(getDocumentBase(), "imagesyukusyo/1.JPG");//←Vectorの[0]要素? } public void update(Graphics g){ paint(g); } public void paint(Graphics g){//drawImageファイルを表示するだけ ct = buf.getGraphics(); Graphics2D ct2 = (Graphics2D) ct; Graphics2D g2 = (Graphics2D) g;//Grahics2Dクラス AlphaComposite composite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha); mt.addImage(nowImage,0); mt2.addImage(nextImage, 0); try { mt.waitForID(0); mt2.waitForID(0); } catch (InterruptedException e) { e.printStackTrace(); } ct2.drawImage(nowImage,0,0,w,h,this); ct2.setComposite(composite); //次からはcompositeを設定した後の描画になる。 ct2.drawImage(nextImage,0,0,w,h,this); g2.drawImage(buf,0,0,w,h,this); } //*********マウスイベント************ public void mouseClicked(MouseEvent e) { int btn = e.getButton(); //*******左クリック********** if(btn == MouseEvent.BUTTON1){//左クリック=進め System.out.println("左クリック"); System.out.println("iは"+i); System.out.println("elementAtの数は"+imgs.size()); if(i >= yousosu){//要素数より多くなったら… i = 0; } nowImage = (Image)imgs.elementAt(i); if(i == yousosu-1){ nextImage = (Image) imgs.elementAt(0); }else{ //通常こっち nextImage = (Image) imgs.elementAt(i+1); } thread = new Thread(this); thread.start(); thread = null; i++; } } public void run(){ alpha = 0.2f; repaint(); try { thread.sleep(sleeptime); } catch (InterruptedException e) { e.printStackTrace(); } alpha = 0.3f; repaint(); try { thread.sleep(sleeptime); } catch (InterruptedException e) { e.printStackTrace(); } alpha = 0.4f; repaint(); try { thread.sleep(sleeptime); } catch (InterruptedException e) { e.printStackTrace(); } alpha = 0.5f; repaint(); try { thread.sleep(sleeptime); } catch (InterruptedException e) { e.printStackTrace(); } alpha = 0.6f; repaint(); try { thread.sleep(sleeptime); } catch (InterruptedException e) { e.printStackTrace(); } alpha = 0.7f; repaint(); try { thread.sleep(sleeptime); } catch (InterruptedException e) { e.printStackTrace(); } alpha = 0.8f; repaint(); try { thread.sleep(sleeptime); } catch (InterruptedException e) { e.printStackTrace(); } alpha = 0.9f; repaint(); try { thread.sleep(sleeptime); } catch (InterruptedException e) { e.printStackTrace(); } alpha = 1f; repaint(); } }

    • ベストアンサー
    • Java
  • プログラムで

    以前も似たような質問をしたのですが、いろいろとやってみたのですがわからなくてまた質問しました。現在、次のようなプログラムを書いています。 int w = img.getWidth(this); int h = img.getHeight(this); int[] pixels = new int[w * h]; int[] epixels = new int[w * h]; int[] uepixels = new int[w * h]; int scan = w; int offset = 0; PixelGrabber pg = new PixelGrabber(img,0,0,w,h,pixels,0,scan); try{pg.grabPixels(); } catch(InterruptedException e){;} for(int i=0; i < w*h ; i++){ int r = (int)(pixels[i]&0x00ff0000); if (r!=0x00000000){r = ((int)((pixels[i]&0x00ff0000)*0.5)&0x00ff0000);} int g = (int)(pixels[i]&0x0000ff00); if (g!=0x00000000){g = ((int)((pixels[i]&0x0000ff00)*0.5)&0x0000ff00);} int b = (int)(pixels[i]&0x000000ff); if (b!=0x00000000){b = ((int)((pixels[i]&0x000000ff)*0.5)&0x000000ff);} if((ra.nextInt()%2)!=0) { epixels[i] = 0xff000000| r | g | b ; uepixels[i]=pixels[i]; } else { epixels[i] = pixels[i]; uepixels[i] = 0xff000000| r | g | b ; } (Exception ex){;} } しかし、これですとiが1進む毎にランダムに真または偽をとってしまうため、実際に動かしてみた所「砂嵐」のように画像が表示されました。このランダムにとるのを、1ライン目はそのままの明るさで2ライン目は明るさ半減していて3ライン目も明るさ半減していて・・・といった感じにライン毎にランダムに「そのままの明るさのライン」か「明るさが半減しているライン」かをとるように改良するにはどうしたらいいでしょうか?お願いします。

    • ベストアンサー
    • Java
  • 動作しない

    下のプログラムのことなのですが、このプログラムをコンパイルし、実行すると動作するのですが画像を他のものに変更して同様に実行すると動作しなくなりました。どうすればいいのでしょうか?教えてくださいお願いします。 import java.applet.*; import java.awt.*; import java.awt.image.*; public class moji extends Applet { Image img; // 元のイメージ int img_width = 0; // 元のイメージの幅 int img_height = 0; // 元のイメージの高さ int pix[]; // 元のイメージを格納する配列 int wcnt_pix[]; // 行ごとの黒画素数を格納する配列 int hcnt_pix[]; // 列ごとの黒画素数を格納する配列 int cnt = 0; // 黒画素のカウント用 int cnt_sum = 0; // 黒画素のカウント総数 int chu = 0; // 中心値 int sum1 = 0; int sum2 = 0; int x = 0; int y = 0; int xmax = 0; // 黒画素の右端 int xmin = 0; // 黒画素の左端 int ymax = 0; // 黒画素の上端 int ymin = 0; // 黒画素の下端 public void init(){ img = getImage(getDocumentBase(), "test.jpg"); // イメージのロード MediaTracker mt = new MediaTracker(this); mt.addImage(img, 0); try{ mt.waitForID(0); }catch(InterruptedException e){} // イメージのロード完了まで待機 img_width = img.getWidth(this); // 元のイメージの幅を取得 img_height = img.getHeight(this); // 元のイメージの高さを取得 cntpix(); box_top(); box_bot(); box_rig(); box_lef(); } // 黒画素数のカウント public void cntpix(){ pix = new int[img_width * img_height]; wcnt_pix = new int[img_width]; hcnt_pix = new int[img_height]; try{ PixelGrabber pg = new PixelGrabber(img, 0, 0, img_width, img_height, pix, 0, img_width); pg.grabPixels(); }catch(InterruptedException e){} // 行ごとのカウント for(int wj = 0; wj < img_height; wj++){ cnt = 0; for(int wi = 0; wi < img_width; wi++){ if((pix[wj * img_width + wi] & 255) < 128){ cnt++; } } wcnt_pix[wj] = cnt; cnt_sum = cnt_sum + cnt; } // 列ごとのカウント for(int hi = 0; hi < img_width; hi++){ cnt = 0; for(int hj = 0; hj < img_height; hj++){ if((pix[hj * img_width + hi] & 255) < 128){ cnt++; } } hcnt_pix[hi] = cnt; } chu = cnt_sum / 2; // 中心値 // 中心値より重心が何行目かを求める int i = 0; while(sum1 < chu){ sum1 = sum1 + wcnt_pix[i]; i++; } x = i - 1; // 中心値より重心が何列目かを求める int j = 0; while(sum2 < chu){ sum2 = sum2 + hcnt_pix[j]; j++; } y = j - 1; } // 黒画素の上端を求める public void box_top(){ int ti = 0; while(wcnt_pix[ti] == 0){ ymax = ti; ti++; } } // 黒画素の下端を求める public void box_bot(){ int bi = img_height - 1; while(wcnt_pix[bi] == 0){ ymin = bi; bi--; } } // 黒画素の右端を求める public void box_rig(){ int ri = 0; while(hcnt_pix[ri] == 0){ xmin = ri; ri++; } } // 黒画素の左端を求める public void box_lef(){ int li = img_width - 1; while(hcnt_pix[li] == 0){ xmax = li; li--; } } // 画像等の描画 public void paint(Graphics g){ int box_w = xmax - xmin; int box_h = ymin - ymax; int dx = x - xmin; // 重心のX座標 int saku = dx / 20 * 3; // 錯視による誤差 int dy = ymin - y + saku; // 重心のY座標 g.drawImage(img, 0, 0, this); g.drawString("このイメージの幅は"+img_width+"で高さは"+img_height+"です。", 0, 20); // 画像の描画 g.drawRect(xmin, ymax, box_w, box_h); // バウンディングボックスの描画 g.setColor(Color.red); g.fillOval(xmin-3, ymin-3, 6, 6); g.drawString("原点( 0, 0 )", xmin-20, ymin+20); // 原点の描画 g.drawString("文字の重心は、( "+dx+", "+dy+" )です。", 0, 40); // 重心の描画 g.drawLine(x-10, y-saku, x+10, y-saku); // 重心の位置の描画 g.drawLine(x, y-saku+10, x, y-saku-10); // 重心の位置の描画 } }

    • ベストアンサー
    • Java