Java tutorial
/** * Copyright (C) 2000 - 2013 Silverpeas * * This program is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or (at your option) any later version. * * As a special exception to the terms and conditions of version 3.0 of the GPL, you may * redistribute this Program in connection with Free/Libre Open Source Software ("FLOSS") * applications as described in Silverpeas's FLOSS exception. You should have recieved a copy of the * text describing the FLOSS exception, and it is also available here: * "http://www.silverpeas.org/docs/core/legal/floss_exception.html" * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with this program. * If not, see <http://www.gnu.org/licenses/>. */ package com.silverpeas.gallery; import com.silverpeas.gallery.image.DrewImageMetadataExtractor; import com.silverpeas.gallery.image.ImageMetadataException; import com.silverpeas.gallery.image.ImageMetadataExtractor; import com.silverpeas.gallery.model.MetaData; import com.silverpeas.gallery.model.PhotoDetail; import com.silverpeas.gallery.model.PhotoPK; import com.silverpeas.gallery.processing.ImageResizer; import com.silverpeas.gallery.processing.ImageUtility; import com.silverpeas.gallery.processing.Size; import com.silverpeas.gallery.processing.Watermarker; import com.silverpeas.util.FileUtil; import com.silverpeas.util.StringUtil; import com.silverpeas.util.i18n.I18NHelper; import com.stratelia.silverpeas.silvertrace.SilverTrace; import com.stratelia.webactiv.util.FileRepositoryManager; import com.stratelia.webactiv.util.ResourceLocator; import java.awt.*; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.util.List; import javax.imageio.ImageIO; import org.apache.commons.fileupload.FileItem; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.silverpeas.process.io.file.FileBasePath; import org.silverpeas.process.io.file.FileHandler; import org.silverpeas.process.io.file.HandledFile; import org.silverpeas.util.ImageLoader; public class ImageHelper { private final static FileBasePath BASE_PATH = FileBasePath.UPLOAD_PATH; final static ResourceLocator gallerySettings = new ResourceLocator( "org.silverpeas.gallery.settings.gallerySettings", ""); final static ResourceLocator settings = new ResourceLocator("org.silverpeas.gallery.settings.metadataSettings", ""); static final String thumbnailSuffix_small = "_66x50.jpg"; static final String thumbnailSuffix_medium = "_133x100.jpg"; static final String thumbnailSuffix_large = "_266x150.jpg"; static final String previewSuffix = "_preview.jpg"; static final String thumbnailSuffix_Xlarge = "_600x400.jpg"; static final String watermarkSuffix = "_watermark.jpg"; /** * Open an output stream of an image according to given details of a photo. * * @param photo * @param isOriginalRequired * @return * @throws IOException */ public static InputStream openInputStream(final PhotoDetail photo, final boolean isOriginalRequired) { final String photoId = photo.getPhotoPK().getId(); final String instanceId = photo.getPhotoPK().getInstanceId(); if (StringUtil.isDefined(photoId) && StringUtil.isDefined(instanceId)) { final String subDirectory = gallerySettings.getString("imagesSubDirectory"); String fileName = photoId + previewSuffix; if (isOriginalRequired) { fileName = photo.getImageName(); } try { return FileUtils.openInputStream(FileUtils.getFile(new File(BASE_PATH.getPath()), instanceId, subDirectory + photoId, fileName)); } catch (IOException e) { SilverTrace.error("gallery", "ImageHelper.getBytes", "gallery.ERR_CANT_GET_IMAGE_BYTES", "image = " + photo.getTitle() + " (#" + photo.getId() + ")"); return null; } } return null; } /** * @param fileHandler * @param photo * @param image * @param watermark * @param watermarkHD * @param watermarkOther * @throws Exception */ public static void processImage(final FileHandler fileHandler, final PhotoDetail photo, final FileItem image, final boolean watermark, final String watermarkHD, final String watermarkOther) throws Exception { final String photoId = photo.getPhotoPK().getId(); final String instanceId = photo.getPhotoPK().getInstanceId(); if (image != null) { String name = image.getName(); if (name != null) { name = FileUtil.getFilename(name); if (ImageType.isImage(name)) { final String subDirectory = gallerySettings.getString("imagesSubDirectory"); final HandledFile handledImageFile = fileHandler.getHandledFile(BASE_PATH, instanceId, subDirectory + photoId, name); handledImageFile.writeByteArrayToFile(image.get()); photo.setImageName(name); photo.setImageMimeType(image.getContentType()); photo.setImageSize(image.getSize()); createImage(name, handledImageFile, photo, watermark, watermarkHD, watermarkOther); } } } } /** * In case of drag And Drop upload. * * @param fileHandler * @param photo * @param image * @param watermark * @param watermarkHD * @param watermarkOther * @throws Exception */ public static void processImage(final FileHandler fileHandler, final PhotoDetail photo, final File image, final boolean watermark, final String watermarkHD, final String watermarkOther) throws Exception { final String photoId = photo.getPhotoPK().getId(); final String instanceId = photo.getPhotoPK().getInstanceId(); if (image != null) { String name = image.getName(); if (name != null) { name = name.substring(name.lastIndexOf(File.separator) + 1, name.length()); if (ImageType.isImage(name)) { String subDirectory = gallerySettings.getString("imagesSubDirectory"); final HandledFile handledImageFile = fileHandler.getHandledFile(BASE_PATH, instanceId, subDirectory + photoId, name); fileHandler.copyFile(image, handledImageFile); photo.setImageName(name); photo.setImageMimeType(FileUtil.getMimeType(name)); photo.setImageSize(image.length()); createImage(name, handledImageFile, photo, watermark, watermarkHD, watermarkOther); } } } } private static void createImage(final String name, final HandledFile handledImageFile, final PhotoDetail photo, final boolean watermark, final String watermarkHD, final String watermarkOther) throws Exception { String percent = gallerySettings.getString("percentSizeWatermark"); if (!StringUtil.isDefined(percent)) { percent = "1"; } int percentSize = Integer.parseInt(percent); if (percentSize <= 0) { percentSize = 1; } if (ImageType.isReadable(name)) { // Getting the size of the image final String type = FileRepositoryManager.getFileExtension(name); final BufferedImage image = ImageLoader.loadImage(handledImageFile.getFile()); getDimension(image, photo); // Computing watermark data final String nameForWatermark = computeWatermarkText(watermarkHD, watermark, type, handledImageFile, photo, percentSize, watermarkOther); // Creating preview and thumbnails try { createThumbnails(photo, handledImageFile, image, watermark, nameForWatermark); } catch (final Exception e) { SilverTrace.error("gallery", "ImageHelper.createImage", "gallery.ERR_CANT_CREATE_THUMBNAILS", "image = " + photo.getTitle() + " (#" + photo.getId() + ")"); } } } public static void setMetaData(final FileHandler fileHandler, final PhotoDetail photo) throws IOException, ImageMetadataException { setMetaData(fileHandler, photo, I18NHelper.defaultLanguage); } public static void setMetaData(final FileHandler fileHandler, final PhotoDetail photo, final String lang) throws ImageMetadataException, IOException { final String photoId = photo.getPhotoPK().getId(); final String name = photo.getImageName(); final String mimeType = photo.getImageMimeType(); if ("image/jpeg".equals(mimeType) || "image/pjpeg".equals(mimeType)) { final HandledFile handledFile = fileHandler.getHandledFile(BASE_PATH, photo.getInstanceId(), settings.getString("imagesSubDirectory") + photoId, name); if (handledFile.exists()) { try { final ImageMetadataExtractor extractor = new DrewImageMetadataExtractor(photo.getInstanceId()); for (final MetaData meta : extractor.extractImageExifMetaData(handledFile.getFile(), lang)) { photo.addMetaData(meta); } for (final MetaData meta : extractor.extractImageIptcMetaData(handledFile.getFile(), lang)) { photo.addMetaData(meta); } } catch (UnsupportedEncodingException e) { SilverTrace.error("gallery", "ImageHelper.computeWatermarkText", "root.MSG_BAD_ENCODING", "Bad metadata encoding in image " + photo.getTitle() + ": " + e.getMessage()); } } } } private static void getDimension(final BufferedImage image, final PhotoDetail photo) { if (image == null) { photo.setSizeL(0); photo.setSizeH(0); } else { photo.setSizeL(image.getWidth()); photo.setSizeH(image.getHeight()); } } private static void createThumbnails(final PhotoDetail photo, final HandledFile originalHandedImageFile, final BufferedImage originalImage, final boolean watermark, final String nameWatermark) throws Exception { // File name final String photoId = photo.getId(); // Preview image resizing only if the original image is larger than the preview int originalImageWidth = photo.getSizeL(); if (photo.getSizeH() > photo.getSizeL()) { originalImageWidth = photo.getSizeH(); } // Processing order : // XLarge (preview without watermark) // Preview // Large // Medium // Small final int[] imageSize = new int[] { 600, 600, 266, 133, 66 }; final boolean[] isWatermark = new boolean[] { false, watermark, watermark, watermark, watermark }; final int[] imageWatermarkSize = new int[] { 0, Integer.parseInt(gallerySettings.getString("sizeWatermark600x400")), Integer.parseInt(gallerySettings.getString("sizeWatermark266x150")), Integer.parseInt(gallerySettings.getString("sizeWatermark133x100")), Integer.parseInt(gallerySettings.getString("sizeWatermark66x50")) }; final String[] imageSuffixName = new String[] { thumbnailSuffix_Xlarge, previewSuffix, thumbnailSuffix_large, thumbnailSuffix_medium, thumbnailSuffix_small }; HandledFile currentThumblail; BufferedImage previewImage = null; for (int i = 0; i < imageSize.length; i++) { // Current thumbnail currentThumblail = originalHandedImageFile.getParentHandledFile() .getHandledFile(photoId + imageSuffixName[i]); // Thumbnail creation redimPhoto((previewImage != null ? previewImage : originalImage), currentThumblail, (originalImageWidth > imageSize[i] ? imageSize[i] : originalImageWidth), isWatermark[i], nameWatermark, imageWatermarkSize[i]); // The first thumbnail that has to be created must be the larger one and without watermark. // This first thumbnail is cached and reused for the following thumbnail creation. if (previewImage == null) { previewImage = ImageLoader.loadImage(currentThumblail.getFile()); } } } public static Size getWidthAndHeight(final String instanceId, final String subDir, final String imageName, final int baseWidth) throws IOException { return ImageUtility.getWidthAndHeight(instanceId, subDir, imageName, baseWidth); } public static Size getWidthAndHeight(final BufferedImage image, final int widthParam) { return ImageUtility.getWidthAndHeight(image, widthParam); } /** * Return the written file * * @param image * @param outputFile * @param widthParam * @param watermark * @param nameWatermark * @param sizeWatermark * @throws Exception */ private static void redimPhoto(final BufferedImage image, final HandledFile outputFile, final int widthParam, final boolean watermark, final String nameWatermark, final int sizeWatermark) throws Exception { OutputStream outputStream = null; try { outputStream = outputFile.openOutputStream(); final ImageResizer resizer = new ImageResizer(image, widthParam); if (watermark) { resizer.resizeImageWithWatermark(outputStream, nameWatermark, sizeWatermark); } else { resizer.resizeImage(outputStream); } } finally { if (outputStream != null) { IOUtils.closeQuietly(outputStream); } } } private static void createWatermark(final OutputStream watermarkedTargetStream, final String watermarkLabel, final BufferedImage image, final int percentSizeWatermark) throws IOException { final int imageWidth = image.getWidth(); final int imageHeight = image.getHeight(); // cration du buffer a la mme taille final BufferedImage outputBuf = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_RGB); final double max = Math.max(imageWidth, imageHeight); // recherche de la taille du watermark en fonction de la taille de la photo int size = 8; if (max < 600) { size = 8; } if (max >= 600 && max < 750) { size = 10; } if (max >= 750 && max < 1000) { size = 12; } if (max >= 1000 && max < 1250) { size = 14; } if (max >= 1250 && max < 1500) { size = 16; } if (max >= 1500 && max < 1750) { size = 18; } if (max >= 1750 && max < 2000) { size = 20; } if (max >= 2000 && max < 2250) { size = 22; } if (max >= 2250 && max < 2500) { size = 24; } if (max >= 2500 && max < 2750) { size = 26; } if (max >= 2750 && max < 3000) { size = 28; } if (max >= 3000) { size = (int) Math.rint(max * percentSizeWatermark / 100); } final Watermarker watermarker = new Watermarker(imageWidth, imageHeight); watermarker.addWatermark(image, outputBuf, new Font("Arial", Font.BOLD, size), watermarkLabel, size); ImageIO.write(outputBuf, "JPEG", watermarkedTargetStream); } public static void pasteImage(final FileHandler fileHandler, final PhotoPK fromPK, final PhotoDetail image, final boolean cut) { final PhotoPK toPK = image.getPhotoPK(); final String subDirectory = gallerySettings.getString("imagesSubDirectory"); final HandledFile fromDir = fileHandler.getHandledFile(BASE_PATH, fromPK.getInstanceId(), subDirectory + fromPK.getId()); final HandledFile toDir = fileHandler.getHandledFile(BASE_PATH, toPK.getInstanceId(), subDirectory + toPK.getId()); // copier et renommer chaque image prsente dans le rpertoire d'origine if (fromDir.exists()) { // copy thumbnails & watermark (only if it does exist) for (final String thumbnailSuffix : new String[] { thumbnailSuffix_large, thumbnailSuffix_medium, thumbnailSuffix_small, previewSuffix, thumbnailSuffix_Xlarge, watermarkSuffix }) { pasteFile(fromDir.getHandledFile(fromPK.getId() + thumbnailSuffix), toDir.getHandledFile(toPK.getId() + thumbnailSuffix), cut); } // copy original image pasteFile(fromDir.getHandledFile(image.getImageName()), toDir.getHandledFile(image.getImageName()), cut); } } private static void pasteFile(final HandledFile fromFile, final HandledFile toFile, final boolean cut) { if (fromFile.exists()) { try { if (cut) { fromFile.moveFile(toFile); } else { fromFile.copyFile(toFile); } } catch (final Exception e) { SilverTrace.error("gallery", "ImageHelper.pasteFile", "root.MSG_GEN_PARAM_VALUE", "Unable to copy file : fromImage = " + fromFile.getFile().getPath() + ", toImage = " + toFile.getFile().getPath(), e); } } } private static String computeWatermarkText(final String watermarkHD, final boolean watermark, final String type, final HandledFile image, final PhotoDetail photo, final int percentSize, final String watermarkOther) throws Exception { String nameAuthor = ""; String nameForWatermark = ""; if (ImageType.isIPTCCompliant(type) && watermark) { final ImageMetadataExtractor extractor = new DrewImageMetadataExtractor(photo.getInstanceId()); final List<MetaData> iptcMetadata; try { iptcMetadata = extractor.extractImageIptcMetaData(image.getFile()); final BufferedImage bufferedImage = ImageLoader.loadImage(image.getFile()); if (StringUtil.isDefined(watermarkHD)) { // cration d'un duplicata de l'image originale avec intgration du // watermark final String value = getWatermarkValue(watermarkHD, iptcMetadata); if (value != null) { nameAuthor = value; } if (!nameAuthor.isEmpty()) { OutputStream watermarkStream = null; try { watermarkStream = image.getParentHandledFile() .getHandledFile(photo.getId() + "_watermark.jpg").openOutputStream(); createWatermark(watermarkStream, nameAuthor, bufferedImage, percentSize); } finally { IOUtils.closeQuietly(watermarkStream); } } } if (StringUtil.isDefined(watermarkOther)) { final String value = getWatermarkValue(watermarkOther, iptcMetadata); if (value != null) { nameAuthor = value; } if (!nameAuthor.isEmpty()) { nameForWatermark = nameAuthor; } } } catch (UnsupportedEncodingException e) { SilverTrace.error("gallery", "ImageHelper.computeWatermarkText", "root.MSG_BAD_ENCODING", "Bad metadata encoding in image " + image.getFile().getPath() + ": " + e.getMessage()); } } return nameForWatermark; } private static String getWatermarkValue(final String property, final List<MetaData> iptcMetadata) { String value = null; for (final MetaData metadata : iptcMetadata) { if (property.equalsIgnoreCase(metadata.getProperty())) { value = metadata.getValue(); } } return value; } private ImageHelper() { } }