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