Thanks for this.
It works like a charm and is exactly what I need.
rgds
Garreth
Peter Speck wrote:
> On 18/12/2006, at 22:25, Garreth McDaid wrote:
>
>> I'd like to be able to use the functionality provided by icctrans in PHP
>> ie take 4 CMYK color channel values and convert them to RGB color
>> channel values with reference to a CMYK and sRGB ICC profile. Once I
>> have this, I can compile it into PHP.
>
> The code below might help. Execute program like:
> ./icc-translate 0 0 0 EuroscaleCoated.icc Adobe-sRGB.icc 3 - 1.0 1.0
> 0 0
> output:
> ## R=18.07 G=11.20 B=52.42 ##
>
> arg 1: 0 = silent or 1 = verbose
> arg 2: Intent (0=Perceptual, 1=Colorimetric, 2=Saturation, 3=Absolute)
> arg 3: WhiteBlackCompensation (0=False, 1=True)
> arg 4: path to input profile
> arg 5: path to output profile
> arg 6: proof intent
> arg 7: path to proof profile, or "-" if not proofing
> arg 8... input colors, can specify multiple, each value is fraction
> from zero to one (1 == 100%)
> for cmyk, 1.0 1.0 0 0 is 100% cyan, 100% yellow, 0% magenta and 0%
> black
> Output is percentage, for some unknown reason...
>
>
> I compile it using:
> CFLAGS=-I/usr/local/lcms/include
> LDFLAGS=-L/usr/local/lcms/lib
> gcc -std=c99 $CFLAGS $LDFLAGS -l lcms -o icc-translate icc-translate.c
>
>
> /*
> Little cms
> Copyright (C) 1998-2001 Marti Maria
>
> THIS SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
> EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
> WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
>
> IN NO EVENT SHALL MARTI MARIA BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
> INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
> OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
> WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY
> THEORY OF
> LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
> OF THIS SOFTWARE.
>
>
> This library is free software; you can redistribute it and/or
> modify it under the terms of the GNU Lesser General Public
> License as published by the Free Software Foundation; either
> version 2 of the License, or (at your option) any later version.
>
> This library is distributed in the hope that it will be useful,
> but WITHOUT ANY WARRANTY; without even the implied warranty of
> MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> Lesser General Public License for more details.
>
> You should have received a copy of the GNU Lesser General Public
> License along with this library; if not, write to the Free Software
> Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
> USA
> */
>
> #include "lcms.h"
> #include <stdarg.h>
> #include <ctype.h>
>
> /*
> ------------------------------------------------------------------------ */
>
> static int Verbose = 0;
> static int gArgc = 0;
> static int gArgIdx = 0;
> static char **gArgv = NULL;
> static char *cInProf = NULL;
> static char *cOutProf = NULL;
> static char *cProofing = NULL;
> static double outputScale = 255;
> static int Intent = INTENT_PERCEPTUAL;
> static int ProofingIntent = INTENT_PERCEPTUAL;
> static BOOL WhiteBlackCompensation = FALSE;
>
> static cmsHPROFILE hInput = NULL;
> static cmsHPROFILE hOutput = NULL;
> static cmsHPROFILE hProof = NULL;
> static cmsHPROFILE hLab = NULL;
> static cmsHPROFILE hXYZ = NULL;
> static cmsHTRANSFORM hTrans, hTransXYZ, hTransLab;
>
> static icColorSpaceSignature InputColorSpace, OutputColorSpace;
> static cmsCIEXYZ xyz;
> static cmsCIELab Lab;
>
> #define xisatty(x) isatty( fileno( (x) ) )
>
> #ifndef stricmp
> #define stricmp strcasecmp
> #endif
>
> static void FatalError(const char *frm,...)
> {
> va_list args;
> va_start(args, frm);
> vfprintf(stderr, frm, args);
> va_end(args);
> printf("Usage: icc-translate\n"
> " <bool> verbose (0 for false, 1 for true)\n"
> " <int> intent: 0=Perceptual, 1=Colorimetric,
> 2=Saturation, 3=Absolute\n"
> " <bool> black/white compensation\n"
> " <path> input profile\n"
> " <path> output profile\n"
> " <int> proofing intent\n"
> " <path> proofing profile, '-' for none\n"
> " <double> color values, floating point from 0 to 1\n"
> "\n"
> "Examples:\n"
> " convert black, gray and white from sRGB to CMYK:\n"
> " icc-translate 0 3 0 Adobe-sRGB.icc EuroscaleCoated.icc 0 -
> 0 0 0 0.5 0.5 0.5 1 1 1\n"
> "\n"
> " convert cmyk from Euroscale to Lanie printer, proofing
> Burda:\n"
> " icc-translate 0 3 0 EuroscaleCoated.icc Lanier.icc \\\n"
> " 3 burda2001v3.icc 0 0 0 0 0 0 0 1 0 0 1 0\n"
> );
> exit(1);
> }
>
> static char* NextArg()
> {
> if (gArgIdx + 1 >= gArgc)
> FatalError("Too few arguments\n");
> return gArgv[++gArgIdx];
> }
>
> static cmsHPROFILE OpenProfile(const char *File)
> {
> if (!File)
> return cmsCreate_sRGBProfile();
> if (stricmp(File, "*Lab") == 0)
> return cmsCreateLabProfile(NULL);
> if (stricmp(File, "*LabD65") == 0) {
> cmsCIExyY D65xyY;
> cmsWhitePointFromTemp(6504, &D65xyY);
> return cmsCreateLabProfile(&D65xyY);
> }
> if (stricmp(File, "*XYZ") == 0)
> return cmsCreateXYZProfile();
> cmsHPROFILE h = cmsOpenProfileFromFile(File, "r");
> if (h == NULL)
> FatalError("Can't open profile '%s'", File);
> return h;
> }
>
> static void OpenTransforms(void)
> {
> DWORD dwFlags = 0;
> dwFlags |= cmsFLAGS_NOTPRECALC;
> hInput = OpenProfile(cInProf);
> hOutput = OpenProfile(cOutProf);
> if (cProofing != NULL && *cProofing && strcmp(cProofing, "-")) {
> hProof = cmsOpenProfileFromFile(cProofing, "r");
> dwFlags |= cmsFLAGS_SOFTPROOFING;
> }
>
> InputColorSpace = cmsGetColorSpace(hInput);
> OutputColorSpace = cmsGetColorSpace(hOutput);
>
> if (cmsGetDeviceClass(hInput) == icSigLinkClass ||
> cmsGetDeviceClass(hOutput) == icSigLinkClass)
> FatalError("Use some flag for devicelink profiles!\n");
>
> hXYZ = cmsCreateXYZProfile();
> hLab = cmsCreateLabProfile(NULL);
>
> if (Verbose) {
> printf("From: %s\n", cmsTakeProductName(hInput));
> if (hOutput)
> printf("To: %s\n", cmsTakeProductName(hOutput));
> if (hProof)
> printf("Proof: %s\n", cmsTakeProductName(hProof));
> printf("\n");
> }
> DWORD dwIn = BYTES_SH(2) |
> CHANNELS_SH(_cmsChannelsOf(InputColorSpace));
> DWORD dwOut = BYTES_SH(2) |
> CHANNELS_SH(_cmsChannelsOf(OutputColorSpace));
>
> if (WhiteBlackCompensation)
> dwFlags |= cmsFLAGS_WHITEBLACKCOMPENSATION;
>
> if (hProof) {
> hTrans = cmsCreateProofingTransform(hInput, dwIn,
> hOutput, dwOut, hProof, Intent, ProofingIntent, dwFlags);
> } else {
> hTrans = cmsCreateTransform(hInput, dwIn,
> hOutput, dwOut, Intent, dwFlags);
> }
>
> if (Verbose) {
> hTransXYZ = cmsCreateTransform(hInput, dwIn,
> hXYZ, TYPE_XYZ_16,
> Intent, cmsFLAGS_NOTPRECALC);
> hTransLab = cmsCreateTransform(hInput, dwIn,
> hLab, TYPE_Lab_16,
> Intent, cmsFLAGS_NOTPRECALC);
> }
> }
>
>
> static void CloseTransforms(void)
> {
> cmsDeleteTransform(hTrans);
> if (hTransLab)
> cmsDeleteTransform(hTransLab);
> if (hTransXYZ)
> cmsDeleteTransform(hTransXYZ);
> cmsCloseProfile(hInput);
> if (hOutput)
> cmsCloseProfile(hOutput);
> cmsCloseProfile(hXYZ);
> cmsCloseProfile(hLab);
> }
>
>
> static void PrintOne(const char *C, double v)
> {
> v /= 257.;
> v /= 255;
> v *= outputScale;
> printf("%s=%.2f ", C, v);
> }
>
> static void PrintCooked(const char *C, double v)
> {
> printf("%s=%.4f ", C, v);
> }
>
>
> static void PrintResults(WORD Encoded[], icColorSpaceSignature ColorSpace)
> {
> switch (ColorSpace) {
> case icSigXYZData:
> cmsXYZEncoded2Float(&xyz, Encoded);
> PrintCooked("X", xyz.X * 100.);
> PrintCooked("Y", xyz.Y * 100.);
> PrintCooked("Z", xyz.Z * 100.);
> break;
>
> case icSigLabData:
> cmsLabEncoded2Float(&Lab, Encoded);
> PrintCooked("L*", Lab.L);
> PrintCooked("a*", Lab.a);
> PrintCooked("b*", Lab.b);
> break;
>
> case icSigLuvData:
> PrintOne("L", Encoded[0]);
> PrintOne("u", Encoded[1]);
> PrintOne("v", Encoded[2]);
> break;
>
> case icSigYCbCrData:
> PrintOne("Y", Encoded[0]);
> PrintOne("Cb", Encoded[1]);
> PrintOne("Cr", Encoded[2]);
> break;
>
>
> case icSigYxyData:
> PrintOne("Y", Encoded[0]);
> PrintOne("x", Encoded[1]);
> PrintOne("y", Encoded[2]);
> break;
>
> case icSigRgbData:
> PrintOne("R", Encoded[0]);
> PrintOne("G", Encoded[1]);
> PrintOne("B", Encoded[2]);
> break;
>
> case icSigGrayData:
> PrintOne("L", Encoded[0]);
> break;
>
> case icSigHsvData:
> PrintOne("H", Encoded[0]);
> PrintOne("s", Encoded[1]);
> PrintOne("v", Encoded[2]);
> break;
>
> case icSigHlsData:
> PrintOne("H", Encoded[0]);
> PrintOne("l", Encoded[1]);
> PrintOne("s", Encoded[2]);
> break;
>
> case icSigCmykData:
> PrintOne("C", Encoded[0]);
> PrintOne("M", Encoded[1]);
> PrintOne("Y", Encoded[2]);
> PrintOne("K", Encoded[3]);
> break;
>
> case icSigCmyData:
> PrintOne("C", Encoded[0]);
> PrintOne("M", Encoded[1]);
> PrintOne("Y", Encoded[2]);
> break;
>
> case icSig6colorData:
> PrintOne("C", Encoded[0]);
> PrintOne("M", Encoded[1]);
> PrintOne("Y", Encoded[2]);
> PrintOne("K", Encoded[3]);
> PrintOne("c", Encoded[1]);
> PrintOne("m", Encoded[2]);
> break;
>
> default:
> for (int i = 0; i < _cmsChannelsOf(OutputColorSpace); i++) {
> char Buffer[10];
> sprintf(Buffer, "CHAN%d", i + 1);
> PrintOne(Buffer, Encoded[i]);
> }
> }
> }
>
> static int GetVal(const char *AskFor)
> {
> double v1 = atof(NextArg());
> double v2 = v1 * 255.0 * 257.0;
> int v = (int) v2;
> if (Verbose) {
> PrintOne("GetVal", v);
> printf(" GetVal(%s) returns %.2f = %.2f = %d\n", AskFor, v1,
> v2, v);
> }
> return v2;
> }
>
>
> static double GetDbl(const char *AskFor)
> {
> return atof(NextArg());
> }
>
>
> static void TakeValues(WORD Encoded[])
> {
> switch (InputColorSpace) {
>
> case icSigXYZData:
> xyz.X = GetDbl("X");
> xyz.Y = GetDbl("Y");
> xyz.Z = GetDbl("Z");
> cmsFloat2XYZEncoded(Encoded, &xyz);
> break;
>
> case icSigLabData:
> Lab.L = GetDbl("L*");
> Lab.a = GetDbl("a*");
> Lab.b = GetDbl("b*");
> cmsFloat2LabEncoded(Encoded, &Lab);
> break;
>
> case icSigLuvData:
> Encoded[0] = GetVal("L");
> Encoded[1] = GetVal("u");
> Encoded[2] = GetVal("v");
> break;
>
> case icSigYCbCrData:
> Encoded[0] = GetVal("Y");
> Encoded[1] = GetVal("Cb");
> Encoded[2] = GetVal("Cr");
> break;
>
>
> case icSigYxyData:
> Encoded[0] = GetVal("Y");
> Encoded[1] = GetVal("x");
> Encoded[2] = GetVal("y");
> break;
>
> case icSigRgbData:
> Encoded[0] = GetVal("R");
> Encoded[1] = GetVal("G");
> Encoded[2] = GetVal("B");
> break;
>
> case icSigGrayData:
> Encoded[0] = GetVal("L");
> break;
>
> case icSigHsvData:
> Encoded[0] = GetVal("H");
> Encoded[1] = GetVal("s");
> Encoded[2] = GetVal("v");
> break;
>
> case icSigHlsData:
> Encoded[0] = GetVal("H");
> Encoded[1] = GetVal("l");
> Encoded[2] = GetVal("s");
> break;
>
> case icSigCmykData:
> Encoded[0] = GetVal("C");
> Encoded[1] = GetVal("M");
> Encoded[2] = GetVal("Y");
> Encoded[3] = GetVal("K");
> break;
>
> case icSigCmyData:
> Encoded[0] = GetVal("C");
> Encoded[1] = GetVal("M");
> Encoded[2] = GetVal("Y");
> break;
>
> case icSig6colorData:
> FatalError("Hexachrome separations unsupported on input");
> break;
>
> default:
> FatalError("Unsupported %d channel profile",
> _cmsChannelsOf(InputColorSpace));
> }
> }
>
>
> int main(int argc, char *argv[])
> {
> WORD Input[MAXCHANNELS], Output[MAXCHANNELS],
> PCSLab[MAXCHANNELS],
> PCSxyz[MAXCHANNELS];
> gArgc = argc;
> gArgv = argv;
> gArgIdx = 0;
>
> Verbose = atoi(NextArg());
> Intent = atoi(NextArg());
> if (Intent > 3 || Intent < 0)
> FatalError("Invalid intent");
> WhiteBlackCompensation = atoi(NextArg()) != 0;
> cInProf = NextArg();
> cOutProf = NextArg();
> ProofingIntent = atoi(NextArg());
> if (ProofingIntent > 3 || ProofingIntent < 0)
> FatalError("Invalid ProofingIntent");
> cProofing = NextArg();
>
> OpenTransforms();
>
> while (gArgIdx + 1 < gArgc) {
> TakeValues(Input);
> cmsDoTransform(hTrans, Input, Output, 1);
>
> if (hTransXYZ)
> cmsDoTransform(hTransXYZ, Input, PCSxyz, 1);
> if (hTransLab)
> cmsDoTransform(hTransLab, Input, PCSLab, 1);
>
> outputScale = 100;
> printf("## ");
> PrintResults(Output, OutputColorSpace);
> printf(" ##\n");
> if (Verbose) {
> outputScale = 255;
> printf("scale255: ");
> PrintResults(Output, OutputColorSpace);
> printf("\n");
> }
> if (Verbose && hTransXYZ && hTransLab) {
> PrintResults(PCSxyz, icSigXYZData);
> printf("\n");
> PrintResults(PCSLab, icSigLabData);
> printf("\n");
> }
> }
> return 0;
> }
>
>
> ----
> - Peter Speck
>
>
>
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Lcms-user mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/lcms-user