Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/thirdparty/lcms2/utils/linkicc/linkicc.c @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1:1d09e1dec1d9 | 2:b50eed0cc0ef |
|---|---|
| 1 //--------------------------------------------------------------------------------- | |
| 2 // | |
| 3 // Little Color Management System | |
| 4 // Copyright (c) 1998-2023 Marti Maria Saguer | |
| 5 // | |
| 6 // Permission is hereby granted, free of charge, to any person obtaining | |
| 7 // a copy of this software and associated documentation files (the "Software"), | |
| 8 // to deal in the Software without restriction, including without limitation | |
| 9 // the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 10 // and/or sell copies of the Software, and to permit persons to whom the Software | |
| 11 // is furnished to do so, subject to the following conditions: | |
| 12 // | |
| 13 // The above copyright notice and this permission notice shall be included in | |
| 14 // all copies or substantial portions of the Software. | |
| 15 // | |
| 16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
| 17 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO | |
| 18 // THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
| 19 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | |
| 20 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |
| 21 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |
| 22 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
| 23 // | |
| 24 //--------------------------------------------------------------------------------- | |
| 25 | |
| 26 #include "utils.h" | |
| 27 | |
| 28 // --------------------------------------------------------------------------------- | |
| 29 | |
| 30 static char* Description = "Devicelink profile"; | |
| 31 static char* Copyright = "No copyright, use freely"; | |
| 32 static int Intent = INTENT_PERCEPTUAL; | |
| 33 static char* cOutProf = "devicelink.icc"; | |
| 34 static int PrecalcMode = 1; | |
| 35 static int NumOfGridPoints = 0; | |
| 36 | |
| 37 static cmsFloat64Number ObserverAdaptationState = 1.0; // According ICC 4.2 this is the default | |
| 38 | |
| 39 static cmsBool BlackPointCompensation = FALSE; | |
| 40 | |
| 41 static cmsFloat64Number InkLimit = 400; | |
| 42 static cmsBool lUse8bits = FALSE; | |
| 43 static cmsBool TagResult = FALSE; | |
| 44 static cmsBool KeepLinearization = FALSE; | |
| 45 static cmsFloat64Number Version = 4.3; | |
| 46 | |
| 47 | |
| 48 // The manual | |
| 49 static | |
| 50 int Help(cmsContext ContextID, int level) | |
| 51 { | |
| 52 UTILS_UNUSED_PARAMETER(level); | |
| 53 | |
| 54 fprintf(stderr, "\nlinkicc: Links profiles into a single devicelink.\n"); | |
| 55 | |
| 56 fprintf(stderr, "\n"); | |
| 57 fprintf(stderr, "usage: linkicc [flags] <profiles>\n\n"); | |
| 58 fprintf(stderr, "flags:\n\n"); | |
| 59 fprintf(stderr, "-o<profile> - Output devicelink profile. [defaults to 'devicelink.icc']\n"); | |
| 60 | |
| 61 PrintRenderingIntents(ContextID); | |
| 62 | |
| 63 fprintf(stderr, "-c<0,1,2> - Precision (0=LowRes, 1=Normal, 2=Hi-res) [defaults to 1]\n"); | |
| 64 fprintf(stderr, "-n<gridpoints> - Alternate way to set precision, number of CLUT points\n"); | |
| 65 fprintf(stderr, "-d<description> - description text (quotes can be used)\n"); | |
| 66 fprintf(stderr, "-y<copyright> - copyright notice (quotes can be used)\n"); | |
| 67 | |
| 68 fprintf(stderr, "\n-k<0..400> - Ink-limiting in %% (CMYK only)\n"); | |
| 69 fprintf(stderr, "-8 - Creates 8-bit devicelink\n"); | |
| 70 fprintf(stderr, "-x - Creatively, guess deviceclass of resulting profile.\n"); | |
| 71 fprintf(stderr, "-b - Black point compensation\n"); | |
| 72 fprintf(stderr, "-a<0..1> - Observer adaptation state (abs.col. only)\n\n"); | |
| 73 fprintf(stderr, "-l - Use linearization curves (may affect accuracy)\n"); | |
| 74 fprintf(stderr, "-r<v.r> - Profile version. (CAUTION: may change the profile implementation)\n"); | |
| 75 fprintf(stderr, "\n"); | |
| 76 fprintf(stderr, "Colorspaces must be paired except Lab/XYZ, that can be interchanged.\n\n"); | |
| 77 | |
| 78 PrintBuiltins(); | |
| 79 | |
| 80 fprintf(stderr, "\nExamples:\n\n" | |
| 81 "To create 'devicelink.icm' from a.icc to b.icc:\n" | |
| 82 "\tlinkicc a.icc b.icc\n\n" | |
| 83 "To create 'out.icc' from sRGB to cmyk.icc:\n" | |
| 84 "\tlinkicc -o out.icc *sRGB cmyk.icc\n\n" | |
| 85 "To create a sRGB input profile working in Lab:\n" | |
| 86 "\tlinkicc -x -o sRGBLab.icc *sRGB *Lab\n\n" | |
| 87 "To create a XYZ -> sRGB output profile:\n" | |
| 88 "\tlinkicc -x -o sRGBLab.icc *XYZ *sRGB\n\n" | |
| 89 "To create a abstract profile doing softproof for cmyk.icc:\n" | |
| 90 "\tlinkicc -t1 -x -o softproof.icc *Lab cmyk.icc cmyk.icc *Lab\n\n" | |
| 91 "To create a 'grayer' sRGB input profile:\n" | |
| 92 "\tlinkicc -x -o grayer.icc *sRGB gray.icc gray.icc *Lab\n\n" | |
| 93 "To embed ink limiting into a cmyk output profile:\n" | |
| 94 "\tlinkicc -x -o cmyklimited.icc -k 250 cmyk.icc *Lab\n\n"); | |
| 95 | |
| 96 fprintf(stderr, "This program is intended to be a demo of the Little CMS\n" | |
| 97 "color engine. Both lcms and this program are open source.\n" | |
| 98 "You can obtain both in source code at https://www.littlecms.com\n" | |
| 99 "For suggestions, comments, bug reports etc. send mail to\n" | |
| 100 "info@littlecms.com\n\n"); | |
| 101 | |
| 102 exit(0); | |
| 103 } | |
| 104 | |
| 105 // The toggles stuff | |
| 106 static | |
| 107 void HandleSwitches(cmsContext ContextID, int argc, char *argv[]) | |
| 108 { | |
| 109 int s; | |
| 110 | |
| 111 while ((s = xgetopt(argc,argv,"a:A:BbC:c:D:d:h:H:k:K:lLn:N:O:o:r:R:T:t:V:v:xX8y:Y:-:")) != EOF) { | |
| 112 | |
| 113 switch (s) { | |
| 114 | |
| 115 case '-': | |
| 116 if (strcmp(xoptarg, "help") == 0) | |
| 117 { | |
| 118 Help(ContextID, 0); | |
| 119 } | |
| 120 else | |
| 121 { | |
| 122 FatalError("Unknown option - run without args to see valid ones.\n"); | |
| 123 } | |
| 124 break; | |
| 125 | |
| 126 case 'a': | |
| 127 case 'A': | |
| 128 ObserverAdaptationState = atof(xoptarg); | |
| 129 if (ObserverAdaptationState < 0 || | |
| 130 ObserverAdaptationState > 1.0) | |
| 131 FatalError("Adaptation state should be 0..1"); | |
| 132 break; | |
| 133 | |
| 134 case 'b': | |
| 135 case 'B': | |
| 136 BlackPointCompensation = TRUE; | |
| 137 break; | |
| 138 | |
| 139 case 'c': | |
| 140 case 'C': | |
| 141 PrecalcMode = atoi(xoptarg); | |
| 142 if (PrecalcMode < 0 || PrecalcMode > 2) { | |
| 143 FatalError("Unknown precalc mode '%d'", PrecalcMode); | |
| 144 } | |
| 145 break; | |
| 146 | |
| 147 case 'd': | |
| 148 case 'D': | |
| 149 // Doing that is correct and safe: Description points to memory allocated in the command line. | |
| 150 // same for Copyright and output devicelink. | |
| 151 Description = xoptarg; | |
| 152 break; | |
| 153 | |
| 154 case 'h': | |
| 155 case 'H': | |
| 156 Help(ContextID, atoi(xoptarg)); | |
| 157 return; | |
| 158 | |
| 159 case 'k': | |
| 160 case 'K': | |
| 161 InkLimit = atof(xoptarg); | |
| 162 if (InkLimit < 0.0 || InkLimit > 400.0) { | |
| 163 FatalError("Ink limit must be 0%%..400%%"); | |
| 164 } | |
| 165 break; | |
| 166 | |
| 167 | |
| 168 case 'l': | |
| 169 case 'L': KeepLinearization = TRUE; | |
| 170 break; | |
| 171 | |
| 172 case 'n': | |
| 173 case 'N': | |
| 174 if (PrecalcMode != 1) { | |
| 175 FatalError("Precalc mode already specified"); | |
| 176 } | |
| 177 NumOfGridPoints = atoi(xoptarg); | |
| 178 break; | |
| 179 | |
| 180 case 'o': | |
| 181 case 'O': | |
| 182 cOutProf = xoptarg; | |
| 183 break; | |
| 184 | |
| 185 | |
| 186 case 'r': | |
| 187 case 'R': | |
| 188 Version = atof(xoptarg); | |
| 189 if (Version < 2.0 || Version > 4.3) { | |
| 190 fprintf(stderr, "WARNING: lcms was not aware of this version, tag types may be wrong!\n"); | |
| 191 } | |
| 192 break; | |
| 193 | |
| 194 case 't': | |
| 195 case 'T': | |
| 196 Intent = atoi(xoptarg); // Will be validated latter on | |
| 197 break; | |
| 198 | |
| 199 case 'V': | |
| 200 case 'v': | |
| 201 Verbose = atoi(xoptarg); | |
| 202 if (Verbose < 0 || Verbose > 3) { | |
| 203 FatalError("Unknown verbosity level '%d'", Verbose); | |
| 204 } | |
| 205 break; | |
| 206 | |
| 207 case '8': | |
| 208 lUse8bits = TRUE; | |
| 209 break; | |
| 210 | |
| 211 | |
| 212 | |
| 213 case 'y': | |
| 214 case 'Y': | |
| 215 Copyright = xoptarg; | |
| 216 break; | |
| 217 | |
| 218 | |
| 219 | |
| 220 case 'x': | |
| 221 case 'X': TagResult = TRUE; | |
| 222 break; | |
| 223 | |
| 224 | |
| 225 default: | |
| 226 | |
| 227 FatalError("Unknown option - run without args to see valid ones.\n"); | |
| 228 } | |
| 229 } | |
| 230 } | |
| 231 | |
| 232 // Set the copyright and description | |
| 233 static | |
| 234 cmsBool SetTextTags(cmsContext ContextID, cmsHPROFILE hProfile) | |
| 235 { | |
| 236 cmsMLU *DescriptionMLU, *CopyrightMLU; | |
| 237 cmsBool rc = FALSE; | |
| 238 | |
| 239 DescriptionMLU = cmsMLUalloc(ContextID, 1); | |
| 240 CopyrightMLU = cmsMLUalloc(ContextID, 1); | |
| 241 | |
| 242 if (DescriptionMLU == NULL || CopyrightMLU == NULL) goto Error; | |
| 243 | |
| 244 if (!cmsMLUsetASCII(ContextID, DescriptionMLU, "en", "US", Description)) goto Error; | |
| 245 if (!cmsMLUsetASCII(ContextID, CopyrightMLU, "en", "US", Copyright)) goto Error; | |
| 246 | |
| 247 if (!cmsWriteTag(ContextID, hProfile, cmsSigProfileDescriptionTag, DescriptionMLU)) goto Error; | |
| 248 if (!cmsWriteTag(ContextID, hProfile, cmsSigCopyrightTag, CopyrightMLU)) goto Error; | |
| 249 | |
| 250 rc = TRUE; | |
| 251 | |
| 252 Error: | |
| 253 | |
| 254 if (DescriptionMLU) | |
| 255 cmsMLUfree(ContextID, DescriptionMLU); | |
| 256 if (CopyrightMLU) | |
| 257 cmsMLUfree(ContextID, CopyrightMLU); | |
| 258 return rc; | |
| 259 } | |
| 260 | |
| 261 | |
| 262 | |
| 263 int main(int argc, char *argv[]) | |
| 264 { | |
| 265 int i, nargs, rc; | |
| 266 cmsHPROFILE Profiles[257]; | |
| 267 cmsHPROFILE hProfile; | |
| 268 cmsUInt32Number dwFlags; | |
| 269 cmsHTRANSFORM hTransform = NULL; | |
| 270 cmsContext ContextID = NULL; | |
| 271 | |
| 272 // Here we are | |
| 273 fprintf(stderr, "Little CMS ICC device link generator - v3.2 [LittleCMS %2.2f]\n", cmsGetEncodedCMMversion() / 1000.0); | |
| 274 fprintf(stderr, "Copyright (c) 1998-2023 Marti Maria Saguer. See COPYING file for details.\n"); | |
| 275 fflush(stderr); | |
| 276 | |
| 277 // Initialize | |
| 278 InitUtils(ContextID, "linkicc"); | |
| 279 rc = 0; | |
| 280 | |
| 281 // Get the options | |
| 282 HandleSwitches(ContextID, argc, argv); | |
| 283 | |
| 284 // How many profiles to link? | |
| 285 nargs = (argc - xoptind); | |
| 286 if (nargs < 1) | |
| 287 return Help(ContextID, 0); | |
| 288 | |
| 289 if (nargs > 255) { | |
| 290 FatalError("Holy profile! what are you trying to do with so many profiles!?"); | |
| 291 goto Cleanup; | |
| 292 } | |
| 293 | |
| 294 // Open all profiles | |
| 295 memset(Profiles, 0, sizeof(Profiles)); | |
| 296 for (i=0; i < nargs; i++) { | |
| 297 | |
| 298 Profiles[i] = OpenStockProfile(ContextID, argv[i + xoptind]); | |
| 299 if (Profiles[i] == NULL) goto Cleanup; | |
| 300 | |
| 301 if (Verbose >= 1) { | |
| 302 PrintProfileInformation(ContextID, Profiles[i]); | |
| 303 } | |
| 304 } | |
| 305 | |
| 306 // Ink limiting | |
| 307 if (InkLimit != 400.0) { | |
| 308 cmsColorSpaceSignature EndingColorSpace = cmsGetColorSpace(ContextID, Profiles[nargs-1]); | |
| 309 Profiles[nargs++] = cmsCreateInkLimitingDeviceLink(ContextID, EndingColorSpace, InkLimit); | |
| 310 } | |
| 311 | |
| 312 // Set the flags | |
| 313 dwFlags = cmsFLAGS_KEEP_SEQUENCE; | |
| 314 switch (PrecalcMode) { | |
| 315 | |
| 316 case 0: dwFlags |= cmsFLAGS_LOWRESPRECALC; break; | |
| 317 case 2: dwFlags |= cmsFLAGS_HIGHRESPRECALC; break; | |
| 318 case 1: | |
| 319 if (NumOfGridPoints > 0) | |
| 320 dwFlags |= cmsFLAGS_GRIDPOINTS(NumOfGridPoints); | |
| 321 break; | |
| 322 | |
| 323 default: | |
| 324 { | |
| 325 FatalError("Unknown precalculation mode '%d'", PrecalcMode); | |
| 326 goto Cleanup; | |
| 327 } | |
| 328 } | |
| 329 | |
| 330 if (BlackPointCompensation) | |
| 331 dwFlags |= cmsFLAGS_BLACKPOINTCOMPENSATION; | |
| 332 | |
| 333 if (TagResult) | |
| 334 dwFlags |= cmsFLAGS_GUESSDEVICECLASS; | |
| 335 | |
| 336 if (KeepLinearization) | |
| 337 dwFlags |= cmsFLAGS_CLUT_PRE_LINEARIZATION|cmsFLAGS_CLUT_POST_LINEARIZATION; | |
| 338 | |
| 339 if (lUse8bits) dwFlags |= cmsFLAGS_8BITS_DEVICELINK; | |
| 340 | |
| 341 cmsSetAdaptationState(ContextID, ObserverAdaptationState); | |
| 342 | |
| 343 // Create the color transform. Specify 0 for the format is safe as the transform | |
| 344 // is intended to be used only for the devicelink. | |
| 345 hTransform = cmsCreateMultiprofileTransform(ContextID, Profiles, nargs, 0, 0, Intent, dwFlags|cmsFLAGS_NOOPTIMIZE); | |
| 346 if (hTransform == NULL) { | |
| 347 FatalError("Transform creation failed"); | |
| 348 goto Cleanup; | |
| 349 } | |
| 350 | |
| 351 hProfile = cmsTransform2DeviceLink(ContextID, hTransform, Version, dwFlags); | |
| 352 if (hProfile == NULL) { | |
| 353 FatalError("Devicelink creation failed"); | |
| 354 goto Cleanup; | |
| 355 } | |
| 356 | |
| 357 SetTextTags(ContextID, hProfile); | |
| 358 cmsSetHeaderRenderingIntent(ContextID, hProfile, Intent); | |
| 359 | |
| 360 if (cmsSaveProfileToFile(ContextID, hProfile, cOutProf)) { | |
| 361 | |
| 362 if (Verbose > 0) | |
| 363 fprintf(stderr, "Ok"); | |
| 364 } | |
| 365 else | |
| 366 FatalError("Error saving file!"); | |
| 367 | |
| 368 cmsCloseProfile(ContextID, hProfile); | |
| 369 | |
| 370 | |
| 371 Cleanup: | |
| 372 | |
| 373 if (hTransform != NULL) cmsDeleteTransform(ContextID, hTransform); | |
| 374 for (i=0; i < nargs; i++) { | |
| 375 | |
| 376 if (Profiles[i] != NULL) cmsCloseProfile(ContextID, Profiles[i]); | |
| 377 } | |
| 378 | |
| 379 return rc; | |
| 380 } |
