func: qcms_profile* qcms_profile_from_file(FILE *file) size_t length ; qcms_profile * profile ; void * data ; if ( ( data == NULL ) || ( length == 0 ) )  profile = qcms_profile_from_memory ( data , length ); qcms_profile* qcms_profile_from_memory(const void *mem, size_t size) uint32_t length ; struct mem_source source ; struct mem_source * src = & source ; struct tag_index index ; qcms_profile * profile ; source . buf = mem; source . size = size; source . valid = true; if ( size < 4 )  length = read_u32 ( src , 0 ); static uint32_t read_u32(struct mem_source *mem, size_t offset) if ( offset > mem -> size - 4 )  return 0 ; be32 k ; memcpy ( & k , mem -> buf + offset , sizeof ( k ) ); return be32_to_cpu ( k ) ; static uint32_t be32_to_cpu(be32 v) return ( ( v & 0xff ) << 24 ) | ( ( v & 0xff00 ) << 8 ) | ( ( v & 0xff0000 ) >> 8 ) | ( ( v & 0xff000000 ) >> 24 ) ; if ( length <= size )  source . size = length; if ( source . size <= 64 || source . size >= MAX_PROFILE_SIZE )  profile = qcms_profile_create ( ); qcms_profile *qcms_profile_create(void) return calloc ( sizeof ( qcms_profile ) , 1 ) ; if ( ! profile )  if ( ! src -> valid )  index = read_tag_table ( profile , src ); static struct tag_index read_tag_table(qcms_profile *profile, struct mem_source *mem) struct tag_index index = { 0 , NULL } ; unsigned int i ; index . count = read_u32 ( mem , 128 ); static uint32_t read_u32(struct mem_source *mem, size_t offset) if ( offset > mem -> size - 4 )  return 0 ; be32 k ; memcpy ( & k , mem -> buf + offset , sizeof ( k ) ); return be32_to_cpu ( k ) ; if ( index . count > MAX_TAG_COUNT )  return index ; index . tags = malloc ( sizeof ( struct tag ) * index . count ); if ( index . tags )  for (i = 0; i < index.count; i++) index . tags [ i ] . signature = read_u32 ( mem , 128 + 4 + 4 * i * 3 ); static uint32_t read_u32(struct mem_source *mem, size_t offset) if ( offset > mem -> size - 4 )  return 0 ; be32 k ; memcpy ( & k , mem -> buf + offset , sizeof ( k ) ); return be32_to_cpu ( k ) ; index . tags [ i ] . offset = read_u32 ( mem , 128 + 4 + 4 * i * 3 + 4 ); static uint32_t read_u32(struct mem_source *mem, size_t offset) if ( offset > mem -> size - 4 )  return 0 ; be32 k ; memcpy ( & k , mem -> buf + offset , sizeof ( k ) ); return be32_to_cpu ( k ) ; index . tags [ i ] . size = read_u32 ( mem , 128 + 4 + 4 * i * 3 + 8 ); static uint32_t read_u32(struct mem_source *mem, size_t offset) if ( offset > mem -> size - 4 )  return 0 ; be32 k ; memcpy ( & k , mem -> buf + offset , sizeof ( k ) ); return be32_to_cpu ( k ) ; return index ; if ( find_tag ( index , TAG_CHAD ) )  static struct tag *find_tag(struct tag_index index, uint32_t tag_id) unsigned int i ; struct tag * tag = NULL ; for (i = 0; i < index.count; i++) if ( index . tags [ i ] . signature == tag_id )  return & index . tags [ i ] ; return tag ; profile -> chromaticAdaption = read_tag_s15Fixed16ArrayType ( src , index , TAG_CHAD ); static struct matrix read_tag_s15Fixed16ArrayType(struct mem_source *src, struct tag_index index, uint32_t tag_id) struct tag * tag = find_tag ( index , tag_id ) ; static struct tag *find_tag(struct tag_index index, uint32_t tag_id) unsigned int i ; struct tag * tag = NULL ; if ( index . tags [ i ] . signature == tag_id )  return & index . tags [ i ] ; return tag ; struct matrix matrix ; if ( tag )  uint8_t i ; uint32_t offset = tag -> offset ; for (i = 0; i < 9; i++) matrix . m [ i / 3 ] [ i % 3 ] = s15Fixed16Number_to_float ( read_s15Fixed16Number ( src , offset + 8 + i * 4 ) ); static s15Fixed16Number read_s15Fixed16Number(struct mem_source *mem, size_t offset) return read_u32 ( mem , offset ) ; static uint32_t read_u32(struct mem_source *mem, size_t offset) if ( offset > mem -> size - 4 )  return 0 ; be32 k ; memcpy ( & k , mem -> buf + offset , sizeof ( k ) ); return be32_to_cpu ( k ) ; matrix . invalid = false; matrix . invalid = true; return matrix ; profile -> chromaticAdaption . invalid = true; if ( profile -> color_space == RGB_SIGNATURE )  if ( find_tag ( index , TAG_B2A0 ) )  static struct tag *find_tag(struct tag_index index, uint32_t tag_id) unsigned int i ; struct tag * tag = NULL ; if ( index . tags [ i ] . signature == tag_id )  return & index . tags [ i ] ; return tag ; if ( read_u32 ( src , find_tag ( index , TAG_B2A0 ) -> offset ) == LUT8_TYPE || read_u32 ( src , find_tag ( index , TAG_B2A0 ) -> offset ) == LUT16_TYPE )  static struct tag *find_tag(struct tag_index index, uint32_t tag_id) unsigned int i ; struct tag * tag = NULL ; if ( index . tags [ i ] . signature == tag_id )  return & index . tags [ i ] ; return tag ; static uint32_t read_u32(struct mem_source *mem, size_t offset) if ( offset > mem -> size - 4 )  return 0 ; be32 k ; memcpy ( & k , mem -> buf + offset , sizeof ( k ) ); return be32_to_cpu ( k ) ; static struct tag *find_tag(struct tag_index index, uint32_t tag_id) unsigned int i ; struct tag * tag = NULL ; if ( index . tags [ i ] . signature == tag_id )  return & index . tags [ i ] ; return tag ; static uint32_t read_u32(struct mem_source *mem, size_t offset) if ( offset > mem -> size - 4 )  return 0 ; be32 k ; memcpy ( & k , mem -> buf + offset , sizeof ( k ) ); return be32_to_cpu ( k ) ; if ( read_u32 ( src , find_tag ( index , TAG_B2A0 ) -> offset ) == LUT_MBA_TYPE )  static struct tag *find_tag(struct tag_index index, uint32_t tag_id) unsigned int i ; struct tag * tag = NULL ; if ( index . tags [ i ] . signature == tag_id )  return & index . tags [ i ] ; return tag ; static uint32_t read_u32(struct mem_source *mem, size_t offset) if ( offset > mem -> size - 4 )  return 0 ; be32 k ; memcpy ( & k , mem -> buf + offset , sizeof ( k ) ); return be32_to_cpu ( k ) ; profile -> mBA = read_tag_lutmABType ( src , index , TAG_B2A0 ); static struct lutmABType *read_tag_lutmABType(struct mem_source *src, struct tag_index index, uint32_t tag_id) struct tag * tag = find_tag ( index , tag_id ) ; static struct tag *find_tag(struct tag_index index, uint32_t tag_id) unsigned int i ; struct tag * tag = NULL ; if ( index . tags [ i ] . signature == tag_id )  return & index . tags [ i ] ; return tag ; uint32_t offset = tag -> offset ; uint32_t clut_offset ; uint32_t clut_size = 1 ; uint32_t type = read_u32 ( src , offset ) ; static uint32_t read_u32(struct mem_source *mem, size_t offset) if ( offset > mem -> size - 4 )  return 0 ; be32 k ; memcpy ( & k , mem -> buf + offset , sizeof ( k ) ); return be32_to_cpu ( k ) ; uint8_t num_in_channels , num_out_channels ; struct lutmABType * lut ; uint32_t i ; if ( type != LUT_MAB_TYPE && type != LUT_MBA_TYPE )  num_in_channels = read_u8 ( src , offset + 8 ); static uint8_t read_u8(struct mem_source *mem, size_t offset) if ( offset > mem -> size - 1 )  return 0 ; return * ( uint8_t * ) ( mem -> buf + offset ) ; num_out_channels = read_u8 ( src , offset + 8 ); static uint8_t read_u8(struct mem_source *mem, size_t offset) if ( offset > mem -> size - 1 )  return 0 ; return * ( uint8_t * ) ( mem -> buf + offset ) ; if ( num_in_channels > MAX_CHANNELS || num_out_channels > MAX_CHANNELS )  if ( num_in_channels != 3 || num_out_channels != 3 )  clut_offset = read_u32 ( src , offset + 24 ); static uint32_t read_u32(struct mem_source *mem, size_t offset) if ( offset > mem -> size - 4 )  return 0 ; be32 k ; memcpy ( & k , mem -> buf + offset , sizeof ( k ) ); return be32_to_cpu ( k ) ; if ( clut_offset )  clut_offset += offset; if ( clut_offset )  for (i = 0; i < num_in_channels; i++) clut_size *= read_u8 ( src , clut_offset + i ); static uint8_t read_u8(struct mem_source *mem, size_t offset) if ( offset > mem -> size - 1 )  return 0 ; return * ( uint8_t * ) ( mem -> buf + offset ) ; clut_size = 0; clut_size = clut_size * num_out_channels; if ( clut_size > MAX_CLUT_SIZE )  lut = malloc ( sizeof ( struct lutmABType ) + ( clut_size ) * sizeof ( float ) ); if ( ! lut )  memset ( lut , 0 , sizeof ( struct lutmABType ) ); lut -> clut_table = & lut -> clut_table_data [ 0 ]; lut -> num_grid_points [ i ] = read_u8 ( src , clut_offset + i ); static uint8_t read_u8(struct mem_source *mem, size_t offset) if ( offset > mem -> size - 1 )  invalid_source ( mem , "Invalid offset" ); static void invalid_source(struct mem_source *mem, const char *reason) mem -> valid = false; mem -> invalid_reason = reason; return * ( uint8_t * ) ( mem -> buf + offset ) ; lut -> reversed = ( type == LUT_MBA_TYPE ); lut -> num_in_channels = num_in_channels; lut -> num_out_channels = num_out_channels; lut -> e00 = read_s15Fixed16Number ( src , matrix_offset + 4 * 0 ); static s15Fixed16Number read_s15Fixed16Number(struct mem_source *mem, size_t offset) return read_u32 ( mem , offset ) ; lut -> e01 = read_s15Fixed16Number ( src , matrix_offset + 4 * 1 ); static s15Fixed16Number read_s15Fixed16Number(struct mem_source *mem, size_t offset) return read_u32 ( mem , offset ) ; lut -> e02 = read_s15Fixed16Number ( src , matrix_offset + 4 * 2 ); static s15Fixed16Number read_s15Fixed16Number(struct mem_source *mem, size_t offset) return read_u32 ( mem , offset ) ; lut -> e10 = read_s15Fixed16Number ( src , matrix_offset + 4 * 3 ); static s15Fixed16Number read_s15Fixed16Number(struct mem_source *mem, size_t offset) return read_u32 ( mem , offset ) ; lut -> e11 = read_s15Fixed16Number ( src , matrix_offset + 4 * 4 ); static s15Fixed16Number read_s15Fixed16Number(struct mem_source *mem, size_t offset) return read_u32 ( mem , offset ) ; lut -> e12 = read_s15Fixed16Number ( src , matrix_offset + 4 * 5 ); static s15Fixed16Number read_s15Fixed16Number(struct mem_source *mem, size_t offset) return read_u32 ( mem , offset ) ; lut -> e20 = read_s15Fixed16Number ( src , matrix_offset + 4 * 6 ); static s15Fixed16Number read_s15Fixed16Number(struct mem_source *mem, size_t offset) return read_u32 ( mem , offset ) ; lut -> e21 = read_s15Fixed16Number ( src , matrix_offset + 4 * 7 ); static s15Fixed16Number read_s15Fixed16Number(struct mem_source *mem, size_t offset) return read_u32 ( mem , offset ) ; lut -> e22 = read_s15Fixed16Number ( src , matrix_offset + 4 * 8 ); static s15Fixed16Number read_s15Fixed16Number(struct mem_source *mem, size_t offset) return read_u32 ( mem , offset ) ; lut -> e03 = read_s15Fixed16Number ( src , matrix_offset + 4 * 9 ); static s15Fixed16Number read_s15Fixed16Number(struct mem_source *mem, size_t offset) return read_u32 ( mem , offset ) ; lut -> e13 = read_s15Fixed16Number ( src , matrix_offset + 4 * 10 ); static s15Fixed16Number read_s15Fixed16Number(struct mem_source *mem, size_t offset) return read_u32 ( mem , offset ) ; lut -> e23 = read_s15Fixed16Number ( src , matrix_offset + 4 * 11 ); static s15Fixed16Number read_s15Fixed16Number(struct mem_source *mem, size_t offset) return read_u32 ( mem , offset ) ; read_nested_curveType ( src , & lut -> a_curves , num_in_channels , a_curve_offset ); static void read_nested_curveType(struct mem_source *src, struct curveType *(*curveArray)[MAX_CHANNELS], uint8_t num_channels, uint32_t curve_offset) for (i = 0; i < num_channels; i++) ( * curveArray ) [ i ] = read_curveType ( src , curve_offset + channel_offset , & tag_len ); static struct curveType *read_curveType(struct mem_source *src, uint32_t offset, uint32_t *len) uint32_t type = read_u32 ( src , offset ) ; static uint32_t read_u32(struct mem_source *mem, size_t offset) if ( offset > mem -> size - 4 )  invalid_source ( mem , "Invalid offset" ); static void invalid_source(struct mem_source *mem, const char *reason) mem -> valid = false; mem -> invalid_reason = reason; memcpy ( & k , mem -> buf + offset , sizeof ( k ) ); return be32_to_cpu ( k ) ; if ( type != CURVE_TYPE && type != PARAMETRIC_CURVE_TYPE )  invalid_source ( src , "unexpected type, expected CURV or PARA" ); static void invalid_source(struct mem_source *mem, const char *reason) mem -> valid = false; mem -> invalid_reason = reason; if ( type == CURVE_TYPE )  count = read_u32 ( src , offset + 8 ); static uint32_t read_u32(struct mem_source *mem, size_t offset) if ( offset > mem -> size - 4 )  invalid_source ( mem , "Invalid offset" ); memcpy ( & k , mem -> buf + offset , sizeof ( k ) ); return be32_to_cpu ( k ) ; if ( count > MAX_CURVE_ENTRIES )  invalid_source ( src , "curve size too large" ); static void invalid_source(struct mem_source *mem, const char *reason) mem -> valid = false; mem -> invalid_reason = reason; curve = malloc ( sizeof ( struct curveType ) + sizeof ( uInt16Number ) * count ); if ( ! curve )  curve -> count = count; curve -> type = CURVE_TYPE; for (i=0; i<count; i++) curve -> data [ i ] = read_u16 ( src , offset + 12 + i * 2 ); static uint16_t read_u16(struct mem_source *mem, size_t offset) if ( offset > mem -> size - 2 )  invalid_source ( mem , "Invalid offset" ); static void invalid_source(struct mem_source *mem, const char *reason) mem -> valid = false; mem -> invalid_reason = reason; memcpy ( & k , mem -> buf + offset , sizeof ( k ) ); return be16_to_cpu ( k ) ; static uint16_t be16_to_cpu(be16 v) return ( ( v & 0xff ) << 8 ) | ( ( v & 0xff00 ) >> 8 ) ; * len = 12 + count * 2; count = read_u16 ( src , offset + 8 ); static uint16_t read_u16(struct mem_source *mem, size_t offset) if ( offset > mem -> size - 2 )  invalid_source ( mem , "Invalid offset" ); memcpy ( & k , mem -> buf + offset , sizeof ( k ) ); return be16_to_cpu ( k ) ; if ( count > 4 )  invalid_source ( src , "parametric function type not supported." ); static void invalid_source(struct mem_source *mem, const char *reason) mem -> valid = false; mem -> invalid_reason = reason; curve -> count = count; curve -> type = PARAMETRIC_CURVE_TYPE; for (i=0; i < COUNT_TO_LENGTH[count]; i++) curve -> parameter [ i ] = s15Fixed16Number_to_float ( read_s15Fixed16Number ( src , offset + 12 + i * 4 ) ); static s15Fixed16Number read_s15Fixed16Number(struct mem_source *mem, size_t offset) return read_u32 ( mem , offset ) ; * len = 12 + COUNT_TO_LENGTH [ count ] * 4; if ( count == 1 || count == 2 )  float a = curve -> parameter [ 1 ] ; if ( a == 0.f )  invalid_source ( src , "parametricCurve definition causes division by zero." ); static void invalid_source(struct mem_source *mem, const char *reason) mem -> valid = false; mem -> invalid_reason = reason; return curve ; if ( ! ( * curveArray ) [ i ] )  invalid_source ( src , "invalid nested curveType curve" ); static void invalid_source(struct mem_source *mem, const char *reason) mem -> valid = false; mem -> invalid_reason = reason; read_nested_curveType ( src , & lut -> m_curves , num_out_channels , m_curve_offset ); static void read_nested_curveType(struct mem_source *src, struct curveType *(*curveArray)[MAX_CHANNELS], uint8_t num_channels, uint32_t curve_offset) ( * curveArray ) [ i ] = read_curveType ( src , curve_offset + channel_offset , & tag_len ); if ( ! ( * curveArray ) [ i ] )  invalid_source ( src , "invalid nested curveType curve" ); read_nested_curveType ( src , & lut -> b_curves , num_out_channels , b_curve_offset ); static void read_nested_curveType(struct mem_source *src, struct curveType *(*curveArray)[MAX_CHANNELS], uint8_t num_channels, uint32_t curve_offset) ( * curveArray ) [ i ] = read_curveType ( src , curve_offset + channel_offset , & tag_len ); if ( ! ( * curveArray ) [ i ] )  invalid_source ( src , "invalid nested curveType curve" ); for (i = 0; i < clut_size; i++) lut -> clut_table [ i ] = uInt8Number_to_float ( read_uInt8Number ( src , clut_offset + 20 + i * 1 ) ); static uInt8Number read_uInt8Number(struct mem_source *mem, size_t offset) return read_u8 ( mem , offset ) ; static uint8_t read_u8(struct mem_source *mem, size_t offset) if ( offset > mem -> size - 1 )  invalid_source ( mem , "Invalid offset" ); return * ( uint8_t * ) ( mem -> buf + offset ) ; lut -> clut_table [ i ] = uInt16Number_to_float ( read_uInt16Number ( src , clut_offset + 20 + i * 2 ) ); static uInt16Number read_uInt16Number(struct mem_source *mem, size_t offset) return read_u16 ( mem , offset ) ; static uint16_t read_u16(struct mem_source *mem, size_t offset) if ( offset > mem -> size - 2 )  invalid_source ( mem , "Invalid offset" ); memcpy ( & k , mem -> buf + offset , sizeof ( k ) ); return be16_to_cpu ( k ) ; mAB_release ( lut ); static void mAB_release(struct lutmABType *lut) for (i = 0; i < lut->num_in_channels; i++) free ( lut -> a_curves [ i ] ); for (i = 0; i < lut->num_out_channels; i++) free ( lut -> b_curves [ i ] ); free ( lut -> m_curves [ i ] ); free ( lut ); return lut ; 