Added image utilities
This commit is contained in:
parent
8a529731b7
commit
bec29c4cd3
219
src/dorkbox/util/ImageUtil.java
Normal file
219
src/dorkbox/util/ImageUtil.java
Normal file
@ -0,0 +1,219 @@
|
||||
/*
|
||||
* Copyright 2016 dorkbox, llc
|
||||
*
|
||||
* 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 dorkbox.util;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Image;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.Iterator;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.imageio.ImageReader;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import javax.swing.ImageIcon;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public
|
||||
class ImageUtil {
|
||||
|
||||
/**
|
||||
* Resizes the image, as either a a FILE on disk, or as a RESOURCE name, and saves the new size as a file on disk. This new file will
|
||||
* replace any other file with the same name.
|
||||
*
|
||||
* @return the file string on disk that is the resized icon
|
||||
*/
|
||||
public static
|
||||
String resizeFileOrResource(final int sizeWidth, final String fileName) throws IOException {
|
||||
FileInputStream fileInputStream = new FileInputStream(fileName);
|
||||
|
||||
Dimension imageSize = getImageSize(fileInputStream);
|
||||
//noinspection NumericCastThatLosesPrecision
|
||||
if (sizeWidth == ((int) imageSize.getWidth())) {
|
||||
// we can reuse this file.
|
||||
return fileName;
|
||||
}
|
||||
|
||||
// have to resize the file (and return the new path)
|
||||
|
||||
String extension = FileUtil.getExtension(fileName);
|
||||
if (extension.isEmpty()) {
|
||||
extension = "png"; // made up
|
||||
}
|
||||
|
||||
// now have to resize this file.
|
||||
File newFile = new File(FileUtil.TEMP_DIR, "temp_resize." + extension).getAbsoluteFile();
|
||||
Image image;
|
||||
|
||||
// is file sitting on drive
|
||||
File iconTest = new File(fileName);
|
||||
if (iconTest.isFile() && iconTest.canRead()) {
|
||||
final String absolutePath = iconTest.getAbsolutePath();
|
||||
|
||||
// resize the image, keep aspect
|
||||
image = new ImageIcon(absolutePath).getImage().getScaledInstance(sizeWidth, -1, Image.SCALE_SMOOTH);
|
||||
image.flush();
|
||||
}
|
||||
else {
|
||||
// suck it out of a URL/Resource (with debugging if necessary)
|
||||
final URL systemResource = LocationResolver.getResource(fileName);
|
||||
|
||||
// resize the image, keep aspect
|
||||
image = new ImageIcon(systemResource).getImage().getScaledInstance(sizeWidth, -1, Image.SCALE_SMOOTH);
|
||||
image.flush();
|
||||
}
|
||||
|
||||
// have to do this twice, so that it will finish loading the image (weird callback stuff is required if we don't do this)
|
||||
image = new ImageIcon(image).getImage();
|
||||
image.flush();
|
||||
|
||||
// make whatever dirs we need to.
|
||||
boolean mkdirs = newFile.getParentFile()
|
||||
.mkdirs();
|
||||
|
||||
if (!mkdirs) {
|
||||
throw new IOException("Unable to create directories for " + newFile.getParentFile());
|
||||
}
|
||||
|
||||
// if it's already there, we have to delete it
|
||||
boolean delete = newFile.delete();
|
||||
if (!delete) {
|
||||
throw new IOException("Temporary file already in use, cannot delete it " + newFile);
|
||||
}
|
||||
|
||||
// now write out the new one
|
||||
BufferedImage bufferedImage = getBufferedImage(image);
|
||||
ImageIO.write(bufferedImage, extension, newFile);
|
||||
|
||||
return newFile.getAbsolutePath();
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("ResultOfMethodCallIgnored")
|
||||
public static
|
||||
File getTransparentImage(final int size, final File fileToUse) throws IOException {
|
||||
if (fileToUse.canRead() && fileToUse.isFile()) {
|
||||
return fileToUse;
|
||||
}
|
||||
|
||||
// make sure the directory exists
|
||||
fileToUse.getParentFile().mkdirs();
|
||||
|
||||
final BufferedImage image = getTransparentImageAsBufferedImage(size);
|
||||
ImageIO.write(image, "png", fileToUse);
|
||||
return fileToUse;
|
||||
}
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public static
|
||||
BufferedImage getTransparentImageAsBufferedImage(final int size) {
|
||||
final BufferedImage image = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);
|
||||
Graphics2D g2d = image.createGraphics();
|
||||
g2d.setColor(new Color(0, 0, 0, 0));
|
||||
g2d.fillRect(0, 0, size, size);
|
||||
g2d.dispose();
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the image as a Buffered Image
|
||||
*/
|
||||
public static
|
||||
BufferedImage getBufferedImage(Image image) {
|
||||
if (image instanceof BufferedImage) {
|
||||
return (BufferedImage) image;
|
||||
}
|
||||
|
||||
BufferedImage bimage = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_ARGB);
|
||||
|
||||
Graphics2D bGr = bimage.createGraphics();
|
||||
bGr.addRenderingHints(new RenderingHints(RenderingHints.KEY_RENDERING,
|
||||
RenderingHints.VALUE_RENDER_QUALITY));
|
||||
bGr.drawImage(image, 0, 0, null);
|
||||
bGr.dispose();
|
||||
|
||||
// Return the buffered image
|
||||
return bimage;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reads the image size information from the specified file, without loading the entire file.
|
||||
*
|
||||
* @param fileStream the input stream of the file
|
||||
*
|
||||
* @return the image size dimensions. IOException if it could not be read
|
||||
*/
|
||||
public static
|
||||
Dimension getImageSize(InputStream fileStream) throws IOException {
|
||||
ImageInputStream in = null;
|
||||
ImageReader reader = null;
|
||||
try {
|
||||
// This will ONLY work for File, InputStream, and RandomAccessFile
|
||||
in = ImageIO.createImageInputStream(fileStream);
|
||||
|
||||
final Iterator<ImageReader> readers = ImageIO.getImageReaders(in);
|
||||
if (readers.hasNext()) {
|
||||
reader = readers.next();
|
||||
reader.setInput(in);
|
||||
|
||||
return new Dimension(reader.getWidth(0), reader.getHeight(0));
|
||||
}
|
||||
} finally {
|
||||
// `ImageInputStream` is not a closeable in 1.6, so we do this manually.
|
||||
if (in != null) {
|
||||
try {
|
||||
in.close();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
if (reader != null) {
|
||||
reader.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
throw new IOException("Unable to read file inputStream for image size data.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Because of the way image loading works in Java, if one wants to IMMEDIATELY get a fully loaded image, one must resort to "hacks"
|
||||
* by loading the image twice.
|
||||
*
|
||||
* @param image the image you want load immediately
|
||||
*
|
||||
* @return a fully loaded image
|
||||
*/
|
||||
public static
|
||||
Image getImageImmediate(final Image image) {
|
||||
// have to do this twice, so that it will finish loading the image (weird callback stuff is required if we don't do this)
|
||||
image.flush();
|
||||
|
||||
final Image loadedImage = new ImageIcon(image).getImage();
|
||||
loadedImage.flush();
|
||||
|
||||
return loadedImage;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user