電子書籍の厳選無料作品が豊富!

画像のRGBヒストグラムを表示するプログラムを以下のように作りました。
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.*;
import javax.swing.ImageIcon;
import java.io.*;
class RGBMain{
public static void main(String argv[]){
JFrame f=new JFrame("画像とそのヒストグラム");
JPanel p1=new JPanel();
JPanel p2=new JPanel();
JPanel p3=new JPanel();
JLabel l1=new JLabel("input photo");
JLabel l2=new JLabel();
JTextField tf=new JTextField(15);
JButton b1=new JButton("open");
JButton b2=new JButton("start");
LoadFile lf=new LoadFile(tf, l2, p2);
ShowHist sh=new ShowHist(tf, p3);
tf.addKeyListener(lf);
b1.addActionListener(lf);
b2.addActionListener(sh);
p1.add(l1);
p1.add(tf);
p1.add(b1);
p1.add(b2);
p2.add(l2);
f.setDefaultCloseOperation(f.EXIT_ON_CLOSE);
f.getContentPane().add(p1,BorderLayout.NORTH);
f.getContentPane().add(p2,BorderLayout.WEST);
f.getContentPane().add(p3,BorderLayout.EAST);
f.setSize(800, 500);
f.setVisible(true);
}
}
class LoadFile implements ActionListener, KeyListener{
JTextField textField;
JLabel label;
JPanel panel;
public LoadFile(JTextField Textfield, JLabel lbl, JPanel pnl){
textField=Textfield;
label=lbl;
panel=pnl;
}
public void actionPerformed(ActionEvent e){
if(getClass().getResource(textField.getText())==null)
label.setText("ファイルが見つかりません。");
else{
ImageIcon imgicon=new ImageIcon(getClass().getResource(textField.getText()));
label.setIcon(imgicon);
}
label.repaint();
panel.repaint();
}
public void keyTyped(KeyEvent e){
if(e.getKeyCode()==e.VK_ENTER){
if(getClass().getResource(textField.getText())==null)
label.setText("ファイルが見つかりません。");
else{
ImageIcon imgicon=new ImageIcon(getClass().getResource(textField.getText()));
label.setIcon(imgicon);
}
label.repaint();
panel.repaint();
}
}
public void keyPressed(KeyEvent e){
}
public void keyReleased(KeyEvent e){
}
}
class ShowHist implements ActionListener{
JTextField textField;
JPanel p;
public ShowHist(JTextField Textfield, JPanel pnl){
textField=Textfield;
p=pnl;
}
public void actionPerformed(ActionEvent e){
try{
File f=new File(textField.getText());
BufferedImage bi=javax.imageio.ImageIO.read(f);
int rgb;
int[] rhist=new int[16];
int[] ghist=new int[16];
int[] bhist=new int[16];
int re, gr, bl;
int width=bi.getWidth()/3*2/16;
for(int y=0;y<=bi.getHeight();y++){
for(int x=0;x<=bi.getWidth();x++){
rgb=bi.getRGB(x, y);
bl=rgb%256;
gr=bl%256;
re=gr%256;
rhist[re/16]++;
ghist[gr/16]++;
bhist[bl/16]++;
}
}
Graphics g=p.getGraphics();
g.setColor(Color.red);
int i;
int xx=0;
for(i=0;i<16;i++){
g.fillRect(xx, bi.getHeight()/3, width, bi.getHeight()/3*(rhist[i]/(bi.getWidth()*bi.getHeight())));
xx+=width;
}
g.setColor(Color.green);
xx=0;
for(i=0;i<16;i++){
g.fillRect(xx, bi.getHeight()/3*2, width, bi.getHeight()/3*(ghist[i]/(bi.getWidth()*bi.getHeight())));
xx+=width;
}
g.setColor(Color.green);
xx=0;
for(i=0;i<16;i++){
g.fillRect(xx, bi.getHeight()/3*3, width, bi.getHeight()/3*(bhist[i]/(bi.getWidth()*bi.getHeight())));
xx+=width;
}
p.repaint();
}catch(IOException ex){
ex.printStackTrace();
}
}
}

