### Rust Example Usage of Documented Item Source: https://docs.rs/kamadak-exif/latest/scrape-examples-help Illustrates how an external example file can call a documented function from a crate. This is the pattern Rustdoc scrapes. ```rust // examples/ex.rs fn main() { a_crate::a_func(); } ``` -------------------------------- ### Rust Function Declaration Example Source: https://docs.rs/kamadak-exif/latest/scrape-examples-help Demonstrates a basic Rust public function declaration within a library. This serves as a target for scraped examples. ```rust // src/lib.rs pub fn a_func() {} ``` -------------------------------- ### Rust Exif Writer Example Source: https://docs.rs/kamadak-exif/latest/src/exif/writer Demonstrates how to use the `Writer` struct to create and write Exif data. It shows how to add fields like ImageDescription and then write the data to a byte buffer, asserting the correctness of the output. ```Rust use exif::{Field, In, Tag, Value}; use exif::experimental::Writer; let image_desc = Field { tag: Tag::ImageDescription, ifd_num: In::PRIMARY, value: Value::Ascii(vec![b"Sample".to_vec()]), }; let mut writer = Writer::new(); let mut buf = std::io::Cursor::new(Vec::new()); writer.push_field(&image_desc); writer.write(&mut buf, false)?; static expected: &[u8] = b"\x4d\x4d\x00\x2a\x00\x00\x00\x08\ \x00\x01\x01\x0e\x00\x02\x00\x00\x00\x07\x00\x00\x00\x1a\ \x00\x00\x00\x00\ Sample\0"; assert_eq!(buf.into_inner(), expected); ``` -------------------------------- ### Example: Reading and Displaying Exif Data (Rust) Source: https://docs.rs/kamadak-exif/latest/src/exif/reader Demonstrates how to open an image file, read its Exif data using `read_from_container`, retrieve a specific field (XResolution), and iterate over all fields. Requires file I/O and the `exif` crate. ```rust #[cfg(test)] mod tests { use std::fs::File; use std::io::BufReader; use crate::tag::Context; use crate::value::Value; use super::*; #[test] fn get_field() { let file = File::open("tests/yaminabe.tif").unwrap(); let exif = Reader::new().read_from_container( &mut BufReader::new(&file)).unwrap(); match exif.get_field(Tag::ImageDescription, In(0)).unwrap().value { Value::Ascii(ref vec) => assert_eq!(vec, &[b"Test image"]), ref v => panic!("wrong variant {:?}", v) } match exif.get_field(Tag::ImageDescription, In(1)).unwrap().value { Value::Ascii(ref vec) => assert_eq!(vec, &[b"Test thumbnail"]), ref v => panic!("wrong variant {:?}", v) } match exif.get_field(Tag::ImageDescription, In(2)).unwrap().value { Value::Ascii(ref vec) => assert_eq!(vec, &[b"Test 2nd IFD"]), } } } ``` -------------------------------- ### Displaying EXIF Field Values with Units (Rust) Source: https://docs.rs/kamadak-exif/latest/exif/doc/upgrade/index Demonstrates the usage of `Field::display_value()` for easily displaying EXIF field values. It also shows how to append units to the displayed value using `with_unit(&reader)`. ```Rust assert_eq!(field.display_value().to_string(), field.value.display_as(field.tag).to_string()); ``` ```Rust // Display the value only. println!("{}", field.display_value()); // Display the value with its unit. If the unit depends on another // field, it is taken from the reader. println!("{}", field.display_value().with_unit(&reader)); ``` -------------------------------- ### Rust Example: Defining EXIF Tag Constants Source: https://docs.rs/kamadak-exif/latest/src/exif/tag This code snippet demonstrates the usage of the `generate_well_known_tag_constants!` macro to define specific EXIF tags. It illustrates how to provide context (e.g., `Context::Tiff`), tag attributes (name, number, default value, display function, units, description), and how these are mapped to constants and metadata. ```rust generate_well_known_tag_constants!( |Context::Tiff| /// A pointer to the Exif IFD. This is used for the internal structure /// of Exif data and will not be returned to the user. #[doc(hidden)] (ExifIFDPointer, 0x8769, DefaultValue::None, d_default, unit![], "Exif IFD pointer"), /// A pointer to the GPS IFD. This is used for the internal structure /// of Exif data and will not be returned to the user. #[doc(hidden)] (GPSInfoIFDPointer, 0x8825, DefaultValue::None, d_default, unit![], "GPS Info IFD pointer"), |Context::Exif| /// A pointer to the interoperability IFD. This is used for the internal /// structure of Exif data and will not be returned to the user. #[doc(hidden)] (InteropIFDPointer, 0xa005, DefaultValue::None, d_default, unit![], "Interoperability IFD pointer"), |Context::Tiff| (ImageWidth, 0x100, DefaultValue::None, d_default, unit!["pixels"], "Image width"), (ImageLength, 0x101, DefaultValue::None, d_default, unit!["pixels"], "Image height") ); ``` -------------------------------- ### Example: Parsing Exif Data with Error Handling in Rust Source: https://docs.rs/kamadak-exif/latest/exif/enum Demonstrates how to read Exif data from a file using `kamadak-exif`. This example showcases enabling `continue_on_error` and using `or_else` with `distill_partial_result` to handle potential parsing errors gracefully, printing warnings for any errors encountered. ```Rust fn dump_file(path: &Path) -> Result<(), exif::Error> { let file = File::open(path)?; // To parse with continue-on-error mode: let exif = exif::Reader::new() .continue_on_error(true) .read_from_container(&mut BufReader::new(&file)) .or_else(|e| e.distill_partial_result(|errors| { eprintln!("{}: {} warning(s)", path.display(), errors.len()); errors.iter().for_each(|e| eprintln!(" {}", e)); }))?; println!("{}", path.display()); for f in exif.fields() { println!(" {}/{}: {}", f.ifd_num.index(), f.tag, f.display_value().with_unit(&exif)); println!(" {:?}", f.value); } Ok(()) } ``` -------------------------------- ### Get Tag Description (Rust) Source: https://docs.rs/kamadak-exif/latest/exif/struct Provides a human-readable string description for a given `Tag`. This function helps in understanding the meaning and purpose of a specific Exif or TIFF tag. It returns an `Option<&str>`, indicating that descriptions are not available for all tags. ```rust pub fn description(&self) -> Option<&str> ``` -------------------------------- ### Upgrade kamadak-exif from 0.4.x to 0.5.x (Rust) Source: https://docs.rs/kamadak-exif/latest/exif/doc/upgrade/index Demonstrates the API change for reading EXIF data, where the `Reader` struct has been split into `Reader` and `Exif`. The old `Reader::new(data)` is replaced with `Reader::new().read_from_container(data)` or `read_raw(data)`, and accessing fields is now done through the `Exif` struct. ```Rust let reader = Reader::new(&mut bufreader).unwrap(); for f in reader.fields() { /* do something */ } ``` ```Rust let exif = Reader::new().read_from_container(&mut bufreader).unwrap(); for f in exif.fields() { /* do something */ } ``` -------------------------------- ### Parse Exif Data from Image Files (Rust) Source: https://docs.rs/kamadak-exif/latest/src/exif/lib This example demonstrates how to read Exif data from JPEG and TIFF image files using the kamadak-exif library. It opens files, creates a buffered reader, initializes an Exif reader, and iterates through the Exif fields, printing their tag, IFD number, and displayable value with units. This function requires file system access and IO operations. ```Rust use std::fs::File; use std::io::BufReader; use exif::Reader; fn main() -> Result<(), Box> { for path in &["tests/exif.jpg", "tests/exif.tif"] { let file = File::open(path)?; let mut bufreader = BufReader::new(&file); let exifreader = Reader::new(); let exif = exifreader.read_from_container(&mut bufreader)?; for f in exif.fields() { println!("{} {} {}", f.tag, f.ifd_num, f.display_value().with_unit(&exif)); } } Ok(()) } ``` -------------------------------- ### Handling EXIF Field IFD Numbers (Rust) Source: https://docs.rs/kamadak-exif/latest/exif/doc/upgrade/index Shows how to differentiate between primary, thumbnail, and other IFD data associated with an EXIF field using a match expression on `field.ifd_num`. ```Rust match field.ifd_num { In::PRIMARY => {}, // for the primary image In::THUMBNAIL => {}, // for the thumbnail image _ => {}, } ``` -------------------------------- ### Display Formatting for Rational (Rust) Source: https://docs.rs/kamadak-exif/latest/src/exif/value Tests the `Display` formatting for the `Rational` struct. It verifies that rational numbers are correctly formatted as 'numerator/denominator', including edge cases like max value and basic examples with padding. ```rust #[test] fn rational_fmt_display() { let r = Rational::from((u32::max_value(), u32::max_value())); assert_eq!(format!("{}", r), "4294967295/4294967295"); let r = Rational::from((10, 20)); assert_eq!(format!("{}", r), "10/20"); assert_eq!(format!("{:11}", r), " 10/20"); assert_eq!(format!("{:3}", r), "10/20"); } ``` -------------------------------- ### Display EXIF Field Value with Unit (Rust) Source: https://docs.rs/kamadak-exif/latest/src/exif/doc Illustrates how to display an EXIF field's value, optionally including its unit. The `with_unit()` method can use data from the `Reader` if the unit depends on other fields. This example requires the `exif` crate. ```Rust # let file = std::fs::File::open("tests/exif.tif").unwrap(); # let reader = exif::Reader::new( # &mut std::io::BufReader::new(&file)).unwrap(); # let field = reader.fields().next().unwrap(); // Display the value only. println!("{}", field.display_value()); // Display the value with its unit. If the unit depends on another // field, it is taken from the reader. println!("{}", field.display_value().with_unit(&reader)); ``` -------------------------------- ### Accessing EXIF Fields with Primary/Thumbnail (Rust) Source: https://docs.rs/kamadak-exif/latest/exif/doc/upgrade/index Illustrates how to specify whether to retrieve primary or thumbnail EXIF image data using the `In` enum, replacing the previous boolean parameter in `Reader::get_field`. It also shows how to access IFDs beyond the primary or thumbnail. ```Rust reader.get_field(Tag::DateTime, In::PRIMARY) ``` ```Rust reader.get_field(Tag::ImageWidth, In(2)) ``` -------------------------------- ### Accessing EXIF Fields: Primary vs. Thumbnail (Rust) Source: https://docs.rs/kamadak-exif/latest/src/exif/doc Illustrates how to access EXIF fields, differentiating between primary and thumbnail images. The upgrade guide shows the transition from using a boolean flag in 0.3.x to using the `In` enum with `Tag::DateTime` and `In(2)` for secondary IFDs in 0.4.x. It also provides a `match` statement example for distinguishing primary and thumbnail fields. ```rust # use exif::{In, Reader, Tag}; # let file = std::fs::File::open("tests/exif.tif").unwrap(); # let reader = Reader::new( # &mut std::io::BufReader::new(&file)).unwrap(); reader.get_field(Tag::DateTime, In::PRIMARY) # ; ``` ```rust # use exif::{In, Reader, Tag}; # let file = std::fs::File::open("tests/exif.tif").unwrap(); # let reader = Reader::new( # &mut std::io::BufReader::new(&file)).unwrap(); reader.get_field(Tag::ImageWidth, In(2)) # ; ``` ```rust # use exif::{In, Reader}; # let file = std::fs::File::open("tests/exif.tif").unwrap(); # let exif = Reader::new().read_from_container( # &mut std::io::BufReader::new(&file)).unwrap(); # let field = exif.fields().next().unwrap(); match field.ifd_num { In::PRIMARY => {}, // for the primary image In::THUMBNAIL => {}, // for the thumbnail image } ``` -------------------------------- ### Check for JPEG Signature - Rust Source: https://docs.rs/kamadak-exif/latest/src/exif/jpeg This function determines if a given byte slice starts with the standard JPEG Start of Image (SOI) marker. It's a simple and efficient way to validate if a buffer contains JPEG data. ```rust /// SOI marker as the JPEG header. const JPEG_SIG: [u8; 2] = [0xff, 0xd8]; pub fn is_jpeg(buf: &[u8]) -> bool { buf.starts_with(&JPEG_SIG) } ``` -------------------------------- ### Rust Writer::new Method Source: https://docs.rs/kamadak-exif/latest/src/exif/writer Provides a constructor for the `Writer` struct. It initializes an empty `Writer` with an empty `ifd_list`, ready to have Exif fields added. ```Rust impl<'a> Writer<'a> { /// Constructs an empty `Writer`. pub fn new() -> Writer<'a> { Writer { ifd_list: Vec::new(), } } // ... ``` -------------------------------- ### Write Primary, Thumbnail, and Second EXIF Data (Rust) Source: https://docs.rs/kamadak-exif/latest/src/exif/writer Demonstrates writing EXIF data with fields designated for primary, thumbnail, and a second image data interpretation (IFD). This involves defining three `ImageDescription` fields for different IFDs and then writing the buffer. The output is asserted against an expected byte sequence. Dependencies include `rs_kamadak_exif::writer::Writer`, `rs_kamadak_exif::tags::Tag`, `rs_kamadak_exif::types::Value`, `rs_kamadak_exif::scope::In`, and `std::io::Cursor`. ```Rust #[test] fn primary_thumbnail_and_2nd() { let desc0 = Field { tag: Tag::ImageDescription, ifd_num: In::PRIMARY, value: Value::Ascii(vec![b"p".to_vec()]), }; let desc1 = Field { tag: Tag::ImageDescription, ifd_num: In::THUMBNAIL, value: Value::Ascii(vec![b"t".to_vec()]), }; let desc2 = Field { tag: Tag::ImageDescription, ifd_num: In(2), value: Value::Ascii(vec![b"2".to_vec()]), }; let mut writer = Writer::new(); let mut buf = Cursor::new(Vec::new()); writer.push_field(&desc0); writer.push_field(&desc1); writer.push_field(&desc2); writer.write(&mut buf, false).unwrap(); let expected: &[u8] = b"\x4d\x4d\x00\x2a\x00\x00\x00\x08\ \x00\x01\x01\x0e\x00\x02\x00\x00\x00\x02p\x00\x00\x00\ \x00\x00\x00\x1a\ \x00\x01\x01\x0e\x00\x02\x00\x00\x00\x02t\x00\x00\x00\"; } ``` -------------------------------- ### Getting Unsigned Integers from UIntValue in Rust Source: https://docs.rs/kamadak-exif/latest/src/exif/value The `get` method on `UIntValue` retrieves an unsigned integer at a specified index. It handles `Byte`, `Short`, and `Long` types, converting them to `u32`. If the index is out of bounds for the underlying data, it returns `None`. This method assumes the `UIntValue` was correctly constructed and will panic if called on an unexpected `Value` variant. ```rust @inline pub fn get(&self, index: usize) -> Option { match self.0 { Value::Byte(ref v) => v.get(index).map(|&x| x.into()), Value::Short(ref v) => v.get(index).map(|&x| x.into()), Value::Long(ref v) => v.get(index).map(|&x| x), _ => panic!(), } } ``` -------------------------------- ### Check TIFF Signature - Rust Source: https://docs.rs/kamadak-exif/latest/src/exif/tiff Determines if a byte buffer starts with a valid TIFF signature (either big-endian or little-endian). ```rust pub fn is_tiff(buf: &[u8]) -> bool { buf.starts_with(&TIFF_BE_SIG) || buf.starts_with(&TIFF_LE_SIG) } ``` -------------------------------- ### Write TIFF Strip Thumbnail EXIF Data (Rust) Source: https://docs.rs/kamadak-exif/latest/src/exif/writer Demonstrates writing EXIF data with TIFF strips as a thumbnail. This involves defining the strips, setting them in the writer for the thumbnail, and then writing the buffer. The output is compared against an expected byte sequence. Dependencies include `rs_kamadak_exif::writer::Writer`, `rs_kamadak_exif::tags::Tag`, `rs_kamadak_exif::types::Value`, `rs_kamadak_exif::scope::In`, and `std::io::Cursor`. ```Rust #[test] fn thumbnail_tiff() { // This is not a valid TIFF strip (only for testing). let desc = Field { tag: Tag::ImageDescription, ifd_num: In::PRIMARY, value: Value::Ascii(vec![b"tif".to_vec()]), }; let strips: &[&[u8]] = &[b"STRIP"]; let mut writer = Writer::new(); let mut buf = Cursor::new(Vec::new()); writer.push_field(&desc); writer.set_strips(strips, In::THUMBNAIL); writer.write(&mut buf, false).unwrap(); let expected: &[u8] = b"\x4d\x4d\x00\x2a\x00\x00\x00\x08\ \x00\x01\x01\x0e\x00\x02\x00\x00\x00\x04tif\x00\ \x00\x00\x00\x1a\ \x00\x02\x01\x11\x00\x04\x00\x00\x00\x01\x00\x00\x00\x38\ \x01\x17\x00\x04\x00\x00\x00\x01\x00\x00\x00\x05\ \x00\x00\x00\x00\ STRIP"; assert_eq!(buf.into_inner(), expected); } ``` -------------------------------- ### Define Device Setting Description EXIF Tag Source: https://docs.rs/kamadak-exif/latest/src/exif/tag Defines the 'Device settings description' EXIF tag (0xa40b). It uses a default formatter and expects no specific units, typically storing a description of device settings. ```Rust (DeviceSettingDescription, 0xa40b, DefaultValue::None, d_default, unit![], "Device settings description"), ``` -------------------------------- ### Writer Struct and Methods Source: https://docs.rs/kamadak-exif/latest/exif/experimental/struct This section details the `Writer` struct, its constructor, methods for adding fields, setting image data, and writing Exif data. ```APIDOC ## Struct Writer ### Description The `Writer` struct is used to encode and write Exif data. ### Methods #### `new()` * **Description**: Constructs an empty `Writer`. * **Method**: `new()` * **Returns**: `Writer<'a>` #### `push_field()` * **Description**: Appends a field to be written. Fields can be appended in any order. Duplicate fields must not be appended. Certain fields like `ExifIFDPointer`, `GPSInfoIFDPointer`, etc., are ignored and synthesized when needed. * **Method**: `push_field(&mut self, field: &'a Field)` * **Parameters**: * `field` (*Field*) - The Exif field to append. #### `set_strips()` * **Description**: Sets TIFF strips for the specified IFD. If called multiple times, the last call prevails. * **Method**: `set_strips(&mut self, strips: &'a [&'a [u8]], ifd_num: In)` * **Parameters**: * `strips` (*&[&[u8]]*) - A slice of byte slices representing the TIFF strips. * `ifd_num` (*In*) - The Image File Directory number. #### `set_tiles()` * **Description**: Sets TIFF tiles for the specified IFD. If called multiple times, the last call prevails. * **Method**: `set_tiles(&mut self, tiles: &'a [&'a [u8]], ifd_num: In)` * **Parameters**: * `tiles` (*&[&[u8]]*) - A slice of byte slices representing the TIFF tiles. * `ifd_num` (*In*) - The Image File Directory number. #### `set_jpeg()` * **Description**: Sets JPEG data for the specified IFD. If called multiple times, the last call prevails. * **Method**: `set_jpeg(&mut self, jpeg: &'a [u8], ifd_num: In)` * **Parameters**: * `jpeg` (*&[u8]*) - A byte slice representing the JPEG data. * `ifd_num` (*In*) - The Image File Directory number. #### `write()` * **Description**: Encodes Exif data and writes it into the provided writer `w`. The write position of `w` must be set to zero before calling this method. * **Method**: `write(&mut self, w: &mut W, little_endian: bool) -> Result<(), Error>` * **Parameters**: * `w` (*W*) - A mutable reference to a type implementing `Write` and `Seek`. * `little_endian` (*bool*) - A boolean indicating whether to use little-endian encoding. * **Returns**: `Result<(), Error>` ### Request Example ```rust use exif::{Field, In, Tag, Value}; use exif::experimental::Writer; let image_desc = Field { tag: Tag::ImageDescription, ifd_num: In::PRIMARY, value: Value::Ascii(vec![b"Sample".to_vec()]) }; let mut writer = Writer::new(); let mut buf = std::io::Cursor::new(Vec::new()); writer.push_field(&image_desc); writer.write(&mut buf, false)?; let expected: &[u8] = b"\x4d\x4d\x00\x2a\x00\x00\x00\x08\x00\x01\x01\x0e\x00\x02\x00\x00\x00\x07\x00\x00\x00\x1a\x00\x00\x00\x00Sample\0"; assert_eq!(buf.into_inner(), expected); ``` ### Response #### Success Response (200) * The `write` method does not return a specific success response body, but rather a `Result<(), Error>`. A successful write operation results in `Ok(())`. #### Response Example * No direct response body for the `write` operation. The output is written to the provided `W` implementor. ``` -------------------------------- ### Write Primary, Thumbnail, and Secondary EXIF Data (Rust) Source: https://docs.rs/kamadak-exif/latest/src/exif/writer Demonstrates writing EXIF data that includes fields for the primary IFD, thumbnail IFD, and a second IFD. This involves defining multiple `Field` instances with different tags and IFD numbers, then pushing them to the writer before writing the buffer. Assertions verify the resulting byte output. Dependencies: `rs_kamadak_exif::writer::Writer`, `rs_kamadak_exif::tags::Tag`, `rs_kamadak_exif::types::Value`, `rs_kamadak_exif::scope::In`, and `std::io::Cursor`. ```Rust #[test] fn primary_and_thumbnail() { let image_desc = Field { tag: Tag::ImageDescription, ifd_num: In::PRIMARY, value: Value::Ascii(vec![b"Sample".to_vec()]), }; let exif_ver = Field { tag: Tag::ExifVersion, ifd_num: In::PRIMARY, value: Value::Undefined(b"0231".to_vec(), 0), }; let gps_ver = Field { tag: Tag::GPSVersionID, ifd_num: In::PRIMARY, value: Value::Byte(vec![2, 3, 0, 0]), }; let interop_index = Field { tag: Tag::InteroperabilityIndex, ifd_num: In::PRIMARY, value: Value::Ascii(vec![b"ABC".to_vec()]), }; let jpeg = b"JPEG"; let mut writer = Writer::new(); let mut buf = Cursor::new(Vec::new()); writer.push_field(&image_desc); writer.push_field(&exif_ver); writer.push_field(&gps_ver); writer.push_field(&interop_index); writer.set_jpeg(jpeg, In::THUMBNAIL); writer.write(&mut buf, false).unwrap(); let expected: &[u8] = b"\x4d\x4d\x00\x2a\x00\x00\x00\x08\ \x00\x03\x01\x0e\x00\x02\x00\x00\x00\x07\x00\x00\x00\x74\ \x87\x69\x00\x04\x00\x00\x00\x01\x00\x00\x00\x32\ \x88\x25\x00\x04\x00\x00\x00\x01\x00\x00\x00\x50\ \x00\x00\x00\x7c\ \x00\x02\x90\x00\x00\x07\x00\x00\x00\x040231\ \xa0\x05\x00\x04\x00\x00\x00\x01\x00\x00\x00\x62\ \x00\x00\x00\x00\ \x00\x01\x00\x00\x00\x01\x00\x00\x00\x04\x02\x03\x00\x00\ \x00\x00\x00\x00\ \x00\x01\x00\x01\x00\x02\x00\x00\x00\x04ABC\0\ \x00\x00\x00\x00\ Sample\0\0\ \x00\x02\x02\x01\x00\x04\x00\x00\x00\x01\x00\x00\x00\x9a\ \x02\x02\x00\x04\x00\x00\x00\x01\x00\x00\x00\x04\ \x00\x00\x00\x00\ JPEG"; assert_eq!(buf.into_inner(), expected); } ``` -------------------------------- ### Implement Tag methods in Rust Source: https://docs.rs/kamadak-exif/latest/src/exif/tag This code implements methods for the `Tag` struct to retrieve the context, number, description, and default value of a tag. These methods provide access to the tag's properties and allow for easy manipulation and display of tag information. ```Rust impl Tag { /// Returns the context of the tag. #[inline] pub fn context(self) -> Context { self.0 } /// Returns the tag number. #[inline] pub fn number(self) -> u16 { self.1 } /// Returns the description of the tag. #[inline] pub fn description(&self) -> Option<&str> { get_tag_info(*self).map(|ti| ti.desc) } /// Returns the default value of the tag. `None` is returned if /// it is not defined in the standard or it depends on another tag. #[inline] pub fn default_value(&self) -> Option { get_tag_info(*self).and_then(|ti| (&ti.default).into()) } pub(crate) fn unit(self) -> Option<&'static [UnitPiece]> { get_tag_info(self).and_then(|ti| ti.unit) } } ``` -------------------------------- ### Configure Exif Reader to Continue on Error in Rust Source: https://docs.rs/kamadak-exif/latest/src/exif/reader Shows how to create an `Exif` reader and enable the `continue_on_error` option. This allows the parser to proceed even if non-fatal errors are encountered, returning partial results if necessary. Error handling for partial results using `distill_partial_result` is also demonstrated. ```rust use exif::Reader; use std::fs::File; use std::io::BufReader; fn main() -> std::result::Result<(), Box> { let file = File::open("tests/exif.jpg")?; let exif = Reader::new() .continue_on_error(true) .read_from_container(&mut BufReader::new(&file)) .or_else(|e| e.distill_partial_result(|errors| { errors.iter().for_each(|e| eprintln!("Warning: {}", e)); }))?; Ok(()) } ``` -------------------------------- ### Read EXIF Data and Display Fields in Rust Source: https://docs.rs/kamadak-exif/latest/src/reading/reading This Rust code snippet demonstrates how to open a JPEG file, read its EXIF metadata using the kamadak-exif crate, and then iterate through a predefined list of tags to print their values. It shows basic usage of `File::open`, `BufReader`, and `Reader::new().read_from_container`. It also illustrates how to retrieve fields by tag and display their values with units. ```rust extern crate exif; use std::fs::File; use std::io::BufReader; use exif::{DateTime, In, Reader, Value, Tag}; fn main() { let file = File::open("tests/exif.jpg").unwrap(); let exif = Reader::new().read_from_container( &mut BufReader::new(&file)).unwrap(); // To obtain a string representation, `Value::display_as` // or `Field::display_value` can be used. To display a value with its // unit, call `with_unit` on the return value of `Field::display_value`. let tag_list = [Tag::ExifVersion, Tag::PixelXDimension, Tag::XResolution, Tag::ImageDescription, Tag::DateTime]; for tag in tag_list { if let Some(field) = exif.get_field(tag, In::PRIMARY) { println!("{}: {}", field.tag, field.display_value().with_unit(&exif)); } } // To get unsigned integer value(s) from either of BYTE, SHORT, // or LONG, `Value::get_uint` or `Value::iter_uint` can be used. if let Some(field) = exif.get_field(Tag::PixelXDimension, In::PRIMARY) { if let Some(width) = field.value.get_uint(0) { println!("Valid width of the image is {}.", width); } } // To convert a Rational or SRational to an f64, `Rational::to_f64` // or `SRational::to_f64` can be used. if let Some(field) = exif.get_field(Tag::XResolution, In::PRIMARY) { match field.value { Value::Rational(ref vec) if !vec.is_empty() => println!("X resolution is {}.", vec[0].to_f64()), _ => {}, } } // To parse a DateTime-like field, `DateTime::from_ascii` can be used. if let Some(field) = exif.get_field(Tag::DateTime, In::PRIMARY) { match field.value { Value::Ascii(ref vec) if !vec.is_empty() => { if let Ok(datetime) = DateTime::from_ascii(&vec[0]) { println!("Year of DateTime is {}.", datetime.year); } }, _ => {}, } } } ``` -------------------------------- ### Write Exif Data using kamadak-exif Writer Source: https://docs.rs/kamadak-exif/latest/exif/experimental/struct Demonstrates how to use the `Writer` struct from the `kamadak-exif` crate to encode and write Exif data to a buffer. It shows the creation of a `Writer`, appending a field, and writing the data to an in-memory buffer. ```rust use exif::{Field, In, Tag, Value}; use exif::experimental::Writer; use std::io::Write; let image_desc = Field { tag: Tag::ImageDescription, ifd_num: In::PRIMARY, value: Value::Ascii(vec![b"Sample".to_vec()]), }; let mut writer = Writer::new(); let mut buf = std::io::Cursor::new(Vec::new()); writer.push_field(&image_desc); writer.write(&mut buf, false)?; static expected: &[u8] = b"\x4d\x4d\x00\x2a\x00\x00\x00\x08\x00\x01\x01\x0e\x00\x02\x00\x00\x00\x07\x00\x00\x00\x1a\x00\x00\x00\x00\nSample\0"; assert_eq!(buf.into_inner(), expected); ``` -------------------------------- ### Check if Buffer is WebP in Rust Source: https://docs.rs/kamadak-exif/latest/src/exif/webp This function `is_webp` checks if a given byte slice starts with the characteristic RIFF and WEBP identifiers, indicating it's likely a WebP file. It requires a minimum buffer length of 12 bytes. ```Rust // Chunk identifiers for RIFF. const FCC_RIFF: [u8; 4] = *b"RIFF"; const FCC_WEBP: [u8; 4] = *b"WEBP"; pub fn is_webp(buf: &[u8]) -> bool { buf.len() >= 12 && buf[0..4] == FCC_RIFF && buf[8..12] == FCC_WEBP } ``` -------------------------------- ### Get Tag Default Value (Rust) Source: https://docs.rs/kamadak-exif/latest/exif/struct Retrieves the default value for a given `Tag`, if one is defined in the standard and does not depend on other tags. This function returns an `Option`, allowing access to predefined defaults. Returns `None` if the default is not specified or is conditional. ```rust pub fn default_value(&self) -> Option ``` -------------------------------- ### Format Sub-Commands for EXIF Value Display in Rust Source: https://docs.rs/kamadak-exif/latest/src/exif/tag Demonstrates the use of helper functions to format various types of EXIF values into a string buffer. Includes formatting for unsigned integers, rationals, floating-point numbers derived from rationals, hexadecimal byte strings, and escaped ASCII strings. ```Rust let mut buf = String::new(); d_sub_comma(&mut buf, &[0u16, 1, 2]).unwrap(); assert_eq!(buf, "0, 1, 2"); let mut buf = String::new(); d_sub_comma(&mut buf, &[Rational::from((3, 5))]).unwrap(); assert_eq!(buf, "3/5"); let mut buf = String::new(); let list = &[Rational::from((1, 2))]; d_sub_comma(&mut buf, list.iter().map(|x| x.to_f64())).unwrap(); assert_eq!(buf, "0.5"); let mut buf = String::new(); d_sub_hex(&mut buf, b"abc\x00\xff").unwrap(); assert_eq!(buf, "0x61626300ff"); let mut buf = String::new(); d_sub_ascii(&mut buf, b"a \"\\b\"\n").unwrap(); assert_eq!(buf, r#""a \"\\b\"\x0a""#); ``` -------------------------------- ### Get Unsigned Integer from Value (Rust) Source: https://docs.rs/kamadak-exif/latest/src/exif/value Tests the `get_uint` method for retrieving specific unsigned integers from Value variants (Byte, Short, Long, SLong) at a given index. It verifies correct retrieval and handling of out-of-bounds indices. ```rust #[test] fn get_uint() { let v = Value::Byte(vec![1, 2]); assert_eq!(v.get_uint(0), Some(1)); assert_eq!(v.get_uint(1), Some(2)); assert_eq!(v.get_uint(2), None); let v = Value::Short(vec![1, 2]); assert_eq!(v.get_uint(0), Some(1)); assert_eq!(v.get_uint(1), Some(2)); assert_eq!(v.get_uint(2), None); let v = Value::Long(vec![1, 2]); assert_eq!(v.get_uint(0), Some(1)); assert_eq!(v.get_uint(1), Some(2)); assert_eq!(v.get_uint(2), None); let v = Value::SLong(vec![1, 2]); assert_eq!(v.get_uint(0), None); assert_eq!(v.get_uint(1), None); assert_eq!(v.get_uint(2), None); } ``` -------------------------------- ### Get Tag Number (Rust) Source: https://docs.rs/kamadak-exif/latest/exif/struct Returns the numerical identifier (`u16`) of a TIFF/Exif tag. Each tag has a unique number within its context, allowing for precise data retrieval. This function is essential for programmatically accessing specific metadata fields based on their numerical representation. ```rust pub fn number(self) -> u16 { // ... implementation ... } // Example usage: // assert_eq!(Tag::XResolution.number(), 0x11a); // assert_eq!(Tag::DateTimeOriginal.number(), 0x9003); ``` -------------------------------- ### Check PNG Signature in Rust Source: https://docs.rs/kamadak-exif/latest/src/exif/png This function determines if a given byte slice starts with the standard PNG file signature. It's a simple check useful for preliminary validation of file types. It takes a byte slice as input and returns a boolean. ```Rust // PNG file signature [PNG12 12.12]. const PNG_SIG: [u8; 8] = *b"\x89PNG\x0d\x0a\x1a\x0a"; pub fn is_png(buf: &[u8]) -> bool { buf.starts_with(&PNG_SIG) } ``` -------------------------------- ### Predefined TIFF/Exif Tags (Rust) Source: https://docs.rs/kamadak-exif/latest/exif/struct Lists predefined `Tag` constants for common TIFF and Exif fields. These constants provide convenient access to standard metadata tags like `ImageWidth`, `Make`, `Model`, `DateTimeOriginal`, and many others. They simplify the process of reading and writing specific image metadata. ```rust pub const ImageWidth: Tag pub const ImageLength: Tag pub const BitsPerSample: Tag // ... many other constants like Make, Model, DateTimeOriginal, etc. ``` -------------------------------- ### Get Current Offset in TIFF Writer (Rust) Source: https://docs.rs/kamadak-exif/latest/src/exif/writer Retrieves the current offset within a TIFF writer. It includes a check to ensure the offset fits within a `u32`, returning an error if it exceeds the limit. This function is useful for tracking positions during TIFF data serialization. ```Rust fn get_offset(w: &mut W) -> Result where W: Write + Seek { let pos = w.seek(SeekFrom::Current(0))?; if pos as u32 as u64 != pos { return Err(Error::TooBig("Offset too large")); } Ok(pos as u32) } ``` -------------------------------- ### BoxSplitter Utilities in Rust Source: https://docs.rs/kamadak-exif/latest/src/exif/isobmff Provides utility methods for the `BoxSplitter` struct, which is used to parse byte slices representing boxes within the HEIF file format. It includes methods for checking emptiness, getting length, and parsing child boxes. ```rust struct BoxSplitter<'a> { inner: &'a [u8], } impl<'a> BoxSplitter<'a> { fn new(slice: &'a [u8]) -> BoxSplitter<'a> { Self { inner: slice } } fn is_empty(&self) -> bool { self.inner.is_empty() } fn len(&self) -> usize { self.inner.len() } // Returns type and body. fn child_box(&mut self) -> Result<(&'a [u8], BoxSplitter<'a>), Error> { let size = self.uint32()? as usize; let boxtype = self.slice(4)?; let body_len = match size { 0 => Some(self.len()), 1 => usize::try_from(self.uint64()?) .or(Err("Box is larger than the address space"))? \ .checked_sub(16), _ => size.checked_sub(8), }; // ... rest of the function } } ``` -------------------------------- ### Test Writing TIFF Tiled Data (Rust) Source: https://docs.rs/kamadak-exif/latest/src/exif/writer Unit test for setting and writing tiled data within a TIFF writer. It simulates the structure of tiled image data and asserts the correctness of the generated byte output, including IFD entries for tile-related tags. ```Rust #[test] fn primary_tiff_tiled() { // This is not a valid TIFF tile (only for testing). let tiles: &[&[u8]] = &[b"TILE"]; let mut writer = Writer::new(); let mut buf = Cursor::new(Vec::new()); writer.set_tiles(tiles, In::PRIMARY); writer.write(&mut buf, false).unwrap(); let expected: &[u8] = b"\x4d\x4d\x00\x2a\x00\x00\x00\x08\ \x00\x02\x01\x44\x00\x04\x00\x00\x00\x01\x00\x00\x00\x26\ \x01\x45\x00\x04\x00\x00\x00\x01\x00\x00\x00\x04\ \x00\x00\x00\ TILE"; assert_eq!(buf.into_inner(), expected); } ``` -------------------------------- ### Write JPEG Thumbnail EXIF Data (Rust) Source: https://docs.rs/kamadak-exif/latest/src/exif/writer Demonstrates writing EXIF data with a JPEG thumbnail. It involves creating a writer, setting the JPEG data for the thumbnail, and then writing the buffer. The expected byte output is asserted to ensure correctness. Dependencies include `rs_kamadak_exif::writer::Writer`, `rs_kamadak_exif::tags::Tag`, `rs_kamadak_exif::types::Value`, `rs_kamadak_exif::scope::In`, and `std::io::Cursor`. ```Rust #[test] fn thumbnail_jpeg() { let desc = Field { tag: Tag::ImageDescription, ifd_num: In::PRIMARY, value: Value::Ascii(vec![b"jpg".to_vec()]), }; let jpeg = b"JPEG"; let mut writer = Writer::new(); let mut buf = Cursor::new(Vec::new()); writer.push_field(&desc); writer.set_jpeg(jpeg, In::THUMBNAIL); writer.write(&mut buf, false).unwrap(); let expected: &[u8] = b"\x4d\x4d\x00\x2a\x00\x00\x00\x08\ \x00\x01\x01\x0e\x00\x02\x00\x00\x00\x04jpg\x00\ \x00\x00\x00\x1a\ \x00\x02\x02\x01\x00\x04\x00\x00\x00\x01\x00\x00\x00\x38\ \x02\x02\x00\x04\x00\x00\x00\x01\x00\x00\x00\x04\ \x00\x00\x00\x00\ JPEG"; assert_eq!(buf.into_inner(), expected); } ``` -------------------------------- ### Get Tag Context (Rust) Source: https://docs.rs/kamadak-exif/latest/exif/struct Retrieves the `Context` (e.g., TIFF or Exif) associated with a given `Tag`. This function is useful for understanding the namespace or standard to which the tag belongs, aiding in correct interpretation and processing of Exif data. It leverages associated constants for predefined tags. ```rust pub fn context(self) -> Context { // ... implementation ... } // Example usage: // assert_eq!(Tag::XResolution.context(), Context::Tiff); // assert_eq!(Tag::DateTimeOriginal.context(), Context::Exif); ``` -------------------------------- ### Parse Exif Attributes from Image Files (Rust) Source: https://docs.rs/kamadak-exif/latest/exif/index This snippet demonstrates how to open image files (JPEG, TIFF), read their Exif data using a BufReader and exif::Reader, and iterate through the fields to display their tags, IFD numbers, and formatted values. It handles potential errors during file opening and Exif reading. ```Rust for path in &["tests/exif.jpg", "tests/exif.tif"] { let file = std::fs::File::open(path)?; let mut bufreader = std::io::BufReader::new(&file); let exifreader = exif::Reader::new(); let exif = exifreader.read_from_container(&mut bufreader)?; for f in exif.fields() { println!("{} {} {}", f.tag, f.ifd_num, f.display_value().with_unit(&exif)); } } ``` -------------------------------- ### Reserve Space for TIFF IFD in Rust Source: https://docs.rs/kamadak-exif/latest/src/exif/writer The `reserve_ifd` function advances the writer's position to create space for a new Image File Directory (IFD) and returns the calculated offset for this new IFD. It ensures the offset is word-aligned and accounts for the IFD entry count, IFD entries, and the pointer to the next IFD. ```rust fn reserve_ifd(w: &mut W, count: usize) -> Result where W: Write + Seek { let ifdpos = get_offset(w)?; assert!(ifdpos % 2 == 0); // The number of entries (2) + array of entries (12 * n) + // the next IFD pointer (4). w.seek(SeekFrom::Current(2 + count as i64 * 12 + 4))?; Ok(ifdpos) } ```