chromium/third_party/qcms/src/iccread.c

/* vim: set ts=8 sw=8 noexpandtab: */
//  qcms
//  Copyright (C) 2009 Mozilla Foundation
//  Copyright (C) 1998-2007 Marti Maria
//
// Permission is hereby granted, free of charge, to any person obtaining 
// a copy of this software and associated documentation files (the "Software"), 
// to deal in the Software without restriction, including without limitation 
// the rights to use, copy, modify, merge, publish, distribute, sublicense, 
// and/or sell copies of the Software, and to permit persons to whom the Software 
// is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in 
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 
// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#include <math.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h> //memset
#include "qcmsint.h"

/* It might be worth having a unified limit on content controlled
 * allocation per profile. This would remove the need for many
 * of the arbitrary limits that we used */

be32;
be16;

#if 0
not used yet
/* __builtin_bswap isn't available in older gccs
 * so open code it for now */
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 __builtin_bswap32(v);
	return v;
#endif
}
#endif

static uint32_t be32_to_cpu(be32 v)
{}

static uint16_t be16_to_cpu(be16 v)
{}

/* a wrapper around the memory that we are going to parse
 * into a qcms_profile */
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

/* An arbitrary 4MB limit on profile size */
#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)
{}

/* Checks a profile for obvious inconsistencies and return true if the
 * profile looks bogus and should probably be ignored.
 */
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__)

// Use the dscm tag to change profile description "Display" to its more specific en-localized monitor name, if any.

#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) // MLUC record size: bytes
			goto invalid_dscm_tag;

		for (uint32_t i = 0; i < records; ++i) {
			const uint32_t limit = sizeof profile->description;
			const uint16_t isoen = 0x656E; // ISO-3166-1 language 'en'

			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;

			// Use a prefix to identify the display description source
			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;
}

// Use the mmod tag to change profile description "Display" to its specific mmod maker model data, if any.

#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; // Four 4-byte fields: 'mmod', 0, maker, model.

		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 // __APPLE__

#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)
{}

// Read the tag at a given offset rather then the tag_index. 
// This method is used when reading mAB tags where nested curveType are
// present that are not part of the tag_index.
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)
{}

/* See section 10.10 for specs */
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)
{}



/* build sRGB gamma table */
/* based on cmsBuildParametricGamma() */
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)
{}


//XXX: it would be nice if we had a way of ensuring
// everything in a profile was initialized regardless of how it was created

//XXX: should this also be taking a black_point?
/* similar to CGColorSpaceCreateCalibratedRGB */
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)
{}

/* from lcms: cmsWhitePointFromTemp */
/* tempK must be >= 4000. and <= 25000.
 * Invalid values of tempK will return
 * (x,y,Y) = (-1.0, -1.0, -1.0)
 * similar to argyll: icx_DTEMP2XYZ() */
qcms_CIE_xyY white_point_from_temp(int temp_K)
{}

qcms_profile* qcms_profile_sRGB(void)
{}

/* qcms_profile_from_memory does not hold a reference to the memory passed in */
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)
{}

// Check unsigned short is uint16_t.
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
/* Unicode path version */
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