1use std::collections::HashMap;
4use std::io::{Error,ErrorKind};
5use std::io::Result;
6use bin_rs::io::*;
7use bin_rs::Endian;
8use crate::iccprofile::Data::*;
9use crate::utils::bound_check;
10
11pub fn icc_profile_decode(data :&Vec<u8>) -> Result<DecodedICCProfile> {
12 let icc_profile = ICCProfile::new(data)?;
13
14 let mut decoded: HashMap<String,Data> = HashMap::new();
15 let header_size = 128;
16 let mut ptr = header_size;
17 let tags = read_u32_be(&icc_profile.data,ptr);
18 ptr += 4;
19 bound_check(&icc_profile.data,ptr,tags as usize * 12)?;
20 for _ in 0..tags {
21 let tag_name = read_string(&icc_profile.data,ptr,4);
22 ptr += 4;
23 let tag_offset = read_u32_be(&icc_profile.data,ptr) as usize;
24 ptr += 4;
25 let tag_length = read_u32_be(&icc_profile.data,ptr) as usize;
26 ptr += 4;
27 let (_,val) = Data::parse(&icc_profile.data[tag_offset..],tag_length,icc_profile.version)?;
28 decoded.insert(tag_name,val);
29 }
30 Ok(DecodedICCProfile {
31 length : icc_profile.length,
32 cmmid : icc_profile.cmmid,
33 version :icc_profile.version,
34 device_class :icc_profile.device_class,
35 color_space : icc_profile.color_space,
36 pcs : icc_profile.pcs,
37 create_date: icc_profile.create_date.clone(),
38 magicnumber_ascp: icc_profile.magicnumber_ascp,
39 platform: icc_profile.platform,
40 flags: icc_profile.flags,
41 manufacturer: icc_profile.manufacturer,
42 model: icc_profile.model,
43 attributes: icc_profile.attributes,
44 rendering_intent: icc_profile.rendering_intent,
45 illuminate :icc_profile.illuminate,
46 creator: icc_profile.creator,
47 profile_id: icc_profile.profile_id,
48 tags: decoded,
49 })
50}
51
52#[derive(Debug)]
53pub struct DecodedICCProfile {
54 pub length : u32,
55 pub cmmid : u32,
56 pub version :u32,
57 pub device_class :u32,
58 pub color_space : u32,
59 pub pcs : u32,
60 pub create_date: String,
61 pub magicnumber_ascp: u32,
62 pub platform: u32,
63 pub flags: u32,
64 pub manufacturer: u32,
65 pub model: u32,
66 pub attributes: u64,
67 pub rendering_intent: u32,
68 pub illuminate :XYZNumber,
69 pub creator: u32,
70 pub profile_id: u128,
71 pub tags: HashMap<String,Data>,
72}
73
74impl DecodedICCProfile {
75 pub fn new(buffer :&Vec<u8>) -> Result<Self> {
76 icc_profile_decode(buffer)
77 }
78
79 pub fn to_string(&self) -> Result<String> {
80 crate::utils::decoded_print(self,0)
81 }
82
83 pub fn to_string_with_verbose(&self,verbose:usize) -> Result<String> {
84 crate::utils::decoded_print(self,verbose)
85 }
86
87}
88
89#[derive(Debug)]
90pub struct ICCProfile {
91 pub length : u32,
92 pub cmmid : u32,
93 pub version :u32,
94 pub device_class :u32,
95 pub color_space : u32,
96 pub pcs : u32,
97 pub create_date: String,
98 pub magicnumber_ascp: u32,
99 pub platform: u32,
100 pub flags: u32,
101 pub manufacturer: u32,
102 pub model: u32,
103 pub attributes: u64,
104 pub rendering_intent: u32,
105 pub illuminate :XYZNumber,
106 pub creator: u32,
107 pub profile_id: u128,
108 pub reserved :Vec<u8>, pub data: Vec<u8> }
111
112impl ICCProfile {
113 pub fn new(buffer :&Vec<u8>) -> Result<Self> {
114 if buffer.len() < 128 {
115 return Err(Error::new(ErrorKind::Other,"ICCProfile data shotage"))
116 }
117 let mut ptr = 0;
118 let length = read_u32_be(&buffer,ptr);
119 ptr += 4;
120 let cmmid = read_u32_be(&buffer,ptr);
121 ptr += 4;
122 let version = read_u32_be(&buffer,ptr);
123 ptr += 4;
124 let device_class = read_u32_be(&buffer,ptr);
125 ptr += 4;
126 let color_space = read_u32_be(&buffer,ptr);
127 ptr += 4;
128 let pcs = read_u32_be(&buffer,ptr);
129 ptr += 4;
130 let year = read_u16_be(&buffer,ptr);
131 ptr += 2;
132 let month = read_u16_be(&buffer,ptr);
133 ptr += 2;
134 let day = read_u16_be(&buffer,ptr);
135 ptr += 2;
136 let hour = read_u16_be(&buffer,ptr);
137 ptr += 2;
138 let minute = read_u16_be(&buffer,ptr);
139 ptr += 2;
140 let second = read_u16_be(&buffer,ptr);
141 ptr += 2;
142 let magicnumber_ascp = read_u32_be(&buffer,ptr);
143 ptr += 4;
144 let platform = read_u32_be(&buffer,ptr);
145 ptr += 4;
146 let flags = read_u32_be(&buffer,ptr);
147 ptr += 4;
148 let manufacturer = read_u32_be(&buffer,ptr);
149 ptr += 4;
150 let model = read_u32_be(&buffer,ptr);
151 ptr += 4;
152 let attributes = read_u64_be(&buffer,ptr);
153 ptr += 8;
154 let rendering_intent = read_u32_be(&buffer,ptr);
155 ptr += 4;
156 let x = S15Fixed16Number{
157 integer: read_i16_be(buffer, ptr),
158 decimal: read_u16_be(buffer, ptr+2)
159 };
160 ptr += 4;
161 let y = S15Fixed16Number{
162 integer: read_i16_be(buffer, ptr),
163 decimal: read_u16_be(buffer, ptr+2)
164 };
165 ptr += 4;
166 let z = S15Fixed16Number{
167 integer: read_i16_be(buffer, ptr),
168 decimal: read_u16_be(buffer, ptr+2)
169 };
170 ptr += 4;
171 let illuminate = XYZNumber{x,y,z};
172
173 let creator = read_u32_be(&buffer,ptr);
174 ptr += 4;
175 let profile_id = read_u128_be(&buffer, ptr);
176let create_date = format!("{:>4}/{:>2}/{:>2} {:>02}:{:>02}:{:>02}",
179 year,month,day,hour,minute,second);
180 Ok(Self {
181 length: length,
182 cmmid : cmmid,
183 version: version,
184 device_class: device_class,
185 color_space: color_space,
186 pcs: pcs,
187 create_date: create_date.clone(),
188 magicnumber_ascp: magicnumber_ascp,
189 platform: platform,
190 flags: flags,
191 manufacturer: manufacturer,
192 model: model,
193 attributes: attributes,
194 rendering_intent: rendering_intent,
195 illuminate: illuminate,
196 creator: creator,
197 profile_id: profile_id,
198 reserved: Vec::new(),
199 data : buffer.to_vec(),
200 })
201 }
202}
203
204
205pub trait ICCNumber {
206 fn as_f32(&self) -> f32;
207 fn as_f64(&self) -> f64;
208 fn int(&self) -> i32;
209 fn decimal(&self) -> u32;
210}
211
212#[derive(Debug)]
213pub struct S15Fixed16Number {
214 integer: i16,
215 decimal: u16,
216}
217
218impl S15Fixed16Number {
219 pub fn new(val: f64) -> Self {
220 let integer = val.floor() as i16;
221 let decimal = ((val - val.floor()) * u16::MAX as f64) as u16;
222 S15Fixed16Number { integer, decimal }
223 }
224}
225
226impl ICCNumber for S15Fixed16Number {
227 fn as_f32(&self) -> f32 { self.integer as f32 + self.decimal as f32 / u16::MAX as f32 }
228 fn as_f64(&self) -> f64 { self.integer as f64 + self.decimal as f64 / u16::MAX as f64 }
229 fn int(&self) -> i32 { self.integer as i32 }
230 fn decimal(&self) -> u32 { self.decimal as u32}
231}
232
233#[derive(Debug)]
234pub struct U16Fixed16Number {
235 integer:u16,
236 decimal:u16,
237}
238
239impl ICCNumber for U16Fixed16Number {
240 fn as_f32(&self) -> f32 { self.integer as f32 + self.decimal as f32 / u16::MAX as f32 }
241 fn as_f64(&self) -> f64 { self.integer as f64 + self.decimal as f64 / u16::MAX as f64 }
242 fn int(&self) -> i32 { self.integer as i32 }
243 fn decimal(&self) -> u32 { self.decimal as u32}
244}
245
246#[derive(Debug)]
247pub struct U1Fixed15Number {
248 decimal:u16,
249}
250
251impl ICCNumber for U1Fixed15Number {
252 fn as_f32(&self) -> f32 { self.decimal as f32 / i16::MAX as f32 }
253 fn as_f64(&self) -> f64 { self.decimal as f64 / i16::MAX as f64 }
254 fn int(&self) -> i32 { 0 }
255 fn decimal(&self) -> u32 { self.decimal as u32}
256}
257
258#[derive(Debug)]
259pub struct U8Fixed8Number {
260 integer:u8,
261 decimal:u8,
262}
263
264impl ICCNumber for U8Fixed8Number {
265 fn as_f32(&self) -> f32 { self.integer as f32 + self.decimal as f32 / u8::MAX as f32 }
266 fn as_f64(&self) -> f64 { self.integer as f64 + self.decimal as f64 / u8::MAX as f64 }
267 fn int(&self) -> i32 { self.integer as i32 }
268 fn decimal(&self) -> u32 { self.decimal as u32}
269}
270
271#[derive(Debug)]
272pub struct XYZNumber {
273 pub x:S15Fixed16Number,
274 pub y:S15Fixed16Number,
275 pub z:S15Fixed16Number
276}
277
278impl XYZNumber {
279 pub fn to_string(&self) -> String {
280 format!("X:{} Y:{} Z:{} ",self.x.as_f32(),self.y.as_f32(),self.z.as_f32())
281 }
282}
283
284#[derive(Debug)]
286pub struct Mft1 {
287 pub input_channels :u8,
288 pub output_channels:u8,
289 pub number_of_clut_grid_points:u8,
290 pub e_params:Vec<S15Fixed16Number>,
291 pub input_table: Vec<u8>,
292 pub clut_values: Vec<u8>,
293 pub output_table: Vec<u8>,
294}
295
296#[derive(Debug)]
298pub struct Mft2 {
299 pub input_channels :u8,
300 pub output_channels:u8,
301 pub number_of_clut_grid_points:u8,
302 pub e_params:Vec<S15Fixed16Number>,
303 pub input_table_enteries: u16,
304 pub output_table_enteries: u16,
305 pub input_table: Vec<u16>,
306 pub clut_values: Vec<u16>,
307 pub output_table: Vec<u16>,
308}
309
310#[derive(Debug)]
312pub enum Curve {
313 ParametricCurve(ParametricCurve),
314 Curve(Vec<u16>),
315}
316
317impl Curve {
318 pub fn as_size(&self) -> usize {
319 match self {
320 Curve::Curve(curve) => {
321 curve.len() * 2 + 12
322 },
323 Curve::ParametricCurve(curve) => {
324 curve.as_size() + 8
325 }
326 }
327 }
328
329 pub fn to_string(&self) -> String {
330 match self {
331 Curve::Curve(curve) => {
332 format!("Curve Type\n{:?}\n",curve)
333 },
334 Curve::ParametricCurve(curve) => {
335 let mut str = "Parametic Curve Type\n".to_string();
336 str += &match curve.funtion_type {
337 0x000 => {"function Y = X**ganma\n"},
338 0x001 => {"function Y = (aX+b)**ganma (X >= -b/a), Y = 0 (X < -b/a)\n"},
339 0x002 => {"function Y = (aX+b)**ganma + c(X >= -b/a), Y = c (X < -b/a)\n"},
340 0x003 => {"function Y = (aX+b)**ganma (X >= d), Y = cX (X < d)\n"},
341 0x004 => {"function Y = (aX+b)**ganma + e(X >= d), Y = cX + f (X < d)\n"},
342 _ => {"function Unknown"},
343 }.to_string();
344 for f in &curve.vals {
345 str += &f.as_f32().to_string();
346 str += " ";
347 }
348 str += "\n";
349 str
350 }
351 }
352 }
353}
354
355#[derive(Debug)]
357pub enum Clut {
358 UInt8(Vec<u8>),
359 UInt16(Vec<u16>),
360}
361
362
363#[derive(Debug)]
364pub struct MClut {
365 grid_points: Vec<u8>, precision: u8,
367 clut_data: Clut,
368}
369
370impl MClut {
371 pub fn len(&self) -> usize {
372 match &self.clut_data {
373 Clut::UInt16(clut) => {
374 clut.len()
375 },
376 Clut::UInt8(clut) => {
377 clut.len()
378 }
379 }
380 }
381}
382
383
384#[derive(Debug)]
386pub struct Mba {
387 pub input_channels :u8,
388 pub output_channels:u8,
389 pub b_curves: Vec<Curve>,
390 pub matrix: Vec<S15Fixed16Number>,
391 pub m_curves: Vec<Curve>,
392 pub clut: MClut,
393 pub a_curves: Vec<Curve>,
394}
395
396#[derive(Debug)]
398pub struct Mab {
399 pub input_channels :u8,
400 pub output_channels:u8,
401 pub b_curves: Vec<Curve>,
402 pub matrix: Vec<S15Fixed16Number>,
403 pub m_curves: Vec<Curve>,
404 pub clut: MClut,
405 pub a_curves: Vec<Curve>,
406}
407
408#[derive(Debug)]
409pub struct ResponseCurveSet16 {
410 pub number_of_channels: u16,
411 pub count_of_measirement_types: u16,
412 pub response_curve_structures: Vec<CurveStructure>,
413}
414
415#[derive(Debug)]
416pub struct Response16Number {
417 pub encoding_the_interval: u16,
418 reserved: u16,
419 pub measurement_value:S15Fixed16Number
420}
421
422#[derive(Debug)]
423pub struct CurveStructure {
424 pub signature: u32,
425 pub for_each_channel:Vec<u32>,
426 pub patch_with_the_maximum_colorant_value:Vec<XYZNumber>,
427 pub response_arrays:Vec<Response16Number>,
428}
429
430#[derive(Debug)]
431pub struct ParametricCurve {
432 pub funtion_type:u16,
433 pub vals:Vec<S15Fixed16Number>,
434}
435
436impl ParametricCurve {
437 pub fn as_size(&self) -> usize {
438 self.vals.len() * 4 + 4
439 }
440}
441
442#[derive(Debug)]
443pub struct FormulaCurve {
444 pub funtion_type:u16,
445 pub vals:Vec<f32>,
446}
447
448impl FormulaCurve {
449 pub fn as_size(&self) -> usize {
450 self.vals.len() * 4 + 2
451 }
452}
453
454#[derive(Debug)]
455pub struct DateTime{
456 pub year: u32,
457 pub month: u32,
458 pub day: u32,
459 pub hour: u32,
460 pub minutes: u32,
461 pub second: u32,
462}
463
464impl DateTime{
465 fn as_string(&self) -> String{
466 format!("{:4}-{:02}-{:02} {:02}:{:02}:{:02}",
467 self.year,self.month,self.day,self.hour,self.minutes,self.second)
468 }
469}
470
471#[derive(Debug)]
472pub struct ColorNameWithData {
473 pub root_color_name: String,
474 pub pcs: [u16;3],
475 pub coordinate: Vec<u16>,
476}
477
478
479#[derive(Debug)]
480pub struct NamedColor2Type {
481 pub vendor_specific_flag: u32,
482 pub prefix_color_name:String,
483 pub suffix_color_name:String,
484 pub entries:Vec<ColorNameWithData>,
485}
486
487#[derive(Debug)]
488pub struct ViewingConditions {
489 pub illuminant: XYZNumber,
490 pub surround: XYZNumber,
491 pub illuminant_type:u32,
492}
493
494#[derive(Debug)]
495pub struct ChromaticityType {
496 pub device_channels: u16,
497 pub encoded_value: u16,
498 pub cie_xy_coordinate_values:Vec<(U16Fixed16Number,U16Fixed16Number)>,
499}
500
501#[derive(Debug)]
502pub struct MeasurementType {
503 pub standard_observer:u32,
504 pub measurement_backing:XYZNumber,
505 pub measurement_geometry:u32,
506 pub measurement_flare:U16Fixed16Number,
507 pub standard_illuminant: u32,
508}
509
510#[derive(Debug)]
511pub struct ColorantTableType {
512 pub colorant_name:String,
513 pub pcs_values:Vec<[u16;3]>,
514}
515
516#[derive(Debug)]
517pub struct PositionNumber {
518 pub offset:u32,
519 pub size:u32,
520}
521
522#[derive(Debug)]
523pub struct MultiProcessElementsType {
524 pub input_channels: u16,
525 pub output_channels: u16,
526 pub process_element_positions: Vec<PositionNumber>,
527 pub data: Vec<u8>,
528}
529
530#[derive(Debug)]
531pub struct CurveSetType {
532 pub input_channels: u16,
533 pub output_channels: u16,
534 pub curve_positions: Vec<PositionNumber>,
535 pub data: Vec<u8>,
536}
537
538#[derive(Debug)]
539pub struct OneDimensionalCurvesType {
540 pub segments: u16,
541 pub dimensional_curves: Vec<Vec<f32>>,
542}
543
544#[derive(Debug)]
545pub struct MatrixElement {
546 pub input_channels: u16,
547 pub output_channels: u16,
548 pub matrix: Vec<f32>,
549}
550
551#[derive(Debug)]
552pub struct Descriptor {
553 pub ascii_string: String,
554 pub lang: String,
555 pub local_string: String,
556}
557
558impl Descriptor {
559 pub fn to_string(&self) -> String {
560 self.ascii_string.to_string()
561 }
562}
563
564#[derive(Debug)]
565pub struct LocalizedUnicode {
566 pub lang: String,
567 pub country: String,
568 pub unicode_string : String,
569}
570
571impl LocalizedUnicode {
572 pub fn as_string(&self) -> String {
573 self.unicode_string.to_string()
574 }
575}
576
577#[derive(Debug)]
578pub struct MultiLocalizedUnicodeType {
579 pub unicode_strings : Vec<LocalizedUnicode>,
580}
581
582impl MultiLocalizedUnicodeType {
583 pub fn as_string(&self) -> String {
584 if self.unicode_strings.len() > 0 {
585 self.unicode_strings[0].unicode_string.to_string()
586 } else {
587 "".to_string()
588 }
589 }
590
591 pub fn from(ascii: String) -> Self {
592 let unicode_string = LocalizedUnicode{
593 lang: "C".to_string(),
594 country: "".to_string(),
595 unicode_string: ascii,
596 };
597 let unicode_strings = vec![unicode_string];
598 Self {
599 unicode_strings
600 }
601 }
602
603 pub fn list_string(&self) -> String {
604 let mut str = "".to_string();
605 for unicode_string in &self.unicode_strings{
606 str += &format!("[{}_{}] {}\n",unicode_string.lang,unicode_string.country,unicode_string.as_string());
607 }
608 str.to_string()
609 }
610}
611
612#[derive(Debug)]
613pub struct ProfileDescription {
614 pub device_manufacturer:u32,
615 pub device_model:u32,
616 pub device_attributes:String,
617 pub technology_information:u32,
618 pub description_device_manufacturer: MultiLocalizedUnicodeType,
619 pub description_device_model: MultiLocalizedUnicodeType,
620}
621
622#[derive(Debug)]
623pub enum Data {
624 Raw(String,Vec<u8>), DataTimeNumber(DateTime),
627 U16Fixed16Number(U16Fixed16Number),
628 U8Fixed8Number(U8Fixed8Number),
629 UInt16Number(u16),
630 UInt32Number(u32),
631 UInt64Number(u64),
632 UInt8Number(u8),
633 XYZNumber(XYZNumber),
634
635 ASCII(String),
636 Binary(Vec<u8>),
637
638
639 Float32Number(f32),
640 PositionNumber(PositionNumber),
641 S15Fixed16Number(S15Fixed16Number),
642 S15Fixed16NumberArray(Vec<S15Fixed16Number>),
643 U16Fixed16NumberArray(Vec<U16Fixed16Number>),
644 Response16Number(Response16Number),
645 U1Fixed15Number(U1Fixed15Number),
646 UInt16NumberArray(Vec<u16>),
647 UInt32NumberArray(Vec<u32>),
648 UInt64NumberArray(Vec<u64>),
649 UInt8NumberArray(Vec<u8>),
650 XYZNumberArray(Vec<XYZNumber>),
651
652 Curve(Vec<u16>),
655 ParametricCurve(ParametricCurve),
656 Lut8(Mft1),
657 Lut16(Mft2),
658 Chromaticity(ChromaticityType),
659 MultiLocalizedUnicode(MultiLocalizedUnicodeType),
660 ViewConditions(ViewingConditions),
661 Measurement(MeasurementType),
662 CurveSet(CurveSetType),
663 ProfileDescription(Vec<ProfileDescription>),
664
665 FormulaCurve(FormulaCurve),
667 SampledCurve(Vec<f32>),
668 NamedColor(NamedColor2Type),
669 Descriptor(Descriptor),
670 LutAtoB(Mab),
671 LutBtoA(Mba),
672 ResponseCurveSet16(ResponseCurveSet16),
673 CrdInfo(Vec<String>),
674 ColorantTable(ColorantTableType),
675 MultiProcessElements(MultiProcessElementsType),
676 OneDimenstionalCurves(OneDimensionalCurvesType),
677 MatrixElement(MatrixElement),
678 None,
679}
680
681fn illuminant_type_string(measurement_illuminate: u32) -> String {
682 let string = match measurement_illuminate {
683 0x00000001 => {"D50"},
684 0x00000002 => {"D65"},
685 0x00000003 => {"D93"},
686 0x00000004 => {"F2"},
687 0x00000005 => {"D55"},
688 0x00000006 => {"A"},
689 0x00000007 => {"Equi-Power (E)"},
690 0x00000008 => {"F8\n"},
691 _ => {"unknown"},
692 };
693 string.to_string()
694}
695
696impl Data {
697 pub fn parse(data: &[u8],length:usize,version:u32) -> Result<(String,Data)> {
698 let data_type = Self::read_data_type(data,0)?;
699 Ok((data_type.clone(),Self::get(&data_type,data,length,version)?))
700 }
701
702 fn read_parmetic_curve(data:&[u8]) -> Result<Curve> {
703 bound_check(data,0,12)?;
704 let data_type = Self::read_data_type(data,0)?;
705 if data_type != "para" {
706 let mut ptr = 8;
707 bound_check(data, ptr, 4)?;
708 let mut curv = vec![];
709 let count = read_u32_be(data, ptr) as usize;
710 ptr += 4;
711 bound_check(data, ptr, count * 2)?;
712 for _ in 0..count {
713 curv.push(read_u16_be(data, ptr));
714 ptr += 2;
715 }
716 return Ok(Curve::Curve(curv))
717 }
718
719 let mut ptr = 8;
720 let funtion_type = read_u16_be(data,ptr);
721 ptr += 4;
722 let mut vals :Vec<S15Fixed16Number> = vec![];
723
724 let num = match funtion_type {
725 0 => {
726 1
727 },
728 1 => {
729 3
730 },
731 2 => {
732 4
733 },
734 3 => {
735 5
736 },
737 4 => {
738 7
739 },
740 _ => { 0
742 },
743 };
744 bound_check(data,ptr,num * 4)?;
745 for _ in 0..num {
746 vals.push(S15Fixed16Number{
747 integer: read_i16_be(data, ptr),
748 decimal: read_u16_be(data, ptr+2)
749 });
750 ptr += 4;
751 }
752 Ok(Curve::ParametricCurve(ParametricCurve{funtion_type,vals}))
753 }
754
755 fn read_formula_curve(data:&[u8]) -> Result<FormulaCurve> {
756 bound_check(data,0,4)?;
757 let mut ptr = 8;
758 let funtion_type = read_u16_be(data,ptr);
759 ptr += 4;
760 let mut vals = vec![];
761
762 let num = match funtion_type {
763 0 => {
764 4
765 },
766 1 => {
767 5
768 },
769 2 => {
770 5
771 },
772 _ => { 0
774 },
775 };
776 bound_check(data,ptr,num * 4)?;
777 for _ in 0..num {
778 vals.push(read_f32(data, ptr, Endian::BigEndian));
779 ptr += 4;
780 }
781 Ok(FormulaCurve{funtion_type,vals})
782 }
783
784 fn read_localization(data:&[u8],ptr:usize,_version:u32) -> Result<LocalizedUnicode> {
785 let mut ptr = ptr;
786 bound_check(data, ptr, 12)?;
787 let _ = read_u32_be(data,ptr); ptr +=4;
789 let lang = read_ascii_string(data,ptr,2);
790 ptr +=2;
791 let country = read_ascii_string(data,ptr,2);
792 ptr +=2;
793 let name_length = read_u32_be(data,ptr) as usize;
794 ptr +=4;
795 let name_offset = read_u32_be(data,ptr) as usize;
796let mut len = 0;
798 bound_check(data, name_offset, name_length)?;
799 let mut vals = vec![];
800 while len < name_length {
801 let val = read_u16_be(data, name_offset + len);
802 if val == 0 {
803 break;
804 }
805 vals.push(val);
806 len += 2;
807 }
808 let unicode_string = String::from_utf16_lossy(&vals);
809 let mult = LocalizedUnicode {
810 lang,
811 country,
812 unicode_string
813 };
814 Ok(mult)
815 }
816
817 fn read_multi_localization(data:&[u8],ptr:usize,version:u32) -> Result<MultiLocalizedUnicodeType>{
818 let mut ptr = ptr;
819 bound_check(data, ptr, 20)?;
820 let number_of_names = read_u32_be(data,ptr) as usize;
821 ptr +=4;
822 let mut unicode_strings = Vec::with_capacity(number_of_names);
823 for _ in 0..number_of_names {
824 let string =Self::read_localization(data, ptr, version)?;
825 unicode_strings.push(string);
826 }
827 Ok(MultiLocalizedUnicodeType {
828 unicode_strings
829 })
830 }
831
832 pub fn get(data_type:&str,data: &[u8],length:usize,version:u32) -> Result<Data> {
833 let len = length - 8;
834 let mut ptr = 8;
835 bound_check(data,ptr, len)?;
836 match data_type {
837 "para" => {
838 let curve = Self::read_parmetic_curve(data)?;
839 if let Curve::ParametricCurve(p_curve) = curve {
840 Ok(ParametricCurve(p_curve))
841 } else {
842 Ok(None)
843 }
844 },
845 "parf" => {
846 Ok(FormulaCurve(Self::read_formula_curve(data)?))
847 },
848 "sig " => {
849 let string = read_ascii_string(data, ptr, 4);
850 Ok(ASCII(string))
851 }
852 "XYZ " | "XYZ" => {
853 let mut xyzs :Vec<XYZNumber> = vec![];
854 while ptr < length {
855 let xyz = Self::xyz_number(data, ptr)?;
856 xyzs.push(xyz);
857 ptr += 12;
858 }
859 Ok(XYZNumberArray(xyzs))
860 },
861 "sf32" => { let mut vals :Vec<S15Fixed16Number> = vec![];
863 while ptr < length {
864 vals.push(S15Fixed16Number{
865 integer: read_i16_be(data, ptr),
866 decimal: read_u16_be(data, ptr+2)
867 });
868 ptr += 4;
869 }
870 Ok(S15Fixed16NumberArray(vals))
871 },
872 "uf32" => { let mut vals :Vec<U16Fixed16Number> = vec![];
874 while ptr < length {
875 vals.push(U16Fixed16Number{
876 integer: read_u16_be(data, ptr),
877 decimal: read_u16_be(data, ptr+2)
878 });
879 ptr += 4;
880 }
881 Ok(U16Fixed16NumberArray(vals))
882 },
883 "ui08" => {
884 let vals= read_bytes_as_vec(data, ptr,len);
885 Ok(UInt8NumberArray(vals))
886 },
887 "ui16" => {
888 let mut vals= vec![];
889 while ptr < length {
890 vals.push(read_u16_be(data, ptr));
891 ptr += 2;
892 }
893 Ok(UInt16NumberArray(vals))
894 },
895 "ui32" => {
896 let mut vals= vec![];
897 while ptr < length {
898 vals.push(read_u32_be(data, ptr));
899 ptr += 4;
900 }
901 Ok(UInt32NumberArray(vals))
902 },
903 "ui64" => {
904 let mut vals= vec![];
905 while ptr < length {
906 vals.push(read_u64_be(data, ptr));
907 ptr += 8;
908 }
909 Ok(UInt64NumberArray(vals))
910 },
911 "text"=> {
912 let string = read_ascii_string(data, ptr,len);
913 Ok(Self::ASCII(string))
914 },
915 "desc" => {
916 if version >= 0x40000000 {
917 let counts = read_u32_be(data, ptr) as usize;
918 ptr +=4;
919 bound_check(data,ptr,counts)?;
920 let ascii_string = read_ascii_string(data, ptr+4,counts);
921 ptr += counts;
922 bound_check(data,ptr,8)?;
923 let lang = read_ascii_string(data, ptr,4);
924 ptr += 4;
925 let counts = read_u32_be(data, ptr) as usize;
926 ptr +=4;
927 bound_check(data,ptr,counts)?;
928 let mut len = 0;
930 let mut vals = vec![];
931 while len < counts {
932 let val = read_u16_be(data, ptr);
933 if val == 0 {
934 break;
935 }
936 vals.push(val);
937 ptr += 2;
938 len += 2;
939 }
940 let local_string = String::from_utf16_lossy(&vals);
941 Ok(Descriptor(Descriptor{
942 ascii_string,
943 lang,
944 local_string,
945 }))
947 } else {
948 let ascii_string = read_ascii_string(data, ptr+4,len-4);
949 Ok(ASCII(ascii_string))
950 }
951 },
952 "chrm" => {
953 let device_number = read_u16_be(data,ptr);
954 let encoded_value = read_u16_be(data,ptr+2);
955 ptr += 4;
956 let mut vals :Vec<(U16Fixed16Number,U16Fixed16Number)> = vec![];
957 while ptr < length {
958 vals.push((
959 U16Fixed16Number{
960 integer: read_u16_be(data, ptr),
961 decimal: read_u16_be(data, ptr+2)
962 },
963 U16Fixed16Number{
964 integer: read_u16_be(data, ptr+2),
965 decimal: read_u16_be(data, ptr+4)
966 }));
967 ptr += 8;
968 }
969 Ok(Chromaticity(
970 ChromaticityType{
971 device_channels: device_number,
972 encoded_value: encoded_value,
973 cie_xy_coordinate_values: vals
974 }))
975 },
976 "mluc" |"vued" => {
977
978 Ok(MultiLocalizedUnicode(
979 Self::read_multi_localization(data,ptr,version)?
980 ))
981
982 },
983 "view" => {
984 bound_check(data, ptr, 32)?;
985 let illuminant = Self::xyz_number(data, ptr)?;
986 ptr += 12;
987 let surround = Self::xyz_number(data, ptr)?;
988 ptr += 12;
989 let illuminant_type = read_u32_be(data,ptr);
990 Ok(ViewConditions(
991 ViewingConditions{
992 illuminant,
993 surround,
994 illuminant_type,
995 }
996 ))
997 },
998 "meas" => {
999 bound_check(data, ptr, 28)?;
1000 let standard_observer = read_u32_be(data, ptr);
1001 ptr += 4;
1002 let measurement_backing = Self::xyz_number(data, ptr)?;
1003 ptr += 12;
1004 let measurement_geometry = read_u32_be(data, ptr);
1005 ptr += 4;
1006 let measurement_flare = U16Fixed16Number{
1007 integer: read_u16_be(data, ptr),
1008 decimal: read_u16_be(data, ptr+2)
1009 };
1010 ptr += 4;
1011
1012 let standard_illuminant = read_u32_be(data, ptr);
1013 Ok(Measurement(
1014 MeasurementType{
1015 standard_observer,
1016 measurement_backing,
1017 measurement_geometry,
1018 measurement_flare,
1019 standard_illuminant
1020 }))
1021 },
1022 "curv" => {
1023 bound_check(data, ptr, 4)?;
1024 let mut curv = vec![];
1025 let count = read_u32_be(data, ptr) as usize;
1026 ptr += 4;
1027 bound_check(data, ptr, count * 2)?;
1028 for _ in 0..count {
1029 curv.push(read_u16_be(data, ptr));
1030 ptr += 2;
1031 }
1032 Ok(Curve(curv))
1033 },
1034 "mft1" | "mft2" => {
1035 bound_check(data, ptr,52)?;
1036 let input_channels= read_byte(data, ptr);
1037 ptr +=1;
1038 let output_channels = read_byte(data, ptr);
1039 ptr +=1;
1040 let number_of_clut_grid_points = read_byte(data, ptr);
1041 ptr +=2; let mut e_params:Vec<S15Fixed16Number> = vec![];
1044 for _ in 0..9 {
1046 let e = S15Fixed16Number {
1047 integer: read_i16_be(data, ptr),
1048 decimal: read_u16_be(data, ptr+2)
1049 };
1050 e_params.push(e);
1051 ptr += 4;
1052 }
1053
1054 let clut_size = ((number_of_clut_grid_points as u32).pow(input_channels as u32) * output_channels as u32) as usize;
1055
1056 if data_type == "mft1" {
1057 let mut input_table = vec![];
1058 let mut clut_values = vec![];
1059 let mut output_table =vec![];
1060
1061 let input_channels_size = input_channels as usize * 256;
1062 let output_channels_size = output_channels as usize * 256;
1063
1064 bound_check(data, ptr,input_channels_size + clut_size + output_channels_size)?;
1065 for _ in 0..input_channels_size {
1066 input_table.push(read_byte(data, ptr));
1067 ptr += 1;
1068 }
1069
1070 for _ in 0..clut_size {
1071 clut_values.push(read_byte(data, ptr));
1072 ptr += 1;
1073 }
1074
1075 for _ in 0..output_channels_size {
1076 output_table.push(read_byte(data, ptr));
1077 ptr += 1;
1078 }
1079
1080
1081 let mft = Mft1{
1082 input_channels,
1083 output_channels,
1084 number_of_clut_grid_points,
1085 e_params,
1086 input_table,
1087 clut_values,
1088 output_table,
1089
1090 };
1091 Ok(Lut8(mft))
1092 } else {
1093 let mut input_table = vec![];
1094 let mut clut_values = vec![];
1095 let mut output_table =vec![];
1096 bound_check(data, ptr,4)?;
1097
1098 let input_table_enteries = read_u16_be(data, ptr);
1099 ptr += 2;
1100 let output_table_enteries = read_u16_be(data, ptr);
1101 ptr += 2;
1102
1103 let input_channels_size = input_channels as usize * input_table_enteries as usize;
1104 let output_channels_size = output_channels as usize * output_table_enteries as usize;
1105 bound_check(data, ptr,(input_channels_size + clut_size + output_channels_size) * 2)?;
1106
1107 for _ in 0..input_channels_size {
1108 input_table.push(read_u16_be(data, ptr));
1109 ptr += 2;
1110 }
1111
1112 for _ in 0..clut_size {
1113 clut_values.push(read_u16_be(data, ptr));
1114 ptr += 2;
1115 }
1116
1117 for _ in 0..output_channels_size {
1118 output_table.push(read_u16_be(data, ptr));
1119 ptr += 2;
1120 }
1121
1122 let mft = Mft2{
1123 input_channels,
1124 output_channels,
1125 number_of_clut_grid_points,
1126 e_params,
1127 input_table_enteries,
1128 output_table_enteries,
1129 input_table,
1130 clut_values,
1131 output_table,
1132
1133 };
1134 Ok(Lut16(mft))
1135 }
1136 },
1137 "mBA " | "mAB " => { bound_check(data, ptr,32)?;
1139
1140 let input_channels= read_byte(data, ptr);
1141 ptr +=1;
1142 let output_channels = read_byte(data, ptr);
1143 ptr +=1;
1144 ptr +=2; let offset_b_curve = read_u32_be(data, ptr) as usize;
1146 ptr +=4;
1147 let offset_matrix = read_u32_be(data, ptr) as usize;
1148 ptr +=4;
1149 let offset_m_curve = read_u32_be(data, ptr) as usize;
1150 ptr +=4;
1151 let offset_clut = read_u32_be(data, ptr) as usize;
1152 ptr +=4;
1153 let offset_a_curve = read_u32_be(data, ptr) as usize;
1154
1155 let mut b_curves = vec![];
1156 let mut m_curves = vec![];
1157 let mut a_curves = vec![];
1158 let mut matrix = vec![];
1159
1160 let mut ptr = offset_b_curve;
1161 for _ in 0..input_channels {
1162 let b_curve = Self::read_parmetic_curve(&data[ptr..])?;
1163 ptr += b_curve.as_size();
1164 b_curves.push(b_curve);
1165 }
1166 let mut ptr = offset_matrix;
1167 bound_check(data, ptr,12 *4)?;
1168 for _ in 0..12 {
1169 let e = S15Fixed16Number {
1170 integer: read_i16_be(data, ptr),
1171 decimal: read_u16_be(data, ptr+2)
1172 };
1173 matrix.push(e);
1174 ptr += 4;
1175 }
1176 let mut ptr = offset_m_curve;
1177 for _ in 0..input_channels {
1178 let m_curve = Self::read_parmetic_curve(&data[ptr..])?;
1179 ptr += m_curve.as_size();
1180 m_curves.push(m_curve);
1181 }
1182 let mut ptr = offset_clut;
1183 bound_check(data, ptr,16)?;
1184
1185 let mut grid_points = vec![];
1186 let mut clut_size = output_channels as usize;
1187 for i in 0..16 {
1188 let grid_point = read_byte(&data,ptr+i);
1189 if grid_point > 0 {
1190 clut_size *= grid_point as usize;
1191 } else {
1192 break;
1193 }
1194 grid_points.push(grid_point);
1195 }
1196 ptr += 16;
1197 let precision = read_byte(&data,ptr);
1198 ptr += 4; let clut_data = if precision == 1 {
1200 let mut clut_entries:Vec<u8> = vec![];
1201 bound_check(data, ptr,clut_size)?;
1202 for _ in 0..clut_size {
1203 clut_entries.push(read_byte(data, ptr));
1204 ptr += 1;
1205 }
1206 Clut::UInt8(clut_entries)
1207 } else {
1208 let mut clut_entries:Vec<u16> = vec![];
1209 bound_check(data, ptr,clut_size * 2)?;
1210 for _ in 0..clut_size {
1211 clut_entries.push(read_u16_be(data, ptr));
1212 ptr += 2;
1213 }
1214 Clut::UInt16(clut_entries)
1215 };
1216
1217 let clut = MClut {
1218 grid_points,
1219 precision,
1220 clut_data,
1221 };
1222
1223 let mut ptr = offset_a_curve;
1224 for _ in 0..input_channels {
1225 let a_curve = Self::read_parmetic_curve(&data[ptr..])?;
1226 ptr += a_curve.as_size();
1227 a_curves.push(a_curve);
1228 }
1229 if data_type == "mBA " {
1230
1231 Ok(LutBtoA(Mba{
1232 input_channels,
1233 output_channels,
1234 b_curves,
1235 matrix,
1236 m_curves,
1237 clut,
1238 a_curves,
1239 }))
1240 } else {
1241 Ok(LutAtoB(Mab{
1242 input_channels,
1243 output_channels,
1244 b_curves,
1245 matrix,
1246 m_curves,
1247 clut,
1248 a_curves,
1249 }))
1250
1251 }
1252 },
1253 "rcs2" => {
1254 bound_check(data, ptr, 4)?;
1255 let number_of_channels = read_u16_be(data, ptr);
1256 ptr += 2;
1257 let count_of_measirement_types = read_u16_be(data, ptr);
1258 let mut count_relative_offsets = vec![];
1259 for _ in 0..count_of_measirement_types {
1260 count_relative_offsets.push(read_u32_be(data, ptr));
1261 ptr += 4;
1262 }
1263 let mut response_curve_structures = vec![];
1264 for offset in count_relative_offsets {
1265 let mut offset = offset as usize;
1266 bound_check(data, offset, number_of_channels as usize * (4 + 12 + 8) + 4)?;
1267 let signature = read_u32_be(data,offset);
1268 offset += 4;
1269 let mut for_each_channel = vec![];
1270 for _ in 0..number_of_channels {
1271 let val = read_u32_be(data,offset);
1272 offset += 4;
1273 for_each_channel.push(val);
1274 }
1275 let mut patch_with_the_maximum_colorant_value = vec![];
1276 for _ in 0..number_of_channels {
1277 let val = Self::xyz_number(data, offset)?;
1278 offset += 12;
1279 patch_with_the_maximum_colorant_value.push(val);
1280 }
1281 let mut response_arrays = vec![];
1282 for _ in 0..number_of_channels {
1283 let encoding_the_interval = read_u16_be(data, offset);
1284 offset += 2;
1285 let reserved = read_u16_be(data, offset);
1286 offset += 2;
1287 let measurement_value = S15Fixed16Number {
1288 integer: read_i16_be(data, offset),
1289 decimal: read_u16_be(data, offset+2)
1290 };
1291 offset += 4;
1292 response_arrays.push(Response16Number{
1293 encoding_the_interval,
1294 reserved,
1295 measurement_value,
1296 });
1297 }
1298 response_curve_structures.push(CurveStructure{
1299 signature,
1300 for_each_channel,
1301 patch_with_the_maximum_colorant_value,
1302 response_arrays,
1303 });
1304 }
1305 Ok(Self::ResponseCurveSet16(ResponseCurveSet16{
1306 number_of_channels,
1307 count_of_measirement_types,
1308 response_curve_structures,
1309 }))
1310 },
1311 "crdi" => {
1312 let mut strings = vec![];
1313 while ptr < length {
1314 bound_check(data, ptr, 4)?;
1315 let strlen = read_u32_be(data, ptr) as usize;
1316 ptr += 4;
1317 bound_check(data, ptr, strlen)?;
1318 strings.push(read_ascii_string(data, ptr, strlen));
1319 ptr += strlen;
1320 }
1321 Ok(CrdInfo(strings))
1322 },
1323 "data" => {
1324 bound_check(data, ptr, 4)?;
1325 let data_type = read_u32_be(data, ptr) as usize;
1326 ptr += 4;
1327 bound_check(data, ptr, len-4)?;
1328 if data_type == 0 {
1329 let string = read_ascii_string(data, ptr, len -4);
1330 Ok(ASCII(string))
1331 } else {
1332 let raw = read_bytes_as_vec(data, ptr, len -4);
1333 Ok(Binary(raw))
1334 }
1335
1336 },
1337 "clro" => {
1338 bound_check(data, ptr, 4)?;
1339 let counts = read_u32_be(data, ptr) as usize;
1340 ptr += 4;
1341 let count = read_u32_be(data, ptr) as usize;
1342 bound_check(data, ptr, count)?;
1343 let raw = read_bytes_as_vec(data, ptr, counts);
1344 Ok(UInt8NumberArray(raw))
1345 },
1346 "clrt" => {
1347 bound_check(data, ptr, 38)?;
1348 let counts = read_u32_be(data, ptr) as usize;
1349 ptr += 4;
1350 let colorant_name = read_ascii_string(data, ptr, 32);
1351 ptr += 32;
1352 bound_check(data, ptr, counts*6)?;
1353 let mut pcs_values: Vec<[u16;3]> = Vec::with_capacity(counts);
1354 for _ in 0..counts {
1355 let mut pcs = [0_u16;3];
1356 pcs[0] = read_u16_be(data, ptr);
1357 pcs[1] = read_u16_be(data, ptr+2);
1358 pcs[2] = read_u16_be(data, ptr+4);
1359 ptr += 6;
1360 pcs_values.push(pcs);
1361 }
1362
1363 Ok(ColorantTable(ColorantTableType{colorant_name,pcs_values}))
1364
1365 },
1366 "mpet" => {
1367 bound_check(data, ptr, 8)?;
1368 let input_channels = read_u16_be(data, ptr);
1369 let output_channels = read_u16_be(data, ptr+2);
1370 let counts = read_u32_be(data, ptr+4) as usize;
1371 ptr += 8;
1372 bound_check(data, ptr, counts*8)?;
1373 let mut process_element_positions = Vec::with_capacity(counts);
1374 for _ in 0..counts {
1375 let offset = read_u32_be(data, ptr);
1376 let size = read_u32_be(data, ptr+4);
1377 ptr += 8;
1378 process_element_positions.push(PositionNumber{offset,size});
1379 }
1380 let data = read_bytes_as_vec(data,ptr,length - ptr);
1381
1382 Ok(MultiProcessElements(
1383 MultiProcessElementsType {
1384 input_channels,
1385 output_channels,
1386 process_element_positions,
1387 data
1388 }
1389 ))
1390 },
1391 "cvst" => {
1392 bound_check(data, ptr, 4)?;
1393 let input_channels = read_u16_be(data, ptr);
1394 let output_channels = read_u16_be(data, ptr+2);
1395 let counts = input_channels as usize;
1396 ptr += 4;
1397 bound_check(data, ptr, counts*8)?;
1398 let mut curve_positions = Vec::with_capacity(counts);
1399 for _ in 0..counts {
1400 let offset = read_u32_be(data, ptr);
1401 let size = read_u32_be(data, ptr+4);
1402 ptr += 8;
1403 curve_positions.push(PositionNumber{offset,size});
1404 }
1405 let data = read_bytes_as_vec(data,ptr,length - ptr);
1406
1407 Ok(CurveSet(
1408 CurveSetType {
1409 input_channels,
1410 output_channels,
1411 curve_positions,
1412 data
1413 }
1414 ))
1415 },
1416 "curf" => { bound_check(data, ptr, 4)?;
1418 let segments = read_u16_be(data, ptr);
1419 ptr += 4; let counts = segments as usize - 1;
1421 let mut dimensional_curves = Vec::with_capacity(segments as usize);
1422 for _ in 0..segments as usize {
1423 bound_check(data, ptr, counts*4)?;
1424 let mut break_points = Vec::with_capacity(counts);
1425 for _ in 0..counts {
1426 let float = read_f32(data, ptr, Endian::BigEndian);
1427 ptr += 4;
1428 break_points.push(float);
1429 }
1430 if ptr + counts * 4 > length {break}
1431 dimensional_curves.push(break_points);
1432 }
1433
1434 Ok(OneDimenstionalCurves(
1435 OneDimensionalCurvesType {
1436 segments,
1437 dimensional_curves,
1438 }
1439 ))
1440 },
1441 "samf" => { bound_check(data, ptr, 4)?;
1443 let counts = read_u16_be(data, ptr) as usize;
1444 ptr += 4; bound_check(data, ptr, counts * 4)?;
1446 let mut curve_entries = vec![];
1447 for _ in 0..counts {
1448 let float = read_f32(data, ptr, Endian::BigEndian);
1449 ptr += 4;
1450 curve_entries.push(float);
1451 }
1452 Ok(SampledCurve(curve_entries))
1453 },
1454 "matf" => { bound_check(data, ptr, 4)?;
1456 let input_channels = read_u16_be(data, ptr);
1457 let output_channels = read_u16_be(data, ptr+2);
1458 ptr += 4;
1459 let counts = (input_channels as usize + 1) * output_channels as usize;
1460 bound_check(data, ptr, counts*4)?;
1461 let mut matrix = vec![];
1462 for _ in 0..counts {
1463 let float = read_f32(data, ptr, Endian::BigEndian);
1464 ptr += 4;
1465 matrix.push(float);
1466 }
1467 Ok(MatrixElement(MatrixElement{input_channels,output_channels,matrix}))
1468 },
1469 "ncl2" => { bound_check(data, ptr, 122)?;
1471 let vendor_specific_flag = read_u32_be(data, ptr);
1472 ptr += 4;
1473 let counts = read_u32_be(data, ptr) as usize;
1474 ptr += 4;
1475 let number_device_coordinates = read_u32_be(data, ptr) as usize;
1476 ptr += 4;
1477 let prefix_color_name = read_ascii_string(data, ptr,32);
1478 ptr += 32;
1479 let suffix_color_name = read_ascii_string(data, ptr,32);
1480 ptr += 32;
1481 let mut entries = vec![];
1482 for _ in 0..counts {
1483 bound_check(data, ptr, number_device_coordinates * 2 + 32 + 6)?;
1484 let root_color_name = read_ascii_string(data, ptr,32);
1485 ptr += 32;
1486 let mut pcs = [0_u16;3];
1487 pcs[0] = read_u16_be(data, ptr);
1488 pcs[1] = read_u16_be(data, ptr+2);
1489 pcs[2] = read_u16_be(data, ptr+4);
1490 ptr += 6;
1491 let mut coordinate = vec![];
1492 for _ in 0..number_device_coordinates {
1493 coordinate.push(read_u16_be(data, ptr));
1494 ptr += 2;
1495 }
1496 entries.push(ColorNameWithData{
1497 root_color_name,
1498 pcs,
1499 coordinate,
1500 });
1501 }
1502 Ok(NamedColor(NamedColor2Type{
1503 vendor_specific_flag,
1504 prefix_color_name,
1505 suffix_color_name,
1506 entries,
1507 }))
1508 }
1509 "pseq" => {
1510 bound_check(data,ptr,4)?;
1511 let counts = read_u32_be(data, ptr) as usize;
1512 ptr += 4;
1513 bound_check(data,ptr,counts)?;
1514 let mut remain = length - ptr;
1515 let mut profiles = vec![];
1516 for _ in 0..counts {
1517 bound_check(data,ptr,20)?;
1518 if remain <= 0 {break;}
1519 let device_manufacturer = read_u32_be(data, ptr);
1520 ptr += 4;
1521 let device_model = read_u32_be(data, ptr);
1522 ptr += 4;
1523 let device_attributes = read_ascii_string(data, ptr,8);
1524 ptr += 8;
1525 let technology_information = read_u32_be(data, ptr);
1526 ptr += 4;
1527 remain -=20;
1528 let _tag = read_u32_be(data, ptr); ptr += 4;
1530 let len = read_u32_be(data, ptr) as usize;
1531 ptr += 4;
1532 bound_check(data, ptr, len)?;
1533 let (_,res) = Self::parse(&data[ptr..],len, version)?;
1534 let description_device_manufacturer;
1535 match res {
1536 ASCII(text) => {
1537 description_device_manufacturer = MultiLocalizedUnicodeType::from(text);
1538
1539 },
1540 MultiLocalizedUnicode(mlut) => {
1541 description_device_manufacturer = mlut;
1542 }
1543 _ => {
1544 description_device_manufacturer = MultiLocalizedUnicodeType::from("".to_string());
1545 }
1546 }
1547 ptr += len;
1548 let _tag = read_u32_be(data, ptr); ptr += 4;
1550 let len = read_u32_be(data, ptr) as usize;
1551 ptr += 4;
1552 bound_check(data, ptr, len)?;
1553 let (_,res) = Self::parse(&data[ptr..],len, version)?;
1554 let description_device_model;
1555 match res {
1556 ASCII(text) => {
1557 description_device_model = MultiLocalizedUnicodeType::from(text);
1558
1559 },
1560 MultiLocalizedUnicode(mlut) => {
1561 description_device_model = mlut;
1562 }
1563 _ => {
1564 description_device_model = MultiLocalizedUnicodeType::from("".to_string());
1565 }
1566 }
1567 profiles.push(ProfileDescription{
1568 device_manufacturer,
1569 device_model,
1570 device_attributes,
1571 technology_information,
1572 description_device_manufacturer,
1573 description_device_model,
1574 })
1575 }
1576 Ok(ProfileDescription(profiles))
1577 }
1578
1579 _ => { let raw = read_bytes_as_vec(data, ptr, len);
1604 Ok(Raw(data_type.to_string(),raw))
1605 }
1606 }
1607
1608 }
1609
1610 pub fn as_string(&self,verbose:usize) -> String{
1611 match &*self {
1612 DataTimeNumber(datetime) => {
1613 datetime.as_string()
1614 },
1615 Float32Number(f) => {
1616 f.to_string()
1617 },
1618 PositionNumber(position) => {
1619 format!("offset {} size {}",position.offset,position.size)
1620 },
1621 S15Fixed16Number(f) => {
1622 f.as_f32().to_string()
1623 },
1624 S15Fixed16NumberArray(vals) => {
1625 let mut str = "".to_string();
1626 for f in vals {
1627 str += &f.as_f32().to_string();
1628 str += " ";
1629 }
1630 str.to_string()
1631 },
1632 ParametricCurve(parametic_curve) => {
1633 let mut str = match parametic_curve.funtion_type {
1634 0x000 => {"function Y = X**ganma\n"},
1635 0x001 => {"function Y = (aX+b)**ganma (X >= -b/a), Y = 0 (X < -b/a)\n"},
1636 0x002 => {"function Y = (aX+b)**ganma + c(X >= -b/a), Y = c (X < -b/a)\n"},
1637 0x003 => {"function Y = (aX+b)**ganma (X >= d), Y = cX (X < d)\n"},
1638 0x004 => {"function Y = (aX+b)**ganma + e(X >= d), Y = cX + f (X < d)\n"},
1639 _ => {"function Unknown"},
1640 }.to_string();
1641 for f in ¶metic_curve.vals {
1642 str += &f.as_f32().to_string();
1643 str += " ";
1644 }
1645 str.to_string()
1646 }
1647 U16Fixed16Number(f) => {
1648 f.as_f32().to_string()
1649 },
1650 Response16Number(v) => {
1651 format!("{} {} {}",v.encoding_the_interval,v.reserved,v.measurement_value.as_f32())
1652 },
1653 U1Fixed15Number(f) => {
1654 f.as_f32().to_string()
1655 },
1656 U8Fixed8Number(f) => {
1657 f.as_f32().to_string()
1658 },
1659 UInt8Number(n) => {
1660 n.to_string()
1661 },
1662 UInt16Number(n) => {
1663 n.to_string()
1664 },
1665 UInt32Number(n) => {
1666 n.to_string()
1667 },
1668 UInt64Number(n) => {
1669 n.to_string()
1670 },
1671 XYZNumber(xyz) => {
1672 format!("X:{} Y:{} Z:{}\n",xyz.x.as_f32(),xyz.y.as_f32(),xyz.z.as_f32())
1673 },
1674 XYZNumberArray(xyzs) => {
1675 let mut str = "".to_string();
1676 for xyz in xyzs {
1677 str += &format!("X:{} Y:{} Z:{} ",xyz.x.as_f32(),xyz.y.as_f32(),xyz.z.as_f32())
1678 }
1679 str + "\n"
1680 },
1681 Chromaticity(chromaticity) => {
1682 let encoded = match chromaticity.encoded_value {
1683 0x001 => {"ITU-R BT.709"},
1684 0x002 => {"SMPTE RP145-1994"},
1685 0x003 => {"EBU Tech.3213-E"},
1686 0x004 => {"P22"},
1687 _ => {"unknown"},
1688
1689 };
1690 let mut str = format!("Number of Device Channels {} {} ",chromaticity.device_channels,encoded);
1691 for (x,y) in &chromaticity.cie_xy_coordinate_values {
1692 str += &format!("x:{} y:{} ",x.as_f32(),y.as_f32());
1693 }
1694
1695 str + "\n"
1696 },
1697 Measurement(mesaurement) => {
1698 let mut str = match mesaurement.standard_observer {
1699 0x00000001 => {"Standard Observer: CIE 1931 standard colorimetric observer\n"},
1700 0x00000002 => {"Standard Observer: CIE 1964 standard colorimetric observer\n"},
1701 _ => {"Standard: Observer unknown\n"},
1702 }.to_string();
1703 str += &format!("XYZ tristimulus values {}\n",mesaurement.measurement_backing.to_string());
1704 str += "Measurement geometry ";
1705 str += match mesaurement.measurement_geometry {
1706 0x00000001 => {"0/45 or 45/0\n"},
1707 0x00000002 => {"0/d or d/0\n"},
1708 _ => {"unknown\n"},
1709 };
1710 str += &format!("Measurement flare {}\n",mesaurement.measurement_flare.as_f32());
1711 str += "Standard Illuminant: ";
1712 str += &illuminant_type_string(mesaurement.standard_illuminant);
1713 str + "\n"
1714 },
1715 ResponseCurveSet16(response_curve_structures) => {
1716 let mut str = "".to_string();
1717 str += &format!("number_of_channels {} count_of_measirement_types{}\n",
1718 response_curve_structures.number_of_channels,
1719 response_curve_structures.count_of_measirement_types);
1720
1721 for curve_structure in &response_curve_structures.response_curve_structures {
1722 let sig = read_ascii_string(&curve_structure.signature.to_be_bytes(),0,4);
1723
1724 str += &format!("{}\n",sig);
1725
1726 for each in &curve_structure.for_each_channel {
1727 str += &format!("{} ",each)
1728 }
1729 str += "\n";
1730
1731 for xyz in &curve_structure.patch_with_the_maximum_colorant_value {
1732 str += &format!("X:{} Y:{} Z:{} ",xyz.x.as_f32(),xyz.y.as_f32(),xyz.z.as_f32())
1733 }
1734 str += "\n";
1735
1736 for respose in &curve_structure.response_arrays {
1737 str += &format!("{:?} ",respose)
1738 }
1739 str += "\n";
1740 }
1741
1742 str + "\n"
1743 }
1744
1745 ASCII(string) => {
1746 string.to_string()
1747 },
1748 ViewConditions(condition) => {
1749 format!("illuminant {} surround {} type {}",
1750 condition.illuminant.to_string(),
1751 condition.surround.to_string(),
1752 illuminant_type_string(condition.illuminant_type))
1753 },
1754 Lut8(lut) => {
1755 let mut str = format!("Lut8 input #{} output #{} grid {}\n",
1756 lut.input_channels,
1757 lut.output_channels,
1758 lut.number_of_clut_grid_points
1759 );
1760 let e = &lut.e_params;
1761
1762 if e.len() > 9 {
1763 str += &format!("|{} {} {}|\n",e[0].as_f32(),e[1].as_f32(),e[2].as_f32());
1764 str += &format!("|{} {} {}|\n",e[3].as_f32(),e[4].as_f32(),e[5].as_f32());
1765 str += &format!("|{} {} {}|\n",e[6].as_f32(),e[7].as_f32(),e[8].as_f32());
1766 }
1767 str += &format!("input table size {} clut values {} output table size {}\n",
1768 lut.input_table.len(),lut.clut_values.len(),lut.output_table.len());
1769 if verbose > 0 {
1770 let len = lut.input_table.len() / lut.input_channels as usize;
1771 str += &format!("Input table\n");
1772 for j in 0..lut.input_channels as usize {
1773 str += &format!("{:3}: ", j);
1774 for i in 0..len {
1775 str += &format!("{:3} ", lut.input_table[j*len + i]);
1776 }
1777 str += &format!("\n");
1778 }
1779 str += &format!("Clut values\n");
1780 let mut nums = vec![0_usize;lut.input_channels as usize];
1781 let mut i = 0;
1782 while i < lut.clut_values.len() as usize {
1783 let mut current = i / lut.output_channels as usize;
1784 for j in 0..lut.input_channels as usize {
1785 nums[j] = current % lut.number_of_clut_grid_points as usize;
1786 current /= lut.number_of_clut_grid_points as usize;
1787 }
1788 for j in 0..lut.input_channels as usize {
1789 str += &format!("{:3} ",nums[lut.input_channels as usize - j -1 ]);
1790 }
1791 str += ": ";
1792
1793 for j in 0..lut.output_channels as usize {
1794 str += &format!("{:3} ",lut.clut_values[i+j]);
1795 }
1796
1797 i += lut.output_channels as usize;
1798 str += &format!("\n");
1799 }
1800
1801 let len = lut.output_table.len() / lut.output_channels as usize;
1802 str += &format!("\nOutput table\n");
1803 for j in 0..lut.output_channels as usize {
1804 str += &format!("{:3}: ", j);
1805 for i in 0..len {
1806 str += &format!("{:3} ", lut.output_table[j*len + i]);
1807 }
1808 str += &format!("\n");
1809 }
1810 }
1811
1812 str.to_string()
1813 }
1814 Lut16(lut) => {
1815 let mut str = format!("Lut16 input #{} output #{} grid {}\n",
1816 lut.input_channels,
1817 lut.output_channels,
1818 lut.number_of_clut_grid_points
1819 );
1820 let e = &lut.e_params;
1821
1822 if e.len() >= 9 {
1823 str += &format!("|{} {} {}|\n",e[0].as_f32(),e[1].as_f32(),e[2].as_f32());
1824 str += &format!("|{} {} {}|\n",e[3].as_f32(),e[4].as_f32(),e[5].as_f32());
1825 str += &format!("|{} {} {}|\n",e[6].as_f32(),e[7].as_f32(),e[8].as_f32());
1826 }
1827
1828 str += &format!("input table entries {} output table entries {}\n",
1829 lut.input_table_enteries,
1830 lut.output_table_enteries);
1831
1832 str += &format!("input table size {} clut values {} output table size {}\n",
1833 lut.input_table.len(),lut.clut_values.len(),lut.output_table.len());
1834 if verbose > 0 {
1835 let len = lut.input_table.len() / lut.input_channels as usize;
1836 str += &format!("Input table\n");
1837 for j in 0..lut.input_channels as usize {
1838 str += &format!("{:3}: ", j);
1839 for i in 0..len {
1840 str += &format!("{:5} ", lut.input_table[j*len + i]);
1841 }
1842 str += &format!("\n");
1843 }
1844 str += &format!("Clut values\n");
1845 let mut nums = vec![0_usize;lut.input_channels as usize];
1846 let mut i = 0;
1847 while i < lut.clut_values.len() as usize {
1848 let mut current = i / lut.output_channels as usize;
1849 for j in 0..lut.input_channels as usize {
1850 nums[j] = current % lut.number_of_clut_grid_points as usize;
1851 current /= lut.number_of_clut_grid_points as usize;
1852 }
1853 for j in 0..lut.input_channels as usize {
1854 str += &format!("{:3} ",nums[lut.input_channels as usize - j -1 ]);
1855 }
1856 str += ": ";
1857
1858 for j in 0..lut.output_channels as usize {
1859 str += &format!("{:5} ",lut.clut_values[i+j]);
1860 }
1861
1862 i += lut.output_channels as usize;
1863 str += &format!("\n");
1864 }
1865
1866
1867 let len = lut.output_table.len() / lut.output_channels as usize;
1868 str += &format!("\nOutput table\n");
1869 for j in 0..lut.output_channels as usize {
1870 str += &format!("{:3}: ", j);
1871 for i in 0..len {
1872 str += &format!("{:5} ", lut.output_table[j*len + i]);
1873 }
1874 str += &format!("\n");
1875 }
1876 }
1877 str
1878 },
1879 LutBtoA(lut) => {
1880 let mut str = format!("Lut B to A input #{} output #{}\n",
1881 lut.input_channels, lut.output_channels);
1882
1883 str += "B Curves\n";
1884
1885
1886 for curve in &lut.b_curves {
1887 str += &curve.to_string();
1888 }
1889
1890 let e = &lut.matrix;
1891 str += "Matrix\n";
1892
1893 if e.len() >= 12 {
1894 str += &format!("|{} {} {}| |{}|\n",e[0].as_f32(),e[1].as_f32(),e[2].as_f32(),e[9].as_f32() );
1895 str += &format!("|{} {} {}| |{}|\n",e[3].as_f32(),e[4].as_f32(),e[5].as_f32(),e[10].as_f32());
1896 str += &format!("|{} {} {}| |{}|\n",e[6].as_f32(),e[7].as_f32(),e[8].as_f32(),e[11].as_f32());
1897 }
1898
1899 str += "M Curves\n";
1900 for curve in &lut.m_curves {
1901 str += &curve.to_string();
1902 }
1903
1904 str += "CLUT\n";
1905 let clut = &lut.clut;
1906 if verbose > 0 {
1907 str += &format!("{:?} Precision {} {:?}\n",clut.grid_points,clut.precision,clut.clut_data);
1908 } else {
1909 str += &format!("{:?} Precision {} CLUT {} entries\n",clut.grid_points,clut.precision,clut.len());
1910 }
1911
1912 str += "A Curves\n";
1913 for curve in &lut.m_curves {
1914 str += &curve.to_string();
1915 }
1916
1917 str.to_string()
1918 },
1919 LutAtoB(lut) => {
1920 let mut str = format!("Lut A to B input #{} output #{}\n",
1921 lut.input_channels, lut.output_channels);
1922
1923 str += "B Curves\n";
1924
1925
1926 for curve in &lut.b_curves {
1927 str += &curve.to_string();
1928 }
1929
1930 let e = &lut.matrix;
1931 str += "Matrix\n";
1932
1933 if e.len() >= 12 {
1934 str += &format!("|{} {} {}| |{}|\n",e[0].as_f32(),e[1].as_f32(),e[2].as_f32(),e[9].as_f32() );
1935 str += &format!("|{} {} {}| |{}|\n",e[3].as_f32(),e[4].as_f32(),e[5].as_f32(),e[10].as_f32());
1936 str += &format!("|{} {} {}| |{}|\n",e[6].as_f32(),e[7].as_f32(),e[8].as_f32(),e[11].as_f32());
1937 }
1938
1939 str += "M Curves\n";
1940 for curve in &lut.m_curves {
1941 str += &curve.to_string();
1942 }
1943
1944 let clut = &lut.clut;
1945
1946 if verbose > 0 {
1947 str += &format!("{:?} Precision {} {:?}\n",clut.grid_points,clut.precision,clut.clut_data);
1948 } else {
1949 str += &format!("{:?} Precision {} CLUT {} entries\n",clut.grid_points,clut.precision,clut.len());
1950 }
1951
1952 str += "A Curves\n";
1953 for curve in &lut.m_curves {
1954 str += &curve.to_string();
1955 }
1956
1957 str.to_string()
1958 },
1959 Curve(curve) => {
1960 let str = format!("Curve table size {}\n",curve.len());
1961 str
1962 },
1963 MultiLocalizedUnicode(mult) => {
1964 mult.list_string()
1965 },
1966 Raw(data_type,data) => {
1967 if verbose == 0 {
1968 format!("Unimplement data type {} length {}bytes\n",data_type,data.len())
1969 } else {
1970 format!("Unimplement data type {} {:?}\n",data_type,data)
1971 }
1972 }
1973 None => {
1974 "None".to_string()
1975 },
1976 _ => {
1977 format!("{:?}",*self)
1978 }
1979 }
1980 }
1981
1982
1983 pub fn xyz_number(data: &[u8],ptr: usize) -> Result<XYZNumber> {
1984 bound_check(data, ptr, 12)?;
1985 let cie_x = S15Fixed16Number {
1986 integer: read_i16_be(&data, ptr),
1987 decimal: read_u16_be(&data, ptr+2)
1988 };
1989 let cie_y = S15Fixed16Number {
1990 integer: read_i16_be(&data, ptr+4),
1991 decimal: read_u16_be(&data, ptr+6)
1992 };
1993 let cie_z = S15Fixed16Number {
1994 integer: read_i16_be(&data, ptr+8),
1995 decimal: read_u16_be(&data, ptr+10)
1996 };
1997 Ok(XYZNumber{x:cie_x,y:cie_y,z:cie_z})
1998 }
1999
2000 pub fn read_data_type(data:&[u8],ptr: usize) -> Result<String> {
2001 bound_check(data, ptr, 4)?;
2002 let data_type = read_string(data, ptr, 4);
2003 if data_type.len() == 0 {
2004 return Ok(read_string(data, ptr + 1, 3))
2005 }
2006 Ok(data_type)
2007 }
2008}
2009