ImageUtils

来源:互联网 发布:武汉seo大牛 编辑:程序博客网 时间:2024/05/29 14:43

java中经常需要上传图片,对图片类型进行校验,常常使用的校验是通过文件后缀或者getContentType来判断文件类型是否符合,但是如果你使用了flash上传,有可能得到的图片类型为:application/octet-stream(任意的二进制数)如果你将这个类型加入到了判断条件里边实际上就没有多大意义了,所以确切的文件类型校验就需要如下判断了。所以可以考虑如下操作。

 

java图片处理类包含如下类:

 

第一:图片类型类:

 

Java代码  收藏代码
  1. /** 
  2.  * 图片类型 
  3.  *  
  4.  * @author  
  5.  * @since 2010-5-19 
  6.  */  
  7. public enum ImageType {  
  8.   
  9.     unknown(0"unknown"), jpg(1"jpg"), gif(2"gif"), png(3"png"), bmp(4,  
  10.             "bmp");  
  11.   
  12.     private int code;  
  13.     private String name;  
  14.   
  15.     ImageType(int code, String name) {  
  16.         this.code = code;  
  17.         this.name = name;  
  18.     }  
  19.   
  20.     public int getCode() {  
  21.         return code;  
  22.     }  
  23.   
  24.     public String getName() {  
  25.         return name;  
  26.     }  
  27.   
  28.     /** 
  29.      * 将后缀转换成图片类型, JPEG将转成jpg 
  30.      *  
  31.      * @param suffix 
  32.      * @return 
  33.      */  
  34.     public static ImageType toImageType(String suffix) {  
  35.         if (suffix == null || "".equals(suffix)) {  
  36.             return unknown;  
  37.         }  
  38.         suffix = suffix.toLowerCase();  
  39.         if ("jpeg".equals(suffix)) {  
  40.             suffix = "jpg";  
  41.         }  
  42.         try {  
  43.             return valueOf(suffix);  
  44.         } catch (Exception e) {  
  45.             return unknown;  
  46.         }  
  47.     }  
  48.   
  49.     /** 
  50.      * 判断图片类型 
  51.      *  
  52.      * @param suffix 
  53.      * @return 
  54.      */  
  55.     public static boolean isAcceptType(String suffix) {  
  56.         if (suffix == null || "".equals(suffix)) {  
  57.             return false;  
  58.         }  
  59.         if ("jpeg".equalsIgnoreCase(suffix)) {  
  60.             return true;  
  61.         }  
  62.         ImageType type = ImageType.valueOf(suffix.toLowerCase());  
  63.         if (type != null && type.getCode() > 0 && type.getCode() < 5) {  
  64.             return true;  
  65.         }  
  66.         return false;  
  67.     }  
  68.   
  69.     public static boolean isAcceptType(ImageType type) {  
  70.         if (type == null) {  
  71.             return false;  
  72.         }  
  73.         return isAcceptType(type.getName());  
  74.     }  
  75. }  

 

 图片扩展信息类:

 

