Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mm2/Little-CMS.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
authorMarti Maria <info@littlecms.com>2010-03-16 16:44:25 +0300
committerMarti Maria <info@littlecms.com>2010-03-16 16:44:25 +0300
commitc3934910e193c76237850b5a904d47d5a3946c0f (patch)
treefd73e73c523ef77dc8dd886b4eea0189db8e24b5 /utils
parentbda1fa929aea10ce50f37aeaf72b579630b07c14 (diff)
Added MatLab support
Diffstat (limited to 'utils')
-rwxr-xr-xutils/matlab/icctrans.c689
-rwxr-xr-xutils/matlab/lcms_rsp27
2 files changed, 716 insertions, 0 deletions
diff --git a/utils/matlab/icctrans.c b/utils/matlab/icctrans.c
new file mode 100755
index 0000000..d7cd7d8
--- /dev/null
+++ b/utils/matlab/icctrans.c
@@ -0,0 +1,689 @@
+//
+// Little cms
+// Copyright (C) 1998-2010 Marti Maria, Ignacio Ruiz de Conejo
+//
+// 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 "mex.h"
+
+#include "lcms2.h"
+#include "string.h"
+#include "stdarg.h"
+
+// xgetopt() interface -----------------------------------------------------
+
+static int xoptind;
+static char *xoptarg;
+static int xopterr;
+static char *letP;
+static char SW = '-';
+
+// ------------------------------------------------------------------------
+
+
+static int Verbose ; // Print some statistics
+static char *cInProf; // Input profile
+static char *cOutProf; // Output profile
+static char *cProofing; // Softproofing profile
+
+
+static int Intent; // Rendering Intent
+static int ProofingIntent; // RI for proof
+
+static int PrecalcMode; // 0 = Not, 1=Normal, 2=Accurate, 3=Fast
+
+static cmsBool BlackPointCompensation;
+static cmsBool lIsDeviceLink;
+static cmsBool lMultiProfileChain; // Multiple profile chain
+
+static cmsHPROFILE hInput, hOutput, hProof;
+static cmsHTRANSFORM hColorTransform;
+static cmsHPROFILE hProfiles[255];
+static int nProfiles;
+
+static cmsColorSpaceSignature InputColorSpace, OutputColorSpace;
+static int OutputChannels, InputChannels, nBytesDepth;
+
+
+// Error. Print error message and abort
+
+static
+cmsBool FatalError(const char *frm, ...)
+{
+ va_list args;
+ char Buffer[1024];
+
+ va_start(args, frm);
+ vsprintf(Buffer, frm, args);
+ mexErrMsgTxt(Buffer);
+ va_end(args);
+
+ return FALSE;
+}
+
+// This is the handler passed to lcms
+
+static
+void MatLabErrorHandler(cmsContext ContextID, cmsUInt32Number ErrorCode,
+ const char *Text)
+{
+ mexErrMsgTxt(Text);
+}
+//
+// Parse the command line options, System V style.
+//
+
+static
+void xoptinit()
+{
+ xoptind = 1;
+ xopterr = 0;
+ letP = NULL;
+}
+
+
+static
+int xgetopt(int argc, char *argv[], char *optionS)
+{
+ unsigned char ch;
+ char *optP;
+
+ if (SW == 0) {
+ SW = '/';
+ }
+
+ if (argc > xoptind) {
+ if (letP == NULL) {
+ if ((letP = argv[xoptind]) == NULL ||
+ *(letP++) != SW) goto gopEOF;
+ if (*letP == SW) {
+ xoptind++; goto gopEOF;
+ }
+ }
+ if (0 == (ch = *(letP++))) {
+ xoptind++; goto gopEOF;
+ }
+ if (':' == ch || (optP = strchr(optionS, ch)) == NULL)
+ goto gopError;
+ if (':' == *(++optP)) {
+ xoptind++;
+ if (0 == *letP) {
+ if (argc <= xoptind) goto gopError;
+ letP = argv[xoptind++];
+ }
+ xoptarg = letP;
+ letP = NULL;
+ } else {
+ if (0 == *letP) {
+ xoptind++;
+ letP = NULL;
+ }
+ xoptarg = NULL;
+ }
+ return ch;
+ }
+gopEOF:
+ xoptarg = letP = NULL;
+ return EOF;
+
+gopError:
+ xoptarg = NULL;
+ if (xopterr)
+ FatalError ("get command line option");
+ return ('?');
+}
+
+
+// Return Mathlab type by depth
+
+static
+size_t SizeOfArrayType(const mxArray *Array)
+{
+
+ switch (mxGetClassID(Array)) {
+
+ case mxINT8_CLASS: return 1;
+ case mxUINT8_CLASS: return 1;
+ case mxINT16_CLASS: return 2;
+ case mxUINT16_CLASS: return 2;
+ case mxSINGLE_CLASS: return 4;
+ case mxDOUBLE_CLASS: return 0; // Special case -- lcms handles double as size=0
+
+
+ default:
+ FatalError("Unsupported data type");
+ return 0;
+ }
+}
+
+
+// Get number of pixels of input array. Supported arrays are
+// organized as NxMxD, being N and M the size of image and D the
+// number of components.
+
+static
+size_t GetNumberOfPixels(const mxArray* In)
+{
+ int nDimensions = mxGetNumberOfDimensions(In);
+ const int *Dimensions = mxGetDimensions(In);
+
+ switch (nDimensions) {
+
+ case 1: return 1; // It is just a spot color
+ case 2: return Dimensions[0]; // A scanline
+ case 3: return Dimensions[0]*Dimensions[1]; // A image
+
+ default:
+ FatalError("Unsupported array of %d dimensions", nDimensions);
+ return 0;
+ }
+}
+
+
+// Allocates the output array. Copies the input array modifying the pixel
+// definition to match "OutputChannels".
+
+static
+mxArray* AllocateOutputArray(const mxArray* In, int OutputChannels)
+{
+
+ mxArray* Out = mxDuplicateArray(In); // Make a "deep copy" of Input array
+ int nDimensions = mxGetNumberOfDimensions(In);
+ const int* Dimensions = mxGetDimensions(In);
+ int InputChannels = Dimensions[nDimensions-1];
+
+
+ // Modify pixel size only if needed
+
+ if (InputChannels != OutputChannels) {
+
+
+ int i, NewSize;
+ int *ModifiedDimensions = (int*) mxMalloc(nDimensions * sizeof(int));
+
+
+ mexPrintf("Pepitez nOut=%d\n", OutputChannels);
+
+ memmove(ModifiedDimensions, Dimensions, nDimensions * sizeof(int));
+ ModifiedDimensions[nDimensions - 1] = OutputChannels;
+
+ switch (mxGetClassID(In)) {
+
+ case mxINT8_CLASS: NewSize = sizeof(char); break;
+ case mxUINT8_CLASS: NewSize = sizeof(unsigned char); break;
+ case mxINT16_CLASS: NewSize = sizeof(short); break;
+ case mxUINT16_CLASS: NewSize = sizeof(unsigned short); break;
+
+ default:
+ case mxDOUBLE_CLASS: NewSize = sizeof(double); break;
+ }
+
+
+ // NewSize = 1;
+ for (i=0; i < nDimensions; i++)
+ NewSize *= ModifiedDimensions[i];
+
+
+ mxSetDimensions(Out, ModifiedDimensions, nDimensions);
+ mxFree(ModifiedDimensions);
+
+ mxSetPr(Out, mxRealloc(mxGetPr(Out), NewSize));
+
+ }
+
+
+ return Out;
+}
+
+
+
+// Does create a format descriptor. "Bytes" is the sizeof type in bytes
+//
+// Bytes Meaning
+// ------ --------
+// 0 Floating point (double)
+// 1 8-bit samples
+// 2 16-bit samples
+
+static
+cmsUInt32Number MakeFormatDescriptor(cmsColorSpaceSignature ColorSpace, int Bytes)
+{
+ int Channels = cmsChannelsOf(ColorSpace);
+ return COLORSPACE_SH(_cmsLCMScolorSpace(ColorSpace))|BYTES_SH(Bytes)|CHANNELS_SH(Channels)|PLANAR_SH(1);
+}
+
+
+// Opens a profile or proper built-in
+
+static
+cmsHPROFILE OpenProfile(const char* File)
+{
+
+ if (!File)
+ return cmsCreate_sRGBProfile();
+
+ if (cmsstrcasecmp(File, "*sRGB") == 0)
+ return cmsCreate_sRGBProfile();
+
+ if (cmsstrcasecmp(File, "*Lab") == 0)
+ return cmsCreateLab4Profile(NULL);
+
+ if (cmsstrcasecmp(File, "*LabD65") == 0) {
+
+ cmsCIExyY D65xyY;
+
+ cmsWhitePointFromTemp(&D65xyY, 6504);
+ return cmsCreateLab4Profile(&D65xyY);
+ }
+
+ if (cmsstrcasecmp(File, "*XYZ") == 0)
+ return cmsCreateXYZProfile();
+
+ if (cmsstrcasecmp(File, "*Gray22") == 0) {
+ cmsToneCurve* Gamma = cmsBuildGamma(NULL, 2.2);
+ cmsHPROFILE hProfile = cmsCreateGrayProfile(cmsD50_xyY(), Gamma);
+ cmsFreeToneCurve(Gamma);
+ return hProfile;
+
+ }
+
+ return cmsOpenProfileFromFile(File, "r");
+}
+
+
+static
+cmsUInt32Number GetFlags()
+{
+ cmsUInt32Number dwFlags = 0;
+
+ switch (PrecalcMode) {
+
+ case 0: dwFlags = cmsFLAGS_NOOPTIMIZE; break;
+ case 2: dwFlags = cmsFLAGS_HIGHRESPRECALC; break;
+ case 3: dwFlags = cmsFLAGS_LOWRESPRECALC; break;
+ case 1: break;
+
+ default: FatalError("Unknown precalculation mode '%d'", PrecalcMode);
+ }
+
+ if (BlackPointCompensation)
+ dwFlags |= cmsFLAGS_BLACKPOINTCOMPENSATION;
+
+ return dwFlags;
+}
+
+// Create transforms
+
+static
+void OpenTransforms(int argc, char *argv[])
+{
+
+ cmsUInt32Number dwIn, dwOut, dwFlags;
+
+
+ if (lMultiProfileChain) {
+
+ int i;
+ cmsHTRANSFORM hTmp;
+
+
+ nProfiles = argc - xoptind;
+ for (i=0; i < nProfiles; i++) {
+
+ hProfiles[i] = OpenProfile(argv[i+xoptind]);
+ }
+
+
+ // Create a temporary devicelink
+
+ hTmp = cmsCreateMultiprofileTransform(hProfiles, nProfiles,
+ 0, 0, Intent, GetFlags());
+
+ hInput = cmsTransform2DeviceLink(hTmp, 4.2, 0);
+ hOutput = NULL;
+ cmsDeleteTransform(hTmp);
+
+ InputColorSpace = cmsGetColorSpace(hInput);
+ OutputColorSpace = cmsGetPCS(hInput);
+ lIsDeviceLink = TRUE;
+
+ }
+ else
+ if (lIsDeviceLink) {
+
+ hInput = cmsOpenProfileFromFile(cInProf, "r");
+ hOutput = NULL;
+ InputColorSpace = cmsGetColorSpace(hInput);
+ OutputColorSpace = cmsGetPCS(hInput);
+
+
+ }
+ else {
+
+ hInput = OpenProfile(cInProf);
+ hOutput = OpenProfile(cOutProf);
+
+ InputColorSpace = cmsGetColorSpace(hInput);
+ OutputColorSpace = cmsGetColorSpace(hOutput);
+
+ if (cmsGetDeviceClass(hInput) == cmsSigLinkClass ||
+ cmsGetDeviceClass(hOutput) == cmsSigLinkClass)
+ FatalError("Use %cl flag for devicelink profiles!\n", SW);
+
+ }
+
+
+ /*
+
+ if (Verbose) {
+
+ mexPrintf("From: %s\n", cmsTakeProductName(hInput));
+ if (hOutput) mexPrintf("To : %s\n\n", cmsTakeProductName(hOutput));
+
+ }
+ */
+
+
+ OutputChannels = cmsChannelsOf(OutputColorSpace);
+ InputChannels = cmsChannelsOf(InputColorSpace);
+
+
+ dwIn = MakeFormatDescriptor(InputColorSpace, nBytesDepth);
+ dwOut = MakeFormatDescriptor(OutputColorSpace, nBytesDepth);
+
+
+ dwFlags = GetFlags();
+
+ if (cProofing != NULL) {
+
+ hProof = OpenProfile(cProofing);
+ dwFlags |= cmsFLAGS_SOFTPROOFING;
+ }
+
+
+
+
+ hColorTransform = cmsCreateProofingTransform(hInput, dwIn,
+ hOutput, dwOut,
+ hProof, Intent,
+ ProofingIntent,
+ dwFlags);
+
+
+
+}
+
+
+
+static
+void ApplyTransforms(const mxArray *In, mxArray *Out)
+{
+ double *Input = mxGetPr(In);
+ double *Output = mxGetPr(Out);
+ size_t nPixels = GetNumberOfPixels(In);;
+
+ cmsDoTransform(hColorTransform, Input, Output, nPixels );
+
+}
+
+
+static
+void CloseTransforms(void)
+{
+ int i;
+
+ if (hColorTransform) cmsDeleteTransform(hColorTransform);
+ if (hInput) cmsCloseProfile(hInput);
+ if (hOutput) cmsCloseProfile(hOutput);
+ if (hProof) cmsCloseProfile(hProof);
+
+ for (i=0; i < nProfiles; i++)
+ cmsCloseProfile(hProfiles[i]);
+
+ hColorTransform = NULL; hInput = NULL; hOutput = NULL; hProof = NULL;
+}
+
+
+static
+void HandleSwitches(int argc, char *argv[])
+{
+ int s;
+
+ xoptinit();
+
+ while ((s = xgetopt(argc, argv,"C:c:VvbBI:i:O:o:T:t:L:l:r:r:P:p:Mm")) != EOF) {
+
+
+ switch (s){
+
+ case 'b':
+ case 'B':
+ BlackPointCompensation = TRUE;
+ break;
+
+ case 'c':
+ case 'C':
+ PrecalcMode = atoi(xoptarg);
+ if (PrecalcMode < 0 || PrecalcMode > 3)
+ FatalError("Unknown precalc mode '%d'", PrecalcMode);
+ break;
+
+ case 'v':
+ case 'V':
+ Verbose = TRUE;
+ break;
+
+ case 'i':
+ case 'I':
+ if (lIsDeviceLink)
+ FatalError("Device-link already specified");
+ cInProf = xoptarg;
+ break;
+
+ case 'o':
+ case 'O':
+ if (lIsDeviceLink)
+ FatalError("Device-link already specified");
+ cOutProf = xoptarg;
+ break;
+
+ case 't':
+ case 'T':
+ Intent = atoi(xoptarg);
+ if (Intent > 3) Intent = 3;
+ if (Intent < 0) Intent = 0;
+ break;
+
+
+ case 'l':
+ case 'L':
+ cInProf = xoptarg;
+ lIsDeviceLink = TRUE;
+ break;
+
+ case 'p':
+ case 'P':
+ cProofing = xoptarg;
+ break;
+
+
+
+ case 'r':
+ case 'R':
+ ProofingIntent = atoi(xoptarg);
+ if (ProofingIntent > 3) ProofingIntent = 3;
+ if (ProofingIntent < 0) ProofingIntent = 0;
+ break;
+
+
+ case 'm':
+ case 'M':
+ lMultiProfileChain = TRUE;
+ break;
+
+ default:
+ FatalError("Unknown option.");
+ }
+ }
+
+ // For multiprofile, need to specify -m
+
+ if (xoptind < argc) {
+
+ if (!lMultiProfileChain)
+ FatalError("Use %cm for multiprofile transforms", SW);
+ }
+
+}
+
+
+
+// -------------------------------------------------- Print some fancy help
+static
+void PrintHelp(void)
+{
+ mexPrintf("(MX) little cms ColorSpace conversion tool - v2.0\n\n");
+
+ mexPrintf("usage: icctrans (mVar, flags)\n\n");
+
+ mexPrintf("mVar : Matlab array.\n");
+ mexPrintf("flags: a string containing one or more of following options.\n\n");
+ mexPrintf("\t%cv - Verbose\n", SW);
+ mexPrintf("\t%ci<profile> - Input profile (defaults to sRGB)\n", SW);
+ mexPrintf("\t%co<profile> - Output profile (defaults to sRGB)\n", SW);
+ mexPrintf("\t%cl<profile> - Transform by device-link profile\n", SW);
+ mexPrintf("\t%cm<profiles> - Apply multiprofile chain\n", SW);
+
+ mexPrintf("\t%ct<n> - Rendering intent\n", SW);
+
+ mexPrintf("\t%cb - Black point compensation\n", SW);
+ mexPrintf("\t%cc<0,1,2,3> - Optimize transform (0=Off, 1=Normal, 2=Hi-res, 3=Lo-Res) [defaults to 1]\n", SW);
+
+ mexPrintf("\t%cp<profile> - Soft proof profile\n", SW);
+ mexPrintf("\t%cr<0,1,2,3> - Soft proof intent\n", SW);
+
+ mexPrintf("\nYou can use following built-ins as profiles:\n\n");
+ mexPrintf("\t'*sRGB' -> IEC6 1996-2.1 sRGB\n");
+ mexPrintf("\t'*Lab' -> D50 based Lab\n");
+ mexPrintf("\t'*LabD65' -> D65 based Lab\n");
+ mexPrintf("\t'*XYZ' -> XYZ (D50)\n");
+ mexPrintf("\t'*Gray22' -> D50 gamma 2.2 grayscale.\n\n");
+
+ mexPrintf("For suggestions, comments, bug reports etc. send mail to info@littlecms.com\n\n");
+
+}
+
+
+
+// Main entry point
+
+void mexFunction(
+ int nlhs, // Number of left hand side (output) arguments
+ mxArray *plhs[], // Array of left hand side arguments
+ int nrhs, // Number of right hand side (input) arguments
+ const mxArray *prhs[] // Array of right hand side arguments
+)
+{
+
+ char CommandLine[4096+1];
+ char *pt, *argv[128];
+ int argc = 1;
+
+
+ if (nrhs != 2) {
+
+ PrintHelp();
+ return;
+ }
+
+
+ if(nlhs > 1) {
+ FatalError("Too many output arguments.");
+ }
+
+
+ // Setup error handler
+
+ cmsSetLogErrorHandler(MatLabErrorHandler);
+
+ // Defaults
+
+ Verbose = 0;
+ cInProf = NULL;
+ cOutProf = NULL;
+ cProofing = NULL;
+
+ lMultiProfileChain = FALSE;
+ nProfiles = 0;
+
+ Intent = INTENT_PERCEPTUAL;
+ ProofingIntent = INTENT_ABSOLUTE_COLORIMETRIC;
+ PrecalcMode = 1;
+ BlackPointCompensation = FALSE;
+ lIsDeviceLink = FALSE;
+
+ // Check types. Fist parameter is array of values, second parameter is command line
+
+ if (!mxIsNumeric(prhs[0]))
+ FatalError("Type mismatch on argument 1 -- Must be numeric");
+
+ if (!mxIsChar(prhs[1]))
+ FatalError("Type mismatch on argument 2 -- Must be string");
+
+
+
+
+ // Unpack string to command line buffer
+
+ if (mxGetString(prhs[1], CommandLine, 4096))
+ FatalError("Cannot unpack command string");
+
+ // Separate to argv[] convention
+
+ argv[0] = NULL;
+ for (pt = strtok(CommandLine, " ");
+ pt;
+ pt = strtok(NULL, " ")) {
+
+ argv[argc++] = pt;
+ }
+
+
+
+ // Parse arguments
+ HandleSwitches(argc, argv);
+
+
+ nBytesDepth = SizeOfArrayType(prhs[0]);
+
+ OpenTransforms(argc, argv);
+
+
+ plhs[0] = AllocateOutputArray(prhs[0], OutputChannels);
+
+
+ ApplyTransforms(prhs[0], plhs[0]);
+
+ CloseTransforms();
+
+ // Done!
+}
+
+
diff --git a/utils/matlab/lcms_rsp b/utils/matlab/lcms_rsp
new file mode 100755
index 0000000..c2b8c8d
--- /dev/null
+++ b/utils/matlab/lcms_rsp
@@ -0,0 +1,27 @@
+-O
+-I..\..\include
+icctrans.c
+..\..\src\cmscam02.c
+..\..\src\cmscgats.c
+..\..\src\cmscnvrt.c
+..\..\src\cmserr.c
+..\..\src\cmsgamma.c
+..\..\src\cmsgmt.c
+..\..\src\cmsintrp.c
+..\..\src\cmsio0.c
+..\..\src\cmsio1.c
+..\..\src\cmslut.c
+..\..\src\cmsmd5.c
+..\..\src\cmsmtrx.c
+..\..\src\cmsnamed.c
+..\..\src\cmsopt.c
+..\..\src\cmspack.c
+..\..\src\cmspcs.c
+..\..\src\cmsplugin.c
+..\..\src\cmsps2.c
+..\..\src\cmssamp.c
+..\..\src\cmssm.c
+..\..\src\cmstypes.c
+..\..\src\cmsvirt.c
+..\..\src\cmswtpnt.c
+..\..\src\cmsxform.c