@@ -12,6 +12,45 @@ pub struct Dimensions {
12
12
pub height : u16 ,
13
13
}
14
14
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
+
15
54
#[ derive( Clone , Copy , Debug , PartialEq ) ]
16
55
pub enum EntropyCoding {
17
56
Huffman ,
@@ -65,7 +104,7 @@ pub struct Component {
65
104
#[ derive( Debug ) ]
66
105
pub enum AppData {
67
106
Adobe ( AdobeColorTransform ) ,
68
- Jfif ,
107
+ Jfif ( JfifApp0 ) ,
69
108
Avi1 ,
70
109
}
71
110
@@ -472,6 +511,43 @@ pub fn parse_com<R: Read>(reader: &mut R) -> Result<Vec<u8>> {
472
511
Ok ( buffer)
473
512
}
474
513
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
+
475
551
// Section B.2.4.6
476
552
pub fn parse_app < R : Read > ( reader : & mut R , marker : Marker ) -> Result < Option < AppData > > {
477
553
let length = read_length ( reader, marker) ?;
@@ -487,7 +563,9 @@ pub fn parse_app<R: Read>(reader: &mut R, marker: Marker) -> Result<Option<AppDa
487
563
488
564
// http://www.w3.org/Graphics/JPEG/jfif3.pdf
489
565
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) ) ;
491
569
// https://sno.phy.queensu.ca/~phil/exiftool/TagNames/JPEG.html#AVI1
492
570
} else if & buffer[ 0 .. 5 ] == & [ b'A' , b'V' , b'I' , b'1' , b'\0' ] {
493
571
result = Some ( AppData :: Avi1 ) ;
0 commit comments