package test;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
/**
* 因为等距采样法放大或者缩小的图像素点比较低,所以采取局部俊值法
* 根据上一张的内容讲到,将原来的图形像素填充到更大的区域里面去,分到大的空间,但是采取的像素是每个区域的开头的那个点,而这里是采取
* 区域内每一个点的均值作为缩小的那个图的像素点值
* @author Administrator
*
*/
public class ImageChangeTwo extends ImageChange {
public ImageChangeTwo(String filePath, String newFilePath)
throws IOException {
super(filePath, newFilePath);
// TODO 自动生成的构造函数存根
}
/**
* @param width 缩小后图片的宽
* @param height 缩小后图片的高
*/
public void flex(float width, float height) throws IOException {
// TODO 自动生成的方法存根
float kx = this.getOldBufferedImage().getWidth()/width;//算出旧图比新图宽度的比例
float ky = this.getOldBufferedImage().getHeight()/height;//算出旧图比新图高度的比例
System.out.println("kx:"+kx);
System.out.println("ky:"+ky);
if(kx>1||ky>1){
doBeSmall(width,height);
}else{
doBeBig(width,height);
}
}
private void doBeBig(float width, float height) {
// TODO 自动生成的方法存根
//采用双立方插值算法 或双线性插值放大
}
/**
* 采用局部均值法进行缩小
* @param width
* @param height
*/
private void doBeSmall(float width, float height) throws IOException {
// TODO 自动生成的方法存根
float kx = this.getOldBufferedImage().getWidth()/width;//算出旧图比新图宽度的比例
float ky = this.getOldBufferedImage().getHeight()/height;//算出旧图比新图高度的比例
int oldOffset=0,startX=0,startY=0;
int oldScansize=this.getOldBufferedImage().getWidth();
int oldWidth = this.getOldBufferedImage().getWidth();
int oldHeight = this.getOldBufferedImage().getHeight();
//定义旧图片像素数组
int[] pix = new int[oldOffset+(oldHeight-startY)*oldScansize+(oldWidth-startX)];
this.getOldBufferedImage().getRGB(startX, startY, oldWidth, oldHeight, pix, oldOffset, oldScansize);
//默认offset,startX,startY为0,scansize=newWidth
int[] newPix = new int [(int)(0+(height-0)*width+(width-0))] ;
//老规矩 遍历
for(int y =0; y<height;y++){
for(int x =0;x<width;x++){
//现在取到的是一个矩形的像素然后再用一个循环进去里面把像素的RGB像素值都取出来
int r=0,g=0,b=0;
ColorModel cm = ColorModel.getRGBdefault();
/*
* 返回描述整数 RGB 值的默认格式的 DirectColorModel,颜色空间为默认的 ColorSpace(即 sRGB)。
* RGB 值的格式是一个 8 位的整数,从最高有效字节到最低有效字节的相应顺序排列 alpha、红色、绿色和蓝色颜色分量,格式如下:0xAARRGGBB。颜色分量未与 alpha 分量预乘。
* 此格式不一定表示特定设备或所有图像的本机或最有效的 ColorModel。它只是一种通用的颜色模型格式。
*/
System.out.println(ky);
System.out.println(kx);
System.out.println((int)ky);
System.out.println((int)kx);
for(int my=0;my<(int)ky;my++){//这里记住要把ky转为int类型,不然会有错误,因为如果不强转的话,那么因为是float的原因,my将会自动读取到多一位,就相当于是my<=ky,这样会读到别的区域中的数值去
for(int mx = 0;mx<(int)kx;mx++){//这里记得要把kx转为int类型,不然会有错误
r=r+cm.getRed(pix [ (int)(y*ky+my)*oldWidth+(int)(x*kx+mx)]);
g=g+cm.getGreen(pix[((int)(y*ky+my))*oldScansize+(int)(x*kx+mx)]);
b=b+cm.getBlue(pix[((int)(y*ky+my))*oldScansize+(int)(x*kx+mx)]);
}
}
//求均值
r=r/((int)(kx*ky));
g=g/((int)(kx*ky));
b=b/((int)(kx*ky));
newPix[(int)(y*width)+x]=255<<24 | r<<16 | g<<8 | b;
//255<<24 | r<<16 | g<<8 | b 这个公式解释一下,颜色的RGB在内存中是
//以二进制的形式保存的,从右到左1-8位表示blue,9-16表示green,17-24表示red
//所以"<<24" "<<16" "<<8"分别表示左移24,16,8位
}
}
BufferedImage imgOut = new BufferedImage((int)width, (int)height, this.getOldBufferedImage().getType());
imgOut.setRGB(0, 0, (int)width, (int)height, newPix, 0, (int) width);
ImageIO.write(imgOut, "jpg", new File(this.getNewFilePath()));
System.out.println(new File(this.getNewFilePath()).exists());
}
}