@@ -3,7 +3,8 @@ use error::{Error, Result, UnsupportedFeature};
3
3
use huffman:: { fill_default_mjpeg_tables, HuffmanDecoder , HuffmanTable } ;
4
4
use marker:: Marker ;
5
5
use parser:: { AdobeColorTransform , AppData , CodingProcess , Component , Dimensions , EntropyCoding , FrameInfo ,
6
- parse_app, parse_com, parse_dht, parse_dqt, parse_dri, parse_sof, parse_sos, ScanInfo } ;
6
+ parse_app, parse_com, parse_dht, parse_dqt, parse_dri, parse_sof, parse_sos, IccChunk ,
7
+ ScanInfo } ;
7
8
use upsampler:: Upsampler ;
8
9
use std:: cmp;
9
10
use std:: io:: Read ;
@@ -72,6 +73,8 @@ pub struct Decoder<R> {
72
73
is_jfif : bool ,
73
74
is_mjpeg : bool ,
74
75
76
+ icc_markers : Vec < IccChunk > ,
77
+
75
78
// Used for progressive JPEGs.
76
79
coefficients : Vec < Vec < i16 > > ,
77
80
// Bitmask of which coefficients has been completely decoded.
@@ -91,6 +94,7 @@ impl<R: Read> Decoder<R> {
91
94
color_transform : None ,
92
95
is_jfif : false ,
93
96
is_mjpeg : false ,
97
+ icc_markers : Vec :: new ( ) ,
94
98
coefficients : Vec :: new ( ) ,
95
99
coefficients_finished : [ 0 ; MAX_COMPONENTS ] ,
96
100
}
@@ -120,6 +124,39 @@ impl<R: Read> Decoder<R> {
120
124
}
121
125
}
122
126
127
+ /// Returns the embeded icc profile if the image contains one.
128
+ pub fn icc_profile ( & self ) -> Option < Vec < u8 > > {
129
+ let mut marker_present: [ Option < & IccChunk > ; 256 ] = [ None ; 256 ] ;
130
+ let num_markers = self . icc_markers . len ( ) ;
131
+ if num_markers == 0 && num_markers < 256 {
132
+ return None ;
133
+ }
134
+ // check the validity of the markers
135
+ for chunk in & self . icc_markers {
136
+ if usize:: from ( chunk. num_markers ) != num_markers {
137
+ // all the lengths must match
138
+ return None ;
139
+ }
140
+ if chunk. seq_no == 0 {
141
+ return None ;
142
+ }
143
+ if marker_present[ usize:: from ( chunk. seq_no ) ] . is_some ( ) {
144
+ // duplicate seq_no
145
+ return None ;
146
+ } else {
147
+ marker_present[ usize:: from ( chunk. seq_no ) ] = Some ( chunk) ;
148
+ }
149
+ }
150
+
151
+ // assemble them together by seq_no failing if any are missing
152
+ let mut data = Vec :: new ( ) ;
153
+ // seq_no's start at 1
154
+ for & chunk in marker_present. get ( 1 ..=num_markers) ? {
155
+ data. extend_from_slice ( & chunk?. data ) ;
156
+ }
157
+ Some ( data)
158
+ }
159
+
123
160
/// Tries to read metadata from the image without decoding it.
124
161
///
125
162
/// If successful, the metadata can be obtained using the `info` method.
@@ -336,6 +373,7 @@ impl<R: Read> Decoder<R> {
336
373
self . is_jfif = true ;
337
374
} ,
338
375
AppData :: Avi1 => self . is_mjpeg = true ,
376
+ AppData :: Icc ( icc) => self . icc_markers . push ( icc) ,
339
377
}
340
378
}
341
379
} ,
0 commit comments