X-Git-Url: https://git.nikiroo.be/?a=blobdiff_plain;f=src%2Fbe%2Fnikiroo%2Futils%2FImage.java;h=58b1f5aeac05f71370365ac9c3a562f70f722797;hb=1dbed6237611f74292af13f20f9d80c446a60020;hp=f2b94991417ff922dba3a8c00713fe7202912657;hpb=a6a73de36765b85947ac885529da82d3e7189269;p=fanfix.git diff --git a/src/be/nikiroo/utils/Image.java b/src/be/nikiroo/utils/Image.java index f2b9499..9b28835 100644 --- a/src/be/nikiroo/utils/Image.java +++ b/src/be/nikiroo/utils/Image.java @@ -3,10 +3,14 @@ package be.nikiroo.utils; import java.io.ByteArrayInputStream; import java.io.Closeable; import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.OutputStream; +import java.io.Serializable; +import be.nikiroo.utils.streams.Base64InputStream; import be.nikiroo.utils.streams.MarkableFileInputStream; /** @@ -14,13 +18,17 @@ import be.nikiroo.utils.streams.MarkableFileInputStream; * * @author niki */ -public class Image implements Closeable { +public class Image implements Closeable, Serializable { + static private final long serialVersionUID = 1L; + static private File tempRoot; static private TempFiles tmpRepository; static private long count = 0; static private Object lock = new Object(); + private Object instanceLock = new Object(); private File data; + private long size; /** * Do not use -- for serialisation purposes only. @@ -39,7 +47,7 @@ public class Image implements Closeable { ByteArrayInputStream in = new ByteArrayInputStream(data); try { this.data = getTemporaryFile(); - IOUtils.write(in, this.data); + size = IOUtils.write(in, this.data); } catch (IOException e) { throw new RuntimeException(e); } finally { @@ -51,6 +59,24 @@ public class Image implements Closeable { } } + /** + * Create an image from Base64 encoded data. + * + *
+ * Please use {@link Image#Image(InputStream)} when possible instead, with a + * {@link Base64InputStream}; it can be much more efficient. + * + * @param base64EncodedData + * the Base64 encoded data as a String + * + * @throws IOException + * in case of I/O error or badly formated Base64 + */ + public Image(String base64EncodedData) throws IOException { + this(new Base64InputStream(new ByteArrayInputStream( + StringUtils.getBytes(base64EncodedData)), false)); + } + /** * Create a new {@link Image} from a stream. * @@ -62,7 +88,16 @@ public class Image implements Closeable { */ public Image(InputStream in) throws IOException { data = getTemporaryFile(); - IOUtils.write(in, data); + size = IOUtils.write(in, data); + } + + /** + * The size of the enclosed image in bytes. + * + * @return the size + */ + public long getSize() { + return size; } /** @@ -81,17 +116,24 @@ public class Image implements Closeable { * in case of I/O error */ public InputStream newInputStream() throws IOException { - return new MarkableFileInputStream(new FileInputStream(data)); + synchronized (instanceLock) { + if (data == null) { + throw new IOException("Image was close()d"); + } + + return new MarkableFileInputStream(data); + } } /** * Read the actual image data, as a byte array. - *
- * Note: if possible, prefer the {@link Image#newInputStream()} method, as - * it can be more efficient. + * + * @deprecated if possible, prefer the {@link Image#newInputStream()} + * method, as it can be more efficient * * @return the image data */ + @Deprecated public byte[] getData() { try { InputStream in = newInputStream(); @@ -105,6 +147,30 @@ public class Image implements Closeable { } } + /** + * Convert the given {@link Image} object into a Base64 representation of + * the same {@link Image} object. + * + * @deprecated Please use {@link Image#newInputStream()} instead, it is more + * efficient + * + * @return the Base64 representation + */ + @Deprecated + public String toBase64() { + try { + Base64InputStream stream = new Base64InputStream(newInputStream(), + true); + try { + return IOUtils.readSmallStream(stream); + } finally { + stream.close(); + } + } catch (IOException e) { + return null; + } + } + /** * Closing the {@link Image} will delete the associated temporary file on * disk. @@ -114,13 +180,21 @@ public class Image implements Closeable { */ @Override public void close() throws IOException { - data.delete(); - synchronized (lock) { - count--; - if (count <= 0) { - count = 0; - tmpRepository.close(); - tmpRepository = null; + synchronized (instanceLock) { + new Exception().printStackTrace(); + if (size >= 0) { + size = -1; + data.delete(); + data = null; + + synchronized (lock) { + count--; + if (count <= 0) { + count = 0; + tmpRepository.close(); + tmpRepository = null; + } + } } } } @@ -155,6 +229,44 @@ public class Image implements Closeable { } } + /** + * Write this {@link Image} for serialization purposes; that is, write the + * content of the backing temporary file. + * + * @param out + * the {@link OutputStream} to write to + * + * @throws IOException + * in case of I/O error + */ + private void writeObject(ObjectOutputStream out) throws IOException { + InputStream in = newInputStream(); + try { + IOUtils.write(in, out); + } finally { + in.close(); + } + } + + /** + * Read an {@link Image} written by + * {@link Image#writeObject(java.io.ObjectOutputStream)}; that is, create a + * new temporary file with the saved content. + * + * @param in + * the {@link InputStream} to read from + * @throws IOException + * in case of I/O error + * @throws ClassNotFoundException + * will not be thrown by this method + */ + @SuppressWarnings("unused") + private void readObject(ObjectInputStream in) throws IOException, + ClassNotFoundException { + data = getTemporaryFile(); + IOUtils.write(in, data); + } + /** * Change the temporary root directory used by the program. *