- 浏览: 206727 次
- 性别:
- 来自: 西安
文章分类
最新评论
-
tmy2016:
...
SpringMVC文件上传 -
lzj0327:
我刚学solr,感觉没法跟踪代码,都是封装好的,所以我对作者的 ...
Solr中DIH模式的使用 -
chenlf238:
不好意思,踩错了。
SpringMVC文件上传 -
wsh525354:
你好,我用的solr版本是4.9的,现在我自定义了一个Test ...
Solr中DIH模式的使用 -
田智伟:
<div class="quote_title ...
java图片处理
java中经常需要上传图片,对图片类型进行校验,常常使用的校验是通过文件后缀或者getContentType来判断文件类型是否符合,但是如果你使用了flash上传,有可能得到的图片类型为:application/octet-stream(任意的二进制数),如果你将这个类型加入到了判断条件里边实际上就没有多大意义了,所以确切的文件类型校验就需要如下判断了。所以可以考虑如下操作。
java图片处理类包含如下类:
第一:图片类型类:
/** * 图片类型 * * @author * @since 2010-5-19 */ public enum ImageType { unknown(0, "unknown"), jpg(1, "jpg"), gif(2, "gif"), png(3, "png"), bmp(4, "bmp"); private int code; private String name; ImageType(int code, String name) { this.code = code; this.name = name; } public int getCode() { return code; } public String getName() { return name; } /** * 将后缀转换成图片类型, JPEG将转成jpg * * @param suffix * @return */ public static ImageType toImageType(String suffix) { if (suffix == null || "".equals(suffix)) { return unknown; } suffix = suffix.toLowerCase(); if ("jpeg".equals(suffix)) { suffix = "jpg"; } try { return valueOf(suffix); } catch (Exception e) { return unknown; } } /** * 判断图片类型 * * @param suffix * @return */ public static boolean isAcceptType(String suffix) { if (suffix == null || "".equals(suffix)) { return false; } if ("jpeg".equalsIgnoreCase(suffix)) { return true; } ImageType type = ImageType.valueOf(suffix.toLowerCase()); if (type != null && type.getCode() > 0 && type.getCode() < 5) { return true; } return false; } public static boolean isAcceptType(ImageType type) { if (type == null) { return false; } return isAcceptType(type.getName()); } }
图片扩展信息类:
import java.io.Serializable; /** * JPG的EXIT信息 ,相关规范参考: 1.* EXIF.org http://www.exif.org/ 2.* Opanda * http://www.opanda.com/cn/iexif/exif.htm 3.* EXIF 2.1 * 官方标准(PDF文档)http://www.exif.org/Exif2-1.PDF 4.* EXIF 2.2 * 官方标准(PDF文档)http://www.exif.org/Exif2-2.PDF 5.* EXIF 文件格式说明 * http://park2.wakwak.com/~tsuruzoh/Computer/Digicams/exif-e.html * * @author * @since 2010-5-19 */ public class ImageExif implements Serializable { private static final long serialVersionUID = 4713490466591635082L; private String ImageDescription;// 图像描述、来源. 指生成图像的工具 private String Artist;// 作者 有些相机可以输入使用者的名字 private String Make;// 生产者 指产品生产厂家 private String Model;// 型号 指设备型号 private String Orientation;// 方向 有的相机支持,有的不支持 private String XResolution; // X方向分辨率 private String YResolution;// Y方向分辨率 private String ResolutionUnit;// 分辨率单位 一般为PPI private String Software;// 软件 显示固件 private String Firmware;// 版本 private String DateTime;// 日期和时间 private String YCbCrPositioning;// 色相定位 private String ExifOffsetExif;// 信息位置,定义Exif在信息在文件中的写入,有些软件不显示。 private String ExposureTime;// 曝光时间 即快门速度 private String FNumber; // 光圈系数 private String ExposureProgram;// 曝光程序 指程序式自动曝光的设置,各相机不同,可能是Sutter // Priority(快门优先)、Aperture Priority(快门优先)等等。 private String IsoSpeedRatings;// 感光度 private String ExifVersion;// Exif版本 private String DateTimeOriginal;// 创建时间 private String DateTimeDigitized;// 数字化时间 private String ComponentsConfiguration;// 图像构造(多指色彩组合方案) private String CompressedBitsPerPixel;// (BPP)压缩时每像素色彩位 指压缩程度 private String ExposureBiasValue;// 曝光补偿。 private String MaxApertureValue;// 最大光圈 private String MeteringMode;// 测光方式,平均式测光、中央重点测光、点测光等。 private String Lightsource;// 光源 指白平衡设置 private String Flash;// 是否使用闪光灯。 private String FocalLength;// 焦距,一般显示镜头物理焦距,有些软件可以定义一个系数,从而显示相当于35mm相机的焦距 private String MakerNote;// (User Comment)作者标记、说明、记录 private String FlashPixVersionFlashPix;// 版本 (个别机型支持) private String ColorSpace;// 色域、色彩空间 private String ExifImageWidth;// (Pixel X Dimension)图像宽度 指横向像素数 private String ExifImageLength;// (Pixel Y Dimension)图像高度 指纵向像素数 private String Interoperability;// IFD通用性扩展项定义指针 和TIFF文件相关,具体含义不详 private String FileSource;// 源文件 Compression压缩比 public String getImageDescription() { return ImageDescription; } public void setImageDescription(String imageDescription) { ImageDescription = imageDescription; } public String getArtist() { return Artist; } public void setArtist(String artist) { Artist = artist; } public String getMake() { return Make; } public void setMake(String make) { Make = make; } public String getModel() { return Model; } public void setModel(String model) { Model = model; } public String getOrientation() { return Orientation; } public void setOrientation(String orientation) { Orientation = orientation; } public String getXResolution() { return XResolution; } public void setXResolution(String xResolution) { XResolution = xResolution; } public String getYResolution() { return YResolution; } public void setYResolution(String yResolution) { YResolution = yResolution; } public String getResolutionUnit() { return ResolutionUnit; } public void setResolutionUnit(String resolutionUnit) { ResolutionUnit = resolutionUnit; } public String getSoftware() { return Software; } public void setSoftware(String software) { Software = software; } public String getFirmware() { return Firmware; } public void setFirmware(String firmware) { Firmware = firmware; } public String getDateTime() { return DateTime; } public void setDateTime(String dateTime) { DateTime = dateTime; } public String getYCbCrPositioning() { return YCbCrPositioning; } public void setYCbCrPositioning(String yCbCrPositioning) { YCbCrPositioning = yCbCrPositioning; } public String getExifOffsetExif() { return ExifOffsetExif; } public void setExifOffsetExif(String exifOffsetExif) { ExifOffsetExif = exifOffsetExif; } public String getExposureTime() { return ExposureTime; } public void setExposureTime(String exposureTime) { ExposureTime = exposureTime; } public String getFNumber() { return FNumber; } public void setFNumber(String fNumber) { FNumber = fNumber; } public String getExposureProgram() { return ExposureProgram; } public void setExposureProgram(String exposureProgram) { ExposureProgram = exposureProgram; } public String getIsoSpeedRatings() { return IsoSpeedRatings; } public void setIsoSpeedRatings(String isoSpeedRatings) { IsoSpeedRatings = isoSpeedRatings; } public String getExifVersion() { return ExifVersion; } public void setExifVersion(String exifVersion) { ExifVersion = exifVersion; } public String getDateTimeOriginal() { return DateTimeOriginal; } public void setDateTimeOriginal(String dateTimeOriginal) { DateTimeOriginal = dateTimeOriginal; } public String getDateTimeDigitized() { return DateTimeDigitized; } public void setDateTimeDigitized(String dateTimeDigitized) { DateTimeDigitized = dateTimeDigitized; } public String getComponentsConfiguration() { return ComponentsConfiguration; } public void setComponentsConfiguration(String componentsConfiguration) { ComponentsConfiguration = componentsConfiguration; } public String getCompressedBitsPerPixel() { return CompressedBitsPerPixel; } public void setCompressedBitsPerPixel(String compressedBitsPerPixel) { CompressedBitsPerPixel = compressedBitsPerPixel; } public String getExposureBiasValue() { return ExposureBiasValue; } public void setExposureBiasValue(String exposureBiasValue) { ExposureBiasValue = exposureBiasValue; } public String getMaxApertureValue() { return MaxApertureValue; } public void setMaxApertureValue(String maxApertureValue) { MaxApertureValue = maxApertureValue; } public String getMeteringMode() { return MeteringMode; } public void setMeteringMode(String meteringMode) { MeteringMode = meteringMode; } public String getLightsource() { return Lightsource; } public void setLightsource(String lightsource) { Lightsource = lightsource; } public String getFlash() { return Flash; } public void setFlash(String flash) { Flash = flash; } public String getFocalLength() { return FocalLength; } public void setFocalLength(String focalLength) { FocalLength = focalLength; } public String getMakerNote() { return MakerNote; } public void setMakerNote(String makerNote) { MakerNote = makerNote; } public String getFlashPixVersionFlashPix() { return FlashPixVersionFlashPix; } public void setFlashPixVersionFlashPix(String flashPixVersionFlashPix) { FlashPixVersionFlashPix = flashPixVersionFlashPix; } public String getColorSpace() { return ColorSpace; } public void setColorSpace(String colorSpace) { ColorSpace = colorSpace; } public String getExifImageWidth() { return ExifImageWidth; } public void setExifImageWidth(String exifImageWidth) { ExifImageWidth = exifImageWidth; } public String getExifImageLength() { return ExifImageLength; } public void setExifImageLength(String exifImageLength) { ExifImageLength = exifImageLength; } public String getInteroperability() { return Interoperability; } public void setInteroperability(String interoperability) { Interoperability = interoperability; } public String getFileSource() { return FileSource; } public void setFileSource(String fileSource) { FileSource = fileSource; } }
图片文件对象:
import java.io.File; import java.io.Serializable; /** * 图片文件信息 * * @author * @since 2010-5-19 */ public class ImageFile implements Serializable { private static final long serialVersionUID = -337911125594555523L; /** * 图片宽,单位:px */ private double width; /** * 图片高,单位:px */ private double height; /** * 图片大小,单位:byte */ private double size; /** * 图片类型 */ private ImageType type; /** * 图片文件 */ private File file; /** * 图片EXIF信息 */ private ImageExif exif; public double getWidth() { return width; } public void setWidth(double width) { this.width = width; } public double getHeight() { return height; } public void setHeight(double height) { this.height = height; } public double getSize() { return size; } public void setSize(double size) { this.size = size; } public ImageType getType() { return type; } public void setType(ImageType type) { this.type = type; } public File getFile() { return file; } public void setFile(File file) { this.file = file; } public ImageExif getExif() { return exif; } public void setExif(ImageExif exif) { this.exif = exif; } }
import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.RenderingHints; import java.awt.Toolkit; import java.awt.image.BufferedImage; import java.awt.image.CropImageFilter; import java.awt.image.FilteredImageSource; import java.awt.image.ImageFilter; import java.awt.image.RenderedImage; import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Method; import java.util.Iterator; import javax.imageio.ImageIO; import javax.imageio.ImageReader; import javax.imageio.stream.MemoryCacheImageInputStream; import magick.MagickImage; import org.apache.commons.lang.StringUtils; import com.sun.image.codec.jpeg.JPEGCodec; import com.sun.image.codec.jpeg.JPEGEncodeParam; import com.sun.image.codec.jpeg.JPEGImageEncoder; import com.sun.imageio.plugins.bmp.BMPImageReader; import com.sun.imageio.plugins.gif.GIFImageReader; import com.sun.imageio.plugins.jpeg.JPEGImageReader; import com.sun.imageio.plugins.png.PNGImageReader; import com.sun.imageio.plugins.wbmp.WBMPImageReader; /** * 使用 imageio 实现的图片处理工具 * * @author * @since 2010-7-14 */ public class ImageIOUtil { /** * 是否是合法图片 * * @param suffix * 图片文件后缀 * @param imageContent * 图片内容 * @return */ public static boolean isImage(byte[] imageContent) { return isImage(null, imageContent); } /** * 是否是合法图片 * * @param imageContent * 图片内容 * @return */ public static boolean isImage(String suffix, byte[] imageContent) { if (imageContent == null || imageContent.length == 0) { return false; } Image img = null; InputStream is = null; try { is = new ByteArrayInputStream(imageContent); img = ImageIO.read(is); if (img == null || img.getWidth(null) <= 0 || img.getHeight(null) <= 0) { return false; } return true; } catch (Exception e) { return false; } finally { if (is != null) { try { is.close(); } catch (IOException e) { } } } } /** * 是否是合法图片 * * @param imageFullPath * 图片本地绝对路径 * @return */ public static boolean isImage(String localImagePath) { File imgFile = new File(localImagePath); if (!imgFile.isFile()) { return false; } Image img; try { img = ImageIO.read(imgFile); if (imgFile.length() == 0 || img == null || img.getWidth(null) <= 0 || img.getHeight(null) <= 0) { return false; } return true; } catch (Exception e) { return false; } } /** * 根据要求的坐标截取图片 * * @param source * @param x * @param y * @param width * @param height */ public static void cropPart(String imageFullPath, int x, int y, int width, int height) throws RuntimeException { Image img = null; ImageFilter cropFilter = null; BufferedImage bi = null; try { bi = ImageIO.read(new File(imageFullPath)); if (bi == null) { throw new RuntimeException("ImageIO.read return null"); } } catch (Exception e) { throw new RuntimeException(String.format("read image fail, src=", imageFullPath)); } int srcW = bi.getWidth(); int srcH = bi.getHeight(); if (srcW <= 0 || srcH <= 0) { throw new RuntimeException(String.format("invalid image, src=", imageFullPath)); } // 异常的图片参数 if (x >= srcW || y >= srcH) { throw new RuntimeException( String .format( "cropPart fail, point (x=%s,y=%s) not in the image(width=%s,height=%s)", x, y, srcW, srcH)); } width = Math.min(width, srcW - x); height = Math.min(height, srcH - y); try { Image image = bi.getScaledInstance(srcW, srcH, Image.SCALE_DEFAULT); cropFilter = new CropImageFilter(x, y, width, height); img = Toolkit.getDefaultToolkit().createImage( new FilteredImageSource(image.getSource(), cropFilter)); BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics2D g = (Graphics2D) tag.getGraphics(); g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); g.drawImage(img, 0, 0, null); g.dispose(); ImageIO.write(tag, "jpg", new File(imageFullPath)); } catch (Exception e) { throw new RuntimeException("process image error, src=" + imageFullPath, e); } } /** * 将imageFullPath指定的图片进行等比缩放,最长的边为<t>maxEdgeLength</t> * * @param imageFullPath * :需要裁剪的图片绝对路径 * @param maxEdgeLength * : 边长 * @return */ public static boolean resizeImage(String imageFullPath, int maxEdgeLength) throws Exception { File file = new File(imageFullPath); if (!file.exists()) { return false; } Image img = ImageIO.read(file); // 判断图片格式是否正确 if (img == null || img.getWidth(null) <= 0 || img.getHeight(null) <= 0) { return false; } int width = img.getWidth(null); int height = img.getHeight(null); boolean isWidthLonger = width > height ? true : false; // 得到调整后的尺寸及缩小的比例,如果{width,height}都小于等于maxEdgeLength,直接返回 if (width > maxEdgeLength || height > maxEdgeLength) { double ratio; if (isWidthLonger) { ratio = ((double) maxEdgeLength) / width; width = maxEdgeLength; height = ((Double) Math.floor(ratio * height)).intValue(); } else { ratio = ((double) maxEdgeLength) / height; width = ((Double) Math.floor(ratio * width)).intValue(); height = maxEdgeLength; } } else { return true; } FileOutputStream out = null; try { BufferedImage tag = new BufferedImage((int) width, (int) height, BufferedImage.TYPE_INT_RGB); tag.getGraphics().drawImage( img.getScaledInstance(width, height, Image.SCALE_SMOOTH), 0, 0, null); out = new FileOutputStream(imageFullPath); ImageIO.write(tag, "jpg", out); } catch (Exception e) { throw new RuntimeException("resize image error, img=" + imageFullPath, e); } finally { if (out != null) { out.close(); } } return true; } /** * 对imageFullPath 指定的文件按要求的质量quality进行压缩(gif将不会进行压缩)。quality的范围是(0-100) * * @param imageFullPath * 文件的绝对路径 * @param quality * 压缩的质量,范围是(0-100) * @param maxFileSize * 文件超过该大小才进行质量有损压缩,单位:byte * @return 文件大小,单位:byte */ public static int compressImage(String imageFullPath, int quality, long maxFileSize) { // 1. entry validation if (StringUtil.isEmpty(imageFullPath) || quality < 0 || quality > 100) { throw new RuntimeException("invalid parameters, src=" + imageFullPath + ",quality=" + quality); } File img = new File(imageFullPath); if (!img.isFile()) { throw new RuntimeException("file not exists, src=" + imageFullPath); } if (img.length() <= maxFileSize) { return (int) img.length(); } // 2. compress FileOutputStream out = null; try { // Retrieve jpg image to be compressed RenderedImage rendImage = ImageIO.read(new File(imageFullPath)); if (rendImage == null || rendImage.getWidth() <= 0 || rendImage.getHeight() <= 0) { throw new RuntimeException("file is not an image, src=" + imageFullPath); } out = new FileOutputStream(img); BufferedImage tag = new BufferedImage(rendImage.getWidth(), rendImage.getHeight(), BufferedImage.TYPE_INT_RGB); tag.getGraphics().drawImage((Image) rendImage, 0, 0, rendImage.getWidth(), rendImage.getHeight(), null); JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out); JPEGEncodeParam jep = JPEGCodec.getDefaultJPEGEncodeParam(tag); jep.setQuality(quality / 100f, true); encoder.encode(tag, jep); } catch (Exception e) { throw new RuntimeException("compressImage fail, src=" + imageFullPath, e); } finally { if (out != null) { try { out.close(); } catch (IOException e) { } } } return (int) new File(imageFullPath).length(); } /** * 获取图片信息,包括宽/高/大小/类型,如果取不到会抛异常 * * @param imageFullPath * @return * @throws Exception */ public static ImageFile getImageInfo(String imageFullPath) throws Exception { return getImageInfo(imageFullPath, false); } /** * (本方法暂不支持)获取图片信息+EXIF信息,如果非图片格式会抛异常 * * @param localImagePath * 本地图片路径 * @param isReadExif * 是否需要读取exif信息 * @return * @throws Exception */ @SuppressWarnings("unchecked") public static ImageFile getImageInfo(String localImagePath, boolean isReadExif) { File imgFile = new File(localImagePath); if (!imgFile.isFile()) { throw new RuntimeException("file not exists or not a file, file=" + localImagePath); } Image img; try { img = ImageIO.read(imgFile); if (imgFile.length() == 0 || img == null || img.getWidth(null) <= 0 || img.getHeight(null) <= 0) { throw new RuntimeException( "get image's size/width/height error, file=" + localImagePath); } } catch (IOException e) { throw new RuntimeException( "get image's size/width/height error, file=" + localImagePath); } ImageFile imageFile = new ImageFile(); imageFile.setWidth(img.getWidth(null)); imageFile.setHeight(img.getHeight(null)); imageFile.setSize(imgFile.length()); imageFile.setFile(imgFile); FileInputStream fis = null; BufferedInputStream buff = null; int leng; byte[] mapObj; try { fis = new FileInputStream(imgFile); leng = fis.available(); buff = new BufferedInputStream(fis); mapObj = new byte[leng]; buff.read(mapObj, 0, leng); } catch (IOException e) { throw new RuntimeException("read image file stream error, file=" + localImagePath); } String type = null; ByteArrayInputStream bais = null; MemoryCacheImageInputStream mcis = null; try { bais = new ByteArrayInputStream(mapObj); mcis = new MemoryCacheImageInputStream(bais); Iterator itr = ImageIO.getImageReaders(mcis); while (itr.hasNext()) { ImageReader reader = (ImageReader) itr.next(); if (reader instanceof GIFImageReader) { type = "gif"; } else if (reader instanceof JPEGImageReader) { type = "jpg"; } else if (reader instanceof PNGImageReader) { type = "png"; } else if (reader instanceof BMPImageReader || reader instanceof WBMPImageReader) { type = "bmp"; } } if (type != null) { imageFile.setType(ImageType.valueOf(type)); if (isReadExif) { // TODO read exif information } return imageFile; } } finally { if (bais != null) { try { bais.close(); } catch (IOException ioe) { } } if (mcis != null) { try { mcis.close(); } catch (IOException ioe) { } } if (buff != null) { try { buff.close(); } catch (IOException ioe) { } } if (fis != null) { try { fis.close(); } catch (IOException ioe) { } } } return null; } private static Method[] exifMethods = ImageExif.class.getMethods(); private static ImageExif readImageExif(MagickImage image) { ImageExif exif = new ImageExif(); if (image == null) { return exif; } try { for (Method method : exifMethods) { if ("set".equals(method.getName().substring(0, 3))) { if (method.getName().length() > 3) { method.invoke(exif, image.getImageAttribute("EXIF:" + method.getName().substring(3))); } } } } catch (Exception e) { throw new RuntimeException("read image exif error", e); } return exif; } /** * 给图片打水印(本地图片会被替换成有水印的图片),如果图片宽高要小于水印宽高+x或y,则不会打水印 * * @param localImage * 源图的本地绝对路径 * @param markImage * 水印图片的绝对路径 * @param maskType * 0-右下角, 1-左下角, 2-正中间, 3-左上角, 4-右上角, 5-自定义 * @param x * 离横向边间隔距离,如左对齐则左边距,右对齐则是右边距,居中传0,自定义则为左边距,单位:px * @param y * 离纵向边距离,如上对齐则上边距,下对齐则是下边距,居中传0,自定义则为上边距,单位:px * @return * @throws Exception */ public static boolean mask(String localImage, String markImage, int maskType, int x, int y) throws Exception { return mask(localImage, localImage, markImage, maskType, x, y); } /** * 给图片打水印(生成目标图片会带水印),如果图片宽高要小于水印宽高+endX或endY,则不会打水印 * * @param imageBytes * 源图的byte数组 * @param markImage * 水印图片的绝对路径 * @param maskType * 0-右下角, 1-左下角, 2-正中间, 3-左上角, 4-右上角, 5-自定义 * @param x * 离横向边间隔距离,如左对齐则左边距,右对齐则是右边距,居中传0,自定义则为左边距,单位:px * @param y * 离纵向边距离,如上对齐则上边距,下对齐则是下边距,居中传0,自定义则为上边距,单位:px * @return 处理后图片的byte数组 * @throws Exception */ public static byte[] mask(byte[] imageBytes, String markImage, int maskType, int x, int y) throws Exception { File srcTmp = File.createTempFile("ImageIOUtil", null); Image src = ImageIO.read(new ByteArrayInputStream(imageBytes)); Image logo = ImageIO.read(new File(markImage)); maskCore(src, srcTmp, logo, maskType, x, y); InputStream input = null; ByteArrayOutputStream out = null; try { input = new FileInputStream(srcTmp); out = new ByteArrayOutputStream(4096); byte[] b = new byte[4096]; int n; while ((n = input.read(b)) != -1) { out.write(b, 0, n); out.flush(); } return out.toByteArray(); } finally { if (input != null) { try { input.close(); } catch (Exception e) { } } if (out != null) { try { out.close(); } catch (Exception e) { } } } } /** * 给图片打水印(生成目标图片会带水印),如果图片宽高要小于水印宽高+x或y,则不会打水印 * * @param localImage * 源图的本地绝对路径 * @param destImage * 目标图片的本地绝对路径 * @param markImage * 水印图片的绝对路径 * @param maskType * 0-右下角, 1-左下角, 2-正中间, 3-左上角, 4-右上角, 5-自定义 * @param x * 离横向边间隔距离,如左对齐则左边距,右对齐则是右边距,居中传0,自定义则为左边距,单位:px * @param y * 离纵向边距离,如上对齐则上边距,下对齐则是下边距,居中传0,自定义则为上边距,单位:px * @return * @throws Exception */ public static boolean mask(String localImage, String destImage, String markImage, int maskType, int x, int y) throws Exception { Image src = ImageIO.read(new File(localImage)); Image logo = ImageIO.read(new File(markImage)); File dest = new File(destImage); return maskCore(src, dest, logo, maskType, x, y); } /** * 打水印主逻辑 * * @param src * 源图 * @param dest * 目标输出文件 * @param logo * 水印 * @param maskType * 0-右下角, 1-左下角, 2-正中间, 3-左上角, 4-右上角, 5-自定义 * @param marginX * 离横向边间隔距离,如左对齐则左边距,右对齐则是右边距,居中传0,自定义则为左边距,单位:px * @param marginY * 离纵向边距离,如上对齐则上边距,下对齐则是下边距,居中传0,自定义则为上边距,单位:px * @return * @throws Exception */ private static boolean maskCore(Image src, File dest, Image logo, int maskType, int marginX, int marginY) throws Exception { // 校验图片合法性 if (src == null || src.getWidth(null) <= 0 || src.getHeight(null) <= 0 || dest == null || logo == null || src.getWidth(null) <= 0 || src.getHeight(null) <= 0) { return false; } int srcW = src.getWidth(null); int srcH = src.getHeight(null); int logoW = logo.getWidth(null); int logoH = logo.getHeight(null); int x = 0, y = 0; switch (maskType) { // 左下角 case 1: x = marginX; y = (int) (srcH - logoH - marginY); break; // 正中间 case 2: x = (int) ((srcW - logoW) / 2); y = (int) ((srcH - logoH) / 2); break; // 左上角 case 3: x = marginX; y = marginY; break; // 右上角 case 4: x = (int) (srcW - logoW - marginX); y = marginY; break; // 自定义 case 5: x = marginX; y = marginY; break; // 右下角 case 0: // 其它值默认右下角 default: x = (int) (srcW - logoW - marginX); y = (int) (srcH - logoH - marginY); } // 校验水印是否全部落在图片中 if (x <= 0 || y <= 0 || x > srcW - logoW || y > srcH - logoH) { return false; } FileOutputStream out = null; try { BufferedImage tag = new BufferedImage((int) srcW, (int) srcH, BufferedImage.TYPE_INT_RGB); Graphics g = tag.getGraphics(); g.drawImage(src, 0, 0, srcW, srcH, null); g.drawImage(logo, x, y, logoW, logoH, null); out = new FileOutputStream(dest); ImageIO.write(tag, "jpg", out); g.dispose(); } catch (Exception e) { throw new RuntimeException("resize image error", e); } finally { if (out != null) { out.close(); } } return true; } }
上边的图片是要exif是需要使用JMagick获取所以如果有兴趣就需要同学安装,下面给出
JMagickUtil
import java.awt.Rectangle; import java.io.File; import java.lang.reflect.Method; import magick.CompositeOperator; import magick.ImageInfo; import magick.MagickImage; import org.apache.commons.lang.StringUtils; import com.taobao.communitypsc.common.image.ImageExif; import com.taobao.communitypsc.common.image.ImageFile; import com.taobao.communitypsc.common.image.ImageType; /** * JMagick 处理图片 * * @author * @since 2010-5-20 */ public class JMagickUtil { static { System.setProperty("jmagick.systemclassloader", "no"); } /** * 是否是合法图片 * * @param suffix * 图片文件后缀 * @param imageContent * 图片内容 * @return */ public static boolean isImage(String suffix, byte[] imageContent) { try { MagickImage image = new MagickImage(new ImageInfo(suffix), imageContent); if (image == null || image.getDimension().getWidth() <= 0) { return false; } } catch (Exception e) { return false; } return true; } /** * 是否是合法图片 * * @param imageFullPath * 图片本地绝对路径 * @return */ public static boolean isImage(String localImagePath) { if (localImagePath == null || !new File(localImagePath).isFile()) { return false; } try { MagickImage image = new MagickImage(new ImageInfo(localImagePath)); if (image.getDimension() == null || image.getDimension().getWidth() <= 0) { return false; } } catch (Exception e) { return false; } return true; } /** * 根据要求的坐标截取图片 * * @param source * @param x * @param y * @param width * @param height */ public static void cropPart(String imageFullPath, int x, int y, int width, int height) throws Exception { MagickImage image = null; ImageInfo info = null; // 取得原文件 try { info = new ImageInfo(imageFullPath); // 获取图片 image = new MagickImage(info); // 原始尺寸 int beforeScaleX = image.getDimension().width; int beforeScaleY = image.getDimension().height; // 是否需要这个约束 int cropWidth = (x + width > beforeScaleX) ? (beforeScaleX - x) : width; int cropHeight = (y + height > beforeScaleY) ? (beforeScaleY - y) : height; MagickImage small = image.cropImage(new Rectangle(x, y, cropWidth, cropHeight)); small.setFileName(imageFullPath); small.writeImage(new ImageInfo()); small.destroyImages(); } finally { if (image != null) { image.destroyImages(); } } } /** * 将imageFullPath指定的图片进行等比缩放,最长的边为<t>maxEdgeLength</t> * * @param imageFullPath * :需要裁剪的图片绝对路径 * @param edgeLength * : 边长 * @return */ public static boolean resizeImage(String imageFullPath, int maxEdgeLength) throws Exception { // 取得原文件 MagickImage image = new MagickImage(new ImageInfo(imageFullPath)); String suffix = image.getImageFormat(); if (suffix.equalsIgnoreCase("gif")) { image = extractFirstFrame(image); } // 原始尺寸 int width = image.getDimension().width; int height = image.getDimension().height; boolean isWidthLonger = width > height ? true : false; // 得到调整后的尺寸及缩小的比例,如果{width,height}都小于等于maxEdgeLength,直接返回 if (width > maxEdgeLength || height > maxEdgeLength) { double ratio; if (isWidthLonger) { ratio = ((double) maxEdgeLength) / width; width = maxEdgeLength; height = ((Double) Math.floor(ratio * height)).intValue(); } else { ratio = ((double) maxEdgeLength) / height; width = ((Double) Math.floor(ratio * width)).intValue(); height = maxEdgeLength; } MagickImage small = image.scaleImage(width, height); small.setFileName(imageFullPath); small.writeImage(new ImageInfo()); small.destroyImages(); } return true; } /** * 截取第一帧 * * @param image * gif动画 * @return */ private static MagickImage extractFirstFrame(MagickImage image) throws Exception { MagickImage[] frames = image.breakFrames(); return frames[0]; } /** * 对imageFullPath 指定的文件按要求的质量quality进行压缩(gif将不会进行压缩)。quality的范围是(0-100) * * @param imageFullPath * 文件的绝对路径 * @param quality * 压缩的质量,范围是(0-100) * @param maxFileSize * 文件超过该大小才进行质量有损压缩,单位:byte * @return 文件大小,单位:byte */ public static int compressImage(String imageFullPath, int quality, long maxFileSize) throws Exception { // 1. entry validation if (StringUtil.isEmpty(imageFullPath) || quality <= 0 || quality >= 100) { return -1; } int i = imageFullPath.lastIndexOf("."); if (i < 0) { return -1; } // 2. compress String fileName = imageFullPath.substring(0, i); File fileSrc = new File(imageFullPath); ImageInfo info = null; MagickImage image = null; try { info = new ImageInfo(imageFullPath); image = new MagickImage(info); if (null == image || image.getDimension() == null || image.getDimension().getWidth() <= 0) { return -1; } String type = image.getImageFormat(); if ("gif".equalsIgnoreCase(type)) { // 解决 trojan.giframe 病毒 问题,gif 也通过MagickImage另存一下图片 fileName = fileName + ".gif"; image.setFileName(fileName); image.writeImage(new ImageInfo()); } else { if (fileSrc.length() > maxFileSize) {// 大于指定文件大小,进行压缩 // 调整图片品质 最佳为40~50 info.setQuality(quality); image.profileImage("*", null); image.setImageAttribute("comment", null); image.setImageAttribute("JPEG-Sampling-factors", null); image.setFileName(imageFullPath); image.writeImage(info); } } return (int) fileSrc.length(); } finally { if (image != null) { image.destroyImages(); } } } /** * 获取图片信息,包括宽/高/大小/类型,如果取不到会抛异常 * * @param imageFullPath * @return * @throws Exception */ public static ImageFile getImageInfo(String imageFullPath) throws Exception { return getImageInfo(imageFullPath, false); } /** * 获取图片信息+EXIF信息,如果非图片格式会抛异常 * * @param localImagePath * 本地图片路径 * @param isReadExif * 是否需要读取exif信息 * @return * @throws Exception */ public static ImageFile getImageInfo(String localImagePath, boolean isReadExif) throws Exception { File file = new File(localImagePath); if (!file.isFile()) { throw new Exception("file not exists or not a file, file=" + localImagePath); } ImageFile imageFile = new ImageFile(); MagickImage image = new MagickImage(new ImageInfo(localImagePath)); if (image.getDimension() == null || image.getDimension().getWidth() <= 0) { throw new Exception("get image's dimension error, file=" + localImagePath); } imageFile.setFile(new File(localImagePath)); imageFile.setHeight(image.getDimension().getHeight()); imageFile.setWidth(image.getDimension().getWidth()); imageFile.setType(ImageType.toImageType(image.getImageFormat())); imageFile.setSize(file.length()); if (isReadExif) { imageFile.setExif(readImageExif(image)); } return imageFile; } private static Method[] exifMethods = ImageExif.class.getMethods(); private static ImageExif readImageExif(MagickImage image) { ImageExif exif = new ImageExif(); if (image == null) { return exif; } try { for (Method method : exifMethods) { if ("set".equals(method.getName().substring(0, 3))) { if (method.getName().length() > 3) { method.invoke(exif, image.getImageAttribute("EXIF:" + method.getName().substring(3))); } } } } catch (Exception e) { throw new RuntimeException("read image exif error", e); } return exif; } /** * 给图片打水印(本地图片会被替换成有水印的图片),如果图片宽高要小于水印宽高+x或y,则不会打水印 * * @param localImage * 源图的本地绝对路径 * @param markImage * 水印图片的绝对路径 * @param maskType * 0-右下角, 1-左下角, 2-正中间, 3-左上角, 4-右上角, 5-自定义 * @param x * 离横向边间隔距离,如左对齐则左边距,右对齐则是右边距,居中传0,自定义则为左边距,单位:px * @param y * 离纵向边距离,如上对齐则上边距,下对齐则是下边距,居中传0,自定义则为上边距,单位:px * @return * @throws Exception */ public static boolean mask(String localImage, String markImage, int maskType, int x, int y) throws Exception { return mask(localImage, localImage, markImage, maskType, x, y); } /** * 给图片打水印(生成目标图片会带水印),如果图片宽高要小于水印宽高+endX或endY,则不会打水印 * * @param imageBytes * 源图的byte数组 * @param markImage * 水印图片的绝对路径 * @param maskType * 0-右下角, 1-左下角, 2-正中间, 3-左上角, 4-右上角, 5-自定义 * @param x * 离横向边间隔距离,如左对齐则左边距,右对齐则是右边距,居中传0,自定义则为左边距,单位:px * @param y * 离纵向边距离,如上对齐则上边距,下对齐则是下边距,居中传0,自定义则为上边距,单位:px * @return 处理后图片的byte数组 * @throws Exception */ public static byte[] mask(byte[] imageBytes, String markImage, int maskType, int x, int y) throws Exception { ImageInfo info = new ImageInfo(); MagickImage src = null; MagickImage logo = null; try { src = new MagickImage(info, imageBytes); logo = new MagickImage(new ImageInfo(markImage)); maskCore(src, src, info, logo, maskType, x, y); return src.imageToBlob(info); } finally { if (src != null) { src.destroyImages(); } if (logo != null) { logo.destroyImages(); } } } /** * 给图片打水印(生成目标图片会带水印),如果图片宽高要小于水印宽高+x或y,则不会打水印 * * @param localImage * 源图的本地绝对路径 * @param destImage * 目标图片的本地绝对路径 * @param markImage * 水印图片的绝对路径 * @param maskType * 0-右下角, 1-左下角, 2-正中间, 3-左上角, 4-右上角, 5-自定义 * @param x * 离横向边间隔距离,如左对齐则左边距,右对齐则是右边距,居中传0,自定义则为左边距,单位:px * @param y * 离纵向边距离,如上对齐则上边距,下对齐则是下边距,居中传0,自定义则为上边距,单位:px * @return * @throws Exception */ public static boolean mask(String localImage, String destImage, String markImage, int maskType, int x, int y) throws Exception { MagickImage src = null; MagickImage logo = null; MagickImage dest = null; try { ImageInfo info = new ImageInfo(localImage); src = new MagickImage(info); logo = new MagickImage(new ImageInfo(markImage)); dest = new MagickImage(info); dest.setFileName(destImage); return maskCore(src, dest, info, logo, maskType, x, y); } finally { if (src != null) { src.destroyImages(); } if (logo != null) { logo.destroyImages(); } if (dest != null) { dest.destroyImages(); } } } /** * 打水印主逻辑 * * @param src * 源图 * @param dest * 目标图 * @param writeInfo * 目标图的ImageInfo * @param logo * 水印 * @param maskType * 0-右下角, 1-左下角, 2-正中间, 3-左上角, 4-右上角, 5-自定义 * @param marginX * 离横向边间隔距离,如左对齐则左边距,右对齐则是右边距,居中传0,自定义则为左边距,单位:px * @param marginY * 离纵向边距离,如上对齐则上边距,下对齐则是下边距,居中传0,自定义则为上边距,单位:px * @return * @throws Exception */ private static boolean maskCore(MagickImage src, MagickImage dest, ImageInfo writeInfo, MagickImage logo, int maskType, int marginX, int marginY) throws Exception { // 校验图片合法性 if (src == null || src.getDimension() == null || dest == null || dest.getDimension() == null || logo == null || logo.getDimension() == null) { return false; } // gif图片处理,gif多桢不处理,单桢则处理 String suffix = src.getImageFormat(); if (suffix.equalsIgnoreCase("gif")) { MagickImage[] frames = src.breakFrames(); if (frames.length > 1) { return false; } src = frames[0]; } double srcW = src.getDimension().getWidth(); double srcH = src.getDimension().getHeight(); double logoW = logo.getDimension().getWidth(); double logoH = logo.getDimension().getHeight(); if (srcW <= 0 || dest.getDimension().getWidth() <= 0 || logoW <= 0) { return false; } int x = 0, y = 0; switch (maskType) { // 左下角 case 1: x = marginX; y = (int) (srcH - logoH - marginY); break; // 正中间 case 2: x = (int) ((srcW - logoW) / 2); y = (int) ((srcH - logoH) / 2); break; // 左上角 case 3: x = marginX; y = marginY; break; // 右上角 case 4: x = (int) (srcW - logoW - marginX); y = marginY; break; // 自定义 case 5: x = marginX; y = marginY; break; // 右下角 case 0: // 其它值默认右下角 default: x = (int) (srcW - logoW - marginX); y = (int) (srcH - logoH - marginY); } // 校验水印是否全部落在图片中 if (x <= 0 || y <= 0 || x > srcW - logoW || y > srcH - logoH) { return false; } dest.compositeImage(CompositeOperator.AtopCompositeOp, logo, x, y); dest.writeImage(writeInfo); return true; } }
上传文件为流所以告诉大家一个不常用的好方法:
log4j中有一个StreamUtils.copyThenClose(InputStream, OutputStream);的方法,相信大家都会在自己的项目中使用log4j,所以可以考虑偷个懒试用一下这个类。
评论
3 楼
田智伟
2015-05-14
278506470 写道
楼主,magick 这个包是你自己写的吗? 怎么找不到?找不到那几个java的类,可否提供。
有个包叫jmagick
2 楼
2047699523
2015-05-11
java图片工具类源代码下载:http://www.zuidaima.com/share/k%E5%9B%BE%E7%89%87-p1-s1.htm
1 楼
278506470
2014-04-12
楼主,magick 这个包是你自己写的吗? 怎么找不到?找不到那几个java的类,可否提供。
发表评论
-
java7文件及目录变更监控
2015-06-01 11:59 775之前想过对一些文件操作最好能够监控,从而通过文件变更监控来解 ... -
java中工具类
2013-08-23 18:30 1976java中需要一些toString的操作, ... -
Log4J显示ibatis的执行日志
2012-12-02 11:31 5018首先配置appender <appende ... -
Java中处理CST格式时间
2012-11-20 21:54 12564今天被CST格式的时间折腾了一晚上,先看看什么是CST格式时 ... -
HTTPClient使用
2012-10-23 16:08 4490平时工作中难免需要调用http接口来获取数据,尤其对于json ... -
代码编译出现(illegal character: \65279)
2012-10-11 17:28 24991今天在代码打包时报如下错误::1: illegal chara ... -
java中文档注释
2012-10-11 14:55 132531 常用Java注释标签(Java comment ta ... -
java--初始化与清理
2012-09-22 11:52 1446从java1.5依赖提供了一个我很喜欢用的功能Foreach ... -
java--操作符
2012-09-18 23:14 1575java中的操作符与其他 ... -
java--一切皆对象
2012-09-18 22:39 1265java是一门面向对象语言,这个从一开始我们就明白了,可是真 ... -
如何静态初始化List
2012-09-10 16:29 7673public static List<String&g ... -
Java入门
2012-08-24 00:31 1971昨天面试被人BS,虽然心中有无限怨念,不过本屌 ... -
枚举类型的使用
2012-03-11 13:17 823如何使用枚举类: 通常的方式是直接定义一个枚举类,但是 ...
相关推荐
SimpleImage是阿里巴巴的一个Java图片处理的类库,可以实现图片缩略、水印等处理。 SimpleImage中的ImageRender是图片处理的基类,它是一个抽象类,我们看到,该类中定义了一个抽象方法render(),同时持有一个对...
Java图片处理工具ImageMagick是一个强大的跨平台图形处理库,它允许开发人员在Java应用程序中进行复杂的图像操作,包括但不限于转换、编辑、合成图像以及处理大量格式的图像文件。ImageMagick是由C语言编写的,但...
java 图片处理工具类 java 图片处理工具类 java 图片处理工具类 java 图片处理工具类 java 图片处理工具类 java 图片处理工具类 java 图片处理工具类 java 图片处理工具类 java 图片处理工具类 java 图片处理工具类 ...
这是一个Java图片处理程序。 Java 开源代码,高手学习 java 图片处理源码
在Java编程语言中,处理...综上所述,这段代码展示了Java如何利用AWT库进行图片处理,包括添加图片和文字水印,以及处理透明度和定位。这些都是Java图形处理的基本技术,对于开发涉及图像编辑和处理的应用非常有用。
在Java编程领域,图片处理是一项常见的任务,尤其是在网站开发、移动应用或者数据分析中。这个"java 图片处理类"提供了一种便捷的方式,用于给图片添加水印以及压缩图片,这是开发过程中非常实用的功能。下面将详细...
Java图片处理类是Java编程语言中用于操作和处理图像文件的核心技术,主要涉及Java的AWT(Abstract Window Toolkit)和Swing库。在Java课程设计中,学生通常会被要求掌握这些概念并应用到实际项目中,例如创建一个...
java图片缩放 java缩略图 缩略图 java图片处理
java图片处理工具类JAR包 java-image-scalingjar
java图片处理 根据大小获取指定大小图片 以及图片尺寸处理 等等java图片处理 根据大小获取指定大小图片 以及图片尺寸处理 等等java图片处理 根据大小获取指定大小图片 以及图片尺寸处理 等等java图片处理 根据大小...
这里我们关注的是“rt java图片处理jar包”,这个标题暗示了一个专门用于处理图片的Java库,可能封装了一些方便开发者使用的API。描述中的“图片水印处理,java图片处理”进一步确认了这个库的主要功能之一是添加...
Java 图片处理解决方案:ImageMagick 快速入门教程 Java 图片处理解决方案中,ImageMagick 是一个免费的创建、编辑、合成图片的软件,可以实现图片切割、颜色替换、图片缩略图、图片水印等各种效果。ImageMagick 是...
java 图片处理 切图代码 实现自动缩放图片
图片添加水印图片、可设置水印图片旋转角度;图片添加水印文字(自动换行)、可设置水印文字的旋转角度;获取文本所占长度像素;图片截取;图片高质量缩放;图片png格式缩放;图片克隆副本;读取图片对象;图片输出 ...
Java 图片处理库Java Advanced Imaging (JAI) 是一个强大的工具,用于在Java环境中进行复杂的图像操作和处理。这个库提供了丰富的功能,包括但不限于图片的读取、写入、旋转、缩放、颜色空间转换以及各种滤镜应用。...
Java图片处理-生成火焰效果,public class FirePicApplet extends Applet implements Runnable{ private Image backImage,foreImage; //前景和背景Image对象 private Image image,fireImage; //Applet和绘制...
这是一个java生成随即图片验证码,java图片压缩,java图片水印 ,java图片裁剪 ,java图片旋转 ,java图片放大缩小等工具类,里面有测试方法,欢迎使用!