对于图像的处理,其实就是对矩阵的处理,所以我们可以将图像的放大与缩小以及旋转问题转换为矩阵的放缩以及旋转。
对于图像的放缩,采用了线性插值:
https://blog.csdn.net/xiaqunfeng123/article/details/17362881
原理(步骤):
- 通过原始图像和比例因子得到新图像的大小,并创建图像
- 对(x1,y1)取整得到(xx,yy),(xx+1,yy),(xx,yy+1),(xx+1,yy+1)
- 利用双线性插值得到像素点(x,y)的值,并写回新图像
- 重复上面步骤,直到新图像的所有像素写完
直接上代码
public Image changeImg(Image img,double xScale,double yScale){
//通过原始图像和比例因子得到新图像的大小,并创建图像
//对(x1,y1)取整得到(xx,yy),(xx+1,yy),(xx,yy+1),(xx+1,yy+1)
//利用双线性插值得到像素点(x,y)的值,并写回新图像
//重复上面步骤,直到新图像的所有像素写完
BufferedImage tempImage=(BufferedImage)img;
BufferedImage newImage=new BufferedImage((int)(tempImage.getWidth()*xScale),(int)(tempImage.getHeight()*yScale),BufferedImage.TYPE_INT_RGB);
Graphics gs=newImage.getGraphics();
//由新图像的某个像素(x,y)映射到原始图像(x1,y1)处
for(int i=0;i<newImage.getWidth();i++){
for(int j=0;j<newImage.getHeight();j++){
double r,g,b;
//新图映射到原图的x坐标
double x1=i*(1/xScale);
//新图映射到原图的y坐标
double y1=j*(1/yScale);
//f(i+u,j+v) = (1-u)(1-v)f(i,j) + (1-u)vf(i,j+1) + u(1-v)f(i+1,j) + uvf(i+1,j+1)
//取整
double xx1=(double)Math.round(x1);
double yy1=(double)Math.round(y1);
double xx2=xx1+1;
double yy2=yy1+1;
//
if(xx1==tempImage.getWidth()-1&&yy1!=tempImage.getHeight()-1){
Color color1=new Color(tempImage.getRGB((int)xx1,(int)yy1));
Color color2=new Color(tempImage.getRGB((int)xx1,(int)yy2));
r=(1d-Math.abs(x1-xx1))*(1d-Math.abs(y1-yy1))*color1.getRed()
+(1d-Math.abs(x1-xx1))*(1d-Math.abs(y1-yy2))*color2.getRed();
g=(1-Math.abs(x1-xx1))*(1-Math.abs(y1-yy1))*color1.getGreen()
+(1-Math.abs(x1-xx1))*(1-Math.abs(y1-yy2))*color2.getGreen();
b=(1-Math.abs(x1-xx1))*(1-Math.abs(y1-yy1))*color1.getBlue()
+(1-Math.abs(x1-xx1))*(1-Math.abs(y1-yy2))*color2.getBlue();
gs.setColor(new Color((int)Math.min(255,Math.abs(r)),(int)Math.min(255,Math.abs(g)),(int)Math.min(255,Math.abs(b))));
gs.fillRect(i,j,1,1);
}else if(xx1!=tempImage.getWidth()-1&&yy1==tempImage.getHeight()-1){
Color color1=new Color(tempImage.getRGB((int)xx1,(int)yy1));
Color color3=new Color(tempImage.getRGB((int)xx2,(int)yy1));
r=(1-Math.abs(x1-xx1))*(1-Math.abs(y1-yy1))*color1.getRed()
+(1-Math.abs(x1-xx2))*(1-Math.abs(y1-yy1))*color3.getRed();
g=(1-Math.abs(x1-xx1))*(1-Math.abs(y1-yy1))*color1.getGreen()
+(1-Math.abs(x1-xx2))*(1-Math.abs(y1-yy1))*color3.getGreen();
b=(1-Math.abs(x1-xx1))*(1-Math.abs(y1-yy1))*color1.getBlue()
+(1-Math.abs(x1-xx2))*(1-Math.abs(y1-yy1))*color3.getBlue();
gs.setColor(new Color((int)Math.min(255,Math.abs(r)),(int)Math.min(255,Math.abs(g)),(int)Math.min(255,Math.abs(b))));
gs.fillRect(i,j,1,1);
}else if(xx1==tempImage.getWidth()-1&&yy1==tempImage.getHeight()-1){
Color color1=new Color(tempImage.getRGB((int)xx1,(int)yy1));
r=(1-Math.abs(x1-xx1))*(1-Math.abs(y1-yy1))*color1.getRed();
g=(1-Math.abs(x1-xx1))*(1-Math.abs(y1-yy1))*color1.getGreen();
b=(1-Math.abs(x1-xx1))*(1-Math.abs(y1-yy1))*color1.getBlue();
gs.setColor(new Color((int)Math.min(255,Math.abs(r)),(int)Math.min(255,Math.abs(g)),(int)Math.min(255,Math.abs(b))));
gs.fillRect(i,j,1,1);
}else{
//获取四个位置的Color对象
Color color1=new Color(tempImage.getRGB((int)xx1,(int)yy1));
Color color2=new Color(tempImage.getRGB((int)xx1,(int)yy2));
Color color3=new Color(tempImage.getRGB((int)xx2,(int)yy1));
Color color4=new Color(tempImage.getRGB((int)xx2,(int)yy2));
//对r,g,b进行权值计算
r=(1-Math.abs(x1-xx1))*(1-Math.abs(y1-yy1))*color1.getRed()
+(1-Math.abs(x1-xx1))*(1-Math.abs(y1-yy2))*color2.getRed()
+(1-Math.abs(x1-xx2))*(1-Math.abs(y1-yy1))*color3.getRed()
+(1-Math.abs(x1-xx2))*(1-Math.abs(y1-yy2))*color4.getRed();
g=(1-Math.abs(x1-xx1))*(1-Math.abs(y1-yy1))*color1.getGreen()
+(1-Math.abs(x1-xx1))*(1-Math.abs(y1-yy2))*color2.getGreen()
+(1-Math.abs(x1-xx2))*(1-Math.abs(y1-yy1))*color3.getGreen()
+(1-Math.abs(x1-xx2))*(1-Math.abs(y1-yy2))*color4.getGreen();
b=(1-Math.abs(x1-xx1))*(1-Math.abs(y1-yy1))*color1.getBlue()
+(1-Math.abs(x1-xx1))*(1-Math.abs(y1-yy2))*color2.getBlue()
+(1-Math.abs(x1-xx2))*(1-Math.abs(y1-yy1))*color3.getBlue()
+(1-Math.abs(x1-xx2))*(1-Math.abs(y1-yy2))*color4.getBlue();
// System.out.println("r= "+(int)Math.min(255,r)+" g= "+(int)Math.min(255,g)+" b= "+(int)Math.min(255,b));
gs.setColor(new Color((int)Math.min(255,Math.abs(r)),(int)Math.min(255,Math.abs(g)),(int)Math.min(255,Math.abs(b))));
gs.fillRect(i,j,1,1);
}
}
}
return newImage;
}
.
图像的旋转
规律: 顺时针旋转90度:原像素点的纵坐标变为新像素的横坐标,原像素的横坐标与矩阵宽的差值绝对值是新像素的纵坐标
逆时针旋转90度:原像素点的横坐标变为新像素的纵坐标,原像素的纵坐标与矩阵的高的差值的绝对值是新像素的横坐标
//顺时针
public Image change(Image image){
BufferedImage tempImage=(BufferedImage) image;
BufferedImage newImage=new BufferedImage(tempImage.getHeight(),tempImage.getWidth(),BufferedImage.TYPE_INT_RGB);
int index=tempImage.getHeight()-1;
for(int i=0;i<tempImage.getHeight();i++,index--){
for(int j=0;j<tempImage.getWidth();j++){
newImage.setRGB(index,j,tempImage.getRGB(j,i));
}
}
return newImage;
}