X-Git-Url: http://git.nikiroo.be/?p=fanfix.git;a=blobdiff_plain;f=src%2Fbe%2Fnikiroo%2Futils%2FImageUtils.java;h=877c8fa8c26b6b8a1a585505cf70f4a37d3d4fc7;hp=9f1e06f36806d57c3876dc38b6400d4d4b371412;hb=HEAD;hpb=11f9e5f37c2570f0376a4c1898c6aea3a7f28fc7 diff --git a/src/be/nikiroo/utils/ImageUtils.java b/src/be/nikiroo/utils/ImageUtils.java index 9f1e06f..877c8fa 100644 --- a/src/be/nikiroo/utils/ImageUtils.java +++ b/src/be/nikiroo/utils/ImageUtils.java @@ -1,262 +1,92 @@ package be.nikiroo.utils; -import java.awt.Dimension; -import java.awt.Image; -import java.awt.geom.AffineTransform; -import java.awt.image.AffineTransformOp; -import java.awt.image.BufferedImage; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; -import javax.imageio.ImageIO; - -import be.nikiroo.utils.ImageText.Mode; +import be.nikiroo.utils.serial.SerialUtils; /** * This class offer some utilities based around images. * * @author niki */ -public class ImageUtils { - /** - * Convert the given {@link Image} object into a Base64 representation of - * the same {@link Image} object. - * - * @param image - * the {@link Image} object to convert - * - * @return the Base64 representation - * - * @throws IOException - * in case of IO error - */ - static public String toBase64(BufferedImage image) throws IOException { - return toBase64(image, null); - } +public abstract class ImageUtils { + private static ImageUtils instance = newObject(); /** - * Convert the given {@link Image} object into a Base64 representation of - * the same {@link Image}. object. - * - * @param image - * the {@link Image} object to convert - * @param format - * the image format to use to serialise it (default is PNG) + * Get a (unique) instance of an {@link ImageUtils} compatible with your + * system. * - * @return the Base64 representation - * - * @throws IOException - * in case of IO error + * @return an {@link ImageUtils} */ - static public String toBase64(BufferedImage image, String format) - throws IOException { - if (format == null) { - format = "png"; - } - - String imageString = null; - ByteArrayOutputStream out = new ByteArrayOutputStream(); - - ImageIO.write(image, format, out); - byte[] imageBytes = out.toByteArray(); - - imageString = new String(Base64.encodeBytes(imageBytes)); - - out.close(); - - return imageString; + public static ImageUtils getInstance() { + return instance; } /** - * Convert the given image into a Base64 representation of the same - * {@link File}. + * Save the given resource as an image on disk using the given image format + * for content, or with "png" format if it fails. * - * @param in - * the image to convert - * - * @return the Base64 representation + * @param img + * the resource + * @param target + * the target file + * @param format + * the file format ("png", "jpeg", "bmp"...) * * @throws IOException - * in case of IO error + * in case of I/O error */ - static public String toBase64(InputStream in) throws IOException { - String fileString = null; - ByteArrayOutputStream out = new ByteArrayOutputStream(); - - byte[] buf = new byte[8192]; - - int c = 0; - while ((c = in.read(buf, 0, buf.length)) > 0) { - out.write(buf, 0, c); - } - out.flush(); - in.close(); - - fileString = new String(Base64.encodeBytes(out.toByteArray())); - out.close(); - - return fileString; - } + public abstract void saveAsImage(Image img, File target, String format) + throws IOException; /** - * Convert the given Base64 representation of an image into an {@link Image} - * object. + * Scale a dimension. * - * @param b64data - * the {@link Image} in Base64 format * - * @return the {@link Image} object + * @param imageWidth + * the actual image width + * @param imageHeight + * the actual image height + * @param areaWidth + * the base width of the target dimension for snap sizes + * @param areaHeight + * the base height of the target dimension for snap sizes + * @param zoom + * the zoom factor (ignored on snap mode) + * @param snapMode + * NULL for no snap mode, TRUE to snap to width and FALSE for + * snap to height) * - * @throws IOException - * in case of IO error + * @return the scaled size, width is [0] and height is [1] (minimum is 1x1) */ - static public BufferedImage fromBase64(String b64data) throws IOException { - ByteArrayInputStream in = new ByteArrayInputStream( - Base64.decode(b64data)); - return fromStream(in); - } - - /** - * Convert the given {@link InputStream} (which should allow calls to - * {@link InputStream#reset()} for better perfs) into an {@link Image} - * object, respecting the EXIF transformations if any. - * - * @param in - * the 'resetable' {@link InputStream} - * - * @return the {@link Image} object - * - * @throws IOException - * in case of IO error - */ - static public BufferedImage fromStream(InputStream in) throws IOException { - MarkableFileInputStream tmpIn = null; - File tmp = null; - - boolean repack = !in.markSupported(); - if (!repack) { - try { - in.reset(); - } catch (IOException e) { - repack = true; - } - } - - if (repack) { - tmp = File.createTempFile(".tmp-image", ".tmp"); - tmp.deleteOnExit(); - IOUtils.write(in, tmp); - tmpIn = new MarkableFileInputStream(new FileInputStream(tmp)); - } - - int orientation; - try { - orientation = getExifTransorm(in); - } catch (Exception e) { - // no EXIF transform, ok - orientation = -1; - } - - in.reset(); - BufferedImage image = ImageIO.read(in); - - if (image == null) { - if (tmp != null) { - tmp.delete(); - tmpIn.close(); - } - throw new IOException("Failed to convert input to image"); - } - - // Note: this code has been found on Internet; - // thank you anonymous coder. - int width = image.getWidth(); - int height = image.getHeight(); - AffineTransform affineTransform = new AffineTransform(); - - switch (orientation) { - case 1: - affineTransform = null; - break; - case 2: // Flip X - affineTransform.scale(-1.0, 1.0); - affineTransform.translate(-width, 0); - break; - case 3: // PI rotation - affineTransform.translate(width, height); - affineTransform.rotate(Math.PI); - break; - case 4: // Flip Y - affineTransform.scale(1.0, -1.0); - affineTransform.translate(0, -height); - break; - case 5: // - PI/2 and Flip X - affineTransform.rotate(-Math.PI / 2); - affineTransform.scale(-1.0, 1.0); - break; - case 6: // -PI/2 and -width - affineTransform.translate(height, 0); - affineTransform.rotate(Math.PI / 2); - break; - case 7: // PI/2 and Flip - affineTransform.scale(-1.0, 1.0); - affineTransform.translate(-height, 0); - affineTransform.translate(0, width); - affineTransform.rotate(3 * Math.PI / 2); - break; - case 8: // PI / 2 - affineTransform.translate(0, width); - affineTransform.rotate(3 * Math.PI / 2); - break; - default: - affineTransform = null; - break; - } - - if (affineTransform != null) { - AffineTransformOp affineTransformOp = new AffineTransformOp( - affineTransform, AffineTransformOp.TYPE_BILINEAR); - - BufferedImage transformedImage = new BufferedImage(width, height, - image.getType()); - transformedImage = affineTransformOp - .filter(image, transformedImage); - - image = transformedImage; - } - // + protected static Integer[] scaleSize(int imageWidth, int imageHeight, + int areaWidth, int areaHeight, double zoom, Boolean snapMode) { + int width; + int height; + if (snapMode == null) { + width = (int) Math.round(imageWidth * zoom); + height = (int) Math.round(imageHeight * zoom); + } else if (snapMode) { + width = areaWidth; + height = (int) Math + .round((((double) areaWidth) / imageWidth) * imageHeight); + } else { + height = areaHeight; + width = (int) Math + .round((((double) areaHeight) / imageHeight) * imageWidth); - if (tmp != null) { - tmp.delete(); - tmpIn.close(); } - return image; - } + if (width < 1) + width = 1; + if (height < 1) + height = 1; - /** - * A shorthand method to create an {@link ImageText} and return its output. - * - * @param image - * the source {@link Image} - * @param size - * the final text size to target - * @param mode - * the mode of conversion - * @param invert - * TRUE to invert colours rendering - * - * @return the text image - */ - static public String toAscii(Image image, Dimension size, Mode mode, - boolean invert) { - return new ImageText(image, size, mode, invert).toString(); + return new Integer[] { width, height }; } - + /** * Return the EXIF transformation flag of this image if any. * @@ -272,7 +102,7 @@ public class ImageUtils { * @throws IOException * in case of IO error */ - static private int getExifTransorm(InputStream in) throws IOException { + protected static int getExifTransorm(InputStream in) throws IOException { int[] exif_data = new int[100]; int set_flag = 0; int is_motorola = 0; @@ -405,4 +235,32 @@ public class ImageUtils { return set_flag; } + + /** + * Check that the class can operate (for instance, that all the required + * libraries or frameworks are present). + * + * @return TRUE if it works + */ + abstract protected boolean check(); + + /** + * Create a new {@link ImageUtils}. + * + * @return the {@link ImageUtils} + */ + private static ImageUtils newObject() { + for (String clazz : new String[] { "be.nikiroo.utils.ui.ImageUtilsAwt", + "be.nikiroo.utils.android.ImageUtilsAndroid" }) { + try { + ImageUtils obj = (ImageUtils) SerialUtils.createObject(clazz); + if (obj.check()) { + return obj; + } + } catch (Throwable e) { + } + } + + return null; + } }