![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?8acaa2e)
画像の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件)
- 最新から表示
- 回答順に表示
No.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ボタンを押すと、ヒストグラムを表示する位置が真っ白になって表示されます。なぜこうなるのかどうしてもわかりません。
よろしくお願いします。
No.1
- 回答日時:
私の環境(XP、JDK6)では、openボタンを押すと画像が表示されました。
ヒストグラムは表示されません。ソースを見る限り、画像を読み込んでアイコンとしてラベルに貼り付けているので、書いてあるとおりの挙動に見えます。ヒストグラムを表示するにはShowHistクラスのactionPerformed()を呼ぶ必要がありそうですが、どこでも呼ばれていませんね。そのあたりが解決の鍵ではないかと。
この回答への補足
回答ありがとうございます。
調べたところ、表示しようとした画像ファイルが壊れていました。
別の正常な画像で実行したところ、表示されました。
初歩的なミスですみませんでした。
ShowHistクラスのactionPerformed()が呼ばれていないというのがよくわからないんですが…。
見た限りLoadFileクラスと特に違いはないのですが…。
あとEnterキーを押した時も反応しません。
Enterキーを押した時もopenボタンと同じ動作をするようにしたのですが…。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Java java 入力 3 4 3 出力 ABC DEFG HIJ このようなプログラムの書き方を教えてくだ 2 2022/07/15 14:18
- Ruby 【JAVA】数字をひし形に出力するプログラムについて 2 2022/07/11 23:32
- Java javaでのプログラム(配列)について質問です. 2 2022/10/14 22:27
- C言語・C++・C# 大量のデータを読み込んで表示する速度を改善したい 8 2023/05/07 13:29
- JavaScript アップロードファイルの種類によって処理を分岐させたいのですが書き方が分からずアドバイスお願いします 4 2023/06/17 19:12
- Java Java プログラム public class Main { public static void 3 2023/08/10 23:46
- Java Java 配列<選挙> 4 2023/07/31 15:07
- その他(プログラミング・Web制作) pythonのグローバル変数 2 2022/11/25 18:02
- JavaScript clear機能を失わずにファイルアップロード機能を作成したい 3 2023/06/10 16:12
- C言語・C++・C# C#テキストボックスの文字を配列にいれてその後表示する 4 2022/07/17 04:47
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
メンバ関数のconst
-
JUnit4のアノテーションについて
-
Javaの基礎のプログラム
-
画像が表示されません。
-
Dateクラスへ格納
-
初心者です。JScrollPane につ...
-
Java 初心者 int型の取り扱い方
-
eclipseに記述したjavaファイル...
-
C# 半角カナの文字化けについて
-
【JAVAエラー】互換性のない型...
-
Javaで文字と数字が混ざったも...
-
ハートマークを表示するには?
-
0~9まで入力させ、前に入力さ...
-
System.out.printlnの出力先
-
配列への文字列の格納について
-
C言語のポインターに関する警告
-
JSPでDBからデータ読み込みブラ...
-
パソコンキーボードで時分秒を...
-
nullcline
-
エクセルの配列定数について教...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
「配列定数は、イニシャライザ...
-
Javaで電卓を作りたい
-
式の型は配列型で int に解決済...
-
javaでカレンダー作成
-
java spring でエラーが出て困...
-
JAVAでCの関数ポインタのような...
-
JAVA エラー 式の開始が不正で...
-
6桁の数字を重複なしでランダム...
-
c# デリゲート関連の命名について
-
C++からC#のdllを参照する際、...
-
メインが含まれていません
-
(Swing)JTextFieldを半角のみ入...
-
DataSet(DataTable)の使い方
-
三目並べ(Tick-Tack-Toe)をJav...
-
JUnit4のアノテーションについて
-
初心者ですが、今javaで簡単な...
-
classを使って座標軸を求めるコ...
-
javaでcsvファイル読込時の改行...
-
C#で実行時にメソッドの返り値...
-
Java 初心者 int型の取り扱い方
おすすめ情報