#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include <string.h>
#include "qcmsint.h"
#include "chain.h"
#include "halffloat.h"
#include "matrix.h"
#include "transform_util.h"
#ifdef USE_LIBFUZZER
#define ASSERT …
#else
#define ASSERT(x) …
#endif
#if defined(_M_IX86) || defined(__i386__) || defined(__i386) || defined(_M_AMD64) || defined(__x86_64__) || defined(__x86_64)
#define X86
#endif
static struct matrix build_RGB_to_XYZ_transfer_matrix(qcms_CIE_xyY white, qcms_CIE_xyYTRIPLE primrs)
{ … }
struct CIE_XYZ { … };
static const struct CIE_XYZ D50_XYZ = …;
static struct CIE_XYZ xyY2XYZ(qcms_CIE_xyY source)
{ … }
static struct matrix
compute_chromatic_adaption(struct CIE_XYZ source_white_point,
struct CIE_XYZ dest_white_point,
struct matrix chad)
{ … }
static struct matrix
adaption_matrix(struct CIE_XYZ source_illumination, struct CIE_XYZ target_illumination)
{ … }
static struct matrix adapt_matrix_to_D50(struct matrix r, qcms_CIE_xyY source_white_point)
{ … }
qcms_bool set_rgb_colorants(qcms_profile *profile, qcms_CIE_xyY white_point, qcms_CIE_xyYTRIPLE primaries)
{ … }
#if 0
static void qcms_transform_data_rgb_out_pow(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
{
const int r_out = output_format.r;
const int b_out = output_format.b;
int i;
float (*mat)[4] = transform->matrix;
for (i=0; i<length; i++) {
unsigned char device_r = *src++;
unsigned char device_g = *src++;
unsigned char device_b = *src++;
float linear_r = transform->input_gamma_table_r[device_r];
float linear_g = transform->input_gamma_table_g[device_g];
float linear_b = transform->input_gamma_table_b[device_b];
float out_linear_r = mat[0][0]*linear_r + mat[1][0]*linear_g + mat[2][0]*linear_b;
float out_linear_g = mat[0][1]*linear_r + mat[1][1]*linear_g + mat[2][1]*linear_b;
float out_linear_b = mat[0][2]*linear_r + mat[1][2]*linear_g + mat[2][2]*linear_b;
float out_device_r = pow(out_linear_r, transform->out_gamma_r);
float out_device_g = pow(out_linear_g, transform->out_gamma_g);
float out_device_b = pow(out_linear_b, transform->out_gamma_b);
dest[r_out] = clamp_u8(out_device_r*255);
dest[1] = clamp_u8(out_device_g*255);
dest[b_out] = clamp_u8(out_device_b*255);
dest += 3;
}
}
#endif
static void qcms_transform_data_gray_out_lut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
{ … }
static void qcms_transform_data_graya_out_lut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
{ … }
static void qcms_transform_data_gray_out_precache(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
{ … }
static void qcms_transform_data_graya_out_precache(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
{ … }
static void qcms_transform_data_rgb_out_lut_precache(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
{ … }
void qcms_transform_data_rgba_out_lut_precache(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
{ … }
void qcms_transform_data_tetra_clut_rgba(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
{ … }
static void qcms_transform_data_tetra_clut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
{ … }
static void qcms_transform_data_rgb_out_lut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
{ … }
static void qcms_transform_data_rgba_out_lut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
{ … }
#if 0
static void qcms_transform_data_rgb_out_linear(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
{
const int r_out = output_format.r;
const int b_out = output_format.b;
int i;
float (*mat)[4] = transform->matrix;
for (i = 0; i < length; i++) {
unsigned char device_r = *src++;
unsigned char device_g = *src++;
unsigned char device_b = *src++;
float linear_r = transform->input_gamma_table_r[device_r];
float linear_g = transform->input_gamma_table_g[device_g];
float linear_b = transform->input_gamma_table_b[device_b];
float out_linear_r = mat[0][0]*linear_r + mat[1][0]*linear_g + mat[2][0]*linear_b;
float out_linear_g = mat[0][1]*linear_r + mat[1][1]*linear_g + mat[2][1]*linear_b;
float out_linear_b = mat[0][2]*linear_r + mat[1][2]*linear_g + mat[2][2]*linear_b;
dest[r_out] = clamp_u8(out_linear_r*255);
dest[1] = clamp_u8(out_linear_g*255);
dest[b_out] = clamp_u8(out_linear_b*255);
dest += 3;
}
}
#endif
static struct precache_output *precache_reference(struct precache_output *p)
{ … }
static struct precache_output *precache_create()
{ … }
void precache_release(struct precache_output *p)
{ … }
#ifdef HAVE_POSIX_MEMALIGN
static qcms_transform *transform_alloc(void)
{
qcms_transform *t;
if (!posix_memalign(&t, 16, sizeof(*t))) {
return t;
} else {
return NULL;
}
}
static void transform_free(qcms_transform *t)
{
free(t);
}
#else
static qcms_transform *transform_alloc(void)
{ … }
static void transform_free(qcms_transform *t)
{ … }
#endif
void qcms_transform_release(qcms_transform *t)
{ … }
#ifdef X86
#if defined(_M_IX86) && defined(_MSC_VER)
#define HAS_CPUID
static void cpuid(uint32_t fxn, uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d) {
uint32_t a_, b_, c_, d_;
__asm {
xchg ebx, esi
mov eax, fxn
cpuid
mov a_, eax
mov b_, ebx
mov c_, ecx
mov d_, edx
xchg ebx, esi
}
*a = a_;
*b = b_;
*c = c_;
*d = d_;
}
#elif (defined(__GNUC__) || defined(__SUNPRO_C)) && (defined(__i386__) || defined(__i386))
#define HAS_CPUID
static void cpuid(uint32_t fxn, uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d) {
uint32_t a_, b_, c_, d_;
__asm__ __volatile__ ("xchgl %%ebx, %%esi; cpuid; xchgl %%ebx, %%esi;"
: "=a" (a_), "=S" (b_), "=c" (c_), "=d" (d_) : "a" (fxn));
*a = a_;
*b = b_;
*c = c_;
*d = d_;
}
#endif
#define SSE1_EDX_MASK …
#define SSE2_EDX_MASK …
#define SSE3_ECX_MASK …
static int sse_version_available(void)
{ … }
#endif
static const struct matrix bradford_matrix = …;
static const struct matrix bradford_matrix_inv = …;
struct matrix compute_whitepoint_adaption(float X, float Y, float Z) { … }
void qcms_profile_precache_output_transform(qcms_profile *profile)
{ … }
qcms_transform* qcms_transform_precacheLUT_float(qcms_transform *transform, qcms_profile *in, qcms_profile *out,
int samples, qcms_data_type in_type)
{ … }
qcms_bool qcms_transform_create_LUT_zyx_bgra(qcms_profile *in, qcms_profile *out, qcms_intent intent,
int samples, unsigned char* cube)
{ … }
void qcms_transform_build_clut_cache(qcms_transform* transform) { … }
#define NO_MEM_TRANSFORM …
qcms_transform* qcms_transform_create(
qcms_profile *in, qcms_data_type in_type,
qcms_profile *out, qcms_data_type out_type,
qcms_intent intent)
{ … }
#if defined(__has_attribute)
#define HAS_FORCE_ALIGN_ARG_POINTER …
#elif defined(__GNUC__) && defined(__i386__)
#define HAS_FORCE_ALIGN_ARG_POINTER …
#else
#define HAS_FORCE_ALIGN_ARG_POINTER …
#endif
#if HAS_FORCE_ALIGN_ARG_POINTER
__attribute__((__force_align_arg_pointer__))
#endif
void qcms_transform_data(qcms_transform *transform, void *src, void *dest, size_t length)
{ … }
void qcms_transform_data_type(qcms_transform *transform, void *src, void *dest, size_t length, qcms_output_type type)
{ … }
#define ENABLE_ICC_V4_PROFILE_SUPPORT …
qcms_bool qcms_supports_iccv4 = …;
void qcms_enable_iccv4()
{ … }
static inline qcms_bool transform_is_matrix(qcms_transform *t)
{ … }
qcms_bool qcms_transform_is_matrix(qcms_transform *t)
{ … }
float qcms_transform_get_matrix(qcms_transform *t, unsigned i, unsigned j)
{ … }
static inline qcms_bool supported_trc_type(qcms_trc_type type)
{ … }
const uint16_t half_float_one = …;
size_t qcms_transform_get_input_trc_rgba(qcms_transform *t, qcms_profile *in, qcms_trc_type type, unsigned short *data)
{ … }
const float inverse65535 = …;
size_t qcms_transform_get_output_trc_rgba(qcms_transform *t, qcms_profile *out, qcms_trc_type type, unsigned short *data)
{ … }