Java代码  收藏代码
  1. import java.io.Serializable;  
  2.   
  3. /** 
  4.  * JPG的EXIT信息 ,相关规范参考: 1.* EXIF.org http://www.exif.org/ 2.* Opanda 
  5.  * http://www.opanda.com/cn/iexif/exif.htm 3.* EXIF 2.1 
  6.  * 官方标准(PDF文档)http://www.exif.org/Exif2-1.PDF 4.* EXIF 2.2 
  7.  * 官方标准(PDF文档)http://www.exif.org/Exif2-2.PDF 5.* EXIF 文件格式说明 
  8.  * http://park2.wakwak.com/~tsuruzoh/Computer/Digicams/exif-e.html 
  9.  *  
  10.  * @author  
  11.  * @since 2010-5-19 
  12.  */  
  13. public class ImageExif implements Serializable {  
  14.   
  15.     private static final long serialVersionUID = 4713490466591635082L;  
  16.   
  17.     private String ImageDescription;// 图像描述、来源. 指生成图像的工具     
  18.     private String Artist;// 作者 有些相机可以输入使用者的名字     
  19.     private String Make;// 生产者 指产品生产厂家     
  20.     private String Model;// 型号 指设备型号     
  21.     private String Orientation;// 方向 有的相机支持,有的不支持     
  22.     private String XResolution; // X方向分辨率  
  23.     private String YResolution;// Y方向分辨率  
  24.     private String ResolutionUnit;// 分辨率单位 一般为PPI  
  25.     private String Software;// 软件 显示固件  
  26.     private String Firmware;// 版本  
  27.     private String DateTime;// 日期和时间  
  28.     private String YCbCrPositioning;// 色相定位     
  29.     private String ExifOffsetExif;// 信息位置,定义Exif在信息在文件中的写入,有些软件不显示。  
  30.     private String ExposureTime;// 曝光时间 即快门速度    
  31.     private String FNumber; // 光圈系数  
  32.     private String ExposureProgram;// 曝光程序 指程序式自动曝光的设置,各相机不同,可能是Sutter  
  33.     // Priority(快门优先)、Aperture Priority(快门优先)等等。  
  34.     private String IsoSpeedRatings;// 感光度  
  35.     private String ExifVersion;// Exif版本  
  36.     private String DateTimeOriginal;// 创建时间  
  37.     private String DateTimeDigitized;// 数字化时间  
  38.     private String ComponentsConfiguration;// 图像构造(多指色彩组合方案)  
  39.     private String CompressedBitsPerPixel;// (BPP)压缩时每像素色彩位 指压缩程度  
  40.     private String ExposureBiasValue;// 曝光补偿。  
  41.     private String MaxApertureValue;// 最大光圈  
  42.     private String MeteringMode;// 测光方式,平均式测光、中央重点测光、点测光等。  
  43.     private String Lightsource;// 光源 指白平衡设置  
  44.     private String Flash;// 是否使用闪光灯。  
  45.     private String FocalLength;// 焦距,一般显示镜头物理焦距,有些软件可以定义一个系数,从而显示相当于35mm相机的焦距  
  46.     private String MakerNote;// (User Comment)作者标记、说明、记录  
  47.     private String FlashPixVersionFlashPix;// 版本 (个别机型支持)  
  48.     private String ColorSpace;// 色域、色彩空间  
  49.     private String ExifImageWidth;// (Pixel X Dimension)图像宽度 指横向像素数  
  50.     private String ExifImageLength;// (Pixel Y Dimension)图像高度 指纵向像素数  
  51.     private String Interoperability;// IFD通用性扩展项定义指针 和TIFF文件相关,具体含义不详  
  52.     private String FileSource;// 源文件 Compression压缩比  
  53.   
  54.     public String getImageDescription() {  
  55.         return ImageDescription;  
  56.     }  
  57.   
  58.     public void setImageDescription(String imageDescription) {  
  59.         ImageDescription = imageDescription;  
  60.     }  
  61.   
  62.     public String getArtist() {  
  63.         return Artist;  
  64.     }  
  65.   
  66.     public void setArtist(String artist) {  
  67.         Artist = artist;  
  68.     }  
  69.   
  70.     public String getMake() {  
  71.         return Make;  
  72.     }  
  73.   
  74.     public void setMake(String make) {  
  75.         Make = make;  
  76.     }  
  77.   
  78.     public String getModel() {  
  79.         return Model;  
  80.     }  
  81.   
  82.     public void setModel(String model) {  
  83.         Model = model;  
  84.     }  
  85.   
  86.     public String getOrientation() {  
  87.         return Orientation;  
  88.     }  
  89.   
  90.     public void setOrientation(String orientation) {  
  91.         Orientation = orientation;  
  92.     }  
  93.   
  94.     public String getXResolution() {  
  95.         return XResolution;  
  96.     }  
  97.   
  98.     public void setXResolution(String xResolution) {  
  99.         XResolution = xResolution;  
  100.     }  
  101.   
  102.     public String getYResolution() {  
  103.         return YResolution;  
  104.     }  
  105.   
  106.     public void setYResolution(String yResolution) {  
  107.         YResolution = yResolution;  
  108.     }  
  109.   
  110.     public String getResolutionUnit() {  
  111.         return ResolutionUnit;  
  112.     }  
  113.   
  114.     public void setResolutionUnit(String resolutionUnit) {  
  115.         ResolutionUnit = resolutionUnit;  
  116.     }  
  117.   
  118.     public String getSoftware() {  
  119.         return Software;  
  120.     }  
  121.   
  122.     public void setSoftware(String software) {  
  123.         Software = software;  
  124.     }  
  125.   
  126.     public String getFirmware() {  
  127.         return Firmware;  
  128.     }  
  129.   
  130.     public void setFirmware(String firmware) {  
  131.         Firmware = firmware;  
  132.     }  
  133.   
  134.     public String getDateTime() {  
  135.         return DateTime;  
  136.     }  
  137.   
  138.     public void setDateTime(String dateTime) {  
  139.         DateTime = dateTime;  
  140.     }  
  141.   
  142.     public String getYCbCrPositioning() {  
  143.         return YCbCrPositioning;  
  144.     }  
  145.   
  146.     public void setYCbCrPositioning(String yCbCrPositioning) {  
  147.         YCbCrPositioning = yCbCrPositioning;  
  148.     }  
  149.   
  150.     public String getExifOffsetExif() {  
  151.         return ExifOffsetExif;  
  152.     }  
  153.   
  154.     public void setExifOffsetExif(String exifOffsetExif) {  
  155.         ExifOffsetExif = exifOffsetExif;  
  156.     }  
  157.   
  158.     public String getExposureTime() {  
  159.         return ExposureTime;  
  160.     }  
  161.   
  162.     public void setExposureTime(String exposureTime) {  
  163.         ExposureTime = exposureTime;  
  164.     }  
  165.   
  166.     public String getFNumber() {  
  167.         return FNumber;  
  168.     }  
  169.   
  170.     public void setFNumber(String fNumber) {  
  171.         FNumber = fNumber;  
  172.     }  
  173.   
  174.     public String getExposureProgram() {  
  175.         return ExposureProgram;  
  176.     }  
  177.   
  178.     public void setExposureProgram(String exposureProgram) {  
  179.         ExposureProgram = exposureProgram;  
  180.     }  
  181.   
  182.     public String getIsoSpeedRatings() {  
  183.         return IsoSpeedRatings;  
  184.     }  
  185.   
  186.     public void setIsoSpeedRatings(String isoSpeedRatings) {  
  187.         IsoSpeedRatings = isoSpeedRatings;  
  188.     }  
  189.   
  190.     public String getExifVersion() {  
  191.         return ExifVersion;  
  192.     }  
  193.   
  194.     public void setExifVersion(String exifVersion) {  
  195.         ExifVersion = exifVersion;  
  196.     }  
  197.   
  198.     public String getDateTimeOriginal() {  
  199.         return DateTimeOriginal;  
  200.     }  
  201.   
  202.     public void setDateTimeOriginal(String dateTimeOriginal) {  
  203.         DateTimeOriginal = dateTimeOriginal;  
  204.     }  
  205.   
  206.     public String getDateTimeDigitized() {  
  207.         return DateTimeDigitized;  
  208.     }  
  209.   
  210.     public void setDateTimeDigitized(String dateTimeDigitized) {  
  211.         DateTimeDigitized = dateTimeDigitized;  
  212.     }  
  213.   
  214.     public String getComponentsConfiguration() {  
  215.         return ComponentsConfiguration;  
  216.     }  
  217.   
  218.     public void setComponentsConfiguration(String componentsConfiguration) {  
  219.         ComponentsConfiguration = componentsConfiguration;  
  220.     }  
  221.   
  222.     public String getCompressedBitsPerPixel() {  
  223.         return CompressedBitsPerPixel;  
  224.     }  
  225.   
  226.     public void setCompressedBitsPerPixel(String compressedBitsPerPixel) {  
  227.         CompressedBitsPerPixel = compressedBitsPerPixel;  
  228.     }  
  229.   
  230.     public String getExposureBiasValue() {  
  231.         return ExposureBiasValue;  
  232.     }  
  233.   
  234.     public void setExposureBiasValue(String exposureBiasValue) {  
  235.         ExposureBiasValue = exposureBiasValue;  
  236.     }  
  237.   
  238.     public String getMaxApertureValue() {  
  239.         return MaxApertureValue;  
  240.     }  
  241.   
  242.     public void setMaxApertureValue(String maxApertureValue) {  
  243.         MaxApertureValue = maxApertureValue;  
  244.     }  
  245.   
  246.     public String getMeteringMode() {  
  247.         return MeteringMode;  
  248.     }  
  249.   
  250.     public void setMeteringMode(String meteringMode) {  
  251.         MeteringMode = meteringMode;  
  252.     }  
  253.   
  254.     public String getLightsource() {  
  255.         return Lightsource;  
  256.     }  
  257.   
  258.     public void setLightsource(String lightsource) {  
  259.         Lightsource = lightsource;  
  260.     }  
  261.   
  262.     public String getFlash() {  
  263.         return Flash;  
  264.     }  
  265.   
  266.     public void setFlash(String flash) {  
  267.         Flash = flash;  
  268.     }  
  269.   
  270.     public String getFocalLength() {  
  271.         return FocalLength;  
  272.     }  
  273.   
  274.     public void setFocalLength(String focalLength) {  
  275.         FocalLength = focalLength;  
  276.     }  
  277.   
  278.     public String getMakerNote() {  
  279.         return MakerNote;  
  280.     }  
  281.   
  282.     public void setMakerNote(String makerNote) {  
  283.         MakerNote = makerNote;  
  284.     }  
  285.   
  286.     public String getFlashPixVersionFlashPix() {  
  287.         return FlashPixVersionFlashPix;  
  288.     }  
  289.   
  290.     public void setFlashPixVersionFlashPix(String flashPixVersionFlashPix) {  
  291.         FlashPixVersionFlashPix = flashPixVersionFlashPix;  
  292.     }  
  293.   
  294.     public String getColorSpace() {  
  295.         return ColorSpace;  
  296.     }  
  297.   
  298.     public void setColorSpace(String colorSpace) {  
  299.         ColorSpace = colorSpace;  
  300.     }  
  301.   
  302.     public String getExifImageWidth() {  
  303.         return ExifImageWidth;  
  304.     }  
  305.   
  306.     public void setExifImageWidth(String exifImageWidth) {  
  307.         ExifImageWidth = exifImageWidth;  
  308.     }  
  309.   
  310.     public String getExifImageLength() {  
  311.         return ExifImageLength;  
  312.     }  
  313.   
  314.     public void setExifImageLength(String exifImageLength) {  
  315.         ExifImageLength = exifImageLength;  
  316.     }  
  317.   
  318.     public String getInteroperability() {  
  319.         return Interoperability;  
  320.     }  
  321.   
  322.     public void setInteroperability(String interoperability) {  
  323.         Interoperability = interoperability;  
  324.     }  
  325.   
  326.     public String getFileSource() {  
  327.         return FileSource;  
  328.     }  
  329.   
  330.     public void setFileSource(String fileSource) {  
  331.         FileSource = fileSource;  
  332.     }  
  333.   
  334. }  

 图片文件对象:

