@@ -12,6 +12,45 @@ 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+
42+ // XXX: Thumbnail data is "(3n bytes) Packed (24-bit) RGB values for the thumbnail
43+ // pixels, n = Xthumbnail * Ythumbnail".
44+ // data: Vec<u8>
45+ }
46+
47+ #[ derive( Clone , Copy , Debug , PartialEq ) ]
48+ pub struct JfifApp0 {
49+ // version: &[u8; 4],
50+ pub density : Density ,
51+ thumbnail : Thumbnail ,
52+ }
53+
1554#[ derive( Clone , Copy , Debug , PartialEq ) ]
1655pub enum EntropyCoding {
1756 Huffman ,
@@ -65,7 +104,7 @@ pub struct Component {
65104#[ derive( Debug ) ]
66105pub enum AppData {
67106 Adobe ( AdobeColorTransform ) ,
68- Jfif ,
107+ Jfif ( JfifApp0 ) ,
69108 Avi1 ,
70109}
71110
@@ -472,6 +511,43 @@ pub fn parse_com<R: Read>(reader: &mut R) -> Result<Vec<u8>> {
472511 Ok ( buffer)
473512}
474513
514+ // https://www.w3.org/Graphics/JPEG/jfif3.pdf
515+ pub fn parse_jfif_app0 < R : Read > ( reader : & mut R , length : usize ) -> Result < JfifApp0 > {
516+ // Total length of APP0 = 16 bytes + 3 * n, where n = Xthumbnail * Ythumbnail
517+ // We already read the 2-byte length and 5-byte identifier, so at least 9 bytes remain.
518+ // We are going to ignore the thumbnail for now.
519+ if length < 9 {
520+ return Err ( Error :: Format ( "JFIF APP0 with invalid length" . to_owned ( ) ) ) ;
521+ }
522+
523+ // version = 0x0102
524+ skip_bytes ( reader, 2 ) ?;
525+
526+ let units = match reader. read_u8 ( ) ? {
527+ 0 => DensityUnits :: PixelAspectRatio ,
528+ 1 => DensityUnits :: DotsPerInch ,
529+ 2 => DensityUnits :: DotsPerCm ,
530+ _ => return Err ( Error :: Format ( "invalid density units in APP0" . to_owned ( ) ) ) ,
531+ } ;
532+ let x_density = reader. read_u16 :: < BigEndian > ( ) ?;
533+ let y_density = reader. read_u16 :: < BigEndian > ( ) ?;
534+
535+ let x_thumbnail = reader. read_u8 ( ) ?;
536+ let y_thumbnail = reader. read_u8 ( ) ?;
537+
538+ Ok ( JfifApp0 {
539+ density : Density {
540+ x : x_density,
541+ y : y_density,
542+ units,
543+ } ,
544+ thumbnail : Thumbnail {
545+ width : x_thumbnail,
546+ height : y_thumbnail,
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