Skip to main content

Clone metadata + thumbnails from one image to another

14 replies [Last post]
sentry0
Offline
Joined: 2009-03-10
Points: 0

I have a method that needs to grab the metadata and thumbnails from a source image and transplant it into a scaled instance of the same image.

My code...note that there's a method called getAllthumbnails() that returns ArrayList called inside the code not detailed for brevity's sake. This code appears to be mostly working save the cloning of metadata and thumbnails which I thought I was doing with image = new IIOImage(resizedImage, getAllThumbnails(originalImage), ir.getImageMetadata(0));

private byte[] getFinalImage(byte[] originalImage, String originalExtension, BufferedImage resizedImage) throws IOException {
Iterator readers = ImageIO.getImageReadersByFormatName(originalExtension);
ImageReader ir = readers.next();
ImageInputStream iis = ImageIO.createImageInputStream(new ByteArrayInputStream(originalImage));
ir.setInput(iis);
IIOImage image = new IIOImage(resizedImage, getAllThumbnails(originalImage), ir.getImageMetadata(0));
ir.dispose();

ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageOutputStream ios = ImageIO.createImageOutputStream(baos) ;
Iterator writers = ImageIO.getImageWritersByFormatName(originalExtension);
ImageWriter imageWriter = writers.next();
imageWriter.setOutput(ios);
imageWriter.write(image);

ios.flush();
imageWriter.dispose();
ios.close();

return baos.toByteArray();
}

Any help would be greatly appreciated.

Message was edited by: sentry0

Message was edited by: sentry0

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Fabrizio Giudici

jai-imageio@javadesktop.org wrote:
> Yes after simplifying my code, putting it all in 1 method, I was able to transfer EXIF data from the file read to the file written.
> This is using JPEGImageWriter, and not modifying image or data at all.
> I will try more code over the weekend:
> - see if it works when image is resized, profile changed, etc
> - test the speed difference between CLibJPEGImageWriter and JPEGImageWriter (I dont care too much if writer is slow, as long as I can use clib for reading)
> AG
>
I will be interested in your findings. My project Mistral (which can
stay on top of ImageIO) has some support for facilitating the reading of
metadata, and I'm going to add write support (a thing that I've never
studied so far).

--
Fabrizio Giudici - Java Architect, Project Manager
Tidalwave s.a.s. - "We make Java work. Everywhere."
weblogs.java.net/blog/fabriziogiudici - www.tidalwave.it/blog
Fabrizio.Giudici@tidalwave.it - mobile: +39 348.150.6941

---------------------------------------------------------------------
To unsubscribe, e-mail: interest-unsubscribe@jai-imageio.dev.java.net
For additional commands, e-mail: interest-help@jai-imageio.dev.java.net

Antoine Girbal

Basic read/write using java module:
Time: start read using JPEGImageReader took 30
Time: set input took 4
Time: read stream meta took 1
Time: read img meta took 85
Time: read thumbnail took 1
Time: read img took 827
Time: start write using JPEGImageWriter took 13
Time: set output took 1
Time: create img took 1
Time: write img took 1540

Basic read/write using clib module:
Time: start read using CLibJPEGImageReader took 29
Time: set input took 4
Time: read stream meta took 0
Time: read img meta took 12
Time: read thumbnail took 216
Time: read img took 835
Time: start write using CLibJPEGImageWriter took 8
Time: set output took 0
Time: create img took 0
Time: write img took 577

Comments:
- reading img is about same time java vs clib.
- for some reason reading thumbnail takes 200ms with clib vs 1ms for
java... odd... maybe because thumb is part of regular metadata.
- writing is 3 times faster with clib, 500ms vs 1.5s. BUT it does not
write thumbnail nor metadata.

Conclusion: java module is pretty much as fast, and actually works.

AG

Fabrizio Giudici wrote:
> jai-imageio@javadesktop.org wrote:
>> Yes after simplifying my code, putting it all in 1 method, I was able
>> to transfer EXIF data from the file read to the file written.
>> This is using JPEGImageWriter, and not modifying image or data at all.
>> I will try more code over the weekend:
>> - see if it works when image is resized, profile changed, etc
>> - test the speed difference between CLibJPEGImageWriter and
>> JPEGImageWriter (I dont care too much if writer is slow, as long as I
>> can use clib for reading)
>> AG
>>
> I will be interested in your findings. My project Mistral (which can
> stay on top of ImageIO) has some support for facilitating the reading
> of metadata, and I'm going to add write support (a thing that I've
> never studied so far).
>

---------------------------------------------------------------------
To unsubscribe, e-mail: interest-unsubscribe@jai-imageio.dev.java.net
For additional commands, e-mail: interest-help@jai-imageio.dev.java.net

agirbal
Offline
Joined: 2009-05-04
Points: 0

Posting again my results, looks like it didnt go through by email.

Basic read/write using java module:
Time: start read using JPEGImageReader took 30
Time: set input took 4
Time: read stream meta took 1
Time: read img meta took 85
Time: read thumbnail took 1
Time: read img took 827
Time: start write using JPEGImageWriter took 13
Time: set output took 1
Time: create img took 1
Time: write img took 1540

Basic read/write using clib module:
Time: start read using CLibJPEGImageReader took 29
Time: set input took 4
Time: read stream meta took 0
Time: read img meta took 12
Time: read thumbnail took 216
Time: read img took 835
Time: start write using CLibJPEGImageWriter took 8
Time: set output took 0
Time: create img took 0
Time: write img took 577

