Skip to main content

icc_profile/
iccprofile.rs

1//! ICC Profile reader
2
3use 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>,  // 28byte,
109    pub data: Vec<u8>   // raw data
110}
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);
176//        ptr += 28;  // padding data
177
178        let 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/// Mft1 is Lut8 type
285#[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/// Mft2 is Lut16 type
297#[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/// enum Curve is for LutAtoB type and LutBtoA type
311#[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/// enum Clut is for LutAtoB type and LutBtoA type
356#[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>,   // max 16
366    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/// Mba is LutBtoA type
385#[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/// Mab is LutAtoB type
397#[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>), // no decodee
625    // General ICC 3.2
626    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    // Type ICC 3.2
653//    OldNamedColor(NamedColorType), // obsolute
654    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    // Type ICC 4.0
666    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            _ => {  // Error
741                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            _ => {  // Error
773                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);  // MUST 12
788        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;
796//        ptr +=4;
797        let 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" => { //s16Fixed16ArrayType
862                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" => { //U16Fixed16ArrayType
873                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                    // Unicode
929                    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                        // Macintosh Profile
946                    }))
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; // with skip padding
1042
1043                let mut e_params:Vec<S15Fixed16Number> = vec![];
1044                // e00 e01 e02 ... e20 d21 e22
1045                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 " => { // no sample 4.0
1138                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; // with skip padding
1145                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;   // with padding
1199                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" => { // 4.x
1417                bound_check(data, ptr, 4)?;
1418                let segments = read_u16_be(data, ptr);
1419                ptr += 4;   // skip
1420                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" => { // 4.x
1442                bound_check(data, ptr, 4)?;
1443                let counts = read_u16_be(data, ptr) as usize;
1444                ptr += 4;   // skip
1445                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" => { // 4.x
1455                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" => { // ncol obsolute
1470                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); // dmnd
1529                    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); // dmnd
1549                    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            _ => { // Data type
1580                // no impl
1581
1582                // "ncol" // 3.2 obsolute?
1583                // "scrn" // 3.2 obsolute 4.0?
1584                // "clut" // 4.0
1585                // "bACS" // 4.0
1586                // "eACS" // 4.0
1587
1588                // "dict" // 5.0
1589                // "ehim" // 5.0
1590                // "enim" // 5.0
1591                // "fl16" // 5.0
1592                // "fl32" // 5.0
1593                // "fl64" // 5.0
1594                // "gbd " // 5.0
1595                // "smat" // 5.0
1596                // "svcn" // 5.0
1597                // "tary" // 5.0
1598                // "tstr" // 5.0
1599                // "utf8" // 5.0
1600                // "zut8" // 5.0
1601                // "zxml" // 5.0
1602
1603                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 &parametic_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