148 lines
5.0 KiB
Java
148 lines
5.0 KiB
Java
package com.bn;
|
|
import java.awt.*;
|
|
import java.awt.event.*;
|
|
import javax.swing.*;
|
|
import java.awt.image.*;
|
|
import java.awt.color.*;
|
|
import java.io.*;
|
|
import javax.imageio.ImageIO;
|
|
|
|
public class NormalMapUtil extends JFrame
|
|
{
|
|
//创建显示源图像的标签,并将其放置到滚动窗格中
|
|
JLabel jls=new JLabel();
|
|
JScrollPane jspz=new JScrollPane(jls);
|
|
//创建显示目标图像的标签,并将其放置到滚动窗格中
|
|
JLabel jlt=new JLabel();
|
|
JScrollPane jspy=new JScrollPane(jlt);
|
|
//创建分割窗格,并设置各子窗格中显示的控件
|
|
JSplitPane jsp=new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,jspz,jspy);
|
|
//创建文件选择器
|
|
JFileChooser jfc;
|
|
|
|
//定义一个图标引用
|
|
ImageIcon ii;
|
|
public NormalMapUtil()
|
|
{
|
|
String path=new File("a").getAbsolutePath();
|
|
path=path.substring(0,path.length()-2);
|
|
jfc=new JFileChooser(path);
|
|
|
|
//加载选择的图片到图标对象中
|
|
ii=this.chooserFile();
|
|
//将图片设置到源标签中
|
|
jls.setIcon(ii);
|
|
//设置两个标签的水平、垂直对齐方式
|
|
jls.setVerticalAlignment(JLabel.CENTER);
|
|
jls.setHorizontalAlignment(JLabel.CENTER);
|
|
jlt.setVerticalAlignment(JLabel.CENTER);
|
|
jlt.setHorizontalAlignment(JLabel.CENTER);
|
|
|
|
//设置分隔条的宽度以及初始位置
|
|
jsp.setDividerLocation(500);
|
|
jsp.setDividerSize(4);
|
|
//将分割窗格添加到窗体中
|
|
this.add(jsp);
|
|
|
|
//设置窗体的标题、大小位置以及可见性
|
|
this.setTitle("高度域灰度图转换成法向量纹理图工具");
|
|
this.setBounds(0,0,1000,500);
|
|
this.setVisible(true);
|
|
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
|
|
|
Image iTemp=process();
|
|
//将处理后的图片设置到目标标签中
|
|
jlt.setIcon(new ImageIcon(iTemp));
|
|
|
|
try
|
|
{
|
|
FileOutputStream os = new FileOutputStream("resultnt.jpg");
|
|
System.out.println(((RenderedImage)iTemp).getColorModel());
|
|
ImageIO.write((RenderedImage)iTemp, "JPEG", os);
|
|
os.flush();
|
|
os.close();
|
|
}
|
|
catch(Exception e)
|
|
{
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
|
|
//加载选中图片的方法
|
|
public ImageIcon chooserFile()
|
|
{
|
|
//弹出文件选择器
|
|
int i=jfc.showOpenDialog(this);
|
|
//获取选择文件的路径
|
|
String dir=(jfc.getSelectedFile()!=null)?(jfc.getSelectedFile().getPath()):null;
|
|
if(dir!=null&&!dir.equals(""))
|
|
{
|
|
//按指定的路径加载图片到图标对象中并返回
|
|
return new ImageIcon(dir);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
//从源高度图生成凹凸贴图的方法
|
|
public Image process(){
|
|
int width=ii.getImage().getWidth(null);//获取待处理图像的宽度与高度
|
|
int height=ii.getImage().getHeight(null);
|
|
//创建两个BufferedImage对象分别用来放置待处理图像与处理后的图像
|
|
BufferedImage sourceBuf=new BufferedImage(width,height,BufferedImage.TYPE_INT_ARGB);
|
|
BufferedImage targetBuf=new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
|
|
//将待处理图像绘制加载到源BufferedImage对像中
|
|
Graphics graph=sourceBuf.getGraphics();
|
|
graph.drawImage(ii.getImage(),0,0,Color.white,null);
|
|
for(int i=0;i<height;i++){//对待处理图中像素的行循环
|
|
for(int j=0;j<width;j++){//对待处理图中像素的列循环
|
|
int color=sourceBuf.getRGB(j,i);//获取指定位置处的像素
|
|
//拆分出RGB三个色彩通道的值
|
|
int r=(color >> 16) & 0xff;int g=(color >> 8) & 0xff;int b=(color) & 0xff;
|
|
float c=(r+g+b)/3.0f/255.0f;//求出折算后此像素的高度
|
|
if(i==0||j==width-1){//若为最左侧一列或最上面一行的像素不用计算
|
|
targetBuf.setRGB(j,i,0xFF8080FF);
|
|
continue;
|
|
}
|
|
//取出正上方像素的值并折算成高度
|
|
int colorUp=sourceBuf.getRGB(j,i-1);
|
|
int rUp=(colorUp >> 16) & 0xff;
|
|
int gUp=(colorUp >> 8) & 0xff;
|
|
int bUp=(colorUp) & 0xff;
|
|
float cUp=(rUp+gUp+bUp)/3.0f/255.0f;
|
|
//取出正右侧像素的值并折算成高度
|
|
int colorRight=sourceBuf.getRGB(j+1,i);
|
|
int rRight=(colorRight >> 16) & 0xff;
|
|
int gRight=(colorRight >> 8) & 0xff;
|
|
int bRight=(colorRight) & 0xff;
|
|
float cRight=(rRight+gRight+bRight)/3.0f/255.0f;
|
|
//计算出两个差分向量
|
|
float[] vec1={1,0,cUp-c};
|
|
float[] vec2={0,1,cRight-c};
|
|
//将差分向量叉积得到结果向量
|
|
float[] vResult=VectorUtil.getCrossProduct(vec1[0],vec1[1],vec1[2]*4,vec2[0],vec2[1],vec2[2]*4);
|
|
vResult=VectorUtil.vectorNormal(vResult);
|
|
//将结果向量各分量值折算到0-255的范围内
|
|
int cResultRed=(int)(vResult[0]*128)+128;
|
|
int cResultGreen=(int)(vResult[1]*128)+128;
|
|
int cResultBlue=(int)(vResult[2]*128)+128;
|
|
cResultRed=(cResultRed>255)?255:cResultRed;
|
|
cResultGreen=(cResultGreen>255)?255:cResultGreen;
|
|
cResultBlue=(cResultBlue>255)?255:cResultBlue;
|
|
//将结果向量送入像素
|
|
int cResult=0xFF000000;
|
|
cResult+=cResultRed<<16;
|
|
cResult+=cResultGreen<<8;
|
|
cResult+=cResultBlue;
|
|
targetBuf.setRGB(j,i,cResult);
|
|
}
|
|
}
|
|
return targetBuf;
|
|
}
|
|
|
|
public static void main(String[] args)
|
|
{
|
|
//创建Sample29_8窗体对象
|
|
new NormalMapUtil();
|
|
}
|
|
}
|