Subversion Repositories Scribus

Compare Revisions

Ignore whitespace Rev 2453 → Rev 2454

/trunk/lprof/src/cmsprf.c
0,0 → 1,439
//
// Little cms - profiler construction set
// 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 "lcmsprf.h"
 
 
double cdecl _cmsxSaturate65535To255(double d);
double cdecl _cmsxSaturate255To65535(double d);
 
 
void cdecl _cmsxClampXYZ100(LPcmsCIEXYZ xyz);
 
 
BOOL cdecl cmsxEmbedCharTarget(LPPROFILERCOMMONDATA hdr);
BOOL cdecl cmsxEmbedMatrixShaper(LPPROFILERCOMMONDATA hdr);
BOOL cdecl cmsxEmbedTextualInfo(LPPROFILERCOMMONDATA hdr);
 
// ----------------------------------------------------------------- Implementation
 
 
// Convert from 0.0..65535.0 to 0.0..255.0
 
double _cmsxSaturate65535To255(double d)
{
double v;
 
v = d / 257.0;
 
if (v < 0) return 0;
if (v > 255.0) return 255.0;
 
return v;
}
 
 
double _cmsxSaturate255To65535(double d)
{
double v;
 
v = d * 257.0;
 
if (v < 0) return 0;
if (v > 65535.0) return 65535.0;
 
return v;
}
 
 
 
// Cut off absurd values
 
void _cmsxClampXYZ100(LPcmsCIEXYZ xyz)
{
 
if (xyz->X > 199.996)
xyz->X = 199.996;
if (xyz->Y > 199.996)
xyz->Y = 199.996;
if (xyz->Z > 199.996)
xyz->Z = 199.996;
if (xyz->Y < 0)
xyz->Y = 0;
 
if (xyz->X < 0)
xyz->X = 0;
 
if (xyz->Z < 0)
xyz->Z = 0;
 
}
 
static
int xfilelength(int fd)
{
#ifdef _MSC_VER
return _filelength(fd);
#else
struct stat sb;
if (fstat(fd, &sb) < 0)
return(-1);
return(sb.st_size);
#endif
 
 
}
 
 
BOOL cmsxEmbedCharTarget(LPPROFILERCOMMONDATA hdr)
{
LCMSHANDLE it8 = cmsxIT8Alloc();
LPBYTE mem;
size_t size, readed;
FILE* f;
BOOL lFreeOnExit = FALSE;
 
 
if (!hdr->m.Patches) {
 
if (!hdr ->ReferenceSheet[0] && !hdr->MeasurementSheet[0]) return FALSE;
 
if (cmsxPCollBuildMeasurement(&hdr ->m,
hdr->ReferenceSheet,
hdr->MeasurementSheet,
PATCH_HAS_RGB|PATCH_HAS_XYZ) == FALSE) return FALSE;
lFreeOnExit = TRUE;
}
 
cmsxIT8SetSheetType(it8,"LCMSEMBED");
cmsxIT8SetProperty(it8, "ORIGINATOR", (const char *) "Little cms");
cmsxIT8SetProperty(it8, "DESCRIPTOR", (const char *) hdr -> Description);
cmsxIT8SetProperty(it8, "MANUFACTURER", (const char *) hdr ->Manufacturer);
cmsxPCollSaveToSheet(&hdr->m, it8);
cmsxIT8SaveToFile(it8, "TMP00.IT8");
cmsxIT8Free(it8);
 
f = fopen("TMP00.IT8", "rb");
size = xfilelength(fileno(f));
mem = (char*) malloc(size + 1);
readed = fread(mem, 1, size, f);
fclose(f);
 
mem[readed] = 0;
unlink("TMP00.IT8");
 
cmsAddTag(hdr->hProfile, icSigCharTargetTag, mem);
free(mem);
 
if (lFreeOnExit) {
cmsxPCollFreeMeasurements(&hdr->m);
}
 
return TRUE;
}
 
 
static
BOOL ComputeColorantMatrix(LPcmsCIEXYZTRIPLE Colorants,
LPcmsCIExyY WhitePoint,
LPcmsCIExyYTRIPLE Primaries)
{
MAT3 MColorants;
if (!cmsBuildRGB2XYZtransferMatrix(&MColorants, WhitePoint, Primaries))
{
return FALSE;
}
 
cmsAdaptMatrixToD50(&MColorants, WhitePoint);
 
Colorants->Red.X = MColorants.v[0].n[0];
Colorants->Red.Y = MColorants.v[1].n[0];
Colorants->Red.Z = MColorants.v[2].n[0];
 
Colorants->Green.X = MColorants.v[0].n[1];
Colorants->Green.Y = MColorants.v[1].n[1];
Colorants->Green.Z = MColorants.v[2].n[1];
 
Colorants->Blue.X = MColorants.v[0].n[2];
Colorants->Blue.Y = MColorants.v[1].n[2];
Colorants->Blue.Z = MColorants.v[2].n[2];
 
return TRUE;
 
}
 
 
BOOL cmsxEmbedMatrixShaper(LPPROFILERCOMMONDATA hdr)
{
cmsCIEXYZTRIPLE Colorant;
cmsCIExyY MediaWhite;
 
cmsXYZ2xyY(&MediaWhite, &hdr ->WhitePoint);
 
if (ComputeColorantMatrix(&Colorant, &MediaWhite, &hdr ->Primaries)) {
 
cmsAddTag(hdr ->hProfile, icSigRedColorantTag, &Colorant.Red);
cmsAddTag(hdr ->hProfile, icSigGreenColorantTag, &Colorant.Green);
cmsAddTag(hdr ->hProfile, icSigBlueColorantTag, &Colorant.Blue);
}
 
cmsAddTag(hdr ->hProfile, icSigRedTRCTag, hdr ->Gamma[0]);
cmsAddTag(hdr ->hProfile, icSigGreenTRCTag, hdr ->Gamma[1]);
cmsAddTag(hdr ->hProfile, icSigBlueTRCTag, hdr ->Gamma[2]);
 
return TRUE;
}
 
 
BOOL cmsxEmbedTextualInfo(LPPROFILERCOMMONDATA hdr)
{
if (*hdr ->Description)
cmsAddTag(hdr ->hProfile, icSigProfileDescriptionTag, hdr ->Description);
if (*hdr ->Copyright)
cmsAddTag(hdr ->hProfile, icSigCopyrightTag, hdr ->Copyright);
if (*hdr ->Manufacturer)
cmsAddTag(hdr ->hProfile, icSigDeviceMfgDescTag, hdr ->Manufacturer);
if (*hdr ->Model)
cmsAddTag(hdr ->hProfile, icSigDeviceModelDescTag, hdr ->Model);
 
return TRUE;
}
 
 
 
