diff -Nru delaboratory-0.7/algorithms/blend_channel.cc delaboratory-0.8/algorithms/blend_channel.cc
--- delaboratory-0.7/algorithms/blend_channel.cc 1970-01-01 00:00:00.000000000 +0000
+++ delaboratory-0.8/algorithms/blend_channel.cc 2012-06-16 01:48:25.000000000 +0000
@@ -0,0 +1,66 @@
+/*
+ delaboratory - color correction utility
+ Copyright (C) 2011 Jacek Poplawski
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include "blend_channel.h"
+#include
+#include "logger.h"
+
+void blendChannel(const deValue* sourcePixels, const deValue* overlayPixels, deValue* resultPixels, deValue* maskPixels, deBlendMode blendMode, deValue opacity, int channelSize)
+{
+ if (!sourcePixels)
+ {
+ logError("no source pixels in blend channel");
+ return;
+ }
+ if (!overlayPixels)
+ {
+ logError("no overlay pixels in blend channel");
+ return;
+ }
+ if (!resultPixels)
+ {
+ logError("no result pixels in blend channel");
+ return;
+ }
+
+ int j;
+ if (maskPixels)
+ {
+ for (j = 0; j < channelSize; j++)
+ {
+ deValue src = sourcePixels[j];
+ deValue ov = overlayPixels[j];
+ deValue dst = calcBlendResult(src, ov, blendMode);
+ deValue m = maskPixels[j] * opacity;
+ deValue result = (1 - m) * src + m * dst;
+ resultPixels[j] = result;
+ }
+ }
+ else
+ {
+ for (j = 0; j < channelSize; j++)
+ {
+ deValue src = sourcePixels[j];
+ deValue ov = overlayPixels[j];
+ deValue dst = calcBlendResult(src, ov, blendMode);
+ deValue result = (1 - opacity) * src + opacity * dst;
+ resultPixels[j] = result;
+ }
+ }
+}
+
diff -Nru delaboratory-0.7/algorithms/blend_channel.h delaboratory-0.8/algorithms/blend_channel.h
--- delaboratory-0.7/algorithms/blend_channel.h 1970-01-01 00:00:00.000000000 +0000
+++ delaboratory-0.8/algorithms/blend_channel.h 2012-06-08 22:38:01.000000000 +0000
@@ -0,0 +1,27 @@
+/*
+ delaboratory - color correction utility
+ Copyright (C) 2011 Jacek Poplawski
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef _DE_BLEND_CHANNEL_H
+#define _DE_BLEND_CHANNEL_H
+
+#include "value.h"
+#include "blend_mode.h"
+
+void blendChannel(const deValue* sourcePixels, const deValue* overlayPixels, deValue* resultPixels, deValue* maskPixels, deBlendMode blendMode, deValue opacity, int channelSize);
+
+#endif
diff -Nru delaboratory-0.7/algorithms/blend_color_luminosity.cc delaboratory-0.8/algorithms/blend_color_luminosity.cc
--- delaboratory-0.7/algorithms/blend_color_luminosity.cc 1970-01-01 00:00:00.000000000 +0000
+++ delaboratory-0.8/algorithms/blend_color_luminosity.cc 2012-06-08 22:38:01.000000000 +0000
@@ -0,0 +1,314 @@
+/*
+ delaboratory - color correction utility
+ Copyright (C) 2011 Jacek Poplawski
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include "blend_color_luminosity.h"
+#include "conversion_cpu.h"
+
+void blendColorRGB(const deValue* source0, const deValue* source1, const deValue* source2, const deValue* overlay0, const deValue* overlay1, const deValue* overlay2, deValue* destination0, deValue* destination1, deValue* destination2, int n, deValue o)
+{
+ deConversionCPU cpu(3);
+ int i;
+ for (i = 0; i < n; i++)
+ {
+ deValue rs = source0[i];
+ deValue gs = source1[i];
+ deValue bs = source2[i];
+
+ cpu.input[0] = rs;
+ cpu.input[1] = gs;
+ cpu.input[2] = bs;
+
+ rgb2lab(cpu);
+
+ deValue L = cpu.output[0];
+
+ deValue ro = overlay0[i];
+ deValue go = overlay1[i];
+ deValue bo = overlay2[i];
+
+ cpu.input[0] = ro;
+ cpu.input[1] = go;
+ cpu.input[2] = bo;
+
+ rgb2lab(cpu);
+
+ deValue A = cpu.output[1];
+ deValue B = cpu.output[2];
+
+ cpu.input[0] = L;
+ cpu.input[1] = A;
+ cpu.input[2] = B;
+
+ lab2rgb(cpu);
+
+ deValue r = cpu.output[0];
+ deValue g = cpu.output[1];
+ deValue b = cpu.output[2];
+
+ destination0[i] = (1 - o) * rs + o * r;
+ destination1[i] = (1 - o) * gs + o * g;
+ destination2[i] = (1 - o) * bs + o * b;
+ }
+}
+
+void blendLuminosityRGB(const deValue* source0, const deValue* source1, const deValue* source2, const deValue* overlay0, const deValue* overlay1, const deValue* overlay2, deValue* destination0, deValue* destination1, deValue* destination2, int n, deValue o)
+{
+ deConversionCPU cpu(3);
+ int i;
+ for (i = 0; i < n; i++)
+ {
+ deValue rs = source0[i];
+ deValue gs = source1[i];
+ deValue bs = source2[i];
+
+ cpu.input[0] = rs;
+ cpu.input[1] = gs;
+ cpu.input[2] = bs;
+
+ rgb2lab(cpu);
+
+ deValue A = cpu.output[1];
+ deValue B = cpu.output[2];
+
+ deValue ro = overlay0[i];
+ deValue go = overlay1[i];
+ deValue bo = overlay2[i];
+
+ cpu.input[0] = ro;
+ cpu.input[1] = go;
+ cpu.input[2] = bo;
+
+ rgb2lab(cpu);
+
+ deValue L = cpu.output[0];
+
+ cpu.input[0] = L;
+ cpu.input[1] = A;
+ cpu.input[2] = B;
+
+ lab2rgb(cpu);
+
+ deValue r = cpu.output[0];
+ deValue g = cpu.output[1];
+ deValue b = cpu.output[2];
+
+ destination0[i] = (1 - o) * rs + o * r;
+ destination1[i] = (1 - o) * gs + o * g;
+ destination2[i] = (1 - o) * bs + o * b;
+ }
+}
+
+void blendColorProPhoto(const deValue* source0, const deValue* source1, const deValue* source2, const deValue* overlay0, const deValue* overlay1, const deValue* overlay2, deValue* destination0, deValue* destination1, deValue* destination2, int n, deValue o)
+{
+ deConversionCPU cpu(3);
+ int i;
+ for (i = 0; i < n; i++)
+ {
+ deValue rs = source0[i];
+ deValue gs = source1[i];
+ deValue bs = source2[i];
+
+ cpu.input[0] = rs;
+ cpu.input[1] = gs;
+ cpu.input[2] = bs;
+
+ prophoto2lab(cpu);
+
+ deValue L = cpu.output[0];
+
+ deValue ro = overlay0[i];
+ deValue go = overlay1[i];
+ deValue bo = overlay2[i];
+
+ cpu.input[0] = ro;
+ cpu.input[1] = go;
+ cpu.input[2] = bo;
+
+ prophoto2lab(cpu);
+
+ deValue A = cpu.output[1];
+ deValue B = cpu.output[2];
+
+ cpu.input[0] = L;
+ cpu.input[1] = A;
+ cpu.input[2] = B;
+
+ lab2prophoto(cpu);
+
+ deValue r = cpu.output[0];
+ deValue g = cpu.output[1];
+ deValue b = cpu.output[2];
+
+ destination0[i] = (1 - o) * rs + o * r;
+ destination1[i] = (1 - o) * gs + o * g;
+ destination2[i] = (1 - o) * bs + o * b;
+ }
+}
+
+void blendLuminosityProPhoto(const deValue* source0, const deValue* source1, const deValue* source2, const deValue* overlay0, const deValue* overlay1, const deValue* overlay2, deValue* destination0, deValue* destination1, deValue* destination2, int n, deValue o)
+{
+ deConversionCPU cpu(3);
+ int i;
+ for (i = 0; i < n; i++)
+ {
+ deValue rs = source0[i];
+ deValue gs = source1[i];
+ deValue bs = source2[i];
+
+ cpu.input[0] = rs;
+ cpu.input[1] = gs;
+ cpu.input[2] = bs;
+
+ prophoto2lab(cpu);
+
+ deValue A = cpu.output[1];
+ deValue B = cpu.output[2];
+
+ deValue ro = overlay0[i];
+ deValue go = overlay1[i];
+ deValue bo = overlay2[i];
+
+ cpu.input[0] = ro;
+ cpu.input[1] = go;
+ cpu.input[2] = bo;
+
+ prophoto2lab(cpu);
+
+ deValue L = cpu.output[0];
+
+ cpu.input[0] = L;
+ cpu.input[1] = A;
+ cpu.input[2] = B;
+
+ lab2prophoto(cpu);
+
+ deValue r = cpu.output[0];
+ deValue g = cpu.output[1];
+ deValue b = cpu.output[2];
+
+ destination0[i] = (1 - o) * rs + o * r;
+ destination1[i] = (1 - o) * gs + o * g;
+ destination2[i] = (1 - o) * bs + o * b;
+ }
+}
+
+void blendColorCMYK(const deValue* source0, const deValue* source1, const deValue* source2, const deValue* source3, const deValue* overlay0, const deValue* overlay1, const deValue* overlay2, const deValue* overlay3, deValue* destination0, deValue* destination1, deValue* destination2, deValue* destination3, int n, deValue o)
+{
+ deConversionCPU cpu(4);
+ int i;
+ for (i = 0; i < n; i++)
+ {
+ deValue cs = source0[i];
+ deValue ms = source1[i];
+ deValue ys = source2[i];
+ deValue ks = source3[i];
+
+ cpu.input[0] = cs;
+ cpu.input[1] = ms;
+ cpu.input[2] = ys;
+ cpu.input[3] = ks;
+
+ cmyk2lab(cpu);
+
+ deValue L = cpu.output[0];
+
+ deValue co = overlay0[i];
+ deValue mo = overlay1[i];
+ deValue yo = overlay2[i];
+ deValue ko = overlay3[i];
+
+ cpu.input[0] = co;
+ cpu.input[1] = mo;
+ cpu.input[2] = yo;
+ cpu.input[3] = ko;
+
+ cmyk2lab(cpu);
+
+ deValue A = cpu.output[1];
+ deValue B = cpu.output[2];
+
+ cpu.input[0] = L;
+ cpu.input[1] = A;
+ cpu.input[2] = B;
+
+ lab2cmyk(cpu);
+
+ deValue c = cpu.output[0];
+ deValue m = cpu.output[1];
+ deValue y = cpu.output[2];
+ deValue k = cpu.output[3];
+
+ destination0[i] = (1 - o) * cs + o * c;
+ destination1[i] = (1 - o) * ms + o * m;
+ destination2[i] = (1 - o) * ys + o * y;
+ destination3[i] = (1 - o) * ks + o * k;
+ }
+}
+
+void blendLuminosityCMYK(const deValue* source0, const deValue* source1, const deValue* source2, const deValue* source3, const deValue* overlay0, const deValue* overlay1, const deValue* overlay2, const deValue* overlay3, deValue* destination0, deValue* destination1, deValue* destination2, deValue* destination3, int n, deValue o)
+{
+ deConversionCPU cpu(4);
+ int i;
+ for (i = 0; i < n; i++)
+ {
+ deValue cs = source0[i];
+ deValue ms = source1[i];
+ deValue ys = source2[i];
+ deValue ks = source3[i];
+
+ cpu.input[0] = cs;
+ cpu.input[1] = ms;
+ cpu.input[2] = ys;
+ cpu.input[3] = ks;
+
+ cmyk2lab(cpu);
+
+ deValue A = cpu.output[1];
+ deValue B = cpu.output[2];
+
+ deValue co = overlay0[i];
+ deValue mo = overlay1[i];
+ deValue yo = overlay2[i];
+ deValue ko = overlay3[i];
+
+ cpu.input[0] = co;
+ cpu.input[1] = mo;
+ cpu.input[2] = yo;
+ cpu.input[3] = ko;
+
+ cmyk2lab(cpu);
+
+ deValue L = cpu.output[0];
+
+ cpu.input[0] = L;
+ cpu.input[1] = A;
+ cpu.input[2] = B;
+
+ lab2cmyk(cpu);
+
+ deValue c = cpu.output[0];
+ deValue m = cpu.output[1];
+ deValue y = cpu.output[2];
+ deValue k = cpu.output[3];
+
+ destination0[i] = (1 - o) * cs + o * c;
+ destination1[i] = (1 - o) * ms + o * m;
+ destination2[i] = (1 - o) * ys + o * y;
+ destination3[i] = (1 - o) * ks + o * k;
+ }
+}
diff -Nru delaboratory-0.7/algorithms/blend_color_luminosity.h delaboratory-0.8/algorithms/blend_color_luminosity.h
--- delaboratory-0.7/algorithms/blend_color_luminosity.h 1970-01-01 00:00:00.000000000 +0000
+++ delaboratory-0.8/algorithms/blend_color_luminosity.h 2012-06-08 22:38:01.000000000 +0000
@@ -0,0 +1,31 @@
+/*
+ delaboratory - color correction utility
+ Copyright (C) 2011 Jacek Poplawski
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef _DE_BLEND_COLOR_LUMINOSITY_H
+#define _DE_BLEND_COLOR_LUMINOSITY_H
+
+#include "value.h"
+
+void blendColorRGB(const deValue* source0, const deValue* source1, const deValue* source2, const deValue* overlay0, const deValue* overlay1, const deValue* overlay2, deValue* destination0, deValue* destination1, deValue* destination2, int n, deValue o);
+void blendLuminosityRGB(const deValue* source0, const deValue* source1, const deValue* source2, const deValue* overlay0, const deValue* overlay1, const deValue* overlay2, deValue* destination0, deValue* destination1, deValue* destination2, int n, deValue o);
+void blendColorProPhoto(const deValue* source0, const deValue* source1, const deValue* source2, const deValue* overlay0, const deValue* overlay1, const deValue* overlay2, deValue* destination0, deValue* destination1, deValue* destination2, int n, deValue o);
+void blendLuminosityProPhoto(const deValue* source0, const deValue* source1, const deValue* source2, const deValue* overlay0, const deValue* overlay1, const deValue* overlay2, deValue* destination0, deValue* destination1, deValue* destination2, int n, deValue o);
+void blendColorCMYK(const deValue* source0, const deValue* source1, const deValue* source2, const deValue* source3, const deValue* overlay0, const deValue* overlay1, const deValue* overlay2, const deValue* overlay3, deValue* destination0, deValue* destination1, deValue* destination2, deValue* destination3, int n, deValue o);
+void blendLuminosityCMYK(const deValue* source0, const deValue* source1, const deValue* source2, const deValue* source3, const deValue* overlay0, const deValue* overlay1, const deValue* overlay2, const deValue* overlay3, deValue* destination0, deValue* destination1, deValue* destination2, deValue* destination3, int n, deValue o);
+
+#endif
diff -Nru delaboratory-0.7/algorithms/blend_mode.cc delaboratory-0.8/algorithms/blend_mode.cc
--- delaboratory-0.7/algorithms/blend_mode.cc 1970-01-01 00:00:00.000000000 +0000
+++ delaboratory-0.8/algorithms/blend_mode.cc 2012-06-08 22:38:01.000000000 +0000
@@ -0,0 +1,355 @@
+/*
+ delaboratory - color correction utility
+ Copyright (C) 2011 Jacek Poplawski
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include "blend_mode.h"
+#include
+
+std::string getBlendModeName(deBlendMode mode)
+{
+ switch (mode)
+ {
+ case deBlendNormal:
+ return "normal";
+ case deBlendNone:
+ return "none";
+ case deBlendMultiply:
+ return "multiply";
+ case deBlendScreen:
+ return "screen";
+ case deBlendOverlay:
+ return "overlay";
+ case deBlendOverlayInvert:
+ return "overlay invert";
+ case deBlendAdd:
+ return "add";
+ case deBlendGrainExtract:
+ return "graint extract";
+ case deBlendGrainMerge:
+ return "graint merge";
+ case deBlendSub:
+ return "sub";
+ case deBlendDifference:
+ return "difference";
+ case deBlendDarken:
+ return "darken";
+ case deBlendLighten:
+ return "lighten";
+ case deBlendDodge:
+ return "dodge";
+ case deBlendBurn:
+ return "burn";
+ case deBlendColor:
+ return "color";
+ case deBlendLuminosity:
+ return "luminosity";
+ default:
+ return "unknown";
+ }
+}
+
+deBlendMode blendModeFromString(const std::string& s)
+{
+ if (s == "normal")
+ {
+ return deBlendNormal;
+ }
+
+ if (s == "none")
+ {
+ return deBlendNone;
+ }
+
+ if (s == "multiply")
+ {
+ return deBlendMultiply;
+ }
+
+ if (s == "screen")
+ {
+ return deBlendScreen;
+ }
+
+ if (s == "overlay")
+ {
+ return deBlendOverlay;
+ }
+
+ if (s == "overlay invert")
+ {
+ return deBlendOverlayInvert;
+ }
+
+ if (s == "add")
+ {
+ return deBlendAdd;
+ }
+
+ if (s == "grain extract")
+ {
+ return deBlendGrainExtract;
+ }
+
+ if (s == "grain merge")
+ {
+ return deBlendGrainMerge;
+ }
+
+ if (s == "sub")
+ {
+ return deBlendSub;
+ }
+
+ if (s == "difference")
+ {
+ return deBlendDifference;
+ }
+
+ if (s == "darken")
+ {
+ return deBlendDarken;
+ }
+
+ if (s == "lighten")
+ {
+ return deBlendLighten;
+ }
+
+ if (s == "dodge")
+ {
+ return deBlendDodge;
+ }
+
+ if (s == "burn")
+ {
+ return deBlendBurn;
+ }
+
+ if (s == "color")
+ {
+ return deBlendColor;
+ }
+
+ if (s == "luminosity")
+ {
+ return deBlendLuminosity;
+ }
+
+ return deBlendInvalid;
+
+}
+
+std::vector getSupportedBlendModes(deColorSpace colorSpace)
+{
+ std::vector result;
+
+ result.push_back(deBlendNormal);
+ result.push_back(deBlendNone);
+ result.push_back(deBlendMultiply);
+ result.push_back(deBlendScreen);
+ result.push_back(deBlendOverlay);
+ result.push_back(deBlendOverlayInvert);
+ result.push_back(deBlendAdd);
+ result.push_back(deBlendGrainExtract);
+ result.push_back(deBlendGrainMerge);
+ result.push_back(deBlendSub);
+ result.push_back(deBlendDifference);
+ result.push_back(deBlendDarken);
+ result.push_back(deBlendLighten);
+ result.push_back(deBlendDodge);
+ result.push_back(deBlendBurn);
+
+ if ((colorSpace == deColorSpaceRGB) || (colorSpace == deColorSpaceProPhoto) || (colorSpace == deColorSpaceCMYK))
+ {
+ result.push_back(deBlendColor);
+ result.push_back(deBlendLuminosity);
+ }
+
+ return result;
+}
+
+std::vector getSupportedBlendModeNames(deColorSpace colorSpace)
+{
+ std::vector modes = getSupportedBlendModes(colorSpace);
+ std::vector result;
+ std::vector::const_iterator i;
+ for (i = modes.begin(); i != modes.end(); i++)
+ {
+ result.push_back(getBlendModeName(*i));
+ }
+ return result;
+}
+
+deValue calcBlendResult(deValue src, deValue v2, deBlendMode mode)
+{
+ switch (mode)
+ {
+ case deBlendNormal:
+ return v2;
+ break;
+ case deBlendNone:
+ return src;
+ break;
+ case deBlendMultiply:
+ return src*v2;
+ break;
+ case deBlendScreen:
+ return 1 - (1-src)*(1-v2);
+ break;
+ case deBlendOverlay:
+ if (src > 0.5)
+ {
+ return 1 - (1 - 2 * ( src - 0.5)) * (1 - v2);
+ }
+ else
+ {
+ return 2 * src * v2;
+ }
+ break;
+ case deBlendOverlayInvert:
+ if (src > 0.5)
+ {
+ return 1 - (1 - 2 * ( src - 0.5)) * v2;
+ }
+ else
+ {
+ return 2 * src * (1 - v2);
+ }
+ break;
+ case deBlendAdd:
+ {
+ deValue v = src + v2;
+ if (v < 0)
+ {
+ return 0;
+ }
+ if (v > 1)
+ {
+ return 1;
+ }
+ return v;
+ break;
+ }
+ case deBlendGrainExtract:
+ {
+ deValue v = 0.5 + src - v2;
+ if (v < 0)
+ {
+ return 0;
+ }
+ if (v > 1)
+ {
+ return 1;
+ }
+ return v;
+ break;
+ }
+ case deBlendGrainMerge:
+ {
+ deValue v = src + v2 - 0.5;
+ if (v < 0)
+ {
+ return 0;
+ }
+ if (v > 1)
+ {
+ return 1;
+ }
+ return v;
+ break;
+ }
+ case deBlendSub:
+ {
+ deValue v = src - v2;
+ if (v < 0)
+ {
+ return 0;
+ }
+ if (v > 1)
+ {
+ return 1;
+ }
+ return v;
+ break;
+ }
+ case deBlendDifference:
+ return fabs(src - v2);
+ break;
+ case deBlendDarken:
+ if (src < v2)
+ {
+ return src;
+ }
+ else
+ {
+ return v2;
+ }
+ break;
+ case deBlendLighten:
+ if (src > v2)
+ {
+ return src;
+ }
+ else
+ {
+ return v2;
+ }
+ break;
+ case deBlendDodge:
+ {
+ deValue d = 1 - v2;
+ if (d == 0)
+ {
+ return 1.0;
+ }
+ else
+ {
+ deValue r = src / d;
+ if ( r > 1)
+ {
+ return 1;
+ }
+ else
+ {
+ return r;
+ }
+ }
+ break;
+ }
+ case deBlendBurn:
+ {
+ if (v2 == 0)
+ {
+ return 0.0;
+ }
+ else
+ {
+ deValue v = (1 - src) / v2;
+ if (v > 1)
+ {
+ v = 1;
+ }
+ deValue r = 1 - v;
+ return r;
+ }
+ break;
+ }
+ default:
+ return 0;
+ }
+}
+
diff -Nru delaboratory-0.7/algorithms/blend_mode.h delaboratory-0.8/algorithms/blend_mode.h
--- delaboratory-0.7/algorithms/blend_mode.h 1970-01-01 00:00:00.000000000 +0000
+++ delaboratory-0.8/algorithms/blend_mode.h 2012-06-08 22:38:01.000000000 +0000
@@ -0,0 +1,54 @@
+/*
+ delaboratory - color correction utility
+ Copyright (C) 2011 Jacek Poplawski
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef _DE_BLEND_MODES_H
+#define _DE_BLEND_MODES_H
+
+#include
+#include
+#include "value.h"
+#include "color_space.h"
+
+enum deBlendMode
+{
+ deBlendInvalid,
+ deBlendNormal,
+ deBlendNone,
+ deBlendMultiply,
+ deBlendScreen,
+ deBlendOverlay,
+ deBlendOverlayInvert,
+ deBlendDodge,
+ deBlendBurn,
+ deBlendAdd,
+ deBlendGrainExtract,
+ deBlendGrainMerge,
+ deBlendSub,
+ deBlendDifference,
+ deBlendDarken,
+ deBlendLighten,
+ deBlendColor,
+ deBlendLuminosity
+};
+
+std::string getBlendModeName(deBlendMode mode);
+deValue calcBlendResult(deValue src, deValue v2, deBlendMode mode);
+deBlendMode blendModeFromString(const std::string& s);
+std::vector getSupportedBlendModeNames(deColorSpace colorSpace);
+
+#endif
diff -Nru delaboratory-0.7/algorithms/blur.cc delaboratory-0.8/algorithms/blur.cc
--- delaboratory-0.7/algorithms/blur.cc 1970-01-01 00:00:00.000000000 +0000
+++ delaboratory-0.8/algorithms/blur.cc 2012-06-08 22:38:01.000000000 +0000
@@ -0,0 +1,359 @@
+/*
+ delaboratory - color correction utility
+ Copyright (C) 2011 Jacek Poplawski
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include "blur.h"
+#include
+#include
+#include "logger.h"
+
+void boxBlur(deValue* source, deValue* destination, int n, int s)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ {
+ deValue result = 0.0;
+
+ int n1 = i - s + 1;
+ int n2 = i + s - 1;
+ if (n1 < 0)
+ {
+ n1 = 0;
+ }
+
+ if (n2 >= n)
+ {
+ n2 = n - 1;
+ }
+
+ int j;
+ for (j = n1; j <= n2; j++)
+ {
+ result += source[j];
+ }
+ destination[i] = result / (n2 - n1 + 1.0);
+ }
+}
+
+void gaussianBlur(deValue* source, deValue* destination, int n, int s, deValue* weights)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ {
+ deValue result = 0.0;
+ deValue sum = 0.0;
+
+ int n1 = i - s + 1;
+ int n2 = i + s - 1;
+ if (n1 < 0)
+ {
+ n1 = 0;
+ }
+
+ if (n2 >= n)
+ {
+ n2 = n - 1;
+ }
+
+ int j;
+ int p;
+
+ j = n1;
+ p = i - n1;
+ while (p >= 0)
+ {
+ deValue v = source[j];
+ deValue w = weights[p];
+ result += w * v;
+ sum += w;
+
+ p--;
+ j++;
+ }
+ p = 1;
+ while (j <= n2)
+ {
+
+ deValue v = source[j];
+ deValue w = weights[p];
+ result += w * v;
+ sum += w;
+
+ p++;
+ j++;
+ }
+
+ destination[i] = result / sum;
+ }
+}
+
+void surfaceBlur(deValue* source, deValue* destination, int n, int s, deValue* weights, deValue t)
+{
+ deValue tt = 1.0 - t;
+
+ int i;
+ for (i = 0; i < n; i++)
+ {
+ deValue result = 0.0;
+ deValue sum = 0.0;
+
+ deValue reference = source[i];
+
+ int n1 = i - s + 1;
+ int n2 = i + s - 1;
+ if (n1 < 0)
+ {
+ n1 = 0;
+ }
+
+ if (n2 >= n)
+ {
+ n2 = n - 1;
+ }
+
+ int j;
+ int p;
+
+ j = n1;
+ p = i - n1;
+ while (p >= 0)
+ {
+ deValue v = source[j];
+ if (fabs(v - reference) <= tt)
+ {
+ deValue w = weights[p];
+ result += w * v;
+ sum += w;
+ }
+
+ p--;
+ j++;
+ }
+ p = 1;
+ while (j <= n2)
+ {
+
+ deValue v = source[j];
+ if (fabs(v - reference) <= tt)
+ {
+ deValue w = weights[p];
+ result += w * v;
+ sum += w;
+ }
+
+ p++;
+ j++;
+ }
+
+
+ destination[i] = result / sum;
+ }
+}
+
+void fillWeightsFlat(deValue* weights, int blurSize)
+{
+ int i;
+ for (i = 0 ; i < blurSize; i++)
+ {
+ weights[i] = 1.0;
+ }
+}
+
+void fillWeightsGaussian(deValue* weights, int blurSize)
+{
+ int i;
+ deValue radius = blurSize / 3.0;
+ deValue rr2 = 2.0 * radius * radius;
+ for (i = 0 ; i < blurSize; i++)
+ {
+ deValue ii = i * i;
+ deValue ee = exp( - ii / rr2 );
+ weights[i] = 1.0 / sqrt(rr2 * M_PI) * ee;
+ }
+}
+
+bool blurChannel(const deValue* source, deValue* destination, deSize size, deValue radiusX, deValue radiusY, deBlurType type, deValue t)
+{
+ assert(source);
+ assert(destination);
+
+ int w = size.getW();
+ int h = size.getH();
+
+ if (w == 0)
+ {
+ return false;
+ }
+
+ if (h == 0)
+ {
+ return false;
+ }
+
+ if ((radiusX <= 0) || (radiusY <= 0))
+ {
+ return false;
+ }
+
+ assert(w > 0);
+ assert(h > 0);
+
+ int min = 1;
+
+ int blurSizeW = radiusX;
+ if (blurSizeW < min)
+ {
+ blurSizeW = min;
+ }
+ int blurSizeH = radiusY;
+ if (blurSizeH < min)
+ {
+ blurSizeH = min;
+ }
+
+ int maxSize = blurSizeW;
+ if (blurSizeH > maxSize)
+ {
+ maxSize = blurSizeH;
+ }
+
+ int max = w;
+ if (h > max)
+ {
+ max = h;
+ }
+
+ deValue* tmp = NULL;
+
+ try
+ {
+ tmp = new deValue[size.getN()];
+ }
+ catch (std::bad_alloc)
+ {
+ logError("allocating memory in blur");
+ if (tmp)
+ {
+ delete [] tmp;
+ }
+ return false;
+ }
+
+ deValue* sourceBuffer = new deValue[max];
+ deValue* destinationBuffer = new deValue[max];
+ deValue* weights = NULL;
+
+
+ if (type != deBoxBlur)
+ {
+ weights = new deValue[maxSize];
+ }
+
+ int i;
+ int j;
+
+ {
+ if (type != deBoxBlur)
+ {
+ fillWeightsGaussian(weights, blurSizeW);
+ }
+
+ for (i = 0; i < h; i++)
+ {
+ int p = i * w;
+ for (j = 0; j < w; j++)
+ {
+ sourceBuffer[j] = source[p + j];
+ }
+ switch (type)
+ {
+ case deBoxBlur:
+ {
+ boxBlur(sourceBuffer, destinationBuffer, w, blurSizeW);
+ break;
+ }
+ case deGaussianBlur:
+ {
+ gaussianBlur(sourceBuffer, destinationBuffer, w, blurSizeW, weights);
+ break;
+ }
+ case deSurfaceBlur:
+ {
+ surfaceBlur(sourceBuffer, destinationBuffer, w, blurSizeW, weights, t);
+ break;
+ }
+ default:
+ break;
+ }
+ for (j = 0; j < w; j++)
+ {
+ tmp[p + j] = destinationBuffer[j];
+ }
+ }
+ }
+
+
+ {
+ if (type != deBoxBlur)
+ {
+ fillWeightsGaussian(weights, blurSizeH);
+ }
+
+ for (i = 0; i < w; i++)
+ {
+ for (j = 0; j < h; j++)
+ {
+ sourceBuffer[j] = tmp[j * w + i];
+ }
+ switch (type)
+ {
+ case deBoxBlur:
+ {
+ boxBlur(sourceBuffer, destinationBuffer, h, blurSizeH);
+ break;
+ }
+ case deGaussianBlur:
+ {
+ gaussianBlur(sourceBuffer, destinationBuffer, h, blurSizeH, weights);
+ break;
+ }
+ case deSurfaceBlur:
+ {
+ surfaceBlur(sourceBuffer, destinationBuffer, h, blurSizeH, weights, t);
+ break;
+ }
+ default:
+ break;
+ }
+ for (j = 0; j < h; j++)
+ {
+ destination[j * w + i] = destinationBuffer[j];
+ }
+ }
+ }
+
+ delete [] tmp;
+ if (type != deBoxBlur)
+ {
+ delete [] weights;
+ }
+ delete [] destinationBuffer;
+ delete [] sourceBuffer;
+
+ return true;
+}
+
diff -Nru delaboratory-0.7/algorithms/blur.h delaboratory-0.8/algorithms/blur.h
--- delaboratory-0.7/algorithms/blur.h 1970-01-01 00:00:00.000000000 +0000
+++ delaboratory-0.8/algorithms/blur.h 2012-06-08 22:38:01.000000000 +0000
@@ -0,0 +1,28 @@
+/*
+ delaboratory - color correction utility
+ Copyright (C) 2011 Jacek Poplawski
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef _DE_BLUR_H
+#define _DE_BLUR_H
+
+#include "value.h"
+#include "blur_type.h"
+#include "size.h"
+
+bool blurChannel(const deValue* source, deValue* destination, deSize size, deValue radiusX, deValue radiusY, deBlurType type, deValue t);
+
+#endif
diff -Nru delaboratory-0.7/algorithms/blur_type.cc delaboratory-0.8/algorithms/blur_type.cc
--- delaboratory-0.7/algorithms/blur_type.cc 1970-01-01 00:00:00.000000000 +0000
+++ delaboratory-0.8/algorithms/blur_type.cc 2012-06-08 22:38:01.000000000 +0000
@@ -0,0 +1,68 @@
+/*
+ delaboratory - color correction utility
+ Copyright (C) 2011 Jacek Poplawski
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include "blur_type.h"
+
+std::string getBlurTypeName(deBlurType type)
+{
+ switch (type)
+ {
+ case deBoxBlur:
+ return "box";
+ case deGaussianBlur:
+ return "gaussian";
+ case deSurfaceBlur:
+ return "surface";
+ default:
+ return "unknown";
+ }
+}
+
+deBlurType blurTypeFromString(const std::string& s)
+{
+ if (s == "box")
+ {
+ return deBoxBlur;
+ }
+ if (s == "gaussian")
+ {
+ return deGaussianBlur;
+ }
+ if (s == "surface")
+ {
+ return deSurfaceBlur;
+ }
+
+ return deBlurInvalid;
+}
+
+void getSupportedBlurTypes(std::vector& result)
+{
+ result.push_back(deBoxBlur);
+ result.push_back(deGaussianBlur);
+ result.push_back(deSurfaceBlur);
+}
+
+std::vector getSupportedBlurTypes()
+{
+ std::vector result;
+ result.push_back("box");
+ result.push_back("gaussian");
+ result.push_back("surface");
+ return result;
+}
diff -Nru delaboratory-0.7/algorithms/blur_type.h delaboratory-0.8/algorithms/blur_type.h
--- delaboratory-0.7/algorithms/blur_type.h 1970-01-01 00:00:00.000000000 +0000
+++ delaboratory-0.8/algorithms/blur_type.h 2012-06-08 22:38:01.000000000 +0000
@@ -0,0 +1,38 @@
+/*
+ delaboratory - color correction utility
+ Copyright (C) 2011 Jacek Poplawski
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef _DE_BLUR_TYPE_H
+#define _DE_BLUR_TYPE_H
+
+#include
+#include
+
+enum deBlurType
+{
+ deBlurInvalid,
+ deBoxBlur,
+ deGaussianBlur,
+ deSurfaceBlur
+};
+
+std::string getBlurTypeName(deBlurType type);
+deBlurType blurTypeFromString(const std::string& s);
+void getSupportedBlurTypes(std::vector& result);
+std::vector getSupportedBlurTypes();
+
+#endif
diff -Nru delaboratory-0.7/algorithms/c2g.cc delaboratory-0.8/algorithms/c2g.cc
--- delaboratory-0.7/algorithms/c2g.cc 1970-01-01 00:00:00.000000000 +0000
+++ delaboratory-0.8/algorithms/c2g.cc 2012-06-08 22:38:01.000000000 +0000
@@ -0,0 +1,154 @@
+/*
+ delaboratory - color correction utility
+ Copyright (C) 2011 Jacek Poplawski
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include "c2g.h"
+#include
+#include
+
+#include "radial_lut.h"
+#include "logger.h"
+#include "str.h"
+
+void c2g(const deValue* source0, const deValue* source1, const deValue* source2, deValue* mask, const deSize& size, deValue r, int samples)
+{
+ int w = size.getW();
+ int h = size.getH();
+
+ int lutsize = 10 * 1024;
+ deRadialLUT lut(lutsize, r);
+
+ int* offsets = new int [samples];
+
+ int x;
+ for (x = 0; x < w; x++)
+ {
+ int y;
+ for (y = 0; y < h; y++)
+ {
+ int p = w * y + x;
+ deValue v0 = source0[p];
+ deValue v1 = source1[p];
+ deValue v2 = source2[p];
+
+ deValue min0 = 1.0;
+ deValue max0 = 0.0;
+ deValue min1 = 1.0;
+ deValue max1 = 0.0;
+ deValue min2 = 1.0;
+ deValue max2 = 0.0;
+
+ int offset = lut.getStart(samples);
+
+ int i = 0;
+ while (i < samples)
+ {
+ int xx;
+ int yy;
+ lut.get(offset, xx, yy);
+ xx += x;
+ yy += y;
+ if ((xx >= 0) && (xx < w) && (yy >= 0) && (yy < h))
+ {
+ int pp = w * yy + xx;
+ offsets[i] = pp;
+ i++;
+ }
+
+ offset++;
+ if (offset >= lutsize)
+ {
+ offset = 0;
+ }
+ }
+
+ for (i = 0; i < samples; i++)
+ {
+ int pp = offsets[i];
+
+ deValue vv0 = source0[pp];
+ deValue vv1 = source1[pp];
+ deValue vv2 = source2[pp];
+
+ if (vv0 < min0)
+ {
+ min0 = vv0;
+ }
+ if (vv0 > max0)
+ {
+ max0 = vv0;
+ }
+
+ if (vv1 < min1)
+ {
+ min1 = vv1;
+ }
+ if (vv1 > max1)
+ {
+ max1 = vv1;
+ }
+
+ if (vv2 < min2)
+ {
+ min2 = vv2;
+ }
+ if (vv2 > max2)
+ {
+ max2 = vv2;
+ }
+ }
+
+ deValue n0 = v0 - min0;
+ deValue d0 = v0 - max0;
+ deValue n1 = v1 - min1;
+ deValue d1 = v1 - max1;
+ deValue n2 = v2 - min2;
+ deValue d2 = v2 - max2;
+
+ deValue n = sqrt(n0 * n0 + n1 * n1 + n2 * n2);
+ deValue d = sqrt(d0 * d0 + d1 * d1 + d2 * d2);
+
+ d = d + n;
+
+ deValue result;
+
+ if (d != 0)
+ {
+ result = n / d;
+
+ if (result < 0)
+ {
+ result = 0;
+ }
+ else if (result > 1)
+ {
+ result = 1;
+ }
+ }
+ else
+ {
+ result = (v0 + v1 + v2) / 3.0;
+ }
+
+ mask[p] = result;
+ }
+ }
+
+ delete [] offsets;
+
+}
+
diff -Nru delaboratory-0.7/algorithms/c2g.h delaboratory-0.8/algorithms/c2g.h
--- delaboratory-0.7/algorithms/c2g.h 1970-01-01 00:00:00.000000000 +0000
+++ delaboratory-0.8/algorithms/c2g.h 2012-06-08 22:38:01.000000000 +0000
@@ -0,0 +1,27 @@
+/*
+ delaboratory - color correction utility
+ Copyright (C) 2011 Jacek Poplawski
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef _DE_C2G_H
+#define _DE_C2G_H
+
+#include "value.h"
+#include "size.h"
+
+void c2g(const deValue* source0, const deValue* source1, const deValue* source2, deValue* mask, const deSize& size, deValue r, int samples);
+
+#endif
diff -Nru delaboratory-0.7/algorithms/fill_channel.cc delaboratory-0.8/algorithms/fill_channel.cc
--- delaboratory-0.7/algorithms/fill_channel.cc 1970-01-01 00:00:00.000000000 +0000
+++ delaboratory-0.8/algorithms/fill_channel.cc 2012-06-08 22:38:01.000000000 +0000
@@ -0,0 +1,29 @@
+/*
+ delaboratory - color correction utility
+ Copyright (C) 2011 Jacek Poplawski
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include "fill_channel.h"
+
+void fillChannel(deValue* dst, int n, deValue v)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ {
+ dst[i] = v;
+ }
+}
+
diff -Nru delaboratory-0.7/algorithms/fill_channel.h delaboratory-0.8/algorithms/fill_channel.h
--- delaboratory-0.7/algorithms/fill_channel.h 1970-01-01 00:00:00.000000000 +0000
+++ delaboratory-0.8/algorithms/fill_channel.h 2012-06-08 22:38:01.000000000 +0000
@@ -0,0 +1,26 @@
+/*
+ delaboratory - color correction utility
+ Copyright (C) 2011 Jacek Poplawski
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef _DE_COPY_CHANNEL_H
+#define _DE_COPY_CHANNEL_H
+
+#include "value.h"
+
+void fillChannel(deValue* dst, int n, deValue v);
+
+#endif
diff -Nru delaboratory-0.7/algorithms/gradient.cc delaboratory-0.8/algorithms/gradient.cc
--- delaboratory-0.7/algorithms/gradient.cc 1970-01-01 00:00:00.000000000 +0000
+++ delaboratory-0.8/algorithms/gradient.cc 2012-07-01 16:53:40.000000000 +0000
@@ -0,0 +1,103 @@
+/*
+ delaboratory - color correction utility
+ Copyright (C) 2011 Jacek Poplawski
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include "gradient.h"
+#include
+#include
+#include "logger.h"
+#include "str.h"
+
+void gradientChannel(deValue* destination, deSize size, deValue cx, deValue cy, deValue r, deValue a, deValue sinus)
+{
+ int w = size.getW();
+ int h = size.getH();
+
+ if (w == 0)
+ {
+ return;
+ }
+
+ if (h == 0)
+ {
+ return;
+ }
+
+ deValue ww = w / 2.0;
+ deValue hh = h / 2.0;
+
+ int i;
+ int j;
+
+ int p = 0;
+
+ deValue angle = 2 * M_PI * (a / 360.0);
+ deValue vx = sin (angle);
+ deValue vy = cos (angle);
+
+ deValue div;
+
+ if (r > 0)
+ {
+ div = 1.0 / (r + 0.1);
+ }
+ else
+ {
+ div = 1.0 / (r - 0.1);
+ }
+
+ for (i = 0; i < h; i++)
+ {
+ deValue y = (i - hh) / hh;
+
+ deValue yy = y - cy;
+
+ for (j = 0; j < w; j++)
+ {
+ deValue x = (j - ww) / ww;
+
+ deValue xx = x - cx;
+
+ deValue rr = (yy * vy + xx * vx) * div;
+
+ rr = 1.0 - rr;
+
+ if (sinus > 0)
+ {
+ rr = 1.0 - sin (sinus * rr * M_PI);
+ }
+ else if (sinus < 0)
+ {
+ rr = sin (sinus * rr * M_PI);
+ }
+
+ if (rr < 0)
+ {
+ rr = -rr;
+ }
+ if (rr > 1)
+ {
+ rr = 1;
+ }
+
+
+
+ destination[p] = rr;
+ p++;
+ }
+ }
+}
diff -Nru delaboratory-0.7/algorithms/gradient.h delaboratory-0.8/algorithms/gradient.h
--- delaboratory-0.7/algorithms/gradient.h 1970-01-01 00:00:00.000000000 +0000
+++ delaboratory-0.8/algorithms/gradient.h 2012-07-01 13:24:19.000000000 +0000
@@ -0,0 +1,28 @@
+/*
+ delaboratory - color correction utility
+ Copyright (C) 2011 Jacek Poplawski
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef _DE_GRADIENT_H
+#define _DE_GRADIENT_H
+
+#include "value.h"
+#include "size.h"
+
+void gradientChannel(deValue* destination, deSize size, deValue cx, deValue cy, deValue r, deValue a, deValue sinus);
+
+
+#endif
diff -Nru delaboratory-0.7/algorithms/radial_lut.cc delaboratory-0.8/algorithms/radial_lut.cc
--- delaboratory-0.7/algorithms/radial_lut.cc 1970-01-01 00:00:00.000000000 +0000
+++ delaboratory-0.8/algorithms/radial_lut.cc 2012-06-08 22:38:01.000000000 +0000
@@ -0,0 +1,62 @@
+/*
+ delaboratory - color correction utility
+ Copyright (C) 2011 Jacek Poplawski
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include "radial_lut.h"
+#include
+#include "value.h"
+#include
+
+deRadialLUT::deRadialLUT(int _size, int r)
+:size(_size)
+{
+ lut = new int [2 * size];
+
+ srand(0);
+
+ int i;
+
+ for (i = 0; i < size; i++)
+ {
+ deValue angle = (rand () % 1024) / 1024.0 * 2 * M_PI;
+ deValue radius_1 = ((rand () % 1024) / 1024.0 * r + 1.0);
+ deValue radius_2 = ((rand () % 1024) / 1024.0 * radius_1 + 1.0);
+ int xx = sin(angle) * radius_2;
+ int yy = cos(angle) * radius_2;
+ lut[2*i+0] = xx;
+ lut[2*i+1] = yy;
+ }
+}
+
+deRadialLUT::~deRadialLUT()
+{
+ delete [] lut;
+}
+
+void deRadialLUT::get(int i, int& x, int& y) const
+{
+ if ((i >= 0) && (i < size))
+ {
+ x = lut[2*i+0];
+ y = lut[2*i+1];
+ }
+}
+
+int deRadialLUT::getStart(int s) const
+{
+ return rand() % (size - s);
+}
diff -Nru delaboratory-0.7/algorithms/radial_lut.h delaboratory-0.8/algorithms/radial_lut.h
--- delaboratory-0.7/algorithms/radial_lut.h 1970-01-01 00:00:00.000000000 +0000
+++ delaboratory-0.8/algorithms/radial_lut.h 2012-06-08 22:38:01.000000000 +0000
@@ -0,0 +1,36 @@
+/*
+ delaboratory - color correction utility
+ Copyright (C) 2011 Jacek Poplawski
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef _DE_RADIAL_LUT_H
+#define _DE_RADIAL_LUT_H
+
+class deRadialLUT
+{
+ private:
+ int size;
+ int* lut;
+ public:
+ deRadialLUT(int _size, int r);
+
+ virtual ~deRadialLUT();
+
+ void get(int i, int& x, int& y) const;
+ int getStart(int s) const;
+};
+
+#endif
diff -Nru delaboratory-0.7/algorithms/sample_pixel.cc delaboratory-0.8/algorithms/sample_pixel.cc
--- delaboratory-0.7/algorithms/sample_pixel.cc 1970-01-01 00:00:00.000000000 +0000
+++ delaboratory-0.8/algorithms/sample_pixel.cc 2012-06-08 22:38:01.000000000 +0000
@@ -0,0 +1,113 @@
+/*
+ delaboratory - color correction utility
+ Copyright (C) 2011 Jacek Poplawski
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include "sample_pixel.h"
+
+deValue samplePixel(const deValue* src, int xx1, int xx2, int yy1, int yy2, bool mirrorX, bool mirrorY, int ws, int hs)
+{
+ if (xx1 < 0)
+ {
+ xx1 = 0;
+ }
+ else if (xx1 >= ws)
+ {
+ xx1 = ws - 1;
+ }
+ if (xx2 < 0)
+ {
+ xx2 = 0;
+ }
+ else if (xx2 >= ws)
+ {
+ xx2 = ws - 1;
+ }
+ if (yy1 < 0)
+ {
+ yy1 = 0;
+ }
+ else if (yy1 >= hs)
+ {
+ yy1 = hs - 1;
+ }
+ if (yy2 < 0)
+ {
+ yy2 = 0;
+ }
+ else if (yy2 >= hs)
+ {
+ yy2 = hs - 1;
+ }
+
+ int n = 0;
+ int x0;
+ int y0;
+ deValue value = 0.0;
+
+ if ((!mirrorX) && (!mirrorY))
+ {
+ for (x0 = xx1; x0 <= xx2; x0++)
+ {
+ for (y0 = yy1; y0 <= yy2; y0++)
+ {
+ value += src[x0 + y0 * ws];
+ n++;
+ }
+ }
+ }
+ if ((mirrorX) && (!mirrorY))
+ {
+ for (x0 = xx1; x0 <= xx2; x0++)
+ {
+ for (y0 = yy1; y0 <= yy2; y0++)
+ {
+ value += src[(ws - 1 - x0) + y0 * ws];
+ n++;
+ }
+ }
+ }
+ if ((!mirrorX) && (mirrorY))
+ {
+ for (x0 = xx1; x0 <= xx2; x0++)
+ {
+ for (y0 = yy1; y0 <= yy2; y0++)
+ {
+ value += src[x0 + (hs - 1 - y0) * ws];
+ n++;
+ }
+ }
+ }
+ if ((mirrorX) && (mirrorY))
+ {
+ for (x0 = xx1; x0 <= xx2; x0++)
+ {
+ for (y0 = yy1; y0 <= yy2; y0++)
+ {
+ value += src[(ws - 1 - x0) + (hs - 1 - y0) * ws];
+ n++;
+ }
+ }
+ }
+
+ if (n == 0)
+ {
+ return 0.0;
+ }
+
+ return value / n;
+}
+
diff -Nru delaboratory-0.7/algorithms/sample_pixel.h delaboratory-0.8/algorithms/sample_pixel.h
--- delaboratory-0.7/algorithms/sample_pixel.h 1970-01-01 00:00:00.000000000 +0000
+++ delaboratory-0.8/algorithms/sample_pixel.h 2012-06-08 22:38:01.000000000 +0000
@@ -0,0 +1,26 @@
+/*
+ delaboratory - color correction utility
+ Copyright (C) 2011 Jacek Poplawski
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef _DE_SAMPLE_PIXEL_H
+#define _DE_SAMPLE_PIXEL_H
+
+#include "value.h"
+
+deValue samplePixel(const deValue* src, int xx1, int xx2, int yy1, int yy2, bool mirrorX, bool mirrorY, int ws, int hs);
+
+#endif
diff -Nru delaboratory-0.7/algorithms/scale_channel.cc delaboratory-0.8/algorithms/scale_channel.cc
--- delaboratory-0.7/algorithms/scale_channel.cc 1970-01-01 00:00:00.000000000 +0000
+++ delaboratory-0.8/algorithms/scale_channel.cc 2012-07-10 23:38:22.000000000 +0000
@@ -0,0 +1,99 @@
+/*
+ delaboratory - color correction utility
+ Copyright (C) 2011 Jacek Poplawski
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include "scale_channel.h"
+#include "sample_pixel.h"
+
+void scaleChannel(const deValue* src, deValue* dst, deValue z_x1, deValue z_y1, deValue z_x2, deValue z_y2, int w, int h, bool mirrorX, bool mirrorY, int rotate, int ws, int hs, deValue contrast)
+{
+ int x1;
+ int y1;
+ int x2;
+ int y2;
+ x1 = ws * z_x1;
+ y1 = hs * z_y1;
+ x2 = ws * z_x2;
+ y2 = hs * z_y2;
+ if ((rotate == 90) || (rotate == 270))
+ {
+ x1 = hs * z_x1;
+ y1 = ws * z_y1;
+ x2 = hs * z_x2;
+ y2 = ws * z_y2;
+ }
+
+ deValue scaleW;
+ deValue scaleH;
+
+ deValue dx = x2 - x1;
+ deValue dy = y2 - y1;
+
+ scaleW = dx / w;
+ scaleH = dy / h;
+
+ if (scaleW <= 0)
+ {
+ }
+ if (scaleH <= 0)
+ {
+ }
+
+ int yy1;
+ int yy2;
+ int xx1;
+ int xx2;
+
+ int x;
+ for (x = 0; x < w; x++)
+ {
+ xx1 = scaleW * x;
+ xx2 = scaleW * (x + 1);
+
+ int y;
+ for (y = 0; y < h; y++)
+ {
+ yy1 = scaleH * y;
+ yy2 = scaleH * (y + 1);
+
+ deValue v = 1;
+
+ if (rotate == 0)
+ {
+ v = samplePixel(src, x1 + xx1, x1 + xx2, y1 + yy1, y1 + yy2, mirrorX, mirrorY, ws, hs);
+ }
+ if (rotate == 90)
+ {
+ v = samplePixel(src, ws - 1 - yy2 - y1, ws - 1 - yy1 - y1, xx1 + x1, xx2 + x1, mirrorX, mirrorY, ws, hs);
+ }
+ if (rotate == 180)
+ {
+ v = samplePixel(src, ws - 1 - xx2 - x1, ws - 1 - xx1 - x1, hs - 1 - yy2 - y1, hs - 1 - yy1 - y1, mirrorX, mirrorY, ws, hs);
+ }
+ if (rotate == 270)
+ {
+ v = samplePixel(src, y1 + yy1, y1 + yy2, hs - 1 - xx2 - x1, hs - 1 - xx1 - x1, mirrorX, mirrorY, ws, hs);
+ }
+
+ dst[y * w + x] = contrast * v + 0.5 - 0.5 * contrast;
+
+ }
+
+ }
+
+}
+
diff -Nru delaboratory-0.7/algorithms/scale_channel.h delaboratory-0.8/algorithms/scale_channel.h
--- delaboratory-0.7/algorithms/scale_channel.h 1970-01-01 00:00:00.000000000 +0000
+++ delaboratory-0.8/algorithms/scale_channel.h 2012-07-10 23:38:22.000000000 +0000
@@ -0,0 +1,26 @@
+/*
+ delaboratory - color correction utility
+ Copyright (C) 2011 Jacek Poplawski
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef _DE_SCALE_CHANNEL_H
+#define _DE_SCALE_CHANNEL_H
+
+#include "value.h"
+
+void scaleChannel(const deValue* src, deValue* dst, deValue z_x1, deValue z_y1, deValue z_x2, deValue z_y2, int w, int h, bool mirrorX, bool mirrorY, int rotate, int ws, int hs, deValue contrast);
+
+#endif
diff -Nru delaboratory-0.7/algorithms/usm.cc delaboratory-0.8/algorithms/usm.cc
--- delaboratory-0.7/algorithms/usm.cc 1970-01-01 00:00:00.000000000 +0000
+++ delaboratory-0.8/algorithms/usm.cc 2012-06-16 17:43:16.000000000 +0000
@@ -0,0 +1,288 @@
+/*
+ delaboratory - color correction utility
+ Copyright (C) 2011 Jacek Poplawski
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include "usm.h"
+#include "logger.h"
+#include "blur.h"
+#include "blend_channel.h"
+#include
+#include "image.h"
+#include "color_space_utils.h"
+
+void unsharpMask(const deValue* source, const deValue* mask, deValue* destination, int n, deValue a)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ {
+ deValue src = source[i];
+ deValue u = src - mask[i];
+
+ deValue d = src + a * u;
+
+ if (d < 0)
+ {
+ destination[i] = 0;
+ }
+ else if (d > 1)
+ {
+ destination[i] = 1;
+ }
+ else
+ {
+ destination[i] = d;
+ }
+ }
+}
+
+void unsharpMask(const deValue* source, const deValue* mask, deValue* destination, int n, deValue a, deValue t)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ {
+ deValue src = source[i];
+ deValue u = src - mask[i];
+
+ if (fabs(2 * u) >= t)
+ {
+ deValue d = src + a * u;
+
+ if (d < 0)
+ {
+ destination[i] = 0;
+ }
+ else if (d > 1)
+ {
+ destination[i] = 1;
+ }
+ else
+ {
+ destination[i] = d;
+ }
+ }
+ else
+ {
+ destination[i] = src;
+ }
+ }
+}
+
+bool unsharpMask(const deValue* source, deValue* destination, deSize& size, deValue a, deValue r, deValue t, deBlurType type)
+{
+ logInfo("unsharp mask start");
+ int n = size.getN();
+
+ deValue* mask = NULL;
+ try
+ {
+ mask = new deValue [n];
+ }
+ catch (std::bad_alloc)
+ {
+ logError("allocating memory in USM");
+ if (mask)
+ {
+ delete [] mask;
+ }
+ return false;
+ }
+
+ if (mask)
+ {
+ logInfo("mask allocated");
+ }
+ else
+ {
+ logError("unable to allocate mask");
+ }
+
+ deValue b_t = 0.0;
+
+ if (blurChannel(source, mask, size, r, r, type, b_t))
+ {
+ if (t > 0)
+ {
+ unsharpMask(source, mask, destination, n, a, t);
+ }
+ else
+ {
+ unsharpMask(source, mask, destination, n, a);
+ }
+ }
+
+ delete [] mask;
+
+ logInfo("unsharp mask DONE");
+
+ return true;
+}
+
+bool autoDodgeBurn(const deValue* source, deValue* destination, deSize& size, deValue r1, deValue r2, deValue t, bool burn)
+{
+ int n = size.getN();
+
+ deValue* mask1 = NULL;
+ try
+ {
+ mask1 = new deValue [n];
+ }
+ catch (std::bad_alloc)
+ {
+ logError("allocating memory");
+ if (mask1)
+ {
+ delete [] mask1;
+ }
+ return false;
+ }
+
+ blurChannel(source, mask1, size, r1, r1, deBoxBlur, 0.0);
+ int i;
+
+ t = 1 - t;
+
+ if (burn)
+ {
+
+ deValue d = 1.0 - t;
+ deValue s = 1.0 / d;
+
+ for (i = 0; i < n; i++)
+ {
+ deValue v = 1.0 - mask1[i];
+ if (v < t)
+ {
+ v = 0.0;
+ }
+ else
+ {
+ v = s * (v - t);
+ if (v < 0)
+ {
+ v = 0;
+ }
+ }
+ mask1[i] = v;
+ }
+ }
+ else
+ {
+ deValue d = 1.0 - t;
+ deValue s = 1.0 / d;
+
+ for (i = 0; i < n; i++)
+ {
+ deValue v = mask1[i];
+ if (v < t)
+ {
+ v = 0.0;
+ }
+ else
+ {
+ v = s * (v - t);
+ if (v > 1)
+ {
+ v = 1;
+ }
+ }
+ mask1[i] = v;
+ }
+ }
+
+
+ blurChannel(mask1, mask1, size, r2, r2, deBoxBlur, 0.0);
+
+ deBlendMode mode = deBlendDodge;
+ if (burn)
+ {
+ mode = deBlendBurn;
+ }
+
+ blendChannel(source, source, destination, mask1, mode, 1.0, n);
+
+ delete [] mask1;
+
+ return true;
+}
+
+bool shadowsHighlights(deValue r, int channel, const deImage& sourceImage, deImage& mainLayerImage, bool shadows)
+{
+ deSize size = mainLayerImage.getChannelSize();
+ int n = size.getN();
+
+ deValue* mask = NULL;
+ try
+ {
+ mask = new deValue [n];
+ }
+ catch (std::bad_alloc)
+ {
+ logError("allocating memory");
+ if (mask)
+ {
+ delete [] mask;
+ }
+ return false;
+ }
+
+ const deValue* source = sourceImage.startRead(channel);
+ blurChannel(source, mask, size, r, r, deBoxBlur, 0.0);
+ sourceImage.finishRead(channel);
+
+ int i;
+ int nc = getColorSpaceSize(sourceImage.getColorSpace());
+ for (i = 0; i < nc; i++)
+ {
+ deValue* d = mainLayerImage.startWrite(i);
+ const deValue* s = sourceImage.startRead(i);
+ int j;
+ if (shadows)
+ {
+ for (j = 0; j < n; j++)
+ {
+ deValue v = s[j];
+ deValue m = mask[j];
+ deValue r = calcBlendResult(v, m, deBlendOverlayInvert);
+ if (r > v)
+ {
+ v = r;
+ }
+ d[j] = v;
+ }
+ }
+ else
+ {
+ for (j = 0; j < n; j++)
+ {
+ deValue v = s[j];
+ deValue m = mask[j];
+ deValue r = calcBlendResult(v, m, deBlendOverlayInvert);
+ if (r < v)
+ {
+ v = r;
+ }
+ d[j] = v;
+ }
+ }
+ sourceImage.finishRead(i);
+ mainLayerImage.finishWrite(i);
+ }
+
+ delete [] mask;
+
+ return true;
+}
diff -Nru delaboratory-0.7/algorithms/usm.h delaboratory-0.8/algorithms/usm.h
--- delaboratory-0.7/algorithms/usm.h 1970-01-01 00:00:00.000000000 +0000
+++ delaboratory-0.8/algorithms/usm.h 2012-06-08 22:38:01.000000000 +0000
@@ -0,0 +1,31 @@
+/*
+ delaboratory - color correction utility
+ Copyright (C) 2011 Jacek Poplawski
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef _DE_USM_H
+#define _DE_USM_H
+
+#include "value.h"
+#include "size.h"
+#include "blur.h"
+class deImage;
+
+bool unsharpMask(const deValue* source, deValue* destination, deSize& size, deValue a, deValue r, deValue t, deBlurType type);
+bool autoDodgeBurn(const deValue* source, deValue* destination, deSize& size, deValue r1, deValue r2, deValue t, bool burn);
+bool shadowsHighlights(deValue r, int channel, const deImage& sourceImage, deImage& mainLayerImage, bool shadows);
+
+#endif
diff -Nru delaboratory-0.7/algorithms/vignette.cc delaboratory-0.8/algorithms/vignette.cc
--- delaboratory-0.7/algorithms/vignette.cc 1970-01-01 00:00:00.000000000 +0000
+++ delaboratory-0.8/algorithms/vignette.cc 2012-06-16 17:23:38.000000000 +0000
@@ -0,0 +1,173 @@
+/*
+ delaboratory - color correction utility
+ Copyright (C) 2011 Jacek Poplawski
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include "vignette.h"
+#include
+#include
+#include "logger.h"
+#include "str.h"
+
+deEllipse::deEllipse(deValue _centerX, deValue _centerY, deValue _radiusX, deValue _radiusY)
+:centerX(_centerX),
+ centerY(_centerY),
+ radiusX(_radiusX),
+ radiusY(_radiusY)
+{
+}
+
+deEllipse::~deEllipse()
+{
+}
+
+deValue deEllipse::processX(deValue x) const
+{
+ x = x - centerX;
+
+ x /= radiusX;
+
+ return x;
+}
+
+deValue deEllipse::processY(deValue y) const
+{
+ y = y - centerY;
+
+ y /= radiusY;
+
+ return y;
+}
+
+bool deEllipse::isValid() const
+{
+ if (radiusX <= 0.0)
+ {
+ return false;
+ }
+ if (radiusY <= 0.0)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+void vignetteChannel(deValue* destination, deSize size, deEllipse ellipse, deValue light, deValue darkness, deValue spot)
+{
+ logInfo("vignette start");
+ if (!destination)
+ {
+ logError("NULL channel in vignette");
+ return;
+ }
+
+ if (!ellipse.isValid())
+ {
+ logError("invalid ellipce in ignette");
+ return;
+ }
+
+ int w = size.getW();
+ int h = size.getH();
+
+ if (w == 0)
+ {
+ return;
+ }
+
+ if (h == 0)
+ {
+ return;
+ }
+
+ deValue ww = w / 2.0;
+ deValue hh = h / 2.0;
+
+ int i;
+ int j;
+
+ int p = 0;
+
+ for (i = 0; i < h; i++)
+ {
+ deValue y = (i - hh) / hh;
+
+ y = ellipse.processY(y);
+
+ for (j = 0; j < w; j++)
+ {
+ deValue x = (j - ww) / ww;
+
+ x = ellipse.processX(x);
+
+ deValue r = 1.0;
+
+ deValue rr = x * x + y * y;
+
+// if (rr <= 1.0)
+ {
+ r = sqrt(rr);
+ }
+
+ deValue v = 1.0 - r;
+
+ if (v > 0)
+ {
+ v = sin(v * M_PI / 2);
+ }
+
+ deValue vv = darkness + (light - darkness) * v;
+ if (vv < 0)
+ {
+ vv = 0;
+ }
+ if (vv > 1)
+ {
+ vv = 1;
+ }
+
+ destination[p] = vv;
+ p++;
+ }
+ }
+
+ logInfo("vignette DONE");
+
+}
+
+deEllipse calcEllipse(deValue radX, deValue radY, deValue cenX, deValue cenY, deValue x1, deValue y1, deValue x2, deValue y2)
+{
+ deValue w = x2 - x1;
+ deValue h = y2 - y1;
+
+ deValue rx = radX / w;
+ deValue ry = radY / h;
+
+ // 0..1
+ deValue ccx = (cenX + 1.0) / 2.0;
+ deValue ccy = (cenY + 1.0) / 2.0;
+
+ deValue cccx = (ccx - x1) / w;
+ deValue cccy = (ccy - y1) / h;
+
+ // -1..1
+ deValue cx = cccx * 2.0 - 1.0;
+ deValue cy = cccy * 2.0 - 1.0;
+
+ return deEllipse(cx, cy, rx, ry);
+}
+
diff -Nru delaboratory-0.7/algorithms/vignette.h delaboratory-0.8/algorithms/vignette.h
--- delaboratory-0.7/algorithms/vignette.h 1970-01-01 00:00:00.000000000 +0000
+++ delaboratory-0.8/algorithms/vignette.h 2012-06-08 22:38:01.000000000 +0000
@@ -0,0 +1,47 @@
+/*
+ delaboratory - color correction utility
+ Copyright (C) 2011 Jacek Poplawski
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef _DE_VIGNETTE_H
+#define _DE_VIGNETTE_H
+
+#include "value.h"
+#include "size.h"
+
+class deEllipse
+{
+ private:
+ deValue centerX;
+ deValue centerY;
+ deValue radiusX;
+ deValue radiusY;
+ public:
+ deEllipse(deValue _centerX, deValue _centerY, deValue _radiusX, deValue _radiusY);
+ virtual ~deEllipse();
+
+ deValue processX(deValue x) const;
+ deValue processY(deValue y) const;
+
+ bool isValid() const;
+
+};
+
+void vignetteChannel(deValue* destination, deSize size, deEllipse ellipse, deValue light, deValue darkness, deValue spot);
+
+deEllipse calcEllipse(deValue radX, deValue radY, deValue cenX, deValue cenY, deValue x1, deValue y1, deValue x2, deValue y2);
+
+#endif
diff -Nru delaboratory-0.7/core/base_layer.cc delaboratory-0.8/core/base_layer.cc
--- delaboratory-0.7/core/base_layer.cc 1970-01-01 00:00:00.000000000 +0000
+++ delaboratory-0.8/core/base_layer.cc 2012-07-21 16:02:12.000000000 +0000
@@ -0,0 +1,137 @@
+/*
+ delaboratory - color correction utility
+ Copyright (C) 2011 Jacek Poplawski
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include "base_layer.h"
+#include "logger.h"
+#include "str.h"
+#include "update_main_layer_image.h"
+
+
+deBaseLayer::deBaseLayer(deColorSpace _colorSpace, deChannelManager& _channelManager)
+:colorSpace(_colorSpace),
+ mainLayerImage(_colorSpace, _channelManager)
+{
+}
+
+deBaseLayer::~deBaseLayer()
+{
+}
+
+deColorSpace deBaseLayer::getColorSpace() const
+{
+ return colorSpace;
+}
+
+void deBaseLayer::lockLayer()
+{
+#ifdef DEBUG_LOG
+ logInfo("base layer before lock");
+#endif
+ mutex.lock();
+#ifdef DEBUG_LOG
+ logInfo("base layer locked");
+#endif
+}
+
+void deBaseLayer::unlockLayer()
+{
+ mutex.unlock();
+#ifdef DEBUG_LOG
+ logInfo("base layer unlocked");
+#endif
+}
+
+void deBaseLayer::processLayer(deLayerProcessType type, int channel)
+{
+#ifdef DEBUG_LOG
+ logInfo("processLayer channel: " + str(channel));
+#endif
+ switch (type)
+ {
+ case deLayerProcessFull:
+ {
+ processFull();
+ break;
+ }
+ case deLayerProcessSingleChannel:
+ {
+ processSingleChannel(channel);
+ break;
+ }
+ case deLayerProcessBlend:
+ {
+ updateBlendAllChannels();
+ break;
+ }
+ default:
+ break;
+ }
+#ifdef DEBUG_LOG
+ logInfo("processLayer DONE");
+#endif
+}
+
+bool deBaseLayer::processFull()
+{
+ return updateImage();
+}
+
+const deImage& deBaseLayer::getLayerImage() const
+{
+ return mainLayerImage;
+}
+
+void deBaseLayer::updateChannelUsage(std::map& channelUsage, int layerIndex) const
+{
+ mainLayerImage.updateChannelUsage(channelUsage, layerIndex);
+}
+
+void deBaseLayer::processSingleChannel(int channel)
+{
+ processMainImageSingleChannel(channel);
+}
+
+bool deBaseLayer::processMainImageSingleChannel(int channel)
+{
+ bool result = true;
+#ifdef DEBUG_LOG
+ logInfo("base layer process main image single channel");
+#endif
+ result = updateMainImageSingleChannel(channel);
+#ifdef DEBUG_LOG
+ logInfo("base layer process main image single channel DONE");
+#endif
+ return result;
+}
+
+bool deBaseLayer::updateImage()
+{
+ bool result = updateMainImageNotThreadedWay();
+ if (!result)
+ {
+ updateMainImageAllChannels(*this);
+ result = true;
+ }
+
+ return result;
+}
+
+void deBaseLayer::allocateChannels()
+{
+ mainLayerImage.allocateChannels();
+}
diff -Nru delaboratory-0.7/core/base_layer.h delaboratory-0.8/core/base_layer.h
--- delaboratory-0.7/core/base_layer.h 1970-01-01 00:00:00.000000000 +0000
+++ delaboratory-0.8/core/base_layer.h 2012-06-16 01:48:25.000000000 +0000
@@ -0,0 +1,94 @@
+/*
+ delaboratory - color correction utility
+ Copyright (C) 2011 Jacek Poplawski
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef _DE_BASE_LAYER_H
+#define _DE_BASE_LAYER_H
+
+#include "color_space.h"
+#include "mutex.h"
+#include
+#include
+#include "image.h"
+class deChannelManager;
+class deViewManager;
+class deProperty;
+class dePreset;
+class dePropertyNumeric;
+class dePropertyChoice;
+class dePropertyBoolean;
+
+enum deLayerProcessType
+{
+ deLayerProcessInvalid,
+ deLayerProcessFull,
+ deLayerProcessSingleChannel,
+ deLayerProcessBlend
+};
+
+class deBaseLayer
+{
+ private:
+ deBaseLayer(const deBaseLayer& layer);
+ deBaseLayer& operator = (const deBaseLayer& layer);
+
+ deMutex mutex;
+
+ virtual bool updateMainImageSingleChannel(int channel) {return false;};
+
+ protected:
+ deColorSpace colorSpace;
+ deImage mainLayerImage;
+
+ virtual bool updateBlendAllChannels() {return false;};
+ virtual bool updateMainImageNotThreadedWay() {return false;};
+ virtual bool updateImage();
+
+ public:
+ deBaseLayer(deColorSpace _colorSpace, deChannelManager& _channelManager);
+ virtual ~deBaseLayer();
+
+ deColorSpace getColorSpace() const;
+
+ void lockLayer();
+ void unlockLayer();
+
+ void processLayer(deLayerProcessType type, int channel);
+
+ bool processFull();
+ virtual void processSingleChannel(int channel);
+
+ bool updateImageThreadCall();
+
+ virtual std::string getType() const = 0;
+
+ virtual const deImage& getLayerImage() const;
+
+ virtual void updateChannelUsage(std::map& channelUsage, int layerIndex) const;
+
+ virtual std::string getWarning() const {return "OK";};
+
+ virtual bool onImageClick(deValue x, deValue y) {return false;};
+ virtual void beforeSetUIFromLayer() {};
+
+ bool processMainImageSingleChannel(int channel);
+
+ virtual void allocateChannels();
+
+};
+
+#endif
diff -Nru delaboratory-0.7/core/base_layer_with_properties.cc delaboratory-0.8/core/base_layer_with_properties.cc
--- delaboratory-0.7/core/base_layer_with_properties.cc 1970-01-01 00:00:00.000000000 +0000
+++ delaboratory-0.8/core/base_layer_with_properties.cc 2012-07-10 23:38:22.000000000 +0000
@@ -0,0 +1,211 @@
+/*
+ delaboratory - color correction utility
+ Copyright (C) 2011 Jacek Poplawski
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include "base_layer_with_properties.h"
+#include "color_space_utils.h"
+#include "logger.h"
+#include "semaphore.h"
+#include "str.h"
+#include "property_numeric.h"
+#include "property_boolean.h"
+#include "property_choice.h"
+#include "preset.h"
+
+deBaseLayerWithProperties::deBaseLayerWithProperties(deColorSpace _colorSpace, deChannelManager& _channelManager)
+:deBaseLayer(_colorSpace, _channelManager)
+{
+}
+
+deBaseLayerWithProperties::~deBaseLayerWithProperties()
+{
+ std::vector::iterator i;
+ while (properties.size() > 0)
+ {
+ i = properties.begin();
+ delete *i;
+ properties.erase(i);
+ }
+ std::vector::iterator j;
+ while (presets.size() > 0)
+ {
+ j = presets.begin();
+ delete *j;
+ presets.erase(j);
+ }
+}
+
+void deBaseLayerWithProperties::createPropertyNumeric(const std::string& _name, deValue _min, deValue _max)
+{
+ std::vector::iterator i;
+ for (i = properties.begin(); i != properties.end(); i++)
+ {
+ deProperty* property = *i;
+ if (property->getName() == _name)
+ {
+ return;
+ }
+ }
+ properties.push_back(new dePropertyNumeric(_name, _min, _max));
+}
+
+void deBaseLayerWithProperties::createPropertyChoice(const std::string& _name, const std::vector& _choices)
+{
+ std::vector::iterator i;
+ for (i = properties.begin(); i != properties.end(); i++)
+ {
+ deProperty* property = *i;
+ if (property->getName() == _name)
+ {
+ return;
+ }
+ }
+ properties.push_back(new dePropertyChoice(_name, _choices));
+}
+
+void deBaseLayerWithProperties::createPropertyBoolean(const std::string& _name)
+{
+ std::vector::iterator i;
+ for (i = properties.begin(); i != properties.end(); i++)
+ {
+ deProperty* property = *i;
+ if (property->getName() == _name)
+ {
+ return;
+ }
+ }
+ properties.push_back(new dePropertyBoolean(_name));
+}
+
+deProperty* deBaseLayerWithProperties::getProperty(const std::string& _name)
+{
+ std::vector::iterator i;
+ for (i = properties.begin(); i != properties.end(); i++)
+ {
+ deProperty* property = *i;
+ if (property->getName() == _name)
+ {
+ return property;
+ }
+ }
+ logError("property " + _name + " not found");
+
+ return NULL;
+}
+
+const deProperty* deBaseLayerWithProperties::getProperty(const std::string& _name) const
+{
+ std::vector::const_iterator i;
+ for (i = properties.begin(); i != properties.end(); i++)
+ {
+ deProperty* property = *i;
+ if (property->getName() == _name)
+ {
+ return property;
+ }
+ }
+
+ return NULL;
+}
+
+void deBaseLayerWithProperties::getProperties(std::vector& names) const
+{
+ std::vector::const_iterator i;
+ for (i = properties.begin(); i != properties.end(); i++)
+ {
+ deProperty* property = *i;
+ names.push_back(property->getName());
+ }
+
+}
+
+dePropertyNumeric* deBaseLayerWithProperties::getPropertyNumeric(const std::string& _name)
+{
+ return dynamic_cast(getProperty(_name));
+}
+
+const dePropertyNumeric* deBaseLayerWithProperties::getPropertyNumeric(const std::string& _name) const
+{
+ return dynamic_cast(getProperty(_name));
+}
+
+dePropertyChoice* deBaseLayerWithProperties::getPropertyChoice(const std::string& _name)
+{
+ return dynamic_cast(getProperty(_name));
+}
+
+const dePropertyChoice* deBaseLayerWithProperties::getPropertyChoice(const std::string& _name) const
+{
+ return dynamic_cast(getProperty(_name));
+}
+
+dePropertyBoolean* deBaseLayerWithProperties::getPropertyBoolean(const std::string& _name)
+{
+ return dynamic_cast(getProperty(_name));
+}
+
+const dePropertyBoolean* deBaseLayerWithProperties::getPropertyBoolean(const std::string& _name) const
+{
+ return dynamic_cast(getProperty(_name));
+}
+
+deValue deBaseLayerWithProperties::getNumericValue(const std::string& name) const
+{
+ const dePropertyNumeric* p = getPropertyNumeric(name);
+ if (p)
+ {
+ return p->get();
+ }
+ return 0;
+}
+
+void deBaseLayerWithProperties::applyPreset(const std::string& name)
+{
+ std::vector::iterator i;
+ for (i = presets.begin(); i != presets.end(); i++)
+ {
+ dePreset* preset = *i;
+ if (preset->getName() == name)
+ {
+ preset->apply(*this);
+ }
+ }
+}
+
+void deBaseLayerWithProperties::getPresets(std::vector& names)
+{
+ std::vector::iterator i;
+ for (i = presets.begin(); i != presets.end(); i++)
+ {
+ dePreset* preset = *i;
+ if (preset)
+ {
+ names.push_back(preset->getName());
+ }
+ else
+ {
+ logError("NULL preset found");
+ }
+ }
+}
+
+dePreset* deBaseLayerWithProperties::createPreset(const std::string& name)
+{
+ dePreset* preset = new dePreset(name);
+ presets.push_back(preset);
+ return preset;
+}
diff -Nru delaboratory-0.7/core/base_layer_with_properties.h delaboratory-0.8/core/base_layer_with_properties.h
--- delaboratory-0.7/core/base_layer_with_properties.h 1970-01-01 00:00:00.000000000 +0000
+++ delaboratory-0.8/core/base_layer_with_properties.h 2012-06-08 22:38:01.000000000 +0000
@@ -0,0 +1,66 @@
+/*
+ delaboratory - color correction utility
+ Copyright (C) 2011 Jacek Poplawski
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef _DE_BASE_LAYER_WITH_PROPERTIES_H
+#define _DE_BASE_LAYER_WITH_PROPERTIES_H
+
+#include "base_layer.h"
+
+class deBaseLayerWithProperties:public deBaseLayer
+{
+ private:
+ deBaseLayerWithProperties(const deBaseLayerWithProperties& layer);
+ deBaseLayerWithProperties& operator = (const deBaseLayerWithProperties& layer);
+
+ protected:
+ std::vector properties;
+ std::vector presets;
+
+ void createPropertyNumeric(const std::string& _name, deValue _min, deValue _max);
+ void createPropertyChoice(const std::string& _name, const std::vector& _choices);
+ void createPropertyBoolean(const std::string& _name);
+
+ public:
+ deBaseLayerWithProperties(deColorSpace _colorSpace, deChannelManager& _channelManager);
+ virtual ~deBaseLayerWithProperties();
+
+ deProperty* getProperty(const std::string& _name);
+ const deProperty* getProperty(const std::string& _name) const;
+
+ dePropertyNumeric* getPropertyNumeric(const std::string& _name);
+ const dePropertyNumeric* getPropertyNumeric(const std::string& _name) const;
+
+ dePropertyChoice* getPropertyChoice(const std::string& _name);
+ const dePropertyChoice* getPropertyChoice(const std::string& _name) const;
+
+ dePropertyBoolean* getPropertyBoolean(const std::string& _name);
+ const dePropertyBoolean* getPropertyBoolean(const std::string& _name) const;
+
+ void getProperties(std::vector& names) const;
+
+ deValue getNumericValue(const std::string& name) const;
+
+ void applyPreset(const std::string& name);
+ void getPresets(std::vector& names);
+ dePreset* createPreset(const std::string& name);
+
+ virtual void executeOperation(const std::string& o) {};
+
+};
+
+#endif
diff -Nru delaboratory-0.7/core/base_layer_with_source.cc delaboratory-0.8/core/base_layer_with_source.cc
--- delaboratory-0.7/core/base_layer_with_source.cc 1970-01-01 00:00:00.000000000 +0000
+++ delaboratory-0.8/core/base_layer_with_source.cc 2012-07-03 22:57:08.000000000 +0000
@@ -0,0 +1,85 @@
+/*
+ delaboratory - color correction utility
+ Copyright (C) 2011 Jacek Poplawski
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include "base_layer_with_source.h"
+#include "layer_stack.h"
+#include "copy_channel.h"
+#include "logger.h"
+#include "str.h"
+
+deBaseLayerWithSource::deBaseLayerWithSource(deColorSpace _colorSpace, deChannelManager& _channelManager, int _sourceLayerIndex, deLayerStack& _layerStack)
+:deBaseLayerWithProperties(_colorSpace, _channelManager),
+sourceLayerIndex(_sourceLayerIndex),
+layerStack(_layerStack)
+{
+}
+
+deBaseLayerWithSource::~deBaseLayerWithSource()
+{
+}
+
+const deBaseLayer& deBaseLayerWithSource::getSourceLayer() const
+{
+ const deBaseLayer* layer = layerStack.getLayer(sourceLayerIndex);
+ return *layer;
+}
+
+const deBaseLayer& deBaseLayerWithSource::getOriginalLayer() const
+{
+ const deBaseLayer* layer = layerStack.getLayer(0);
+ return *layer;
+}
+
+const deImage& deBaseLayerWithSource::getSourceImage() const
+{
+ return getSourceLayer().getLayerImage();
+}
+
+const deImage& deBaseLayerWithSource::getOriginalImage() const
+{
+ return getOriginalLayer().getLayerImage();
+}
+
+const deImage& deBaseLayerWithSource::getOtherLayerImage(int a) const
+{
+ deBaseLayer* applied = layerStack.getLayer(a);
+
+ const deImage& appliedImage = applied->getLayerImage();
+
+ return appliedImage;
+}
+
+deColorSpace deBaseLayerWithSource::getSourceColorSpace() const
+{
+ return getSourceLayer().getColorSpace();
+}
+
+int deBaseLayerWithSource::getLayerStackSize() const
+{
+ return layerStack.getSize();
+}
+
+void deBaseLayerWithSource::copySourceChannel(int channel)
+{
+ logInfo("copy source channel " + str(channel));
+ const deValue* s = getSourceImage().startRead(channel);
+ deValue* d = mainLayerImage.startWrite(channel);
+ copyChannel(s, d, mainLayerImage.getChannelSize().getN());
+ mainLayerImage.finishWrite(channel);
+ getSourceImage().finishRead(channel);
+}
diff -Nru delaboratory-0.7/core/base_layer_with_source.h delaboratory-0.8/core/base_layer_with_source.h
--- delaboratory-0.7/core/base_layer_with_source.h 1970-01-01 00:00:00.000000000 +0000
+++ delaboratory-0.8/core/base_layer_with_source.h 2012-07-03 22:57:08.000000000 +0000
@@ -0,0 +1,50 @@
+/*
+ delaboratory - color correction utility
+ Copyright (C) 2011 Jacek Poplawski
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef _DE_BASE_LAYER_WITH_SOURCE_H
+#define _DE_BASE_LAYER_WITH_SOURCE_H
+
+#include "base_layer_with_properties.h"
+class deLayerStack;
+
+class deBaseLayerWithSource:public deBaseLayerWithProperties
+{
+ private:
+ int sourceLayerIndex;
+ deLayerStack& layerStack;
+
+ const deBaseLayer& getSourceLayer() const;
+ const deBaseLayer& getOriginalLayer() const;
+
+ protected:
+ void copySourceChannel(int channel);
+
+ public:
+ deBaseLayerWithSource(deColorSpace _colorSpace, deChannelManager& _channelManager, int _sourceLayer, deLayerStack& _layerStack);
+ virtual ~deBaseLayerWithSource();
+
+ const deImage& getOriginalImage() const;
+ const deImage& getSourceImage() const;
+ const deImage& getOtherLayerImage(int a) const;
+ deColorSpace getSourceColorSpace() const;
+ int getLayerStackSize() const;
+
+
+};
+
+#endif
diff -Nru delaboratory-0.7/core/channel_manager.cc delaboratory-0.8/core/channel_manager.cc
--- delaboratory-0.7/core/channel_manager.cc 1970-01-01 00:00:00.000000000 +0000
+++ delaboratory-0.8/core/channel_manager.cc 2012-07-21 16:02:12.000000000 +0000
@@ -0,0 +1,397 @@
+/*
+ delaboratory - color correction utility
+ Copyright (C) 2011 Jacek Poplawski
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include "channel_manager.h"
+#include
+#include
+#include "logger.h"
+#include "str.h"
+
+deChannelManager::deChannelManager()
+:channelSize(0,0)
+{
+#ifdef DEBUG_LOG
+ logInfo("channel manager constructor");
+#endif
+}
+
+deChannelManager::~deChannelManager()
+{
+#ifdef DEBUG_LOG
+ logInfo("channel manager destructor");
+#endif
+ unsigned int i;
+ for (i = 0; i < channels.size(); i++)
+ {
+ lock();
+
+ freeChannel(i);
+ delete mutexes[i];
+
+ unlock();
+ }
+#ifdef DEBUG_LOG
+ logInfo("channel manager destructor DONE");
+#endif
+}
+
+void deChannelManager::setChannelSize(const deSize& size, bool reallocate)
+{
+ lock();
+
+ channelSize = size;
+
+ if (channelSize.getW() < 0)
+ {
+ logError("w: " + str(channelSize.getW()) + " when setting channel size in channel manager");
+ }
+ if (channelSize.getH() < 0)
+ {
+ logError("h: " + str(channelSize.getH()) + " when setting channel size in channel manager");
+ }
+
+ unsigned int i;
+ for (i = 0; i < channels.size(); i++)
+ {
+ logInfo("destroy channel " + str(i));
+ mutexes[i]->lockWrite();
+ tryDeallocateChannel(i);
+ if (reallocate)
+ {
+ tryAllocateChannel(i);
+ }
+ mutexes[i]->unlockWrite();
+ }
+
+ unlock();
+}
+
+void deChannelManager::lock()
+{
+#ifdef DEBUG_LOG
+ logInfo("channel manager before lock");
+#endif
+ mutex.lock();
+#ifdef DEBUG_LOG
+ logInfo("channel manager locked");
+#endif
+}
+
+void deChannelManager::unlock()
+{
+ mutex.unlock();
+#ifdef DEBUG_LOG
+ logInfo("channel manager unlocked");
+#endif
+}
+
+int deChannelManager::reserveNewChannel()
+{
+ lock();
+
+ deValue* channel = NULL;
+
+ int c = -1;
+ if (trashed.size() > 0)
+ {
+ std::set::iterator i = trashed.begin();
+ c = *i;
+ trashed.erase(c);
+ channels[c] = channel;
+ logInfo("reused trashed channel " + str(c));
+ }
+ else
+ {
+ channels.push_back(channel);
+ mutexes.push_back(new deMutexReadWrite(4));
+ c = channels.size() - 1;
+ logInfo("added channel " + str(c));
+ }
+
+ unlock();
+
+ return c;
+}
+
+void deChannelManager::freeChannel(int index)
+{
+ lock();
+
+ bool error = false;
+
+ if (index < 0)
+ {
+ logError("freeChannel index < 0");
+ error = true;
+ }
+ else if ((unsigned int)index >= channels.size())
+ {
+ int s = channels.size();
+ logError("freeChannel index >= " + str(s));
+ error = true;
+ }
+
+ if (!error)
+ {
+ logInfo("freeChannel before lockWrite");
+ mutexes[index]->lockWrite();
+ logInfo("freeChannel after locks");
+
+ assert(index >= 0);
+ assert((unsigned int)index < channels.size());
+
+ if (channels[index])
+ {
+ delete [] channels[index];
+ channels[index] = NULL;
+ trashed.insert(index);
+ logInfo("destroyed channel " + str(index));
+ }
+ else
+ {
+ }
+
+ mutexes[index]->unlockWrite();
+ }
+
+ unlock();
+
+ logInfo("freeChannel after unlocks");
+
+}
+
+deSize deChannelManager::getChannelSizeFromChannelManager() const
+{
+ if (channelSize.getW() < 0)
+ {
+ logError("w: " + str(channelSize.getW()) + " when getting channel size from channel manager");
+ }
+ if (channelSize.getH() < 0)
+ {
+ logError("h: " + str(channelSize.getH()) + " when getting channel size from channel manager");
+ }
+
+ deSize size = channelSize;
+
+ return size;
+}
+
+void deChannelManager::tryAllocateChannel(int index)
+{
+ lock();
+
+ bool error = false;
+
+ if (index < 0)
+ {
+ logError("tryAllocateChannel index < 0");
+ error = true;
+ }
+ else if ((unsigned int)index >= channels.size())
+ {
+ int s = channels.size();
+ logError("tryAllocateChannel index >= " + str(s));
+ error = true;
+ }
+
+ if (!error)
+ {
+ if (!channels[index])
+ {
+ logInfo("allocating channel " + str(index));
+ try
+ {
+ deValue* c = new deValue [channelSize.getN()];
+ if (c)
+ {
+ logInfo("allocated channel " + str(index));
+ }
+ else
+ {
+ logError("unable to allocate channel " + str(index));
+ }
+ channels[index] = c;
+ }
+ catch (std::bad_alloc)
+ {
+ logError("bad_alloc exception on allocate channel " + str(index));
+ channels[index] = NULL;
+ }
+ }
+ }
+
+ unlock();
+
+}
+
+void deChannelManager::tryDeallocateChannel(int index)
+{
+ lock();
+
+ bool error = false;
+
+ if (index < 0)
+ {
+ logError("tryDeallocateChannel index < 0");
+ error = true;
+ }
+ else if ((unsigned int)index >= channels.size())
+ {
+ int s = channels.size();
+ logError("tryDeallocateChannel index >= " + str(s));
+ error = true;
+ }
+
+ if (!error)
+ {
+ if (channels[index])
+ {
+ logInfo("deallocating channel " + str(index));
+ delete [] channels[index];
+ channels[index] = NULL;
+ }
+ }
+
+ unlock();
+
+}
+
+bool deChannelManager::isImageEmpty() const
+{
+ return channelSize.getN() == 0;
+}
+
+const deValue* deChannelManager::startRead(int index)
+{
+#ifdef DEBUG_LOG
+ logInfo("startRead " + str(index));
+#endif
+
+ bool error = false;
+
+ if (index < 0)
+ {
+ logError("startRead index < 0");
+ error = true;
+ }
+ else if ((unsigned int)index >= channels.size())
+ {
+ int s = channels.size();
+ logError("startRead index >= " + str(s));
+ error = true;
+ }
+
+ deValue* p = NULL;
+
+ if (!error)
+ {
+ mutexes[index]->lockRead();
+
+ p = channels[index];
+ }
+
+ return p;
+}
+
+void deChannelManager::finishRead(int index)
+{
+#ifdef DEBUG_LOG
+ logInfo("finishRead " + str(index));
+#endif
+
+ bool error = false;
+
+ if (index < 0)
+ {
+ logError("finishRead index < 0");
+ error = true;
+ }
+ else if ((unsigned int)index >= channels.size())
+ {
+ int s = channels.size();
+ logError("finishRead index >= " + str(s));
+ error = true;
+ }
+
+ if (!error)
+ {
+ mutexes[index]->unlockRead();
+ }
+}
+
+deValue* deChannelManager::startWrite(int index)
+{
+#ifdef DEBUG_LOG
+ logInfo("startWrite " + str(index));
+#endif
+
+ bool error = false;
+
+ if (index < 0)
+ {
+ logError("startWrite index < 0");
+ error = true;
+ }
+ else if ((unsigned int)index >= channels.size())
+ {
+ int s = channels.size();
+ logError("startWrite index >= " + str(s));
+ error = true;
+ }
+
+ deValue* p = NULL;
+
+ if (!error)
+ {
+ mutexes[index]->lockWrite();
+
+#ifdef DEBUG_LOG
+ logInfo("startWrite " + str(index) + " locked");
+#endif
+
+ p = channels[index];
+ }
+
+ return p;
+}
+
+void deChannelManager::finishWrite(int index)
+{
+#ifdef DEBUG_LOG
+ logInfo("finishWrite " + str(index));
+#endif
+
+ bool error = false;
+
+ if (index < 0)
+ {
+ logError("finishWrite index < 0");
+ error = true;
+ }
+ else if ((unsigned int)index >= channels.size())
+ {
+ int s = channels.size();
+ logError("finishWrite index >= " + str(s));
+ error = true;
+ }
+
+ if (!error)
+ {
+ mutexes[index]->unlockWrite();
+ }
+}
diff -Nru delaboratory-0.7/core/channel_manager.h delaboratory-0.8/core/channel_manager.h
--- delaboratory-0.7/core/channel_manager.h 1970-01-01 00:00:00.000000000 +0000
+++ delaboratory-0.8/core/channel_manager.h 2012-06-16 01:48:25.000000000 +0000
@@ -0,0 +1,70 @@
+/*
+ delaboratory - color correction utility
+ Copyright (C) 2011 Jacek Poplawski
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef _DE_CHANNEL_MANAGER_H
+#define _DE_CHANNEL_MANAGER_H
+
+#include "size.h"
+#include
+#include
+#include "mutex.h"
+#include "mutex_read_write.h"
+
+class deImage;
+class deLogger;
+
+class deChannelManager
+{
+ private:
+ deSize channelSize;
+ deMutex mutex;
+
+ std::vector channels;
+ std::vector mutexes;
+ std::set trashed;
+
+ deChannelManager(const deChannelManager& m);
+ deChannelManager& operator =(const deChannelManager& m);
+
+ public:
+ deChannelManager();
+ virtual ~deChannelManager();
+
+ void setChannelSize(const deSize& size, bool reallocate);
+ deSize getChannelSizeFromChannelManager() const;
+
+ int reserveNewChannel();
+ void freeChannel(int index);
+
+ void tryAllocateChannel(int index);
+ void tryDeallocateChannel(int index);
+
+ bool isImageEmpty() const;
+
+ const deValue* startRead(int index);
+ void finishRead(int index);
+ deValue* startWrite(int index);
+ void finishWrite(int index);
+
+ void lock();
+ void unlock();
+
+
+};
+
+#endif
diff -Nru delaboratory-0.7/core/channels.h delaboratory-0.8/core/channels.h
--- delaboratory-0.7/core/channels.h 1970-01-01 00:00:00.000000000 +0000
+++ delaboratory-0.8/core/channels.h 2012-06-08 22:38:01.000000000 +0000
@@ -0,0 +1,56 @@
+/*
+ delaboratory - color correction utility
+ Copyright (C) 2011 Jacek Poplawski
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef _DE_CHANNELS_H
+#define _DE_CHANNELS_H
+
+// RGB
+#define DE_CHANNEL_RED 0
+#define DE_CHANNEL_GREEN 1
+#define DE_CHANNEL_BLUE 2
+
+// BW
+#define DE_CHANNEL_GRAYSCALE 0
+
+// LAB
+#define DE_CHANNEL_L 0
+#define DE_CHANNEL_A 1
+#define DE_CHANNEL_B 2
+
+// LCH
+#define DE_CHANNEL_C 1
+#define DE_CHANNEL_H 2
+
+// CMY/CMYK
+#define DE_CHANNEL_CYAN 0
+#define DE_CHANNEL_MAGENTA 1
+#define DE_CHANNEL_YELLOW 2
+#define DE_CHANNEL_KEY 3
+
+// HSL/HSV
+#define DE_CHANNEL_HUE 0
+#define DE_CHANNEL_SATURATION 1
+#define DE_CHANNEL_LIGHTNESS 2
+#define DE_CHANNEL_VALUE 2
+
+// XYZ
+#define DE_CHANNEL_X 0
+#define DE_CHANNEL_Y 1
+#define DE_CHANNEL_Z 2
+
+#endif
diff -Nru delaboratory-0.7/core/color_matrix.cc delaboratory-0.8/core/color_matrix.cc
--- delaboratory-0.7/core/color_matrix.cc 1970-01-01 00:00:00.000000000 +0000
+++ delaboratory-0.8/core/color_matrix.cc 2012-07-10 23:38:22.000000000 +0000
@@ -0,0 +1,253 @@
+/*
+ delaboratory - color correction utility
+ Copyright (C) 2011 Jacek Poplawski
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include "color_matrix.h"
+#include
+#include
+
+deColorMatrix::deColorMatrix(int _w, int _h)
+{
+ width = _w;
+ height = _h;
+
+ minX = 0;
+ minY = 0;
+ maxX = 1;
+ maxY = 1;
+
+ int n = width * height;
+ matrix = new deValue [n];
+ density = new int [n];
+}
+
+deColorMatrix::~deColorMatrix()
+{
+ delete [] matrix;
+ delete [] density;
+}
+
+void deColorMatrix::clear()
+{
+ int n = width * height;
+ int i;
+ for (i = 0; i < n; i++)
+ {
+ matrix[i] = -1;
+ density[i] = 0;
+ }
+}
+
+void deColorMatrix::buildZoomed(const deValue* channelH, const deValue* channelV, const deValue* channelA, int n, int min)
+{
+ minX = 0;
+ minY = 0;
+ maxX = 1;
+ maxY = 1;
+
+ clear();
+ build(channelH, channelV, channelA, n);
+ int xx;
+ int yy;
+ int minxx = width;
+ int maxxx = -1;
+ int minyy = height;
+ int maxyy = -1;
+
+ for (xx = 0; xx < width; xx++)
+ {
+ for (yy = 0; yy < height; yy++)
+ {
+ int pos = width * yy + xx;
+ if (density[pos] >= min)
+ {
+ if (xx < minxx)
+ {
+ minxx = xx;
+ }
+ if (yy < minyy)
+ {
+ minyy = yy;
+ }
+ if (xx > maxxx)
+ {
+ maxxx = xx;
+ }
+ if (yy > maxyy)
+ {
+ maxyy = yy;
+ }
+ }
+ }
+ }
+
+ if (minxx > 0)
+ {
+ minxx--;
+ }
+ if (minyy > 0)
+ {
+ minyy--;
+ }
+ if (maxxx < width - 1)
+ {
+ maxxx++;
+ }
+ if (maxyy < height - 1)
+ {
+ maxyy++;
+ }
+
+ minX = (deValue) minxx / width;
+ minY = (deValue) minyy / height;
+ maxX = (deValue) maxxx / width;
+ maxY = (deValue) maxyy / height;
+
+ deValue margin = -0.01;
+
+ if (maxX < 0.5 - margin)
+ {
+ maxX = 0.5 - margin;
+ }
+ if (maxY < 0.5 - margin)
+ {
+ maxY = 0.5 - margin;
+ }
+ if (minX > 0.5 + margin)
+ {
+ minX = 0.5 + margin;
+ }
+ if (minY > 0.5 + margin)
+ {
+ minY = 0.5 + margin;
+ }
+
+ clear();
+ build(channelH, channelV, channelA, n);
+
+}
+
+void deColorMatrix::build(const deValue* channelH, const deValue* channelV, const deValue* channelA, int n)
+{
+ if (!channelH)
+ {
+ return;
+ }
+ if (!channelV)
+ {
+ return;
+ }
+ if (!channelA)
+ {
+ return;
+ }
+
+ int i;
+
+ for (i = 0; i < n; i++)
+ {
+ deValue h = channelH[i];
+ deValue v = channelV[i];
+ deValue a = channelA[i];
+
+ if ((h >= 0) && (h < 1) && (v >= 0) && (v < 1) && ((a >= 0) && (a < 1)))
+ {
+ int x = (h - minX) / (maxX - minX) * width;
+ int y = (v - minY) / (maxY - minY) * height;
+
+ if ((x >= 0) && (y >= 0) && (x < width) && (y < height))
+ {
+ int pos = width * y + x;
+
+ int d = density[pos];
+
+ if (d == 0)
+ {
+ density[pos] = 1;
+ matrix[pos] = a;
+ }
+ else
+ {
+ density[pos]++;
+ matrix[pos] += a;
+ }
+ }
+ }
+ }
+
+ int nn = width * height;
+ for (i = 0; i < nn; i++)
+ {
+ int d = density[i];
+ if (d > 0)
+ {
+ matrix[i] /= d;
+ }
+ }
+}
+
+deValue deColorMatrix::get(int x, int y, int min, deValue& vx, deValue& vy, bool& center) const
+{
+ vx = minX + ((deValue) x / width) * (maxX - minX);
+ deValue vx2 = minX + ((deValue) (x+1) / width) * (maxX - minX);
+ deValue vx3 = minX + ((deValue) (x-1) / width) * (maxX - minX);
+ deValue dx = fabs(0.5 - vx);
+ deValue dx2 = fabs(0.5 - vx2);
+ deValue dx3 = fabs(0.5 - vx3);
+
+ vy = minY + ((deValue) y / height) * (maxY - minY);
+ deValue vy2 = minY + ((deValue) (y+1) / height) * (maxY - minY);
+ deValue vy3 = minY + ((deValue) (y-1) / height) * (maxY - minY);
+ deValue dy = fabs(0.5 - vy);
+ deValue dy2 = fabs(0.5 - vy2);
+ deValue dy3 = fabs(0.5 - vy3);
+
+ center = false;
+ if ((dx < dx2) && (dx < dx3))
+ {
+ center = true;
+ }
+ if ((dy < dy2) && (dy < dy3))
+ {
+ center = true;
+ }
+
+ if (x < 0)
+ {
+ return -1;
+ }
+ if (y < 0)
+ {
+ return -1;
+ }
+ if (x >= width)
+ {
+ return -1;
+ }
+ if (y >= height)
+ {
+ return -1;
+ }
+ int pos = width * y + x;
+ if (density[pos] < min)
+ {
+ return -1;
+ }
+
+ deValue result = matrix[pos];
+ return result;
+}
diff -Nru delaboratory-0.7/core/color_matrix.h delaboratory-0.8/core/color_matrix.h
--- delaboratory-0.7/core/color_matrix.h 1970-01-01 00:00:00.000000000 +0000
+++ delaboratory-0.8/core/color_matrix.h 2012-06-12 00:31:57.000000000 +0000
@@ -0,0 +1,49 @@
+/*
+ delaboratory - color correction utility
+ Copyright (C) 2011 Jacek Poplawski
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef _DE_COLOR_MATRIX_H
+#define _DE_COLOR_MATRIX_H
+
+#include "value.h"
+
+class deColorMatrix
+{
+ private:
+ int width;
+ int height;
+ deValue minX;
+ deValue minY;
+ deValue maxX;
+ deValue maxY;
+
+ deValue* matrix;
+ int* density;
+ public:
+ deColorMatrix(int _w, int _h);
+ virtual ~deColorMatrix();
+
+ void clear();
+ void build(const deValue* channelH, const deValue* channelV, const deValue* channelA, int n);
+ void buildZoomed(const deValue* channelH, const deValue* channelV, const deValue* channelA, int n, int min);
+
+ deValue get(int x, int y, int min, deValue& vx, deValue& vy, bool& center) const;
+
+
+};
+
+#endif
diff -Nru delaboratory-0.7/core/color_space.cc delaboratory-0.8/core/color_space.cc
--- delaboratory-0.7/core/color_space.cc 1970-01-01 00:00:00.000000000 +0000
+++ delaboratory-0.8/core/color_space.cc 2012-06-08 22:38:01.000000000 +0000
@@ -0,0 +1,20 @@
+/*
+ delaboratory - color correction utility
+ Copyright (C) 2011 Jacek Poplawski
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include "color_space.h"
+
diff -Nru delaboratory-0.7/core/color_space.h delaboratory-0.8/core/color_space.h
--- delaboratory-0.7/core/color_space.h 1970-01-01 00:00:00.000000000 +0000
+++ delaboratory-0.8/core/color_space.h 2012-06-08 22:38:01.000000000 +0000
@@ -0,0 +1,39 @@
+/*
+ delaboratory - color correction utility
+ Copyright (C) 2011 Jacek Poplawski
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef _DE_COLOR_SPACE_H
+#define _DE_COLOR_SPACE_H
+
+#define MAX_COLOR_SPACE_SIZE 4
+
+enum deColorSpace
+{
+ deColorSpaceInvalid,
+ deColorSpaceRGB,
+ deColorSpaceProPhoto,
+ deColorSpaceBW,
+ deColorSpaceLAB,
+ deColorSpaceCMY,
+ deColorSpaceCMYK,
+ deColorSpaceHSV,
+ deColorSpaceHSL,
+ deColorSpaceXYZ,
+ deColorSpaceLCH
+};
+
+#endif
diff -Nru delaboratory-0.7/core/conversion_cpu.cc delaboratory-0.8/core/conversion_cpu.cc
--- delaboratory-0.7/core/conversion_cpu.cc 1970-01-01 00:00:00.000000000 +0000
+++ delaboratory-0.8/core/conversion_cpu.cc 2012-07-15 13:03:42.000000000 +0000
@@ -0,0 +1,1933 @@
+/*
+ delaboratory - color correction utility
+ Copyright (C) 2011 Jacek Poplawski
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include "conversion_processor.h"
+
+#include "image.h"
+#include "channel_manager.h"
+#include "color_space_utils.h"
+
+#include "logger.h"
+
+#include "power.h"
+
+#include "str.h"
+
+#include
+
+static const deValue Xn = 0.951;
+static const deValue Yn = 1.0;
+static const deValue Zn = 1.089;
+static const deValue c6_29 = 6.0 / 29.0;
+static const deValue c29_6 = 29.0 / 6.0;
+static const deValue c6_29_2 = c6_29 * c6_29;
+static const deValue c6_29_3 = c6_29 * c6_29 * c6_29;
+static const deValue c29_6_2 = c29_6 * c29_6;
+static const deValue c4_29 = 4.0 / 29.0;
+
+deConversionCPU::deConversionCPU(int size)
+{
+ input = new deValue [size];
+ output = new deValue [size];
+ registers = new deValue [CPU_REGISTERS];
+
+ registers[CPU_REGISTER_OVERFLOW] = 0;
+ registers[CPU_REGISTER_CMYK_KEY_SUB] = 0.25;
+ registers[CPU_REGISTER_CMYK_KEY_MAX] = 0.8;
+ registers[CPU_REGISTER_CMYK_MIN_SUM] = 1.0;
+ registers[CPU_REGISTER_BW_MIXER_R] = 0.3;
+ registers[CPU_REGISTER_BW_MIXER_G] = 0.6;
+ registers[CPU_REGISTER_BW_MIXER_B] = 0.1;
+ registers[CPU_REGISTER_CONTRAST] = 1.0;
+ registers[CPU_REGISTER_SATURATION] = 1.0;
+ registers[CPU_REGISTER_PSEUDOGREY] = 0.0;
+}
+
+deConversionCPU::~deConversionCPU()
+{
+ delete [] input;
+ delete [] output;
+ delete [] registers;
+}
+
+void deConversionCPU::switchIO()
+{
+ deValue* a = input;
+ input = output;
+ output = a;
+}
+
+void deConversionCPU::incOverflow()
+{
+ registers[CPU_REGISTER_OVERFLOW] ++;
+}
+
+bool deConversionCPU::renderImage1(const deImage& image, deConversionCPU::deFunction f, unsigned char* data)
+{
+ int n = image.getChannelSize().getN();
+
+ const deValue* s0 = image.startRead(0);
+ if (!s0)
+ {
+ logError("NULL in renderImage1");
+ image.finishRead(0);
+ return false;
+ }
+
+ int i;
+ int pos = 0;
+
+ for (i = 0; i < n; i++)
+ {
+ input[0] = s0[i];
+
+ f(*this);
+
+ unsigned char r = 255 * output[0];
+ data[pos] = r;
+ pos++;
+ unsigned char g = 255 * output[1];
+ data[pos] = g;
+ pos++;
+ unsigned char b = 255 * output[2];
+ data[pos] = b;
+ pos++;
+ }
+
+ image.finishRead(0);
+
+ return true;
+}
+
+bool deConversionCPU::renderImage3(const deImage& image, deConversionCPU::deFunction f, unsigned char* data)
+{
+ int n = image.getChannelSize().getN();
+
+ const deValue* s0 = image.startRead(0);
+ const deValue* s1 = image.startRead(1);
+ const deValue* s2 = image.startRead(2);
+ if ((!s0) || (!s1) || (!s2))
+ {
+ logError("NULL in renderImage3");
+ image.finishRead(0);
+ image.finishRead(1);
+ image.finishRead(2);
+ return false;
+ }
+
+ int i;
+ int pos = 0;
+
+ for (i = 0; i < n; i++)
+ {
+ input[0] = s0[i];
+ input[1] = s1[i];
+ input[2] = s2[i];
+
+ f(*this);
+
+ unsigned char r = 255 * output[0];
+ data[pos] = r;
+ pos++;
+ unsigned char g = 255 * output[1];
+ data[pos] = g;
+ pos++;
+ unsigned char b = 255 * output[2];
+ data[pos] = b;
+ pos++;
+ }
+
+ image.finishRead(0);
+ image.finishRead(1);
+ image.finishRead(2);
+
+ return true;
+}
+
+bool deConversionCPU::renderImage4(const deImage& image, deConversionCPU::deFunction f, unsigned char* data)
+{
+ int n = image.getChannelSize().getN();
+
+ const deValue* s0 = image.startRead(0);
+ const deValue* s1 = image.startRead(1);
+ const deValue* s2 = image.startRead(2);
+ const deValue* s3 = image.startRead(3);
+
+ if ((!s0) || (!s1) || (!s2) || (!s3))
+ {
+ logError("NULL in renderImage4");
+ image.finishRead(0);
+ image.finishRead(1);
+ image.finishRead(2);
+ image.finishRead(3);
+ return false;
+ }
+
+ int i;
+ int pos = 0;
+
+ for (i = 0; i < n; i++)
+ {
+ input[0] = s0[i];
+ input[1] = s1[i];
+ input[2] = s2[i];
+ input[3] = s3[i];
+
+ f(*this);
+
+ unsigned char r = 255 * output[0];
+ data[pos] = r;
+ pos++;
+ unsigned char g = 255 * output[1];
+ data[pos] = g;
+ pos++;
+ unsigned char b = 255 * output[2];
+ data[pos] = b;
+ pos++;
+ }
+
+ image.finishRead(0);
+ image.finishRead(1);
+ image.finishRead(2);
+ image.finishRead(3);
+
+ return true;
+}
+
+void deConversionCPU::convertImage3x3(const deImage& sourceImage, deImage& image, deConversionCPU::deFunction f1, deConversionCPU::deFunction f2)
+{
+ int n = sourceImage.getChannelSize().getN();
+
+ const deValue* s0 = sourceImage.startRead(0);
+ const deValue* s1 = sourceImage.startRead(1);
+ const deValue* s2 = sourceImage.startRead(2);
+
+ deValue* d0 = image.startWrite(0);
+ deValue* d1 = image.startWrite(1);
+ deValue* d2 = image.startWrite(2);
+
+ bool ok;
+ if (s0 && s1 && s2 && d0 && d1 && d2)
+ {
+ ok = true;
+ }
+ else
+ {
+ logError("NULL channel in convertImage 3x3");
+ ok = false;
+ }
+ if (ok)
+ {
+ int i;
+
+ for (i = 0; i < n; i++)
+ {
+ input[0] = s0[i];
+ input[1] = s1[i];
+ input[2] = s2[i];
+
+ f1(*this);
+ f2(*this);
+
+ d0[i] = output[0];
+ d1[i] = output[1];
+ d2[i] = output[2];
+ }
+ }
+
+ sourceImage.finishRead(0);
+ sourceImage.finishRead(1);
+ sourceImage.finishRead(2);
+ image.finishWrite(0);
+ image.finishWrite(1);
+ image.finishWrite(2);
+}
+
+void deConversionCPU::convertImage3x4(const deImage& sourceImage, deImage& image, deConversionCPU::deFunction f1, deConversionCPU::deFunction f2)
+{
+ int n = sourceImage.getChannelSize().getN();
+
+ const deValue* s0 = sourceImage.startRead(0);
+ const deValue* s1 = sourceImage.startRead(1);
+ const deValue* s2 = sourceImage.startRead(2);
+
+ deValue* d0 = image.startWrite(0);
+ deValue* d1 = image.startWrite(1);
+ deValue* d2 = image.startWrite(2);
+ deValue* d3 = image.startWrite(3);
+
+ bool ok;
+ if (s0 && s1 && s2 && d0 && d1 && d2 && d3)
+ {
+ ok = true;
+ }
+ else
+ {
+ logError("NULL channel in convertImage 3x4");
+ ok = false;
+ }
+ if (ok)
+ {
+ int i;
+ for (i = 0; i < n; i++)
+ {
+ input[0] = s0[i];
+ input[1] = s1[i];
+ input[2] = s2[i];
+
+ f1(*this);
+ f2(*this);
+
+ d0[i] = output[0];
+ d1[i] = output[1];
+ d2[i] = output[2];
+ d3[i] = output[3];
+ }
+ }
+
+ sourceImage.finishRead(0);
+ sourceImage.finishRead(1);
+ sourceImage.finishRead(2);
+ image.finishWrite(0);
+ image.finishWrite(1);
+ image.finishWrite(2);
+ image.finishWrite(3);
+}
+
+void deConversionCPU::convertImage3x1(const deImage& sourceImage, deImage& image, deConversionCPU::deFunction f1, deConversionCPU::deFunction f2)
+{
+ int n = sourceImage.getChannelSize().getN();
+
+ const deValue* s0 = sourceImage.startRead(0);
+ const deValue* s1 = sourceImage.startRead(1);
+ const deValue* s2 = sourceImage.startRead(2);
+
+ deValue* d0 = image.startWrite(0);
+
+ bool ok;
+ if (s0 && s1 && s2 && d0)
+ {
+ ok = true;
+ }
+ else
+ {
+ logError("NULL channel in convertImage 3x1");
+ ok = false;
+ }
+ if (ok)
+ {
+ int i;
+
+ for (i = 0; i < n; i++)
+ {
+ input[0] = s0[i];
+ input[1] = s1[i];
+ input[2] = s2[i];
+
+ f1(*this);
+ f2(*this);
+
+ d0[i] = output[0];
+ }
+ }
+
+ sourceImage.finishRead(0);
+ sourceImage.finishRead(1);
+ sourceImage.finishRead(2);
+ image.finishWrite(0);
+}
+
+void deConversionCPU::convertImage4x1(const deImage& sourceImage, deImage& image, deConversionCPU::deFunction f1, deConversionCPU::deFunction f2)
+{
+ int n = sourceImage.getChannelSize().getN();
+
+ const deValue* s0 = sourceImage.startRead(0);
+ const deValue* s1 = sourceImage.startRead(1);
+ const deValue* s2 = sourceImage.startRead(2);
+ const deValue* s3 = sourceImage.startRead(3);
+
+ deValue* d0 = image.startWrite(0);
+
+ bool ok;
+ if (s0 && s1 && s2 && s3 && d0)
+ {
+ ok = true;
+ }
+ else
+ {
+ logError("NULL channel in convertImage 4x1");
+ ok = false;
+ }
+
+ if (ok)
+ {
+ int i;
+
+ for (i = 0; i < n; i++)
+ {
+ input[0] = s0[i];
+ input[1] = s1[i];
+ input[2] = s2[i];
+ input[3] = s3[i];
+
+ f1(*this);
+ f2(*this);
+
+ d0[i] = output[0];
+ }
+ }
+
+ sourceImage.finishRead(0);
+ sourceImage.finishRead(1);
+ sourceImage.finishRead(2);
+ sourceImage.finishRead(3);
+ image.finishWrite(0);
+}
+
+void deConversionCPU::convertImage4x3(const deImage& sourceImage, deImage& image, deConversionCPU::deFunction f1, deConversionCPU::deFunction f2)
+{
+ int n = sourceImage.getChannelSize().getN();
+
+ const deValue* s0 = sourceImage.startRead(0);
+ const deValue* s1 = sourceImage.startRead(1);
+ const deValue* s2 = sourceImage.startRead(2);
+ const deValue* s3 = sourceImage.startRead(3);
+
+ deValue* d0 = image.startWrite(0);
+ deValue* d1 = image.startWrite(1);
+ deValue* d2 = image.startWrite(2);
+
+ bool ok;
+ if (s0 && s1 && s2 && s3 && d0 && d1 && d2)
+ {
+ ok = true;
+ }
+ else
+ {
+ logError("NULL channel in convertImage 4x3");
+ ok = false;
+ }
+ if (ok)
+ {
+ int i;
+
+ for (i = 0; i < n; i++)
+ {
+ input[0] = s0[i];
+ input[1] = s1[i];
+ input[2] = s2[i];
+ input[3] = s3[i];
+
+ f1(*this);
+ f2(*this);
+
+ d0[i] = output[0];
+ d1[i] = output[1];
+ d2[i] = output[2];
+ }
+ }
+
+ sourceImage.finishRead(0);
+ sourceImage.finishRead(1);
+ sourceImage.finishRead(2);
+ sourceImage.finishRead(3);
+ image.finishWrite(0);
+ image.finishWrite(1);
+ image.finishWrite(2);
+}
+
+void deConversionCPU::convertImage1x3(const deImage& sourceImage, deImage& image, deConversionCPU::deFunction f1, deConversionCPU::deFunction f2)
+{
+ int n = sourceImage.getChannelSize().getN();
+
+ const deValue* s0 = sourceImage.startRead(0);
+
+ deValue* d0 = image.startWrite(0);
+ deValue* d1 = image.startWrite(1);
+ deValue* d2 = image.startWrite(2);
+
+ bool ok;
+ if (s0 && d0 && d1 && d2)
+ {
+ ok = true;
+ }
+ else
+ {
+ logError("NULL channel in convertImage 1x3");
+ ok = false;
+ }
+ if (ok)
+ {
+ int i;
+
+ for (i = 0; i < n; i++)
+ {
+ input[0] = s0[i];
+
+ f1(*this);
+ f2(*this);
+
+ d0[i] = output[0];
+ d1[i] = output[1];
+ d2[i] = output[2];
+ }
+ }
+
+ sourceImage.finishRead(0);
+ image.finishWrite(0);
+ image.finishWrite(1);
+ image.finishWrite(2);
+}
+
+void deConversionCPU::convertImage1x4(const deImage& sourceImage, deImage& image, deConversionCPU::deFunction f1, deConversionCPU::deFunction f2)
+{
+ int n = sourceImage.getChannelSize().getN();
+
+ const deValue* s0 = sourceImage.startRead(0);
+
+ deValue* d0 = image.startWrite(0);
+ deValue* d1 = image.startWrite(1);
+ deValue* d2 = image.startWrite(2);
+ deValue* d3 = image.startWrite(3);
+
+ bool ok;
+ if (s0 && d0 && d1 && d2 && d3)
+ {
+ ok = true;
+ }
+ else
+ {
+ logError("NULL channel in convertImage 1x4");
+ ok = false;
+ }
+ if (ok)
+ {
+ int i;
+
+ for (i = 0; i < n; i++)
+ {
+ input[0] = s0[i];
+
+ f1(*this);
+ f2(*this);
+
+ d0[i] = output[0];
+ d1[i] = output[1];
+ d2[i] = output[2];
+ d3[i] = output[3];
+ }
+ }
+
+ sourceImage.finishRead(0);
+ image.finishWrite(0);
+ image.finishWrite(1);
+ image.finishWrite(2);
+ image.finishWrite(3);
+}
+
+void empty(deConversionCPU& cpu)
+{
+}
+
+void rgb2cmy(deConversionCPU& cpu)
+{
+ cpu.output[0] = 1.0 - cpu.input[0];
+ cpu.output[1] = 1.0 - cpu.input[1];
+ cpu.output[2] = 1.0 - cpu.input[2];
+}
+
+void bw2rgb(deConversionCPU& cpu)
+{
+ deValue pg = cpu.registers[CPU_REGISTER_PSEUDOGREY] / 255.0;
+
+ deValue bw = cpu.input[0];
+
+ if (pg == 0)
+ {
+ cpu.output[0] = bw;
+ cpu.output[1] = bw;
+ cpu.output[2] = bw;
+ }
+ else
+ {
+ int bbw = (int) (255 * bw * 16);
+ int m = bbw % 16;
+
+ deValue r = 0;
+ deValue g = 0;
+ deValue b = 0;
+
+ if ((m >= 2) && (m <= 4))
+ {
+ b = 1;
+ }
+ if ((m >= 5) && (m <= 6))
+ {
+ r = 1;
+ }
+ if ((m >= 7) && (m <= 8))
+ {
+ r = 1;
+ b = 1;
+ }
+ if ((m >= 9) && (m <= 10))
+ {
+ g = 1;
+ }
+ if ((m >= 11) && (m <= 13))
+ {
+ g = 1;
+ b = 1;
+ }
+ if ((m >= 14) && (m <= 15))
+ {
+ g = 1;
+ r = 1;
+ }
+
+ r = bw + pg * r;
+ if (r > 1)
+ {
+ r = 1;
+ }
+ g = bw + pg * g;
+ if (g > 1)
+ {
+ g = 1;
+ }
+ b = bw + pg * b;
+ if (b > 1)
+ {
+ b = 1;
+ }
+ cpu.output[0] = r;
+ cpu.output[1] = g;
+ cpu.output[2] = b;
+ }
+}
+
+void rgb2bw(deConversionCPU& cpu)
+{
+ deValue r = cpu.input[0];
+ deValue g = cpu.input[1];
+ deValue b = cpu.input[2];
+
+ deValue mr = cpu.registers[CPU_REGISTER_BW_MIXER_R];
+ deValue mg = cpu.registers[CPU_REGISTER_BW_MIXER_G];
+ deValue mb = cpu.registers[CPU_REGISTER_BW_MIXER_B];
+
+ deValue bw = mr * r + mg * g + mb * b;
+
+ if (bw < 0)
+ {
+ bw = 0;
+ cpu.incOverflow();
+ }
+ else if (bw > 1)
+ {
+ bw = 1;
+ cpu.incOverflow();
+ }
+
+ cpu.output[0] = bw;
+}
+
+void cmy2rgb(deConversionCPU& cpu)
+{
+ cpu.output[0] = 1.0 - cpu.input[0];
+ cpu.output[1] = 1.0 - cpu.input[1];
+ cpu.output[2] = 1.0 - cpu.input[2];
+}
+
+void cmy2cmyk(deConversionCPU& cpu)
+{
+ deValue k;
+ deValue c = cpu.input[0];
+ deValue m = cpu.input[1];
+ deValue y = cpu.input[2];
+
+ if (c < m)
+ {
+ if (c < y)
+ {
+ k = c;
+ }
+ else
+ {
+ k = y;
+ }
+ }
+ else
+ {
+ if (m < y)
+ {
+ k = m;
+ }
+ else
+ {
+ k = y;
+ }
+ }
+
+ k = k - cpu.registers[CPU_REGISTER_CMYK_KEY_SUB];
+
+ if (k < 0.0)
+ {
+ k = 0.0;
+ }
+
+ deValue max = cpu.registers[CPU_REGISTER_CMYK_KEY_MAX];
+ if (k > max)
+ {
+ k = max;
+ }
+
+ if (c + m + y < cpu.registers[CPU_REGISTER_CMYK_MIN_SUM])
+ {
+ k = 0.0;
+ }
+
+ deValue kk = (1 - k);
+
+ cpu.output[0] = (c - k) / kk;
+ cpu.output[1] = (m - k) / kk;
+ cpu.output[2] = (y - k) / kk;
+ cpu.output[3] = k;
+}
+
+void cmyk2cmy(deConversionCPU& cpu)
+{
+ deValue k = cpu.input[3];
+ deValue kk = 1.0 - k;
+
+ deValue c = cpu.input[0] * kk + k;
+ deValue m = cpu.input[1] * kk + k;
+ deValue y = cpu.input[2] * kk + k;
+
+ cpu.output[0] = c;
+ cpu.output[1] = m;
+ cpu.output[2] = y;
+}
+
+void rgb2prophoto(deConversionCPU& cpu)
+{
+ /*
+ from dcraw
+
+ octave:1> x = [0.529317, 0.330092, 0.140588; 0.098368, 0.873465, 0.028169; 0.016879, 0.117663, 0.865457]
+ x =
+
+ 0.529317 0.330092 0.140588
+ 0.098368 0.873465 0.028169
+ 0.016879 0.117663 0.865457
+
+ */
+
+
+ deValue r = cpu.input[0];
+ deValue g = cpu.input[1];
+ deValue b = cpu.input[2];
+
+ cpu.output[0] = 0.529317 * r + 0.330092 * g + 0.140588 * b;
+ cpu.output[1] = 0.098368 * r + 0.873465 * g + 0.028169 * b;
+ cpu.output[2] = 0.016879 * r + 0.117663 * g + 0.865457 * b;
+
+}
+
+void prophoto2rgb(deConversionCPU& cpu)
+{
+
+ /*
+ invert matrix from dcraw
+
+ octave:2> inv(x)
+ ans =
+
+ 2.0341926 -0.7274198 -0.3067655
+ -0.2288108 1.2317292 -0.0029216
+ -0.0085649 -0.1532726 1.1618390
+
+ */
+
+ deValue pr = cpu.input[0];
+ deValue pg = cpu.input[1];
+ deValue pb = cpu.input[2];
+
+ deValue r = 2.0341926 * pr -0.7274198 * pg -0.3067655 * pb;
+ deValue g = -0.2288108 * pr + 1.2317292 * pg -0.0029216 * pb;
+ deValue b = -0.0085649 * pr -0.1532726 * pg + 1.1618390 * pb;
+
+ if (r < 0)
+ {
+ r = 0;
+ cpu.incOverflow();
+ }
+ else if (r > 1)
+ {
+ r = 1;
+ cpu.incOverflow();
+ }
+ if (g < 0)
+ {
+ g = 0;
+ cpu.incOverflow();
+ }
+ else if (g > 1)
+ {
+ g = 1;
+ cpu.incOverflow();
+ }
+ if (b < 0)
+ {
+ b = 0;
+ cpu.incOverflow();
+ }
+ else if (b > 1)
+ {
+ b = 1;
+ cpu.incOverflow();
+ }
+
+ cpu.output[0] = r;
+ cpu.output[1] = g;
+ cpu.output[2] = b;
+
+}
+
+void prophoto2xyz(deConversionCPU& cpu)
+{
+
+ /*
+
+ octave:7> z
+ z =
+
+ 2.0341926 -0.7274198 -0.3067655
+ -0.2288108 1.2317292 -0.0029216
+ -0.0085649 -0.1532726 1.1618390
+
+ octave:8> y
+ y =
+
+ 0.412400 0.357600 0.180500
+ 0.212600 0.715200 0.072200
+ 0.019300 0.119200 0.950500
+
+ octave:10> y * z
+ ans =
+
+ 0.7555323 0.1128127 0.0821571
+ 0.2682055 0.7152170 0.0165769
+ 0.0038447 -0.0129027 1.0980591
+
+ */
+
+ deValue pr = cpu.input[0];
+ deValue pg = cpu.input[1];
+ deValue pb = cpu.input[2];
+
+ cpu.output[0] = 0.7555323 * pr + 0.1128127* pg + 0.0821571* pb;
+ cpu.output[1] = 0.2682055 * pr + 0.7152170* pg + 0.0165769* pb;
+ cpu.output[2] = 0.0038447 * pr -0.0129027 * pg + 1.0980591* pb;
+
+}
+
+void rgb2xyz(deConversionCPU& cpu)
+{
+ deValue r = cpu.input[0];
+ deValue g = cpu.input[1];
+ deValue b = cpu.input[2];
+
+ cpu.output[0] = 0.4124 * r + 0.3576 * g + 0.1805 * b;
+ cpu.output[1] = 0.2126 * r + 0.7152 * g + 0.0722 * b;
+ cpu.output[2] = 0.0193 * r + 0.1192 * g + 0.9505 * b;
+
+}
+
+void xyz2rgb(deConversionCPU& cpu)
+{
+ deValue x = cpu.input[0];
+ deValue y = cpu.input[1];
+ deValue z = cpu.input[2];
+
+ deValue r = 3.2410 * x - 1.5374 * y - 0.4986 * z;
+ deValue g = -0.9692 * x + 1.8760 * y + 0.0416 * z;
+ deValue b = 0.0556 * x - 0.2040 * y + 1.0570 * z;
+
+ if (r < 0)
+ {
+ r = 0;
+ cpu.incOverflow();
+ }
+ else if (r > 1)
+ {
+ r = 1;
+ cpu.incOverflow();
+ }
+ if (g < 0)
+ {
+ g = 0;
+ cpu.incOverflow();
+ }
+ else if (g > 1)
+ {
+ g = 1;
+ cpu.incOverflow();
+ }
+ if (b < 0)
+ {
+ b = 0;
+ cpu.incOverflow();
+ }
+ else if (b > 1)
+ {
+ b = 1;
+ cpu.incOverflow();
+ }
+
+ cpu.output[0] = r;
+ cpu.output[1] = g;
+ cpu.output[2] = b;
+}
+
+void xyz2lab(deConversionCPU& cpu)
+{
+ static dePower power(1.0 / 3.0, 2);
+
+ deValue xx = cpu.input[0] / Xn;
+ deValue yy = cpu.input[1] / Yn;
+ deValue zz = cpu.input[2] / Zn;
+
+ deValue fx;
+ deValue fy;
+ deValue fz;
+
+ if (xx > c6_29_3)
+ {
+ fx = power.get(xx);
+ }
+ else
+ {
+ fx = 1.0 / 3.0 * c29_6_2 * xx + c4_29;
+ }
+
+ if (yy > c6_29_3)
+ {
+ fy = power.get(yy);
+ }
+ else
+ {
+ fy = 1.0 / 3.0 * c29_6_2 * yy + c4_29;
+ }
+
+ if (zz > c6_29_3)
+ {
+ fz = power.get(zz);
+ }
+ else
+ {
+ fz = 1.0 / 3.0 * c29_6_2 * zz + c4_29;
+ }
+
+ deValue l = 116.0 * fy - 16.0;
+ deValue a = 500.0 * (fx - fy);
+ deValue b = 200.0 * (fy - fz);
+
+ l /= 100.0;
+ a += 100.0;
+ b += 100.0;
+ a /= 200.0;
+ b /= 200.0;
+
+ if (l < 0)
+ {
+ l = 0;
+ cpu.incOverflow();
+ }
+ else if (l > 1)
+ {
+ l = 1;
+ cpu.incOverflow();
+ }
+
+ if (a < 0)
+ {
+ a = 0;
+ cpu.incOverflow();
+ }
+ else if (a > 1)
+ {
+ a = 1;
+ cpu.incOverflow();
+ }
+
+ if (b < 0)
+ {
+ b = 0;
+ cpu.incOverflow();
+ }
+ else if (b > 1)
+ {
+ b = 1;
+ cpu.incOverflow();
+ }
+
+
+ cpu.output[0] = l;
+ cpu.output[1] = a;
+ cpu.output[2] = b;
+
+}
+
+void lab2lch(deConversionCPU& cpu)
+{
+ deValue a = cpu.input[1];
+ deValue b = cpu.input[2];
+
+ a = ( a - 0.5) * 200.0;
+ b = ( b - 0.5) * 200.0;
+
+ deValue _c = sqrt(a * a + b * b);
+ deValue _h = atan2(b, a);
+
+ _c = _c / 100.0;
+ _h = (_h / ( 2 * M_PI ));
+
+ if (_h < 0)
+ {
+ _h += 1;
+ }
+
+ if ( _c > 1)
+ {
+ _c = 1;
+ cpu.incOverflow();
+ }
+ if ( _c < 0)
+ {
+ _c = 0;
+ cpu.incOverflow();
+ }
+
+ cpu.output[0] = cpu.input[0];
+
+ cpu.output[1] = _c;
+ cpu.output[2] = _h;
+}
+
+void lch2lab(deConversionCPU& cpu)
+{
+ deValue c = cpu.input[1];
+ deValue h = cpu.input[2];
+
+ c = c * 100.0;
+ h = h * (2 * M_PI);
+
+ deValue a = c * cos(h);
+ deValue b = c * sin(h);
+
+ a = a / 200.0 + 0.5;
+ b = b / 200.0 + 0.5;
+
+ cpu.output[0] = cpu.input[0];
+
+ cpu.output[1] = a;
+ cpu.output[2] = b;
+}
+
+void prophoto2lab(deConversionCPU& cpu)
+{
+ prophoto2xyz(cpu);
+ cpu.switchIO();
+ xyz2lab(cpu);
+}
+
+void rgb2cmyk(deConversionCPU& cpu)
+{
+ rgb2cmy(cpu);
+ cpu.switchIO();
+ cmy2cmyk(cpu);
+}
+
+void prophoto2cmyk(deConversionCPU& cpu)
+{
+ prophoto2rgb(cpu);
+ cpu.switchIO();
+ rgb2cmyk(cpu);
+}
+
+
+void noConversion(deConversionCPU& cpu)
+{
+ cpu.switchIO();
+}
+
+void rgb2lab(deConversionCPU& cpu)
+{
+ rgb2xyz(cpu);
+ cpu.switchIO();
+ xyz2lab(cpu);
+}
+
+void rgb2lch(deConversionCPU& cpu)
+{
+ rgb2lab(cpu);
+ cpu.switchIO();
+ lab2lch(cpu);
+}
+
+void prophoto2lch(deConversionCPU& cpu)
+{
+ prophoto2lab(cpu);
+ cpu.switchIO();
+ lab2lch(cpu);
+}
+
+void cmyk2rgb(deConversionCPU& cpu)
+{
+ cmyk2cmy(cpu);
+ cpu.switchIO();
+ cmy2rgb(cpu);
+}
+
+void cmyk2lab(deConversionCPU& cpu)
+{
+ cmyk2rgb(cpu);
+ cpu.switchIO();
+ rgb2lab(cpu);
+}
+
+void lab2xyz(deConversionCPU& cpu)
+{
+ deValue l = cpu.input[0];
+ deValue a = cpu.input[1];
+ deValue b = cpu.input[2];
+
+ l *= 100.0;
+ a *= 200.0;
+ b *= 200.0;
+ a -= 100.0;
+ b -= 100.0;
+
+ deValue ll = (l + 16.0) / 116.0;
+ deValue ll_aa = ll + a / 500.0;
+ deValue ll_bb = ll - b / 200.0;
+
+ deValue ffx;
+ deValue ffy;
+ deValue ffz;
+
+ if (ll > c6_29)
+ {
+ ffy = ll * ll * ll;
+ }
+ else
+ {
+ ffy = 3.0 * c6_29_2 * (ll - c4_29);
+ }
+
+ if (ll_aa > c6_29)
+ {
+ ffx = ll_aa * ll_aa * ll_aa;
+ }
+ else
+ {
+ ffx = 3.0 * c6_29_2 * (ll_aa - c4_29);
+ }
+
+ if (ll_bb > c6_29)
+ {
+ ffz = ll_bb * ll_bb * ll_bb;
+ }
+ else
+ {
+ ffz = 3.0 * c6_29_2 * (ll_bb - c4_29);
+ }
+
+ cpu.output[0] = Xn * ffx;
+ cpu.output[1] = Yn * ffy;
+ cpu.output[2] = Zn * ffz;
+}
+
+void xyz2prophoto(deConversionCPU& cpu)
+{
+ /*
+
+ x = [0.7555323, 0.1128127, 0.0821571; 0.2682055, 0.7152170, 0.0165769; 0.0038447, -0.0129027, 1.0980591]
+
+ octave:2> inv(x)
+ ans =
+
+ 1.403314 -0.223181 -0.101627
+ -0.525984 1.481448 0.016990
+ -0.011094 0.018189 0.911253
+
+ */
+
+ deValue x = cpu.input[0];
+ deValue y = cpu.input[1];
+ deValue z = cpu.input[2];
+
+ cpu.output[0] = 1.403314* x -0.223181* y -0.101627* z;
+ cpu.output[1] = -0.525984* x + 1.481448* y + 0.016990* z;
+ cpu.output[2] = -0.011094* x + 0.018189* y + 0.911253* z;
+
+}
+
+
+void lab2prophoto(deConversionCPU& cpu)
+{
+ lab2xyz(cpu);
+ cpu.switchIO();
+ xyz2prophoto(cpu);
+}
+
+void lch2prophoto(deConversionCPU& cpu)
+{
+ lch2lab(cpu);
+ cpu.switchIO();
+ lab2prophoto(cpu);
+}
+
+
+void lab2rgb(deConversionCPU& cpu)
+{
+ lab2xyz(cpu);
+ cpu.switchIO();
+ xyz2rgb(cpu);
+}
+
+void lab2bw(deConversionCPU& cpu)
+{
+ lab2rgb(cpu);
+ cpu.switchIO();
+ rgb2bw(cpu);
+}
+
+void cmyk2bw(deConversionCPU& cpu)
+{
+ cmyk2rgb(cpu);
+ cpu.switchIO();
+ rgb2bw(cpu);
+}
+
+void bw2cmyk(deConversionCPU& cpu)
+{
+ bw2rgb(cpu);
+ cpu.switchIO();
+ rgb2cmyk(cpu);
+}
+
+void bw2lab(deConversionCPU& cpu)
+{
+ bw2rgb(cpu);
+ cpu.switchIO();
+ rgb2lab(cpu);
+}
+
+void bw2lch(deConversionCPU& cpu)
+{
+ bw2lab(cpu);
+ cpu.switchIO();
+ lab2lch(cpu);
+}
+
+void lch2bw(deConversionCPU& cpu)
+{
+ lch2lab(cpu);
+ cpu.switchIO();
+ lab2bw(cpu);
+}
+
+void lab2cmyk(deConversionCPU& cpu)
+{
+ lab2rgb(cpu);
+ cpu.switchIO();
+ rgb2cmy(cpu);
+ cpu.switchIO();
+ cmy2cmyk(cpu);
+}
+
+void lch2rgb(deConversionCPU& cpu)
+{
+ lch2lab(cpu);
+ cpu.switchIO();
+ lab2rgb(cpu);
+}
+
+void lch2cmyk(deConversionCPU& cpu)
+{
+ lch2rgb(cpu);
+ cpu.switchIO();
+ rgb2cmyk(cpu);
+}
+
+void cmyk2lch(deConversionCPU& cpu)
+{
+ cmyk2rgb(cpu);
+ cpu.switchIO();
+ rgb2lch(cpu);
+}
+
+deValue min3(deValue a, deValue b, deValue c)
+{
+ if (a < b)
+ {
+ if (a < c)
+ {
+ return a;
+ }
+ else
+ {
+ return c;
+ }
+ }
+ else
+ {
+ if (b < c)
+ {
+ return b;
+ }
+ else
+ {
+ return c;
+ }
+ }
+}
+
+deValue max3(deValue a, deValue b, deValue c)
+{
+ if (a > b)
+ {
+ if (a > c)
+ {
+ return a;
+ }
+ else
+ {
+ return c;
+ }
+ }
+ else
+ {
+ if (b > c)
+ {
+ return b;
+ }
+ else
+ {
+ return c;
+ }
+ }
+}
+
+void rgb2hsl(deConversionCPU& cpu)
+{
+ deValue r = cpu.input[0];
+ deValue g = cpu.input[1];
+ deValue b = cpu.input[2];
+
+ deValue minVal = min3( r, g, b );
+ deValue maxVal = max3( r, g, b );
+ deValue delta = maxVal - minVal;
+ deValue sum = minVal + maxVal;
+
+ deValue l = sum / 2.0;
+ deValue h;
+ deValue s;
+
+ if (delta == 0)
+ {
+ h = 0;
+ s = 0;
+ }
+ else
+ {
+ if ( l < 0.5 )
+ {
+ s = delta / sum;
+ }
+ else
+ {
+ s = delta / ( 2.0 - sum );
+ }
+
+ deValue deltaR = ( ( ( maxVal - r ) / 6 ) + ( delta / 2 ) ) / delta;
+ deValue deltaG = ( ( ( maxVal - g ) / 6 ) + ( delta / 2 ) ) / delta;
+ deValue deltaB = ( ( ( maxVal - b ) / 6 ) + ( delta / 2 ) ) / delta;
+
+ if ( r == maxVal )
+ {
+ h = deltaB - deltaG;
+ }
+ else if ( g == maxVal )
+ {
+ h = ( 1.0 / 3.0 ) + deltaR - deltaB;
+ }
+ else if ( b == maxVal )
+ {
+ h = ( 2.0 / 3.0 ) + deltaG - deltaR;
+ }
+
+ if ( h < 0 )
+ h += 1;
+ if ( h > 1 )
+ h -= 1;
+ }
+ cpu.output[0] = h;
+ cpu.output[1] = s;
+ cpu.output[2] = l;
+}
+
+deValue min(deValue a, deValue b, deValue c)
+{
+ if (a < b)
+ {
+ if (a < c)
+ {
+ return a;
+ }
+ else
+ {
+ return c;
+ }
+ }
+ else
+ {
+ if (b < c)
+ {
+ return b;
+ }
+ else
+ {
+ return c;
+ }
+ }
+}
+
+deValue max(deValue a, deValue b, deValue c)
+{
+ if (a > b)
+ {
+ if (a > c)
+ {
+ return a;
+ }
+ else
+ {
+ return c;
+ }
+ }
+ else
+ {
+ if (b > c)
+ {
+ return b;
+ }
+ else
+ {
+ return c;
+ }
+ }
+}
+
+deValue hue2rgb( deValue v1, deValue v2, deValue vH )
+{
+ if ( vH < 0 )
+ vH += 1;
+ if ( vH > 1 )
+ vH -= 1;
+ if ( ( 6.0 * vH ) < 1.0 )
+ return ( v1 + ( v2 - v1 ) * 6.0 * vH );
+ if ( ( 2.0 * vH ) < 1.0 )
+ return ( v2 );
+ if ( ( 3.0 * vH ) < 2.0 )
+ return ( v1 + ( v2 - v1 ) * ( ( 2.0 / 3.0 ) - vH ) * 6.0 );
+ return ( v1 );
+}
+
+void hsl2rgb(deConversionCPU& cpu)
+{
+ deValue h = cpu.input[0];
+ deValue s = cpu.input[1];
+ deValue l = cpu.input[2];
+
+ deValue r = 0.0;
+ deValue g = 0.0;
+ deValue b = 0.0;
+
+ if ( s == 0 )
+ {
+ r = l;
+ g = l;
+ b = l;
+ }
+ else
+ {
+ deValue v1;
+ deValue v2;
+
+ if ( l < 0.5 )
+ {
+ v2 = l * ( 1 + s );
+ }
+ else
+ {
+ v2 = ( l + s ) - ( s * l );
+ }
+
+ v1 = 2.0 * l - v2;
+
+ r = hue2rgb( v1, v2, h + ( 1.0 / 3.0 ) );
+ g = hue2rgb( v1, v2, h );
+ b = hue2rgb( v1, v2, h - ( 1.0 / 3.0 ) );
+ }
+
+ cpu.output[0] = r;
+ cpu.output[1] = g;
+ cpu.output[2] = b;
+}
+
+void rgb2hsv(deConversionCPU& cpu)
+{
+ deValue r = cpu.input[0];
+ deValue g = cpu.input[1];
+ deValue b = cpu.input[2];
+
+ deValue h = 0.0;
+ deValue s = 0.0;
+ deValue v = max( r, g, b );
+
+ deValue minVal = min( r, g, b );
+ deValue delta = v - minVal;
+
+ if (delta == 0)
+ {
+ h = 0;
+ s = 0;
+ }
+ else
+ {
+ s = delta / v;
+
+ deValue deltaR = ( ( ( v - r ) / 6.0 ) + ( delta / 2.0 ) ) / delta;
+ deValue deltaG = ( ( ( v - g ) / 6.0 ) + ( delta / 2.0 ) ) / delta;
+ deValue deltaB = ( ( ( v - b ) / 6.0 ) + ( delta / 2.0 ) ) / delta;
+
+ if ( r == v )
+ {
+ h = deltaB - deltaG;
+ }
+ else if ( g == v )
+ {
+ h = ( 1.0 / 3.0 ) + deltaR - deltaB;
+ }
+ else if ( b == v )
+ {
+ h = ( 2.0 / 3.0 ) + deltaG - deltaR;
+ }
+
+ if ( h < 0 )
+ h += 1.0;
+ if ( h > 1 )
+ h -= 1.0;
+ }
+
+ cpu.output[0] = h;
+ cpu.output[1] = s;
+ cpu.output[2] = v;
+}
+
+void prophoto2hsv(deConversionCPU& cpu)
+{
+ prophoto2rgb(cpu);
+ cpu.switchIO();
+ rgb2hsv(cpu);
+}
+
+void prophoto2hsl(deConversionCPU& cpu)
+{
+ prophoto2rgb(cpu);
+ cpu.switchIO();
+ rgb2hsl(cpu);
+}
+
+void lab2hsv(deConversionCPU& cpu)
+{
+ lab2rgb(cpu);
+ cpu.switchIO();
+ rgb2hsv(cpu);
+}
+
+void lch2hsv(deConversionCPU& cpu)
+{
+ lch2lab(cpu);
+ cpu.switchIO();
+ lab2hsv(cpu);
+}
+
+void bw2hsv(deConversionCPU& cpu)
+{
+ bw2rgb(cpu);
+ cpu.switchIO();
+ rgb2hsv(cpu);
+}
+
+void lab2hsl(deConversionCPU& cpu)
+{
+ lab2rgb(cpu);
+ cpu.switchIO();
+ rgb2hsl(cpu);
+}
+
+void lch2hsl(deConversionCPU& cpu)
+{
+ lch2lab(cpu);
+ cpu.switchIO();
+ lab2hsl(cpu);
+}
+
+void bw2hsl(deConversionCPU& cpu)
+{
+ bw2rgb(cpu);
+ cpu.switchIO();
+ rgb2hsl(cpu);
+}
+
+
+void hsv2rgb(deConversionCPU& cpu)
+{
+ deValue h = cpu.input[0];
+ deValue s = cpu.input[1];
+ deValue v = cpu.input[2];
+
+ deValue r = 0.0;
+ deValue g = 0.0;
+ deValue b = 0.0;
+
+ if ( s == 0 )
+ {
+ r = v;
+ g = v;
+ b = v;
+ }
+ else
+ {
+ deValue var_h = h * 6.0;
+
+ if ( var_h == 6.0 )
+ {
+ var_h = 0;
+ }
+
+ deValue var_i = int( var_h);
+ deValue var_1 = v * ( 1.0 - s );
+ deValue var_2 = v * ( 1.0 - s * ( var_h - var_i ) );
+ deValue var_3 = v * ( 1.0 - s * ( 1.0 - ( var_h - var_i ) ) );
+
+ if ( var_i == 0 )
+ {
+ r = v;
+ g = var_3;
+ b = var_1;
+ }
+ else if ( var_i == 1 )
+ {
+ r = var_2;
+ g = v;
+ b = var_1;
+ }
+ else if ( var_i == 2 )
+ {
+ r = var_1;
+ g = v;
+ b = var_3;
+ }
+ else if ( var_i == 3 )
+ {
+ r = var_1;
+ g = var_2;
+ b = v;
+ }
+ else if ( var_i == 4 )
+ {
+ r = var_3;
+ g = var_1;
+ b = v;
+ }
+ else
+ {
+ r = v;
+ g = var_1;
+ b = var_2;
+ }
+ }
+
+ cpu.output[0] = r;
+ cpu.output[1] = g;
+ cpu.output[2] = b;
+}
+
+void hsv2cmyk(deConversionCPU& cpu)
+{
+ hsv2rgb(cpu);
+ cpu.switchIO();
+ rgb2cmyk(cpu);
+}
+
+void cmyk2hsv(deConversionCPU& cpu)
+{
+ cmyk2rgb(cpu);
+ cpu.switchIO();
+ rgb2hsv(cpu);
+}
+
+void cmyk2hsl(deConversionCPU& cpu)
+{
+ cmyk2rgb(cpu);
+ cpu.switchIO();
+ rgb2hsl(cpu);
+}
+
+void hsv2lab(deConversionCPU& cpu)
+{
+ hsv2rgb(cpu);
+ cpu.switchIO();
+ rgb2lab(cpu);
+}
+
+void hsv2bw(deConversionCPU& cpu)
+{
+ hsv2rgb(cpu);
+ cpu.switchIO();
+ rgb2bw(cpu);
+}
+
+void hsv2lch(deConversionCPU& cpu)
+{
+ hsv2rgb(cpu);
+ cpu.switchIO();
+ rgb2lch(cpu);
+}
+
+
+deConversionCPU::deFunction getConversion(deColorSpace sourceColorSpace, deColorSpace targetColorSpace)
+{
+ if (sourceColorSpace == targetColorSpace)
+ {
+ return noConversion;
+ }
+
+ if ((sourceColorSpace == deColorSpaceProPhoto) && (targetColorSpace == deColorSpaceRGB))
+ {
+ return prophoto2rgb;
+ }
+ if ((targetColorSpace == deColorSpaceProPhoto) && (sourceColorSpace == deColorSpaceRGB))
+ {
+ return rgb2prophoto;
+ }
+ if ((sourceColorSpace == deColorSpaceProPhoto) && (targetColorSpace == deColorSpaceLAB))
+ {
+ return prophoto2lab;
+ }
+ if ((targetColorSpace == deColorSpaceProPhoto) && (sourceColorSpace == deColorSpaceLAB))
+ {
+ return lab2prophoto;
+ }
+ if ((sourceColorSpace == deColorSpaceProPhoto) && (targetColorSpace == deColorSpaceLCH))
+ {
+ return prophoto2lch;
+ }
+ if ((targetColorSpace == deColorSpaceProPhoto) && (sourceColorSpace == deColorSpaceLCH))
+ {
+ return lch2prophoto;
+ }
+ if ((sourceColorSpace == deColorSpaceRGB) && (targetColorSpace == deColorSpaceLAB))
+ {
+ return rgb2lab;
+ }
+ if ((sourceColorSpace == deColorSpaceRGB) && (targetColorSpace == deColorSpaceHSL))
+ {
+ return rgb2hsl;
+ }
+
+ if ((sourceColorSpace == deColorSpaceRGB) && (targetColorSpace == deColorSpaceHSV))
+ {
+ return rgb2hsv;
+ }
+ if ((sourceColorSpace == deColorSpaceCMYK) && (targetColorSpace == deColorSpaceHSV))
+ {
+ return cmyk2hsv;
+ }
+ if ((sourceColorSpace == deColorSpaceProPhoto) && (targetColorSpace == deColorSpaceHSV))
+ {
+ return prophoto2hsv;
+ }
+ if ((sourceColorSpace == deColorSpaceLCH) && (targetColorSpace == deColorSpaceHSV))
+ {
+ return lch2hsv;
+ }
+ if ((sourceColorSpace == deColorSpaceLAB) && (targetColorSpace == deColorSpaceHSV))
+ {
+ return lab2hsv;
+ }
+ if ((targetColorSpace == deColorSpaceHSV) && (sourceColorSpace == deColorSpaceBW))
+ {
+ return bw2hsv;
+ }
+
+ if ((sourceColorSpace == deColorSpaceRGB) && (targetColorSpace == deColorSpaceHSL))
+ {
+ return rgb2hsl;
+ }
+ if ((sourceColorSpace == deColorSpaceCMYK) && (targetColorSpace == deColorSpaceHSL))
+ {
+ return cmyk2hsl;
+ }
+ if ((sourceColorSpace == deColorSpaceProPhoto) && (targetColorSpace == deColorSpaceHSL))
+ {
+ return prophoto2hsl;
+ }
+ if ((sourceColorSpace == deColorSpaceLCH) && (targetColorSpace == deColorSpaceHSL))
+ {
+ return lch2hsl;
+ }
+ if ((sourceColorSpace == deColorSpaceLAB) && (targetColorSpace == deColorSpaceHSL))
+ {
+ return lab2hsl;
+ }
+ if ((targetColorSpace == deColorSpaceHSL) && (sourceColorSpace == deColorSpaceBW))
+ {
+ return bw2hsl;
+ }
+
+ if ((sourceColorSpace == deColorSpaceHSL) && (targetColorSpace == deColorSpaceRGB))
+ {
+ return hsl2rgb;
+ }
+ if ((sourceColorSpace == deColorSpaceHSV) && (targetColorSpace == deColorSpaceRGB))
+ {
+ return hsv2rgb;
+ }
+ if ((sourceColorSpace == deColorSpaceHSV) && (targetColorSpace == deColorSpaceLAB))
+ {
+ return hsv2lab;
+ }
+ if ((sourceColorSpace == deColorSpaceHSV) && (targetColorSpace == deColorSpaceCMYK))
+ {
+ return hsv2cmyk;
+ }
+ if ((sourceColorSpace == deColorSpaceHSV) && (targetColorSpace == deColorSpaceBW))
+ {
+ return hsv2bw;
+ }
+ if ((sourceColorSpace == deColorSpaceHSV) && (targetColorSpace == deColorSpaceLCH))
+ {
+ return hsv2lch;
+ }
+ if ((sourceColorSpace == deColorSpaceRGB) && (targetColorSpace == deColorSpaceLCH))
+ {
+ return rgb2lch;
+ }
+ if ((sourceColorSpace == deColorSpaceLCH) && (targetColorSpace == deColorSpaceRGB))
+ {
+ return lch2rgb;
+ }
+ if ((sourceColorSpace == deColorSpaceLCH) && (targetColorSpace == deColorSpaceCMYK))
+ {
+ return lch2cmyk;
+ }
+ if ((targetColorSpace == deColorSpaceLCH) && (sourceColorSpace == deColorSpaceCMYK))
+ {
+ return cmyk2lch;
+ }
+ if ((sourceColorSpace == deColorSpaceLAB) && (targetColorSpace == deColorSpaceRGB))
+ {
+ return lab2rgb;
+ }
+ if ((sourceColorSpace == deColorSpaceLAB) && (targetColorSpace == deColorSpaceLCH))
+ {
+ return lab2lch;
+ }
+ if ((sourceColorSpace == deColorSpaceLCH) && (targetColorSpace == deColorSpaceLAB))
+ {
+ return lch2lab;
+ }
+ if ((sourceColorSpace == deColorSpaceProPhoto) && (targetColorSpace == deColorSpaceCMYK))
+ {
+ return prophoto2cmyk;
+ }
+ if ((sourceColorSpace == deColorSpaceRGB) && (targetColorSpace == deColorSpaceCMYK))
+ {
+ return rgb2cmyk;
+ }
+ if ((sourceColorSpace == deColorSpaceCMYK) && (targetColorSpace == deColorSpaceRGB))
+ {
+ return cmyk2rgb;
+ }
+ if ((sourceColorSpace == deColorSpaceRGB) && (targetColorSpace == deColorSpaceBW))
+ {
+ return rgb2bw;
+ }
+ if ((sourceColorSpace == deColorSpaceProPhoto) && (targetColorSpace == deColorSpaceBW))
+ {
+ return rgb2bw;
+ }
+ if ((sourceColorSpace == deColorSpaceLAB) && (targetColorSpace == deColorSpaceBW))
+ {
+ return lab2bw;
+ }
+ if ((sourceColorSpace == deColorSpaceLCH) && (targetColorSpace == deColorSpaceBW))
+ {
+ return lch2bw;
+ }
+ if ((sourceColorSpace == deColorSpaceCMYK) && (targetColorSpace == deColorSpaceBW))
+ {
+ return cmyk2bw;
+ }
+ if ((sourceColorSpace == deColorSpaceBW) && (targetColorSpace == deColorSpaceRGB))
+ {
+ return bw2rgb;
+ }
+ if ((sourceColorSpace == deColorSpaceCMYK) && (targetColorSpace == deColorSpaceLAB))
+ {
+ return cmyk2lab;
+ }
+ if ((sourceColorSpace == deColorSpaceLAB) && (targetColorSpace == deColorSpaceCMYK))
+ {
+ return lab2cmyk;
+ }
+ if ((targetColorSpace == deColorSpaceLAB) && (sourceColorSpace == deColorSpaceBW))
+ {
+ return bw2lab;
+ }
+ if ((targetColorSpace == deColorSpaceLCH) && (sourceColorSpace == deColorSpaceBW))
+ {
+ return bw2lch;
+ }
+ if ((targetColorSpace == deColorSpaceCMYK) && (sourceColorSpace == deColorSpaceBW))
+ {
+ return bw2cmyk;
+ }
+
+ logError("no conversion for " + getColorSpaceName(sourceColorSpace) + " -> " + getColorSpaceName(targetColorSpace));
+ return NULL;
+
+}
+
+
diff -Nru delaboratory-0.7/core/conversion_cpu.h delaboratory-0.8/core/conversion_cpu.h
--- delaboratory-0.7/core/conversion_cpu.h 1970-01-01 00:00:00.000000000 +0000
+++ delaboratory-0.8/core/conversion_cpu.h 2012-06-23 07:19:49.000000000 +0000
@@ -0,0 +1,86 @@
+/*
+ delaboratory - color correction utility
+ Copyright (C) 2011 Jacek Poplawski
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef _DE_CONVERSION_CPU_H
+#define _DE_CONVERSION_CPU_H
+
+#include "value.h"
+class deImage;
+class deChannelManager;
+#include "color_space.h"
+
+#define CPU_REGISTER_OVERFLOW 0
+#define CPU_REGISTER_CMYK_KEY_SUB 1
+#define CPU_REGISTER_CMYK_KEY_MAX 2
+#define CPU_REGISTER_CMYK_MIN_SUM 3
+#define CPU_REGISTER_BW_MIXER_R 4
+#define CPU_REGISTER_BW_MIXER_G 5
+#define CPU_REGISTER_BW_MIXER_B 6
+#define CPU_REGISTER_CONTRAST 7
+#define CPU_REGISTER_SATURATION 8
+#define CPU_REGISTER_PSEUDOGREY 9
+
+#define CPU_REGISTERS 10
+
+class deConversionCPU
+{
+ private:
+ public:
+ typedef void (*deFunction)(deConversionCPU& cpu);
+
+ deValue* input;
+ deValue* output;
+ deValue* registers;
+
+ deConversionCPU(int size);
+ virtual ~deConversionCPU();
+
+ void switchIO();
+ void incOverflow();
+
+ void convertImage3x3(const deImage& sourceImage, deImage& image, deFunction f1, deFunction f2);
+ void convertImage3x4(const deImage& sourceImage, deImage& image, deFunction f1, deFunction f2);
+ void convertImage4x3(const deImage& sourceImage, deImage& image, deFunction f1, deFunction f2);
+ void convertImage3x1(const deImage& sourceImage, deImage& image, deFunction f1, deFunction f2);
+ void convertImage1x3(const deImage& sourceImage, deImage& image, deFunction f1, deFunction f2);
+ void convertImage4x1(const deImage& sourceImage, deImage& image, deFunction f1, deFunction f2);
+ void convertImage1x4(const deImage& sourceImage, deImage& image, deFunction f1, deFunction f2);
+
+ bool renderImage1(const deImage& image, deConversionCPU::deFunction f, unsigned char* data);
+ bool renderImage3(const deImage& image, deConversionCPU::deFunction f, unsigned char* data);
+ bool renderImage4(const deImage& image, deConversionCPU::deFunction f, unsigned char* data);
+
+};
+
+void rgb2cmy(deConversionCPU& cpu);
+void cmy2rgb(deConversionCPU& cpu);
+void cmy2cmyk(deConversionCPU& cpu);
+void cmyk2cmy(deConversionCPU& cpu);
+void rgb2prophoto(deConversionCPU& cpu);
+void prophoto2rgb(deConversionCPU& cpu);
+void empty(deConversionCPU& cpu);
+void rgb2lab(deConversionCPU& cpu);
+void lab2rgb(deConversionCPU& cpu);
+void prophoto2lab(deConversionCPU& cpu);
+void lab2prophoto(deConversionCPU& cpu);
+void cmyk2lab(deConversionCPU& cpu);
+void lab2cmyk(deConversionCPU& cpu);
+
+deConversionCPU::deFunction getConversion(deColorSpace sourceColorSpace, deColorSpace targetColorSpace);
+
+#endif
diff -Nru delaboratory-0.7/core/conversion_processor.cc delaboratory-0.8/core/conversion_processor.cc
--- delaboratory-0.7/core/conversion_processor.cc 1970-01-01 00:00:00.000000000 +0000
+++ delaboratory-0.8/core/conversion_processor.cc 2012-07-10 23:38:22.000000000 +0000
@@ -0,0 +1,256 @@
+/*
+ delaboratory - color correction utility
+ Copyright (C) 2011 Jacek Poplawski
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include "conversion_processor.h"
+
+#include "image.h"
+#include "channel_manager.h"
+#include "color_space_utils.h"
+#include "copy_channel.h"
+
+#include "logger.h"
+
+#include "power.h"
+
+#include "str.h"
+
+void copyImage(const deImage& sourceImage, deImage& image)
+{
+ int n = getColorSpaceSize(sourceImage.getColorSpace());
+ int i;
+
+ for (i = 0; i < n; i++)
+ {
+ const deValue* source = sourceImage.startRead(i);
+ deValue* destination = image.startWrite(i);
+ copyChannel(source, destination, sourceImage.getChannelSize().getN());
+ image.finishWrite(i);
+ sourceImage.finishRead(i);
+ }
+}
+
+void applyContrastRGB(deConversionCPU& cpu)
+{
+ deValue a = cpu.registers[CPU_REGISTER_CONTRAST];
+ deValue b = 0.5 - 0.5 * a;
+
+ cpu.input[0] = a * cpu.input[0] + b;
+ cpu.input[1] = a * cpu.input[1] + b;
+ cpu.input[2] = a * cpu.input[2] + b;
+}
+
+void applyContrastSaturationLAB(deConversionCPU& cpu)
+{
+ deValue a1 = cpu.registers[CPU_REGISTER_CONTRAST];
+ deValue b1 = 0.5 - 0.5 * a1;
+ deValue a2 = cpu.registers[CPU_REGISTER_SATURATION];
+ deValue b2 = 0.5 - 0.5 * a2;
+
+ cpu.input[0] = a1 * cpu.input[0] + b1;
+ cpu.input[1] = a2 * cpu.input[1] + b2;
+ cpu.input[2] = a2 * cpu.input[2] + b2;
+}
+
+void applyContrastSaturationLCH(deConversionCPU& cpu)
+{
+ deValue a1 = cpu.registers[CPU_REGISTER_CONTRAST];
+ deValue b1 = 0.5 - 0.5 * a1;
+ deValue a2 = cpu.registers[CPU_REGISTER_SATURATION];
+
+ cpu.input[0] = a1 * cpu.input[0] + b1;
+ cpu.input[1] = a2 * cpu.input[1];
+}
+
+
+
+deConversionProcessor::deConversionProcessor()
+{
+}
+
+deConversionProcessor::~deConversionProcessor()
+{
+}
+
+
+bool deConversionProcessor::convert(deColorSpace sourceColorSpace, deValue v1, deValue v2, deValue v3, deValue v4, deColorSpace targetColorSpace, deValue &r1, deValue& r2, deValue& r3, deValue& r4)
+{
+ deConversionCPU cpu(4);
+ deConversionCPU::deFunction f = getConversion(sourceColorSpace, targetColorSpace);
+
+ if (!f)
+ {
+ return false;
+ }
+
+ cpu.input[0] = v1;
+ cpu.input[1] = v2;
+ cpu.input[2] = v3;
+ cpu.input[3] = v4;
+
+ f(cpu);
+
+ r1 = cpu.output[0];
+ r2 = cpu.output[1];
+ r3 = cpu.output[2];
+ r4 = cpu.output[3];
+
+ return true;
+}
+
+bool deConversionProcessor::renderImageToRGBNew(const deImage& image, unsigned char* data)
+{
+ deColorSpace colorSpace = image.getColorSpace();
+
+ deConversionCPU cpu(4);
+ cpu.registers[CPU_REGISTER_OVERFLOW] = 0;
+
+ int s = getColorSpaceSize(colorSpace);
+
+ deConversionCPU::deFunction f = getConversion(colorSpace, deColorSpaceRGB);
+
+ if (!f)
+ {
+ return false;
+ }
+
+ if (s == 3)
+ {
+ return cpu.renderImage3(image, f, data);
+ } else
+ if (s == 4)
+ {
+ return cpu.renderImage4(image, f, data);
+ } else
+ if (s == 1)
+ {
+ return cpu.renderImage1(image, f, data);
+ };
+
+ return false;
+
+}
+
+void deConversionProcessor::convertImage(const deImage& sourceImage, deImage& image, deConversionCPU& cpu)
+{
+ deColorSpace sourceColorSpace = sourceImage.getColorSpace();
+ deColorSpace targetColorSpace = image.getColorSpace();
+
+ if (sourceColorSpace == targetColorSpace)
+ {
+ copyImage(sourceImage, image);
+ return;
+ }
+
+ int ss = getColorSpaceSize(sourceColorSpace);
+ int ds = getColorSpaceSize(targetColorSpace);
+
+ deConversionCPU::deFunction f1 = empty;
+
+ if (sourceColorSpace == deColorSpaceProPhoto)
+ {
+ if (cpu.registers[CPU_REGISTER_CONTRAST] < 1.0)
+ {
+ f1 = applyContrastRGB;
+ }
+ }
+ if (sourceColorSpace == deColorSpaceLAB)
+ {
+ if ((cpu.registers[CPU_REGISTER_SATURATION] < 1.0) || (cpu.registers[CPU_REGISTER_CONTRAST] < 1.0))
+ {
+ f1 = applyContrastSaturationLAB;
+ }
+ }
+ if (sourceColorSpace == deColorSpaceLCH)
+ {
+ if ((cpu.registers[CPU_REGISTER_SATURATION] < 1.0) || (cpu.registers[CPU_REGISTER_CONTRAST] < 1.0))
+ {
+ f1 = applyContrastSaturationLCH;
+ }
+ }
+
+ deConversionCPU::deFunction f2 = getConversion(sourceColorSpace, targetColorSpace);
+ if (!f2)
+ {
+ logError("conversion not found");
+ }
+
+ if ((ss == 3) && (ds == 3))
+ {
+ if (f2)
+ {
+ cpu.convertImage3x3(sourceImage, image, f1, f2);
+ return;
+ }
+ }
+ else
+ if ((ss == 3) && (ds == 4))
+ {
+ if (f2)
+ {
+ cpu.convertImage3x4(sourceImage, image, f1, f2);
+ return;
+ }
+ }
+ else
+ if ((ss == 4) && (ds == 3))
+ {
+ if (f2)
+ {
+ cpu.convertImage4x3(sourceImage, image, f1, f2);
+ return;
+ }
+ }
+ else
+ if ((ss == 3) && (ds == 1))
+ {
+ if (f2)
+ {
+ cpu.convertImage3x1(sourceImage, image, f1, f2);
+ return;
+ }
+ }
+ else
+ if ((ss == 1) && (ds == 3))
+ {
+ if (f2)
+ {
+ cpu.convertImage1x3(sourceImage, image, f1, f2);
+ return;
+ }
+ }
+ if ((ss == 4) && (ds == 1))
+ {
+ if (f2)
+ {
+ cpu.convertImage4x1(sourceImage, image, f1, f2);
+ return;
+ }
+ }
+ else
+ if ((ss == 1) && (ds == 4))
+ {
+ if (f2)
+ {
+ cpu.convertImage1x4(sourceImage, image, f1, f2);
+ return;
+ }
+ }
+
+ logError("convert image FAILED");
+
+}
diff -Nru delaboratory-0.7/core/conversion_processor.h delaboratory-0.8/core/conversion_processor.h
--- delaboratory-0.7/core/conversion_processor.h 1970-01-01 00:00:00.000000000 +0000
+++ delaboratory-0.8/core/conversion_processor.h 2012-07-10 23:38:22.000000000 +0000
@@ -0,0 +1,42 @@
+/*
+ delaboratory - color correction utility
+ Copyright (C) 2011 Jacek Poplawski
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef _DE_CONVERSION_PROCESSOR_H
+#define _DE_CONVERSION_PROCESSOR_H
+
+#include "conversion_cpu.h"
+
+
+class deConversionProcessor
+{
+ private:
+
+ public:
+ deConversionProcessor();
+ virtual ~deConversionProcessor();
+
+ void convertImage(const deImage& sourceImage, deImage& image, deConversionCPU& cpu);
+
+ bool renderImageToRGBNew(const deImage& image, unsigned char* data);
+ bool convert(deColorSpace sourceColorSpace, deValue v1, deValue v2, deValue v3, deValue v4, deColorSpace targetColorSpace, deValue &r1, deValue& r2, deValue& r3, deValue& r4);
+
+};
+
+
+
+#endif
diff -Nru delaboratory-0.7/core/copy_channel.cc delaboratory-0.8/core/copy_channel.cc
--- delaboratory-0.7/core/copy_channel.cc 1970-01-01 00:00:00.000000000 +0000
+++ delaboratory-0.8/core/copy_channel.cc 2012-06-08 22:38:01.000000000 +0000
@@ -0,0 +1,31 @@
+/*
+ delaboratory - color correction utility
+ Copyright (C) 2011 Jacek Poplawski
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include "copy_channel.h"
+#include
+
+void copyChannel(const deValue* src, deValue* dst, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ {
+ deValue v = src[i];
+ dst[i] = v;
+ }
+}
+
diff -Nru delaboratory-0.7/core/copy_channel.h delaboratory-0.8/core/copy_channel.h
--- delaboratory-0.7/core/copy_channel.h 1970-01-01 00:00:00.000000000 +0000
+++ delaboratory-0.8/core/copy_channel.h 2012-06-08 22:38:01.000000000 +0000
@@ -0,0 +1,26 @@
+/*
+ delaboratory - color correction utility
+ Copyright (C) 2011 Jacek Poplawski
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef _DE_COPY_CHANNEL_H
+#define _DE_COPY_CHANNEL_H
+
+#include "value.h"
+
+void copyChannel(const deValue* src, deValue* dst, int n);
+
+#endif
diff -Nru delaboratory-0.7/core/flatten_layers.cc delaboratory-0.8/core/flatten_layers.cc
--- delaboratory-0.7/core/flatten_layers.cc 1970-01-01 00:00:00.000000000 +0000
+++ delaboratory-0.8/core/flatten_layers.cc 2012-06-16 21:34:03.000000000 +0000
@@ -0,0 +1,124 @@
+/*
+ delaboratory - color correction utility
+ Copyright (C) 2011 Jacek Poplawski
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include "flatten_layers.h"
+
+#include "progress_dialog.h"
+#include "logger.h"
+#include "layer_stack.h"
+#include "base_layer.h"
+#include "channel_manager.h"
+#include "image_io.h"
+#include "str.h"
+#include