org.springframework.util.ImageUtils Maven / Gradle / Ivy
The newest version!
package org.springframework.util;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.DimensionCustom;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Paths;
import java.util.GregorianCalendar;
import javax.imageio.ImageIO;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import com.drew.imaging.ImageMetadataReader;
import com.drew.imaging.ImageProcessingException;
import com.drew.metadata.exif.ExifDirectoryBase;
import net.coobird.thumbnailator.Thumbnails;
import net.coobird.thumbnailator.Thumbnails.Builder;
import net.coobird.thumbnailator.filters.Canvas;
import net.coobird.thumbnailator.geometry.Positions;
public final class ImageUtils {
private static final Log logger = LogFactory.getLog(ImageUtils.class);
public static final String IMAGE = "image";
public static final String WIDTH = "width";
public static final String HEIGHT = "height";
public static final File CACHE_DIRECTORY = getCacheDirectory();
private static File getCacheDirectory() {
File cacheDirectory = Paths.get(SystemPropertyUtils.resolvePlaceholders("${user.home}"), Paths.get(SystemPropertyUtils.resolvePlaceholders("${java.io.tmpdir}")).toFile().getName()).toFile();
Assert.isTrue(cacheDirectory != null && (cacheDirectory.mkdirs() || cacheDirectory.isDirectory()), "Create CacheDirectory fail... " + cacheDirectory);
ImageIO.setCacheDirectory(cacheDirectory);
return cacheDirectory;
}
public static int getOrientation(Resource resource) {
Object o = getObject(resource, ExifDirectoryBase.TAG_ORIENTATION);
return o instanceof Integer ? (Integer) o : 0;
}
private static Object getObject(Resource resource, int tagType) {
try (InputStream inputStream = resource.getInputStream()) {
for (ExifDirectoryBase exifDirectoryBase : ImageMetadataReader.readMetadata(inputStream).getDirectoriesOfType(ExifDirectoryBase.class)) {
if (exifDirectoryBase.containsTag(ExifDirectoryBase.TAG_ORIENTATION)) {
return exifDirectoryBase.getObject(ExifDirectoryBase.TAG_ORIENTATION);
}
}
}
catch (IOException | ImageProcessingException e) {
if (logger.isTraceEnabled()) {
logger.trace("Read Metadata fail... " + tagType + " from " + resource, e);
}
else if (logger.isWarnEnabled()) {
logger.warn("Read Metadata fail... " + tagType + " from " + resource + " (" + e.getMessage() + ")");
}
}
return null;
}
/**
*
* new GregorianCalendar(1970, 01, 01).getTimeInMillis();
* new Date(0).getTime();
*
*/
public static String getFilename(Resource resource, Dimension dimension) {
Assert.notNull(resource, "'resource' must not be null");
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(resource.hashCode());
if (dimension != null) {
stringBuilder.append('_');
stringBuilder.append(dimension.hashCode());
}
String extension = StringUtils.getFilenameExtension(resource.getFilename());
if (extension != null) {
stringBuilder.append('.');
stringBuilder.append(extension);
}
return new String(stringBuilder);
}
public static Resource getResource(Resource resource, Dimension dimension) {
StringBuilder sb = new StringBuilder();
sb.append(resource.hashCode());
sb.append('_');
try {
sb.append(resource.lastModified());
}
catch (IOException e) {
sb.append(new GregorianCalendar(1970, 01, 01).getTimeInMillis());
// sb.append(new Date(0).getTime());
}
if (dimension != null) {
sb.append('_');
sb.append(dimension.hashCode());
}
String extention = StringUtils.getFilenameExtension(resource.getFilename());
if (StringUtils.hasText(extention)) {
sb.append('.');
sb.append(extention);
}
File file = Paths.get(CACHE_DIRECTORY.getPath(), new String(sb)).toFile();
if (file.exists()) {
Assert.isTrue(file.isFile(), "'file' must be file");
return new FileSystemResource(file);
}
try (InputStream inputStream = resource.getInputStream()) {
resource = new ByteArrayResource(StreamUtils.copyToByteArray(inputStream));
if (dimension == null) {
return resource;
}
boolean width = dimension.width > 0;
boolean height = dimension.height > 0;
BufferedImage image = Thumbnails.of(resource.getInputStream()).imageType(BufferedImage.TYPE_INT_ARGB).scale(1.0D).asBufferedImage();
if ((!width && !height) || (image.getWidth() < dimension.width && image.getHeight() < dimension.height)) {
return resource;
// Thumbnails.of(image).toFile(file);
// return new FileSystemResource(file);
}
Builder builder = Thumbnails.of(image);
if (width && height) {
builder = builder.size(dimension.width, dimension.height).crop(Positions.CENTER);
// builder = builder.addFilter(new Canvas(150, 150, Positions.CENTER,
// Color.blue));
}
else if (width) {
builder = builder.size(dimension.width, image.getHeight());
}
else if (height) {
builder = builder.size(image.getWidth(), dimension.height);
}
builder.toFile(file);
return new FileSystemResource(file);
}
catch (IOException e) {
throw new IllegalStateException(e);
}
}
public static Resource getResource(Resource resource, Dimension dimension, File file, boolean force) {
Assert.isTrue(file != null && file.getParentFile() != null && (file.getParentFile().mkdirs() || file.getParentFile().isDirectory()), "Create Directory fail... " + file);
Assert.isTrue(force || !file.exists(), "'file' already exists");
try (InputStream inputStream = resource.getInputStream()) {
if (dimension == null) {
try (OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(file))) {
StreamUtils.copy(inputStream, outputStream);
}
return new FileSystemResource(file);
}
BufferedImage image = Thumbnails.of(inputStream).imageType(BufferedImage.TYPE_INT_ARGB).scale(1.0D).asBufferedImage();
if ((dimension.width <= 0 && dimension.height <= 0) || (image.getWidth() < dimension.width && image.getHeight() < dimension.height)) {
Thumbnails.of(image).scale(1.0D).toFile(file);
return new FileSystemResource(file);
}
boolean width = dimension.width > 0;
boolean height = dimension.height > 0;
Builder builder = Thumbnails.of(image);
if (width && height) {
builder = builder.size(dimension.width, dimension.height);
builder = builder.crop(Positions.CENTER);
}
else if (width) {
builder = builder.size(dimension.width, image.getHeight());
}
else if (height) {
builder = builder.size(image.getWidth(), dimension.height);
}
else {
// TODO:check
// throw new UnsupportedOperationException();
}
builder.toFile(file);
return new FileSystemResource(file);
}
catch (IOException e) {
throw new IllegalStateException(e);
}
}
public static Resource getImage(Resource resource, Dimension dimension, File directory) {
Assert.isTrue(directory != null && (directory.mkdirs() || directory.isDirectory()), "Create Directory fail... " + directory);
File file = new File(directory, getFilename(resource, dimension));
if (file.exists()) {
return new FileSystemResource(file);
}
try (InputStream inputStream = resource.getInputStream()) {
BufferedImage image = Thumbnails.of(inputStream).imageType(BufferedImage.TYPE_INT_ARGB).scale(1.0D).asBufferedImage();
boolean width, height = false;
if (dimension == null || (!(width = dimension.width > 0) && !(height = dimension.height <= 0)) || (image.getWidth() < dimension.width && image.getHeight() < dimension.height)) {
Thumbnails.of(image).scale(1.0D).toFile(file);
}
else {
Builder builder = Thumbnails.of(image);
if (width && height) {
builder = builder.size(dimension.width, dimension.height);
if (dimension instanceof DimensionCustom && ((DimensionCustom) dimension).a != -1) {
builder = builder.addFilter(new Canvas(dimension.width, dimension.height, Positions.CENTER,
new Color(((DimensionCustom) dimension).r, ((DimensionCustom) dimension).g, ((DimensionCustom) dimension).b, ((DimensionCustom) dimension).a)));
}
else {
builder = builder.crop(Positions.CENTER);
}
}
else if (width) {
builder = builder.size(dimension.width, image.getHeight());
}
else if (height) {
builder = builder.size(image.getWidth(), dimension.height);
}
else {
throw new UnsupportedOperationException();
}
builder.toFile(file);
}
return new FileSystemResource(file);
}
catch (IOException e) {
throw new IllegalStateException(e);
}
}
public static Resource getResource(Resource resource, Dimension dimension, File file) {
return getResource(resource, dimension, file, true);
}
/**
* -Djava.awt.headless=true
*/
// public static AffineTransform getExifTransformation(Resource resource) {
// int orientation = getOrientation(resource);
// AffineTransform t = new AffineTransform();
// switch (orientation) {
// case 1:
// break;
// case 2: // Flip X
// t.scale(-1.0, 1.0);
// t.translate(-info.width, 0);
// break;
// case 3: // PI rotation
// t.translate(info.width, info.height);
// t.rotate(Math.PI);
// break;
// case 4: // Flip Y
// t.scale(1.0, -1.0);
// t.translate(0, -info.height);
// break;
// case 5: // - PI/2 and Flip X
// t.rotate(-Math.PI / 2);
// t.scale(-1.0, 1.0);
// break;
// case 6: // -PI/2 and -width
// t.translate(info.height, 0);
// t.rotate(Math.PI / 2);
// break;
// case 7: // PI/2 and Flip
// t.scale(-1.0, 1.0);
// t.translate(-info.height, 0);
// t.translate(0, info.width);
// t.rotate(3 * Math.PI / 2);
// break;
// case 8: // PI / 2
// t.translate(0, info.width);
// t.rotate(3 * Math.PI / 2);
// break;
// }
// return t;
// }
/**
* @see org.imgscalr.Scalr#OP_ANTIALIAS
* @see javax.imageio.IIOImage#IIOImage(java.awt.image.RenderedImage, java.util.List,
* javax.imageio.metadata.IIOMetadata)
* @see javax.swing.ImageIcon#ImageIcon(byte[])
*/
public static BufferedImage getBufferedImage(Resource resource) {
return getBufferedImage(resource, null);
// int orientation = getOrientation(resource);
// try (InputStream inputStream = resource.getInputStream()) {
// BufferedImage bufferedImage = ImageIO.read(inputStream);
// switch (orientation) {// orientation == null ? 0 : orientation
// case 2:
// bufferedImage = Scalr.rotate(bufferedImage, Rotation.FLIP_HORZ);// 좌우
// break;
// case 3:
// bufferedImage = Scalr.rotate(bufferedImage, Rotation.CW_180);
// break;
// case 4:
// bufferedImage = Scalr.rotate(bufferedImage, Rotation.FLIP_VERT);// 상하
// break;
// case 5:
// bufferedImage = Scalr.rotate(bufferedImage, Rotation.FLIP_HORZ);
// bufferedImage = Scalr.rotate(bufferedImage, Rotation.CW_90);
// break;
// case 6:
// bufferedImage = Scalr.rotate(bufferedImage, Rotation.CW_90);
// break;
// case 7:
// bufferedImage = Scalr.rotate(bufferedImage, Rotation.FLIP_HORZ);
// bufferedImage = Scalr.rotate(bufferedImage, Rotation.CW_270);
// break;
// case 8:
// bufferedImage = Scalr.rotate(bufferedImage, Rotation.CW_270);
// break;
// default:
// break;
// }
// return bufferedImage;
// }
// catch (IOException e) {
// throw new IllegalStateException(e.getMessage(), e);
// }
}
public static BufferedImage getBufferedImage(Resource resource, Dimension dimension) {
try (InputStream inputStream = resource.getInputStream()) {
BufferedImage image = Thumbnails.of(inputStream).imageType(BufferedImage.TYPE_INT_ARGB).scale(1.0D).asBufferedImage();
if (dimension == null || dimension.width <= 0 || dimension.height <= 0 || (image.getWidth() < dimension.width && image.getHeight() < dimension.height)) {
return image;
}
return Thumbnails.of(image).imageType(BufferedImage.TYPE_INT_ARGB).size(dimension.width, dimension.height).crop(Positions.CENTER).asBufferedImage();
}
catch (IOException e) {
throw new IllegalStateException(e.getMessage(), e);
}
}
public static void createThumbnail(Resource resource, Dimension dimension, File file) {
Assert.isTrue(file != null && file.getParentFile() != null && (file.getParentFile().mkdirs() || file.getParentFile().isDirectory()), "Create Directory fail... " + file);
Assert.notNull(dimension, "'dimension' must not be null");
// int orientation = getOrientation(resource);
try (InputStream inputStream = resource.getInputStream()) {
Builder builder = Thumbnails.of(inputStream).imageType(BufferedImage.TYPE_INT_ARGB);
// Builder builder =
// Thumbnails.of(inputStream).imageType(BufferedImage.TYPE_4BYTE_ABGR);
boolean width = dimension.width > 0;
boolean height = dimension.height > 0;
if (width) {
builder = builder.width(dimension.width);
}
if (height) {
builder = builder.height(dimension.height);
}
if (width && height) {
builder = builder.crop(Positions.CENTER);
}
builder.toFile(file);
}
catch (IOException e) {
throw new IllegalStateException(e.getMessage(), e);
}
}
public static BufferedImage transformImage(BufferedImage image, AffineTransform transform) throws Exception {
AffineTransformOp op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BICUBIC);
BufferedImage destinationImage = op.createCompatibleDestImage(image, (image.getType() == BufferedImage.TYPE_BYTE_GRAY) ? image.getColorModel() : null);
Graphics2D g = destinationImage.createGraphics();
g.setBackground(Color.WHITE);
g.clearRect(0, 0, destinationImage.getWidth(), destinationImage.getHeight());
destinationImage = op.filter(image, destinationImage);
return destinationImage;
}
/**
* @see net.coobird.thumbnailator.name.Rename#PREFIX_DOT_THUMBNAIL
*/
public static BufferedImage getBufferedImageTest(Resource resource, Dimension dimension) {
try (InputStream inputStream = resource.getInputStream()) {
BufferedImage image = Thumbnails.of(inputStream).scale(1.0D).asBufferedImage();
if (dimension == null || dimension.width <= 0 || dimension.height <= 0 || (image.getWidth() < dimension.width && image.getHeight() < dimension.height)) {
return image;
}
return Thumbnails.of(image).size(dimension.width, dimension.height).crop(Positions.CENTER).asBufferedImage();
}
catch (IOException e) {
throw new IllegalStateException(e.getMessage(), e);
}
}
}