Java代码  收藏代码
  1. import java.io.File;  
  2. import java.io.Serializable;  
  3.   
  4. /** 
  5.  * 图片文件信息 
  6.  *  
  7.  * @author  
  8.  * @since 2010-5-19 
  9.  */  
  10. public class ImageFile implements Serializable {  
  11.   
  12.     private static final long serialVersionUID = -337911125594555523L;  
  13.   
  14.     /** 
  15.      * 图片宽,单位:px 
  16.      */  
  17.     private double width;  
  18.   
  19.     /** 
  20.      * 图片高,单位:px 
  21.      */  
  22.     private double height;  
  23.   
  24.     /** 
  25.      * 图片大小,单位:byte 
  26.      */  
  27.     private double size;  
  28.   
  29.     /** 
  30.      * 图片类型 
  31.      */  
  32.     private ImageType type;  
  33.   
  34.     /** 
  35.      * 图片文件 
  36.      */  
  37.     private File file;  
  38.   
  39.     /** 
  40.      * 图片EXIF信息 
  41.      */  
  42.     private ImageExif exif;  
  43.   
  44.     public double getWidth() {  
  45.         return width;  
  46.     }  
  47.   
  48.     public void setWidth(double width) {  
  49.         this.width = width;  
  50.     }  
  51.   
  52.     public double getHeight() {  
  53.         return height;  
  54.     }  
  55.   
  56.     public void setHeight(double height) {  
  57.         this.height = height;  
  58.     }  
  59.   
  60.     public double getSize() {  
  61.         return size;  
  62.     }  
  63.   
  64.     public void setSize(double size) {  
  65.         this.size = size;  
  66.     }  
  67.   
  68.     public ImageType getType() {  
  69.         return type;  
  70.     }  
  71.   
  72.     public void setType(ImageType type) {  
  73.         this.type = type;  
  74.     }  
  75.   
  76.     public File getFile() {  
  77.         return file;  
  78.     }  
  79.   
  80.     public void setFile(File file) {  
  81.         this.file = file;  
  82.     }  
  83.   
  84.     public ImageExif getExif() {  
  85.         return exif;  
  86.     }  
  87.   
  88.     public void setExif(ImageExif exif) {  
  89.         this.exif = exif;  
  90.     }  
  91.   
  92. }  
 
