@@ -74,6 +74,31 @@ pub struct ImageInfo {
74
74
pub coding_process : CodingProcess ,
75
75
}
76
76
77
+ /// Describes the colour transform to apply before binary data is returned
78
+ #[ derive( Debug , Clone , Copy ) ]
79
+ pub enum ColorTransform {
80
+ /// No transform should be applied and the data is returned as-is.
81
+ None ,
82
+ /// Default colour transform should be applied. If there are 3 channels then YCbCr and if there are 4 then YCCK.
83
+ Default ,
84
+ /// RGB transform should be applied.
85
+ RGB ,
86
+ /// YCbCr transform should be applied.
87
+ YCbCr ,
88
+ /// CMYK transform should be applied.
89
+ CMYK ,
90
+ /// YCCK transform should be applied.
91
+ YCCK ,
92
+ /// Use the colour transform specified in the Adobe extended tag
93
+ AdobeColorTransform ( AdobeColorTransform ) ,
94
+ }
95
+
96
+ impl Default for ColorTransform {
97
+ fn default ( ) -> Self {
98
+ ColorTransform :: Default
99
+ }
100
+ }
101
+
77
102
/// JPEG decoder
78
103
pub struct Decoder < R > {
79
104
reader : R ,
@@ -84,7 +109,7 @@ pub struct Decoder<R> {
84
109
quantization_tables : [ Option < Arc < [ u16 ; 64 ] > > ; 4 ] ,
85
110
86
111
restart_interval : u16 ,
87
- color_transform : Option < AdobeColorTransform > ,
112
+ color_transform : ColorTransform ,
88
113
is_jfif : bool ,
89
114
is_mjpeg : bool ,
90
115
@@ -111,7 +136,8 @@ impl<R: Read> Decoder<R> {
111
136
ac_huffman_tables : vec ! [ None , None , None , None ] ,
112
137
quantization_tables : [ None , None , None , None ] ,
113
138
restart_interval : 0 ,
114
- color_transform : None ,
139
+ // Set the default transform as unknown. This can be overriden using `set_color_transform`
140
+ color_transform : ColorTransform :: default ( ) ,
115
141
is_jfif : false ,
116
142
is_mjpeg : false ,
117
143
icc_markers : Vec :: new ( ) ,
@@ -122,6 +148,11 @@ impl<R: Read> Decoder<R> {
122
148
}
123
149
}
124
150
151
+ /// Sets the colour transform to be applied before returning the data.
152
+ pub fn set_color_transform ( & mut self , transform : ColorTransform ) {
153
+ self . color_transform = transform;
154
+ }
155
+
125
156
/// Set maximum buffer size allowed for decoded images
126
157
pub fn set_max_decoding_buffer_size ( & mut self , max : usize ) {
127
158
self . decoding_buffer_size_limit = max;
@@ -489,7 +520,8 @@ impl<R: Read> Decoder<R> {
489
520
if let Some ( data) = parse_app ( & mut self . reader , marker) ? {
490
521
match data {
491
522
AppData :: Adobe ( color_transform) => {
492
- self . color_transform = Some ( color_transform)
523
+ self . color_transform =
524
+ ColorTransform :: AdobeColorTransform ( color_transform)
493
525
}
494
526
AppData :: Jfif => {
495
527
// From the JFIF spec:
@@ -1187,7 +1219,7 @@ fn compute_image(
1187
1219
mut data : Vec < Vec < u8 > > ,
1188
1220
output_size : Dimensions ,
1189
1221
is_jfif : bool ,
1190
- color_transform : Option < AdobeColorTransform > ,
1222
+ color_transform : ColorTransform ,
1191
1223
) -> Result < Vec < u8 > > {
1192
1224
if data. is_empty ( ) || data. iter ( ) . any ( Vec :: is_empty) {
1193
1225
return Err ( Error :: Format ( "not all components have data" . to_owned ( ) ) ) ;
@@ -1224,28 +1256,50 @@ fn compute_image(
1224
1256
pub ( crate ) fn choose_color_convert_func (
1225
1257
component_count : usize ,
1226
1258
_is_jfif : bool ,
1227
- color_transform : Option < AdobeColorTransform > ,
1259
+ color_transform : ColorTransform ,
1228
1260
) -> Result < fn ( & [ Vec < u8 > ] , & mut [ u8 ] ) > {
1229
1261
match component_count {
1230
1262
3 => {
1231
- // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/JPEG.html#Adobe
1232
- // Unknown means the data is RGB, so we don't need to perform any color conversion on it.
1233
- if color_transform == Some ( AdobeColorTransform :: Unknown ) {
1234
- Ok ( color_convert_line_rgb)
1235
- } else if color_transform. is_none ( ) {
1236
- Ok ( color_no_convert)
1237
- } else {
1238
- Ok ( color_convert_line_ycbcr)
1263
+ match color_transform {
1264
+ ColorTransform :: None => Ok ( color_no_convert) ,
1265
+ ColorTransform :: Default => Ok ( color_convert_line_ycbcr) ,
1266
+ ColorTransform :: RGB => Ok ( color_convert_line_rgb) ,
1267
+ ColorTransform :: YCbCr => Ok ( color_convert_line_ycbcr) ,
1268
+ ColorTransform :: CMYK => Err ( Error :: Format (
1269
+ "Invalid number of channels (3) for CMYK data" . to_string ( ) ,
1270
+ ) ) ,
1271
+ ColorTransform :: YCCK => Err ( Error :: Format (
1272
+ "Invalid number of channels (3) for YCCK data" . to_string ( ) ,
1273
+ ) ) ,
1274
+ ColorTransform :: AdobeColorTransform ( adobe_transform) => {
1275
+ // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/JPEG.html#Adobe
1276
+ // Unknown means the data is RGB, so we don't need to perform any color conversion on it.
1277
+ if adobe_transform == AdobeColorTransform :: Unknown {
1278
+ Ok ( color_convert_line_rgb)
1279
+ } else {
1280
+ Ok ( color_convert_line_ycbcr)
1281
+ }
1282
+ }
1239
1283
}
1240
1284
}
1241
1285
4 => {
1242
- // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/JPEG.html#Adobe
1243
1286
match color_transform {
1244
- Some ( AdobeColorTransform :: Unknown ) => Ok ( color_convert_line_cmyk) ,
1245
- Some ( _) => Ok ( color_convert_line_ycck) ,
1246
- None => {
1247
- // Assume CMYK because no APP14 marker was found
1248
- Ok ( color_no_convert)
1287
+ ColorTransform :: None => Ok ( color_no_convert) ,
1288
+ ColorTransform :: Default => Ok ( color_convert_line_cmyk) ,
1289
+ ColorTransform :: RGB => Err ( Error :: Format (
1290
+ "Invalid number of channels (4) for RGB data" . to_string ( ) ,
1291
+ ) ) ,
1292
+ ColorTransform :: YCbCr => Err ( Error :: Format (
1293
+ "Invalid number of channels (4) for YCbCr data" . to_string ( ) ,
1294
+ ) ) ,
1295
+ ColorTransform :: CMYK => Ok ( color_convert_line_cmyk) ,
1296
+ ColorTransform :: YCCK => Ok ( color_convert_line_ycck) ,
1297
+ ColorTransform :: AdobeColorTransform ( adobe_transform) => {
1298
+ // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/JPEG.html#Adobe
1299
+ match adobe_transform {
1300
+ AdobeColorTransform :: Unknown => Ok ( color_convert_line_cmyk) ,
1301
+ _ => Ok ( color_convert_line_ycck) ,
1302
+ }
1249
1303
}
1250
1304
}
1251
1305
}
0 commit comments