/**
* MyPanel.java
*
* 該類顯示兩個(gè)圖片:濾波前和濾波后的圖片
* 用函數(shù)WFilter來(lái)對(duì)圖片進(jìn)行濾波處理
* 由于JAVA的Image類不直接支持bmp位圖,所以要自己編寫(xiě)代碼來(lái)顯示位圖
*
* Copyright 2004 by 海南大學(xué)信息學(xué)院
* @author 溫小斌
* @version 1.0
*/
import java.awt.*;
import java.awt.geom.*;
import java.awt.image.*;
import java.io.*;
import javax.swing.*;
import java.awt.color.*;
public class MyPanel extends JPanel
{
BufferedImage image;
FileInputStream fs;
int bflen=14; // 14 字節(jié) BitmapFileHeader
byte bf[]=new byte[bflen];
int bilen=40; // 40 字節(jié) BitmapInfoHeader
byte bi[]=new byte[bilen];
int nsize;
int nbisize;
int nwidth;
int nheight;
int nplanes;//位面數(shù)總為1
int nbitcount;//比特?cái)?shù)/象素
int ncompression;//壓縮數(shù)據(jù)
int nsizeimage;
int nxpm;
int nypm;
int nclrused;//使用的顏色索引
int nclrimp;//重要顏色索引
int nNumColors = 0;
int npalette[];
byte bpalette[];//調(diào)色板范圍
int npad8;
int ndata8[];
byte bdata[];
protected void paintComponent(Graphics g) //重畫(huà),刷新
{
super.paintComponent(g);
if (image != null)
g.drawImage(image, 0, 0, null);
}
public void loadImage(String name, boolean filter, float a, float q, float c, float r) //參數(shù)name表示文件名,filter表示是否濾波
{
// 調(diào)用圖像,在這之前需要先調(diào)用自定義的loadBitmap函數(shù),這是因?yàn)镴AVA不直接支持bmp位圖
Image loadedImage
= loadBitmap(name, filter, a, q, c, r);
MediaTracker tracker = new MediaTracker(this);
tracker.addImage(loadedImage, 0);
try { tracker.waitForID(0); }
catch (InterruptedException e) {}
//調(diào)入圖像緩沖
image = new BufferedImage(loadedImage.getWidth(null), loadedImage.getHeight(null), BufferedImage.TYPE_INT_BGR);
Graphics2D g2 = image.createGraphics();
g2.drawImage(loadedImage, 0, 0, null);
repaint(); //調(diào)用paintComponent刷新窗口
}
public Image loadBitmap(String name, boolean filter, float a, float q, float c, float r)
{
Image bitmap;
try{
fs=new FileInputStream(name);
fs.read(bf,0,bflen);
fs.read(bi,0,bilen);
//解釋數(shù)據(jù)
nsize = (((int)bf[5]&0xff)<<24) | (((int)bf[4]&0xff)<<16) | (((int)bf[3]&0xff)<<8) | (int)bf[2]&0xff;
nbisize = (((int)bi[3]&0xff)<<24) | (((int)bi[2]&0xff)<<16) | (((int)bi[1]&0xff)<<8) | (int)bi[0]&0xff;
nwidth = (((int)bi[7]&0xff)<<24) | (((int)bi[6]&0xff)<<16) | (((int)bi[5]&0xff)<<8) | (int)bi[4]&0xff;
nheight = (((int)bi[11]&0xff)<<24) | (((int)bi[10]&0xff)<<16) | (((int)bi[9]&0xff)<<8) | (int)bi[8]&0xff;
nplanes = (((int)bi[13]&0xff)<<8) | (int)bi[12]&0xff;
nbitcount = (((int)bi[15]&0xff)<<8) | (int)bi[14]&0xff;
ncompression = (((int)bi[19])<<24) | (((int)bi[18])<<16) | (((int)bi[17])<<8) | (int)bi[16];
nsizeimage = (((int)bi[23]&0xff)<<24) | (((int)bi[22]&0xff)<<16) | (((int)bi[21]&0xff)<<8) | (int)bi[20]&0xff;
nxpm = (((int)bi[27]&0xff)<<24) | (((int)bi[26]&0xff)<<16) | (((int)bi[25]&0xff)<<8) | (int)bi[24]&0xff;
nypm = (((int)bi[31]&0xff)<<24) | (((int)bi[30]&0xff)<<16) | (((int)bi[29]&0xff)<<8) | (int)bi[28]&0xff;
nclrused = (((int)bi[35]&0xff)<<24) | (((int)bi[34]&0xff)<<16) | (((int)bi[33]&0xff)<<8) | (int)bi[32]&0xff;
nclrimp = (((int)bi[39]&0xff)<<24) | (((int)bi[38]&0xff)<<16) | (((int)bi[37]&0xff)<<8) | (int)bi[36]&0xff;
if (nbitcount == 8) //如果是256色位圖
{
if (nclrused > 0)//clrused 為0表示使用所有調(diào)色板項(xiàng)
nNumColors = nclrused;
else
nNumColors = (1&0xff)<<nbitcount;
// 讀取調(diào)色板顏色。
npalette = new int [nNumColors];
bpalette = new byte [nNumColors*4];
fs.read (bpalette, 0, nNumColors*4);
int nindex8 = 0;
for (int n = 0; n < nNumColors; n++)
{
npalette[n] = (255&0xff)<<24 | (((int)bpalette[nindex8+2]&0xff)<<16) | (((int)bpalette[nindex8+1]&0xff)<<8) | (int)bpalette[nindex8]&0xff;
nindex8 += 4;
}
// 讀取圖像數(shù)據(jù)(實(shí)際上是調(diào)色板的索引)
// 掃描行仍被補(bǔ)足到 4 個(gè)字節(jié)。
npad8 = (nsizeimage / nheight) - nwidth;
ndata8 = new int [nwidth*nheight];
bdata = new byte [(nwidth+npad8)*nheight];
fs.read (bdata, 0, (nwidth+npad8)*nheight);
nindex8 = 0;
for (int j8 = 0; j8 < nheight; j8++)
{
for (int i8 = 0; i8 < nwidth; i8++)
{
if(filter) //如果需要濾波,調(diào)用濾波函數(shù)WFilter
{
ndata8 [nwidth*(nheight-j8-1)+i8] = npalette [(WFilter(nindex8, a, q, c, r)&0xff)];
nindex8++;
}
else //如果不需要濾波
{
ndata8 [nwidth*(nheight-j8-1)+i8] = npalette [((int)bdata[nindex8]&0xff)];
nindex8++;
}
}
nindex8 += npad8;
}
bitmap = createImage(new MemoryImageSource(nwidth, nheight, ndata8, 0, nwidth)); //產(chǎn)生Image的對(duì)象bitmap
}
else
{
return (Image)null;
}
fs.close();
return bitmap;
}
catch(Exception e){
System.err.println(e);
return (Image)null;
}
}
//維納濾波函數(shù)
public int WFilter(int n, float a, float q, float c, float r)
{
// x 為濾波器的輸入信號(hào)
float p;
float p1, p2, p3, p4, p5;
float g;
float f;
//濾波器的沖激響應(yīng)
int j;
int s[]; //濾波器的輸出信號(hào)
p1 = (a*a-1)*r;
p2 = c*c*q;
p3 = (a*a-1)*(a*a-1)*r*r;
p4 = 2*c*c*r*q*(1+a*a);
p5 = c*c*c*c*q*q;
p = (float)((p1+p2+Math.sqrt(p3+p4+p5))/(2*a));
g = (c*p)/(r+c*c*p);
f = a*(1-c*g);
/*
for(int i=0; i<=n; i++)
{
s += g*(float)Math.pow(f, n)*bdata[n-i];
}
*/
if(j=0)
{
s[j]=g*bdata[0];
return Math.round(s);
}
else
{
for(int i=1;i<=n;i++)
{j=i;
s[j]=f*s[j-1]+g*bdata[i]
/*s=g*f*bdata[n];*/
return Math.round(s);
}
}
}
}