java - Manipulate an image without deleting its EXIF data -
using imageio, have problem of transforming image file, , after overwriting it, loses of exif data. there way preserve without first extracting it, caching it, , resetting it?
here solution using combination of imageio, imgscalr , apache commons-imaging. it's pity there's no single library combines reading image metadata, making rather excessive on memory usage; improvements welcome.
import java.awt.image.bufferedimage; import java.io.bytearrayinputstream; import java.io.bytearrayoutputstream; import java.io.ioexception; import java.io.inputstream; import java.io.outputstream; import javax.imageio.imageio; import org.apache.commons.imaging.imagereadexception; import org.apache.commons.imaging.imagewriteexception; import org.apache.commons.imaging.imaging; import org.apache.commons.imaging.common.iimagemetadata; import org.apache.commons.imaging.formats.jpeg.jpegimagemetadata; import org.apache.commons.imaging.formats.jpeg.exif.exifrewriter; import org.apache.commons.imaging.formats.tiff.tiffimagemetadata; import org.apache.commons.io.ioutils; import org.imgscalr.scalr; public class imagedata { private byte[] imagedata; public imagedata(inputstream instream) throws ioexception { imagedata = ioutils.tobytearray(instream); instream.close(); } public synchronized void resize(int maxdimension) throws ioexception, imagereadexception, imagewriteexception { // resize image if necessary bufferedimage image = readimage(imagedata); if (image.getwidth() > maxdimension || image.getheight() > maxdimension) { // save existing metadata, if tiffimagemetadata metadata = readexifmetadata(imagedata); imagedata = null; // allow immediate gc // resize image = scalr.resize(image, maxdimension); // rewrite resized image byte[] byte[] resizeddata = writejpeg(image); image = null; // allow immediate gc // re-code resizeddata + metadata imagedata if (metadata != null) { this.imagedata = writeexifmetadata(metadata, resizeddata); } else { this.imagedata = resizeddata; } } } private tiffimagemetadata readexifmetadata(byte[] jpegdata) throws imagereadexception, ioexception { iimagemetadata imagemetadata = imaging.getmetadata(jpegdata); if (imagemetadata == null) { return null; } jpegimagemetadata jpegmetadata = (jpegimagemetadata)imagemetadata; tiffimagemetadata exif = jpegmetadata.getexif(); if (exif == null) { return null; } return exif; } private byte[] writeexifmetadata(tiffimagemetadata metadata, byte[] jpegdata) throws imagereadexception, imagewriteexception, ioexception { bytearrayoutputstream out = new bytearrayoutputstream(); new exifrewriter().updateexifmetadatalossless(jpegdata, out, metadata.getoutputset()); out.close(); return out.tobytearray(); } private bufferedimage readimage(byte[] data) throws ioexception { return imageio.read(new bytearrayinputstream(data)); } private byte[] writejpeg(bufferedimage image) throws ioexception { bytearrayoutputstream jpegout = new bytearrayoutputstream(); imageio.write(image, "jpeg", jpegout); jpegout.close(); return jpegout.tobytearray(); } public synchronized void writejpeg(outputstream outstream) throws ioexception { ioutils.write(imagedata, outstream); } public synchronized byte[] getjpegdata() { return imagedata; } }
Comments
Post a Comment