# nikiroo-utils
+## Version 4.0.0
+
+- Deplace all dependencies on java.awt into its own package (ui)
+
## Version 3.1.6
- Fix Serialiser issue with custom objects and String in a custom object
PREFIX=/usr/local
PROGS="java javac jar"
+UI=be/nikiroo/utils/ui/test/TestUI
+JUI="-C bin/ be/nikiroo/utils/ui"
+ANDOIRD=
+JANDROID=
+
valid=true
while [ "$*" != "" ]; do
- key=`echo "$1" | cut -c1-9`
- val=`echo "$1" | cut -c10-`
+ key=`echo "$1" | cut -f1 -d=`
+ val=`echo "$1" | cut -f2 -d=`
case "$key" in
- --prefix=)
+ --help) # This help message
+ echo The following arguments can be used:
+ cat "$0" | grep '^\s*--' | grep '#' | while read ln; do
+ cmd=`echo "$ln" | cut -f1 -d')'`
+ msg=`echo "$ln" | cut -f2 -d'#'`
+ echo " $cmd$msg"
+ done
+ ;;
+ --prefix) #=PATH Change the prefix to the given path
PREFIX="$val"
;;
+ --ui) #=no Disable UI (Swing/AWT) support
+ [ "$val" = no -o "$val" = false ] && UI= && JUI=
+ if [ "$val" = yes -o "$val" = true ]; then
+ UI=be/nikiroo/utils/ui/test/TestUI
+ JUI="-C bin/ be/nikiroo/utils/ui"
+ fi
+ ;;
+ --android) #=yes Enable Android UI support
+ [ "$val" = no -o "$val" = false ] && ANDROID= && JANDROID=
+ if [ "$val" = yes -o "$val" = true ]; then
+ ANDROID=be/nikiroo/utils/android/test/TestAndroid
+ JANDROID="-C bin/ be/nikiroo/utils/android"
+ fi
+ ;;
*)
echo "Unsupported parameter: '$1'" >&2
valid=false
echo "MAIN = be/nikiroo/utils/test/Test" > Makefile
-echo "MORE = be/nikiroo/utils/MarkableFileInputStream be/nikiroo/utils/ui/UIUtils be/nikiroo/utils/ui/WrapLayout be/nikiroo/utils/ui/ProgressBar be/nikiroo/utils/Downloader be/nikiroo/utils/Cache" >> Makefile
+echo "MORE = $UI $ANDROID" >> Makefile
echo "TEST = be/nikiroo/utils/test/Test" >> Makefile
echo "TEST_PARAMS = $cols $ok $ko" >> Makefile
echo "NAME = nikiroo-utils" >> Makefile
echo "PREFIX = $PREFIX" >> Makefile
-echo "JAR_FLAGS += -C bin/ be -C bin/ org -C bin/ VERSION" >> Makefile
+echo "JAR_FLAGS += -C bin/ be $JUI $JANDROID -C bin/ VERSION" >> Makefile
echo "SJAR_FLAGS += -C src/ org -C src/ be" >> Makefile
cat Makefile.base >> Makefile
* the new traces handler
*/
public void setTraceHandler(TraceHandler tracer) {
+ if (tracer == null) {
+ tracer = new TraceHandler(false, false, false);
+ }
+
this.tracer = tracer;
}
*/
public boolean check(URL url, boolean allowTooOld, boolean stable) {
File file = getCached(url);
- if (file.exists()) {
+ if (file.exists() && file.isFile()) {
if (allowTooOld || !isOld(file, stable)) {
return true;
}
* @return the opened resource if found, NULL if not
*/
private InputStream load(File cached, boolean allowTooOld, boolean stable) {
- if (cached.exists() && (allowTooOld || !isOld(cached, stable))) {
+ if (cached.exists() && cached.isFile()
+ && (allowTooOld || !isOld(cached, stable))) {
try {
return new MarkableFileInputStream(new FileInputStream(cached));
} catch (FileNotFoundException e) {
* the new traces handler
*/
public void setTraceHandler(TraceHandler tracer) {
+ if (tracer == null) {
+ tracer = new TraceHandler(false, false, false);
+ }
+
this.tracer = tracer;
}
package be.nikiroo.utils;
import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
return loader.getResourceAsStream(name);
}
+
+ /**
+ * Return a resetable {@link InputStream} from this stream, and reset it.
+ *
+ * @param in
+ * the input stream
+ * @return the resetable stream, which <b>may</b> be the same
+ *
+ * @throws IOException
+ * in case of I/O error
+ */
+ public static InputStream forceResetableStream(InputStream in)
+ throws IOException {
+ MarkableFileInputStream tmpIn = null;
+ File tmp = null;
+
+ boolean resetable = in.markSupported();
+ if (resetable) {
+ try {
+ in.reset();
+ } catch (IOException e) {
+ resetable = false;
+ }
+ }
+
+ if (resetable) {
+ return in;
+ }
+
+ tmp = File.createTempFile(".tmp-stream", ".tmp");
+ try {
+ write(in, tmp);
+ tmpIn = new MarkableFileInputStream(new FileInputStream(tmp));
+ return tmpIn;
+ } finally {
+ try {
+ if (tmpIn != null) {
+ tmpIn.close();
+ }
+ } finally {
+ tmp.delete();
+ }
+ }
+ }
+
+ /**
+ * Convert the {@link InputStream} into a byte array.
+ *
+ * @param in
+ * the input stream
+ *
+ * @return the array
+ *
+ * @throws IOException
+ * in case of I/O error
+ */
+ public static byte[] toByteArray(InputStream in) throws IOException {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ write(in, out);
+
+ byte[] array = out.toByteArray();
+ out.close();
+
+ return array;
+ }
}
--- /dev/null
+package be.nikiroo.utils;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * This class represents an image data.
+ *
+ * @author niki
+ */
+public class Image {
+ private byte[] data;
+
+ /**
+ * Do not use -- for serialisation purposes only.
+ */
+ @SuppressWarnings("unused")
+ private Image() {
+ }
+
+ /**
+ * Create a new {@link Image} with the given data.
+ *
+ * @param data
+ * the data
+ */
+ public Image(byte[] data) {
+ this.data = data;
+ }
+
+ /**
+ * Create a new {@link Image} from its Base64 representation.
+ *
+ * @param base64
+ * the {@link Image} in Base64 format
+ *
+ * @throws IOException
+ * in case of I/O error
+ */
+ public Image(String base64) throws IOException {
+ this(Base64.decode(base64));
+ }
+
+ /**
+ * Create a new {@link Image} from a stream.
+ *
+ * @param in
+ * the stream
+ *
+ * @throws IOException
+ * in case of I/O error
+ */
+ public Image(InputStream in) throws IOException {
+ this.data = IOUtils.toByteArray(in);
+ }
+
+ /**
+ * The actual image data.
+ * <p>
+ * This is the actual data, not a copy, so any change made here will be
+ * reflected into the {@link Image} and vice-versa.
+ *
+ * @return the image data
+ */
+ public byte[] getData() {
+ return data;
+ }
+
+ /**
+ * Convert the given {@link Image} object into a Base64 representation of
+ * the same {@link Image} object.
+ *
+ * @return the Base64 representation
+ */
+ public String toBase64() {
+ return new String(Base64.encodeBytes(getData()));
+ }
+}
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)
- *
- * @return the Base64 representation
+ * Get a (unique) instance of an {@link ImageUtils} compatible with your
+ * system.
*
- * @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}.
- *
- * @param in
- * the image to convert
+ * Save the given resource as an image on disk using the given image format
+ * for content, or with "png" format if it fails.
*
- * @return the Base64 representation
- *
- * @throws IOException
- * in case of IO 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;
- }
-
- /**
- * Convert the given Base64 representation of an image into an {@link Image}
- * object.
- *
- * @param b64data
- * the {@link Image} in Base64 format
- *
- * @return the {@link Image} object
- *
- * @throws IOException
- * in case of IO error
- */
- static public BufferedImage fromBase64(String b64data) throws IOException {
- ByteArrayInputStream in = new ByteArrayInputStream(
- Base64.decode(b64data));
- return fromStream(in);
- }
-
- /**
- * 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();
- }
-
- /**
- * 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 {@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 resetable = in.markSupported();
- if (resetable) {
- try {
- in.reset();
- } catch (IOException e) {
- resetable = false;
- }
- }
-
- if (resetable) {
- return fromResetableStream(in);
- }
-
- tmp = File.createTempFile(".tmp-image", ".tmp");
- try {
- IOUtils.write(in, tmp);
- tmpIn = new MarkableFileInputStream(new FileInputStream(tmp));
- return fromResetableStream(tmpIn);
- } finally {
- try {
- if (tmpIn != null) {
- tmpIn.close();
- }
- } finally {
- tmp.delete();
- }
- }
- }
-
- /**
- * Convert the given resetable {@link InputStream} into an {@link Image}
- * object, respecting the EXIF transformations if any.
- *
- * @param in
- * the 'resetable' (this is mandatory) {@link InputStream}
- *
- * @return the {@link Image} object
+ * @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 private BufferedImage fromResetableStream(InputStream in)
- throws IOException {
-
- 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) {
- 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;
- }
- //
-
- return image;
- }
+ public abstract void saveAsImage(Image img, File target, String format)
+ throws IOException;
/**
* Return the EXIF transformation flag of this image if any.
* @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;
return set_flag;
}
+
+ /**
+ * Create a new {@link ImageUtils}.
+ *
+ * @return the {@link ImageUtils}
+ */
+ private static ImageUtils newObject() {
+ for (String clazz : new String[] { "be.nikiroo.utils.ui.ImageUtilsAwt" }) {
+ try {
+ return (ImageUtils) SerialUtils.createObject(clazz);
+ } catch (Exception e) {
+ }
+ }
+
+ return null;
+ }
}
HtmlEscapeLevel.LEVEL_1_ONLY_MARKUP_SIGNIFICANT);
}
+ /**
+ * Zip the data and then encode it into Base64.
+ *
+ * @param data
+ * the data
+ *
+ * @return the Base64 zipped version
+ */
public static String zip64(String data) {
try {
return Base64.encodeBytes(data.getBytes(), Base64.GZIP);
}
}
+ /**
+ * Unconvert from Base64 then unzip the content.
+ *
+ * @param data
+ * the data in Base64 format
+ *
+ * @return the raw data
+ *
+ * @throws IOException
+ * in case of I/O error
+ */
public static String unzip64(String data) throws IOException {
ByteArrayInputStream in = new ByteArrayInputStream(Base64.decode(data,
Base64.GZIP));
package be.nikiroo.utils.resources;
-import java.awt.Color;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
}
/**
- * Return the value associated to the given id as a {@link Color}.
+ * Return the value associated to the given id as a colour if it is found
+ * and can be parsed.
+ * <p>
+ * The returned value is an ARGB value.
*
* @param id
* the id of the value to get
*
* @return the associated value
*/
- public Color getColor(E id) {
- Color color = null;
+ public Integer getColor(E id) {
+ Integer rep = null;
String bg = getString(id).trim();
+
+ int r = 0, g = 0, b = 0, a = -1;
if (bg.startsWith("#") && (bg.length() == 7 || bg.length() == 9)) {
try {
- int r = Integer.parseInt(bg.substring(1, 3), 16);
- int g = Integer.parseInt(bg.substring(3, 5), 16);
- int b = Integer.parseInt(bg.substring(5, 7), 16);
- int a = 255;
+ r = Integer.parseInt(bg.substring(1, 3), 16);
+ g = Integer.parseInt(bg.substring(3, 5), 16);
+ b = Integer.parseInt(bg.substring(5, 7), 16);
if (bg.length() == 9) {
a = Integer.parseInt(bg.substring(7, 9), 16);
+ } else {
+ a = 255;
}
- color = new Color(r, g, b, a);
+
} catch (NumberFormatException e) {
- color = null; // no changes
+ // no changes
}
}
// Try by name if still not found
- if (color == null) {
- try {
- Field field = Color.class.getField(bg);
- color = (Color) field.get(null);
- } catch (Exception e) {
+ if (a == -1) {
+ if ("black".equalsIgnoreCase(bg)) {
+ a = 255;
+ r = 0;
+ g = 0;
+ b = 0;
+ } else if ("white".equalsIgnoreCase(bg)) {
+ a = 255;
+ r = 255;
+ g = 255;
+ b = 255;
+ } else if ("red".equalsIgnoreCase(bg)) {
+ a = 255;
+ r = 255;
+ g = 0;
+ b = 0;
+ } else if ("green".equalsIgnoreCase(bg)) {
+ a = 255;
+ r = 0;
+ g = 255;
+ b = 0;
+ } else if ("blue".equalsIgnoreCase(bg)) {
+ a = 255;
+ r = 0;
+ g = 0;
+ b = 255;
+ } else if ("grey".equalsIgnoreCase(bg)
+ || "gray".equalsIgnoreCase(bg)) {
+ a = 255;
+ r = 128;
+ g = 128;
+ b = 128;
+ } else if ("cyan".equalsIgnoreCase(bg)) {
+ a = 255;
+ r = 0;
+ g = 255;
+ b = 255;
+ } else if ("magenta".equalsIgnoreCase(bg)) {
+ a = 255;
+ r = 255;
+ g = 0;
+ b = 255;
+ } else if ("yellow".equalsIgnoreCase(bg)) {
+ a = 255;
+ r = 255;
+ g = 255;
+ b = 0;
}
}
- //
- return color;
+ if (a != -1) {
+ rep = ((a & 0xFF) << 24) //
+ | ((r & 0xFF) << 16) //
+ | ((g & 0xFF) << 8) //
+ | ((b & 0xFF) << 0);
+ }
+
+ return rep;
}
/**
- * Set the value associated to the given id as a {@link Color}.
+ * Set the value associated to the given id as a colour.
+ * <p>
+ * The value is an BGRA value.
*
* @param id
* the id of the value to set
* @param color
- * the new color
- */
- public void setColor(E id, Color color) {
- // Check for named colours first
- try {
- Field[] fields = Color.class.getFields();
- for (Field field : fields) {
- if (field.equals(color)) {
- setString(id, field.getName());
- return;
- }
- }
- } catch (Exception e) {
- }
- //
-
- String r = Integer.toString(color.getRed(), 16);
- String g = Integer.toString(color.getGreen(), 16);
- String b = Integer.toString(color.getBlue(), 16);
- String a = "";
- if (color.getAlpha() < 255) {
- a = Integer.toString(color.getAlpha(), 16);
+ * the new colour
+ */
+ public void setColor(E id, Integer color) {
+ int a = (color >> 24) & 0xFF;
+ int r = (color >> 16) & 0xFF;
+ int g = (color >> 8) & 0xFF;
+ int b = (color >> 0) & 0xFF;
+
+ String rs = Integer.toString(r, 16);
+ String gs = Integer.toString(g, 16);
+ String bs = Integer.toString(b, 16);
+ String as = "";
+ if (a < 255) {
+ as = Integer.toString(a, 16);
}
- setString(id, "#" + r + g + b + a);
+ setString(id, "#" + rs + gs + bs + as);
}
/**
package be.nikiroo.utils.serial;
-import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.NotSerializableException;
import java.lang.reflect.Array;
import java.util.Map;
import java.util.UnknownFormatConversionException;
-import be.nikiroo.utils.ImageUtils;
+import be.nikiroo.utils.Image;
/**
* Small class to help with serialisation.
});
// Images (this is currently the only supported image type by default)
- customTypes.put("java.awt.image.BufferedImage", new CustomSerializer() {
+ customTypes.put("be.nikiroo.utils.Image", new CustomSerializer() {
@Override
protected String toString(Object value) {
- try {
- return ImageUtils.toBase64((BufferedImage) value);
- } catch (IOException e) {
- throw new UnknownFormatConversionException(e.getMessage());
- }
+ return ((Image) value).toBase64();
}
@Override
protected String getType() {
- return "java.awt.image.BufferedImage";
+ return "be.nikiroo.utils.Image";
}
@Override
protected Object fromString(String content) {
try {
- return ImageUtils.fromBase64(content);
+ return new Image(content);
} catch (IOException e) {
throw new UnknownFormatConversionException(e.getMessage());
}
package be.nikiroo.utils.test;
+import be.nikiroo.utils.Cache;
+import be.nikiroo.utils.Downloader;
+
/**
* Tests for nikiroo-utils.
*
addSeries(new SerialTest(args));
addSeries(new SerialServerTest(args));
addSeries(new StringUtilsTest(args));
+
+ // TODO: test cache and downloader
+ Cache cache = null;
+ Downloader downloader = null;
}
/**
-package be.nikiroo.utils;
+package be.nikiroo.utils.ui;
import java.awt.Color;
import java.awt.Dimension;
*
* @author niki
*/
-public class ImageText {
+public class ImageTextAwt {
private Image image;
private Dimension size;
private String text;
private boolean invert;
/**
- * Th rendering modes supported by this {@link ImageText} to convert
+ * The rendering modes supported by this {@link ImageTextAwt} to convert
* {@link Image}s into text.
*
* @author niki
}
/**
- * Create a new {@link ImageText} with the given parameters. Defaults to
+ * Create a new {@link ImageTextAwt} with the given parameters. Defaults to
* {@link Mode#DOUBLE_DITHERING} and no colour inversion.
*
* @param image
* @param size
* the final text size to target
*/
- public ImageText(Image image, Dimension size) {
+ public ImageTextAwt(Image image, Dimension size) {
this(image, size, Mode.DOUBLE_DITHERING, false);
}
/**
- * Create a new {@link ImageText} with the given parameters.
+ * Create a new {@link ImageTextAwt} with the given parameters.
*
* @param image
* the source {@link Image}
* @param invert
* TRUE to invert colours rendering
*/
- public ImageText(Image image, Dimension size, Mode mode, boolean invert) {
+ public ImageTextAwt(Image image, Dimension size, Mode mode, boolean invert) {
setImage(image);
setSize(size);
setMode(mode);
}
/**
- * Change the target size of this {@link ImageText}.
+ * Change the target size of this {@link ImageTextAwt}.
*
* @param size
* the new size
@Override
public boolean imageUpdate(Image img, int infoflags, int x,
int y, int width, int height) {
- ImageText.this.ready = true;
+ ImageTextAwt.this.ready = true;
return true;
}
})) {
--- /dev/null
+package be.nikiroo.utils.ui;
+
+import java.awt.geom.AffineTransform;
+import java.awt.image.AffineTransformOp;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.imageio.ImageIO;
+
+import be.nikiroo.utils.Image;
+import be.nikiroo.utils.ImageUtils;
+
+/**
+ * This class offer some utilities based around images and uses java.awt.
+ *
+ * @author niki
+ */
+public class ImageUtilsAwt extends ImageUtils {
+ @Override
+ public void saveAsImage(Image img, File target, String format)
+ throws IOException {
+ try {
+ BufferedImage image = ImageUtilsAwt.fromImage(img);
+
+ boolean ok = false;
+ try {
+
+ ok = ImageIO.write(image, format, target);
+ } catch (IOException e) {
+ ok = false;
+ }
+
+ // Some formats are not reliable
+ // Second change: PNG
+ if (!ok && !format.equals("png")) {
+ ok = ImageIO.write(image, "png", target);
+ }
+
+ if (!ok) {
+ throw new IOException(
+ "Cannot find a writer for this image and format: "
+ + format);
+ }
+ } catch (IOException e) {
+ throw new IOException("Cannot write image to " + target, e);
+ }
+ }
+
+ /**
+ * Convert the given {@link Image} into a {@link BufferedImage} object,
+ * respecting the EXIF transformations if any.
+ *
+ * @param img
+ * the {@link Image}
+ *
+ * @return the {@link Image} object
+ *
+ * @throws IOException
+ * in case of IO error
+ */
+ static public BufferedImage fromImage(Image img) throws IOException {
+ InputStream in = new ByteArrayInputStream(img.getData());
+
+ 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) {
+ 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;
+ }
+ //
+
+ return image;
+ }
+}
-package be.nikiroo.utils.test;
+package be.nikiroo.utils.ui.test;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
--- /dev/null
+package be.nikiroo.utils.ui.test;
+
+public class TestUI {
+ // TODO: make a GUI tester
+ public TestUI() {
+ ProgressBarManualTest a = new ProgressBarManualTest();
+ }
+}