@@ -12,6 +12,44 @@ pub struct Dimensions {
1212 pub height : u16 ,
1313}
1414
15+ /// The image density, in x and y directions with a common unit
16+ #[ derive( Clone , Copy , Debug , PartialEq ) ]
17+ pub struct Density {
18+ /// The pixel density, measured in `units`, in the x direction
19+ pub x : u16 ,
20+ /// The pixel density, measured in `units`, in the y direction
21+ pub y : u16 ,
22+ /// The unit of measurement that both `x` and `y` are specified in.
23+ pub units : DensityUnits ,
24+ }
25+
26+ /// The different units that `x` and `y` pixel density can be measured in
27+ #[ derive( Clone , Copy , Debug , PartialEq ) ]
28+ pub enum DensityUnits {
29+ /// no units, `x` and `y` specify the pixel aspect ratio
30+ PixelAspectRatio ,
31+ /// `x` and `y` are dots per inch
32+ DotsPerInch ,
33+ /// `x` and `y` are dots per cm
34+ DotsPerCm ,
35+ }
36+
37+ #[ derive( Clone , Copy , Debug , PartialEq ) ]
38+ struct Thumbnail {
39+ pub width : u8 ,
40+ pub height : u8 ,
41+ // XXX: Thumbnail data is "(3n bytes) Packed (24-bit) RGB values for the thumbnail
42+ // pixels, n = Xthumbnail * Ythumbnail".
43+ data : std:: marker:: PhantomData < ( ) > ,
44+ }
45+
46+ #[ derive( Clone , Copy , Debug , PartialEq ) ]
47+ pub struct JfifApp0 {
48+ // version: &[u8; 4],
49+ pub density : Density ,
50+ thumbnail : Thumbnail ,
51+ }
52+
1553#[ derive( Clone , Copy , Debug , PartialEq ) ]
1654pub enum EntropyCoding {
1755 Huffman ,
@@ -65,7 +103,7 @@ pub struct Component {
65103#[ derive( Debug ) ]
66104pub enum AppData {
67105 Adobe ( AdobeColorTransform ) ,
68- Jfif ,
106+ Jfif ( JfifApp0 ) ,
69107 Avi1 ,
70108}
71109
@@ -472,6 +510,44 @@ pub fn parse_com<R: Read>(reader: &mut R) -> Result<Vec<u8>> {
472510 Ok ( buffer)
473511}
474512
513+ // https://www.w3.org/Graphics/JPEG/jfif3.pdf
514+ pub fn parse_jfif_app0 < R : Read > ( reader : & mut R , length : usize ) -> Result < JfifApp0 > {
515+ // Total length of APP0 = 16 bytes + 3 * n, where n = Xthumbnail * Ythumbnail
516+ // We already read the 2-byte length and 5-byte identifier, so at least 9 bytes remain.
517+ // We are going to ignore the thumbnail for now.
518+ if length < 9 {
519+ return Err ( Error :: Format ( "JFIF APP0 with invalid length" . to_owned ( ) ) ) ;
520+ }
521+
522+ // version = 0x0102
523+ skip_bytes ( reader, 2 ) ?;
524+
525+ let units = match reader. read_u8 ( ) ? {
526+ 0 => DensityUnits :: PixelAspectRatio ,
527+ 1 => DensityUnits :: DotsPerInch ,
528+ 2 => DensityUnits :: DotsPerCm ,
529+ _ => return Err ( Error :: Format ( "invalid density units in APP0" . to_owned ( ) ) ) ,
530+ } ;
531+ let x_density = reader. read_u16 :: < BigEndian > ( ) ?;
532+ let y_density = reader. read_u16 :: < BigEndian > ( ) ?;
533+
534+ let x_thumbnail = reader. read_u8 ( ) ?;
535+ let y_thumbnail = reader. read_u8 ( ) ?;
536+
537+ Ok ( JfifApp0 {
538+ density : Density {
539+ x : x_density,
540+ y : y_density,
541+ units,
542+ } ,
543+ thumbnail : Thumbnail {
544+ width : x_thumbnail,
545+ height : y_thumbnail,
546+ data : Default :: default ( ) ,
547+ }
548+ } )
549+ }
550+
475551// Section B.2.4.6
476552pub fn parse_app < R : Read > ( reader : & mut R , marker : Marker ) -> Result < Option < AppData > > {
477553 let length = read_length ( reader, marker) ?;
@@ -487,7 +563,9 @@ pub fn parse_app<R: Read>(reader: &mut R, marker: Marker) -> Result<Option<AppDa
487563
488564 // http://www.w3.org/Graphics/JPEG/jfif3.pdf
489565 if & buffer[ 0 .. 5 ] == & [ b'J' , b'F' , b'I' , b'F' , b'\0' ] {
490- result = Some ( AppData :: Jfif ) ;
566+ let jfif = parse_jfif_app0 ( reader, length - bytes_read) ?;
567+ bytes_read += 9 ;
568+ result = Some ( AppData :: Jfif ( jfif) ) ;
491569 // https://sno.phy.queensu.ca/~phil/exiftool/TagNames/JPEG.html#AVI1
492570 } else if & buffer[ 0 .. 5 ] == & [ b'A' , b'V' , b'I' , b'1' , b'\0' ] {
493571 result = Some ( AppData :: Avi1 ) ;
0 commit comments