/* * Copyright (c) www.bugull.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.tooan.ynpay.third.mongodb.fs; import com.mongodb.BasicDBObject; import com.mongodb.DBObject; import com.mongodb.gridfs.GridFSDBFile; import com.sun.image.codec.jpeg.ImageFormatException; import com.sun.image.codec.jpeg.JPEGCodec; import com.sun.image.codec.jpeg.JPEGEncodeParam; import com.sun.image.codec.jpeg.JPEGImageEncoder; import net.tooan.ynpay.third.jfinal.log.Logger; import net.tooan.ynpay.third.mongodb.mapper.StreamUtil; import net.tooan.ynpay.third.mongodb.mapper.StringUtil; import javax.imageio.ImageIO; import java.awt.*; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; /** * Convenient class for uploading an image file to GridFS. * <p/> * <p>Besides uploading, ImageUploader can watermark and compress an image.</p> * * @author Frank Wen(xbwen@hotmail.com) */ public class ImageUploader extends Uploader { private final static Logger logger = Logger.getLogger(ImageUploader.class); public final static String DIMENSION = "dimension"; public ImageUploader(File file, String originalName) { super(file, originalName); } public ImageUploader(File file, String originalName, boolean rename) { super(file, originalName, rename); } public ImageUploader(InputStream input, String originalName) { super(input, originalName); } public ImageUploader(InputStream input, String originalName, boolean rename) { super(input, originalName, rename); } public ImageUploader(byte[] data, String originalName) { super(data, originalName); } public ImageUploader(byte[] data, String originalName, boolean rename) { super(data, originalName, rename); } /** * Save the image with a watermark on it. * * @param watermark */ public void save(Watermark watermark) { processFilename(); if (!StringUtil.isEmpty(watermark.getText())) { pressText(watermark); } else if (!StringUtil.isEmpty(watermark.getImagePath())) { pressImage(watermark); } else { saveInputStream(); } } private void pressText(Watermark watermark) { BufferedImage originalImage = openImage(input); int originalWidth = originalImage.getWidth(null); int originalHeight = originalImage.getHeight(null); BufferedImage newImage = new BufferedImage(originalWidth, originalHeight, BufferedImage.TYPE_INT_RGB); Graphics2D g = newImage.createGraphics(); g.drawImage(originalImage, 0, 0, originalWidth, originalHeight, null); g.setColor(watermark.getColor()); g.setFont(new Font(watermark.getFontName(), watermark.getFontStyle(), watermark.getFontSize())); g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, watermark.getAlpha())); String text = watermark.getText(); int len = text.length(); int fontSize = watermark.getFontSize(); switch (watermark.getAlign()) { case Watermark.BOTTOM_RIGHT: g.drawString(text, originalWidth - (len * fontSize) - watermark.getRight(), originalHeight - fontSize - watermark.getBottom()); break; case Watermark.CENTER: g.drawString(text, (originalWidth - (len * fontSize)) / 2, (originalHeight - fontSize) / 2); break; default: break; } g.dispose(); saveImage(newImage); } private void pressImage(Watermark watermark) { BufferedImage originalImage = openImage(input); BufferedImage watermarkImage = openImage(new File(watermark.getImagePath())); int originalWidth = originalImage.getWidth(null); int originalHeight = originalImage.getHeight(null); int watermarkWidth = watermarkImage.getWidth(null); int watermarkHeight = watermarkImage.getHeight(null); if (originalWidth < watermarkWidth || originalHeight < watermarkHeight) { saveInputStream(); return; } BufferedImage newImage = new BufferedImage(originalWidth, originalHeight, BufferedImage.TYPE_INT_RGB); Graphics2D g = newImage.createGraphics(); g.drawImage(originalImage, 0, 0, originalWidth, originalHeight, null); g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, watermark.getAlpha())); //position of the watermark switch (watermark.getAlign()) { case Watermark.BOTTOM_RIGHT: g.drawImage(watermarkImage, originalWidth - watermarkWidth - watermark.getRight(), originalHeight - watermarkHeight - watermark.getBottom(), watermarkWidth, watermarkHeight, null); break; case Watermark.CENTER: g.drawImage(watermarkImage, (originalWidth - watermarkWidth) / 2, (originalHeight - watermarkHeight) / 2, watermarkWidth, watermarkHeight, null); break; default: break; } g.dispose(); saveImage(newImage); } public void compress(String dimension, int maxWidth, int maxHeight) { setAttribute(DIMENSION, dimension); BufferedImage srcImage = openImage(getOriginalInputStream()); int srcWidth = srcImage.getWidth(null); int srcHeight = srcImage.getHeight(null); if (srcWidth <= maxWidth && srcHeight <= maxHeight) { saveImage(srcImage); return; } double ratio = Math.min((double) maxWidth / srcWidth, (double) maxHeight / srcHeight); int targetWidth = (int) (srcWidth * ratio); int targetHeight = (int) (srcHeight * ratio); BufferedImage targetImage = new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_INT_RGB); Image img = srcImage.getScaledInstance(targetWidth, targetHeight, Image.SCALE_SMOOTH); Graphics g = targetImage.getGraphics(); g.drawImage(img, 0, 0, targetWidth, targetHeight, null); g.dispose(); saveImage(targetImage); } private InputStream getOriginalInputStream() { DBObject query = new BasicDBObject(BuguFS.FILENAME, filename); query.put(DIMENSION, null); BuguFS fs = new BuguFS(bucketName, chunkSize); GridFSDBFile f = fs.findOne(query); return f.getInputStream(); } private BufferedImage openImage(File f) { BufferedImage bi = null; try { bi = ImageIO.read(f); } catch (IOException ex) { logger.error("Can not read the image file", ex); } return bi; } private BufferedImage openImage(InputStream is) { BufferedImage bi = null; try { bi = ImageIO.read(is); } catch (IOException ex) { logger.error("Can not read the InputStream", ex); } finally { StreamUtil.safeClose(is); } return bi; } private void saveImage(BufferedImage bi) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(baos); JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(bi); param.setQuality(1.0f, true); try { encoder.encode(bi, param); } catch (ImageFormatException ex) { logger.error("Can not encode the JPEGImageEncoder", ex); } catch (IOException ex) { logger.error("Can not encode the JPEGImageEncoder", ex); } BuguFS fs = new BuguFS(bucketName, chunkSize); fs.save(baos.toByteArray(), filename, params); StreamUtil.safeClose(baos); } /** * Get the image's width and height. * * @return element 0 for width, element 1 for height */ public int[] getSize() { int[] size = new int[2]; BufferedImage image = openImage(getOriginalInputStream()); size[0] = image.getWidth(null); size[1] = image.getHeight(null); return size; } }