Java代码  收藏代码
  1. import java.awt.Graphics;  
  2. import java.awt.Graphics2D;  
  3. import java.awt.Image;  
  4. import java.awt.RenderingHints;  
  5. import java.awt.Toolkit;  
  6. import java.awt.image.BufferedImage;  
  7. import java.awt.image.CropImageFilter;  
  8. import java.awt.image.FilteredImageSource;  
  9. import java.awt.image.ImageFilter;  
  10. import java.awt.image.RenderedImage;  
  11. import java.io.BufferedInputStream;  
  12. import java.io.ByteArrayInputStream;  
  13. import java.io.ByteArrayOutputStream;  
  14. import java.io.File;  
  15. import java.io.FileInputStream;  
  16. import java.io.FileOutputStream;  
  17. import java.io.IOException;  
  18. import java.io.InputStream;  
  19. import java.lang.reflect.Method;  
  20. import java.util.Iterator;  
  21.   
  22. import javax.imageio.ImageIO;  
  23. import javax.imageio.ImageReader;  
  24. import javax.imageio.stream.MemoryCacheImageInputStream;  
  25.   
  26. import magick.MagickImage;  
  27.   
  28. import org.apache.commons.lang.StringUtils;  
  29. import com.sun.image.codec.jpeg.JPEGCodec;  
  30. import com.sun.image.codec.jpeg.JPEGEncodeParam;  
  31. import com.sun.image.codec.jpeg.JPEGImageEncoder;  
  32. import com.sun.imageio.plugins.bmp.BMPImageReader;  
  33. import com.sun.imageio.plugins.gif.GIFImageReader;  
  34. import com.sun.imageio.plugins.jpeg.JPEGImageReader;  
  35. import com.sun.imageio.plugins.png.PNGImageReader;  
  36. import com.sun.imageio.plugins.wbmp.WBMPImageReader;  
  37.   
  38.   
  39. /** 
  40.  * 使用 imageio 实现的图片处理工具 
  41.  *  
  42.  * @author 
  43.  * @since 2010-7-14 
  44.  */  
  45. public class ImageIOUtil {  
  46.   
  47.     /** 
  48.      * 是否是合法图片 
  49.      *  
  50.      * @param suffix 
  51.      *            图片文件后缀 
  52.      * @param imageContent 
  53.      *            图片内容 
  54.      * @return 
  55.      */  
  56.     public static boolean isImage(byte[] imageContent) {  
  57.         return isImage(null, imageContent);  
  58.     }  
  59.   
  60.     /** 
  61.      * 是否是合法图片 
  62.      *  
  63.      * @param imageContent 
  64.      *            图片内容 
  65.      * @return 
  66.      */  
  67.     public static boolean isImage(String suffix, byte[] imageContent) {  
  68.         if (imageContent == null || imageContent.length == 0) {  
  69.             return false;  
  70.         }  
  71.         Image img = null;  
  72.         InputStream is = null;  
  73.         try {  
  74.             is = new ByteArrayInputStream(imageContent);  
  75.             img = ImageIO.read(is);  
  76.             if (img == null || img.getWidth(null) <= 0  
  77.                     || img.getHeight(null) <= 0) {  
  78.                 return false;  
  79.             }  
  80.             return true;  
  81.         } catch (Exception e) {  
  82.             return false;  
  83.         } finally {  
  84.             if (is != null) {  
  85.                 try {  
  86.                     is.close();  
  87.                 } catch (IOException e) {  
  88.                 }  
  89.             }  
  90.         }  
  91.     }  
  92.   
  93.     /** 
  94.      * 是否是合法图片 
  95.      *  
  96.      * @param imageFullPath 
  97.      *            图片本地绝对路径 
  98.      * @return 
  99.      */  
  100.     public static boolean isImage(String localImagePath) {  
  101.         File imgFile = new File(localImagePath);  
  102.         if (!imgFile.isFile()) {  
  103.             return false;  
  104.         }  
  105.         Image img;  
  106.         try {  
  107.             img = ImageIO.read(imgFile);  
  108.             if (imgFile.length() == 0 || img == null || img.getWidth(null) <= 0  
  109.                     || img.getHeight(null) <= 0) {  
  110.                 return false;  
  111.             }  
  112.             return true;  
  113.         } catch (Exception e) {  
  114.             return false;  
  115.         }  
  116.     }  
  117.   
  118.     /** 
  119.      * 根据要求的坐标截取图片 
  120.      *  
  121.      * @param source 
  122.      * @param x 
  123.      * @param y 
  124.      * @param width 
  125.      * @param height 
  126.      */  
  127.     public static void cropPart(String imageFullPath, int x, int y, int width,  
  128.             int height) throws RuntimeException {  
  129.         Image img = null;  
  130.         ImageFilter cropFilter = null;  
  131.         BufferedImage bi = null;  
  132.         try {  
  133.             bi = ImageIO.read(new File(imageFullPath));  
  134.             if (bi == null) {  
  135.                 throw new RuntimeException("ImageIO.read return null");  
  136.             }  
  137.         } catch (Exception e) {  
  138.             throw new RuntimeException(String.format("read image fail, src=",  
  139.                     imageFullPath));  
  140.         }  
  141.         int srcW = bi.getWidth();  
  142.         int srcH = bi.getHeight();  
  143.         if (srcW <= 0 || srcH <= 0) {  
  144.             throw new RuntimeException(String.format("invalid image, src=",  
  145.                     imageFullPath));  
  146.         }  
  147.         // 异常的图片参数  
  148.         if (x >= srcW || y >= srcH) {  
  149.             throw new RuntimeException(  
  150.                     String  
  151.                             .format(  
  152.                                     "cropPart fail, point (x=%s,y=%s) not in the image(width=%s,height=%s)",  
  153.                                     x, y, srcW, srcH));  
  154.         }  
  155.         width = Math.min(width, srcW - x);  
  156.         height = Math.min(height, srcH - y);  
  157.         try {  
  158.             Image image = bi.getScaledInstance(srcW, srcH, Image.SCALE_DEFAULT);  
  159.             cropFilter = new CropImageFilter(x, y, width, height);  
  160.             img = Toolkit.getDefaultToolkit().createImage(  
  161.                     new FilteredImageSource(image.getSource(), cropFilter));  
  162.             BufferedImage tag = new BufferedImage(width, height,  
  163.                     BufferedImage.TYPE_INT_RGB);  
  164.             Graphics2D g = (Graphics2D) tag.getGraphics();  
  165.             g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,  
  166.                     RenderingHints.VALUE_INTERPOLATION_BILINEAR);  
  167.             g.drawImage(img, 00null);  
  168.             g.dispose();  
  169.             ImageIO.write(tag, "jpg"new File(imageFullPath));  
  170.         } catch (Exception e) {  
  171.             throw new RuntimeException("process image error, src="  
  172.                     + imageFullPath, e);  
  173.         }  
  174.     }  
  175.   
  176.     /** 
  177.      * 将imageFullPath指定的图片进行等比缩放,最长的边为<t>maxEdgeLength</t> 
  178.      *  
  179.      * @param imageFullPath 
  180.      *            :需要裁剪的图片绝对路径 
  181.      * @param maxEdgeLength 
  182.      *            : 边长 
  183.      * @return 
  184.      */  
  185.     public static boolean resizeImage(String imageFullPath, int maxEdgeLength)  
  186.             throws Exception {  
  187.         File file = new File(imageFullPath);  
  188.         if (!file.exists()) {  
  189.             return false;  
  190.         }  
  191.         Image img = ImageIO.read(file);  
  192.         // 判断图片格式是否正确  
  193.         if (img == null || img.getWidth(null) <= 0 || img.getHeight(null) <= 0) {  
  194.             return false;  
  195.         }  
  196.         int width = img.getWidth(null);  
  197.         int height = img.getHeight(null);  
  198.   
  199.         boolean isWidthLonger = width > height ? true : false;  
  200.   
  201.         // 得到调整后的尺寸及缩小的比例,如果{width,height}都小于等于maxEdgeLength,直接返回  
  202.         if (width > maxEdgeLength || height > maxEdgeLength) {  
  203.             double ratio;  
  204.   
  205.             if (isWidthLonger) {  
  206.                 ratio = ((double) maxEdgeLength) / width;  
  207.                 width = maxEdgeLength;  
  208.                 height = ((Double) Math.floor(ratio * height)).intValue();  
  209.             } else {  
  210.                 ratio = ((double) maxEdgeLength) / height;  
  211.                 width = ((Double) Math.floor(ratio * width)).intValue();  
  212.                 height = maxEdgeLength;  
  213.             }  
  214.         } else {  
  215.             return true;  
  216.         }  
  217.         FileOutputStream out = null;  
  218.         try {  
  219.             BufferedImage tag = new BufferedImage((int) width, (int) height,  
  220.                     BufferedImage.TYPE_INT_RGB);  
  221.             tag.getGraphics().drawImage(  
  222.                     img.getScaledInstance(width, height, Image.SCALE_SMOOTH),  
  223.                     00null);  
  224.             out = new FileOutputStream(imageFullPath);  
  225.             ImageIO.write(tag, "jpg", out);  
  226.         } catch (Exception e) {  
  227.             throw new RuntimeException("resize image error, img="  
  228.                     + imageFullPath, e);  
  229.         } finally {  
  230.             if (out != null) {  
  231.                 out.close();  
  232.             }  
  233.         }  
  234.         return true;  
  235.     }  
  236.   
  237.     /** 
  238.      * 对imageFullPath 指定的文件按要求的质量quality进行压缩(gif将不会进行压缩)。quality的范围是(0-100) 
  239.      *  
  240.      * @param imageFullPath 
  241.      *            文件的绝对路径 
  242.      * @param quality 
  243.      *            压缩的质量,范围是(0-100) 
  244.      * @param maxFileSize 
  245.      *            文件超过该大小才进行质量有损压缩,单位:byte 
  246.      * @return 文件大小,单位:byte 
  247.      */  
  248.     public static int compressImage(String imageFullPath, int quality,  
  249.             long maxFileSize) {  
  250.         // 1. entry validation  
  251.         if (StringUtil.isEmpty(imageFullPath) || quality < 0 || quality > 100) {  
  252.             throw new RuntimeException("invalid parameters, src="  
  253.                     + imageFullPath + ",quality=" + quality);  
  254.         }  
  255.         File img = new File(imageFullPath);  
  256.         if (!img.isFile()) {  
  257.             throw new RuntimeException("file not exists, src=" + imageFullPath);  
  258.         }  
  259.         if (img.length() <= maxFileSize) {  
  260.             return (int) img.length();  
  261.         }  
  262.   
  263.         // 2. compress  
  264.         FileOutputStream out = null;  
  265.         try {  
  266.             // Retrieve jpg image to be compressed  
  267.             RenderedImage rendImage = ImageIO.read(new File(imageFullPath));  
  268.             if (rendImage == null || rendImage.getWidth() <= 0  
  269.                     || rendImage.getHeight() <= 0) {  
  270.                 throw new RuntimeException("file is not an image, src="  
  271.                         + imageFullPath);  
  272.             }  
  273.             out = new FileOutputStream(img);  
  274.             BufferedImage tag = new BufferedImage(rendImage.getWidth(),  
  275.                     rendImage.getHeight(), BufferedImage.TYPE_INT_RGB);  
  276.             tag.getGraphics().drawImage((Image) rendImage, 00,  
  277.                     rendImage.getWidth(), rendImage.getHeight(), null);  
  278.             JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);  
  279.             JPEGEncodeParam jep = JPEGCodec.getDefaultJPEGEncodeParam(tag);  
  280.             jep.setQuality(quality / 100f, true);  
  281.             encoder.encode(tag, jep);  
  282.         } catch (Exception e) {  
  283.             throw new RuntimeException("compressImage fail, src="  
  284.                     + imageFullPath, e);  
  285.         } finally {  
  286.             if (out != null) {  
  287.                 try {  
  288.                     out.close();  
  289.                 } catch (IOException e) {  
  290.                 }  
  291.             }  
  292.         }  
  293.         return (intnew File(imageFullPath).length();  
  294.     }  
  295.   
  296.     /** 
  297.      * 获取图片信息,包括宽/高/大小/类型,如果取不到会抛异常 
  298.      *  
  299.      * @param imageFullPath 
  300.      * @return 
  301.      * @throws Exception 
  302.      */  
  303.     public static ImageFile getImageInfo(String imageFullPath) throws Exception {  
  304.         return getImageInfo(imageFullPath, false);  
  305.     }  
  306.   
  307.     /** 
  308.      * (本方法暂不支持)获取图片信息+EXIF信息,如果非图片格式会抛异常 
  309.      *  
  310.      * @param localImagePath 
  311.      *            本地图片路径 
  312.      * @param isReadExif 
  313.      *            是否需要读取exif信息 
  314.      * @return 
  315.      * @throws Exception 
  316.      */  
  317.     @SuppressWarnings("unchecked")  
  318.     public static ImageFile getImageInfo(String localImagePath,  
  319.             boolean isReadExif) {  
  320.         File imgFile = new File(localImagePath);  
  321.         if (!imgFile.isFile()) {  
  322.             throw new RuntimeException("file not exists or not a file, file="  
  323.                     + localImagePath);  
  324.         }  
  325.         Image img;  
  326.         try {  
  327.             img = ImageIO.read(imgFile);  
  328.             if (imgFile.length() == 0 || img == null || img.getWidth(null) <= 0  
  329.                     || img.getHeight(null) <= 0) {  
  330.                 throw new RuntimeException(  
  331.                         "get image's size/width/height error, file="  
  332.                                 + localImagePath);  
  333.             }  
  334.         } catch (IOException e) {  
  335.             throw new RuntimeException(  
  336.                     "get image's size/width/height error, file="  
  337.                             + localImagePath);  
  338.         }  
  339.         ImageFile imageFile = new ImageFile();  
  340.         imageFile.setWidth(img.getWidth(null));  
  341.         imageFile.setHeight(img.getHeight(null));  
  342.         imageFile.setSize(imgFile.length());  
  343.         imageFile.setFile(imgFile);  
  344.   
  345.         FileInputStream fis = null;  
  346.         BufferedInputStream buff = null;  
  347.         int leng;  
  348.         byte[] mapObj;  
  349.         try {  
  350.             fis = new FileInputStream(imgFile);  
  351.             leng = fis.available();  
  352.             buff = new BufferedInputStream(fis);  
  353.             mapObj = new byte[leng];  
  354.             buff.read(mapObj, 0, leng);  
  355.         } catch (IOException e) {  
  356.             throw new RuntimeException("read image file stream error, file="  
  357.                     + localImagePath);  
  358.         }  
  359.   
  360.         String type = null;  
  361.         ByteArrayInputStream bais = null;  
  362.         MemoryCacheImageInputStream mcis = null;  
  363.         try {  
  364.             bais = new ByteArrayInputStream(mapObj);  
  365.             mcis = new MemoryCacheImageInputStream(bais);  
  366.             Iterator itr = ImageIO.getImageReaders(mcis);  
  367.             while (itr.hasNext()) {  
  368.                 ImageReader reader = (ImageReader) itr.next();  
  369.                 if (reader instanceof GIFImageReader) {  
  370.                     type = "gif";  
  371.                 } else if (reader instanceof JPEGImageReader) {  
  372.                     type = "jpg";  
  373.                 } else if (reader instanceof PNGImageReader) {  
  374.                     type = "png";  
  375.                 } else if (reader instanceof BMPImageReader  
  376.                         || reader instanceof WBMPImageReader) {  
  377.                     type = "bmp";  
  378.                 }  
  379.             }  
  380.             if (type != null) {  
  381.                 imageFile.setType(ImageType.valueOf(type));  
  382.                 if (isReadExif) {  
  383.                     // TODO read exif information  
  384.                 }  
  385.                 return imageFile;  
  386.             }  
  387.         } finally {  
  388.             if (bais != null) {  
  389.                 try {  
  390.                     bais.close();  
  391.                 } catch (IOException ioe) {  
  392.                 }  
  393.             }  
  394.             if (mcis != null) {  
  395.                 try {  
  396.                     mcis.close();  
  397.                 } catch (IOException ioe) {  
  398.                 }  
  399.             }  
  400.             if (buff != null) {  
  401.                 try {  
  402.                     buff.close();  
  403.                 } catch (IOException ioe) {  
  404.                 }  
  405.             }  
  406.             if (fis != null) {  
  407.                 try {  
  408.                     fis.close();  
  409.                 } catch (IOException ioe) {  
  410.                 }  
  411.             }  
  412.         }  
  413.         return null;  
  414.     }  
  415.   
  416.     private static Method[] exifMethods = ImageExif.class.getMethods();  
  417.   
  418.     private static ImageExif readImageExif(MagickImage image) {  
  419.         ImageExif exif = new ImageExif();  
  420.         if (image == null) {  
  421.             return exif;  
  422.         }  
  423.         try {  
  424.             for (Method method : exifMethods) {  
  425.                 if ("set".equals(method.getName().substring(03))) {  
  426.                     if (method.getName().length() > 3) {  
  427.                         method.invoke(exif, image.getImageAttribute("EXIF:"  
  428.                                 + method.getName().substring(3)));  
  429.                     }  
  430.                 }  
  431.             }  
  432.   
  433.         } catch (Exception e) {  
  434.             throw new RuntimeException("read image exif error", e);  
  435.         }  
  436.         return exif;  
  437.     }  
  438.   
  439.     /** 
  440.      * 给图片打水印(本地图片会被替换成有水印的图片),如果图片宽高要小于水印宽高+x或y,则不会打水印 
  441.      *  
  442.      * @param localImage 
  443.      *            源图的本地绝对路径 
  444.      * @param markImage 
  445.      *            水印图片的绝对路径 
  446.      * @param maskType 
  447.      *            0-右下角, 1-左下角, 2-正中间, 3-左上角, 4-右上角, 5-自定义 
  448.      * @param x 
  449.      *            离横向边间隔距离,如左对齐则左边距,右对齐则是右边距,居中传0,自定义则为左边距,单位:px 
  450.      * @param y 
  451.      *            离纵向边距离,如上对齐则上边距,下对齐则是下边距,居中传0,自定义则为上边距,单位:px 
  452.      * @return 
  453.      * @throws Exception 
  454.      */  
  455.     public static boolean mask(String localImage, String markImage,  
  456.             int maskType, int x, int y) throws Exception {  
  457.         return mask(localImage, localImage, markImage, maskType, x, y);  
  458.     }  
  459.   
  460.     /** 
  461.      * 给图片打水印(生成目标图片会带水印),如果图片宽高要小于水印宽高+endX或endY,则不会打水印 
  462.      *  
  463.      * @param imageBytes 
  464.      *            源图的byte数组 
  465.      * @param markImage 
  466.      *            水印图片的绝对路径 
  467.      * @param maskType 
  468.      *            0-右下角, 1-左下角, 2-正中间, 3-左上角, 4-右上角, 5-自定义 
  469.      * @param x 
  470.      *            离横向边间隔距离,如左对齐则左边距,右对齐则是右边距,居中传0,自定义则为左边距,单位:px 
  471.      * @param y 
  472.      *            离纵向边距离,如上对齐则上边距,下对齐则是下边距,居中传0,自定义则为上边距,单位:px 
  473.      * @return 处理后图片的byte数组 
  474.      * @throws Exception 
  475.      */  
  476.     public static byte[] mask(byte[] imageBytes, String markImage,  
  477.             int maskType, int x, int y) throws Exception {  
  478.         File srcTmp = File.createTempFile("ImageIOUtil"null);  
  479.         Image src = ImageIO.read(new ByteArrayInputStream(imageBytes));  
  480.         Image logo = ImageIO.read(new File(markImage));  
  481.         maskCore(src, srcTmp, logo, maskType, x, y);  
  482.         InputStream input = null;  
  483.         ByteArrayOutputStream out = null;  
  484.         try {  
  485.             input = new FileInputStream(srcTmp);  
  486.             out = new ByteArrayOutputStream(4096);  
  487.             byte[] b = new byte[4096];  
  488.             int n;  
  489.             while ((n = input.read(b)) != -1) {  
  490.                 out.write(b, 0, n);  
  491.                 out.flush();  
  492.             }  
  493.             return out.toByteArray();  
  494.         } finally {  
  495.             if (input != null) {  
  496.                 try {  
  497.                     input.close();  
  498.                 } catch (Exception e) {  
  499.                 }  
  500.             }  
  501.             if (out != null) {  
  502.                 try {  
  503.                     out.close();  
  504.                 } catch (Exception e) {  
  505.                 }  
  506.             }  
  507.         }  
  508.     }  
  509.   
  510.     /** 
  511.      * 给图片打水印(生成目标图片会带水印),如果图片宽高要小于水印宽高+x或y,则不会打水印 
  512.      *  
  513.      * @param localImage 
  514.      *            源图的本地绝对路径 
  515.      * @param destImage 
  516.      *            目标图片的本地绝对路径 
  517.      * @param markImage 
  518.      *            水印图片的绝对路径 
  519.      * @param maskType 
  520.      *            0-右下角, 1-左下角, 2-正中间, 3-左上角, 4-右上角, 5-自定义 
  521.      * @param x 
  522.      *            离横向边间隔距离,如左对齐则左边距,右对齐则是右边距,居中传0,自定义则为左边距,单位:px 
  523.      * @param y 
  524.      *            离纵向边距离,如上对齐则上边距,下对齐则是下边距,居中传0,自定义则为上边距,单位:px 
  525.      * @return 
  526.      * @throws Exception 
  527.      */  
  528.     public static boolean mask(String localImage, String destImage,  
  529.             String markImage, int maskType, int x, int y) throws Exception {  
  530.         Image src = ImageIO.read(new File(localImage));  
  531.         Image logo = ImageIO.read(new File(markImage));  
  532.         File dest = new File(destImage);  
  533.         return maskCore(src, dest, logo, maskType, x, y);  
  534.     }  
  535.   
  536.     /** 
  537.      * 打水印主逻辑 
  538.      *  
  539.      * @param src 
  540.      *            源图 
  541.      * @param dest 
  542.      *            目标输出文件 
  543.      * @param logo 
  544.      *            水印 
  545.      * @param maskType 
  546.      *            0-右下角, 1-左下角, 2-正中间, 3-左上角, 4-右上角, 5-自定义 
  547.      * @param marginX 
  548.      *            离横向边间隔距离,如左对齐则左边距,右对齐则是右边距,居中传0,自定义则为左边距,单位:px 
  549.      * @param marginY 
  550.      *            离纵向边距离,如上对齐则上边距,下对齐则是下边距,居中传0,自定义则为上边距,单位:px 
  551.      * @return 
  552.      * @throws Exception 
  553.      */  
  554.     private static boolean maskCore(Image src, File dest, Image logo,  
  555.             int maskType, int marginX, int marginY) throws Exception {  
  556.         // 校验图片合法性  
  557.         if (src == null || src.getWidth(null) <= 0 || src.getHeight(null) <= 0  
  558.                 || dest == null || logo == null || src.getWidth(null) <= 0  
  559.                 || src.getHeight(null) <= 0) {  
  560.             return false;  
  561.         }  
  562.         int srcW = src.getWidth(null);  
  563.         int srcH = src.getHeight(null);  
  564.         int logoW = logo.getWidth(null);  
  565.         int logoH = logo.getHeight(null);  
  566.   
  567.         int x = 0, y = 0;  
  568.         switch (maskType) {  
  569.         // 左下角  
  570.         case 1:  
  571.             x = marginX;  
  572.             y = (int) (srcH - logoH - marginY);  
  573.             break;  
  574.         // 正中间  
  575.         case 2:  
  576.             x = (int) ((srcW - logoW) / 2);  
  577.             y = (int) ((srcH - logoH) / 2);  
  578.             break;  
  579.         // 左上角  
  580.         case 3:  
  581.             x = marginX;  
  582.             y = marginY;  
  583.             break;  
  584.         // 右上角  
  585.         case 4:  
  586.             x = (int) (srcW - logoW - marginX);  
  587.             y = marginY;  
  588.             break;  
  589.         // 自定义  
  590.         case 5:  
  591.             x = marginX;  
  592.             y = marginY;  
  593.             break;  
  594.         // 右下角  
  595.         case 0:  
  596.             // 其它值默认右下角  
  597.         default:  
  598.             x = (int) (srcW - logoW - marginX);  
  599.             y = (int) (srcH - logoH - marginY);  
  600.         }  
  601.   
  602.         // 校验水印是否全部落在图片中  
  603.         if (x <= 0 || y <= 0 || x > srcW - logoW || y > srcH - logoH) {  
  604.             return false;  
  605.         }  
  606.   
  607.         FileOutputStream out = null;  
  608.         try {  
  609.             BufferedImage tag = new BufferedImage((int) srcW, (int) srcH,  
  610.                     BufferedImage.TYPE_INT_RGB);  
  611.             Graphics g = tag.getGraphics();  
  612.             g.drawImage(src, 00, srcW, srcH, null);  
  613.             g.drawImage(logo, x, y, logoW, logoH, null);  
  614.             out = new FileOutputStream(dest);  
  615.             ImageIO.write(tag, "jpg", out);  
  616.             g.dispose();  
  617.         } catch (Exception e) {  
  618.             throw new RuntimeException("resize image error", e);  
  619.         } finally {  
  620.             if (out != null) {  
  621.                 out.close();  
  622.             }  
  623.         }  
  624.         return true;  
  625.     }  
  626. }  

 上边的图片是要exif是需要使用JMagick获取所以如果有兴趣就需要同学安装,下面给出

