1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
|
/* this is taken from recent versions of libeog based on Ross Burton's patch */
/*
* right now we return the parsed profile rather than the data to avoid wrapping the XFree
* as well.
*/
#include <config.h>
#include <gtk/gtk.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <gdk/gdkx.h>
#include <lcms.h>
cmsHPROFILE *
f_screen_get_profile (GdkScreen *screen)
{
Display *dpy;
Atom icc_atom, type;
int format;
gulong nitems;
gulong bytes_after;
guchar *str;
int result;
cmsHPROFILE *profile;
dpy = GDK_DISPLAY_XDISPLAY (gdk_screen_get_display (screen));
icc_atom = gdk_x11_get_xatom_by_name_for_display (gdk_screen_get_display (screen), "_ICC_PROFILE");
result = XGetWindowProperty (dpy, GDK_WINDOW_XID (gdk_screen_get_root_window (screen)),
icc_atom, 0, G_MAXLONG,
False, XA_CARDINAL, &type, &format, &nitems,
&bytes_after, (guchar **)&str);
/* TODO: handle bytes_after != 0 */
if (nitems) {
profile = cmsOpenProfileFromMem(str, nitems);
XFree (str);
return profile;
} else
return NULL;
}
typedef struct {
double Exposure;
double Brightness;
double Contrast;
double Hue;
double Saturation;
cmsCIEXYZ WPsrc, WPdest;
} BCHSWADJUSTS, *LPBCHSWADJUSTS;
static
int bchswSampler(register WORD In[], register WORD Out[], register LPVOID Cargo)
{
cmsCIELab LabIn, LabOut;
cmsCIELCh LChIn, LChOut;
cmsCIEXYZ XYZ;
double l;
double power;
gboolean shift;
LPBCHSWADJUSTS bchsw = (LPBCHSWADJUSTS) Cargo;
cmsLabEncoded2Float(&LabIn, In);
// Move white point in Lab
cmsLab2XYZ(&bchsw ->WPsrc, &XYZ, &LabIn);
cmsXYZ2Lab(&bchsw ->WPdest, &LabIn, &XYZ);
shift = (LabIn.L > 0.5);
l = LabIn.L / 100;
if (shift)
l = 1.0 - l;
if (l < 0.0)
l = 0.0;
if (bchsw->Contrast < 0)
power = 1.0 + bchsw->Contrast;
else
power = (bchsw->Contrast == 1.0) ? 127 : 1.0 / (1.0 - bchsw->Contrast);
l = 0.5 * pow (l * 2.0 , power);
if (shift)
l = 1.0 - l;
LabIn.L = l * 100;
cmsLab2LCh(&LChIn, &LabIn);
// Do some adjusts on LCh
LChOut.L = LChIn.L * bchsw ->Exposure + bchsw ->Brightness;
LChOut.C = MAX (0, LChIn.C + bchsw ->Saturation);
LChOut.h = LChIn.h + bchsw ->Hue;
cmsLCh2Lab(&LabOut, &LChOut);
// Back to encoded
cmsFloat2LabEncoded(Out, &LabOut);
return TRUE;
}
// Creates an abstract profile operating in Lab space for Brightness,
// contrast, Saturation and white point displacement
cmsHPROFILE LCMSEXPORT f_cmsCreateBCHSWabstractProfile(int nLUTPoints,
double Exposure,
double Bright,
double Contrast,
double Hue,
double Saturation,
LPcmsCIExyY current_wp,
LPcmsCIExyY destination_wp,
LPGAMMATABLE Tables [])
{
cmsHPROFILE hICC;
LPLUT Lut;
BCHSWADJUSTS bchsw;
cmsCIExyY WhitePnt;
bchsw.Exposure = Exposure;
bchsw.Brightness = Bright;
bchsw.Contrast = Contrast;
bchsw.Hue = Hue;
bchsw.Saturation = Saturation;
cmsxyY2XYZ(&bchsw.WPsrc, current_wp);
cmsxyY2XYZ(&bchsw.WPdest, destination_wp);
hICC = _cmsCreateProfilePlaceholder();
if (!hICC) // can't allocate
return NULL;
cmsSetDeviceClass(hICC, icSigAbstractClass);
cmsSetColorSpace(hICC, icSigLabData);
cmsSetPCS(hICC, icSigLabData);
cmsSetRenderingIntent(hICC, INTENT_PERCEPTUAL);
// Creates a LUT with 3D grid only
Lut = cmsAllocLUT();
cmsAlloc3DGrid(Lut, nLUTPoints, 3, 3);
if (Tables != NULL)
cmsAllocLinearTable (Lut, Tables, 1);
if (!cmsSample3DGrid(Lut, bchswSampler, (LPVOID) &bchsw, 0)) {
// Shouldn't reach here
cmsFreeLUT(Lut);
cmsCloseProfile(hICC);
return NULL;
}
// Create tags
cmsAddTag(hICC, icSigDeviceMfgDescTag, (LPVOID) "(f-spot internal)");
cmsAddTag(hICC, icSigProfileDescriptionTag, (LPVOID) "f-spot BCHSW abstract profile");
cmsAddTag(hICC, icSigDeviceModelDescTag, (LPVOID) "BCHSW built-in");
cmsAddTag(hICC, icSigMediaWhitePointTag, (LPVOID) cmsD50_XYZ());
cmsAddTag(hICC, icSigAToB0Tag, (LPVOID) Lut);
// LUT is already on virtual profile
cmsFreeLUT(Lut);
// Ok, done
return hICC;
}
LPGAMMATABLE
f_cms_gamma_table_new (unsigned short data[], int start, int length)
{
LPGAMMATABLE table = cmsAllocGamma (length);
int i;
if (!table)
return NULL;
data += start;
for (i = 0; i < length; i++)
table->GammaTable [i] = data [i];
g_warning ("table %p, count = %d v[0] = %d", table, table->nEntries, table->GammaTable [0]);
return table;
}
ushort *
f_cms_gamma_table_get_values (LPGAMMATABLE table)
{
return &(table->GammaTable [0]);
}
int
f_cms_gamma_table_get_count (LPGAMMATABLE table)
{
return table->nEntries;
}
|