
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.io.*;

class BMPanel extends JPanel implements MouseMotionListener {

	BufferedImage biImg;
	int iWidth,iHeight;
	jpht1 frm;
	int [] pixel;

	public BMPanel(jpht1 arg) {

		biImg=new BufferedImage(128,128,BufferedImage.TYPE_INT_BGR);

		pixel=new int[128*128];

		setPixelToImage();

		setPanelSize(128,128);

		frm=arg;

		addMouseMotionListener(this);

	}

	public void setPanelSize(int iArg1,int iArg2) {

		iWidth=iArg1;
		iHeight=iArg2;

		setSize(new Dimension(iWidth,iHeight));

	}

	public void paintComponent(Graphics g) {

		g.drawImage(biImg,0,0,this);

	}

	public Dimension getPreferredSize() {

		return new Dimension(iWidth,iHeight);

	}

	public boolean load(String stArg) {

		int size=0,offset=0,width=0,height=0,length=0;

		File f=new File(stArg);

		size=(int)(f.length());

		if (size<1)
			return false;

		byte dat[]=new byte[size];

		try { // ファイルの内容をdatに読み込む

			FileInputStream fs=new FileInputStream(stArg);

			fs.read(dat);

			fs.close();

		} catch (FileNotFoundException e) {}
		  catch (IOException e) { return false; }

		// 24BitBMPでなければ戻る
		if (dat[0]!='B' || dat[1]!='M' || dat[28]!=24)
			return false;

		offset=getInt(dat,10); // ピクセル列までのオフセット

		width=getInt(dat,18);
		height=getInt(dat,22);

		if (width % 4==0) /* バッファの１ラインの長さを計算 */
			length=width*3;
		else
			length=width*3+(4-(width*3) % 4);

		// ピクセル列配列取得
		pixel=new int[width*height];

		iWidth=width;
		iHeight=height;

		// 24bit-32bit変換を行いながらピクセル列設定
		for (int i=0;i<height;i++)
			for (int j=0;j<width;j++)
				pixel[j+(height-i-1)*width]=getRGB(dat,offset+j*3+i*length);

		// BufferedImage生成
		biImg=new BufferedImage(width,height,BufferedImage.TYPE_INT_BGR);

		setPixelToImage();

		setPanelSize(width,height);

		return true;

	}

	void setPixelToImage() {

		// BufferedImageのピクセル列設定
		biImg.getRaster().setDataElements(0,0,iWidth,iHeight,pixel);

	}

	// 指定されたbyteを符号なし整数（0-255）のint値として返す
	private int getByte(byte bArg) {

		if (bArg<0)
			return 256+bArg;
		else
			return bArg;

	}

	// 指定された位置からの４バイトを正のint値として返す
	private int getInt(byte bArg[],int iArg) {

		if (bArg[iArg+3]<0)
			return 0;

		int iNum=0,iP=1;

		for (int i=0;i<4;i++) {

			iNum+=getByte(bArg[iArg+i])*iP;
			iP*=256;

		}

		return iNum;

	}

	// 指定された位置からの３バイトをint値として返す
	private int getRGB(byte bArg[],int iArg) {

		int iNum=0,iP=1;

		for (int i=0;i<3;i++) {

			iNum+=getByte(bArg[iArg+(2-i)])*iP;
			iP*=256;

		}

		return iNum;

	}

	public void mouseDragged(MouseEvent e) {}

	public void mouseMoved(MouseEvent e) {

		if (e.getX()>=iWidth || e.getY()>=iHeight)
			return;

		int rgb=pixel[e.getX()+e.getY()*iWidth];

		int b=(rgb >> 16) & 0xff;
		int g=(rgb >> 8) & 0xff;
		int r=rgb & 0xff;

		String mes=" ("+e.getX()+","+e.getY()+")"+":";
		mes=mes+r+","+g+","+b;

		frm.setStatus(mes);

	}

}

public class jpht1 extends JFrame implements ActionListener {

	BMPanel bp;
	JLabel lState;
	JMenuBar mbMain;
	JMenu mFile;
	JMenuItem miOpen,miExit;
	JScrollPane jp;

	public jpht1() {

		setSize(new Dimension(320,320));

		mbMain=new JMenuBar();
		mFile=new JMenu("File");
		miOpen=new JMenuItem("Open");
		miExit=new JMenuItem("Exit");
		miOpen.addActionListener(this);
		miExit.addActionListener(this);

		mFile.add(miOpen);
		mFile.addSeparator();
		mFile.add(miExit);
		mbMain.add(mFile);
		setJMenuBar(mbMain);

		Container cp=getContentPane();

		bp=new BMPanel(this);

		jp=new JScrollPane(bp,
		    ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
		    ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);

		lState=new JLabel(" ",JLabel.LEFT);

		GridBagLayout gl=new GridBagLayout();
		cp.setLayout(gl);

		GridBagConstraints gc=new GridBagConstraints();

		gc.fill=GridBagConstraints.BOTH;
		gc.weightx=100;
		gc.weighty=100;
		gc.gridx=0;
		gc.gridy=0;
		gc.gridwidth=1;
		gc.gridheight=1;

		cp.add(jp,gc);

		gc.weightx=100;
		gc.weighty=0;
		gc.gridx=0;
		gc.gridy=1;
		gc.gridwidth=1;
		gc.gridheight=1;

		cp.add(lState,gc);

		setVisible(true);
		setDefaultCloseOperation(EXIT_ON_CLOSE);

	}

	public void actionPerformed(ActionEvent e) {

		if (e.getSource()==miOpen) {

			JFileChooser jf=new JFileChooser();

			if (jf.showOpenDialog(this)==JFileChooser.APPROVE_OPTION) {

				bp.load(jf.getSelectedFile().getAbsolutePath());

				setTitle(jf.getSelectedFile().getAbsolutePath());

				jp.setViewport(jp.getViewport());

			}

		}

		if (e.getSource()==miExit) {

			dispose();
			System.exit(0);

		}

	}

	public void setStatus(String stArg) {

		lState.setText(stArg);

	}

	public static void main(String stArgs[]) {

		jpht1 ap=new jpht1();

	}

}
