eBookReaderSwitch/thirdparty/lcms2/utils/common/vprf.c

337 lines
9.5 KiB
C

//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2017 Marti Maria Saguer
//
// 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 "utils.h"
int Verbose = 0;
static char ProgramName[256] = "";
void FatalError(const char *frm, ...)
{
va_list args;
va_start(args, frm);
fprintf(stderr, "[%s fatal error]: ", ProgramName);
vfprintf(stderr, frm, args);
fprintf(stderr, "\n");
va_end(args);
exit(1);
}
// Show errors to the end user (unless quiet option)
static
void MyErrorLogHandler(cmsContext ContextID, cmsUInt32Number ErrorCode, const char *Text)
{
if (Verbose >= 0)
fprintf(stderr, "[%s]: %s\n", ProgramName, Text);
UTILS_UNUSED_PARAMETER(ErrorCode);
UTILS_UNUSED_PARAMETER(ContextID);
}
void InitUtils(cmsContext ContextID, const char* PName)
{
strncpy(ProgramName, PName, sizeof(ProgramName));
ProgramName[sizeof(ProgramName)-1] = 0;
cmsSetLogErrorHandler(ContextID, MyErrorLogHandler);
}
// Virtual profiles are handled here.
cmsHPROFILE OpenStockProfile(cmsContext ContextID, const char* File)
{
if (!File)
return cmsCreate_sRGBProfile(ContextID);
if (cmsstrcasecmp(File, "*Lab2") == 0)
return cmsCreateLab2Profile(ContextID, NULL);
if (cmsstrcasecmp(File, "*Lab4") == 0)
return cmsCreateLab4Profile(ContextID, NULL);
if (cmsstrcasecmp(File, "*Lab") == 0)
return cmsCreateLab4Profile(ContextID, NULL);
if (cmsstrcasecmp(File, "*LabD65") == 0) {
cmsCIExyY D65xyY;
cmsWhitePointFromTemp(ContextID, &D65xyY, 6504);
return cmsCreateLab4Profile(ContextID, &D65xyY);
}
if (cmsstrcasecmp(File, "*XYZ") == 0)
return cmsCreateXYZProfile(ContextID);
if (cmsstrcasecmp(File, "*Gray22") == 0) {
cmsToneCurve* Curve = cmsBuildGamma(ContextID, 2.2);
cmsHPROFILE hProfile = cmsCreateGrayProfile(ContextID, cmsD50_xyY(ContextID), Curve);
cmsFreeToneCurve(ContextID, Curve);
return hProfile;
}
if (cmsstrcasecmp(File, "*Gray30") == 0) {
cmsToneCurve* Curve = cmsBuildGamma(ContextID, 3.0);
cmsHPROFILE hProfile = cmsCreateGrayProfile(ContextID, cmsD50_xyY(ContextID), Curve);
cmsFreeToneCurve(ContextID, Curve);
return hProfile;
}
if (cmsstrcasecmp(File, "*srgb") == 0)
return cmsCreate_sRGBProfile(ContextID);
if (cmsstrcasecmp(File, "*null") == 0)
return cmsCreateNULLProfile(ContextID);
if (cmsstrcasecmp(File, "*Lin2222") == 0) {
cmsToneCurve* Gamma = cmsBuildGamma(0, 2.2);
cmsToneCurve* Gamma4[4];
cmsHPROFILE hProfile;
Gamma4[0] = Gamma4[1] = Gamma4[2] = Gamma4[3] = Gamma;
hProfile = cmsCreateLinearizationDeviceLink(ContextID, cmsSigCmykData, Gamma4);
cmsFreeToneCurve(ContextID, Gamma);
return hProfile;
}
return cmsOpenProfileFromFile(ContextID, File, "r");
}
// Help on available built-ins
void PrintBuiltins(void)
{
fprintf(stderr, "\nBuilt-in profiles:\n\n");
fprintf(stderr, "\t*Lab2 -- D50-based v2 CIEL*a*b\n"
"\t*Lab4 -- D50-based v4 CIEL*a*b\n"
"\t*Lab -- D50-based v4 CIEL*a*b\n"
"\t*XYZ -- CIE XYZ (PCS)\n"
"\t*sRGB -- sRGB color space\n"
"\t*Gray22 - Monochrome of Gamma 2.2\n"
"\t*Gray30 - Monochrome of Gamma 3.0\n"
"\t*null - Monochrome black for all input\n"
"\t*Lin2222- CMYK linearization of gamma 2.2 on each channel\n");
}
// Auxiliary for printing information on profile
static
void PrintInfo(cmsContext ContextID, cmsHPROFILE h, cmsInfoType Info)
{
char* text;
int len;
len = cmsGetProfileInfoASCII(ContextID, h, Info, "en", "US", NULL, 0);
if (len == 0) return;
text = (char*) malloc(len * sizeof(char));
if (text == NULL) return;
cmsGetProfileInfoASCII(ContextID, h, Info, "en", "US", text, len);
if (strlen(text) > 0)
printf("%s\n", text);
free(text);
}
// Displays the colorant table
static
void PrintColorantTable(cmsContext ContextID, cmsHPROFILE hInput, cmsTagSignature Sig, const char* Title)
{
cmsNAMEDCOLORLIST* list;
int i, n;
if (cmsIsTag(ContextID, hInput, Sig)) {
printf("%s:\n", Title);
list = (cmsNAMEDCOLORLIST*) cmsReadTag(ContextID, hInput, Sig);
if (list == NULL) {
printf("(Unavailable)\n");
return;
}
n = cmsNamedColorCount(ContextID, list);
for (i=0; i < n; i++) {
char Name[cmsMAX_PATH];
cmsNamedColorInfo(ContextID, list, i, Name, NULL, NULL, NULL, NULL);
printf("\t%s\n", Name);
}
printf("\n");
}
}
void PrintProfileInformation(cmsContext ContextID, cmsHPROFILE hInput)
{
if (hInput == NULL) {
fprintf(stderr, "*Wrong or corrupted profile*\n");
return;
}
PrintInfo(ContextID, hInput, cmsInfoDescription);
PrintInfo(ContextID, hInput, cmsInfoManufacturer);
PrintInfo(ContextID, hInput, cmsInfoModel);
PrintInfo(ContextID, hInput, cmsInfoCopyright);
if (Verbose > 2) {
PrintColorantTable(ContextID, hInput, cmsSigColorantTableTag, "Input colorant table");
PrintColorantTable(ContextID, hInput, cmsSigColorantTableOutTag, "Input colorant out table");
}
printf("\n");
}
// -----------------------------------------------------------------------------
void PrintRenderingIntents(cmsContext ContextID)
{
cmsUInt32Number Codes[200];
char* Descriptions[200];
cmsUInt32Number n, i;
fprintf(stderr, "%ct<n> rendering intent:\n\n", SW);
n = cmsGetSupportedIntents(ContextID, 200, Codes, Descriptions);
for (i=0; i < n; i++) {
fprintf(stderr, "\t%u - %s\n", Codes[i], Descriptions[i]);
}
fprintf(stderr, "\n");
}
// ------------------------------------------------------------------------------
cmsBool SaveMemoryBlock(const cmsUInt8Number* Buffer, cmsUInt32Number dwLen, const char* Filename)
{
FILE* out = fopen(Filename, "wb");
if (out == NULL) {
FatalError("Cannot create '%s'", Filename);
return FALSE;
}
if (fwrite(Buffer, 1, dwLen, out) != dwLen) {
FatalError("Cannot write %ld bytes to %s", dwLen, Filename);
return FALSE;
}
if (fclose(out) != 0) {
FatalError("Error flushing file '%s'", Filename);
return FALSE;
}
return TRUE;
}
// ------------------------------------------------------------------------------
// Return a pixel type on depending on the number of channels
int PixelTypeFromChanCount(int ColorChannels)
{
switch (ColorChannels) {
case 1: return PT_GRAY;
case 2: return PT_MCH2;
case 3: return PT_MCH3;
case 4: return PT_CMYK;
case 5: return PT_MCH5;
case 6: return PT_MCH6;
case 7: return PT_MCH7;
case 8: return PT_MCH8;
case 9: return PT_MCH9;
case 10: return PT_MCH10;
case 11: return PT_MCH11;
case 12: return PT_MCH12;
case 13: return PT_MCH13;
case 14: return PT_MCH14;
case 15: return PT_MCH15;
default:
FatalError("What a weird separation of %d channels?!?!", ColorChannels);
return -1;
}
}
// ------------------------------------------------------------------------------
// Return number of channels of pixel type
int ChanCountFromPixelType(int ColorChannels)
{
switch (ColorChannels) {
case PT_GRAY: return 1;
case PT_RGB:
case PT_CMY:
case PT_Lab:
case PT_YUV:
case PT_YCbCr: return 3;
case PT_CMYK: return 4 ;
case PT_MCH2: return 2 ;
case PT_MCH3: return 3 ;
case PT_MCH4: return 4 ;
case PT_MCH5: return 5 ;
case PT_MCH6: return 6 ;
case PT_MCH7: return 7 ;
case PT_MCH8: return 8 ;
case PT_MCH9: return 9 ;
case PT_MCH10: return 10;
case PT_MCH11: return 11;
case PT_MCH12: return 12;
case PT_MCH13: return 12;
case PT_MCH14: return 14;
case PT_MCH15: return 15;
default:
FatalError("Unsupported color space of %d channels", ColorChannels);
return -1;
}
}