#include <math.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "qcmsint.h"
be32;
be16;
#if 0
not used yet
static be32 cpu_to_be32(int32_t v)
{
#ifdef IS_LITTLE_ENDIAN
return ((v & 0xff) << 24) | ((v & 0xff00) << 8) | ((v & 0xff0000) >> 8) | ((v & 0xff000000) >> 24);
return v;
#endif
}
#endif
static uint32_t be32_to_cpu(be32 v)
{ … }
static uint16_t be16_to_cpu(be16 v)
{ … }
struct mem_source
{ … };
static void invalid_source(struct mem_source *mem, const char *reason)
{ … }
static uint32_t read_u32(struct mem_source *mem, size_t offset)
{ … }
static uint16_t read_u16(struct mem_source *mem, size_t offset)
{ … }
static uint8_t read_u8(struct mem_source *mem, size_t offset)
{ … }
static s15Fixed16Number read_s15Fixed16Number(struct mem_source *mem, size_t offset)
{ … }
static uInt8Number read_uInt8Number(struct mem_source *mem, size_t offset)
{ … }
static uInt16Number read_uInt16Number(struct mem_source *mem, size_t offset)
{ … }
#define BAD_VALUE_PROFILE …
#define INVALID_PROFILE …
#define NO_MEM_PROFILE …
#define MAX_PROFILE_SIZE …
#define MAX_TAG_COUNT …
static void check_CMM_type_signature(struct mem_source *src)
{ … }
static void read_profile_version(qcms_profile *profile, struct mem_source *src)
{ … }
#define INPUT_DEVICE_PROFILE …
#define DISPLAY_DEVICE_PROFILE …
#define OUTPUT_DEVICE_PROFILE …
#define DEVICE_LINK_PROFILE …
#define COLOR_SPACE_PROFILE …
#define ABSTRACT_PROFILE …
#define NAMED_COLOR_PROFILE …
static void read_class_signature(qcms_profile *profile, struct mem_source *mem)
{ … }
static void read_color_space(qcms_profile *profile, struct mem_source *mem)
{ … }
static void read_pcs(qcms_profile *profile, struct mem_source *mem)
{ … }
struct tag { … };
struct tag_index { … };
static struct tag_index read_tag_table(qcms_profile *profile, struct mem_source *mem)
{ … }
qcms_bool qcms_profile_is_bogus(qcms_profile *profile)
{ … }
qcms_bool qcms_profile_has_white_point(qcms_profile *profile)
{ … }
qcms_xyz_float qcms_profile_get_white_point(qcms_profile *profile)
{ … }
#define TAG_bXYZ …
#define TAG_gXYZ …
#define TAG_rXYZ …
#define TAG_rTRC …
#define TAG_bTRC …
#define TAG_gTRC …
#define TAG_kTRC …
#define TAG_A2B0 …
#define TAG_B2A0 …
#define TAG_CHAD …
#define TAG_desc …
#define TAG_vcgt …
#define TAG_wtpt …
static struct tag *find_tag(struct tag_index index, uint32_t tag_id)
{ … }
#define DESC_TYPE …
#define MLUC_TYPE …
#define MMOD_TYPE …
#define VCGT_TYPE …
enum { … };
static qcms_bool read_tag_vcgtType(qcms_profile *profile, struct mem_source *src, struct tag_index index)
{ … }
static bool read_tag_descType(qcms_profile *profile, struct mem_source *src, struct tag_index index, uint32_t tag_id)
{ … }
#if defined(__APPLE__)
#define TAG_dscm …
static bool read_tag_dscmType(qcms_profile *profile, struct mem_source *src, struct tag_index index, uint32_t tag_id)
{
if (strcmp(profile->description, "Display") != 0)
return true;
struct tag *tag = find_tag(index, tag_id);
if (tag) {
uint32_t offset = tag->offset;
uint32_t type = read_u32(src, offset);
uint32_t records = read_u32(src, offset+8);
if (!src->valid || !records || type != MLUC_TYPE)
goto invalid_dscm_tag;
if (read_u32(src, offset+12) != 12)
goto invalid_dscm_tag;
for (uint32_t i = 0; i < records; ++i) {
const uint32_t limit = sizeof profile->description;
const uint16_t isoen = 0x656E;
uint16_t language = read_u16(src, offset + 16 + (i * 12) + 0);
uint32_t length = read_u32(src, offset + 16 + (i * 12) + 4);
uint32_t description_offset = read_u32(src, offset + 16 + (i * 12) + 8);
if (!src->valid || !length || (length & 1))
goto invalid_dscm_tag;
if (language != isoen)
continue;
strcpy(profile->description, "dscm:");
length += 5;
if (length >= limit)
length = limit - 1;
for (uint32_t j = 5; j < length; ++j) {
uint8_t value = read_u8(src, offset + description_offset + j - 5);
if (!src->valid)
goto invalid_dscm_tag;
profile->description[j] = value ? value : '.';
}
profile->description[length] = 0;
break;
}
}
if (src->valid)
return true;
invalid_dscm_tag:
invalid_source(src, "invalid dscm tag");
return false;
}
#define TAG_mmod …
static bool read_tag_mmodType(qcms_profile *profile, struct mem_source *src, struct tag_index index, uint32_t tag_id)
{
if (strcmp(profile->description, "Display") != 0)
return true;
struct tag *tag = find_tag(index, tag_id);
if (tag) {
const uint8_t length = 4 * 4;
uint32_t offset = tag->offset;
if (tag->size < 40 || read_u32(src, offset) != MMOD_TYPE)
goto invalid_mmod_tag;
for (uint8_t i = 0; i < length; ++i) {
uint8_t value = read_u8(src, offset + i);
if (!src->valid)
goto invalid_mmod_tag;
profile->description[i] = value ? value : '.';
}
profile->description[length] = 0;
}
if (src->valid)
return true;
invalid_mmod_tag:
invalid_source(src, "invalid mmod tag");
return false;
}
#endif
#define XYZ_TYPE …
#define CURVE_TYPE …
#define PARAMETRIC_CURVE_TYPE …
#define LUT16_TYPE …
#define LUT8_TYPE …
#define LUT_MAB_TYPE …
#define LUT_MBA_TYPE …
#define CHROMATIC_TYPE …
static struct matrix read_tag_s15Fixed16ArrayType(struct mem_source *src, struct tag_index index, uint32_t tag_id)
{ … }
static struct XYZNumber read_tag_XYZType(struct mem_source *src, struct tag_index index, uint32_t tag_id)
{ … }
static struct curveType *read_curveType(struct mem_source *src, uint32_t offset, uint32_t *len)
{ … }
static struct curveType *read_tag_curveType(struct mem_source *src, struct tag_index index, uint32_t tag_id)
{ … }
#define MAX_CLUT_SIZE …
#define MAX_CHANNELS …
static void read_nested_curveType(struct mem_source *src, struct curveType *(*curveArray)[MAX_CHANNELS], uint8_t num_channels, uint32_t curve_offset)
{ … }
static void mAB_release(struct lutmABType *lut)
{ … }
static struct lutmABType *read_tag_lutmABType(struct mem_source *src, struct tag_index index, uint32_t tag_id)
{ … }
static struct lutType *read_tag_lutType(struct mem_source *src, struct tag_index index, uint32_t tag_id)
{ … }
static void read_rendering_intent(qcms_profile *profile, struct mem_source *src)
{ … }
qcms_profile *qcms_profile_create(void)
{ … }
static uint16_t *build_sRGB_gamma_table(int num_entries)
{ … }
static struct curveType *curve_from_table(uint16_t *table, int num_entries)
{ … }
static uint16_t float_to_u8Fixed8Number(float a)
{ … }
static struct curveType *curve_from_gamma(float gamma)
{ … }
qcms_profile* qcms_profile_create_rgb_with_gamma(
qcms_CIE_xyY white_point,
qcms_CIE_xyYTRIPLE primaries,
float gamma)
{ … }
qcms_profile* qcms_profile_create_rgb_with_table(
qcms_CIE_xyY white_point,
qcms_CIE_xyYTRIPLE primaries,
uint16_t *table, int num_entries)
{ … }
qcms_CIE_xyY white_point_from_temp(int temp_K)
{ … }
qcms_profile* qcms_profile_sRGB(void)
{ … }
qcms_profile* qcms_profile_from_memory(const void *mem, size_t size)
{ … }
qcms_bool qcms_profile_match(qcms_profile *p1, qcms_profile *p2)
{ … }
const char* qcms_profile_get_description(qcms_profile *profile)
{ … }
qcms_intent qcms_profile_get_rendering_intent(qcms_profile *profile)
{ … }
qcms_color_space qcms_profile_get_color_space(qcms_profile *profile)
{ … }
unsigned qcms_profile_get_version(qcms_profile *profile)
{ … }
size_t qcms_profile_get_vcgt_channel_length(qcms_profile *profile)
{ … }
assert_short_not_16b;
qcms_bool qcms_profile_get_vcgt_rgb_channels(qcms_profile *profile, unsigned short *data)
{ … }
static void lut_release(struct lutType *lut)
{ … }
void qcms_profile_release(qcms_profile *profile)
{ … }
#include <stdio.h>
qcms_profile* qcms_profile_from_file(FILE *file)
{ … }
qcms_profile* qcms_profile_from_path(const char *path)
{ … }
#ifdef _WIN32
qcms_profile* qcms_profile_from_unicode_path(const wchar_t *path)
{
qcms_profile *profile = NULL;
FILE *file = _wfopen(path, L"rb");
if (file) {
profile = qcms_profile_from_file(file);
fclose(file);
}
return profile;
}
#endif