用了com.sun.media的jai-codec
完整代码了,开箱即用。
使用片段如下:
//crop7070
File fileOut = new File(uploadFolder.getAbsolutePath(), "crop_7070_" + photoFileName);
JpegCropper cropper7070 = new JpegCropper();
cropper7070.setCropScale(70f/cropInfo.getCropwidth(), 70f/cropInfo.getCropwidth());
boolean crop = cropper7070.crop(fileIn, fileOut, 70, 70);
if (!crop)
{
return false;
}
package xxx.xxx;
import java.awt.RenderingHints;
import java.awt.image.renderable.ParameterBlock;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import javax.media.jai.BorderExtender;
import javax.media.jai.Interpolation;
import javax.media.jai.JAI;
import javax.media.jai.KernelJAI;
import javax.media.jai.PlanarImage;
import javax.media.jai.RenderedOp;
import com.sun.media.jai.codec.ImageEncoder;
import com.sun.media.jai.codec.JPEGEncodeParam;
import com.sun.media.jai.codec.SeekableStream;
import com.sun.media.jai.codecimpl.JPEGCodec;
public class JpegCropper
{
private float x = 0;
private float y = 0;
private float scalex = 1;
private float scaley = 1;
private float quality = 0.8f;
private boolean scaleAuto = false;
//设置裁剪的起始坐标,如果没有调用该函数,在0,0位置开始裁剪
public void setCropCoordinate(float x, float y)
{
this.x = x;
this.y = y;
}
//设置横纵坐标下的缩放,如果没有调用该函数,不进行裁剪.其中为1表示不缩放,大于1表示拉升,小于1表示压缩
public void setCropScale(float scalex, float scaley)
{
this.scalex = scalex;
this.scaley = scaley;
}
//设置按输出和源大小等比例缩放
public void setCropScaleAuto(boolean b)
{
this.scaleAuto = b;
}
//设置jpeg输出的质量
public void setJpegOutQuality(float quality)
{
if (quality > 1)
{
return;
}
this.quality = quality;
}
//重写该函数,检查源图片的尺寸是否合适
protected boolean sourceImgSizeCheck(float width, float height)
{
//默认纵横超过就不合格
return !(width > 450 || height > 450);
}
public boolean crop(String filenameIn, String filenameOut, float targetW, float targetH)
{
return crop(new File(filenameIn), new File(filenameOut), targetW, targetH);
}
//裁剪目标高宽的图片
public boolean crop(File fileIn, File fileOut, float targetW, float targetH)
{
FileInputStream fis = null;
FileOutputStream fos = null;
try
{
fis = new FileInputStream(fileIn);
fos = new FileOutputStream(fileOut);
}
catch (FileNotFoundException e)
{
return false;
}
SeekableStream seekableStream = SeekableStream.wrapInputStream(fis, true);
PlanarImage sourceImage = JAI.create("stream", seekableStream);
if (!sourceImgSizeCheck(sourceImage.getWidth(), sourceImage.getHeight()))
{
//尺寸不符合要求
return false;
}
if (this.x + targetW > sourceImage.getWidth() || this.y + targetH > sourceImage.getHeight())
{
//x,y,targetW或targetH参数错误
return false;
}
if (scaleAuto)
{
//注意sourceImage有没有被重新赋值
this.scalex = targetW / sourceImage.getWidth();
this.scaley = targetH / sourceImage.getHeight();
}
RenderingHints copyBorderRenderingHints = new RenderingHints(JAI.KEY_BORDER_EXTENDER, BorderExtender.createInstance(BorderExtender.BORDER_COPY));
Interpolation interpolation = Interpolation.getInstance( Interpolation.INTERP_BILINEAR);
ParameterBlock pbPreTranslate = new ParameterBlock();
pbPreTranslate.addSource( sourceImage);
pbPreTranslate.add(x);
pbPreTranslate.add(y);
pbPreTranslate.add(interpolation);
RenderedOp translatedImage = JAI.create( "Translate", pbPreTranslate, copyBorderRenderingHints);
sourceImage = translatedImage;
//在很多使用下,并不需要进行缩放,所以有这个检查
if (this.scalex != 1 || this.scaley != 1)
{
//进行缩放
ParameterBlock pbScale = new ParameterBlock();
pbScale.addSource(sourceImage);
pbScale.add(this.scalex); //x Scale amount
pbScale.add(this.scaley); //y Scale amount
pbScale.add(0.0f); //x Translate amount
pbScale.add(0.0f); //y Translate amount
pbScale.add(interpolation); // interpolation
PlanarImage scaledImage = JAI.create("Scale", pbScale, copyBorderRenderingHints);
sourceImage = scaledImage;
}
//进行裁剪
ParameterBlock pbCropFinal = new ParameterBlock();
pbCropFinal.addSource( sourceImage);
pbCropFinal.add(0.0f);
pbCropFinal.add(0.0f);
pbCropFinal.add((float)targetW);
pbCropFinal.add((float)targetH);
PlanarImage croppedFinalImage = JAI.create("crop", pbCropFinal, copyBorderRenderingHints);
// Unsharpening image
KernelJAI unsharpKernel = getLowPassKernel(3);
ParameterBlock pbUnsharpMask = new ParameterBlock();
pbUnsharpMask.addSource(croppedFinalImage);
pbUnsharpMask.add(unsharpKernel);
pbUnsharpMask.add(0.25f);
PlanarImage unsharpenedImage = JAI.create("UnsharpMask",pbUnsharpMask,copyBorderRenderingHints);
// Writing image
JPEGEncodeParam param = new JPEGEncodeParam();
param.setQuality(this.quality);
ImageEncoder encoder = JPEGCodec.createImageEncoder("jpeg", fos, param);
try
{
encoder.encode(unsharpenedImage);
fos.flush();
fos.close();
}
catch (IOException e)
{
return false;
}
return true;
}
/**
* The default low-pass kernel. Every entry contains the value 1.0/(number of kernel elements)
*/
private static KernelJAI getLowPassKernel(int size)
{
int length = size * size;
float [] data = new float[length];
float value = 1.0f / (float) length;
for (int i = 0; i< length; i++)
{
data[i] = value;
}
return new KernelJAI(size, size, data);
}
}