void cmsxChromaticAdaptationAndNormalization(LPPROFILERCOMMONDATA hdr, LPcmsCIEXYZ xyz, BOOL lReverse)
{
if (hdr->lUseCIECAM97s) {
 
cmsJCh JCh;
 
// Let's CIECAM97s to do the adaptation to D50
xyz->X *= 100.;
xyz->Y *= 100.;
xyz->Z *= 100.;
 
_cmsxClampXYZ100(xyz);
 
if (lReverse) {
cmsCIECAM97sForward(hdr->hPCS, xyz, &JCh);
cmsCIECAM97sReverse(hdr->hDevice, &JCh, xyz);
}
else {
 
cmsCIECAM97sForward(hdr->hDevice, xyz, &JCh);
cmsCIECAM97sReverse(hdr->hPCS, &JCh, xyz);
}
 
_cmsxClampXYZ100(xyz);
 
xyz -> X /= 100.;
xyz -> Y /= 100.;
xyz -> Z /= 100.;
}
else {
// Else, use Bradford
 
if (lReverse) {
cmsAdaptToIlluminant(xyz, cmsD50_XYZ(), &hdr->WhitePoint, xyz);
}
else {
cmsAdaptToIlluminant(xyz, &hdr->WhitePoint, cmsD50_XYZ(), xyz);
}
}
}
 
 
void cmsxInitPCSViewingConditions(LPPROFILERCOMMONDATA hdr)
{
hdr->PCS.whitePoint.X = cmsD50_XYZ()->X * 100.;
hdr->PCS.whitePoint.Y = cmsD50_XYZ()->Y * 100.;
hdr->PCS.whitePoint.Z = cmsD50_XYZ()->Z * 100.;
 
 
hdr->PCS.Yb = 20; // 20% of surround
hdr->PCS.La = 20; // Adapting field luminance
hdr->PCS.surround = AVG_SURROUND;
hdr->PCS.D_value = 1.0; // Complete adaptation
 
}
 
 
// Build gamut hull by geometric means
void cmsxComputeGamutHull(LPPROFILERCOMMONDATA hdr)
{
int i;
int x0, y0, z0;
int Inside, Outside, Boundaries;
char code;
 
 
hdr -> hRGBHull = cmsxHullInit();
 
// For all valid patches, mark RGB knots as 0
for (i=0; i < hdr ->m.nPatches; i++) {
 
if (hdr ->m.Allowed[i]) {
 
LPPATCH p = hdr ->m.Patches + i;
 
 
x0 = (int) floor(p->Colorant.RGB[0] + .5);
y0 = (int) floor(p->Colorant.RGB[1] + .5);
z0 = (int) floor(p->Colorant.RGB[2] + .5);
 
cmsxHullAddPoint(hdr->hRGBHull, x0, y0, z0);
}
}
cmsxHullComputeHull(hdr ->hRGBHull);
 
// #ifdef DEBUG
cmsxHullDumpVRML(hdr -> hRGBHull, "rgbhull.wrl");
// #endif
 
 
 
// A check
 
Inside = Outside = Boundaries = 0;
// For all valid patches, mark RGB knots as 0
for (i=0; i < hdr ->m.nPatches; i++) {
 
if (hdr ->m.Allowed[i]) {
 
LPPATCH p = hdr ->m.Patches + i;
 
x0 = (int) floor(p->Colorant.RGB[0] + .5);
y0 = (int) floor(p->Colorant.RGB[1] + .5);
z0 = (int) floor(p->Colorant.RGB[2] + .5);
 
code = cmsxHullCheckpoint(hdr -> hRGBHull, x0, y0, z0);
 
switch (code) {
case 'i': Inside++; break;
case 'o': Outside++; break;
default: Boundaries++;
}
 
}
}
 
if (hdr ->printf)
hdr ->printf("Gamut hull: %d inside, %d outside, %d on boundaries", Inside, Outside, Boundaries);
}
 
