Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support EXIF #1045

Open
schulzch opened this issue Sep 28, 2019 · 18 comments
Open

Support EXIF #1045

schulzch opened this issue Sep 28, 2019 · 18 comments
Labels
kind: API missing or awkward public APIs kind: enhancement

Comments

@schulzch
Copy link

I would like to be able to read and write EXIF meta data, especially for PNG and JPEG.

My specific use case for this functionality is
a) storing/loading configuration within/from screenshots for reproducibility,
b) maintaining metadata when processing images.

If there is interest I would be very willing to implement this - hints and feedback welcome :)

@fintelia
Copy link
Contributor

👍 I think the way to do this would be to implement this first for a single format, directly on the encoder/decoder and then if we can find a clean/general API extend it to more formats.

@HeroicKatora
Copy link
Member

Seems like a problem similar to Limits for decoder but for the encoders.

@kaj
Copy link
Member

kaj commented Sep 30, 2019

There is a few packages providing exif info currently. I use kamadak-exif in a project and is quite happy with that. But yes, better integration with the image echosystem would probably be nice.

@birktj
Copy link
Member

birktj commented Oct 12, 2019

You may be interested in image-rs/image-png#116

@maghoff
Copy link

maghoff commented Nov 17, 2019

This is also neccessary for correctly orienting JPEGs.

It could be argued that orientation correction should be automatically applied to the pixel buffer, making it even more important to integrate this functionality rather than pointing to other crates 🙂

@lovasoa
Copy link
Contributor

lovasoa commented Nov 21, 2019

I recently got a feature request that would require image-rs to support writing EXIF data:
lovasoa/dezoomify-rs#12

So, 👍 on this !

@zeh
Copy link

zeh commented Nov 22, 2020

One year later (!) but this would be great.

I'm saving images using image and would like to add some basic metadata to them, but there's no good way to do it!

Strangely, currently, there's no good create for writing EXIF data for Rust. There's a bunch of crates to read metadata; a few wrappers for some C libraries (ugh); and a bunch of really old crates of dubious effectiveness. BA pure Rust EXIF writer is nowhere to be found.

I could see this being a separate crate just for EXIF writing (depending on format) and then exposed somehow so Image can make use of it when writing images to disk.

@paolobarbolini
Copy link
Contributor

currently there's no good create for writing EXIF data for Rust

You should be able to do so with the help of kamadak-exif to encode the EXIF data and img-parts (I'm the author of it) to write it to an existing image.

See also kamadak/exif-rs#1

@zeh
Copy link

zeh commented Nov 25, 2020

currently there's no good create for writing EXIF data for Rust

You should be able to do so with the help of kamadak-exif to encode the EXIF data and img-parts (I'm the author of it) to write it to an existing image.

Thanks for the tip. I hadn't ran into img-parts before when trying to find libraries for my use case. I managed to add metadata writing to a project of mine using img-parts and it seems to be working well. A bit suboptimal since it writes the file, reads it, and writes it again with metadata, but it's "good enough" for now.


After implementing this feature and doing some research on the problem space I think it might actually not be a good idea for image to try and provide a way to write EXIF or other metadata. The feature is more complicated than I thought; it would make total sense to have this as a dedicated, separate library.

In fact, I wonder if it makes sense for image to implement save() at all, given the edge cases required for it to properly work (say, JPEG rotation as mentioned). It's convenient, for sure, but not always enough; it can probably work for 98% of the use cases out there, but the rest 2% end up requiring a radically different solution. For my specific use case, since I require metadata too, to avoid having to write the file twice it would be better to have a to_file_buffer() that saves the encoded image to a buffer (basically exposing save_buffer_impl()) so it can be used elsewhere - adding metadata, etc - before writing the file.

(Note: I'm not an advanced Rust programmer, so I might be missing a better solution for my use case.)

@paolobarbolini
Copy link
Contributor

paolobarbolini commented Nov 25, 2020

For my specific use case, since I require metadata too, to avoid having to write the file twice it would be better to have a to_file_buffer() that saves the encoded image to a buffer

The image crate already supports it. Instead of using save(), which takes the path to where you want the file to be saved to, you can use write_to(), which asks for a Writer instead. With it you can make it write into a buffer, just as I show in this example.

@zeh
Copy link

zeh commented Nov 25, 2020

The image crate already supports it. Instead of using save(), which takes the path to where you want the file to be saved to, you can use write_to(), which asks for a Writer instead. With it you can make it write into a buffer, just as I show in this example.

Ah, I see. I was using ImageBuffer, which didn't expose write_to(), unlike DynamicImage. Still a but confused about those abstractions. I'll use that instead.

@stephanbogner
Copy link

stephanbogner commented Mar 8, 2023

I'd also appreciate this (mainly to preserve image orientation/rotation).

My workaround:
I found an example on how to integrate img-parts with image ... but I couldn't get it to work.

What I now did instead: I use kamadak-exif (which I already use anyway to get the exif date information) and rotate/flip the image myself using image::imageops (with information from here on what the exif orientation values mean).
Not an ideal solution, but it works and I only load and save the image once.

@marcalj
Copy link

marcalj commented Jun 7, 2024

I'd also appreciate this (mainly to preserve image orientation/rotation).

My workaround: I found an example on how to integrate img-parts with image ... but I couldn't get it to work.

What I now did instead: I use kamadak-exif (which I already use anyway to get the exif date information) and rotate/flip the image myself using image::imageops (with information from here on what the exif orientation values mean). Not an ideal solution, but it works and I only load and save the image once.

I'm using your approach and I'm wondering how to read the EXIF data without having to clone the image buffer. Since loading the buffer as an image moves the value. Any thoughts? Thanks.

@marcalj
Copy link

marcalj commented Jun 7, 2024

Ok, since my input is a buffer, I can read EXIF data without modifying the buffer like this:

// input: image_buffer: &[u8]
let exif_reader = exif::Reader::new();
let exif = exif_reader.read_raw(image_buffer.to_vec());

Update: Oh, just figured that this is actually cloning the buffer... :-/

@marvinruder
Copy link

I'd also appreciate this (mainly to preserve image orientation/rotation).
My workaround: I found an example on how to integrate img-parts with image ... but I couldn't get it to work.
What I now did instead: I use kamadak-exif (which I already use anyway to get the exif date information) and rotate/flip the image myself using image::imageops (with information from here on what the exif orientation values mean). Not an ideal solution, but it works and I only load and save the image once.

I'm using your approach and I'm wondering how to read the EXIF data without having to clone the image buffer. Since loading the buffer as an image moves the value. Any thoughts? Thanks.

I am doing something similar with

// input: image_buffer: &[u8]
exif::Reader::new().read_from_container(&mut std::io::Cursor::new(image_buffer))

@marcalj
Copy link

marcalj commented Jun 13, 2024

// input: image_buffer: &[u8]
exif::Reader::new().read_from_container(&mut std::io::Cursor::new(image_buffer))

AFAIK is also creating a copy of the buffer.

@Shnatsel
Copy link
Contributor

Reading Exif chunks was implemented for JPEG and WebP in #2291 and #2319

No writing support yet

@mschnell1
Copy link

You should be able to do so with the help of kamadak-exif to encode the EXIF data and img-parts (I'm the author of it) to write it to an existing image.

Writing a ImageDescription into an existing JPG file.

I already tested this with kamadak-exif, but when just doing so the file seems to feature no image any more :(
trying to use set_jpeg()failed, as I don't seem to be able to extract the jpeg picture data.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind: API missing or awkward public APIs kind: enhancement
Projects
None yet
Development

No branches or pull requests