コンパイルは問題なく通り、
実行すると、ウィンドウは表示されるのですが、ファイル名を入力して
openボタンをクリックしてもなにも反応がありません。特に例外も発生していないようなのですが、なぜでしょうか。
ちなみに、画像ファイル名はtrain.jpgで、javaソースファイル、各classファイルと同じディレクトリに置いています。
どなたかよろしくお願いします。

A 回答 (2件)

#1です。


すいません、ヒストグラムの表示はStartボタンで行うんですね。見逃していました。

Openボタンで画像を読み込んでからStartボタンを押したところ、ArrayIndexOutOfBoundsExceptionが出ました。発生位置は

> rhist[re/16]++;

この行です。インデックス値が-15になっていました。
BufferedImageクラスのgetRGB()をAPIリファレンスで調べてみると、
http://java.sun.com./javase/ja/6/docs/ja/api/ind …

「デフォルト RGB カラーモデル (TYPE_INT_ARGB) 」で値を返すとあるので、アルファ成分も数値に含まれるのでしょう。下記のようにして上位16ビット分(アルファ値の領域)を削ってしまえば、argbではなくrgbの値を取得できます。

rgb=bi.getRGB(x, y);



rgb=(bi.getRGB(x, y) & 0x00ffffff);

あと、forループのx、yの上限がおかしいです。インデックスは0から始まる数値なので、<=だと1ずつ多く参照してしまいます。

