OLD | NEW |
(Empty) | |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the Chromium LICENSE file. |
| 4 |
| 5 #include "qcms.h" |
| 6 #include "qcms_test_util.h" |
| 7 |
| 8 #include <assert.h> |
| 9 #include <math.h> |
| 10 #include <stdio.h> |
| 11 #include <stdlib.h> |
| 12 #include <time.h> |
| 13 |
| 14 #define PARAMETRIC_CURVE_TYPE 0x70617261 // 'para' |
| 15 |
| 16 static const float inverse65535 = (float) (1.0 / 65535.0); |
| 17 |
| 18 extern float clamp_float(float a); |
| 19 |
| 20 static int get_output_gamma_table(const char *profile_path, uint16_t **table, si
ze_t *size) |
| 21 { |
| 22 qcms_transform *transform; |
| 23 qcms_profile *sRGB; |
| 24 qcms_profile *target; |
| 25 |
| 26 target = qcms_profile_from_path(profile_path); |
| 27 if (!target) { |
| 28 fprintf(stderr, "Invalid input profile\n"); |
| 29 return EXIT_FAILURE; |
| 30 } |
| 31 |
| 32 sRGB = qcms_profile_sRGB(); |
| 33 |
| 34 transform = qcms_transform_create(sRGB, QCMS_DATA_RGBA_8, target, QCMS_DATA_
RGBA_8, QCMS_INTENT_DEFAULT); |
| 35 if (!transform) { |
| 36 fprintf(stderr, "Failed to create colour transform\n"); |
| 37 qcms_profile_release(sRGB); |
| 38 qcms_profile_release(target); |
| 39 return EXIT_FAILURE; |
| 40 } |
| 41 |
| 42 *size = qcms_transform_get_output_trc_rgba(transform, target, QCMS_TRC_USHOR
T, NULL); |
| 43 assert(*size >= 256); |
| 44 |
| 45 *table = malloc(*size * sizeof(uint16_t) * 4); |
| 46 qcms_transform_get_output_trc_rgba(transform, target, QCMS_TRC_USHORT, *tabl
e); |
| 47 |
| 48 qcms_transform_release(transform); |
| 49 qcms_profile_release(sRGB); |
| 50 qcms_profile_release(target); |
| 51 |
| 52 return 0; |
| 53 } |
| 54 |
| 55 static int get_input_gamma_table(const char *profile_path, uint16_t **table, siz
e_t *size) |
| 56 { |
| 57 qcms_transform *transform; |
| 58 qcms_profile *source; |
| 59 qcms_profile *sRGB; |
| 60 |
| 61 source = qcms_profile_from_path(profile_path); |
| 62 if (!source) { |
| 63 fprintf(stderr, "Invalid input profile\n"); |
| 64 return EXIT_FAILURE; |
| 65 } |
| 66 |
| 67 sRGB = qcms_profile_sRGB(); |
| 68 |
| 69 transform = qcms_transform_create(source, QCMS_DATA_RGBA_8, sRGB, QCMS_DATA_
RGBA_8, QCMS_INTENT_DEFAULT); |
| 70 if (!transform) { |
| 71 fprintf(stderr, "Failed to create colour transform\n"); |
| 72 qcms_profile_release(sRGB); |
| 73 qcms_profile_release(source); |
| 74 return EXIT_FAILURE; |
| 75 } |
| 76 |
| 77 *size = qcms_transform_get_input_trc_rgba(transform, source, QCMS_TRC_USHORT
, NULL); |
| 78 assert(*size >= 256); |
| 79 |
| 80 *table = calloc(*size, sizeof(uint16_t) * 4); |
| 81 qcms_transform_get_input_trc_rgba(transform, source, QCMS_TRC_USHORT, *table
); |
| 82 |
| 83 qcms_transform_release(transform); |
| 84 qcms_profile_release(sRGB); |
| 85 qcms_profile_release(source); |
| 86 |
| 87 return 0; |
| 88 } |
| 89 |
| 90 static int qcms_test_output_trc(size_t width, |
| 91 size_t height, |
| 92 int iterations, |
| 93 const char *in_path, |
| 94 const char *out_path, |
| 95 const int force_software) |
| 96 { |
| 97 uint16_t *gamma_table_out = NULL; |
| 98 size_t output_size = 0; |
| 99 qcms_profile *profile; |
| 100 long time_stamp = (long)time(NULL); |
| 101 char output_file_name[1024]; |
| 102 float scale_factor; |
| 103 size_t i; |
| 104 |
| 105 if (!in_path) { |
| 106 fprintf(stderr, "%s: please provide valid ICC profiles via -i option\n",
__FUNCTION__); |
| 107 return EXIT_FAILURE; |
| 108 } |
| 109 |
| 110 printf("Test color profile gamma curves\n"); |
| 111 fflush(stdout); |
| 112 |
| 113 if (get_output_gamma_table(in_path, &gamma_table_out, &output_size) != 0) { |
| 114 fprintf(stderr, "Unable to extract output gamma table\n"); |
| 115 return EXIT_FAILURE; |
| 116 } |
| 117 |
| 118 printf("Output gamma table size = %zu\n", output_size); |
| 119 |
| 120 profile = qcms_profile_from_path(in_path); |
| 121 if (!profile) { |
| 122 fprintf(stderr, "Invalid input profile\n"); |
| 123 free(gamma_table_out); |
| 124 return EXIT_FAILURE; |
| 125 } |
| 126 |
| 127 if (profile->redTRC->type == PARAMETRIC_CURVE_TYPE) { |
| 128 // Check the red TRC curve only for now. |
| 129 int type = - (int)(profile->redTRC->count + 1); |
| 130 uint16_t *gamma_table_in = NULL; |
| 131 size_t input_size = 0; |
| 132 FILE *output_file; |
| 133 |
| 134 printf("Detected parametric curve type = %d\n", profile->redTRC->count); |
| 135 |
| 136 if (get_input_gamma_table(in_path, &gamma_table_in, &input_size) != 0) { |
| 137 fprintf(stderr, "Failed to compute input gamma table\n"); |
| 138 qcms_profile_release(profile); |
| 139 free(gamma_table_out); |
| 140 return EXIT_FAILURE; |
| 141 } |
| 142 |
| 143 // Write output to stdout and tables into a csv file. |
| 144 sprintf(output_file_name, "qcms-test-%ld-parametric-gamma-output-%s.csv"
, |
| 145 time_stamp, profile->description); |
| 146 printf("Writing output gamma tables to %s\n", output_file_name); |
| 147 output_file = fopen(output_file_name, "w"); |
| 148 |
| 149 printf("Parametric gamma values for profile %s description [%s]\n", |
| 150 in_path, profile->description); |
| 151 fprintf(output_file, "Parametric gamma values for profile %s description
[%s]\n", |
| 152 in_path, profile->description); |
| 153 |
| 154 printf("gamma = %.6f, a = %.6f, b = %.6f, c = %.6f, d = %.6f, e = %.6f,
f = %.6f\n", |
| 155 profile->redTRC->parameter[0], profile->redTRC->parameter[1], pr
ofile->redTRC->parameter[2], |
| 156 profile->redTRC->parameter[3], profile->redTRC->parameter[4], pr
ofile->redTRC->parameter[5], |
| 157 profile->redTRC->parameter[6]); |
| 158 |
| 159 fprintf(output_file, "gamma, a, b, c, d, e, f\n"); |
| 160 fprintf(output_file, "%.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f\n", |
| 161 profile->redTRC->parameter[0], profile->redTRC->parameter[1], pr
ofile->redTRC->parameter[2], |
| 162 profile->redTRC->parameter[3], profile->redTRC->parameter[4], pr
ofile->redTRC->parameter[5], |
| 163 profile->redTRC->parameter[6]); |
| 164 |
| 165 fprintf(output_file, "\nInput curve size: %zu", input_size); |
| 166 fprintf(output_file, "\nOutput curve size: %zu", output_size); |
| 167 |
| 168 fprintf(output_file, "\n\nInput gamma, Output gamma, LCMS Output gamma,
Output gamma error\n"); |
| 169 // Output gamma curve down-sample factor. |
| 170 scale_factor = (float)(output_size - 1) / (input_size - 1); |
| 171 |
| 172 for (i = 0; i < input_size; ++i) { |
| 173 float input = gamma_table_in[i * 4] * inverse65535; |
| 174 size_t out_index = (size_t)floor(i * scale_factor + 0.5); |
| 175 float output = gamma_table_out[out_index * 4] * inverse65535; |
| 176 float x = out_index / (float)(output_size - 1); |
| 177 float reference = clamp_float(evaluate_parametric_curve(type, profil
e->redTRC->parameter, x)); |
| 178 float difference = fabs(output - reference); |
| 179 |
| 180 fprintf(output_file, "%.6f, %.6f, %6f, %6f\n", input, output, refere
nce, difference); |
| 181 } |
| 182 |
| 183 fprintf(output_file, "\nNote: the output gamma curves are down-sampled b
y a factor of %zu / %zu\n", |
| 184 output_size, input_size); |
| 185 |
| 186 fclose(output_file); |
| 187 free(gamma_table_in); |
| 188 } else { |
| 189 uint16_t *gamma_table_in = NULL; |
| 190 size_t input_size = 0; |
| 191 FILE *output_file; |
| 192 |
| 193 if (get_input_gamma_table(in_path, &gamma_table_in, &input_size) != 0) { |
| 194 fprintf(stderr, "Failed to compute input gamma table\n"); |
| 195 qcms_profile_release(profile); |
| 196 free(gamma_table_out); |
| 197 return EXIT_FAILURE; |
| 198 } |
| 199 |
| 200 // Write output to stdout and tables into a csv file. |
| 201 sprintf(output_file_name, "qcms-test-%ld-gamma-output-%s.csv", |
| 202 time_stamp, profile->description); |
| 203 printf("Writing gamma tables to %s\n", output_file_name); |
| 204 output_file = fopen(output_file_name, "w"); |
| 205 |
| 206 printf("Gamma values for profile %s description [%s]\n", |
| 207 in_path, profile->description); |
| 208 fprintf(output_file, "Gamma values for profile %s description [%s]\n", |
| 209 in_path, profile->description); |
| 210 |
| 211 if (profile->redTRC->count == 0) { |
| 212 printf("Gamma LUT type 0: linear gamma\n"); |
| 213 fprintf(output_file, "Gamma LUT type 0: linear gamma\n"); |
| 214 } else if (profile->redTRC->count == 1) { |
| 215 float gamma = profile->redTRC->data[0] / 256.0f; |
| 216 printf("Gamma LUT type 1: gamma = %.6f\n", gamma); |
| 217 fprintf(output_file, "Gamma LUT type 1: gamma = %.6f\n", gamma); |
| 218 } else { |
| 219 printf("Gamma LUT table size = %u\n", profile->redTRC->count); |
| 220 fprintf(output_file, "Gamma LUT table size = %u\n", profile->redTRC-
>count); |
| 221 } |
| 222 |
| 223 fprintf(output_file, "\nInput curve size: %zu", input_size); |
| 224 fprintf(output_file, "\nOutput curve size: %zu", output_size); |
| 225 |
| 226 fprintf(output_file, "\n\nInput gamma, Output gamma\n"); |
| 227 // Output gamma curve down-sample factor. |
| 228 scale_factor = (float)(output_size - 1) / (input_size - 1); |
| 229 |
| 230 for (i = 0; i < input_size; ++i) { |
| 231 float input = gamma_table_in[i * 4] * inverse65535; |
| 232 size_t out_index = (size_t)floor(i * scale_factor + 0.5); |
| 233 float output = gamma_table_out[out_index * 4] * inverse65535; |
| 234 |
| 235 fprintf(output_file, "%.6f, %.6f\n", input, output); |
| 236 } |
| 237 |
| 238 fprintf(output_file, "\nNote: the output gamma curves are down-sampled b
y a factor of %zu / %zu\n", |
| 239 output_size, input_size); |
| 240 |
| 241 fclose(output_file); |
| 242 free(gamma_table_in); |
| 243 } |
| 244 |
| 245 qcms_profile_release(profile); |
| 246 free(gamma_table_out); |
| 247 |
| 248 return 0; |
| 249 } |
| 250 |
| 251 struct qcms_test_case qcms_test_output_trc_info = { |
| 252 "qcms_test_output_trc", |
| 253 qcms_test_output_trc, |
| 254 QCMS_TEST_DISABLED |
| 255 }; |
OLD | NEW |