BOOL cmsxChoosePCS(LPPROFILERCOMMONDATA hdr)
{
 
double gamma_r, gamma_g, gamma_b;
cmsCIExyY SourceWhite;
 
// At first, compute aproximation on matrix-shaper
if (!cmsxComputeMatrixShaper(hdr ->ReferenceSheet,
hdr ->MeasurementSheet,
hdr -> Medium,
hdr ->Gamma,
&hdr ->WhitePoint,
&hdr ->BlackPoint,
&hdr ->Primaries)) return FALSE;
 
 
cmsXYZ2xyY(&SourceWhite, &hdr ->WhitePoint);
gamma_r = cmsEstimateGamma(hdr ->Gamma[0]);
gamma_g = cmsEstimateGamma(hdr ->Gamma[1]);
gamma_b = cmsEstimateGamma(hdr ->Gamma[2]);
 
 
if (gamma_r > 1.8 || gamma_g > 1.8 || gamma_b > 1.8 ||
gamma_r == -1 || gamma_g == -1 || gamma_b == -1) {
 
hdr ->PCSType = PT_Lab;
 
if (hdr ->printf)
hdr ->printf("I have choosen Lab as PCS");
 
}
else {
hdr ->PCSType = PT_XYZ;
 
if (hdr ->printf)
hdr ->printf("I have choosen XYZ as PCS");
}
 
 
if (hdr ->printf) {
 
char Buffer[256] = "Infered ";
_cmsIdentifyWhitePoint(Buffer, &hdr ->WhitePoint);
hdr ->printf("%s", Buffer);
hdr ->printf("Primaries (x-y): [Red: %2.2f, %2.2f] [Green: %2.2f, %2.2f] [Blue: %2.2f, %2.2f]",
hdr ->Primaries.Red.x, hdr ->Primaries.Red.y,
hdr ->Primaries.Green.x, hdr ->Primaries.Green.y,
hdr ->Primaries.Blue.x, hdr ->Primaries.Blue.y);
 
if ((gamma_r != -1) && (gamma_g != -1) && (gamma_b != -1)) {
hdr ->printf("Estimated gamma: [Red: %2.2f] [Green: %2.2f] [Blue: %2.2f]",
gamma_r, gamma_g, gamma_b);
}
 
}
 
 
return TRUE;
}
Property changes:
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Revision
\ No newline at end of property