for(int y=0;y<=bi.getHeight();y++){
for(int x=0;x<=bi.getWidth();x++){



for(int y=0;y<bi.getHeight();y++){
for(int x=0;x<bi.getWidth();x++){

これでエラーは発生しなくなりますが、ヒストグラムは表示されませんでした。これは画像によるのかもしれません。ただパネルp3のサイズ指定がないと、p3はコンテンツを含まないため小さいサイズで初期化されるようです(p3.setBackground(Color.BLACK);として頂ければ起動時に確認できると思います)ので、パネルのサイズについて検討する必要はありそうです。

あとENTERキー入力については、KeyTyped()ではなくKeyPressed()内で処理するように変更してみてください。getKeyCode()の値が異なるようです。

対症療法的な回答のみですみませんが、とりあえずエラーが出なくなるということで、いったん回答を終わらせて頂きます。

この回答への補足

回答ありがとうございます。
komi1341さんの言うとおりに直して、さらに手を加えて次のようにしました。

import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.*;
import javax.swing.ImageIcon;
import java.io.*;
public class RGBMain {
public static void main(String[] args) {
JFrame f=new JFrame("画像とそのヒストグラム");
BTPanel p1=new BTPanel();
JPanel p2=new JPanel();
HistPanel p3=new HistPanel();
JLabel l2=new JLabel();
Dimension dm=new Dimension(650, 800);
p3.setPreferredSize(dm);
LoadFileorShowHist lfsh=new LoadFileorShowHist(p1.tf, l2, p1, p2, p3);
p1.tf.addKeyListener(lfsh);
p1.b1.addActionListener(lfsh);
p1.b2.addActionListener(lfsh);
p1.add(p1.l1);
p1.add(p1.tf);
p1.add(p1.b1);
p1.add(p1.b2);
p2.add(l2);
f.setDefaultCloseOperation(f.EXIT_ON_CLOSE);
f.getContentPane().add(p1,BorderLayout.NORTH);
f.getContentPane().add(p2,BorderLayout.WEST);
f.getContentPane().add(p3,BorderLayout.EAST);
f.setSize(1300, 800);
f.setVisible(true);
}
}
public class BTPanel extends JPanel {
public JLabel l1;
public JTextField tf;
public JButton b1, b2;
public BTPanel(){
l1=new JLabel("input photo");
tf=new JTextField(15);
b1=new JButton("open");
b2=new JButton("start");
}
}
public class HistPanel extends JPanel {
private int[] rhist;
private int[] ghist;
private int[] bhist;
private int n;
private int width;
private int w;
private int h;
public void setData(int[] rhist, int[] ghist, int[] bhist, int n, int width, int w, int h){
this.rhist=rhist;
this.ghist=ghist;
this.bhist=bhist;
this.n=n;
this.width=width;
this.w=w;
this.h=h;
}
public void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(Color.red);
int i;
int xx=0;
for(i=0;i<n;i++){
g.fillRect(xx, h/3, width, h/3*(rhist[i]/(w*h)));
xx+=width;
}
g.setColor(Color.green);
xx=0;
for(i=0;i<n;i++){
g.fillRect(xx, h/3*2, width, h/3*(ghist[i]/(w*h)));
xx+=width;
}
g.setColor(Color.blue);
xx=0;
for(i=0;i<n;i++){
g.fillRect(xx, h/3*3, width, h/3*(bhist[i]/(w*h)));
xx+=width;
}
}
}
public class LoadFileorShowHist implements ActionListener, KeyListener {
public JTextField textField;
public JLabel label;
public JPanel panel1;
public HistPanel panel2;
public BTPanel btpanel;
public LoadFileorShowHist(JTextField Textfield, JLabel lbl, BTPanel btp, JPanel pnl1, HistPanel pnl2){
textField=Textfield;
label=lbl;
panel1=pnl1;
panel2=pnl2;
btpanel=btp;
}
public void actionPerformed(ActionEvent e) {
if(e.getSource()==btpanel.b1){
String filename = textField.getText();
ImageIcon imgicon=new ImageIcon(filename);
label.setIcon(imgicon);
label.repaint();
panel1.repaint();
}else if(e.getSource()==btpanel.b2){
try{
File f=new File(textField.getText());
BufferedImage bi=javax.imageio.ImageIO.read(f);
int rgb;
int[] rhist=new int[16];
int[] ghist=new int[16];
int[] bhist=new int[16];
int re, gr, bl;
int width=bi.getWidth()/3*2/16;
for(int y=0;y<bi.getHeight();y++){
for(int x=0;x<bi.getWidth();x++){
rgb=(bi.getRGB(x, y)&0x00ffffff);
bl=rgb%256;
gr=bl%256;
re=gr%256;
rhist[re/16]++;
ghist[gr/16]++;
bhist[bl/16]++;
}
}
int w=bi.getWidth();
int h=bi.getHeight();
Graphics g=panel2.getGraphics();
panel2.setData(rhist, ghist, bhist, 16, width, w, h);
(HistPanelクラスpaintComponentメソッドからsuper.paintComponent(g)をのぞいた一連の動作)
panel2.repaint();
}catch(IOException ex){
ex.printStackTrace();
}
}
}
public void keyPressed(KeyEvent e) {
if(e.getKeyCode()==e.VK_ENTER){
String filename = textField.getText();
ImageIcon imgicon=new ImageIcon(filename);
label.setIcon(imgicon);
label.repaint();
panel1.repaint();
}
}
public void keyReleased(KeyEvent arg0) {
}
public void keyTyped(KeyEvent arg0) {
}
}

エラーは出なくなり、エンターキーも正しく動作するようになりましたが、startボタンを押すと、ヒストグラムを表示する位置が真っ白になって表示されます。なぜこうなるのかどうしてもわかりません。
よろしくお願いします。

補足日時:2009/11/17 13:40
    • good
    • 0

私の環境(XP、JDK6)では、openボタンを押すと画像が表示されました。

ヒストグラムは表示されません。

ソースを見る限り、画像を読み込んでアイコンとしてラベルに貼り付けているので、書いてあるとおりの挙動に見えます。ヒストグラムを表示するにはShowHistクラスのactionPerformed()を呼ぶ必要がありそうですが、どこでも呼ばれていませんね。そのあたりが解決の鍵ではないかと。

この回答への補足

回答ありがとうございます。
調べたところ、表示しようとした画像ファイルが壊れていました。
別の正常な画像で実行したところ、表示されました。
初歩的なミスですみませんでした。
ShowHistクラスのactionPerformed()が呼ばれていないというのがよくわからないんですが…。
見た限りLoadFileクラスと特に違いはないのですが…。
あとEnterキーを押した時も反応しません。
Enterキーを押した時もopenボタンと同じ動作をするようにしたのですが…。

補足日時:2009/11/14 17:32
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!