JMagickUtil

 

 

Java代码  收藏代码
  1. import java.awt.Rectangle;  
  2. import java.io.File;  
  3. import java.lang.reflect.Method;  
  4.   
  5. import magick.CompositeOperator;  
  6. import magick.ImageInfo;  
  7. import magick.MagickImage;  
  8.   
  9. import org.apache.commons.lang.StringUtils;  
  10. import com.taobao.communitypsc.common.image.ImageExif;  
  11. import com.taobao.communitypsc.common.image.ImageFile;  
  12. import com.taobao.communitypsc.common.image.ImageType;  
  13.   
  14. /** 
  15.  * JMagick 处理图片 
  16.  *  
  17.  * @author  
  18.  * @since 2010-5-20 
  19.  */  
  20. public class JMagickUtil {  
  21.   
  22.     static {  
  23.         System.setProperty("jmagick.systemclassloader""no");  
  24.     }  
  25.   
  26.     /** 
  27.      * 是否是合法图片 
  28.      *  
  29.      * @param suffix 
  30.      *            图片文件后缀 
  31.      * @param imageContent 
  32.      *            图片内容 
  33.      * @return 
  34.      */  
  35.     public static boolean isImage(String suffix, byte[] imageContent) {  
  36.         try {  
  37.             MagickImage image = new MagickImage(new ImageInfo(suffix),  
  38.                     imageContent);  
  39.             if (image == null || image.getDimension().getWidth() <= 0) {  
  40.                 return false;  
  41.             }  
  42.         } catch (Exception e) {  
  43.             return false;  
  44.         }  
  45.         return true;  
  46.     }  
  47.   
  48.     /** 
  49.      * 是否是合法图片 
  50.      *  
  51.      * @param imageFullPath 
  52.      *            图片本地绝对路径 
  53.      * @return 
  54.      */  
  55.     public static boolean isImage(String localImagePath) {  
  56.         if (localImagePath == null || !new File(localImagePath).isFile()) {  
  57.             return false;  
  58.         }  
  59.         try {  
  60.             MagickImage image = new MagickImage(new ImageInfo(localImagePath));  
  61.             if (image.getDimension() == null  
  62.                     || image.getDimension().getWidth() <= 0) {  
  63.                 return false;  
  64.             }  
  65.         } catch (Exception e) {  
  66.             return false;  
  67.         }  
  68.         return true;  
  69.     }  
  70.   
  71.     /** 
  72.      * 根据要求的坐标截取图片 
  73.      *  
  74.      * @param source 
  75.      * @param x 
  76.      * @param y 
  77.      * @param width 
  78.      * @param height 
  79.      */  
  80.     public static void cropPart(String imageFullPath, int x, int y, int width,  
  81.             int height) throws Exception {  
  82.         MagickImage image = null;  
  83.         ImageInfo info = null;  
  84.         // 取得原文件  
  85.         try {  
  86.             info = new ImageInfo(imageFullPath);  
  87.             // 获取图片  
  88.             image = new MagickImage(info);  
  89.             // 原始尺寸  
  90.             int beforeScaleX = image.getDimension().width;  
  91.             int beforeScaleY = image.getDimension().height;  
  92.   
  93.             // 是否需要这个约束  
  94.             int cropWidth = (x + width > beforeScaleX) ? (beforeScaleX - x)  
  95.                     : width;  
  96.             int cropHeight = (y + height > beforeScaleY) ? (beforeScaleY - y)  
  97.                     : height;  
  98.   
  99.             MagickImage small = image.cropImage(new Rectangle(x, y, cropWidth,  
  100.                     cropHeight));  
  101.             small.setFileName(imageFullPath);  
  102.             small.writeImage(new ImageInfo());  
  103.             small.destroyImages();  
  104.         } finally {  
  105.             if (image != null) {  
  106.                 image.destroyImages();  
  107.             }  
  108.         }  
  109.     }  
  110.   
  111.     /** 
  112.      * 将imageFullPath指定的图片进行等比缩放,最长的边为<t>maxEdgeLength</t> 
  113.      *  
  114.      * @param imageFullPath 
  115.      *            :需要裁剪的图片绝对路径 
  116.      * @param edgeLength 
  117.      *            : 边长 
  118.      * @return 
  119.      */  
  120.     public static boolean resizeImage(String imageFullPath, int maxEdgeLength)  
  121.             throws Exception {  
  122.         // 取得原文件  
  123.         MagickImage image = new MagickImage(new ImageInfo(imageFullPath));  
  124.         String suffix = image.getImageFormat();  
  125.         if (suffix.equalsIgnoreCase("gif")) {  
  126.             image = extractFirstFrame(image);  
  127.         }  
  128.         // 原始尺寸  
  129.         int width = image.getDimension().width;  
  130.         int height = image.getDimension().height;  
  131.   
  132.         boolean isWidthLonger = width > height ? true : false;  
  133.   
  134.         // 得到调整后的尺寸及缩小的比例,如果{width,height}都小于等于maxEdgeLength,直接返回  
  135.         if (width > maxEdgeLength || height > maxEdgeLength) {  
  136.             double ratio;  
  137.   
  138.             if (isWidthLonger) {  
  139.                 ratio = ((double) maxEdgeLength) / width;  
  140.                 width = maxEdgeLength;  
  141.                 height = ((Double) Math.floor(ratio * height)).intValue();  
  142.             } else {  
  143.                 ratio = ((double) maxEdgeLength) / height;  
  144.                 width = ((Double) Math.floor(ratio * width)).intValue();  
  145.                 height = maxEdgeLength;  
  146.             }  
  147.   
  148.             MagickImage small = image.scaleImage(width, height);  
  149.             small.setFileName(imageFullPath);  
  150.             small.writeImage(new ImageInfo());  
  151.             small.destroyImages();  
  152.         }  
  153.         return true;  
  154.     }  
  155.   
  156.     /** 
  157.      * 截取第一帧 
  158.      *  
  159.      * @param image 
  160.      *            gif动画 
  161.      * @return 
  162.      */  
  163.     private static MagickImage extractFirstFrame(MagickImage image)  
  164.             throws Exception {  
  165.         MagickImage[] frames = image.breakFrames();  
  166.         return frames[0];  
  167.     }  
  168.   
  169.     /** 
  170.      * 对imageFullPath 指定的文件按要求的质量quality进行压缩(gif将不会进行压缩)。quality的范围是(0-100) 
  171.      *  
  172.      * @param imageFullPath 
  173.      *            文件的绝对路径 
  174.      * @param quality 
  175.      *            压缩的质量,范围是(0-100) 
  176.      * @param maxFileSize 
  177.      *            文件超过该大小才进行质量有损压缩,单位:byte 
  178.      * @return 文件大小,单位:byte 
  179.      */  
  180.     public static int compressImage(String imageFullPath, int quality,  
  181.             long maxFileSize) throws Exception {  
  182.         // 1. entry validation  
  183.         if (StringUtil.isEmpty(imageFullPath) || quality <= 0 || quality >= 100) {  
  184.             return -1;  
  185.         }  
  186.         int i = imageFullPath.lastIndexOf(".");  
  187.         if (i < 0) {  
  188.             return -1;  
  189.         }  
  190.   
  191.         // 2. compress  
  192.         String fileName = imageFullPath.substring(0, i);  
  193.         File fileSrc = new File(imageFullPath);  
  194.   
  195.         ImageInfo info = null;  
  196.         MagickImage image = null;  
  197.         try {  
  198.             info = new ImageInfo(imageFullPath);  
  199.             image = new MagickImage(info);  
  200.   
  201.             if (null == image || image.getDimension() == null  
  202.                     || image.getDimension().getWidth() <= 0) {  
  203.                 return -1;  
  204.             }  
  205.   
  206.             String type = image.getImageFormat();  
  207.   
  208.             if ("gif".equalsIgnoreCase(type)) {  
  209.                 // 解决 trojan.giframe 病毒 问题,gif 也通过MagickImage另存一下图片  
  210.                 fileName = fileName + ".gif";  
  211.                 image.setFileName(fileName);  
  212.                 image.writeImage(new ImageInfo());  
  213.             } else {  
  214.                 if (fileSrc.length() > maxFileSize) {// 大于指定文件大小,进行压缩  
  215.                     // 调整图片品质 最佳为40~50  
  216.                     info.setQuality(quality);  
  217.                     image.profileImage("*"null);  
  218.                     image.setImageAttribute("comment"null);  
  219.                     image.setImageAttribute("JPEG-Sampling-factors"null);  
  220.                     image.setFileName(imageFullPath);  
  221.                     image.writeImage(info);  
  222.                 }  
  223.             }  
  224.             return (int) fileSrc.length();  
  225.         } finally {  
  226.             if (image != null) {  
  227.                 image.destroyImages();  
  228.             }  
  229.         }  
  230.     }  
  231.   
  232.     /** 
  233.      * 获取图片信息,包括宽/高/大小/类型,如果取不到会抛异常 
  234.      *  
  235.      * @param imageFullPath 
  236.      * @return 
  237.      * @throws Exception 
  238.      */  
  239.     public static ImageFile getImageInfo(String imageFullPath) throws Exception {  
  240.         return getImageInfo(imageFullPath, false);  
  241.     }  
  242.   
  243.     /** 
  244.      * 获取图片信息+EXIF信息,如果非图片格式会抛异常 
  245.      *  
  246.      * @param localImagePath 
  247.      *            本地图片路径 
  248.      * @param isReadExif 
  249.      *            是否需要读取exif信息 
  250.      * @return 
  251.      * @throws Exception 
  252.      */  
  253.     public static ImageFile getImageInfo(String localImagePath,  
  254.             boolean isReadExif) throws Exception {  
  255.         File file = new File(localImagePath);  
  256.         if (!file.isFile()) {  
  257.             throw new Exception("file not exists or not a file, file="  
  258.                     + localImagePath);  
  259.         }  
  260.         ImageFile imageFile = new ImageFile();  
  261.         MagickImage image = new MagickImage(new ImageInfo(localImagePath));  
  262.         if (image.getDimension() == null  
  263.                 || image.getDimension().getWidth() <= 0) {  
  264.             throw new Exception("get image's dimension error, file="  
  265.                     + localImagePath);  
  266.         }  
  267.         imageFile.setFile(new File(localImagePath));  
  268.         imageFile.setHeight(image.getDimension().getHeight());  
  269.         imageFile.setWidth(image.getDimension().getWidth());  
  270.         imageFile.setType(ImageType.toImageType(image.getImageFormat()));  
  271.         imageFile.setSize(file.length());  
  272.         if (isReadExif) {  
  273.             imageFile.setExif(readImageExif(image));  
  274.         }  
  275.         return imageFile;  
  276.     }  
  277.   
  278.     private static Method[] exifMethods = ImageExif.class.getMethods();  
  279.   
  280.     private static ImageExif readImageExif(MagickImage image) {  
  281.         ImageExif exif = new ImageExif();  
  282.         if (image == null) {  
  283.             return exif;  
  284.         }  
  285.         try {  
  286.             for (Method method : exifMethods) {  
  287.                 if ("set".equals(method.getName().substring(03))) {  
  288.                     if (method.getName().length() > 3) {  
  289.                         method.invoke(exif, image.getImageAttribute("EXIF:"  
  290.                                 + method.getName().substring(3)));  
  291.                     }  
  292.                 }  
  293.             }  
  294.   
  295.         } catch (Exception e) {  
  296.             throw new RuntimeException("read image exif error", e);  
  297.         }  
  298.         return exif;  
  299.     }  
  300.   
  301.     /** 
  302.      * 给图片打水印(本地图片会被替换成有水印的图片),如果图片宽高要小于水印宽高+x或y,则不会打水印 
  303.      *  
  304.      * @param localImage 
  305.      *            源图的本地绝对路径 
  306.      * @param markImage 
  307.      *            水印图片的绝对路径 
  308.      * @param maskType 
  309.      *            0-右下角, 1-左下角, 2-正中间, 3-左上角, 4-右上角, 5-自定义 
  310.      * @param x 
  311.      *            离横向边间隔距离,如左对齐则左边距,右对齐则是右边距,居中传0,自定义则为左边距,单位:px 
  312.      * @param y 
  313.      *            离纵向边距离,如上对齐则上边距,下对齐则是下边距,居中传0,自定义则为上边距,单位:px 
  314.      * @return 
  315.      * @throws Exception 
  316.      */  
  317.     public static boolean mask(String localImage, String markImage,  
  318.             int maskType, int x, int y) throws Exception {  
  319.         return mask(localImage, localImage, markImage, maskType, x, y);  
  320.     }  
  321.   
  322.     /** 
  323.      * 给图片打水印(生成目标图片会带水印),如果图片宽高要小于水印宽高+endX或endY,则不会打水印 
  324.      *  
  325.      * @param imageBytes 
  326.      *            源图的byte数组 
  327.      * @param markImage 
  328.      *            水印图片的绝对路径 
  329.      * @param maskType 
  330.      *            0-右下角, 1-左下角, 2-正中间, 3-左上角, 4-右上角, 5-自定义 
  331.      * @param x 
  332.      *            离横向边间隔距离,如左对齐则左边距,右对齐则是右边距,居中传0,自定义则为左边距,单位:px 
  333.      * @param y 
  334.      *            离纵向边距离,如上对齐则上边距,下对齐则是下边距,居中传0,自定义则为上边距,单位:px 
  335.      * @return 处理后图片的byte数组 
  336.      * @throws Exception 
  337.      */  
  338.     public static byte[] mask(byte[] imageBytes, String markImage,  
  339.             int maskType, int x, int y) throws Exception {  
  340.         ImageInfo info = new ImageInfo();  
  341.         MagickImage src = null;  
  342.         MagickImage logo = null;  
  343.         try {  
  344.             src = new MagickImage(info, imageBytes);  
  345.             logo = new MagickImage(new ImageInfo(markImage));  
  346.             maskCore(src, src, info, logo, maskType, x, y);  
  347.             return src.imageToBlob(info);  
  348.         } finally {  
  349.             if (src != null) {  
  350.                 src.destroyImages();  
  351.             }  
  352.             if (logo != null) {  
  353.                 logo.destroyImages();  
  354.             }  
  355.         }  
  356.     }  
  357.   
  358.     /** 
  359.      * 给图片打水印(生成目标图片会带水印),如果图片宽高要小于水印宽高+x或y,则不会打水印 
  360.      *  
  361.      * @param localImage 
  362.      *            源图的本地绝对路径 
  363.      * @param destImage 
  364.      *            目标图片的本地绝对路径 
  365.      * @param markImage 
  366.      *            水印图片的绝对路径 
  367.      * @param maskType 
  368.      *            0-右下角, 1-左下角, 2-正中间, 3-左上角, 4-右上角, 5-自定义 
  369.      * @param x 
  370.      *            离横向边间隔距离,如左对齐则左边距,右对齐则是右边距,居中传0,自定义则为左边距,单位:px 
  371.      * @param y 
  372.      *            离纵向边距离,如上对齐则上边距,下对齐则是下边距,居中传0,自定义则为上边距,单位:px 
  373.      * @return 
  374.      * @throws Exception 
  375.      */  
  376.     public static boolean mask(String localImage, String destImage,  
  377.             String markImage, int maskType, int x, int y) throws Exception {  
  378.         MagickImage src = null;  
  379.         MagickImage logo = null;  
  380.         MagickImage dest = null;  
  381.         try {  
  382.             ImageInfo info = new ImageInfo(localImage);  
  383.             src = new MagickImage(info);  
  384.             logo = new MagickImage(new ImageInfo(markImage));  
  385.             dest = new MagickImage(info);  
  386.             dest.setFileName(destImage);  
  387.             return maskCore(src, dest, info, logo, maskType, x, y);  
  388.         } finally {  
  389.             if (src != null) {  
  390.                 src.destroyImages();  
  391.             }  
  392.             if (logo != null) {  
  393.                 logo.destroyImages();  
  394.             }  
  395.             if (dest != null) {  
  396.                 dest.destroyImages();  
  397.             }  
  398.         }  
  399.     }  
  400.   
  401.     /** 
  402.      * 打水印主逻辑 
  403.      *  
  404.      * @param src 
  405.      *            源图 
  406.      * @param dest 
  407.      *            目标图 
  408.      * @param writeInfo 
  409.      *            目标图的ImageInfo 
  410.      * @param logo 
  411.      *            水印 
  412.      * @param maskType 
  413.      *            0-右下角, 1-左下角, 2-正中间, 3-左上角, 4-右上角, 5-自定义 
  414.      * @param marginX 
  415.      *            离横向边间隔距离,如左对齐则左边距,右对齐则是右边距,居中传0,自定义则为左边距,单位:px 
  416.      * @param marginY 
  417.      *            离纵向边距离,如上对齐则上边距,下对齐则是下边距,居中传0,自定义则为上边距,单位:px 
  418.      * @return 
  419.      * @throws Exception 
  420.      */  
  421.     private static boolean maskCore(MagickImage src, MagickImage dest,  
  422.             ImageInfo writeInfo, MagickImage logo, int maskType, int marginX,  
  423.             int marginY) throws Exception {  
  424.         // 校验图片合法性  
  425.         if (src == null || src.getDimension() == null || dest == null  
  426.                 || dest.getDimension() == null || logo == null  
  427.                 || logo.getDimension() == null) {  
  428.             return false;  
  429.         }  
  430.         // gif图片处理,gif多桢不处理,单桢则处理  
  431.         String suffix = src.getImageFormat();  
  432.         if (suffix.equalsIgnoreCase("gif")) {  
  433.             MagickImage[] frames = src.breakFrames();  
  434.             if (frames.length > 1) {  
  435.                 return false;  
  436.             }  
  437.             src = frames[0];  
  438.         }  
  439.         double srcW = src.getDimension().getWidth();  
  440.         double srcH = src.getDimension().getHeight();  
  441.         double logoW = logo.getDimension().getWidth();  
  442.         double logoH = logo.getDimension().getHeight();  
  443.         if (srcW <= 0 || dest.getDimension().getWidth() <= 0 || logoW <= 0) {  
  444.             return false;  
  445.         }  
  446.         int x = 0, y = 0;  
  447.   
  448.         switch (maskType) {  
  449.         // 左下角  
  450.         case 1:  
  451.             x = marginX;  
  452.             y = (int) (srcH - logoH - marginY);  
  453.             break;  
  454.         // 正中间  
  455.         case 2:  
  456.             x = (int) ((srcW - logoW) / 2);  
  457.             y = (int) ((srcH - logoH) / 2);  
  458.             break;  
  459.         // 左上角  
  460.         case 3:  
  461.             x = marginX;  
  462.             y = marginY;  
  463.             break;  
  464.         // 右上角  
  465.         case 4:  
  466.             x = (int) (srcW - logoW - marginX);  
  467.             y = marginY;  
  468.             break;  
  469.         // 自定义  
  470.         case 5:  
  471.             x = marginX;  
  472.             y = marginY;  
  473.             break;  
  474.         // 右下角  
  475.         case 0:  
  476.             // 其它值默认右下角  
  477.         default:  
  478.             x = (int) (srcW - logoW - marginX);  
  479.             y = (int) (srcH - logoH - marginY);  
  480.         }  
  481.   
  482.         // 校验水印是否全部落在图片中  
  483.         if (x <= 0 || y <= 0 || x > srcW - logoW || y > srcH - logoH) {  
  484.             return false;  
  485.         }  
  486.   
  487.         dest.compositeImage(CompositeOperator.AtopCompositeOp, logo, x, y);  
  488.         dest.writeImage(writeInfo);  
  489.         return true;  
  490.     }  
  491. }  

 上传文件为流所以告诉大家一个不常用的好方法:

log4j中有一个StreamUtils.copyThenClose(InputStream, OutputStream);的方法,相信大家都会在自己的项目中使用log4j,所以可以考虑偷个懒试用一下这个类。

0 0