void store_colGray(T *buffer, int wrap, int r_ly, T *col, int ly, int x, int dy,
@@ -576,7 +600,19 @@ void do_filtering_chan(BlurPixel *row1, T *row2, int length, float coeff,
BLUR_CODE((P)0.5, Q)
}
}
+template <>
+void do_filtering_chan(BlurPixel *row1,
+ TPixelF *row2, int length,
+ float coeff, float coeffq,
+ int brad, float diff,
+ bool useSSE) {
+ int i;
+ double rsum, gsum, bsum, msum;
+ BlurPixel sigma1, sigma2, sigma3, desigma;
+ BlurPixel *pix1, *pix2, *pix3, *pix4;
+ BLUR_CODE(0.0, float)
+}
//-------------------------------------------------------------------
template
@@ -741,14 +777,14 @@ void load_rowGray(TRasterPT &rin, T *row, int lx, int y, int brad, int bx1,
template
void do_filtering_floatRgb(T *row1, BlurPixel *row2, int length, float coeff,
float coeffq, int brad, float diff, bool useSSE) {
-/*
- int i;
- float rsum, gsum, bsum, msum;
- CASM_FPIXEL sigma1, sigma2, sigma3, desigma;
- TPixel32 *pix1, *pix2, *pix3, *pix4;
+ /*
+ int i;
+ float rsum, gsum, bsum, msum;
+ CASM_FPIXEL sigma1, sigma2, sigma3, desigma;
+ TPixel32 *pix1, *pix2, *pix3, *pix4;
- BLUR_CODE(0, unsigned char)
-*/
+ BLUR_CODE(0, unsigned char)
+ */
#ifdef USE_SSE2
if (useSSE)
@@ -771,7 +807,7 @@ void doBlurRgb(TRasterPT &dstRas, TRasterPT &srcRas, double blur, int dx,
// int border = brad*2; // per sicurezza
- coeff = (float)(blur /
+ coeff = (float)(blur /
(brad - brad * brad +
blur * (2 * brad -
1))); /*sum of the weights of triangolar filter. */
@@ -805,7 +841,7 @@ void doBlurRgb(TRasterPT &dstRas, TRasterPT &srcRas, double blur, int dx,
r1->lock();
fbuffer = (BlurPixel *)r1->getRawData(); // new CASM_FPIXEL [llx *ly];
row1 = new T[llx + 2 * brad];
- col1 = new BlurPixel
[ lly + 2 * brad ];
+ col1 = new BlurPixel
[lly + 2 * brad];
col2 = new T[lly];
}
@@ -879,8 +915,8 @@ void doBlurGray(TRasterPT &dstRas, TRasterPT &srcRas, double blur, int dx,
float coeff, coeffq, diff;
int bx1 = 0, by1 = 0, bx2 = 0, by2 = 0;
- brad = (int)ceil(blur); /* number of pixels involved in the filtering */
- coeff = (float)(blur /
+ brad = (int)ceil(blur); /* number of pixels involved in the filtering */
+ coeff = (float)(blur /
(brad - brad * brad +
blur * (2 * brad -
1))); /*sum of the weights of triangolar filter. */
@@ -958,30 +994,39 @@ void TRop::blur(const TRasterP &dstRas, const TRasterP &srcRas, double blur,
int dx, int dy, bool useSSE) {
TRaster32P dstRas32 = dstRas;
TRaster32P srcRas32 = srcRas;
-
- if (dstRas32 && srcRas32)
+ if (dstRas32 && srcRas32) {
doBlurRgb(dstRas32, srcRas32, blur, dx, dy, useSSE);
- else {
- TRaster64P dstRas64 = dstRas;
- TRaster64P srcRas64 = srcRas;
- if (dstRas64 && srcRas64)
- doBlurRgb(dstRas64, srcRas64, blur, dx, dy,
- useSSE);
- else {
- TRasterGR8P dstRasGR8 = dstRas;
- TRasterGR8P srcRasGR8 = srcRas;
-
- if (dstRasGR8 && srcRasGR8)
- doBlurGray(dstRasGR8, srcRasGR8, blur, dx, dy);
- else {
- TRasterGR16P dstRasGR16 = dstRas;
- TRasterGR16P srcRasGR16 = srcRas;
-
- if (dstRasGR16 && srcRasGR16)
- doBlurGray(dstRasGR16, srcRasGR16, blur, dx, dy);
- else
- throw TException("TRop::blur unsupported pixel type");
- }
- }
+ return;
+ }
+
+ TRaster64P dstRas64 = dstRas;
+ TRaster64P srcRas64 = srcRas;
+ if (dstRas64 && srcRas64) {
+ doBlurRgb(dstRas64, srcRas64, blur, dx, dy,
+ useSSE);
+ return;
+ }
+
+ TRasterFP dstRasF = dstRas;
+ TRasterFP srcRasF = srcRas;
+ if (dstRasF && srcRasF) {
+ doBlurRgb(dstRasF, srcRasF, blur, dx, dy, useSSE);
+ return;
}
+
+ TRasterGR8P dstRasGR8 = dstRas;
+ TRasterGR8P srcRasGR8 = srcRas;
+ if (dstRasGR8 && srcRasGR8) {
+ doBlurGray(dstRasGR8, srcRasGR8, blur, dx, dy);
+ return;
+ }
+
+ TRasterGR16P dstRasGR16 = dstRas;
+ TRasterGR16P srcRasGR16 = srcRas;
+ if (dstRasGR16 && srcRasGR16) {
+ doBlurGray(dstRasGR16, srcRasGR16, blur, dx, dy);
+ return;
+ }
+
+ throw TException("TRop::blur unsupported pixel type");
}
diff --git a/toonz/sources/common/trop/tcheckboard.cpp b/toonz/sources/common/trop/tcheckboard.cpp
index 71afc4a..a9be5f7 100644
--- a/toonz/sources/common/trop/tcheckboard.cpp
+++ b/toonz/sources/common/trop/tcheckboard.cpp
@@ -82,14 +82,15 @@ void TRop::checkBoard(TRasterP rout, const TPixel32 &pix1, const TPixel32 &pix2,
// assert(offset.x<=dim.lx && offset.y<=dim.ly);
TRaster32P rout32 = rout;
+ TRaster64P rout64 = rout;
+ TRasterFP routF = rout;
if (rout32)
do_checkBoard(rout32, pix1, pix2, dim, offset);
- else {
- TRaster64P rout64 = rout;
- if (rout64)
- do_checkBoard(rout64, toPixel64(pix1), toPixel64(pix2), dim,
- offset);
- else
- throw TRopException("unsupported pixel type");
- }
+ else if (rout64)
+ do_checkBoard(rout64, toPixel64(pix1), toPixel64(pix2), dim,
+ offset);
+ else if (routF)
+ do_checkBoard(routF, toPixelF(pix1), toPixelF(pix2), dim, offset);
+ else
+ throw TRopException("unsupported pixel type");
}
diff --git a/toonz/sources/common/trop/tconvert.cpp b/toonz/sources/common/trop/tconvert.cpp
index 413ae34..72a877a 100644
--- a/toonz/sources/common/trop/tconvert.cpp
+++ b/toonz/sources/common/trop/tconvert.cpp
@@ -252,9 +252,9 @@ static void do_convert(const TRasterYUV422P &dst, const TRaster32P &src) {
/* limit the chroma */
if (u1 < -112) u1 = -112;
- if (u1 > 111) u1 = 111;
+ if (u1 > 111) u1 = 111;
if (v1 < -112) v1 = -112;
- if (v1 > 111) v1 = 111;
+ if (v1 > 111) v1 = 111;
/* limit the lum */
if (y1 > 0x00dbffff) y1 = 0x00dbffff;
@@ -291,17 +291,17 @@ static void do_convert(const TRaster32P &dst, const TRasterYUV422P &src) {
y2 -= 16;
in++;
- r = 76310 * y1 + 104635 * v;
+ r = 76310 * y1 + 104635 * v;
if (r > 0xFFFFFF) r = 0xFFFFFF;
- if (r <= 0xFFFF) r = 0;
+ if (r <= 0xFFFF) r = 0;
- g = 76310 * y1 + -25690 * u + -53294 * v;
+ g = 76310 * y1 + -25690 * u + -53294 * v;
if (g > 0xFFFFFF) g = 0xFFFFFF;
- if (g <= 0xFFFF) g = 0;
+ if (g <= 0xFFFF) g = 0;
- b = 76310 * y1 + 132278 * u;
+ b = 76310 * y1 + 132278 * u;
if (b > 0xFFFFFF) b = 0xFFFFFF;
- if (b <= 0xFFFF) b = 0;
+ if (b <= 0xFFFF) b = 0;
buf->r = (UCHAR)(r >> 16);
buf->g = (UCHAR)(g >> 16);
@@ -309,17 +309,17 @@ static void do_convert(const TRaster32P &dst, const TRasterYUV422P &src) {
buf->m = (UCHAR)255;
buf++;
- r = 76310 * y2 + 104635 * v;
+ r = 76310 * y2 + 104635 * v;
if (r > 0xFFFFFF) r = 0xFFFFFF;
- if (r <= 0xFFFF) r = 0;
+ if (r <= 0xFFFF) r = 0;
- g = 76310 * y2 + -25690 * u + -53294 * v;
+ g = 76310 * y2 + -25690 * u + -53294 * v;
if (g > 0xFFFFFF) g = 0xFFFFFF;
- if (g <= 0xFFFF) g = 0;
+ if (g <= 0xFFFF) g = 0;
- b = 76310 * y2 + 132278 * u;
+ b = 76310 * y2 + 132278 * u;
if (b > 0xFFFFFF) b = 0xFFFFFF;
- if (b <= 0xFFFF) b = 0;
+ if (b <= 0xFFFF) b = 0;
buf->r = (UCHAR)(r >> 16);
buf->g = (UCHAR)(g >> 16);
@@ -330,6 +330,94 @@ static void do_convert(const TRaster32P &dst, const TRasterYUV422P &src) {
}
//******************************************************************
+// Conversion from/to double raster
+//******************************************************************
+
+static void do_convert(const TRasterFP &dst, const TRaster32P &src) {
+ assert(dst->getSize() == src->getSize());
+ int lx = src->getLx();
+ for (int y = 0; y < src->getLy(); y++) {
+ TPixelF *outPix = dst->pixels(y);
+ TPixel32 *inPix = src->pixels(y);
+ TPixel32 *inEndPix = inPix + lx;
+ for (; inPix < inEndPix; ++outPix, ++inPix) {
+ outPix->r = (float)inPix->r / (float)TPixel32::maxChannelValue;
+ outPix->g = (float)inPix->g / (float)TPixel32::maxChannelValue;
+ outPix->b = (float)inPix->b / (float)TPixel32::maxChannelValue;
+ outPix->m = (float)inPix->m / (float)TPixel32::maxChannelValue;
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+
+static void do_convert(const TRasterFP &dst, const TRaster64P &src) {
+ assert(dst->getSize() == src->getSize());
+ int lx = src->getLx();
+ for (int y = 0; y < src->getLy(); y++) {
+ TPixelF *outPix = dst->pixels(y);
+ TPixel64 *inPix = src->pixels(y);
+ TPixel64 *inEndPix = inPix + lx;
+ for (; inPix < inEndPix; ++outPix, ++inPix) {
+ outPix->r = (float)inPix->r / (float)TPixel64::maxChannelValue;
+ outPix->g = (float)inPix->g / (float)TPixel64::maxChannelValue;
+ outPix->b = (float)inPix->b / (float)TPixel64::maxChannelValue;
+ outPix->m = (float)inPix->m / (float)TPixel64::maxChannelValue;
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+
+static void do_convert(const TRaster32P &dst, const TRasterFP &src) {
+ auto clamp01 = [](float val) {
+ return (val < 0.f) ? 0.f : (val > 1.f) ? 1.f : val;
+ };
+ assert(dst->getSize() == src->getSize());
+ int lx = src->getLx();
+ for (int y = 0; y < src->getLy(); y++) {
+ TPixel32 *outPix = dst->pixels(y);
+ TPixelF *inPix = src->pixels(y);
+ TPixelF *inEndPix = inPix + lx;
+ for (; inPix < inEndPix; ++outPix, ++inPix) {
+ outPix->r = (TPixel32::Channel)(
+ clamp01(inPix->r) * (float)TPixel32::maxChannelValue + 0.5f);
+ outPix->g = (TPixel32::Channel)(
+ clamp01(inPix->g) * (float)TPixel32::maxChannelValue + 0.5f);
+ outPix->b = (TPixel32::Channel)(
+ clamp01(inPix->b) * (float)TPixel32::maxChannelValue + 0.5f);
+ outPix->m = (TPixel32::Channel)(
+ clamp01(inPix->m) * (float)TPixel32::maxChannelValue + 0.5f);
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+
+static void do_convert(const TRaster64P &dst, const TRasterFP &src) {
+ auto clamp01 = [](float val) {
+ return (val < 0.f) ? 0.f : (val > 1.f) ? 1.f : val;
+ };
+ assert(dst->getSize() == src->getSize());
+ int lx = src->getLx();
+ for (int y = 0; y < src->getLy(); y++) {
+ TPixel64 *outPix = dst->pixels(y);
+ TPixelF *inPix = src->pixels(y);
+ TPixelF *inEndPix = inPix + lx;
+ for (; inPix < inEndPix; ++outPix, ++inPix) {
+ outPix->r = (TPixel64::Channel)(
+ clamp01(inPix->r) * (float)TPixel64::maxChannelValue + 0.5f);
+ outPix->g = (TPixel64::Channel)(
+ clamp01(inPix->g) * (float)TPixel64::maxChannelValue + 0.5f);
+ outPix->b = (TPixel64::Channel)(
+ clamp01(inPix->b) * (float)TPixel64::maxChannelValue + 0.5f);
+ outPix->m = (TPixel64::Channel)(
+ clamp01(inPix->m) * (float)TPixel64::maxChannelValue + 0.5f);
+ }
+ }
+}
+
+//******************************************************************
// Main conversion function
//******************************************************************
@@ -337,17 +425,19 @@ void TRop::convert(TRasterP dst, const TRasterP &src) {
if (dst->getSize() != src->getSize())
throw TRopException("convert: size mismatch");
- TRaster32P dst32 = dst;
- TRasterGR8P dst8 = dst;
- TRasterGR16P dst16 = dst;
- TRaster64P dst64 = dst;
- TRasterCM32P dstCm = dst;
+ TRaster32P dst32 = dst;
+ TRasterGR8P dst8 = dst;
+ TRasterGR16P dst16 = dst;
+ TRaster64P dst64 = dst;
+ TRasterCM32P dstCm = dst;
+ TRasterYUV422P dstYUV = dst;
+ TRasterFP dstF = dst;
TRaster32P src32 = src;
TRasterGR8P src8 = src;
TRaster64P src64 = src;
TRasterYUV422P srcYUV = src;
- TRasterYUV422P dstYUV = dst;
+ TRasterFP srcF = src;
src->lock();
dst->lock();
@@ -372,6 +462,15 @@ void TRop::convert(TRasterP dst, const TRasterP &src) {
do_convert(dstCm, src32); //
else if (dstCm && src8)
do_convert(dstCm, src8); //
+ // conversion from/to double
+ else if (dstF && src32)
+ do_convert(dstF, src32);
+ else if (dstF && src64)
+ do_convert(dstF, src64);
+ else if (dst32 && srcF)
+ do_convert(dst32, srcF);
+ else if (dst64 && srcF)
+ do_convert(dst64, srcF);
else {
dst->unlock();
src->unlock();
@@ -379,6 +478,7 @@ void TRop::convert(TRasterP dst, const TRasterP &src) {
throw TRopException("unsupported pixel type");
}
+ dst->setLinear(src->isLinear());
dst->unlock();
src->unlock();
}
diff --git a/toonz/sources/common/trop/tinvert.cpp b/toonz/sources/common/trop/tinvert.cpp
index 0208a8b..e473b62 100644
--- a/toonz/sources/common/trop/tinvert.cpp
+++ b/toonz/sources/common/trop/tinvert.cpp
@@ -42,9 +42,9 @@ inline void do_invert(TRasterPT ras, bool invRed, bool invGreen,
pixIn = rowIn;
endPix = pixIn + lx;
while (pixIn < endPix) {
- if (invRed) pixIn->r = pixIn->m - pixIn->r;
+ if (invRed) pixIn->r = pixIn->m - pixIn->r;
if (invGreen) pixIn->g = pixIn->m - pixIn->g;
- if (invBlue) pixIn->b = pixIn->m - pixIn->b;
+ if (invBlue) pixIn->b = pixIn->m - pixIn->b;
if (invMatte) pixIn->m = ~pixIn->m;
++pixIn;
}
@@ -74,8 +74,35 @@ inline void do_invert(TRasterPT ras) {
rowIn += wrap;
}
}
+
+//------------------------------------------------------------------------------
+
+template <>
+inline void do_invert(TRasterFP ras, bool invRed, bool invGreen,
+ bool invBlue, bool invMatte) {
+ int wrap = ras->getWrap();
+ int lx = ras->getLx();
+ TPixelF *rowIn = ras->pixels();
+ TPixelF *lastPix = rowIn + wrap * ras->getLy();
+ TPixelF *pixIn = 0;
+ TPixelF *endPix = 0;
+
+ while (pixIn < lastPix) {
+ pixIn = rowIn;
+ endPix = pixIn + lx;
+ while (pixIn < endPix) {
+ if (invRed) pixIn->r = pixIn->m - pixIn->r;
+ if (invGreen) pixIn->g = pixIn->m - pixIn->g;
+ if (invBlue) pixIn->b = pixIn->m - pixIn->b;
+ if (invMatte) pixIn->m = 1.f - pixIn->m;
+ ++pixIn;
+ }
+ rowIn += wrap;
+ }
}
+} // namespace
+
//------------------------------------------------------------------------------
void TRop::invert(TRasterP ras, bool invRed, bool invGreen, bool invBlue,
@@ -84,29 +111,33 @@ void TRop::invert(TRasterP ras, bool invRed, bool invGreen, bool invBlue,
bool flag = invRed && invGreen && invBlue && !invMatte;
TRaster32P ras32 = ras;
+ TRaster64P ras64 = ras;
+ TRasterFP rasF = ras;
+ TRasterGR8P ras8 = ras;
ras->lock();
- if (ras32)
+
+ if (ras32) {
if (flag)
do_invert(ras32);
else
do_invert(ras, invRed, invGreen, invBlue, invMatte);
+ } else if (ras64) {
+ if (flag)
+ do_invert(ras64);
+ else
+ do_invert(ras64, invRed, invGreen, invBlue, invMatte);
+ } else if (rasF) {
+ if (flag)
+ do_invert(rasF);
+ else
+ do_invert(rasF, invRed, invGreen, invBlue, invMatte);
+ } else if (ras8)
+ do_invert(ras8);
else {
- TRaster64P ras64 = ras;
- if (ras64)
- if (flag)
- do_invert(ras64);
- else
- do_invert(ras64, invRed, invGreen, invBlue, invMatte);
- else {
- TRasterGR8P ras8 = ras;
- if (ras8)
- do_invert(ras8);
- else {
- ras->unlock();
- throw TRopException("unsupported pixel type");
- }
- }
+ ras->unlock();
+ throw TRopException("unsupported pixel type");
}
+
ras->unlock();
}
diff --git a/toonz/sources/common/trop/toperators.cpp b/toonz/sources/common/trop/toperators.cpp
index a1bb38b..55ffe33 100644
--- a/toonz/sources/common/trop/toperators.cpp
+++ b/toonz/sources/common/trop/toperators.cpp
@@ -92,6 +92,18 @@ inline double luminance(TPixel64 *pix) {
//-----------------------------------------------------------------------------
+#define FOR_EACH_PIXEL_F_BEGIN_LOOP \
+ assert(upF &&downF &&outF); \
+ FOR_EACH_PIXEL_BEGIN_LOOP(TPixelF, upF, TPixelF, downF, TPixelF, outF)
+
+//-----------------------------------------------------------------------------
+
+#define FOR_EACH_PIXEL_F_END_LOOP \
+ assert(upF &&downF &&outF); \
+ FOR_EACH_PIXEL_END_LOOP(upF, downF, outF)
+
+//-----------------------------------------------------------------------------
+
#define FOR_EACH_PIXEL_8_BEGIN_LOOP \
assert(up8 &&down8 &&out8); \
FOR_EACH_PIXEL_BEGIN_LOOP(TPixelGR8, up8, TPixelGR8, down8, TPixelGR8, out8)
@@ -128,43 +140,63 @@ void TRop::add(const TRasterP &rup, const TRasterP &rdown, const TRasterP &rout,
}
FOR_EACH_PIXEL_32_END_LOOP
- } else {
- TRaster64P up64 = rup;
- TRaster64P down64 = rdown;
- TRaster64P out64 = rout;
+ return;
+ }
- if (up64 && down64 && out64) {
- FOR_EACH_PIXEL_64_BEGIN_LOOP
+ TRaster64P up64 = rup;
+ TRaster64P down64 = rdown;
+ TRaster64P out64 = rout;
- TINT32 r, g, b, m;
- r = downPix->r + tround(upPix->r * v);
- g = downPix->g + tround(upPix->g * v);
- b = downPix->b + tround(upPix->b * v);
- m = downPix->m + tround(upPix->m * v);
+ if (up64 && down64 && out64) {
+ FOR_EACH_PIXEL_64_BEGIN_LOOP
- outPix->r = (USHORT)tcrop(r, 0, 0xffff);
- outPix->g = (USHORT)tcrop(g, 0, 0xffff);
- outPix->b = (USHORT)tcrop(b, 0, 0xffff);
- outPix->m = (USHORT)tcrop(m, 0, 0xffff);
+ TINT32 r, g, b, m;
+ r = downPix->r + tround(upPix->r * v);
+ g = downPix->g + tround(upPix->g * v);
+ b = downPix->b + tround(upPix->b * v);
+ m = downPix->m + tround(upPix->m * v);
- FOR_EACH_PIXEL_64_END_LOOP
- } else {
- TRasterGR8P up8 = rup;
- TRasterGR8P down8 = rdown;
- TRasterGR8P out8 = rout;
+ outPix->r = (USHORT)tcrop(r, 0, 0xffff);
+ outPix->g = (USHORT)tcrop(g, 0, 0xffff);
+ outPix->b = (USHORT)tcrop(b, 0, 0xffff);
+ outPix->m = (USHORT)tcrop(m, 0, 0xffff);
- if (up8 && down8 && out8) {
- FOR_EACH_PIXEL_8_BEGIN_LOOP
+ FOR_EACH_PIXEL_64_END_LOOP
+ return;
+ }
- USHORT value = troundp(upPix->value * v) + downPix->value;
+ TRasterFP upF = rup;
+ TRasterFP downF = rdown;
+ TRasterFP outF = rout;
- outPix->value = (UCHAR)tcrop(value, 0, 255);
+ if (upF && downF && outF) {
+ FOR_EACH_PIXEL_F_BEGIN_LOOP
- FOR_EACH_PIXEL_8_END_LOOP
- } else
- throw TRopException("TRop::add invalid raster combination");
- }
+ outPix->r = downPix->r + upPix->r * v;
+ outPix->g = downPix->g + upPix->g * v;
+ outPix->b = downPix->b + upPix->b * v;
+ outPix->m = tcrop(downPix->m + upPix->m * v, 0.f, 1.f);
+
+ FOR_EACH_PIXEL_F_END_LOOP
+ return;
+ }
+
+ TRasterGR8P up8 = rup;
+ TRasterGR8P down8 = rdown;
+ TRasterGR8P out8 = rout;
+
+ if (up8 && down8 && out8) {
+ FOR_EACH_PIXEL_8_BEGIN_LOOP
+
+ USHORT value = troundp(upPix->value * v) + downPix->value;
+
+ outPix->value = (UCHAR)tcrop(value, 0, 255);
+
+ FOR_EACH_PIXEL_8_END_LOOP
+ return;
}
+
+ throw TRopException("TRop::add invalid raster combination");
}
//-----------------------------------------------------------------------------
@@ -190,43 +222,62 @@ void TRop::add(const TRasterP &rup, const TRasterP &rdown,
outPix->m = (UCHAR)tcrop(m, 0, 255);
FOR_EACH_PIXEL_32_END_LOOP
- } else {
- TRaster64P up64 = rup;
- TRaster64P down64 = rdown;
- TRaster64P out64 = rout;
+ return;
+ }
+ TRaster64P up64 = rup;
+ TRaster64P down64 = rdown;
+ TRaster64P out64 = rout;
- if (up64 && down64 && out64) {
- FOR_EACH_PIXEL_64_BEGIN_LOOP
+ if (up64 && down64 && out64) {
+ FOR_EACH_PIXEL_64_BEGIN_LOOP
- TINT32 r, g, b, m;
- r = downPix->r + upPix->r;
- g = downPix->g + upPix->g;
- b = downPix->b + upPix->b;
- m = downPix->m + upPix->m;
+ TINT32 r, g, b, m;
+ r = downPix->r + upPix->r;
+ g = downPix->g + upPix->g;
+ b = downPix->b + upPix->b;
+ m = downPix->m + upPix->m;
- outPix->r = (USHORT)tcrop(r, 0, 0xffff);
- outPix->g = (USHORT)tcrop(g, 0, 0xffff);
- outPix->b = (USHORT)tcrop(b, 0, 0xffff);
- outPix->m = (USHORT)tcrop(m, 0, 0xffff);
+ outPix->r = (USHORT)tcrop(r, 0, 0xffff);
+ outPix->g = (USHORT)tcrop(g, 0, 0xffff);
+ outPix->b = (USHORT)tcrop(b, 0, 0xffff);
+ outPix->m = (USHORT)tcrop(m, 0, 0xffff);
- FOR_EACH_PIXEL_64_END_LOOP
- } else {
- TRasterGR8P up8 = rup;
- TRasterGR8P down8 = rdown;
- TRasterGR8P out8 = rout;
+ FOR_EACH_PIXEL_64_END_LOOP
+ return;
+ }
- if (up8 && down8 && out8) {
- FOR_EACH_PIXEL_8_BEGIN_LOOP
+ TRasterFP upF = rup;
+ TRasterFP downF = rdown;
+ TRasterFP outF = rout;
- USHORT value = upPix->value + downPix->value;
+ if (upF && downF && outF) {
+ FOR_EACH_PIXEL_F_BEGIN_LOOP
- outPix->value = (UCHAR)tcrop(value, 0, 255);
+ outPix->r = downPix->r + upPix->r;
+ outPix->g = downPix->g + upPix->g;
+ outPix->b = downPix->b + upPix->b;
+ outPix->m = tcrop(downPix->m + upPix->m, 0.f, 1.f);
- FOR_EACH_PIXEL_8_END_LOOP
- } else
- throw TRopException("TRop::add invalid raster combination");
- }
+ FOR_EACH_PIXEL_F_END_LOOP
+ return;
+ }
+
+ TRasterGR8P up8 = rup;
+ TRasterGR8P down8 = rdown;
+ TRasterGR8P out8 = rout;
+
+ if (up8 && down8 && out8) {
+ FOR_EACH_PIXEL_8_BEGIN_LOOP
+
+ USHORT value = upPix->value + downPix->value;
+
+ outPix->value = (UCHAR)tcrop(value, 0, 255);
+
+ FOR_EACH_PIXEL_8_END_LOOP
+ return;
}
+
+ throw TRopException("TRop::add invalid raster combination");
}
//-----------------------------------------------------------------------------
@@ -277,21 +328,36 @@ void TRop::colordodge(const TRasterP &rup, const TRasterP &rdown,
FOR_EACH_PIXEL_64_END_LOOP
} else {
- TRasterGR8P up8 = rup;
- TRasterGR8P down8 = rdown;
- TRasterGR8P out8 = rout;
+ TRasterFP upF = rup;
+ TRasterFP downF = rdown;
+ TRasterFP outF = rout;
- if (up8 && down8 && out8) {
- FOR_EACH_PIXEL_8_BEGIN_LOOP
- USHORT value;
- if (downPix->value)
- value = (USHORT)((downPix->value << 8) / (255.0 - upPix->value));
+ if (upF && downF && outF) {
+ FOR_EACH_PIXEL_F_BEGIN_LOOP
- outPix->value = (UCHAR)tcrop(value, 0, 255);
+ outPix->r = downPix->r / (1.f - upPix->r);
+ outPix->g = downPix->g / (1.f - upPix->g);
+ outPix->b = downPix->b / (1.f - upPix->b);
+ outPix->m = tcrop(downPix->m + upPix->m, 0.f, 1.f);
- FOR_EACH_PIXEL_8_END_LOOP
- } else
- throw TRopException("TRop::color dodge invalid raster combination");
+ FOR_EACH_PIXEL_F_END_LOOP
+ } else {
+ TRasterGR8P up8 = rup;
+ TRasterGR8P down8 = rdown;
+ TRasterGR8P out8 = rout;
+
+ if (up8 && down8 && out8) {
+ FOR_EACH_PIXEL_8_BEGIN_LOOP
+ USHORT value;
+ if (downPix->value)
+ value = (USHORT)((downPix->value << 8) / (255.0 - upPix->value));
+
+ outPix->value = (UCHAR)tcrop(value, 0, 255);
+
+ FOR_EACH_PIXEL_8_END_LOOP
+ } else
+ throw TRopException("TRop::color dodge invalid raster combination");
+ }
}
}
}
@@ -392,8 +458,50 @@ void TRop::colorburn(const TRasterP &rup, const TRasterP &rdown,
outPix = downPix;
}
FOR_EACH_PIXEL_64_END_LOOP
- } else
- throw TRopException("TRop::color burn invalid raster combination");
+ } else {
+ TRasterFP upF = rup;
+ TRasterFP downF = rdown;
+ TRasterFP outF = rout;
+
+ if (upF && downF && outF) {
+ FOR_EACH_PIXEL_F_BEGIN_LOOP
+ float r, g, b;
+ if (upPix->m > 0.f) {
+ if (downPix->r <= 0.f || downPix->r >= 1.f)
+ r = downPix->r;
+ else if (upPix->r)
+ r = 1.f - (1.f - downPix->r) / upPix->r;
+ else
+ r = 0.f;
+ if (downPix->g <= 0.f || downPix->g >= 1.f)
+ g = downPix->g;
+ else if (upPix->g)
+ g = 1.f - (1.f - downPix->g) / upPix->g;
+ else
+ g = 0.f;
+ if (downPix->b <= 0.f || downPix->b >= 1.f)
+ b = downPix->b;
+ else if (upPix->b)
+ b = 1.f - (1.f - downPix->b) / upPix->b;
+ else
+ b = 0.f;
+
+ if (upPix->m < 1.f) {
+ overPix(*outPix, *downPix,
+ TPixelF(r, g, b, upPix->m));
+ } else {
+ outPix->r = r;
+ outPix->g = g;
+ outPix->b = b;
+ outPix->m = downPix->m;
+ }
+ } else {
+ outPix = downPix;
+ }
+ FOR_EACH_PIXEL_F_END_LOOP
+ } else
+ throw TRopException("TRop::color burn invalid raster combination");
+ }
}
}
@@ -428,54 +536,86 @@ void TRop::screen(const TRasterP &rup, const TRasterP &rdown,
outPix->m = upPix->m;
}
FOR_EACH_PIXEL_32_END_LOOP
- } else {
- TRaster64P up64 = rup;
- TRaster64P down64 = rdown;
- TRaster64P out64 = rout;
+ return;
+ }
- if (up64 && down64 && out64) {
- FOR_EACH_PIXEL_64_BEGIN_LOOP
+ TRaster64P up64 = rup;
+ TRaster64P down64 = rdown;
+ TRaster64P out64 = rout;
- double r, g, b;
- r = 65536 - (65536 - upPix->r) * ((65536 - downPix->r) / 65536.0);
- g = 65536 - (65536 - upPix->g) * ((65536 - downPix->g) / 65536.0);
- b = 65536 - (65536 - upPix->b) * ((65536 - downPix->b) / 65536.0);
-
- if (upPix->m != 65535) {
- double m;
- m = 65536 - (65536 - upPix->m) * ((65536 - downPix->m) / 65536.0);
- TPixel64 tmpPix;
- tmpPix.r = (USHORT)tcrop(r, 0, 65535);
- tmpPix.g = (USHORT)tcrop(g, 0, 65535);
- tmpPix.b = (USHORT)tcrop(b, 0, 65535);
- tmpPix.m = (USHORT)tcrop(m, 0, 65535);
- overPix(*outPix, *downPix, tmpPix);
- } else {
- outPix->r = (USHORT)tcrop(r, 0, 65535);
- outPix->g = (USHORT)tcrop(g, 0, 65535);
- outPix->b = (USHORT)tcrop(b, 0, 65535);
- outPix->m = upPix->m;
- }
+ if (up64 && down64 && out64) {
+ FOR_EACH_PIXEL_64_BEGIN_LOOP
- FOR_EACH_PIXEL_64_END_LOOP
+ double r, g, b;
+ r = 65536 - (65536 - upPix->r) * ((65536 - downPix->r) / 65536.0);
+ g = 65536 - (65536 - upPix->g) * ((65536 - downPix->g) / 65536.0);
+ b = 65536 - (65536 - upPix->b) * ((65536 - downPix->b) / 65536.0);
+
+ if (upPix->m != 65535) {
+ double m;
+ m = 65536 - (65536 - upPix->m) * ((65536 - downPix->m) / 65536.0);
+ TPixel64 tmpPix;
+ tmpPix.r = (USHORT)tcrop(r, 0, 65535);
+ tmpPix.g = (USHORT)tcrop(g, 0, 65535);
+ tmpPix.b = (USHORT)tcrop(b, 0, 65535);
+ tmpPix.m = (USHORT)tcrop(m, 0, 65535);
+ overPix(*outPix, *downPix, tmpPix);
} else {
- TRasterGR8P up8 = rup;
- TRasterGR8P down8 = rdown;
- TRasterGR8P out8 = rout;
+ outPix->r = (USHORT)tcrop(r, 0, 65535);
+ outPix->g = (USHORT)tcrop(g, 0, 65535);
+ outPix->b = (USHORT)tcrop(b, 0, 65535);
+ outPix->m = upPix->m;
+ }
- if (up8 && down8 && out8) {
- FOR_EACH_PIXEL_8_BEGIN_LOOP
- USHORT value;
- if (downPix->value)
- value = (USHORT)((downPix->value << 8) / (255.0 - upPix->value));
+ FOR_EACH_PIXEL_64_END_LOOP
+ return;
+ }
- outPix->value = (UCHAR)tcrop(value, 0, 255);
+ TRasterFP upF = rup;
+ TRasterFP downF = rdown;
+ TRasterFP outF = rout;
- FOR_EACH_PIXEL_8_END_LOOP
- } else
- throw TRopException("TRop::color dodge invalid raster combination");
+ if (upF && downF && outF) {
+ FOR_EACH_PIXEL_F_BEGIN_LOOP
+
+ float r, g, b;
+ r = 1.f - (1.f - upPix->r) * (1.f - downPix->r);
+ g = 1.f - (1.f - upPix->g) * (1.f - downPix->g);
+ b = 1.f - (1.f - upPix->b) * (1.f - downPix->b);
+
+ if (upPix->m <= 1.f) {
+ float m;
+ m = 1.f - (1.f - upPix->m) * (1.f - downPix->m);
+ TPixelF tmpPix(r, g, b, tcrop(m, 0.f, 1.f));
+ overPix(*outPix, *downPix, tmpPix);
+ } else {
+ outPix->r = r;
+ outPix->g = g;
+ outPix->b = b;
+ outPix->m = upPix->m;
}
+
+ FOR_EACH_PIXEL_F_END_LOOP
+ return;
+ }
+
+ TRasterGR8P up8 = rup;
+ TRasterGR8P down8 = rdown;
+ TRasterGR8P out8 = rout;
+
+ if (up8 && down8 && out8) {
+ FOR_EACH_PIXEL_8_BEGIN_LOOP
+ USHORT value;
+ if (downPix->value)
+ value = (USHORT)((downPix->value << 8) / (255.0 - upPix->value));
+
+ outPix->value = (UCHAR)tcrop(value, 0, 255);
+
+ FOR_EACH_PIXEL_8_END_LOOP
+ return;
}
+
+ throw TRopException("TRop::color dodge invalid raster combination");
}
//-----------------------------------------------------------------------------
@@ -500,40 +640,61 @@ void TRop::sub(const TRasterP &rup, const TRasterP &rdown, const TRasterP &rout,
outPix->m = (UCHAR)tcrop(m, 0, 255);
FOR_EACH_PIXEL_32_END_LOOP
- } else {
- TRaster64P up64 = rup;
- TRaster64P down64 = rdown;
- TRaster64P out64 = rout;
-
- if (up64 && down64 && out64) {
- FOR_EACH_PIXEL_64_BEGIN_LOOP
-
- TINT32 r = downPix->r - upPix->r;
- TINT32 g = downPix->g - upPix->g;
- TINT32 b = downPix->b - upPix->b;
- TINT32 m = downPix->m - upPix->m;
- outPix->r = (USHORT)tcrop(r, 0, 0xffff);
- outPix->g = (USHORT)tcrop(g, 0, 0xffff);
- outPix->b = (USHORT)tcrop(b, 0, 0xffff);
- outPix->m = (USHORT)tcrop(m, 0, 0xffff);
-
- FOR_EACH_PIXEL_64_END_LOOP
- } else {
- TRasterGR8P up8 = rup;
- TRasterGR8P down8 = rdown;
- TRasterGR8P out8 = rout;
+ return;
+ }
- if (up8 && down8 && out8) {
- FOR_EACH_PIXEL_8_BEGIN_LOOP
+ TRaster64P up64 = rup;
+ TRaster64P down64 = rdown;
+ TRaster64P out64 = rout;
- SHORT value = upPix->value - downPix->value;
- outPix->value = (UCHAR)tcrop(value, 0, 255);
+ if (up64 && down64 && out64) {
+ FOR_EACH_PIXEL_64_BEGIN_LOOP
- FOR_EACH_PIXEL_8_END_LOOP
- } else
- throw TRopException("TRop::sub invalid raster combination");
- }
+ TINT32 r = downPix->r - upPix->r;
+ TINT32 g = downPix->g - upPix->g;
+ TINT32 b = downPix->b - upPix->b;
+ TINT32 m = downPix->m - upPix->m;
+ outPix->r = (USHORT)tcrop(r, 0, 0xffff);
+ outPix->g = (USHORT)tcrop(g, 0, 0xffff);
+ outPix->b = (USHORT)tcrop(b, 0, 0xffff);
+ outPix->m = (USHORT)tcrop(m, 0, 0xffff);
+
+ FOR_EACH_PIXEL_64_END_LOOP
+ return;
+ }
+
+ TRasterFP upF = rup;
+ TRasterFP downF = rdown;
+ TRasterFP outF = rout;
+
+ if (upF && downF && outF) {
+ FOR_EACH_PIXEL_F_BEGIN_LOOP
+
+ outPix->r = downPix->r - upPix->r;
+ outPix->g = downPix->g - upPix->g;
+ outPix->b = downPix->b - upPix->b;
+ outPix->m = tcrop(downPix->m - upPix->m, 0.f, 1.f);
+
+ FOR_EACH_PIXEL_F_END_LOOP
+ return;
+ }
+
+ TRasterGR8P up8 = rup;
+ TRasterGR8P down8 = rdown;
+ TRasterGR8P out8 = rout;
+
+ if (up8 && down8 && out8) {
+ FOR_EACH_PIXEL_8_BEGIN_LOOP
+
+ SHORT value = upPix->value - downPix->value;
+ outPix->value = (UCHAR)tcrop(value, 0, 255);
+
+ FOR_EACH_PIXEL_8_END_LOOP
+ return;
}
+
+ throw TRopException("TRop::sub invalid raster combination");
+
} else {
if (up32 && down32 && out32) {
FOR_EACH_PIXEL_32_BEGIN_LOOP
@@ -549,40 +710,60 @@ void TRop::sub(const TRasterP &rup, const TRasterP &rdown, const TRasterP &rout,
outPix->m = (UCHAR)tcrop(m, 0, 255);
FOR_EACH_PIXEL_32_END_LOOP
- } else {
- TRaster64P up64 = rup;
- TRaster64P down64 = rdown;
- TRaster64P out64 = rout;
-
- if (up64 && down64 && out64) {
- FOR_EACH_PIXEL_64_BEGIN_LOOP
-
- TINT32 r = downPix->r - upPix->r;
- TINT32 g = downPix->g - upPix->g;
- TINT32 b = downPix->b - upPix->b;
- TINT32 m = downPix->m; // - upPix->m;
- outPix->r = (USHORT)tcrop(r, 0, 0xffff);
- outPix->g = (USHORT)tcrop(g, 0, 0xffff);
- outPix->b = (USHORT)tcrop(b, 0, 0xffff);
- outPix->m = (USHORT)tcrop(m, 0, 0xffff);
-
- FOR_EACH_PIXEL_64_END_LOOP
- } else {
- TRasterGR8P up8 = rup;
- TRasterGR8P down8 = rdown;
- TRasterGR8P out8 = rout;
+ return;
+ }
- if (up8 && down8 && out8) {
- FOR_EACH_PIXEL_8_BEGIN_LOOP
+ TRaster64P up64 = rup;
+ TRaster64P down64 = rdown;
+ TRaster64P out64 = rout;
- SHORT value = upPix->value - downPix->value;
- outPix->value = (UCHAR)tcrop(value, 0, 255);
+ if (up64 && down64 && out64) {
+ FOR_EACH_PIXEL_64_BEGIN_LOOP
- FOR_EACH_PIXEL_8_END_LOOP
- } else
- throw TRopException("TRop::sub invalid raster combination");
- }
+ TINT32 r = downPix->r - upPix->r;
+ TINT32 g = downPix->g - upPix->g;
+ TINT32 b = downPix->b - upPix->b;
+ TINT32 m = downPix->m; // - upPix->m;
+ outPix->r = (USHORT)tcrop(r, 0, 0xffff);
+ outPix->g = (USHORT)tcrop(g, 0, 0xffff);
+ outPix->b = (USHORT)tcrop(b, 0, 0xffff);
+ outPix->m = (USHORT)tcrop(m, 0, 0xffff);
+
+ FOR_EACH_PIXEL_64_END_LOOP
+ return;
+ }
+
+ TRasterFP upF = rup;
+ TRasterFP downF = rdown;
+ TRasterFP outF = rout;
+
+ if (upF && downF && outF) {
+ FOR_EACH_PIXEL_F_BEGIN_LOOP
+
+ outPix->r = downPix->r - upPix->r;
+ outPix->g = downPix->g - upPix->g;
+ outPix->b = downPix->b - upPix->b;
+ outPix->m = tcrop(downPix->m, 0.f, 1.f);
+
+ FOR_EACH_PIXEL_F_END_LOOP
+ return;
}
+
+ TRasterGR8P up8 = rup;
+ TRasterGR8P down8 = rdown;
+ TRasterGR8P out8 = rout;
+
+ if (up8 && down8 && out8) {
+ FOR_EACH_PIXEL_8_BEGIN_LOOP
+
+ SHORT value = upPix->value - downPix->value;
+ outPix->value = (UCHAR)tcrop(value, 0, 255);
+
+ FOR_EACH_PIXEL_8_END_LOOP
+ return;
+ }
+
+ throw TRopException("TRop::sub invalid raster combination");
}
}
@@ -776,6 +957,76 @@ D_m)
return;
}
+ // 32-bit floating point images case
+ TRasterFP upF = rup, downF = rdown, outF = rout;
+
+ if (upF && downF && outF) {
+ float vf = (float)v / (float)(TPixel32::maxChannelValue);
+
+ if (matte) {
+ float outMf;
+
+ FOR_EACH_PIXEL_F_BEGIN_LOOP
+
+ outMf = downPix->m * upPix->m;
+
+ outPix->r = tcrop((upPix->r / upPix->m + vf) * (downPix->r / downPix->m),
+ 0.f, outMf);
+ outPix->g = tcrop((upPix->g / upPix->m + vf) * (downPix->g / downPix->m),
+ 0.f, outMf);
+ outPix->b = tcrop((upPix->b / upPix->m + vf) * (downPix->b / downPix->m),
+ 0.f, outMf);
+ outPix->m = outMf;
+
+ FOR_EACH_PIXEL_F_END_LOOP
+ } else {
+ float umdmf_norm, outMf;
+ float mSumf, uf, df, ufdf, normalizer;
+
+ FOR_EACH_PIXEL_F_BEGIN_LOOP
+
+ mSumf = upPix->m + downPix->m;
+ if (mSumf > 0.f) {
+ outMf = upPix->m + (1.f - upPix->m) * downPix->m;
+
+ normalizer = outMf / mSumf;
+ umdmf_norm = upPix->m * downPix->m;
+ ;
+
+ uf = upPix->r + vf * umdmf_norm;
+ df = downPix->r;
+ ufdf = uf * df;
+ outPix->r = tcrop(
+ (uf * (1.f - downPix->m) + df * (1.f - upPix->m) + ufdf + ufdf) *
+ normalizer,
+ 0.f, outMf);
+
+ uf = upPix->g + vf * umdmf_norm;
+ df = downPix->g;
+ ufdf = uf * df;
+ outPix->g = tcrop(
+ (uf * (1.f - downPix->m) + df * (1.f - upPix->m) + ufdf + ufdf) *
+ normalizer,
+ 0.f, outMf);
+
+ uf = upPix->b + vf * umdmf_norm;
+ df = downPix->b;
+ ufdf = uf * df;
+ outPix->b = tcrop(
+ (uf * (1.f - downPix->m) + df * (1.f - upPix->m) + ufdf + ufdf) *
+ normalizer,
+ 0.f, outMf);
+
+ outPix->m = outMf;
+ } else
+ *outPix = TPixelF::Transparent;
+
+ FOR_EACH_PIXEL_F_END_LOOP
+ }
+
+ return;
+ }
+
// According to the specifics, throw an exception. I think it's not
// appropriate, though.
throw TRopException("TRop::mult invalid raster combination");
@@ -791,6 +1042,9 @@ void TRop::ropin(const TRasterP &source, const TRasterP &matte,
TRaster64P source64 = source;
TRaster64P matte64 = matte;
TRaster64P out64 = rout;
+ TRasterFP sourceF = source;
+ TRasterFP matteF = matte;
+ TRasterFP outF = rout;
if (source32 && matte32 && out32) {
FOR_EACH_PIXEL_BEGIN_LOOP(TPixelRGBM32, source32, TPixelRGBM32, matte32,
@@ -868,6 +1122,21 @@ outPix_packed_i = _mm_packus_epi16(outPix_packed_i, zeros);
}
FOR_EACH_PIXEL_END_LOOP(source64, matte64, out64)
+ } else if (sourceF && matteF && outF) {
+ FOR_EACH_PIXEL_BEGIN_LOOP(TPixelF, sourceF, TPixelF, matteF, TPixelF, outF)
+
+ if (downPix->m <= 0.f)
+ outPix->r = outPix->g = outPix->b = outPix->m = 0.f;
+ else if (downPix->m >= 1.f)
+ *outPix = *upPix;
+ else {
+ outPix->r = upPix->r * downPix->m;
+ outPix->g = upPix->g * downPix->m;
+ outPix->b = upPix->b * downPix->m;
+ outPix->m = upPix->m * downPix->m;
+ }
+
+ FOR_EACH_PIXEL_END_LOOP(sourceF, matteF, outF)
} else
throw TRopException("TRop::in invalid raster combination");
}
@@ -882,6 +1151,9 @@ void TRop::ropout(const TRasterP &source, const TRasterP &matte,
TRaster64P source64 = source;
TRaster64P matte64 = matte;
TRaster64P out64 = rout;
+ TRasterFP sourceF = source;
+ TRasterFP matteF = matte;
+ TRasterFP outF = rout;
if (source32 && matte32 && out32) {
FOR_EACH_PIXEL_BEGIN_LOOP(TPixelRGBM32, source32, TPixelRGBM32, matte32,
@@ -920,6 +1192,23 @@ void TRop::ropout(const TRasterP &source, const TRasterP &matte,
}
FOR_EACH_PIXEL_END_LOOP(source64, matte64, out64)
+ } else if (sourceF && matteF && outF) {
+ FOR_EACH_PIXEL_BEGIN_LOOP(TPixelF, sourceF, TPixelF, matteF, TPixelF, outF)
+
+ if (downPix->m >= 1.f)
+ outPix->r = outPix->g = outPix->b = outPix->m = 0;
+ else if (downPix->m <= 0.f)
+ *outPix = *upPix;
+ else {
+ float fac = 1.f - downPix->m;
+
+ outPix->r = upPix->r * fac;
+ outPix->g = upPix->g * fac;
+ outPix->b = upPix->b * fac;
+ outPix->m = upPix->m * fac;
+ }
+
+ FOR_EACH_PIXEL_END_LOOP(sourceF, matteF, outF)
} else
throw TRopException("TRop::out invalid raster combination");
}
@@ -937,6 +1226,9 @@ void TRop::atop(const TRasterP &rup, const TRasterP &rdown,
TRaster64P up64 = rup;
TRaster64P down64 = rdown;
TRaster64P out64 = rout;
+ TRasterFP upF = rup;
+ TRasterFP downF = rdown;
+ TRasterFP outF = rout;
if (up32 && down32 && out32) {
FOR_EACH_PIXEL_32_BEGIN_LOOP
@@ -971,6 +1263,19 @@ void TRop::atop(const TRasterP &rup, const TRasterP &rdown,
overPix(*outPix, *downPix, tmpPix);
FOR_EACH_PIXEL_64_END_LOOP
+ } else if (upF && downF && outF) {
+ FOR_EACH_PIXEL_F_BEGIN_LOOP
+
+ TPixelF tmpPix = TPixelF::Transparent;
+ if (downPix->m >= 0.f) {
+ tmpPix.r = upPix->r * downPix->m;
+ tmpPix.g = upPix->g * downPix->m;
+ tmpPix.b = upPix->b * downPix->m;
+ tmpPix.m = upPix->m * downPix->m;
+ }
+
+ overPix(*outPix, *downPix, tmpPix);
+ FOR_EACH_PIXEL_F_END_LOOP
} else
throw TRopException("TRop::atop invalid raster combination");
}
@@ -1031,6 +1336,9 @@ void TRop::crossDissolve(const TRasterP &rup, const TRasterP &rdown,
TRaster64P up64 = rup;
TRaster64P down64 = rdown;
TRaster64P out64 = rout;
+ TRasterFP upF = rup;
+ TRasterFP downF = rdown;
+ TRasterFP outF = rout;
if (up32 && down32 && out32) {
FOR_EACH_PIXEL_32_BEGIN_LOOP
@@ -1052,6 +1360,16 @@ void TRop::crossDissolve(const TRasterP &rup, const TRasterP &rdown,
outPix->m = (upPix->m * vv + downPix->m * (65535 - vv)) / 65535;
FOR_EACH_PIXEL_64_END_LOOP
+ } else if (upF && downF && outF) {
+ float vv = (float)v / 255.0f;
+ FOR_EACH_PIXEL_F_BEGIN_LOOP
+
+ outPix->r = upPix->r * vv + downPix->r * (1.f - vv);
+ outPix->g = upPix->g * vv + downPix->g * (1.f - vv);
+ outPix->b = upPix->b * vv + downPix->b * (1.f - vv);
+ outPix->m = upPix->m * vv + downPix->m * (1.f - vv);
+
+ FOR_EACH_PIXEL_F_END_LOOP
} else
throw TRopException("TRop::crossDissolve invalid raster combination");
}
@@ -1200,59 +1518,102 @@ void TRop::ropmin(const TRasterP &rup, const TRasterP &rdown,
*outPix = *downPix;
FOR_EACH_PIXEL_32_END_LOOP
}
- } else {
- TRaster64P up64 = rup;
- TRaster64P down64 = rdown;
- TRaster64P out64 = rout;
+ return;
+ }
- if (up64 && down64 && out64) {
- if (matte) {
- FOR_EACH_PIXEL_64_BEGIN_LOOP
+ TRaster64P up64 = rup;
+ TRaster64P down64 = rdown;
+ TRaster64P out64 = rout;
+
+ if (up64 && down64 && out64) {
+ if (matte) {
+ FOR_EACH_PIXEL_64_BEGIN_LOOP
+ outPix->r = upPix->r < downPix->r ? upPix->r : downPix->r;
+ outPix->g = upPix->g < downPix->g ? upPix->g : downPix->g;
+ outPix->b = upPix->b < downPix->b ? upPix->b : downPix->b;
+ outPix->m = upPix->m < downPix->m ? upPix->m : downPix->m;
+
+ FOR_EACH_PIXEL_64_END_LOOP
+ } else {
+ FOR_EACH_PIXEL_32_BEGIN_LOOP
+ if (upPix->m >= 65535) {
outPix->r = upPix->r < downPix->r ? upPix->r : downPix->r;
outPix->g = upPix->g < downPix->g ? upPix->g : downPix->g;
outPix->b = upPix->b < downPix->b ? upPix->b : downPix->b;
outPix->m = upPix->m < downPix->m ? upPix->m : downPix->m;
- FOR_EACH_PIXEL_64_END_LOOP
- } else {
- FOR_EACH_PIXEL_32_BEGIN_LOOP
- if (upPix->m >= 65535) {
- outPix->r = upPix->r < downPix->r ? upPix->r : downPix->r;
- outPix->g = upPix->g < downPix->g ? upPix->g : downPix->g;
- outPix->b = upPix->b < downPix->b ? upPix->b : downPix->b;
- outPix->m = upPix->m < downPix->m ? upPix->m : downPix->m;
-
- } else if (upPix->m) {
- TPixel32 tmp;
- tmp.r = upPix->r < downPix->r ? upPix->r : downPix->r;
- tmp.g = upPix->g < downPix->g ? upPix->g : downPix->g;
- tmp.b = upPix->b < downPix->b ? upPix->b : downPix->b;
- // tmp.m = upPix->m < downPix->m ? upPix->m : downPix->m;
- outPix->r = upPix->m * (tmp.r - downPix->r) / 65535.0 + downPix->r;
- outPix->g = upPix->m * (tmp.g - downPix->g) / 65535.0 + downPix->g;
- outPix->b = upPix->m * (tmp.b - downPix->b) / 65535.0 + downPix->b;
- outPix->m = upPix->m * (tmp.m - downPix->m) / 65535.0 + downPix->m;
- } else
- *outPix = *downPix;
- FOR_EACH_PIXEL_32_END_LOOP
- }
- } else {
- TRasterGR8P up8 = rup;
- TRasterGR8P down8 = rdown;
- TRasterGR8P out8 = rout;
+ } else if (upPix->m) {
+ TPixel32 tmp;
+ tmp.r = upPix->r < downPix->r ? upPix->r : downPix->r;
+ tmp.g = upPix->g < downPix->g ? upPix->g : downPix->g;
+ tmp.b = upPix->b < downPix->b ? upPix->b : downPix->b;
+ // tmp.m = upPix->m < downPix->m ? upPix->m : downPix->m;
+ outPix->r = upPix->m * (tmp.r - downPix->r) / 65535.0 + downPix->r;
+ outPix->g = upPix->m * (tmp.g - downPix->g) / 65535.0 + downPix->g;
+ outPix->b = upPix->m * (tmp.b - downPix->b) / 65535.0 + downPix->b;
+ outPix->m = upPix->m * (tmp.m - downPix->m) / 65535.0 + downPix->m;
+ } else
+ *outPix = *downPix;
+ FOR_EACH_PIXEL_32_END_LOOP
+ }
+ return;
+ }
- if (up8 && down8 && out8) {
- FOR_EACH_PIXEL_8_BEGIN_LOOP
+ TRasterFP upF = rup;
+ TRasterFP downF = rdown;
+ TRasterFP outF = rout;
- outPix->value =
- upPix->value < downPix->value ? upPix->value : downPix->value;
+ if (upF && downF && outF) {
+ if (matte) {
+ FOR_EACH_PIXEL_F_BEGIN_LOOP
- FOR_EACH_PIXEL_8_END_LOOP
+ outPix->r = upPix->r < downPix->r ? upPix->r : downPix->r;
+ outPix->g = upPix->g < downPix->g ? upPix->g : downPix->g;
+ outPix->b = upPix->b < downPix->b ? upPix->b : downPix->b;
+ outPix->m = upPix->m < downPix->m ? upPix->m : downPix->m;
+
+ FOR_EACH_PIXEL_F_END_LOOP
+ } else {
+ FOR_EACH_PIXEL_F_BEGIN_LOOP
+ if (upPix->m >= 1.f) {
+ outPix->r = upPix->r < downPix->r ? upPix->r : downPix->r;
+ outPix->g = upPix->g < downPix->g ? upPix->g : downPix->g;
+ outPix->b = upPix->b < downPix->b ? upPix->b : downPix->b;
+ outPix->m = upPix->m < downPix->m ? upPix->m : downPix->m;
+
+ } else if (upPix->m > 0.f) {
+ TPixelF tmp;
+ tmp.r = upPix->r < downPix->r ? upPix->r : downPix->r;
+ tmp.g = upPix->g < downPix->g ? upPix->g : downPix->g;
+ tmp.b = upPix->b < downPix->b ? upPix->b : downPix->b;
+ // tmp.m = upPix->m < downPix->m ? upPix->m : downPix->m;
+ outPix->r = upPix->m * (tmp.r - downPix->r) + downPix->r;
+ outPix->g = upPix->m * (tmp.g - downPix->g) + downPix->g;
+ outPix->b = upPix->m * (tmp.b - downPix->b) + downPix->b;
+ outPix->m = upPix->m * (tmp.m - downPix->m) + downPix->m;
} else
- throw TRopException("TRop::min invalid raster combination");
+ *outPix = *downPix;
+ FOR_EACH_PIXEL_F_END_LOOP
}
+ return;
+ }
+
+ TRasterGR8P up8 = rup;
+ TRasterGR8P down8 = rdown;
+ TRasterGR8P out8 = rout;
+
+ if (up8 && down8 && out8) {
+ FOR_EACH_PIXEL_8_BEGIN_LOOP
+
+ outPix->value =
+ upPix->value < downPix->value ? upPix->value : downPix->value;
+
+ FOR_EACH_PIXEL_8_END_LOOP
+ return;
}
+
+ throw TRopException("TRop::min invalid raster combination");
}
//-----------------------------------------------------------------------------
@@ -1272,39 +1633,56 @@ void TRop::ropmax(const TRasterP &rup, const TRasterP &rdown,
outPix->m = upPix->m > downPix->m ? upPix->m : downPix->m;
FOR_EACH_PIXEL_32_END_LOOP
- } else {
- TRaster64P up64 = rup;
- TRaster64P down64 = rdown;
- TRaster64P out64 = rout;
+ return;
+ }
+ TRaster64P up64 = rup;
+ TRaster64P down64 = rdown;
+ TRaster64P out64 = rout;
- if (up64 && down64 && out64) {
- FOR_EACH_PIXEL_64_BEGIN_LOOP
+ if (up64 && down64 && out64) {
+ FOR_EACH_PIXEL_64_BEGIN_LOOP
- outPix->r = upPix->r > downPix->r ? upPix->r : downPix->r;
- outPix->g = upPix->g > downPix->g ? upPix->g : downPix->g;
- outPix->b = upPix->b > downPix->b ? upPix->b : downPix->b;
- outPix->m = upPix->m > downPix->m ? upPix->m : downPix->m;
+ outPix->r = upPix->r > downPix->r ? upPix->r : downPix->r;
+ outPix->g = upPix->g > downPix->g ? upPix->g : downPix->g;
+ outPix->b = upPix->b > downPix->b ? upPix->b : downPix->b;
+ outPix->m = upPix->m > downPix->m ? upPix->m : downPix->m;
- FOR_EACH_PIXEL_64_END_LOOP
- } else {
- TRasterGR8P up8 = rup;
- TRasterGR8P down8 = rdown;
- TRasterGR8P out8 = rout;
+ FOR_EACH_PIXEL_64_END_LOOP
+ return;
+ }
+ TRasterFP upF = rup;
+ TRasterFP downF = rdown;
+ TRasterFP outF = rout;
- if (up8 && down8 && out8) {
- FOR_EACH_PIXEL_8_BEGIN_LOOP
+ if (upF && downF && outF) {
+ FOR_EACH_PIXEL_F_BEGIN_LOOP
+
+ outPix->r = upPix->r > downPix->r ? upPix->r : downPix->r;
+ outPix->g = upPix->g > downPix->g ? upPix->g : downPix->g;
+ outPix->b = upPix->b > downPix->b ? upPix->b : downPix->b;
+ outPix->m = upPix->m > downPix->m ? upPix->m : downPix->m;
- outPix->value =
- upPix->value > downPix->value ? upPix->value : downPix->value;
+ FOR_EACH_PIXEL_F_END_LOOP
+ return;
+ }
+ TRasterGR8P up8 = rup;
+ TRasterGR8P down8 = rdown;
+ TRasterGR8P out8 = rout;
- FOR_EACH_PIXEL_8_END_LOOP
- } else
- throw TRopException("TRop::max invalid raster combination");
- }
+ if (up8 && down8 && out8) {
+ FOR_EACH_PIXEL_8_BEGIN_LOOP
+
+ outPix->value =
+ upPix->value > downPix->value ? upPix->value : downPix->value;
+
+ FOR_EACH_PIXEL_8_END_LOOP
+ return;
}
+
+ throw TRopException("TRop::max invalid raster combination");
}
//-----------------------------------------------------------------------------
-
+/*
void TRop::linearburn(const TRasterP &rup, const TRasterP &rdown,
const TRasterP &rout) {
TRaster32P up32 = rup;
@@ -1497,12 +1875,14 @@ void TRop::overlay(const TRasterP &rup, const TRasterP &rdown,
}
}
}
-
+*/
//-----------------------------------------------------------------------------
void TRop::premultiply(const TRasterP &ras) {
ras->lock();
TRaster32P ras32 = ras;
+ TRaster64P ras64 = ras;
+ TRasterFP rasF = ras;
if (ras32) {
TPixel32 *endPix, *upPix = 0, *upRow = ras32->pixels();
TPixel32 *lastPix =
@@ -1517,27 +1897,39 @@ void TRop::premultiply(const TRasterP &ras) {
}
upRow += ras32->getWrap();
}
- } else {
- TRaster64P ras64 = ras;
- if (ras64) {
- TPixel64 *endPix, *upPix = 0, *upRow = ras64->pixels();
- TPixel64 *lastPix =
- upRow + ras64->getWrap() * (ras64->getLy() - 1) + ras64->getLx();
+ } else if (ras64) {
+ TPixel64 *endPix, *upPix = 0, *upRow = ras64->pixels();
+ TPixel64 *lastPix =
+ upRow + ras64->getWrap() * (ras64->getLy() - 1) + ras64->getLx();
- while (upPix < lastPix) {
- upPix = upRow;
- endPix = upPix + ras64->getLx();
- while (upPix < endPix) {
- premult(*upPix);
- ++upPix;
- }
- upRow += ras64->getWrap();
+ while (upPix < lastPix) {
+ upPix = upRow;
+ endPix = upPix + ras64->getLx();
+ while (upPix < endPix) {
+ premult(*upPix);
+ ++upPix;
}
- } else {
- ras->unlock();
- throw TException("TRop::premultiply invalid raster type");
+ upRow += ras64->getWrap();
}
+ } else if (rasF) {
+ TPixelF *endPix, *upPix = nullptr, *upRow = rasF->pixels();
+ TPixelF *lastPix =
+ upRow + rasF->getWrap() * (rasF->getLy() - 1) + rasF->getLx();
+
+ while (upPix < lastPix) {
+ upPix = upRow;
+ endPix = upPix + rasF->getLx();
+ while (upPix < endPix) {
+ premult(*upPix);
+ ++upPix;
+ }
+ upRow += rasF->getWrap();
+ }
+ } else {
+ ras->unlock();
+ throw TException("TRop::premultiply invalid raster type");
}
+
ras->unlock();
}
@@ -1546,6 +1938,8 @@ void TRop::premultiply(const TRasterP &ras) {
void TRop::depremultiply(const TRasterP &ras) {
ras->lock();
TRaster32P ras32 = ras;
+ TRaster64P ras64 = ras;
+ TRasterFP rasF = ras;
if (ras32) {
TPixel32 *endPix, *upPix = 0, *upRow = ras32->pixels();
TPixel32 *lastPix =
@@ -1560,26 +1954,37 @@ void TRop::depremultiply(const TRasterP &ras) {
}
upRow += ras32->getWrap();
}
- } else {
- TRaster64P ras64 = ras;
- if (ras64) {
- TPixel64 *endPix, *upPix = 0, *upRow = ras64->pixels();
- TPixel64 *lastPix =
- upRow + ras64->getWrap() * (ras64->getLy() - 1) + ras64->getLx();
+ } else if (ras64) {
+ TPixel64 *endPix, *upPix = 0, *upRow = ras64->pixels();
+ TPixel64 *lastPix =
+ upRow + ras64->getWrap() * (ras64->getLy() - 1) + ras64->getLx();
- while (upPix < lastPix) {
- upPix = upRow;
- endPix = upPix + ras64->getLx();
- while (upPix < endPix) {
- if (upPix->m != 0) depremult(*upPix);
- ++upPix;
- }
- upRow += ras64->getWrap();
+ while (upPix < lastPix) {
+ upPix = upRow;
+ endPix = upPix + ras64->getLx();
+ while (upPix < endPix) {
+ if (upPix->m != 0) depremult(*upPix);
+ ++upPix;
}
- } else {
- ras->unlock();
- throw TException("TRop::depremultiply invalid raster type");
+ upRow += ras64->getWrap();
+ }
+ } else if (rasF) {
+ TPixelF *endPix, *upPix = nullptr, *upRow = rasF->pixels();
+ TPixelF *lastPix =
+ upRow + rasF->getWrap() * (rasF->getLy() - 1) + rasF->getLx();
+
+ while (upPix < lastPix) {
+ upPix = upRow;
+ endPix = upPix + rasF->getLx();
+ while (upPix < endPix) {
+ if (upPix->m > 0.f) depremult(*upPix);
+ ++upPix;
+ }
+ upRow += rasF->getWrap();
}
+ } else {
+ ras->unlock();
+ throw TException("TRop::depremultiply invalid raster type");
}
ras->unlock();
}
@@ -1651,6 +2056,8 @@ void TRop::expandColor(const TRaster32P &ras32, bool precise) {
void TRop::whiteTransp(const TRasterP &ras) {
ras->lock();
TRaster32P ras32 = ras;
+ TRaster64P ras64 = ras;
+ TRasterFP rasF = ras;
if (ras32) {
TPixel32 *endPix, *upPix = 0, *upRow = ras32->pixels();
TPixel32 *lastPix =
@@ -1665,26 +2072,40 @@ void TRop::whiteTransp(const TRasterP &ras) {
}
upRow += ras32->getWrap();
}
- } else {
- TRaster64P ras64 = ras;
- if (ras64) {
- TPixel64 *endPix, *upPix = 0, *upRow = ras64->pixels();
- TPixel64 *lastPix =
- upRow + ras64->getWrap() * (ras64->getLy() - 1) + ras64->getLx();
+ } else if (ras64) {
+ TPixel64 *endPix, *upPix = 0, *upRow = ras64->pixels();
+ TPixel64 *lastPix =
+ upRow + ras64->getWrap() * (ras64->getLy() - 1) + ras64->getLx();
- while (upPix < lastPix) {
- upPix = upRow;
- endPix = upPix + ras64->getLx();
- while (upPix < endPix) {
- if (*upPix == TPixel64::White) *upPix = TPixel64::Transparent;
- ++upPix;
- }
- upRow += ras64->getWrap();
+ while (upPix < lastPix) {
+ upPix = upRow;
+ endPix = upPix + ras64->getLx();
+ while (upPix < endPix) {
+ if (*upPix == TPixel64::White) *upPix = TPixel64::Transparent;
+ ++upPix;
}
- } else {
- ras->unlock();
- throw TException("TRop::premultiply invalid raster type");
+ upRow += ras64->getWrap();
+ }
+ } else if (rasF) {
+ TPixelF *endPix, *upPix = 0, *upRow = rasF->pixels();
+ TPixelF *lastPix =
+ upRow + rasF->getWrap() * (rasF->getLy() - 1) + rasF->getLx();
+
+ while (upPix < lastPix) {
+ upPix = upRow;
+ endPix = upPix + rasF->getLx();
+ while (upPix < endPix) {
+ if ((*upPix).r >= TPixelF::maxChannelValue &&
+ (*upPix).g >= TPixelF::maxChannelValue &&
+ (*upPix).b >= TPixelF::maxChannelValue)
+ *upPix = TPixelF::Transparent;
+ ++upPix;
+ }
+ upRow += rasF->getWrap();
}
+ } else {
+ ras->unlock();
+ throw TException("TRop::premultiply invalid raster type");
}
ras->unlock();
}
diff --git a/toonz/sources/common/trop/tover.cpp b/toonz/sources/common/trop/tover.cpp
index aae900f..1be7f0f 100644
--- a/toonz/sources/common/trop/tover.cpp
+++ b/toonz/sources/common/trop/tover.cpp
@@ -250,6 +250,28 @@ void do_over(TRasterGR8P rout, const TRaster32P &rup) {
}
}
+//-----------------------------------------------------------------------------
+
+void do_over(TRasterFP rout, const TRasterFP &rup) {
+ assert(rout->getSize() == rup->getSize());
+ for (int y = 0; y < rout->getLy(); y++) {
+ TPixelF *out_pix = rout->pixels(y);
+ TPixelF *const out_end = out_pix + rout->getLx();
+ const TPixelF *up_pix = rup->pixels(y);
+
+ for (; out_pix < out_end; ++out_pix, ++up_pix) {
+ if (up_pix->m >= 1.f)
+ *out_pix = *up_pix;
+ else if (up_pix->m > 0.f) {
+ out_pix->r = up_pix->r + out_pix->r * (1.f - up_pix->m);
+ out_pix->g = up_pix->g + out_pix->g * (1.f - up_pix->m);
+ out_pix->b = up_pix->b + out_pix->b * (1.f - up_pix->m);
+ out_pix->m = up_pix->m + out_pix->m * (1.f - up_pix->m);
+ }
+ }
+ }
+}
+
} // namespace
//-----------------------------------------------------------------------------
@@ -325,6 +347,7 @@ void TRop::over(const TRasterP &rout, const TRasterP &rup, const TPoint &pos) {
TRaster32P rout32 = cRout, rup32 = cRup;
TRaster64P rout64 = cRout, rup64 = cRup;
+ TRasterFP routF = cRout, rupF = cRup;
TRasterGR8P rout8 = cRout, rup8 = cRup;
@@ -356,6 +379,8 @@ void TRop::over(const TRasterP &rout, const TRasterP &rup, const TPoint &pos) {
TRop::copy(rout8, rup8);
else if (routCM32 && rupCM32)
do_over(routCM32, rupCM32);
+ else if (routF && rupF)
+ do_over(routF, rupF);
else {
rout->unlock();
rup->unlock();
diff --git a/toonz/sources/common/trop/traylit.cpp b/toonz/sources/common/trop/traylit.cpp
index a0a09c9..cbde86d 100644
--- a/toonz/sources/common/trop/traylit.cpp
+++ b/toonz/sources/common/trop/traylit.cpp
@@ -151,7 +151,7 @@ of the ray we're tracing
(rayPos.x * ratio *
pow((double)(sq(rayPos.x * ratio) +
sq(rayPos.y * ratio) + sq_z),
- decay)) +
+ decay)) +
0.5); // * ^-d... 0.5 rounds
}
} else
@@ -187,6 +187,176 @@ of the ray we're tracing
}
}
+// specialization for floating point pixel
+
+template <>
+void performStandardRaylit(TPixelF *bufIn, TPixelF *bufOut, int dxIn,
+ int dyIn, int dxOut, int dyOut,
+ const TRect &srcRect, const TRect &dstRect,
+ const TRop::RaylitParams ¶ms) {
+ /* NOTATION: Diagram assuming octant 1
+
+ / |
+ / |
+/ - ray_final_y | octLy
+/ 1 |
++---- |
+_____ octLx
+
+
+So, octLx and octLy are the octant's lx and ly; ray_final_y is the final height
+of the ray we're tracing
+*/
+
+ // Build colors-related variables
+ float max = TPixelF::maxChannelValue;
+ /*-- 透明部分の色 --*/
+ float transp_val = (params.m_invert) ? max : 0.f,
+ opaque_val = max - transp_val;
+ float value, val_r, val_g, val_b, val_m;
+ double lightness, r_fac, g_fac, b_fac, m_fac;
+ /*-- 8bit/ 32bit-Float の違いを吸収する係数 --*/
+ double factor = max / 255.0;
+
+ // NOTE: These variable initializations are, well,
+ // heuristic at least. They were probably tested
+ // to be good, but didn't quite make any REAL sense.
+ // They could be done MUCH better, but changing them
+ // would alter the way raylit has been applied until now.
+ // Should be changed at some point, though...
+
+ double scale = params.m_scale;
+ double decay = log(params.m_decay / 100.0 + 1.0) + 1.0;
+ double intensity = 1e8 * log(params.m_intensity / 100.0 + 1.0) / scale;
+ double smoothness = log(params.m_smoothness * 5.0 / 100.0 + 1.0);
+ double radius = params.m_radius;
+
+ /*-- 1ステップ進んだ時、次のピクセルで光源が無かったときの光の弱まる割合 --*/
+ double neg_delta_p = smoothness * intensity;
+ /*-- 1ステップ進んだ時、次のピクセルで光源が有ったときの光の強まる割合 --*/
+ double quot_delta_p = intensity / max; //
+
+ /*--
+ * m_colorはRaylitFxのColor値。r_fac、g_fac、b_facは各チャンネルをPremultiplyした値
+ * --*/
+ TPixelF colorF = toPixelF(params.m_color);
+ m_fac = colorF.m;
+ r_fac = m_fac * colorF.r;
+ g_fac = m_fac * colorF.g;
+ b_fac = m_fac * colorF.b;
+
+ // Geometry-related variables
+ int x, y, ray_final_y;
+ int octLx = dstRect.x1 - dstRect.x0;
+
+ double rayPosIncrementX = 1.0 / scale;
+
+ double sq_z = sq(params.m_lightOriginSrc.z); // We'll be making square
+ // distances from p, so square
+ // it once now
+
+ // Perform raylit
+ TPixelF *pixIn, *pixOut;
+
+ for (ray_final_y = 0; ray_final_y < octLx; ++ray_final_y) {
+ // Initialize increment variables
+ lightness = 0.0;
+
+ double rayPosIncrementY = rayPosIncrementX * (ray_final_y / (double)octLx);
+
+ // Use an integer counter to know when y must increase. Will add ray_final_y
+ // as long as
+ // a multiple of octLx-1 is reached, then increase
+ int yIncrementCounter = 0, yIncrementThreshold = octLx - 1;
+
+ // Trace a single ray of light
+ TPointD rayPos(rayPosIncrementX, rayPosIncrementY);
+
+ for (x = dstRect.x0, y = dstRect.y0, pixIn = bufIn, pixOut = bufOut;
+ (x < dstRect.x1) && (y < dstRect.y1); ++x) {
+ bool insideSrc = (x >= srcRect.x0) && (x < srcRect.x1) &&
+ (y >= srcRect.y0) && (y < srcRect.y1);
+ if (insideSrc) {
+ // Add a light component depending on source's matte
+ if (areAlmostEqual((double)pixIn->m, (double)opaque_val))
+ lightness = std::max(
+ 0.0, lightness - neg_delta_p); // No light source - ray fading
+ else {
+ if (areAlmostEqual((double)pixIn->m, (double)transp_val))
+ lightness += intensity; // Full light source - ray enforcing
+ else
+ lightness = std::max(
+ 0.0, lightness + // Half light source
+ (params.m_invert ? pixIn->m : (max - pixIn->m)) *
+ quot_delta_p); // matte-linear enforcing
+ }
+
+ if (params.m_includeInput) {
+ val_r = pixIn->r;
+ val_g = pixIn->g;
+ val_b = pixIn->b;
+ val_m = pixIn->m;
+ } else
+ val_r = val_g = val_b = val_m = 0.f;
+ } else {
+ if (!params.m_invert)
+ lightness += intensity;
+ else
+ lightness = std::max(0.0, lightness - neg_delta_p);
+
+ val_r = val_g = val_b = val_m = 0.f;
+ }
+
+ bool insideDst = (x >= 0) && (y >= 0);
+ if (insideDst) {
+ // Write the corresponding destination pixel
+ if (lightness > 0.0) {
+ if (radius == 0.0) {
+ value =
+ factor * lightness /
+ (rayPos.x * pow((double)(sq(rayPos.x) + sq(rayPos.y) + sq_z),
+ decay)); // * ^-d...
+ } else {
+ double ratio = std::max(0.001, 1.0 - radius / norm(rayPos));
+ value = factor * lightness /
+ (rayPos.x * ratio *
+ pow((double)(sq(rayPos.x * ratio) + sq(rayPos.y * ratio) +
+ sq_z),
+ decay)); // * ^-d...
+ }
+ } else
+ value = 0.f;
+
+ // NOTE: pow() could be slow. If that is the case, it could be cached
+ // for the whole octant along the longest ray at integer positions,
+ // and then linearly interpolated between those... Have to profile this
+ // before resorting to that...
+
+ val_r += value * r_fac;
+ val_g += value * g_fac;
+ val_b += value * b_fac;
+ val_m += value * m_fac;
+
+ pixOut->r = val_r;
+ pixOut->g = val_g;
+ pixOut->b = val_b;
+ pixOut->m = (val_m > max) ? max : val_m;
+ }
+
+ // Increment variables along the x-axis
+ pixIn += dxIn, pixOut += dxOut;
+
+ rayPos.x += rayPosIncrementX, rayPos.y += rayPosIncrementY;
+
+ // Increment variables along the y-axis
+ if ((yIncrementCounter += ray_final_y) >= yIncrementThreshold) {
+ ++y, pixIn += dyIn, pixOut += dyOut;
+ yIncrementCounter -= yIncrementThreshold;
+ }
+ }
+ }
+}
+
//--------------------------------------------------------------------------------------------
template
@@ -322,6 +492,141 @@ void performColorRaylit(T *bufIn, T *bufOut, int dxIn, int dyIn, int dxOut,
}
}
+// specialization for floating point pixel
+
+template <>
+void performColorRaylit(TPixelF *bufIn, TPixelF *bufOut, int dxIn,
+ int dyIn, int dxOut, int dyOut,
+ const TRect &srcRect, const TRect &dstRect,
+ const TRop::RaylitParams ¶ms) {
+ // Build colors-related variables
+ float max = TPixelF::maxChannelValue;
+
+ float val_r, val_g, val_b, val_m;
+ double lightness_r, lightness_g, lightness_b;
+ double factor = max / 255.0;
+
+ // NOTE: These variable initializations are, well,
+ // heuristic at least. They were probably tested
+ // to be good, but didn't quite make any REAL sense.
+ // They could be done MUCH better, but changing them
+ // would alter the way raylit has been applied until now.
+ // Should be changed at some point, though...
+
+ double scale = params.m_scale;
+ double decay = log(params.m_decay / 100.0 + 1.0) + 1.0;
+ double intensity = 1e8 * log(params.m_intensity / 100.0 + 1.0) / scale;
+ double smoothness = log(params.m_smoothness * 5.0 / 100.0 + 1.0);
+ double radius = params.m_radius;
+
+ double neg_delta_p =
+ smoothness *
+ intensity; // would alter the way raylit has been applied until now.
+ double quot_delta_p = intensity / max; //
+ // Should be changed at some point, though...
+
+ // Geometry-related variables
+ int x, y, ray_final_y;
+ int octLx = dstRect.x1 - dstRect.x0;
+
+ double rayPosIncrementX = 1.0 / scale;
+
+ double fac, sq_z = sq(params.m_lightOriginSrc.z); // We'll be making square
+ // distances from p, so
+ // square it once now
+
+ // Perform raylit
+ TPixelF *pixIn, *pixOut;
+
+ for (ray_final_y = 0; ray_final_y < octLx; ++ray_final_y) {
+ // Initialize increment variables
+ lightness_r = lightness_g = lightness_b = 0.0;
+ double l, l_max;
+
+ double rayPosIncrementY = rayPosIncrementX * (ray_final_y / (double)octLx);
+
+ // Use an integer counter to know when y must increase. Will add ray_final_y
+ // as long as
+ // a multiple of octLx-1 is reached, then increase
+ int yIncrementCounter = 0, yIncrementThreshold = octLx - 1;
+
+ // Trace a single ray of light
+ TPointD rayPos(rayPosIncrementX, rayPosIncrementY);
+
+ for (x = dstRect.x0, y = dstRect.y0, pixIn = bufIn, pixOut = bufOut;
+ (x < dstRect.x1) && (y < dstRect.y1); ++x) {
+ bool insideSrc = (x >= srcRect.x0) && (x < srcRect.x1) &&
+ (y >= srcRect.y0) && (y < srcRect.y1);
+ if (insideSrc) {
+ val_r = pixIn->r;
+ val_g = pixIn->g;
+ val_b = pixIn->b;
+ val_m = pixIn->m;
+
+ lightness_r = std::max(0.0, val_r ? lightness_r + val_r * quot_delta_p
+ : lightness_r - neg_delta_p);
+ lightness_g = std::max(0.0, val_g ? lightness_g + val_g * quot_delta_p
+ : lightness_g - neg_delta_p);
+ lightness_b = std::max(0.0, val_b ? lightness_b + val_b * quot_delta_p
+ : lightness_b - neg_delta_p);
+
+ if (!params.m_includeInput) val_r = val_g = val_b = val_m = 0.f;
+ } else {
+ lightness_r = std::max(0.0, lightness_r - neg_delta_p);
+ lightness_g = std::max(0.0, lightness_g - neg_delta_p);
+ lightness_b = std::max(0.0, lightness_b - neg_delta_p);
+
+ val_r = val_g = val_b = val_m = 0.f;
+ }
+
+ bool insideDst = (x >= 0) && (y >= 0);
+ if (insideDst) {
+ // Write the corresponding destination pixel
+ if (radius == 0.0) {
+ fac = factor /
+ (rayPos.x *
+ pow((double)(sq(rayPos.x) + sq(rayPos.y) + sq_z), decay));
+ } else {
+ double ratio = std::max(0.001, 1.0 - radius / norm(rayPos));
+ fac =
+ factor /
+ (rayPos.x * ratio *
+ pow((double)(sq(rayPos.x * ratio) + sq(rayPos.y * ratio) + sq_z),
+ decay));
+ }
+
+ // NOTE: pow() could be slow. If that is the case, it could be cached
+ // for the whole octant along the longest ray at integer positions,
+ // and then linearly interpolated between those... Have to profile this
+ // before resorting to that...
+
+ val_r += l = fac * lightness_r;
+ l_max = l;
+ val_g += l = fac * lightness_g;
+ l_max = std::max(l, l_max);
+ val_b += l = fac * lightness_b;
+ l_max = std::max(l, l_max);
+ val_m += l_max;
+
+ pixOut->r = val_r;
+ pixOut->g = val_g;
+ pixOut->b = val_b;
+ pixOut->m = (val_m > max) ? max : val_m;
+ }
+
+ // Increment variables along the x-axis
+ pixIn += dxIn, pixOut += dxOut;
+
+ rayPos.x += rayPosIncrementX, rayPos.y += rayPosIncrementY;
+
+ // Increment variables along the y-axis
+ if ((yIncrementCounter += ray_final_y) >= yIncrementThreshold) {
+ ++y, pixIn += dyIn, pixOut += dyOut;
+ yIncrementCounter -= yIncrementThreshold;
+ }
+ }
+ }
+}
//--------------------------------------------------------------------------------------------
/*-- ピザ状に8分割された領域の1つを計算する --*/
template
@@ -461,6 +766,8 @@ void TRop::raylit(const TRasterP &dstRas, const TRasterP &srcRas,
else if ((TRaster64P)dstRas && (TRaster64P)srcRas)
doRaylit(srcRas, dstRas, params,
&performStandardRaylit);
+ else if ((TRasterFP)dstRas && (TRasterFP)srcRas)
+ doRaylit(srcRas, dstRas, params, &performStandardRaylit);
else
throw TException("TRop::raylit unsupported pixel type");
}
@@ -473,6 +780,8 @@ void TRop::glassRaylit(const TRasterP &dstRas, const TRasterP &srcRas,
doRaylit(srcRas, dstRas, params, &performColorRaylit);
else if ((TRaster64P)dstRas && (TRaster64P)srcRas)
doRaylit(srcRas, dstRas, params, &performColorRaylit);
+ else if ((TRasterFP)dstRas && (TRasterFP)srcRas)
+ doRaylit(srcRas, dstRas, params, &performColorRaylit);
else
throw TException("TRop::raylit unsupported pixel type");
}
diff --git a/toonz/sources/common/trop/tresample.cpp b/toonz/sources/common/trop/tresample.cpp
index fd92cc7..8219a60 100644
--- a/toonz/sources/common/trop/tresample.cpp
+++ b/toonz/sources/common/trop/tresample.cpp
@@ -4,12 +4,12 @@
#include "tpixelgr.h"
#include "quickputP.h"
-//#include "tspecialstyleid.h"
+// #include "tspecialstyleid.h"
#include "tsystem.h"
#include "tcolorstyles.h"
#include "tpixelutils.h"
-//#include "tstopwatch.h"
+// #include "tstopwatch.h"
#ifndef TNZCORE_LIGHT
#include "tpalette.h"
#include "trastercm.h"
@@ -159,7 +159,7 @@ inline TINT32 Double2Int(double val) {
(d2iaux = D, d2iaux += _double2fixmagic, \
(((TINT32 *)&(d2iaux))[iman_] >> _shiftamt))
-//#define USE_DOUBLE_TO_INT
+// #define USE_DOUBLE_TO_INT
//===========================================================================
@@ -598,7 +598,7 @@ static inline void get_flt_fun_rad(TRop::ResampleFilterType flt_type,
break;
}
if (flt_fun) *flt_fun = fun;
- flt_rad = rad;
+ flt_rad = rad;
}
//---------------------------------------------------------------------------
@@ -624,9 +624,9 @@ static FILTER *create_filter(TRop::ResampleFilterType flt_type, double blur,
nodedist_u = blur; /* magnification */
else
nodedist_u = du_dx * blur; /* minification */
- rad_u = flt_rad * nodedist_u;
- rad_x = rad_u * dx_du;
- nodefreq_u = 1 / nodedist_u;
+ rad_u = flt_rad * nodedist_u;
+ rad_x = rad_u * dx_du;
+ nodefreq_u = 1 / nodedist_u;
/*
mu = lu - 1;
*/
@@ -658,11 +658,11 @@ NOT_MORE_THAN(mu, uhi)
if (f->w[uhi]) break;
if (ulo < ulomin) ulomin = ulo;
if (uhi > uhimax) uhimax = uhi;
- n = uhi - ulo + 1;
- if (n > nmax) nmax = n;
- f->first = ulo;
- f->last = uhi;
- norm = 1 / sum;
+ n = uhi - ulo + 1;
+ if (n > nmax) nmax = n;
+ f->first = ulo;
+ f->last = uhi;
+ norm = 1 / sum;
for (u = ulo; u <= uhi; u++) f->w[u] *= (float)norm;
} else {
f->w_base = 0;
@@ -955,7 +955,7 @@ void create_calc(const TRasterPT &rin, int min_pix_ref_u, int max_pix_ref_u,
calc_bytewrap = p_calc_bytewrap;
calc_bytesize = calc_bytewrap * lv; // lv * ceil(lu/8)
if (calc_bytesize > p_calc_allocsize) {
- if (p_calc_allocsize) delete[](p_calc);
+ if (p_calc_allocsize) delete[] (p_calc);
// TMALLOC (*p_calc, calc_bytesize)
p_calc = new UCHAR[calc_bytesize];
assert(p_calc);
@@ -1349,6 +1349,255 @@ void resample_main_rgbm(TRasterPT rout, const TRasterPT &rin,
//---------------------------------------------------------------------------
+template <>
+void resample_main_rgbm(
+ TRasterFP rout, const TRasterFP &rin, const TAffine &aff_xy2uv,
+ const TAffine &aff0_uv2fg, int min_pix_ref_u, int min_pix_ref_v,
+ int max_pix_ref_u, int max_pix_ref_v, int n_pix, int *pix_ref_u,
+ int *pix_ref_v, int *pix_ref_f, int *pix_ref_g, short *filter) {
+ const double max_filter_val = 32767.0;
+
+ const TPixelF *buffer_in;
+ TPixelF *buffer_out;
+ TPixelF *pix_out;
+ int lu, lv, wrap_in, mu, mv;
+ int lx, ly, wrap_out;
+ int out_x, out_y;
+ double out_x_, out_y_;
+ double out_u_, out_v_;
+ int ref_u, ref_v;
+ int pix_u, pix_v;
+ double ref_out_u_, ref_out_v_;
+ double ref_out_f_, ref_out_g_;
+ int ref_out_f, ref_out_g;
+ int pix_out_f, pix_out_g;
+ int filter_mu, filter_mv;
+ UINT inside_limit_u, inside_limit_v;
+ int inside_nonempty;
+ int outside_min_u, outside_min_v;
+ int outside_max_u, outside_max_v;
+ UCHAR *calc;
+ int calc_allocsize;
+ int calc_bytewrap;
+ UCHAR calc_value;
+ bool must_calc;
+ TPixelF pix_value, default_value(0.f, 0.f, 0.f, 0.f);
+ double weight, sum_weights;
+ double inv_sum_weights;
+ float sum_contribs_r, sum_contribs_g, sum_contribs_b, sum_contribs_m;
+ double out_fval_r, out_fval_g, out_fval_b, out_fval_m;
+ double out_value_r, out_value_g, out_value_b, out_value_m;
+ int i;
+
+#ifdef USE_DOUBLE_TO_INT
+ double d2iaux;
+#endif
+
+ if (!(rout->getLx() > 0 && rout->getLy() > 0)) return;
+
+ if (!(rin->getLx() > 0 && rin->getLy() > 0)) {
+ rout->clear();
+ return;
+ }
+
+ calc = 0;
+ calc_allocsize = 0;
+
+ // Create a bit array, each indicating whether a pixel has to be calculated or
+ // not
+ create_calc(rin, min_pix_ref_u, max_pix_ref_u, min_pix_ref_v, max_pix_ref_v,
+ calc, calc_allocsize, calc_bytewrap);
+
+ buffer_in = rin->pixels();
+ buffer_out = rout->pixels();
+ lu = rin->getLx();
+ lx = rout->getLx();
+ lv = rin->getLy();
+ ly = rout->getLy();
+ wrap_in = rin->getWrap();
+ wrap_out = rout->getWrap();
+ mu = lu - 1;
+ mv = lv - 1;
+
+ filter_mu = max_pix_ref_u - min_pix_ref_u;
+ filter_mv = max_pix_ref_v - min_pix_ref_v;
+ inside_limit_u = lu - filter_mu;
+ inside_limit_v = lv - filter_mv;
+ inside_nonempty = (int)inside_limit_u > 0 && (int)inside_limit_v > 0;
+ outside_min_u = -max_pix_ref_u;
+ outside_min_v = -max_pix_ref_v;
+ outside_max_u = mu - min_pix_ref_u;
+ outside_max_v = mv - min_pix_ref_v;
+
+ // For every pixel of the output image
+ for (out_y = 0, out_y_ = 0.5; out_y < ly; out_y++, out_y_ += 1.0) {
+ for (out_x = 0, out_x_ = 0.5; out_x < lx; out_x++, out_x_ += 1.0) {
+ pix_out = buffer_out + out_y * wrap_out + out_x;
+
+ // Take the pre-image of the pixel through the passed affine
+ out_u_ = affMV1(aff_xy2uv, out_x_, out_y_);
+ out_v_ = affMV2(aff_xy2uv, out_x_, out_y_);
+
+ // Convert to integer coordinates
+ ref_u = intLE(out_u_);
+ ref_v = intLE(out_v_);
+
+ // NOTE: The following condition is equivalent to:
+ // (ref_u + min_pix_ref_u >= 0 && ref_v + min_pix_ref_v >= 0 &&
+ // ref_u + max_pix_ref_u < lu && ref_v + max_pix_ref_v < lv)
+ // - since the presence of (UINT) makes integeres < 0 become >> 0
+ if (inside_nonempty && (UINT)(ref_u + min_pix_ref_u) < inside_limit_u &&
+ (UINT)(ref_v + min_pix_ref_v) < inside_limit_v) {
+ // The filter mask starting around (ref_u, ref_v) is completely
+ // contained
+ // in the source raster
+
+ // Get the calculation array mask byte
+ calc_value = calc[(ref_u >> 3) + ref_v * calc_bytewrap];
+ if (calc_value && ((calc_value >> (ref_u & 7)) &
+ 1)) // If the mask bit for this pixel is on
+ {
+ ref_out_u_ = ref_u - out_u_; // Fractionary part of the pre-image
+ ref_out_v_ = ref_v - out_v_;
+ ref_out_f_ = aff0MV1(aff0_uv2fg, ref_out_u_,
+ ref_out_v_); // Make the image of it into fg
+ ref_out_g_ = aff0MV2(aff0_uv2fg, ref_out_u_, ref_out_v_);
+ ref_out_f = tround(ref_out_f_); // Convert to integer coordinates
+ ref_out_g = tround(ref_out_g_);
+
+ sum_weights = 0;
+ sum_contribs_r = 0;
+ sum_contribs_g = 0;
+ sum_contribs_b = 0;
+ sum_contribs_m = 0;
+
+ // Make the weighted sum of source pixels
+ for (i = n_pix - 1; i >= 0; --i) {
+ // Build the weight for this pixel
+ pix_out_f = pix_ref_f[i] + ref_out_f; // image of the integer part
+ // + that of the fractionary
+ // part
+ pix_out_g = pix_ref_g[i] + ref_out_g;
+ weight = (double)filter[pix_out_f] * (double)filter[pix_out_g] /
+ (max_filter_val * max_filter_val);
+
+ // Add the weighted pixel contribute
+ pix_u = pix_ref_u[i] + ref_u;
+ pix_v = pix_ref_v[i] + ref_v;
+
+ pix_value = buffer_in[pix_u + pix_v * wrap_in];
+ sum_contribs_r += pix_value.r * weight;
+ sum_contribs_g += pix_value.g * weight;
+ sum_contribs_b += pix_value.b * weight;
+ sum_contribs_m += pix_value.m * weight;
+ sum_weights += weight;
+ }
+
+ inv_sum_weights = 1.0 / sum_weights;
+ out_fval_r = sum_contribs_r * inv_sum_weights;
+ out_fval_g = sum_contribs_g * inv_sum_weights;
+ out_fval_b = sum_contribs_b * inv_sum_weights;
+ out_fval_m = sum_contribs_m * inv_sum_weights;
+ // notLessThan(0.0, out_fval_r);
+ // notLessThan(0.0, out_fval_g);
+ // notLessThan(0.0, out_fval_b);
+ notLessThan(0.0, out_fval_m);
+ out_value_r = out_fval_r;
+ out_value_g = out_fval_g;
+ out_value_b = out_fval_b;
+ out_value_m = out_fval_m;
+ // notMoreThan(T::maxChannelValue, out_value_r);
+ // notMoreThan(T::maxChannelValue, out_value_g);
+ // notMoreThan(T::maxChannelValue, out_value_b);
+ notMoreThan(1.f, out_value_m);
+ pix_out->r = out_value_r;
+ pix_out->g = out_value_g;
+ pix_out->b = out_value_b;
+ pix_out->m = out_value_m;
+ } else
+ // The pixel is copied from the corresponding source...
+ *pix_out = buffer_in[ref_u + ref_v * wrap_in];
+ } else if (outside_min_u <= ref_u && ref_u <= outside_max_u &&
+ outside_min_v <= ref_v && ref_v <= outside_max_v) {
+ if ((UINT)ref_u >= (UINT)lu || (UINT)ref_v >= (UINT)lv)
+ must_calc = true;
+ else {
+ calc_value = calc[(ref_u >> 3) + ref_v * calc_bytewrap];
+ must_calc = calc_value && ((calc_value >> (ref_u & 7)) & 1);
+ }
+
+ if (must_calc) {
+ ref_out_u_ = ref_u - out_u_;
+ ref_out_v_ = ref_v - out_v_;
+ ref_out_f_ = aff0MV1(aff0_uv2fg, ref_out_u_, ref_out_v_);
+ ref_out_g_ = aff0MV2(aff0_uv2fg, ref_out_u_, ref_out_v_);
+ ref_out_f = tround(ref_out_f_);
+ ref_out_g = tround(ref_out_g_);
+ sum_weights = 0;
+ sum_contribs_r = 0;
+ sum_contribs_g = 0;
+ sum_contribs_b = 0;
+ sum_contribs_m = 0;
+
+ for (i = n_pix - 1; i >= 0; --i) {
+ pix_out_f = pix_ref_f[i] + ref_out_f;
+ pix_out_g = pix_ref_g[i] + ref_out_g;
+ weight = (double)filter[pix_out_f] * (double)filter[pix_out_g] /
+ (max_filter_val * max_filter_val);
+ pix_u = pix_ref_u[i] + ref_u;
+ pix_v = pix_ref_v[i] + ref_v;
+
+ if (pix_u < 0 || pix_u > mu || pix_v < 0 || pix_v > mv) {
+ sum_weights += weight; // 0-padding
+ continue;
+ }
+
+ notLessThan(0, pix_u); // Copy-padding
+ notLessThan(0, pix_v);
+ notMoreThan(mu, pix_u);
+ notMoreThan(mv, pix_v);
+
+ pix_value = buffer_in[pix_u + pix_v * wrap_in];
+ sum_contribs_r += pix_value.r * weight;
+ sum_contribs_g += pix_value.g * weight;
+ sum_contribs_b += pix_value.b * weight;
+ sum_contribs_m += pix_value.m * weight;
+ sum_weights += weight;
+ }
+
+ inv_sum_weights = 1.0 / sum_weights;
+ out_fval_r = sum_contribs_r * inv_sum_weights;
+ out_fval_g = sum_contribs_g * inv_sum_weights;
+ out_fval_b = sum_contribs_b * inv_sum_weights;
+ out_fval_m = sum_contribs_m * inv_sum_weights;
+ // notLessThan(0.0, out_fval_r);
+ // notLessThan(0.0, out_fval_g);
+ // notLessThan(0.0, out_fval_b);
+ notLessThan(0.0, out_fval_m);
+ out_value_r = out_fval_r;
+ out_value_g = out_fval_g;
+ out_value_b = out_fval_b;
+ out_value_m = out_fval_m;
+ // notMoreThan(T::maxChannelValue, out_value_r);
+ // notMoreThan(T::maxChannelValue, out_value_g);
+ // notMoreThan(T::maxChannelValue, out_value_b);
+ notMoreThan(1.f, out_value_m);
+ pix_out->r = out_value_r;
+ pix_out->g = out_value_g;
+ pix_out->b = out_value_b;
+ pix_out->m = out_value_m;
+ } else
+ *pix_out = buffer_in[ref_u + ref_v * wrap_in];
+ } else
+ *pix_out = default_value;
+ }
+ }
+
+ delete[] calc;
+}
+
+//---------------------------------------------------------------------------
+
#ifdef USE_SSE2
namespace {
@@ -1518,74 +1767,75 @@ void resample_main_rgbm_SSE2(TRasterPT rout, const TRasterPT &rin,
} else
*pix_out = buffer_in[ref_u + ref_v * wrap_in];
} else
- // if( outside_min_u_ <= out_u_ && out_u_ <= outside_max_u_ &&
- // outside_min_v_ <= out_v_ && out_v_ <= outside_max_v_ )
- if (outside_min_u <= ref_u && ref_u <= outside_max_u &&
- outside_min_v <= ref_v && ref_v <= outside_max_v) {
- if ((UINT)ref_u >= (UINT)lu || (UINT)ref_v >= (UINT)lv)
- must_calc = true;
- else {
- calc_value = calc[(ref_u >> 3) + ref_v * calc_bytewrap];
- must_calc = calc_value && ((calc_value >> (ref_u & 7)) & 1);
- }
-
- if (must_calc) {
- ref_out_u_ = ref_u - out_u_;
- ref_out_v_ = ref_v - out_v_;
- ref_out_f_ = aff0MV1(aff0_uv2fg, ref_out_u_, ref_out_v_);
- ref_out_g_ = aff0MV2(aff0_uv2fg, ref_out_u_, ref_out_v_);
- ref_out_f = tround(ref_out_f_);
- ref_out_g = tround(ref_out_g_);
- sum_weights = 0;
- sum_contribs_packed = _mm_setzero_ps();
+ // if( outside_min_u_ <= out_u_ && out_u_ <= outside_max_u_ &&
+ // outside_min_v_ <= out_v_ && out_v_ <= outside_max_v_ )
+ if (outside_min_u <= ref_u && ref_u <= outside_max_u &&
+ outside_min_v <= ref_v && ref_v <= outside_max_v) {
+ if ((UINT)ref_u >= (UINT)lu || (UINT)ref_v >= (UINT)lv)
+ must_calc = true;
+ else {
+ calc_value = calc[(ref_u >> 3) + ref_v * calc_bytewrap];
+ must_calc = calc_value && ((calc_value >> (ref_u & 7)) & 1);
+ }
- for (i = n_pix - 1; i >= 0; i--) {
- pix_out_f = pix_ref_f[i] + ref_out_f;
- pix_out_g = pix_ref_g[i] + ref_out_g;
- weight = (float)((filter[pix_out_f] * filter[pix_out_g]) >> 16);
- pix_u = pix_ref_u[i] + ref_u;
- pix_v = pix_ref_v[i] + ref_v;
+ if (must_calc) {
+ ref_out_u_ = ref_u - out_u_;
+ ref_out_v_ = ref_v - out_v_;
+ ref_out_f_ = aff0MV1(aff0_uv2fg, ref_out_u_, ref_out_v_);
+ ref_out_g_ = aff0MV2(aff0_uv2fg, ref_out_u_, ref_out_v_);
+ ref_out_f = tround(ref_out_f_);
+ ref_out_g = tround(ref_out_g_);
+ sum_weights = 0;
+ sum_contribs_packed = _mm_setzero_ps();
+
+ for (i = n_pix - 1; i >= 0; i--) {
+ pix_out_f = pix_ref_f[i] + ref_out_f;
+ pix_out_g = pix_ref_g[i] + ref_out_g;
+ weight = (float)((filter[pix_out_f] * filter[pix_out_g]) >> 16);
+ pix_u = pix_ref_u[i] + ref_u;
+ pix_v = pix_ref_v[i] + ref_v;
+
+ if (pix_u < 0 || pix_u > mu || pix_v < 0 || pix_v > mv) {
+ sum_weights += weight;
+ continue;
+ }
+
+ notLessThan(0, pix_u);
+ notLessThan(0, pix_v);
+ notMoreThan(mu, pix_u);
+ notMoreThan(mv, pix_v);
+
+ pix_value = buffer_in[pix_u + pix_v * wrap_in];
+ pix_value_packed_i = _mm_unpacklo_epi8(
+ _mm_cvtsi32_si128(*(DWORD *)&pix_value), zeros);
+ pix_value_packed = _mm_cvtepi32_ps(
+ _mm_unpacklo_epi16(pix_value_packed_i, zeros));
+
+ weight_packed = _mm_load1_ps(&weight);
+ sum_contribs_packed =
+ _mm_add_ps(sum_contribs_packed,
+ _mm_mul_ps(pix_value_packed, weight_packed));
- if (pix_u < 0 || pix_u > mu || pix_v < 0 || pix_v > mv) {
sum_weights += weight;
- continue;
}
-
- notLessThan(0, pix_u);
- notLessThan(0, pix_v);
- notMoreThan(mu, pix_u);
- notMoreThan(mv, pix_v);
-
- pix_value = buffer_in[pix_u + pix_v * wrap_in];
- pix_value_packed_i = _mm_unpacklo_epi8(
- _mm_cvtsi32_si128(*(DWORD *)&pix_value), zeros);
- pix_value_packed =
- _mm_cvtepi32_ps(_mm_unpacklo_epi16(pix_value_packed_i, zeros));
-
- weight_packed = _mm_load1_ps(&weight);
- sum_contribs_packed =
- _mm_add_ps(sum_contribs_packed,
- _mm_mul_ps(pix_value_packed, weight_packed));
-
- sum_weights += weight;
- }
- inv_sum_weights = 1.0f / sum_weights;
-
- __m128 inv_sum_weights_packed = _mm_load1_ps(&inv_sum_weights);
- __m128 out_fval_packed =
- _mm_mul_ps(sum_contribs_packed, inv_sum_weights_packed);
- out_fval_packed = _mm_max_ps(out_fval_packed, zeros2);
- out_fval_packed = _mm_min_ps(out_fval_packed, maxChanneValue_packed);
-
- __m128i out_value_packed_i = _mm_cvtps_epi32(out_fval_packed);
- out_value_packed_i = _mm_packs_epi32(out_value_packed_i, zeros);
- out_value_packed_i = _mm_packus_epi16(out_value_packed_i, zeros);
- *(DWORD *)(pix_out) = _mm_cvtsi128_si32(out_value_packed_i);
- } else
- *pix_out = buffer_in[ref_u + ref_v * wrap_in];
- } else {
- *pix_out = default_value;
- }
+ inv_sum_weights = 1.0f / sum_weights;
+
+ __m128 inv_sum_weights_packed = _mm_load1_ps(&inv_sum_weights);
+ __m128 out_fval_packed =
+ _mm_mul_ps(sum_contribs_packed, inv_sum_weights_packed);
+ out_fval_packed = _mm_max_ps(out_fval_packed, zeros2);
+ out_fval_packed =
+ _mm_min_ps(out_fval_packed, maxChanneValue_packed);
+
+ __m128i out_value_packed_i = _mm_cvtps_epi32(out_fval_packed);
+ out_value_packed_i = _mm_packs_epi32(out_value_packed_i, zeros);
+ out_value_packed_i = _mm_packus_epi16(out_value_packed_i, zeros);
+ *(DWORD *)(pix_out) = _mm_cvtsi128_si32(out_value_packed_i);
+ } else
+ *pix_out = buffer_in[ref_u + ref_v * wrap_in];
+ } else {
+ *pix_out = default_value;
+ }
}
}
if (calc) delete[] calc;
@@ -1691,9 +1941,9 @@ static void get_prow_gr8(const TRasterGR8P &rin, double a11, double a12,
prow[p] = (float)troundp(
fu * gv *
(((UINT)(u + 1) < lu && (UINT)v < lv) ? in_gr8[du] : BORDER) +
- fu * fv * (((UINT)(u + 1) < lu && (UINT)(v + 1) < lv)
- ? in_gr8[du + dv]
- : BORDER) +
+ fu * fv *
+ (((UINT)(u + 1) < lu && (UINT)(v + 1) < lv) ? in_gr8[du + dv]
+ : BORDER) +
gu * gv * (((UINT)u < lu && (UINT)v < lv) ? in_gr8[0] : BORDER) +
gu * fv *
(((UINT)u < lu && (UINT)(v + 1) < lv) ? in_gr8[dv] : BORDER));
@@ -1714,9 +1964,9 @@ static void get_prow_gr8(const TRasterGR8P &rin, double a11, double a12,
prow[p] = (float)troundp(
fu * gv *
(((UINT)(u + 1) < lu && (UINT)v < lv) ? in_gr8[du] : BORDER) +
- fu * fv * (((UINT)(u + 1) < lu && (UINT)(v + 1) < lv)
- ? in_gr8[du + dv]
- : BORDER) +
+ fu * fv *
+ (((UINT)(u + 1) < lu && (UINT)(v + 1) < lv) ? in_gr8[du + dv]
+ : BORDER) +
gu * gv * (((UINT)u < lu && (UINT)v < lv) ? in_gr8[0] : BORDER) +
gu * fv *
(((UINT)u < lu && (UINT)(v + 1) < lv) ? in_gr8[dv] : BORDER));
@@ -1789,14 +2039,16 @@ static void get_prow_gr8(const TRaster32P &rin, double a11, double a12,
gv = 1. - fv;
in_32 = bufin_32 + (u * du + v * dv);
prow[p] = (float)troundp(
- fu * gv * (((UINT)(u + 1) < lu && (UINT)v < lv) ? grey(in_32[du])
+ fu * gv *
+ (((UINT)(u + 1) < lu && (UINT)v < lv) ? grey(in_32[du])
+ : BORDER) +
+ fu * fv *
+ (((UINT)(u + 1) < lu && (UINT)(v + 1) < lv) ? grey(in_32[du + dv])
: BORDER) +
- fu * fv * (((UINT)(u + 1) < lu && (UINT)(v + 1) < lv)
- ? grey(in_32[du + dv])
- : BORDER) +
gu * gv * (((UINT)u < lu && (UINT)v < lv) ? grey(in_32[0]) : BORDER) +
- gu * fv * (((UINT)u < lu && (UINT)(v + 1) < lv) ? grey(in_32[dv])
- : BORDER));
+ gu * fv *
+ (((UINT)u < lu && (UINT)(v + 1) < lv) ? grey(in_32[dv])
+ : BORDER));
}
p1 = p;
for (p = pmax; p > p1; p--)
@@ -1812,14 +2064,16 @@ static void get_prow_gr8(const TRaster32P &rin, double a11, double a12,
gv = 1. - fv;
in_32 = bufin_32 + (u * du + v * dv);
prow[p] = (float)troundp(
- fu * gv * (((UINT)(u + 1) < lu && (UINT)v < lv) ? grey(in_32[du])
+ fu * gv *
+ (((UINT)(u + 1) < lu && (UINT)v < lv) ? grey(in_32[du])
+ : BORDER) +
+ fu * fv *
+ (((UINT)(u + 1) < lu && (UINT)(v + 1) < lv) ? grey(in_32[du + dv])
: BORDER) +
- fu * fv * (((UINT)(u + 1) < lu && (UINT)(v + 1) < lv)
- ? grey(in_32[du + dv])
- : BORDER) +
gu * gv * (((UINT)u < lu && (UINT)v < lv) ? grey(in_32[0]) : BORDER) +
- gu * fv * (((UINT)u < lu && (UINT)(v + 1) < lv) ? grey(in_32[dv])
- : BORDER));
+ gu * fv *
+ (((UINT)u < lu && (UINT)(v + 1) < lv) ? grey(in_32[dv])
+ : BORDER));
}
p2 = p;
for (p = p1; p <= p2; p++)
@@ -1948,7 +2202,7 @@ TCALLOC (colval, lu);*/
flatcols = 1;
else
flatcols = 0;
- flatval = colval[u];
+ flatval = colval[u];
if (flatcols >= flatdiamu) {
#ifdef VECCHIA_MANIERA
x_ = AFF_M_V_1(aff, u - flatradu, v - flatradv);
@@ -1967,7 +2221,7 @@ TCALLOC (colval, lu);*/
ylo = std::max(0, (int)ylo_);
yhi = std::min(my, (int)yhi_);
for (y = ylo; y <= yhi; y++)
- for (x = xlo; x <= xhi; x++)
+ for (x = xlo; x <= xhi; x++)
bufout_gr8[x + y * wrapout] = flatval, count++;
}
xlo_ += aff.a11;
@@ -2005,7 +2259,7 @@ TCALLOC (colval, lu);*/
nocheight[x] = 0;
}
if (topy < ly && colnoc[topy].first <= topq) {
- for (x = 0; x < lx; x++)
+ for (x = 0; x < lx; x++)
if (nocheight[x] < nocdiamy) xxx[x] = 1.0; /* 1.0 == calc */
} else {
for (x = 0; x < lx; x++) xxx[x] = 1.0; /* 1.0 == calc */
@@ -2020,7 +2274,7 @@ TCALLOC (colval, lu);*/
else {
nocwidth++;
if (nocwidth >= nocdiamx)
- for (p = rownoc[x].first; p <= rownoc[x].last; p++)
+ for (p = rownoc[x].first; p <= rownoc[x].last; p++)
prow[p] = 1.0; /* 1.0 == nocalc */
}
get_prow_gr8(rin, invrot.a11, invrot.a12, invrot.a21, invrot.a22, pmin,
@@ -2157,7 +2411,7 @@ TCALLOC (colval, lu);*/
flatcols = 1;
else
flatcols = 0;
- flatval = colval[u];
+ flatval = colval[u];
if (flatcols >= flatdiamu) {
#ifdef VECCHIA_MANIERA
x_ = AFF_M_V_1(aff, u - flatradu, v - flatradv);
@@ -2176,7 +2430,7 @@ TCALLOC (colval, lu);*/
ylo = std::max(0, (int)ylo_);
yhi = std::min(my, (int)yhi_);
for (y = ylo; y <= yhi; y++)
- for (x = xlo; x <= xhi; x++)
+ for (x = xlo; x <= xhi; x++)
bufout_gr8[x + y * wrapout] = flatval, count++;
}
xlo_ += aff.a11;
@@ -2214,7 +2468,7 @@ TCALLOC (colval, lu);*/
nocheight[x] = 0;
}
if (topy < ly && colnoc[topy].first <= topq) {
- for (x = 0; x < lx; x++)
+ for (x = 0; x < lx; x++)
if (nocheight[x] < nocdiamy) xxx[x] = 1.0; /* 1.0 == calc */
} else {
for (x = 0; x < lx; x++) xxx[x] = 1.0; /* 1.0 == calc */
@@ -2229,7 +2483,7 @@ TCALLOC (colval, lu);*/
else {
nocwidth++;
if (nocwidth >= nocdiamx)
- for (p = rownoc[x].first; p <= rownoc[x].last; p++)
+ for (p = rownoc[x].first; p <= rownoc[x].last; p++)
prow[p] = 1.0; /* 1.0 == nocalc */
}
get_prow_gr8(rin, invrot.a11, invrot.a12, invrot.a21, invrot.a22, pmin,
@@ -2555,7 +2809,7 @@ void rop_resample_rgbm(TRasterPT rout, const TRasterPT &rin,
if (min_pix_out_fg < min_filter_fg) {
int delta = min_filter_fg - min_pix_out_fg;
- for (f = max_filter_fg; f >= min_filter_fg; f--)
+ for (f = max_filter_fg; f >= min_filter_fg; f--)
filter[f + delta] = filter[f];
filter += delta;
for (f = min_filter_fg - 1; f >= min_pix_out_fg; f--) filter[f] = 0;
@@ -2576,7 +2830,12 @@ void rop_resample_rgbm(TRasterPT rout, const TRasterPT &rin,
pix_ref_f.get(), pix_ref_g.get(), filter);
else
#endif
- if (n_pix >= 512 || T::maxChannelValue > 255)
+ if (std::is_same::value)
+ resample_main_rgbm(
+ rout, rin, aff_xy2uv, aff0_uv2fg, min_pix_ref_u, min_pix_ref_v,
+ max_pix_ref_u, max_pix_ref_v, n_pix, pix_ref_u.get(), pix_ref_v.get(),
+ pix_ref_f.get(), pix_ref_g.get(), filter);
+ else if (n_pix >= 512 || T::maxChannelValue > 255)
resample_main_rgbm(
rout, rin, aff_xy2uv, aff0_uv2fg, min_pix_ref_u, min_pix_ref_v,
max_pix_ref_u, max_pix_ref_v, n_pix, pix_ref_u.get(), pix_ref_v.get(),
@@ -3014,7 +3273,7 @@ void do_resample(TRasterCM32P rout, const TRasterCM32P &rin,
tone_tot = 0.0;
some_pencil = false;
for (i = 0; i < 4; i++) {
- tone = tcm[i] & tone_mask;
+ tone = tcm[i] & tone_mask;
if ((TUINT32)tone != tone_mask) some_pencil = true;
tone_tot += tone * w[i];
new_color_blob.val = tcm[i] & color_mask;
@@ -3059,8 +3318,8 @@ void do_resample(TRasterCM32P rout, const TRasterCM32P &rin,
v * wrapin; // Take the associated input pixel pointer
tcm[0] = in_tcm[0];
if (u < lu - 1 && v < lv - 1) {
- // Also take their 4 next neighbours (we shall perform a kind of bilinear
- // interpolation)
+ // Also take their 4 next neighbours (we shall perform a kind of
+ // bilinear interpolation)
tcm[1] = in_tcm[1];
tcm[2] = in_tcm[wrapin];
tcm[3] = in_tcm[wrapin + 1];
@@ -3165,7 +3424,7 @@ void do_resample(TRasterCM32P rout, const TRasterCM32P &rin,
tone_tot = 0.0;
some_pencil = false;
for (i = 0; i < 4; i++) {
- tone = tcm[i] & tone_mask;
+ tone = tcm[i] & tone_mask;
if ((TUINT32)tone != tone_mask) some_pencil = true;
tone_tot += tone * w[i];
new_color_blob.val = tcm[i] & color_mask;
@@ -3586,7 +3845,7 @@ void resample_main_cm32_rgbm_bigradius(
std::vector paints(colorCount);
std::vector inks(colorCount);
- for (i = 0; i < palette->getStyleCount(); i++)
+ for (i = 0; i < palette->getStyleCount(); i++)
paints[i] = inks[i] =
::premultiply(palette->getStyle(i)->getAverageColor());
@@ -3775,7 +4034,7 @@ void resample_main_cm32_rgbm_bigradius(
if (calc) delete[] calc;
}
-}
+} // namespace
/*---------------------------------------------------------------------------*/
@@ -3871,7 +4130,7 @@ void resample_main_cm32_rgbm(TRasterPT rout, const TRasterCM32P &rin,
std::vector paints(colorCount);
std::vector inks(colorCount);
- for (i = 0; i < palette->getStyleCount(); i++)
+ for (i = 0; i < palette->getStyleCount(); i++)
paints[i] = inks[i] =
::premultiply(palette->getStyle(i)->getAverageColor());
@@ -4140,7 +4399,7 @@ resample_main_rgbm_bigradius( rout, rin,
std::vector paints(colorCount);
std::vector inks(colorCount);
- for (i = 0; i < palette->getStyleCount(); i++)
+ for (i = 0; i < palette->getStyleCount(); i++)
paints[i] = inks[i] =
::premultiply(palette->getStyle(i)->getAverageColor());
@@ -4585,7 +4844,7 @@ void rop_resample_rgbm_2(TRasterPT rout, const TRasterCM32P &rin,
if (min_pix_out_fg < min_filter_fg) {
int delta = min_filter_fg - min_pix_out_fg;
- for (f = max_filter_fg; f >= min_filter_fg; f--)
+ for (f = max_filter_fg; f >= min_filter_fg; f--)
filter[f + delta] = filter[f];
filter += delta;
for (f = min_filter_fg - 1; f >= min_pix_out_fg; f--) filter[f] = 0;
@@ -4663,42 +4922,49 @@ void TRop::resample(const TRasterP &rout, const TRasterP &rin,
}
TRaster32P rout32 = rout, rin32 = rin;
+ TRasterCM32P routCM32 = rout, rinCM32 = rin;
+ TRaster64P rout64 = rout, rin64 = rin;
+ TRasterGR8P routGR8 = rout, rinGR8 = rin;
+ TRasterFP routF = rout, rinF = rin;
+
if (rout32) {
if (!rin32) {
rin32 = TRaster32P(rin->getLx(), rin->getLy());
TRop::convert(rin32, rin);
}
do_resample(rout32, rin32, aff, filterType, blur);
- } else {
-#ifndef TNZCORE_LIGHT
- TRasterCM32P routCM32 = rout, rinCM32 = rin;
- if (routCM32 && rinCM32)
- do_resample(routCM32, rinCM32, aff);
- else
-#endif
- {
- TRaster64P rout64 = rout, rin64 = rin;
- if (rout64) {
- if (!rin64) {
- rin64 = TRaster64P(rin->getLx(), rin->getLy());
- TRop::convert(rin64, rin);
- }
- do_resample(rout64, rin64, aff, filterType, blur);
- } else {
- TRasterGR8P routGR8 = rout, rinGR8 = rin;
- TRaster32P rin32 = rin;
- if (routGR8 && rinGR8)
- do_resample(routGR8, rinGR8, aff, filterType, blur);
- else if (routGR8 && rin32)
- do_resample(routGR8, rin32, aff, filterType, blur);
- else {
- rin->unlock();
- rout->unlock();
- throw TRopException("unsupported pixel type");
- }
- }
+ } else if (routCM32 && rinCM32)
+ do_resample(routCM32, rinCM32, aff);
+ else if (rout64) {
+ if (!rin64) {
+ rin64 = TRaster64P(rin->getLx(), rin->getLy());
+ TRop::convert(rin64, rin);
}
+ do_resample(rout64, rin64, aff, filterType, blur);
+ } else if (routGR8) {
+ if (rinGR8)
+ do_resample(routGR8, rinGR8, aff, filterType, blur);
+ else if (routGR8 && rin32)
+ do_resample(routGR8, rin32, aff, filterType, blur);
+ else {
+ rin->unlock();
+ rout->unlock();
+ throw TRopException("unsupported pixel type");
+ }
+ } else if (routF) {
+ if (!rinF) {
+ rinF = TRasterFP(rin->getLx(), rin->getLy());
+ TRop::convert(rinF, rin);
+ }
+ do_resample(routF, rinF, aff, filterType, blur);
+ } else {
+ rin->unlock();
+ rout->unlock();
+ throw TRopException("unsupported pixel type");
}
+
+ rout->setLinear(rin->isLinear());
+
rin->unlock();
rout->unlock();
}
diff --git a/toonz/sources/common/trop/trgbmscale.cpp b/toonz/sources/common/trop/trgbmscale.cpp
index f782d50..50d8d0d 100644
--- a/toonz/sources/common/trop/trgbmscale.cpp
+++ b/toonz/sources/common/trop/trgbmscale.cpp
@@ -24,7 +24,7 @@ void buildLUT(Chan *lut, double a, double k, int chanLow, int chanHigh) {
int i, max = (std::numeric_limits::max)();
a += 0.5; // round rather than trunc
- for (i = 0; i <= max; ++i)
+ for (i = 0; i <= max; ++i)
lut[i] = tcrop((int)(a + i * k), chanLow, chanHigh);
}
@@ -94,18 +94,21 @@ void do_rgbmScale_lut(TRasterPT rout, TRasterPT rin, const double *a,
int out0M = std::max(fac * out0[3], 0),
out1M = std::min(fac * out1[3], T::maxChannelValue);
+ double aFac[4];
+ for (int i = 0; i < 4; i++) aFac[i] = a[i] * (double)fac;
+
// Build luts
Channel *lut_r = new Channel[chanValuesCount];
- buildLUT(lut_r, a[0], k[0], out0R, out1R);
+ buildLUT(lut_r, aFac[0], k[0], out0R, out1R);
Channel *lut_g = new Channel[chanValuesCount];
- buildLUT(lut_g, a[1], k[1], out0G, out1G);
+ buildLUT(lut_g, aFac[1], k[1], out0G, out1G);
Channel *lut_b = new Channel[chanValuesCount];
- buildLUT(lut_b, a[2], k[2], out0B, out1B);
+ buildLUT(lut_b, aFac[2], k[2], out0B, out1B);
Channel *lut_m = new Channel[chanValuesCount];
- buildLUT(lut_m, a[3], k[3], out0M, out1M);
+ buildLUT(lut_m, aFac[3], k[3], out0M, out1M);
// Retrieve de/premultiplication luts
const double *lut_prem = premultiplyTable();
@@ -162,6 +165,9 @@ void do_rgbmScale(TRasterPT rout, TRasterPT rin, const double *a,
const double *lut_deprem = depremultiplyTable();
double premFac, depremFac;
+ double aFac[4];
+ for (int i = 0; i < 4; i++) aFac[i] = a[i] * (double)fac;
+
// Process raster
int y, lx = rin->getLx(), ly = rin->getLy();
T *in, *end, *out;
@@ -169,16 +175,16 @@ void do_rgbmScale(TRasterPT rout, TRasterPT rin, const double *a,
for (y = 0; y < ly; ++y) {
in = rin->pixels(y), end = in + lx, out = rout->pixels(y);
for (; in < end; ++in, ++out) {
- m = tcrop((int)(a[3] + k[3] * in->m), out0M, out1M);
+ m = tcrop((int)(aFac[3] + k[3] * in->m), out0M, out1M);
depremFac = lut_deprem[in->m];
premFac = lut_prem[m];
- out->r =
- premFac * tcrop((int)(a[0] + k[0] * in->r * depremFac), out0R, out1R);
- out->g =
- premFac * tcrop((int)(a[1] + k[1] * in->g * depremFac), out0G, out1G);
- out->b =
- premFac * tcrop((int)(a[2] + k[2] * in->b * depremFac), out0B, out1B);
+ out->r = premFac *
+ tcrop((int)(aFac[0] + k[0] * in->r * depremFac), out0R, out1R);
+ out->g = premFac *
+ tcrop((int)(aFac[1] + k[1] * in->g * depremFac), out0G, out1G);
+ out->b = premFac *
+ tcrop((int)(aFac[2] + k[2] * in->b * depremFac), out0B, out1B);
out->m = m;
}
}
@@ -186,10 +192,103 @@ void do_rgbmScale(TRasterPT rout, TRasterPT rin, const double *a,
//-----------------------------------------------------------------------------
+template <>
+void do_rgbmScale(TRasterFP rout, TRasterFP rin, const double *a,
+ const double *k, const int *out0, const int *out1) {
+ assert(rout->getSize() == rin->getSize());
+
+ float fac = 1.f / 255.f;
+
+ float out0R = std::max(fac * (float)out0[0], 0.f);
+ float out1R = std::min(fac * (float)out1[0], 1.f);
+ float out0G = std::max(fac * (float)out0[1], 0.f);
+ float out1G = std::min(fac * (float)out1[1], 1.f);
+ float out0B = std::max(fac * (float)out0[2], 0.f);
+ float out1B = std::min(fac * (float)out1[2], 1.f);
+ float out0M = std::max(fac * (float)out0[3], 0.f);
+ float out1M = std::min(fac * (float)out1[3], 1.f);
+
+ // Retrieve de/premultiplication luts
+ double premFac, depremFac;
+
+ float aFac[4];
+ for (int i = 0; i < 4; i++) aFac[i] = a[i] * (float)fac;
+
+ // Process raster
+ int y, lx = rin->getLx(), ly = rin->getLy();
+ TPixelF *in, *end, *out;
+ float m;
+
+ for (y = 0; y < ly; ++y) {
+ in = rin->pixels(y), end = in + lx, out = rout->pixels(y);
+ for (; in < end; ++in, ++out) {
+ m = tcrop(aFac[3] + (float)k[3] * in->m, out0M, out1M);
+
+ if (in->m <= 0.f) {
+ out->r = m * tcrop(aFac[0], out0R, out1R);
+ out->g = m * tcrop(aFac[1], out0G, out1G);
+ out->b = m * tcrop(aFac[2], out0B, out1B);
+ out->m = m;
+ } else {
+ out->r = m * tcrop(aFac[0] + (float)k[0] * in->r / in->m, out0R, out1R);
+ out->g = m * tcrop(aFac[1] + (float)k[1] * in->g / in->m, out0G, out1G);
+ out->b = m * tcrop(aFac[2] + (float)k[2] * in->b / in->m, out0B, out1B);
+ out->m = m;
+ }
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+
+void do_rgbmScaleFloat(TRasterFP rout, TRasterFP rin, const double *a,
+ const double *k, const int *out0, const int *out1) {
+ assert(rout->getSize() == rin->getSize());
+ float fac = 1.f / 255.f;
+ float out0R = std::max(fac * (float)out0[0], 0.f);
+ float out1R = fac * (float)out1[0];
+ float out0G = std::max(fac * (float)out0[1], 0.f);
+ float out1G = fac * (float)out1[1];
+ float out0B = std::max(fac * (float)out0[2], 0.f);
+ float out1B = fac * (float)out1[2];
+ float out0M = std::max(fac * (float)out0[3], 0.f);
+ float out1M = fac * (float)out1[3];
+
+ float aFac[4];
+ for (int i = 0; i < 4; i++) aFac[i] = a[i] * fac;
+
+ // Process raster
+ for (int y = 0; y < rin->getLy(); ++y) {
+ TPixelF *in = rin->pixels(y), *out = rout->pixels(y);
+ TPixelF *end = in + rin->getLx();
+ for (; in < end; ++in, ++out) {
+ out->m = tcrop(aFac[3] + (float)k[3] * in->m, out0M, out1M);
+ if (out->m == 0.f) {
+ out->r = 0.f;
+ out->g = 0.f;
+ out->b = 0.f;
+ } else if (in->m == 0.f) {
+ out->r = out->m * tcrop(aFac[0], out0R, out1R);
+ out->g = out->m * tcrop(aFac[1], out0G, out1G);
+ out->b = out->m * tcrop(aFac[2], out0B, out1B);
+ } else {
+ out->r =
+ out->m * tcrop(aFac[0] + (float)k[0] * in->r / in->m, out0R, out1R);
+ out->g =
+ out->m * tcrop(aFac[1] + (float)k[1] * in->g / in->m, out0G, out1G);
+ out->b =
+ out->m * tcrop(aFac[2] + (float)k[2] * in->b / in->m, out0B, out1B);
+ }
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+
template
void do_rgbmAdjust(TRasterPT rout, TRasterPT rin, ScaleFunc scaleFunc,
const int *in0, const int *in1, const int *out0,
- const int *out1) {
+ const int *out1, bool doClamp = true) {
assert(rout->getSize() == rin->getSize());
double a[5], k[5];
@@ -207,16 +306,25 @@ void do_rgbmAdjust(TRasterPT rout, TRasterPT rin, ScaleFunc scaleFunc,
// Ensure that the output is cropped according to output params
int out0i[4], out1i[4];
+ if (doClamp) {
+ out0i[0] = std::max(out0[0], tcrop((int)(a[0] + k[0] * out0[1]), 0, 255));
+ out1i[0] = std::min(out1[0], tcrop((int)(a[0] + k[0] * out1[1]), 0, 255));
- out0i[0] = std::max(out0[0], tcrop((int)(a[0] + k[0] * out0[1]), 0, 255));
- out1i[0] = std::min(out1[0], tcrop((int)(a[0] + k[0] * out1[1]), 0, 255));
+ out0i[1] = std::max(out0[0], tcrop((int)(a[0] + k[0] * out0[2]), 0, 255));
+ out1i[1] = std::min(out1[0], tcrop((int)(a[0] + k[0] * out1[2]), 0, 255));
- out0i[1] = std::max(out0[0], tcrop((int)(a[0] + k[0] * out0[2]), 0, 255));
- out1i[1] = std::min(out1[0], tcrop((int)(a[0] + k[0] * out1[2]), 0, 255));
+ out0i[2] = std::max(out0[0], tcrop((int)(a[0] + k[0] * out0[3]), 0, 255));
+ out1i[2] = std::min(out1[0], tcrop((int)(a[0] + k[0] * out1[3]), 0, 255));
+ } else {
+ out0i[0] = std::max(out0[0], (int)(a[0] + k[0] * out0[1]));
+ out1i[0] = std::min(out1[0], (int)(a[0] + k[0] * out1[1]));
- out0i[2] = std::max(out0[0], tcrop((int)(a[0] + k[0] * out0[3]), 0, 255));
- out1i[2] = std::min(out1[0], tcrop((int)(a[0] + k[0] * out1[3]), 0, 255));
+ out0i[1] = std::max(out0[0], (int)(a[0] + k[0] * out0[2]));
+ out1i[1] = std::min(out1[0], (int)(a[0] + k[0] * out1[2]));
+ out0i[2] = std::max(out0[0], (int)(a[0] + k[0] * out0[3]));
+ out1i[2] = std::min(out1[0], (int)(a[0] + k[0] * out1[3]));
+ }
out0i[3] = out0[4];
out1i[3] = out1[4];
@@ -245,6 +353,8 @@ void TRop::rgbmScale(TRasterP rout, TRasterP rin, const double *k,
do_greyScale_lut(rout, rin, a[0], k[0], out0[0], out1[0]);
else if ((TRasterGR16P)rout && (TRasterGR16P)rin)
do_greyScale_lut(rout, rin, a[0], k[0], out0[0], out1[0]);
+ else if ((TRasterFP)rout && (TRasterFP)rin)
+ do_rgbmScale(rout, rin, a, k, out0, out1);
else {
rout->unlock();
rin->unlock();
@@ -292,7 +402,10 @@ void TRop::rgbmAdjust(TRasterP rout, TRasterP rin, const int *in0,
else
do_rgbmAdjust(rout, rin, &do_rgbmScale_lut, in0, in1,
out0, out1);
- } else if ((TRasterGR8P)rout && (TRasterGR8P)rin)
+ } else if ((TRasterFP)rout && (TRasterFP)rin)
+ do_rgbmAdjust(rout, rin, &do_rgbmScaleFloat, in0, in1, out0, out1,
+ false);
+ else if ((TRasterGR8P)rout && (TRasterGR8P)rin)
do_greyAdjust(rout, rin, in0[0], in1[0], out0[0], out1[0]);
else if ((TRasterGR16P)rout && (TRasterGR16P)rin)
do_greyAdjust