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
Lcms-user@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/lcms-user

Reply via email to