Comments:
- reading img is about same time java vs clib.
- for some reason reading thumbnail takes 200ms with clib vs 1ms for java... odd... maybe because thumb is part of regular metadata.
- writing is 3 times faster with clib, 500ms vs 1.5s. BUT it does not write thumbnail nor metadata.

Conclusion: java module is pretty much as fast, and actually works.

AG

agirbal
Offline
Joined: 2009-05-04
Points: 0

Now for the bad news about JPEGImageReader:
- exif metadata does not get parsed! You just get a big blob. Then you have to use a TIFFImageReader to decode it. Not a huge deal but annoying (lucky I found trick online).
- cannot get the thumbnail! My picture was taken from a Nikon D90, and JPEGImageReader reports that image has no thumbnail. If I try with the clib reader then I get thumbnail fine.

This is getting messy: dont want to use several readers to do different things.
Anyone knows why JPEGImageReader reports there is no thumbnail in there??
AG

agirbal
Offline
Joined: 2009-05-04
Points: 0

So to sum up, the:
- clib reader does everything well (parses EXIF and always finds thumbnail), BUT the metadata it gives cannot be used by jpegimagewriter.
- clib writer doesnt write metadata or thumbnail.
- jpegimagereader doesnt decode EXIF and misses the thumbnail on some pics.
- jpegimagewriter does everything well (writes EXIF and thumbnail) as long as metadata comes from jpegimagereader.

So in the end, here is what I have to do for read:
- read metadata with jpegimagereader
- decode EXIF from metadata using tiffimagereader
- read thumbnail using jpegimagereader
- if no thumbnail, read thumbnail using clib

for write:
- write meta, thumbnail and image using jpegimagewriter.

agirbal
Offline
Joined: 2009-05-04
Points: 0

Yes after simplifying my code, putting it all in 1 method, I was able to transfer EXIF data from the file read to the file written.
This is using JPEGImageWriter, and not modifying image or data at all.
I will try more code over the weekend:
- see if it works when image is resized, profile changed, etc
- test the speed difference between CLibJPEGImageWriter and JPEGImageWriter (I dont care too much if writer is slow, as long as I can use clib for reading)
AG

rcesare
Offline
Joined: 2004-07-12
Points: 0

This works fine if you work with RGB jpeg images only.
But if you need to work with CMYK jpeg images, like me, you have to use CLibJPEGImageWriter. I think that this behaviour should be fixed in the CLibJPEGImageWriter. I read old threads of at least two years about this problem.
I wonder why this is not fixed yet.

Regards,
roberto

Message was edited by: rcesare

agirbal
Offline
Joined: 2009-05-04
Points: 0

Any luck getting this to work??
I need to do the exact same thing: grab exif metadata from the original image, then inject it back into the modified image along with its thumbnail.
I cannot get either EXIF or thumbnail to be written to the final image.
I've seen many postings around that say imagewriter cannot do this even though doc says it can.
Many people say to use Sanselan or Jmagick but JAI has been great for all I needed so far, dont want to switch library just for that last writing step!
thanks,
Antoine

marcojacob
Offline
Joined: 2006-07-10
Points: 0

To read EXIF metadata and write it to a different image you should do this:

IIOImage image = imageReader.readAll(index, null);
IIOMetadata meta = image.getMetadata();
List thumbs = image.getThumbnails();
...
RenderedImage scaledRI = ...;
IIOImage scaled = new IIOImage(scaledRI, thumbs, meta);
writer.write(scaled);
...
flush, close output

This is the way it should go as far as I know.

rcesare
Offline
Joined: 2004-07-12
Points: 0

This works fine if the writer it's an instance of JPEGImageWriter, but it fails if the writer it's an instance of CLibJPEGImageWriter. In others words it doesn't work if you install the native library.

Does Someone know if there are workarounds for CLibJPEGImageWriter?

regards,
roberto

marcojacob
Offline
Joined: 2006-07-10
Points: 0

You are right that the native writer doesn't support metadata.
I read it from the table at:

http://download.java.net/media/jai-imageio/javadoc/1.2-latest/index.html

Standard Image Metadata, Native Image Metadata = true (Reader only).

cesarer
Offline
Joined: 2008-10-17
Points: 0

Do you know it there are some workarounds to preserve at least IPTC info and ICC_profile?

Thanks,
roberto

arnarnesset
Offline
Joined: 2009-06-18
Points: 0

Hi there

I think I am trying to achieve something similar to this. My requirements are however to extract and preserve XMP data (http://www.adobe.com/devnet/xmp/), but I can't see that IIOMetadata provides that. The metadata I get from IIOMetadata (http://java.sun.com/j2se/1.4.2/docs/api/javax/imageio/metadata/doc-files...) is something quite different from what I get when I scan the image file for the APP0 marker etc. I'm probably confusing concepts here (I'm rather new to image processing)?

Anyway, I currently am able to extract the XMP metadata, and I am successful in resizing my images using ImageIO, but I fail to find a way to write the metadata onto the resized image.

Any pointers are much appreciated.

Regards,

Arnar Nesset

chcornwell
Offline
Joined: 2004-09-16
Points: 0

Your basic strategy looks correct to me. The only catch might be if the copied metadata is not compatible with the output image as a result of the change in image size. I have seen some ImageWriters that fail silently under similar circumstances. To get around this you would have to modify the appropriate attributes in the IIOMetadataObject before sending it to the ImageWriter.

Another thought, could it be that ir.dispose() is releasing resources that need to be held until the IIOMetadataObject has been written to the output stream (I think that behavior would be specific to each codec implementation)? If that is the case, perhaps deferring the ir.dispose() to follow the output block would help.

Let me know if that doesn't help and I'll try running your code.

- Carl