Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "trop.h"
Toshihiro Shimizu 890ddd
#include "tpixel.h"
Toshihiro Shimizu 890ddd
#include "tpixelutils.h"
Toshihiro Shimizu 890ddd
322341
// calls to _mm_* functions disabled in code for now (marked as comment)
322341
// so disable include <emmintrin.h></emmintrin.h>
322341
/*
322341
#if defined(_WIN32) && defined(x64)
322341
  #define ENABLE_SSE2
322341
#endif
322341
322341
#ifdef ENABLE_SSE2
Shinya Kitaoka 120a6e
#include <emmintrin.h>  // per SSE2</emmintrin.h>
Toshihiro Shimizu 890ddd
#endif
322341
 */
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Shinya Kitaoka 120a6e
inline double luminance(TPixel32 *pix) {
Shinya Kitaoka 120a6e
  return 0.2126 * pix->r + 0.7152 * pix->g + 0.0722 * pix->b;
Toshihiro Shimizu 890ddd
}
Shinya Kitaoka 120a6e
inline double luminance(TPixel64 *pix) {
Shinya Kitaoka 120a6e
  return 0.2126 * pix->r + 0.7152 * pix->g + 0.0722 * pix->b;
Toshihiro Shimizu 890ddd
}
Shinya Kitaoka 120a6e
}  // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
#define FOR_EACH_PIXEL_BEGIN_LOOP(UpType, up, DownType, down, OutType, out)    \
Shinya Kitaoka 120a6e
  {                                                                            \
Shinya Kitaoka 120a6e
    int upWrap   = up->getWrap();                                              \
Shinya Kitaoka 120a6e
    int downWrap = down->getWrap();                                            \
Shinya Kitaoka 120a6e
    int outWrap  = out->getWrap();                                             \
Shinya Kitaoka 120a6e
                                                                               \
Shinya Kitaoka 120a6e
    up->lock();                                                                \
Shinya Kitaoka 120a6e
    down->lock();                                                              \
Shinya Kitaoka 120a6e
    out->lock();                                                               \
Shinya Kitaoka 120a6e
    UpType *upPix = 0, *upRow   = up->pixels();                                \
Shinya Kitaoka 120a6e
    DownType *downPix, *downRow = down->pixels();                              \
Shinya Kitaoka 120a6e
    OutType *outPix, *outRow    = out->pixels();                               \
Shinya Kitaoka 120a6e
    UpType *endPix;                                                            \
Shinya Kitaoka 120a6e
    int upLx        = up->getLx();                                             \
Shinya Kitaoka 120a6e
    UpType *lastPix = upRow + upWrap * (up->getLy() - 1) + upLx;               \
Shinya Kitaoka 120a6e
    while (upPix < lastPix) {                                                  \
Shinya Kitaoka 120a6e
      upPix   = upRow;                                                         \
Shinya Kitaoka 120a6e
      downPix = downRow;                                                       \
Shinya Kitaoka 120a6e
      outPix  = outRow;                                                        \
Shinya Kitaoka 120a6e
      endPix  = upPix + upLx;                                                  \
Shinya Kitaoka 120a6e
      while (upPix < endPix) {
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
#define FOR_EACH_PIXEL_END_LOOP(up, down, out)                                 \
Shinya Kitaoka 120a6e
  ++upPix;                                                                     \
Shinya Kitaoka 120a6e
  ++downPix;                                                                   \
Shinya Kitaoka 120a6e
  ++outPix;                                                                    \
Shinya Kitaoka 120a6e
  }                                                                            \
Shinya Kitaoka 120a6e
  upRow += upWrap;                                                             \
Shinya Kitaoka 120a6e
  downRow += downWrap;                                                         \
Shinya Kitaoka 120a6e
  outRow += outWrap;                                                           \
Shinya Kitaoka 120a6e
  }                                                                            \
Shinya Kitaoka 120a6e
  up->unlock();                                                                \
Shinya Kitaoka 120a6e
  down->unlock();                                                              \
Shinya Kitaoka 120a6e
  out->unlock();                                                               \
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
#define FOR_EACH_PIXEL_32_BEGIN_LOOP                                           \
Shinya Kitaoka 120a6e
  assert(up32 &&down32 &&out32);                                               \
Shinya Kitaoka 120a6e
  FOR_EACH_PIXEL_BEGIN_LOOP(TPixelRGBM32, up32, TPixelRGBM32, down32,          \
Shinya Kitaoka 120a6e
                            TPixelRGBM32, out32)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
#define FOR_EACH_PIXEL_32_END_LOOP                                             \
Shinya Kitaoka 120a6e
  assert(up32 &&down32 &&out32);                                               \
Shinya Kitaoka 120a6e
  FOR_EACH_PIXEL_END_LOOP(up32, down32, out32)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
#define FOR_EACH_PIXEL_64_BEGIN_LOOP                                           \
Shinya Kitaoka 120a6e
  assert(up64 &&down64 &&out64);                                               \
Shinya Kitaoka 120a6e
  FOR_EACH_PIXEL_BEGIN_LOOP(TPixelRGBM64, up64, TPixelRGBM64, down64,          \
Shinya Kitaoka 120a6e
                            TPixelRGBM64, out64)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
#define FOR_EACH_PIXEL_64_END_LOOP                                             \
Shinya Kitaoka 120a6e
  assert(up64 &&down64 &&out64);                                               \
Shinya Kitaoka 120a6e
  FOR_EACH_PIXEL_END_LOOP(up64, down64, out64)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
shun-iwasawa 481b59
#define FOR_EACH_PIXEL_F_BEGIN_LOOP                                            \
shun-iwasawa 481b59
  assert(upF &&downF &&outF);                                                  \
shun-iwasawa 481b59
  FOR_EACH_PIXEL_BEGIN_LOOP(TPixelF, upF, TPixelF, downF, TPixelF, outF)
shun-iwasawa 481b59
shun-iwasawa 481b59
//-----------------------------------------------------------------------------
shun-iwasawa 481b59
shun-iwasawa 481b59
#define FOR_EACH_PIXEL_F_END_LOOP                                              \
shun-iwasawa 481b59
  assert(upF &&downF &&outF);                                                  \
shun-iwasawa 481b59
  FOR_EACH_PIXEL_END_LOOP(upF, downF, outF)
shun-iwasawa 481b59
shun-iwasawa 481b59
//-----------------------------------------------------------------------------
shun-iwasawa 481b59
Shinya Kitaoka 120a6e
#define FOR_EACH_PIXEL_8_BEGIN_LOOP                                            \
Shinya Kitaoka 120a6e
  assert(up8 &&down8 &&out8);                                                  \
Shinya Kitaoka 120a6e
  FOR_EACH_PIXEL_BEGIN_LOOP(TPixelGR8, up8, TPixelGR8, down8, TPixelGR8, out8)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
#define FOR_EACH_PIXEL_8_END_LOOP                                              \
Shinya Kitaoka 120a6e
  assert(up8 &&down8 &&out8);                                                  \
Shinya Kitaoka 120a6e
  FOR_EACH_PIXEL_END_LOOP(up32, down32, out32)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TRop::add(const TRasterP &rup, const TRasterP &rdown, const TRasterP &rout,
Shinya Kitaoka 120a6e
               double v) {
Shinya Kitaoka 120a6e
  TRaster32P up32   = rup;
Shinya Kitaoka 120a6e
  TRaster32P down32 = rdown;
Shinya Kitaoka 120a6e
  TRaster32P out32  = rout;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (up32 && down32 && out32) {
Shinya Kitaoka 120a6e
    FOR_EACH_PIXEL_32_BEGIN_LOOP
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TINT32 r, g, b, m;
Shinya Kitaoka 120a6e
    if (upPix->m == 0)
Shinya Kitaoka 120a6e
      *outPix = *downPix;
Shinya Kitaoka 120a6e
    else {
Shinya Kitaoka 120a6e
      r         = downPix->r + tround(upPix->r * v);
Shinya Kitaoka 120a6e
      g         = downPix->g + tround(upPix->g * v);
Shinya Kitaoka 120a6e
      b         = downPix->b + tround(upPix->b * v);
Shinya Kitaoka 120a6e
      m         = downPix->m + tround(upPix->m * v);
Shinya Kitaoka 120a6e
      outPix->r = (UCHAR)tcrop<tint32>(r, (TINT32)0, (TINT32)255);</tint32>
Shinya Kitaoka 120a6e
      outPix->g = (UCHAR)tcrop<tint32>(g, (TINT32)0, (TINT32)255);</tint32>
Shinya Kitaoka 120a6e
      outPix->b = (UCHAR)tcrop<tint32>(b, (TINT32)0, (TINT32)255);</tint32>
Shinya Kitaoka 120a6e
      outPix->m = (UCHAR)tcrop<tint32>(m, (TINT32)0, (TINT32)255);</tint32>
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    FOR_EACH_PIXEL_32_END_LOOP
shun-iwasawa 481b59
    return;
shun-iwasawa 481b59
  }
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
  TRaster64P up64   = rup;
shun-iwasawa 481b59
  TRaster64P down64 = rdown;
shun-iwasawa 481b59
  TRaster64P out64  = rout;
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
  if (up64 && down64 && out64) {
shun-iwasawa 481b59
    FOR_EACH_PIXEL_64_BEGIN_LOOP
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
    TINT32 r, g, b, m;
shun-iwasawa 481b59
    r = downPix->r + tround(upPix->r * v);
shun-iwasawa 481b59
    g = downPix->g + tround(upPix->g * v);
shun-iwasawa 481b59
    b = downPix->b + tround(upPix->b * v);
shun-iwasawa 481b59
    m = downPix->m + tround(upPix->m * v);
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
    outPix->r = (USHORT)tcrop<tint32>(r, 0, 0xffff);</tint32>
shun-iwasawa 481b59
    outPix->g = (USHORT)tcrop<tint32>(g, 0, 0xffff);</tint32>
shun-iwasawa 481b59
    outPix->b = (USHORT)tcrop<tint32>(b, 0, 0xffff);</tint32>
shun-iwasawa 481b59
    outPix->m = (USHORT)tcrop<tint32>(m, 0, 0xffff);</tint32>
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
    FOR_EACH_PIXEL_64_END_LOOP
shun-iwasawa 481b59
    return;
shun-iwasawa 481b59
  }
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
  TRasterFP upF   = rup;
shun-iwasawa 481b59
  TRasterFP downF = rdown;
shun-iwasawa 481b59
  TRasterFP outF  = rout;
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
  if (upF && downF && outF) {
shun-iwasawa 481b59
    FOR_EACH_PIXEL_F_BEGIN_LOOP
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
    outPix->r = downPix->r + upPix->r * v;
shun-iwasawa 481b59
    outPix->g = downPix->g + upPix->g * v;
shun-iwasawa 481b59
    outPix->b = downPix->b + upPix->b * v;
shun-iwasawa 481b59
    outPix->m = tcrop<float>(downPix->m + upPix->m * v, 0.f, 1.f);</float>
shun-iwasawa 481b59
shun-iwasawa 481b59
    FOR_EACH_PIXEL_F_END_LOOP
shun-iwasawa 481b59
    return;
shun-iwasawa 481b59
  }
shun-iwasawa 481b59
shun-iwasawa 481b59
  TRasterGR8P up8   = rup;
shun-iwasawa 481b59
  TRasterGR8P down8 = rdown;
shun-iwasawa 481b59
  TRasterGR8P out8  = rout;
shun-iwasawa 481b59
shun-iwasawa 481b59
  if (up8 && down8 && out8) {
shun-iwasawa 481b59
    FOR_EACH_PIXEL_8_BEGIN_LOOP
shun-iwasawa 481b59
shun-iwasawa 481b59
    USHORT value = troundp(upPix->value * v) + downPix->value;
shun-iwasawa 481b59
shun-iwasawa 481b59
    outPix->value = (UCHAR)tcrop<ushort>(value, 0, 255);</ushort>
shun-iwasawa 481b59
shun-iwasawa 481b59
    FOR_EACH_PIXEL_8_END_LOOP
shun-iwasawa 481b59
    return;
Shinya Kitaoka 120a6e
  }
shun-iwasawa 481b59
shun-iwasawa 481b59
  throw TRopException("TRop::add invalid raster combination");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TRop::add(const TRasterP &rup, const TRasterP &rdown,
Shinya Kitaoka 120a6e
               const TRasterP &rout) {
Shinya Kitaoka 120a6e
  TRaster32P up32   = rup;
Shinya Kitaoka 120a6e
  TRaster32P down32 = rdown;
Shinya Kitaoka 120a6e
  TRaster32P out32  = rout;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (up32 && down32 && out32) {
Shinya Kitaoka 120a6e
    FOR_EACH_PIXEL_32_BEGIN_LOOP
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    USHORT r, g, b, m;
Shinya Kitaoka 120a6e
    r = downPix->r + upPix->r;
Shinya Kitaoka 120a6e
    g = downPix->g + upPix->g;
Shinya Kitaoka 120a6e
    b = downPix->b + upPix->b;
Shinya Kitaoka 120a6e
    m = downPix->m + upPix->m;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    outPix->r = (UCHAR)tcrop<ushort>(r, 0, 255);</ushort>
Shinya Kitaoka 120a6e
    outPix->g = (UCHAR)tcrop<ushort>(g, 0, 255);</ushort>
Shinya Kitaoka 120a6e
    outPix->b = (UCHAR)tcrop<ushort>(b, 0, 255);</ushort>
Shinya Kitaoka 120a6e
    outPix->m = (UCHAR)tcrop<ushort>(m, 0, 255);</ushort>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    FOR_EACH_PIXEL_32_END_LOOP
shun-iwasawa 481b59
    return;
shun-iwasawa 481b59
  }
shun-iwasawa 481b59
  TRaster64P up64   = rup;
shun-iwasawa 481b59
  TRaster64P down64 = rdown;
shun-iwasawa 481b59
  TRaster64P out64  = rout;
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
  if (up64 && down64 && out64) {
shun-iwasawa 481b59
    FOR_EACH_PIXEL_64_BEGIN_LOOP
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
    TINT32 r, g, b, m;
shun-iwasawa 481b59
    r = downPix->r + upPix->r;
shun-iwasawa 481b59
    g = downPix->g + upPix->g;
shun-iwasawa 481b59
    b = downPix->b + upPix->b;
shun-iwasawa 481b59
    m = downPix->m + upPix->m;
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
    outPix->r = (USHORT)tcrop<tint32>(r, 0, 0xffff);</tint32>
shun-iwasawa 481b59
    outPix->g = (USHORT)tcrop<tint32>(g, 0, 0xffff);</tint32>
shun-iwasawa 481b59
    outPix->b = (USHORT)tcrop<tint32>(b, 0, 0xffff);</tint32>
shun-iwasawa 481b59
    outPix->m = (USHORT)tcrop<tint32>(m, 0, 0xffff);</tint32>
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
    FOR_EACH_PIXEL_64_END_LOOP
shun-iwasawa 481b59
    return;
shun-iwasawa 481b59
  }
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
  TRasterFP upF   = rup;
shun-iwasawa 481b59
  TRasterFP downF = rdown;
shun-iwasawa 481b59
  TRasterFP outF  = rout;
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
  if (upF && downF && outF) {
shun-iwasawa 481b59
    FOR_EACH_PIXEL_F_BEGIN_LOOP
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
    outPix->r = downPix->r + upPix->r;
shun-iwasawa 481b59
    outPix->g = downPix->g + upPix->g;
shun-iwasawa 481b59
    outPix->b = downPix->b + upPix->b;
shun-iwasawa 481b59
    outPix->m = tcrop<float>(downPix->m + upPix->m, 0.f, 1.f);</float>
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
    FOR_EACH_PIXEL_F_END_LOOP
shun-iwasawa 481b59
    return;
shun-iwasawa 481b59
  }
shun-iwasawa 481b59
shun-iwasawa 481b59
  TRasterGR8P up8   = rup;
shun-iwasawa 481b59
  TRasterGR8P down8 = rdown;
shun-iwasawa 481b59
  TRasterGR8P out8  = rout;
shun-iwasawa 481b59
shun-iwasawa 481b59
  if (up8 && down8 && out8) {
shun-iwasawa 481b59
    FOR_EACH_PIXEL_8_BEGIN_LOOP
shun-iwasawa 481b59
shun-iwasawa 481b59
    USHORT value = upPix->value + downPix->value;
shun-iwasawa 481b59
shun-iwasawa 481b59
    outPix->value = (UCHAR)tcrop<ushort>(value, 0, 255);</ushort>
shun-iwasawa 481b59
shun-iwasawa 481b59
    FOR_EACH_PIXEL_8_END_LOOP
shun-iwasawa 481b59
    return;
Shinya Kitaoka 120a6e
  }
shun-iwasawa 481b59
shun-iwasawa 481b59
  throw TRopException("TRop::add invalid raster combination");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TRop::colordodge(const TRasterP &rup, const TRasterP &rdown,
Shinya Kitaoka 120a6e
                      const TRasterP &rout) {
Shinya Kitaoka 120a6e
  TRaster32P up32   = rup;
Shinya Kitaoka 120a6e
  TRaster32P down32 = rdown;
Shinya Kitaoka 120a6e
  TRaster32P out32  = rout;
Shinya Kitaoka 120a6e
  if (up32 && down32 && out32) {
Shinya Kitaoka 120a6e
    FOR_EACH_PIXEL_32_BEGIN_LOOP
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    USHORT r, g, b, m;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    r = (USHORT)((downPix->r << 8) / (256.0 - upPix->r));
Shinya Kitaoka 120a6e
    g = (USHORT)((downPix->g << 8) / (256.0 - upPix->g));
Shinya Kitaoka 120a6e
    b = (USHORT)((downPix->b << 8) / (256.0 - upPix->b));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    m = downPix->m + upPix->m;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    outPix->r = (UCHAR)tcrop<ushort>(r, 0, 255);</ushort>
Shinya Kitaoka 120a6e
    outPix->g = (UCHAR)tcrop<ushort>(g, 0, 255);</ushort>
Shinya Kitaoka 120a6e
    outPix->b = (UCHAR)tcrop<ushort>(b, 0, 255);</ushort>
Shinya Kitaoka 120a6e
    outPix->m = (UCHAR)tcrop<ushort>(m, 0, 255);</ushort>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    FOR_EACH_PIXEL_32_END_LOOP
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    TRaster64P up64   = rup;
Shinya Kitaoka 120a6e
    TRaster64P down64 = rdown;
Shinya Kitaoka 120a6e
    TRaster64P out64  = rout;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (up64 && down64 && out64) {
Shinya Kitaoka 120a6e
      FOR_EACH_PIXEL_64_BEGIN_LOOP
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      TINT32 r, g, b, m;
Shinya Kitaoka 120a6e
      r = (TINT32)(65536.0 * (downPix->r / (65536.0 - upPix->r)));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      g = (TINT32)(65536.0 * (downPix->g / (65536.0 - upPix->g)));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      b = (TINT32)(65536.0 * (downPix->b / (65536.0 - upPix->b)));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      m = downPix->m + upPix->m;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      outPix->r = (USHORT)tcrop<tint32>(r, 0, 0xffff);</tint32>
Shinya Kitaoka 120a6e
      outPix->g = (USHORT)tcrop<tint32>(g, 0, 0xffff);</tint32>
Shinya Kitaoka 120a6e
      outPix->b = (USHORT)tcrop<tint32>(b, 0, 0xffff);</tint32>
Shinya Kitaoka 120a6e
      outPix->m = (USHORT)tcrop<tint32>(m, 0, 0xffff);</tint32>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      FOR_EACH_PIXEL_64_END_LOOP
Shinya Kitaoka 120a6e
    } else {
shun-iwasawa 481b59
      TRasterFP upF   = rup;
shun-iwasawa 481b59
      TRasterFP downF = rdown;
shun-iwasawa 481b59
      TRasterFP outF  = rout;
Toshihiro Shimizu 890ddd
shun-iwasawa 481b59
      if (upF && downF && outF) {
shun-iwasawa 481b59
        FOR_EACH_PIXEL_F_BEGIN_LOOP
Toshihiro Shimizu 890ddd
shun-iwasawa 481b59
        outPix->r = downPix->r / (1.f - upPix->r);
shun-iwasawa 481b59
        outPix->g = downPix->g / (1.f - upPix->g);
shun-iwasawa 481b59
        outPix->b = downPix->b / (1.f - upPix->b);
shun-iwasawa 481b59
        outPix->m = tcrop<float>(downPix->m + upPix->m, 0.f, 1.f);</float>
Toshihiro Shimizu 890ddd
shun-iwasawa 481b59
        FOR_EACH_PIXEL_F_END_LOOP
shun-iwasawa 481b59
      } else {
shun-iwasawa 481b59
        TRasterGR8P up8   = rup;
shun-iwasawa 481b59
        TRasterGR8P down8 = rdown;
shun-iwasawa 481b59
        TRasterGR8P out8  = rout;
shun-iwasawa 481b59
shun-iwasawa 481b59
        if (up8 && down8 && out8) {
shun-iwasawa 481b59
          FOR_EACH_PIXEL_8_BEGIN_LOOP
shun-iwasawa 481b59
          USHORT value;
shun-iwasawa 481b59
          if (downPix->value)
shun-iwasawa 481b59
            value = (USHORT)((downPix->value << 8) / (255.0 - upPix->value));
shun-iwasawa 481b59
shun-iwasawa 481b59
          outPix->value = (UCHAR)tcrop<ushort>(value, 0, 255);</ushort>
shun-iwasawa 481b59
shun-iwasawa 481b59
          FOR_EACH_PIXEL_8_END_LOOP
shun-iwasawa 481b59
        } else
shun-iwasawa 481b59
          throw TRopException("TRop::color dodge invalid raster combination");
shun-iwasawa 481b59
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TRop::colorburn(const TRasterP &rup, const TRasterP &rdown,
Shinya Kitaoka 120a6e
                     const TRasterP &rout) {
Shinya Kitaoka 120a6e
  TRaster32P up32   = rup;
Shinya Kitaoka 120a6e
  TRaster32P down32 = rdown;
Shinya Kitaoka 120a6e
  TRaster32P out32  = rout;
Shinya Kitaoka 120a6e
  if (up32 && down32 && out32) {
Shinya Kitaoka 120a6e
    FOR_EACH_PIXEL_32_BEGIN_LOOP
Shinya Kitaoka 120a6e
    //  downPix->r=0;
Shinya Kitaoka 120a6e
    //  downPix->g=255;
Shinya Kitaoka 120a6e
    //  downPix->b=0;
Shinya Kitaoka 120a6e
    double r, g, b;
Shinya Kitaoka 120a6e
    if (upPix->m) {
Shinya Kitaoka 120a6e
      if (downPix->r == 0 || downPix->r == 255)
Shinya Kitaoka 120a6e
        r = downPix->r;
Shinya Kitaoka 120a6e
      else if (upPix->r)
Shinya Kitaoka 120a6e
        r = 255 - (((255 - downPix->r) << 8) / (double)upPix->r);
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        r = 0;
Shinya Kitaoka 120a6e
      if (downPix->g == 0 || downPix->g == 255)
Shinya Kitaoka 120a6e
        g = downPix->g;
Shinya Kitaoka 120a6e
      else if (upPix->g)
Shinya Kitaoka 120a6e
        g = 255 - (((255 - downPix->g) << 8) / (double)upPix->g);
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        g = 0;
Shinya Kitaoka 120a6e
      if (downPix->b == 0 || downPix->b == 255)
Shinya Kitaoka 120a6e
        b = downPix->b;
Shinya Kitaoka 120a6e
      else if (upPix->b)
Shinya Kitaoka 120a6e
        b = 255 - (((255 - downPix->b) << 8) / (double)upPix->b);
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        b = 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (upPix->m != 255) {
Shinya Kitaoka 120a6e
        TPixel32 tmpPix;
Shinya Kitaoka 120a6e
        tmpPix.r = (UCHAR)tcrop<double>(r, .0, 255.0);</double>
Shinya Kitaoka 120a6e
        tmpPix.g = (UCHAR)tcrop<double>(g, .0, 255.0);</double>
Shinya Kitaoka 120a6e
        tmpPix.b = (UCHAR)tcrop<double>(b, .0, 255.0);</double>
Shinya Kitaoka 120a6e
        tmpPix.m = upPix->m;
Shinya Kitaoka 120a6e
        ;
Shinya Kitaoka 120a6e
        overPix<tpixel32, uchar="">(*outPix, *downPix, tmpPix);</tpixel32,>
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        outPix->r = (UCHAR)tcrop<double>(r, .0, 255.0);</double>
Shinya Kitaoka 120a6e
        outPix->g = (UCHAR)tcrop<double>(g, .0, 255.0);</double>
Shinya Kitaoka 120a6e
        outPix->b = (UCHAR)tcrop<double>(b, .0, 255.0);</double>
Shinya Kitaoka 120a6e
        outPix->m = downPix->m;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      outPix = downPix;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    FOR_EACH_PIXEL_32_END_LOOP
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    TRaster64P up64   = rup;
Shinya Kitaoka 120a6e
    TRaster64P down64 = rdown;
Shinya Kitaoka 120a6e
    TRaster64P out64  = rout;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (up64 && down64 && out64) {
Shinya Kitaoka 120a6e
      FOR_EACH_PIXEL_64_BEGIN_LOOP
Shinya Kitaoka 120a6e
      double r, g, b;
Shinya Kitaoka 120a6e
      if (upPix->m) {
Shinya Kitaoka 120a6e
        if (downPix->r == 0 || downPix->r == 65535)
Shinya Kitaoka 120a6e
          r = downPix->r;
Shinya Kitaoka 120a6e
        else if (upPix->r)
Shinya Kitaoka 120a6e
          r = 65535 - 65536 * ((65535.0 - downPix->r) / (double)upPix->r);
Shinya Kitaoka 120a6e
        else
Shinya Kitaoka 120a6e
          r = 0;
Shinya Kitaoka 120a6e
        if (downPix->g == 0 || downPix->g == 65535)
Shinya Kitaoka 120a6e
          g = downPix->g;
Shinya Kitaoka 120a6e
        else if (upPix->g)
Shinya Kitaoka 120a6e
          g = 65535 - 65536 * ((65535.0 - downPix->g) / (double)upPix->g);
Shinya Kitaoka 120a6e
        else
Shinya Kitaoka 120a6e
          g = 0;
Shinya Kitaoka 120a6e
        if (downPix->b == 0 || downPix->b == 65535)
Shinya Kitaoka 120a6e
          b = downPix->b;
Shinya Kitaoka 120a6e
        else if (upPix->b)
Shinya Kitaoka 120a6e
          b = 65535 - 65536 * ((65535.0 - downPix->b) / (double)upPix->b);
Shinya Kitaoka 120a6e
        else
Shinya Kitaoka 120a6e
          b = 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        if (upPix->m != 65535) {
Shinya Kitaoka 120a6e
          TPixel64 tmpPix;
Shinya Kitaoka 120a6e
          tmpPix.r = (USHORT)tcrop<double>(r, .0, 65535.0);</double>
Shinya Kitaoka 120a6e
          tmpPix.g = (USHORT)tcrop<double>(g, .0, 65535.0);</double>
Shinya Kitaoka 120a6e
          tmpPix.b = (USHORT)tcrop<double>(b, .0, 65535.0);</double>
Shinya Kitaoka 120a6e
          tmpPix.m = upPix->m;
Shinya Kitaoka 120a6e
          overPix<tpixel64, ushort="">(*outPix, *downPix, tmpPix);</tpixel64,>
Shinya Kitaoka 120a6e
        } else {
Shinya Kitaoka 120a6e
          outPix->r = (USHORT)tcrop<double>(r, .0, 65535.0);</double>
Shinya Kitaoka 120a6e
          outPix->g = (USHORT)tcrop<double>(g, .0, 65535.0);</double>
Shinya Kitaoka 120a6e
          outPix->b = (USHORT)tcrop<double>(b, .0, 65535.0);</double>
Shinya Kitaoka 120a6e
          outPix->m = downPix->m;
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        outPix = downPix;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      FOR_EACH_PIXEL_64_END_LOOP
shun-iwasawa 481b59
    } else {
shun-iwasawa 481b59
      TRasterFP upF   = rup;
shun-iwasawa 481b59
      TRasterFP downF = rdown;
shun-iwasawa 481b59
      TRasterFP outF  = rout;
shun-iwasawa 481b59
shun-iwasawa 481b59
      if (upF && downF && outF) {
shun-iwasawa 481b59
        FOR_EACH_PIXEL_F_BEGIN_LOOP
shun-iwasawa 481b59
        float r, g, b;
shun-iwasawa 481b59
        if (upPix->m > 0.f) {
shun-iwasawa 481b59
          if (downPix->r <= 0.f || downPix->r >= 1.f)
shun-iwasawa 481b59
            r = downPix->r;
shun-iwasawa 481b59
          else if (upPix->r)
shun-iwasawa 481b59
            r = 1.f - (1.f - downPix->r) / upPix->r;
shun-iwasawa 481b59
          else
shun-iwasawa 481b59
            r = 0.f;
shun-iwasawa 481b59
          if (downPix->g <= 0.f || downPix->g >= 1.f)
shun-iwasawa 481b59
            g = downPix->g;
shun-iwasawa 481b59
          else if (upPix->g)
shun-iwasawa 481b59
            g = 1.f - (1.f - downPix->g) / upPix->g;
shun-iwasawa 481b59
          else
shun-iwasawa 481b59
            g = 0.f;
shun-iwasawa 481b59
          if (downPix->b <= 0.f || downPix->b >= 1.f)
shun-iwasawa 481b59
            b = downPix->b;
shun-iwasawa 481b59
          else if (upPix->b)
shun-iwasawa 481b59
            b = 1.f - (1.f - downPix->b) / upPix->b;
shun-iwasawa 481b59
          else
shun-iwasawa 481b59
            b = 0.f;
shun-iwasawa 481b59
shun-iwasawa 481b59
          if (upPix->m < 1.f) {
shun-iwasawa 481b59
            overPix<tpixelf, float="">(*outPix, *downPix,</tpixelf,>
shun-iwasawa 481b59
                                    TPixelF(r, g, b, upPix->m));
shun-iwasawa 481b59
          } else {
shun-iwasawa 481b59
            outPix->r = r;
shun-iwasawa 481b59
            outPix->g = g;
shun-iwasawa 481b59
            outPix->b = b;
shun-iwasawa 481b59
            outPix->m = downPix->m;
shun-iwasawa 481b59
          }
shun-iwasawa 481b59
        } else {
shun-iwasawa 481b59
          outPix = downPix;
shun-iwasawa 481b59
        }
shun-iwasawa 481b59
        FOR_EACH_PIXEL_F_END_LOOP
shun-iwasawa 481b59
      } else
shun-iwasawa 481b59
        throw TRopException("TRop::color burn invalid raster combination");
shun-iwasawa 481b59
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TRop::screen(const TRasterP &rup, const TRasterP &rdown,
Shinya Kitaoka 120a6e
                  const TRasterP &rout) {
Shinya Kitaoka 120a6e
  TRaster32P up32   = rup;
Shinya Kitaoka 120a6e
  TRaster32P down32 = rdown;
Shinya Kitaoka 120a6e
  TRaster32P out32  = rout;
Shinya Kitaoka 120a6e
  if (up32 && down32 && out32) {
Shinya Kitaoka 120a6e
    FOR_EACH_PIXEL_32_BEGIN_LOOP
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    double r, g, b;
Shinya Kitaoka 120a6e
    r = 256 - ((256 - upPix->r) * (256 - downPix->r) >> 8);
Shinya Kitaoka 120a6e
    g = 256 - ((256 - upPix->g) * (256 - downPix->g) >> 8);
Shinya Kitaoka 120a6e
    b = 256 - ((256 - upPix->b) * (256 - downPix->b) >> 8);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (upPix->m != 255) {
Shinya Kitaoka 120a6e
      double m;
Shinya Kitaoka 120a6e
      m = 256 - ((256 - upPix->m) * (256 - downPix->m) >> 8);
Shinya Kitaoka 120a6e
      TPixel32 tmpPix;
Shinya Kitaoka 120a6e
      tmpPix.r = (UCHAR)tcrop<double>(r, 0, 255);</double>
Shinya Kitaoka 120a6e
      tmpPix.g = (UCHAR)tcrop<double>(g, 0, 255);</double>
Shinya Kitaoka 120a6e
      tmpPix.b = (UCHAR)tcrop<double>(b, 0, 255);</double>
Shinya Kitaoka 120a6e
      tmpPix.m = (UCHAR)tcrop<double>(m, 0, 255);</double>
Shinya Kitaoka 120a6e
      overPix<tpixel32, uchar="">(*outPix, *downPix, tmpPix);</tpixel32,>
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      outPix->r = (UCHAR)tcrop<double>(r, 0, 255);</double>
Shinya Kitaoka 120a6e
      outPix->g = (UCHAR)tcrop<double>(g, 0, 255);</double>
Shinya Kitaoka 120a6e
      outPix->b = (UCHAR)tcrop<double>(b, 0, 255);</double>
Shinya Kitaoka 120a6e
      outPix->m = upPix->m;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    FOR_EACH_PIXEL_32_END_LOOP
shun-iwasawa 481b59
    return;
shun-iwasawa 481b59
  }
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
  TRaster64P up64   = rup;
shun-iwasawa 481b59
  TRaster64P down64 = rdown;
shun-iwasawa 481b59
  TRaster64P out64  = rout;
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
  if (up64 && down64 && out64) {
shun-iwasawa 481b59
    FOR_EACH_PIXEL_64_BEGIN_LOOP
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
    double r, g, b;
shun-iwasawa 481b59
    r = 65536 - (65536 - upPix->r) * ((65536 - downPix->r) / 65536.0);
shun-iwasawa 481b59
    g = 65536 - (65536 - upPix->g) * ((65536 - downPix->g) / 65536.0);
shun-iwasawa 481b59
    b = 65536 - (65536 - upPix->b) * ((65536 - downPix->b) / 65536.0);
shun-iwasawa 481b59
shun-iwasawa 481b59
    if (upPix->m != 65535) {
shun-iwasawa 481b59
      double m;
shun-iwasawa 481b59
      m = 65536 - (65536 - upPix->m) * ((65536 - downPix->m) / 65536.0);
shun-iwasawa 481b59
      TPixel64 tmpPix;
shun-iwasawa 481b59
      tmpPix.r = (USHORT)tcrop<double>(r, 0, 65535);</double>
shun-iwasawa 481b59
      tmpPix.g = (USHORT)tcrop<double>(g, 0, 65535);</double>
shun-iwasawa 481b59
      tmpPix.b = (USHORT)tcrop<double>(b, 0, 65535);</double>
shun-iwasawa 481b59
      tmpPix.m = (USHORT)tcrop<double>(m, 0, 65535);</double>
shun-iwasawa 481b59
      overPix<tpixel64, ushort="">(*outPix, *downPix, tmpPix);</tpixel64,>
Shinya Kitaoka 120a6e
    } else {
shun-iwasawa 481b59
      outPix->r = (USHORT)tcrop<double>(r, 0, 65535);</double>
shun-iwasawa 481b59
      outPix->g = (USHORT)tcrop<double>(g, 0, 65535);</double>
shun-iwasawa 481b59
      outPix->b = (USHORT)tcrop<double>(b, 0, 65535);</double>
shun-iwasawa 481b59
      outPix->m = upPix->m;
shun-iwasawa 481b59
    }
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
    FOR_EACH_PIXEL_64_END_LOOP
shun-iwasawa 481b59
    return;
shun-iwasawa 481b59
  }
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
  TRasterFP upF   = rup;
shun-iwasawa 481b59
  TRasterFP downF = rdown;
shun-iwasawa 481b59
  TRasterFP outF  = rout;
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
  if (upF && downF && outF) {
shun-iwasawa 481b59
    FOR_EACH_PIXEL_F_BEGIN_LOOP
shun-iwasawa 481b59
shun-iwasawa 481b59
    float r, g, b;
shun-iwasawa 481b59
    r = 1.f - (1.f - upPix->r) * (1.f - downPix->r);
shun-iwasawa 481b59
    g = 1.f - (1.f - upPix->g) * (1.f - downPix->g);
shun-iwasawa 481b59
    b = 1.f - (1.f - upPix->b) * (1.f - downPix->b);
shun-iwasawa 481b59
shun-iwasawa 481b59
    if (upPix->m <= 1.f) {
shun-iwasawa 481b59
      float m;
shun-iwasawa 481b59
      m = 1.f - (1.f - upPix->m) * (1.f - downPix->m);
shun-iwasawa 481b59
      TPixelF tmpPix(r, g, b, tcrop<float>(m, 0.f, 1.f));</float>
shun-iwasawa 481b59
      overPix<tpixelf, float="">(*outPix, *downPix, tmpPix);</tpixelf,>
shun-iwasawa 481b59
    } else {
shun-iwasawa 481b59
      outPix->r = r;
shun-iwasawa 481b59
      outPix->g = g;
shun-iwasawa 481b59
      outPix->b = b;
shun-iwasawa 481b59
      outPix->m = upPix->m;
Shinya Kitaoka 120a6e
    }
shun-iwasawa 481b59
shun-iwasawa 481b59
    FOR_EACH_PIXEL_F_END_LOOP
shun-iwasawa 481b59
    return;
Shinya Kitaoka 120a6e
  }
shun-iwasawa 481b59
shun-iwasawa 481b59
  TRasterGR8P up8   = rup;
shun-iwasawa 481b59
  TRasterGR8P down8 = rdown;
shun-iwasawa 481b59
  TRasterGR8P out8  = rout;
shun-iwasawa 481b59
shun-iwasawa 481b59
  if (up8 && down8 && out8) {
shun-iwasawa 481b59
    FOR_EACH_PIXEL_8_BEGIN_LOOP
shun-iwasawa 481b59
    USHORT value;
shun-iwasawa 481b59
    if (downPix->value)
shun-iwasawa 481b59
      value = (USHORT)((downPix->value << 8) / (255.0 - upPix->value));
shun-iwasawa 481b59
shun-iwasawa 481b59
    outPix->value = (UCHAR)tcrop<ushort>(value, 0, 255);</ushort>
shun-iwasawa 481b59
shun-iwasawa 481b59
    FOR_EACH_PIXEL_8_END_LOOP
shun-iwasawa 481b59
    return;
shun-iwasawa 481b59
  }
shun-iwasawa 481b59
shun-iwasawa 481b59
  throw TRopException("TRop::color dodge invalid raster combination");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TRop::sub(const TRasterP &rup, const TRasterP &rdown, const TRasterP &rout,
Shinya Kitaoka 120a6e
               bool matte) {
Shinya Kitaoka 120a6e
  TRaster32P up32   = rup;
Shinya Kitaoka 120a6e
  TRaster32P down32 = rdown;
Shinya Kitaoka 120a6e
  TRaster32P out32  = rout;
Shinya Kitaoka 120a6e
  if (matte) {
Shinya Kitaoka 120a6e
    if (up32 && down32 && out32) {
Shinya Kitaoka 120a6e
      FOR_EACH_PIXEL_32_BEGIN_LOOP
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      SHORT r = downPix->r - upPix->r;
Shinya Kitaoka 120a6e
      SHORT g = downPix->g - upPix->g;
Shinya Kitaoka 120a6e
      SHORT b = downPix->b - upPix->b;
Shinya Kitaoka 120a6e
      SHORT m = downPix->m - upPix->m;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      outPix->r = (UCHAR)tcrop<short>(r, 0, 255);</short>
Shinya Kitaoka 120a6e
      outPix->g = (UCHAR)tcrop<short>(g, 0, 255);</short>
Shinya Kitaoka 120a6e
      outPix->b = (UCHAR)tcrop<short>(b, 0, 255);</short>
Shinya Kitaoka 120a6e
      outPix->m = (UCHAR)tcrop<short>(m, 0, 255);</short>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      FOR_EACH_PIXEL_32_END_LOOP
shun-iwasawa 481b59
      return;
shun-iwasawa 481b59
    }
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
    TRaster64P up64   = rup;
shun-iwasawa 481b59
    TRaster64P down64 = rdown;
shun-iwasawa 481b59
    TRaster64P out64  = rout;
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
    if (up64 && down64 && out64) {
shun-iwasawa 481b59
      FOR_EACH_PIXEL_64_BEGIN_LOOP
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
      TINT32 r  = downPix->r - upPix->r;
shun-iwasawa 481b59
      TINT32 g  = downPix->g - upPix->g;
shun-iwasawa 481b59
      TINT32 b  = downPix->b - upPix->b;
shun-iwasawa 481b59
      TINT32 m  = downPix->m - upPix->m;
shun-iwasawa 481b59
      outPix->r = (USHORT)tcrop<tint32>(r, 0, 0xffff);</tint32>
shun-iwasawa 481b59
      outPix->g = (USHORT)tcrop<tint32>(g, 0, 0xffff);</tint32>
shun-iwasawa 481b59
      outPix->b = (USHORT)tcrop<tint32>(b, 0, 0xffff);</tint32>
shun-iwasawa 481b59
      outPix->m = (USHORT)tcrop<tint32>(m, 0, 0xffff);</tint32>
shun-iwasawa 481b59
shun-iwasawa 481b59
      FOR_EACH_PIXEL_64_END_LOOP
shun-iwasawa 481b59
      return;
Shinya Kitaoka 120a6e
    }
shun-iwasawa 481b59
shun-iwasawa 481b59
    TRasterFP upF   = rup;
shun-iwasawa 481b59
    TRasterFP downF = rdown;
shun-iwasawa 481b59
    TRasterFP outF  = rout;
shun-iwasawa 481b59
shun-iwasawa 481b59
    if (upF && downF && outF) {
shun-iwasawa 481b59
      FOR_EACH_PIXEL_F_BEGIN_LOOP
shun-iwasawa 481b59
shun-iwasawa 481b59
      outPix->r = downPix->r - upPix->r;
shun-iwasawa 481b59
      outPix->g = downPix->g - upPix->g;
shun-iwasawa 481b59
      outPix->b = downPix->b - upPix->b;
shun-iwasawa 481b59
      outPix->m = tcrop<float>(downPix->m - upPix->m, 0.f, 1.f);</float>
shun-iwasawa 481b59
shun-iwasawa 481b59
      FOR_EACH_PIXEL_F_END_LOOP
shun-iwasawa 481b59
      return;
shun-iwasawa 481b59
    }
shun-iwasawa 481b59
shun-iwasawa 481b59
    TRasterGR8P up8   = rup;
shun-iwasawa 481b59
    TRasterGR8P down8 = rdown;
shun-iwasawa 481b59
    TRasterGR8P out8  = rout;
shun-iwasawa 481b59
shun-iwasawa 481b59
    if (up8 && down8 && out8) {
shun-iwasawa 481b59
      FOR_EACH_PIXEL_8_BEGIN_LOOP
shun-iwasawa 481b59
shun-iwasawa 481b59
      SHORT value   = upPix->value - downPix->value;
shun-iwasawa 481b59
      outPix->value = (UCHAR)tcrop<short>(value, 0, 255);</short>
shun-iwasawa 481b59
shun-iwasawa 481b59
      FOR_EACH_PIXEL_8_END_LOOP
shun-iwasawa 481b59
      return;
shun-iwasawa 481b59
    }
shun-iwasawa 481b59
shun-iwasawa 481b59
    throw TRopException("TRop::sub invalid raster combination");
shun-iwasawa 481b59
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    if (up32 && down32 && out32) {
Shinya Kitaoka 120a6e
      FOR_EACH_PIXEL_32_BEGIN_LOOP
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      SHORT r = downPix->r - upPix->r;
Shinya Kitaoka 120a6e
      SHORT g = downPix->g - upPix->g;
Shinya Kitaoka 120a6e
      SHORT b = downPix->b - upPix->b;
Shinya Kitaoka 120a6e
      SHORT m = downPix->m;  // - upPix->m;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      outPix->r = (UCHAR)tcrop<short>(r, 0, 255);</short>
Shinya Kitaoka 120a6e
      outPix->g = (UCHAR)tcrop<short>(g, 0, 255);</short>
Shinya Kitaoka 120a6e
      outPix->b = (UCHAR)tcrop<short>(b, 0, 255);</short>
Shinya Kitaoka 120a6e
      outPix->m = (UCHAR)tcrop<short>(m, 0, 255);</short>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      FOR_EACH_PIXEL_32_END_LOOP
shun-iwasawa 481b59
      return;
shun-iwasawa 481b59
    }
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
    TRaster64P up64   = rup;
shun-iwasawa 481b59
    TRaster64P down64 = rdown;
shun-iwasawa 481b59
    TRaster64P out64  = rout;
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
    if (up64 && down64 && out64) {
shun-iwasawa 481b59
      FOR_EACH_PIXEL_64_BEGIN_LOOP
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
      TINT32 r  = downPix->r - upPix->r;
shun-iwasawa 481b59
      TINT32 g  = downPix->g - upPix->g;
shun-iwasawa 481b59
      TINT32 b  = downPix->b - upPix->b;
shun-iwasawa 481b59
      TINT32 m  = downPix->m;  // - upPix->m;
shun-iwasawa 481b59
      outPix->r = (USHORT)tcrop<tint32>(r, 0, 0xffff);</tint32>
shun-iwasawa 481b59
      outPix->g = (USHORT)tcrop<tint32>(g, 0, 0xffff);</tint32>
shun-iwasawa 481b59
      outPix->b = (USHORT)tcrop<tint32>(b, 0, 0xffff);</tint32>
shun-iwasawa 481b59
      outPix->m = (USHORT)tcrop<tint32>(m, 0, 0xffff);</tint32>
shun-iwasawa 481b59
shun-iwasawa 481b59
      FOR_EACH_PIXEL_64_END_LOOP
shun-iwasawa 481b59
      return;
shun-iwasawa 481b59
    }
shun-iwasawa 481b59
shun-iwasawa 481b59
    TRasterFP upF   = rup;
shun-iwasawa 481b59
    TRasterFP downF = rdown;
shun-iwasawa 481b59
    TRasterFP outF  = rout;
shun-iwasawa 481b59
shun-iwasawa 481b59
    if (upF && downF && outF) {
shun-iwasawa 481b59
      FOR_EACH_PIXEL_F_BEGIN_LOOP
shun-iwasawa 481b59
shun-iwasawa 481b59
      outPix->r = downPix->r - upPix->r;
shun-iwasawa 481b59
      outPix->g = downPix->g - upPix->g;
shun-iwasawa 481b59
      outPix->b = downPix->b - upPix->b;
shun-iwasawa 481b59
      outPix->m = tcrop<float>(downPix->m, 0.f, 1.f);</float>
shun-iwasawa 481b59
shun-iwasawa 481b59
      FOR_EACH_PIXEL_F_END_LOOP
shun-iwasawa 481b59
      return;
shun-iwasawa 481b59
    }
shun-iwasawa 481b59
shun-iwasawa 481b59
    TRasterGR8P up8   = rup;
shun-iwasawa 481b59
    TRasterGR8P down8 = rdown;
shun-iwasawa 481b59
    TRasterGR8P out8  = rout;
shun-iwasawa 481b59
shun-iwasawa 481b59
    if (up8 && down8 && out8) {
shun-iwasawa 481b59
      FOR_EACH_PIXEL_8_BEGIN_LOOP
shun-iwasawa 481b59
shun-iwasawa 481b59
      SHORT value   = upPix->value - downPix->value;
shun-iwasawa 481b59
      outPix->value = (UCHAR)tcrop<short>(value, 0, 255);</short>
shun-iwasawa 481b59
shun-iwasawa 481b59
      FOR_EACH_PIXEL_8_END_LOOP
shun-iwasawa 481b59
      return;
Shinya Kitaoka 120a6e
    }
shun-iwasawa 481b59
shun-iwasawa 481b59
    throw TRopException("TRop::sub invalid raster combination");
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TRop::mult(const TRasterP &rup, const TRasterP &rdown,
Shinya Kitaoka 120a6e
                const TRasterP &rout, int v, bool matte) {
Shinya Kitaoka 120a6e
  /*
Shinya Kitaoka 120a6e
Let U be 'up', D be 'down' and M be 'multiplied' (the result), and suppose for
Shinya Kitaoka 120a6e
the moment
Shinya Kitaoka 120a6e
that pixels are both NOT premultiplied and normalized to [0, 1].
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
The additional value v is used to add to RGB components of the U pixel:
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
U'_rgb = (U_rgb + v / 255)
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
The matte component is either U_m D_m in case (matte == true), or D_m in case
Shinya Kitaoka 120a6e
(matte == false).
Shinya Kitaoka 120a6e
Please, observe that in the case (matte == false) that choice makes the product
Shinya Kitaoka 120a6e
NOT COMMUTATIVE,
Shinya Kitaoka 120a6e
but I think that's justified - it's simply the most obvious use case.
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
In case (matte == true), each channel is multiplied independently, and that's
Shinya Kitaoka 120a6e
it.
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
The matter is more complicated when (matte == false). The problem in this case
Shinya Kitaoka 120a6e
is dealing with rgb
Shinya Kitaoka 120a6e
components when U and D both have some transparency.  When U is fully
Shinya Kitaoka 120a6e
transparent, we expect the
Shinya Kitaoka 120a6e
result to be D, and vice-versa, which is non-trivial.
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
We REQUIRE that (let's denote r only here):
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
M_r = M_r_u = U_r (1 - D_m) + U_r D_r D_m,   when  U_m == 1    (When U is fully
Shinya Kitaoka 120a6e
opaque, M_r is a D_m-linear
Shinya Kitaoka 120a6e
                                                                combination of
Shinya Kitaoka 120a6e
U_r and U_r D_r)
Shinya Kitaoka 120a6e
M_r = M_r_d = D_r (1 - U_m) + U_r D_r U_m,   when  D_m == 1    (Vice-versa, when
Shinya Kitaoka 120a6e
it's D that is fully opaque)
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
Finally, we're building a weighted sum, by U_m and D_m of the two above:
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
M_r = (M_r_u * U_m + M_r_d * D_m) / (U_m + D_m) =
Shinya Kitaoka 120a6e
    = (...) =
Shinya Kitaoka 120a6e
    = [ U_r U_m (1 - D_m) + D_r D_m (1 - U_m) + 2 U_r U_m  D_r D_m ] / (U_m +
Shinya Kitaoka 120a6e
D_m)
Shinya Kitaoka 120a6e
*/
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // 32-bit images case
Shinya Kitaoka 120a6e
  TRaster32P up32 = rup, down32 = rdown, out32 = rout;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (up32 && down32 && out32) {
Shinya Kitaoka 120a6e
    static const float maxChannelF = float(TPixel32::maxChannelValue);
Shinya Kitaoka 120a6e
    static const UCHAR maxChannelC = UCHAR(TPixel32::maxChannelValue);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    float vf = v;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (matte) {
Shinya Kitaoka 120a6e
      float dnMf, upMf_norm, outMf;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      FOR_EACH_PIXEL_32_BEGIN_LOOP  // Awful... should be explicit...
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
          dnMf  = downPix->m;
Shinya Kitaoka 120a6e
      upMf_norm = upPix->m / maxChannelF;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      outMf = downPix->m * upMf_norm;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      outPix->r =
Shinya Kitaoka 120a6e
          tcrop((upPix->r / upMf_norm + vf) * (downPix->r / dnMf), 0.0f, outMf);
Shinya Kitaoka 120a6e
      outPix->g =
Shinya Kitaoka 120a6e
          tcrop((upPix->g / upMf_norm + vf) * (downPix->g / dnMf), 0.0f, outMf);
Shinya Kitaoka 120a6e
      outPix->b =
Shinya Kitaoka 120a6e
          tcrop((upPix->b / upMf_norm + vf) * (downPix->b / dnMf), 0.0f, outMf);
Shinya Kitaoka 120a6e
      outPix->m = outMf;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      // NOTE:  + 0.5f in the crop arguments could take care of rounding...
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      FOR_EACH_PIXEL_32_END_LOOP
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      float umf_norm, dmf_norm, umdmf_norm, outMf;
Shinya Kitaoka 120a6e
      float mSumf, uf, df, ufdf, normalizer;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      FOR_EACH_PIXEL_32_BEGIN_LOOP
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      mSumf = upPix->m + float(downPix->m);
Shinya Kitaoka 120a6e
      if (mSumf > 0.0f) {
Shinya Kitaoka 120a6e
        umf_norm = upPix->m / maxChannelF, dmf_norm = downPix->m / maxChannelF;
Shinya Kitaoka 120a6e
        outMf = upPix->m +
Shinya Kitaoka 120a6e
                (1.0f - umf_norm) *
Shinya Kitaoka 120a6e
                    downPix->m;  // umf_norm should be ensured in [0.0, 1.0].
Shinya Kitaoka 120a6e
        // Convex combination should be in the conversion range.
Shinya Kitaoka 120a6e
        normalizer = outMf / (maxChannelF * mSumf);
Shinya Kitaoka 120a6e
        umdmf_norm = umf_norm * dmf_norm;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
        uf = upPix->r + vf * umdmf_norm, df = downPix->r, ufdf = uf * df;
Shinya Kitaoka 120a6e
        outPix->r = tcrop((uf * (maxChannelC - downPix->m) +
Shinya Kitaoka 120a6e
                           df * (maxChannelC - upPix->m) + ufdf + ufdf) *
Shinya Kitaoka 120a6e
                              normalizer,
Shinya Kitaoka 120a6e
                          0.0f, outMf);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
        uf = upPix->g + vf * umdmf_norm, df = downPix->g, ufdf = uf * df;
Shinya Kitaoka 120a6e
        outPix->g = tcrop((uf * (maxChannelC - downPix->m) +
Shinya Kitaoka 120a6e
                           df * (maxChannelC - upPix->m) + ufdf + ufdf) *
Shinya Kitaoka 120a6e
                              normalizer,
Shinya Kitaoka 120a6e
                          0.0f, outMf);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
        uf = upPix->b + vf * umdmf_norm, df = downPix->b, ufdf = uf * df;
Shinya Kitaoka 120a6e
        outPix->b = tcrop((uf * (maxChannelC - downPix->m) +
Shinya Kitaoka 120a6e
                           df * (maxChannelC - upPix->m) + ufdf + ufdf) *
Shinya Kitaoka 120a6e
                              normalizer,
Shinya Kitaoka 120a6e
                          0.0f, outMf);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
        outPix->m = outMf;
Shinya Kitaoka 120a6e
      } else
Shinya Kitaoka 120a6e
        *outPix = TPixel32::Transparent;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      FOR_EACH_PIXEL_32_END_LOOP
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // 64-bit images case
Shinya Kitaoka 120a6e
  TRaster64P up64 = rup, down64 = rdown, out64 = rout;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (up64 && down64 && out64) {
Shinya Kitaoka 120a6e
    static const double maxChannelF = double(TPixel64::maxChannelValue);
Shinya Kitaoka 120a6e
    static const USHORT maxChannelC = USHORT(TPixel64::maxChannelValue);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    double vf =
Shinya Kitaoka 120a6e
        v * (TPixel64::maxChannelValue / double(TPixel32::maxChannelValue));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (matte) {
Shinya Kitaoka 120a6e
      double dnMf, upMf_norm, outMf;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      FOR_EACH_PIXEL_64_BEGIN_LOOP
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      dnMf      = downPix->m;
Shinya Kitaoka 120a6e
      upMf_norm = upPix->m / maxChannelF;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      outMf = downPix->m * upMf_norm;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      outPix->r =
Shinya Kitaoka 120a6e
          tcrop((upPix->r / upMf_norm + vf) * (downPix->r / dnMf), 0.0, outMf);
Shinya Kitaoka 120a6e
      outPix->g =
Shinya Kitaoka 120a6e
          tcrop((upPix->g / upMf_norm + vf) * (downPix->g / dnMf), 0.0, outMf);
Shinya Kitaoka 120a6e
      outPix->b =
Shinya Kitaoka 120a6e
          tcrop((upPix->b / upMf_norm + vf) * (downPix->b / dnMf), 0.0, outMf);
Shinya Kitaoka 120a6e
      outPix->m = outMf;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      FOR_EACH_PIXEL_64_END_LOOP
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      double umf_norm, dmf_norm, umdmf_norm, outMf;
Shinya Kitaoka 120a6e
      double mSumf, uf, df, ufdf, normalizer;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      FOR_EACH_PIXEL_64_BEGIN_LOOP
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      mSumf = upPix->m + double(downPix->m);
Shinya Kitaoka 120a6e
      if (mSumf > 0.0) {
Shinya Kitaoka 120a6e
        umf_norm = upPix->m / maxChannelF, dmf_norm = downPix->m / maxChannelF;
Shinya Kitaoka 120a6e
        outMf = upPix->m + (1.0 - umf_norm) * downPix->m;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        normalizer = outMf / (maxChannelF * mSumf);
Shinya Kitaoka 120a6e
        umdmf_norm = umf_norm * dmf_norm;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        uf = upPix->r + vf * umdmf_norm, df = downPix->r, ufdf = uf * df;
Shinya Kitaoka 120a6e
        outPix->r = tcrop((uf * (maxChannelC - downPix->m) +
Shinya Kitaoka 120a6e
                           df * (maxChannelC - upPix->m) + ufdf + ufdf) *
Shinya Kitaoka 120a6e
                              normalizer,
Shinya Kitaoka 120a6e
                          0.0, outMf);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        uf = upPix->g + vf * umdmf_norm, df = downPix->g, ufdf = uf * df;
Shinya Kitaoka 120a6e
        outPix->g = tcrop((uf * (maxChannelC - downPix->m) +
Shinya Kitaoka 120a6e
                           df * (maxChannelC - upPix->m) + ufdf + ufdf) *
Shinya Kitaoka 120a6e
                              normalizer,
Shinya Kitaoka 120a6e
                          0.0, outMf);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        uf = upPix->b + vf * umdmf_norm, df = downPix->b, ufdf = uf * df;
Shinya Kitaoka 120a6e
        outPix->b = tcrop((uf * (maxChannelC - downPix->m) +
Shinya Kitaoka 120a6e
                           df * (maxChannelC - upPix->m) + ufdf + ufdf) *
Shinya Kitaoka 120a6e
                              normalizer,
Shinya Kitaoka 120a6e
                          0.0, outMf);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        outPix->m = outMf;
Shinya Kitaoka 120a6e
      } else
Shinya Kitaoka 120a6e
        *outPix = TPixel64::Transparent;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      FOR_EACH_PIXEL_64_END_LOOP
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
  // 32-bit floating point images case
shun-iwasawa 481b59
  TRasterFP upF = rup, downF = rdown, outF = rout;
shun-iwasawa 481b59
shun-iwasawa 481b59
  if (upF && downF && outF) {
shun-iwasawa 481b59
    float vf = (float)v / (float)(TPixel32::maxChannelValue);
shun-iwasawa 481b59
shun-iwasawa 481b59
    if (matte) {
shun-iwasawa 481b59
      float outMf;
shun-iwasawa 481b59
shun-iwasawa 481b59
      FOR_EACH_PIXEL_F_BEGIN_LOOP
shun-iwasawa 481b59
shun-iwasawa 481b59
      outMf = downPix->m * upPix->m;
shun-iwasawa 481b59
shun-iwasawa 481b59
      outPix->r = tcrop((upPix->r / upPix->m + vf) * (downPix->r / downPix->m),
shun-iwasawa 481b59
                        0.f, outMf);
shun-iwasawa 481b59
      outPix->g = tcrop((upPix->g / upPix->m + vf) * (downPix->g / downPix->m),
shun-iwasawa 481b59
                        0.f, outMf);
shun-iwasawa 481b59
      outPix->b = tcrop((upPix->b / upPix->m + vf) * (downPix->b / downPix->m),
shun-iwasawa 481b59
                        0.f, outMf);
shun-iwasawa 481b59
      outPix->m = outMf;
shun-iwasawa 481b59
shun-iwasawa 481b59
      FOR_EACH_PIXEL_F_END_LOOP
shun-iwasawa 481b59
    } else {
shun-iwasawa 481b59
      float umdmf_norm, outMf;
shun-iwasawa 481b59
      float mSumf, uf, df, ufdf, normalizer;
shun-iwasawa 481b59
shun-iwasawa 481b59
      FOR_EACH_PIXEL_F_BEGIN_LOOP
shun-iwasawa 481b59
shun-iwasawa 481b59
      mSumf = upPix->m + downPix->m;
shun-iwasawa 481b59
      if (mSumf > 0.f) {
shun-iwasawa 481b59
        outMf = upPix->m + (1.f - upPix->m) * downPix->m;
shun-iwasawa 481b59
shun-iwasawa 481b59
        normalizer = outMf / mSumf;
shun-iwasawa 481b59
        umdmf_norm = upPix->m * downPix->m;
shun-iwasawa 481b59
        ;
shun-iwasawa 481b59
shun-iwasawa 481b59
        uf        = upPix->r + vf * umdmf_norm;
shun-iwasawa 481b59
        df        = downPix->r;
shun-iwasawa 481b59
        ufdf      = uf * df;
shun-iwasawa 481b59
        outPix->r = tcrop(
shun-iwasawa 481b59
            (uf * (1.f - downPix->m) + df * (1.f - upPix->m) + ufdf + ufdf) *
shun-iwasawa 481b59
                normalizer,
shun-iwasawa 481b59
            0.f, outMf);
shun-iwasawa 481b59
shun-iwasawa 481b59
        uf        = upPix->g + vf * umdmf_norm;
shun-iwasawa 481b59
        df        = downPix->g;
shun-iwasawa 481b59
        ufdf      = uf * df;
shun-iwasawa 481b59
        outPix->g = tcrop(
shun-iwasawa 481b59
            (uf * (1.f - downPix->m) + df * (1.f - upPix->m) + ufdf + ufdf) *
shun-iwasawa 481b59
                normalizer,
shun-iwasawa 481b59
            0.f, outMf);
shun-iwasawa 481b59
shun-iwasawa 481b59
        uf        = upPix->b + vf * umdmf_norm;
shun-iwasawa 481b59
        df        = downPix->b;
shun-iwasawa 481b59
        ufdf      = uf * df;
shun-iwasawa 481b59
        outPix->b = tcrop(
shun-iwasawa 481b59
            (uf * (1.f - downPix->m) + df * (1.f - upPix->m) + ufdf + ufdf) *
shun-iwasawa 481b59
                normalizer,
shun-iwasawa 481b59
            0.f, outMf);
shun-iwasawa 481b59
shun-iwasawa 481b59
        outPix->m = outMf;
shun-iwasawa 481b59
      } else
shun-iwasawa 481b59
        *outPix = TPixelF::Transparent;
shun-iwasawa 481b59
shun-iwasawa 481b59
      FOR_EACH_PIXEL_F_END_LOOP
shun-iwasawa 481b59
    }
shun-iwasawa 481b59
shun-iwasawa 481b59
    return;
shun-iwasawa 481b59
  }
shun-iwasawa 481b59
Shinya Kitaoka 120a6e
  // According to the specifics, throw an exception. I think it's not
Shinya Kitaoka 120a6e
  // appropriate, though.
Shinya Kitaoka 120a6e
  throw TRopException("TRop::mult invalid raster combination");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TRop::ropin(const TRasterP &source, const TRasterP &matte,
Shinya Kitaoka 120a6e
                 const TRasterP &rout) {
Shinya Kitaoka 120a6e
  TRaster32P source32 = source;
Shinya Kitaoka 120a6e
  TRaster32P matte32  = matte;
Shinya Kitaoka 120a6e
  TRaster32P out32    = rout;
Shinya Kitaoka 120a6e
  TRaster64P source64 = source;
Shinya Kitaoka 120a6e
  TRaster64P matte64  = matte;
Shinya Kitaoka 120a6e
  TRaster64P out64    = rout;
shun-iwasawa 481b59
  TRasterFP sourceF   = source;
shun-iwasawa 481b59
  TRasterFP matteF    = matte;
shun-iwasawa 481b59
  TRasterFP outF      = rout;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (source32 && matte32 && out32) {
Shinya Kitaoka 120a6e
    FOR_EACH_PIXEL_BEGIN_LOOP(TPixelRGBM32, source32, TPixelRGBM32, matte32,
Shinya Kitaoka 120a6e
                              TPixelRGBM32, out32)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (downPix->m == 0)
Shinya Kitaoka 120a6e
      outPix->r = outPix->g = outPix->b = outPix->m = 0;
Shinya Kitaoka 120a6e
    else if (downPix->m == 255)
Shinya Kitaoka 120a6e
      *outPix = *upPix;
Shinya Kitaoka 120a6e
    else {
Shinya Kitaoka 120a6e
      /*
Shinya Kitaoka 120a6e
__m128i zeros = _mm_setzero_si128();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
__m128i upPix_packed_i= _mm_unpacklo_epi8(_mm_cvtsi32_si128(*(DWORD*)upPix),
Shinya Kitaoka 120a6e
zeros);
Shinya Kitaoka 120a6e
__m128  upPix_packed  = _mm_cvtepi32_ps(_mm_unpacklo_epi16(upPix_packed_i,
Shinya Kitaoka 120a6e
zeros));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
float fac = downPix->m / 255.0;
Shinya Kitaoka 120a6e
__m128 fac_packed = _mm_load1_ps(&fac);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
upPix_packed = _mm_mul_ps(upPix_packed, fac_packed);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
__m128i outPix_packed_i = _mm_cvtps_epi32(upPix_packed);
Shinya Kitaoka 120a6e
outPix_packed_i = _mm_packs_epi32(outPix_packed_i, zeros);
Shinya Kitaoka 120a6e
outPix_packed_i = _mm_packus_epi16(outPix_packed_i, zeros);
Shinya Kitaoka 120a6e
*(DWORD*)(outPix) = _mm_cvtsi128_si32(outPix_packed_i);
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      const int MAGICFAC = (257U * 256U + 1U);
Shinya Kitaoka 120a6e
      UINT fac           = MAGICFAC * downPix->m;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      outPix->r = (UINT)(upPix->r * fac + (1U << 23)) >> 24;
Shinya Kitaoka 120a6e
      outPix->g = (UINT)(upPix->g * fac + (1U << 23)) >> 24;
Shinya Kitaoka 120a6e
      outPix->b = (UINT)(upPix->b * fac + (1U << 23)) >> 24;
Shinya Kitaoka 120a6e
      outPix->m = (UINT)(upPix->m * fac + (1U << 23)) >> 24;
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    FOR_EACH_PIXEL_END_LOOP(source32, matte32, out32)
Shinya Kitaoka 120a6e
  } else if (source64 && matte64 && out64)
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    FOR_EACH_PIXEL_BEGIN_LOOP(TPixelRGBM64, source64, TPixelRGBM64, matte64,
Shinya Kitaoka 120a6e
                              TPixelRGBM64, out64)
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (downPix->m == 0)
Shinya Kitaoka 120a6e
      outPix->r = outPix->g = outPix->b = outPix->m = 0;
Shinya Kitaoka 120a6e
    else if (downPix->m == 65535)
Shinya Kitaoka 120a6e
      *outPix = *upPix;
Shinya Kitaoka 120a6e
    else {
Shinya Kitaoka 120a6e
      /*
Shinya Kitaoka 120a6e
__m128i zeros = _mm_setzero_si128();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
__m128i upPix_packed_i= _mm_unpacklo_epi8(_mm_cvtsi32_si128(*(DWORD*)upPix),
Shinya Kitaoka 120a6e
zeros);
Shinya Kitaoka 120a6e
__m128  upPix_packed  = _mm_cvtepi32_ps(_mm_unpacklo_epi16(upPix_packed_i,
Shinya Kitaoka 120a6e
zeros));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
float fac = downPix->m / 255.0;
Shinya Kitaoka 120a6e
__m128 fac_packed = _mm_load1_ps(&fac);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
upPix_packed = _mm_mul_ps(upPix_packed, fac_packed);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
__m128i outPix_packed_i = _mm_cvtps_epi32(upPix_packed);
Shinya Kitaoka 120a6e
outPix_packed_i = _mm_packs_epi32(outPix_packed_i, zeros);
Shinya Kitaoka 120a6e
outPix_packed_i = _mm_packus_epi16(outPix_packed_i, zeros);
Shinya Kitaoka 120a6e
*(DWORD*)(outPix) = _mm_cvtsi128_si32(outPix_packed_i);
Toshihiro Shimizu 890ddd
*/
Shinya Kitaoka 120a6e
      double fac = downPix->m / 65535.0;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      outPix->r = (USHORT)(upPix->r * fac);
Shinya Kitaoka 120a6e
      outPix->g = (USHORT)(upPix->g * fac);
Shinya Kitaoka 120a6e
      outPix->b = (USHORT)(upPix->b * fac);
Shinya Kitaoka 120a6e
      outPix->m = (USHORT)(upPix->m * fac);
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    FOR_EACH_PIXEL_END_LOOP(source64, matte64, out64)
shun-iwasawa 481b59
  } else if (sourceF && matteF && outF) {
shun-iwasawa 481b59
    FOR_EACH_PIXEL_BEGIN_LOOP(TPixelF, sourceF, TPixelF, matteF, TPixelF, outF)
shun-iwasawa 481b59
shun-iwasawa 481b59
    if (downPix->m <= 0.f)
shun-iwasawa 481b59
      outPix->r = outPix->g = outPix->b = outPix->m = 0.f;
shun-iwasawa 481b59
    else if (downPix->m >= 1.f)
shun-iwasawa 481b59
      *outPix = *upPix;
shun-iwasawa 481b59
    else {
shun-iwasawa 481b59
      outPix->r = upPix->r * downPix->m;
shun-iwasawa 481b59
      outPix->g = upPix->g * downPix->m;
shun-iwasawa 481b59
      outPix->b = upPix->b * downPix->m;
shun-iwasawa 481b59
      outPix->m = upPix->m * downPix->m;
shun-iwasawa 481b59
    }
shun-iwasawa 481b59
shun-iwasawa 481b59
    FOR_EACH_PIXEL_END_LOOP(sourceF, matteF, outF)
Shinya Kitaoka 120a6e
  } else
Shinya Kitaoka 120a6e
    throw TRopException("TRop::in invalid raster combination");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TRop::ropout(const TRasterP &source, const TRasterP &matte,
Shinya Kitaoka 120a6e
                  const TRasterP &rout) {
Shinya Kitaoka 120a6e
  TRaster32P source32 = source;
Shinya Kitaoka 120a6e
  TRaster32P matte32  = matte;
Shinya Kitaoka 120a6e
  TRaster32P out32    = rout;
Shinya Kitaoka 120a6e
  TRaster64P source64 = source;
Shinya Kitaoka 120a6e
  TRaster64P matte64  = matte;
Shinya Kitaoka 120a6e
  TRaster64P out64    = rout;
shun-iwasawa 481b59
  TRasterFP sourceF   = source;
shun-iwasawa 481b59
  TRasterFP matteF    = matte;
shun-iwasawa 481b59
  TRasterFP outF      = rout;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (source32 && matte32 && out32) {
Shinya Kitaoka 120a6e
    FOR_EACH_PIXEL_BEGIN_LOOP(TPixelRGBM32, source32, TPixelRGBM32, matte32,
Shinya Kitaoka 120a6e
                              TPixelRGBM32, out32)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (downPix->m == 255)
Shinya Kitaoka 120a6e
      outPix->r = outPix->g = outPix->b = outPix->m = 0;
Shinya Kitaoka 120a6e
    else if (downPix->m == 0)
Shinya Kitaoka 120a6e
      *outPix = *upPix;
Shinya Kitaoka 120a6e
    else {
Shinya Kitaoka 120a6e
      const int MAGICFAC = (257U * 256U + 1U);
Shinya Kitaoka 120a6e
      UINT fac           = MAGICFAC * (255 - downPix->m);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      outPix->r = (UINT)(upPix->r * fac + (1U << 23)) >> 24;
Shinya Kitaoka 120a6e
      outPix->g = (UINT)(upPix->g * fac + (1U << 23)) >> 24;
Shinya Kitaoka 120a6e
      outPix->b = (UINT)(upPix->b * fac + (1U << 23)) >> 24;
Shinya Kitaoka 120a6e
      outPix->m = (UINT)(upPix->m * fac + (1U << 23)) >> 24;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    FOR_EACH_PIXEL_END_LOOP(source32, matte32, out32)
Shinya Kitaoka 120a6e
  } else if (source64 && matte64 && out64) {
Shinya Kitaoka 120a6e
    FOR_EACH_PIXEL_BEGIN_LOOP(TPixelRGBM64, source64, TPixelRGBM64, matte64,
Shinya Kitaoka 120a6e
                              TPixelRGBM64, out64)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (downPix->m == 65535)
Shinya Kitaoka 120a6e
      outPix->r = outPix->g = outPix->b = outPix->m = 0;
Shinya Kitaoka 120a6e
    else if (downPix->m == 0)
Shinya Kitaoka 120a6e
      *outPix = *upPix;
Shinya Kitaoka 120a6e
    else {
Shinya Kitaoka 120a6e
      double fac = (65535 - downPix->m) / 65535.0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      outPix->r = (USHORT)(upPix->r * fac);
Shinya Kitaoka 120a6e
      outPix->g = (USHORT)(upPix->g * fac);
Shinya Kitaoka 120a6e
      outPix->b = (USHORT)(upPix->b * fac);
Shinya Kitaoka 120a6e
      outPix->m = (USHORT)(upPix->m * fac);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    FOR_EACH_PIXEL_END_LOOP(source64, matte64, out64)
shun-iwasawa 481b59
  } else if (sourceF && matteF && outF) {
shun-iwasawa 481b59
    FOR_EACH_PIXEL_BEGIN_LOOP(TPixelF, sourceF, TPixelF, matteF, TPixelF, outF)
shun-iwasawa 481b59
shun-iwasawa 481b59
    if (downPix->m >= 1.f)
shun-iwasawa 481b59
      outPix->r = outPix->g = outPix->b = outPix->m = 0;
shun-iwasawa 481b59
    else if (downPix->m <= 0.f)
shun-iwasawa 481b59
      *outPix = *upPix;
shun-iwasawa 481b59
    else {
shun-iwasawa 481b59
      float fac = 1.f - downPix->m;
shun-iwasawa 481b59
shun-iwasawa 481b59
      outPix->r = upPix->r * fac;
shun-iwasawa 481b59
      outPix->g = upPix->g * fac;
shun-iwasawa 481b59
      outPix->b = upPix->b * fac;
shun-iwasawa 481b59
      outPix->m = upPix->m * fac;
shun-iwasawa 481b59
    }
shun-iwasawa 481b59
shun-iwasawa 481b59
    FOR_EACH_PIXEL_END_LOOP(sourceF, matteF, outF)
Shinya Kitaoka 120a6e
  } else
Shinya Kitaoka 120a6e
    throw TRopException("TRop::out invalid raster combination");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TRop::atop(const TRasterP &rup, const TRasterP &rdown,
Shinya Kitaoka 120a6e
                const TRasterP &rout) {
Shinya Kitaoka 120a6e
  // calcola rup ATOP rdown
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // da ottimizzare...
Shinya Kitaoka 120a6e
  TRaster32P up32   = rup;
Shinya Kitaoka 120a6e
  TRaster32P down32 = rdown;
Shinya Kitaoka 120a6e
  TRaster32P out32  = rout;
Shinya Kitaoka 120a6e
  TRaster64P up64   = rup;
Shinya Kitaoka 120a6e
  TRaster64P down64 = rdown;
Shinya Kitaoka 120a6e
  TRaster64P out64  = rout;
shun-iwasawa 481b59
  TRasterFP upF     = rup;
shun-iwasawa 481b59
  TRasterFP downF   = rdown;
shun-iwasawa 481b59
  TRasterFP outF    = rout;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (up32 && down32 && out32) {
Shinya Kitaoka 120a6e
    FOR_EACH_PIXEL_32_BEGIN_LOOP
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TPixel32 tmpPix(0, 0, 0, 0);
Shinya Kitaoka 120a6e
    if (downPix->m != 0) {
Shinya Kitaoka 120a6e
      const int MAGICFAC = (257U * 256U + 1U);
Shinya Kitaoka 120a6e
      UINT fac           = MAGICFAC * downPix->m;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      tmpPix.r = (UINT)(upPix->r * fac + (1U << 23)) >> 24;
Shinya Kitaoka 120a6e
      tmpPix.g = (UINT)(upPix->g * fac + (1U << 23)) >> 24;
Shinya Kitaoka 120a6e
      tmpPix.b = (UINT)(upPix->b * fac + (1U << 23)) >> 24;
Shinya Kitaoka 120a6e
      tmpPix.m = (UINT)(upPix->m * fac + (1U << 23)) >> 24;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    overPix<tpixel32, uchar="">(*outPix, *downPix, tmpPix);</tpixel32,>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    FOR_EACH_PIXEL_32_END_LOOP
Shinya Kitaoka 120a6e
  } else if (up64 && down64 && out64) {
Shinya Kitaoka 120a6e
    FOR_EACH_PIXEL_64_BEGIN_LOOP
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TPixel64 tmpPix(0, 0, 0, 0);
Shinya Kitaoka 120a6e
    if (downPix->m != 0) {
Shinya Kitaoka 120a6e
      double fac = downPix->m / 65535.0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      tmpPix.r = (USHORT)(upPix->r * fac);
Shinya Kitaoka 120a6e
      tmpPix.g = (USHORT)(upPix->g * fac);
Shinya Kitaoka 120a6e
      tmpPix.b = (USHORT)(upPix->b * fac);
Shinya Kitaoka 120a6e
      tmpPix.m = (USHORT)(upPix->m * fac);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    overPix<tpixel64, ushort="">(*outPix, *downPix, tmpPix);</tpixel64,>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    FOR_EACH_PIXEL_64_END_LOOP
shun-iwasawa 481b59
  } else if (upF && downF && outF) {
shun-iwasawa 481b59
    FOR_EACH_PIXEL_F_BEGIN_LOOP
shun-iwasawa 481b59
shun-iwasawa 481b59
    TPixelF tmpPix = TPixelF::Transparent;
shun-iwasawa 481b59
    if (downPix->m >= 0.f) {
shun-iwasawa 481b59
      tmpPix.r = upPix->r * downPix->m;
shun-iwasawa 481b59
      tmpPix.g = upPix->g * downPix->m;
shun-iwasawa 481b59
      tmpPix.b = upPix->b * downPix->m;
shun-iwasawa 481b59
      tmpPix.m = upPix->m * downPix->m;
shun-iwasawa 481b59
    }
shun-iwasawa 481b59
shun-iwasawa 481b59
    overPix<tpixelf, float="">(*outPix, *downPix, tmpPix);</tpixelf,>
shun-iwasawa 481b59
    FOR_EACH_PIXEL_F_END_LOOP
Shinya Kitaoka 120a6e
  } else
Shinya Kitaoka 120a6e
    throw TRopException("TRop::atop invalid raster combination");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TRop::txor(const TRasterP &rup, const TRasterP &rdown,
Shinya Kitaoka 120a6e
                const TRasterP &rout) {
Shinya Kitaoka 120a6e
  // da ottimizzare...
Shinya Kitaoka 120a6e
  TRaster32P up32   = rup;
Shinya Kitaoka 120a6e
  TRaster32P down32 = rdown;
Shinya Kitaoka 120a6e
  TRaster32P out32  = rout;
Shinya Kitaoka 120a6e
  TRaster64P up64   = rup;
Shinya Kitaoka 120a6e
  TRaster64P down64 = rdown;
Shinya Kitaoka 120a6e
  TRaster64P out64  = rout;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (up32 && down32 && out32) {
Shinya Kitaoka 120a6e
    FOR_EACH_PIXEL_32_BEGIN_LOOP
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    TUINT32 notUpM   = 255 - upPix->m;
Shinya Kitaoka 120a6e
    TUINT32 notDownM = 255 - downPix->m;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    TUINT32 r = notUpM + upPix->r * (notDownM);
Shinya Kitaoka 120a6e
    TUINT32 g = notUpM + upPix->g * (notDownM);
Shinya Kitaoka 120a6e
    TUINT32 b = notUpM + upPix->b * (notDownM);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    outPix->r = (UCHAR)tcrop<tuint32>(0, 255, r);</tuint32>
Shinya Kitaoka 120a6e
    outPix->g = (UCHAR)tcrop<tuint32>(0, 255, g);</tuint32>
Shinya Kitaoka 120a6e
    outPix->b = (UCHAR)tcrop<tuint32>(0, 255, b);</tuint32>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    FOR_EACH_PIXEL_32_END_LOOP
Shinya Kitaoka 120a6e
  } else if (up64 && down64 && out64) {
Shinya Kitaoka 120a6e
    FOR_EACH_PIXEL_64_BEGIN_LOOP
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    TUINT32 notUpM   = 65535 - upPix->m;
Shinya Kitaoka 120a6e
    TUINT32 notDownM = 65535 - downPix->m;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    TUINT32 r = notUpM + upPix->r * (notDownM);
Shinya Kitaoka 120a6e
    TUINT32 g = notUpM + upPix->g * (notDownM);
Shinya Kitaoka 120a6e
    TUINT32 b = notUpM + upPix->b * (notDownM);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    outPix->r = (USHORT)tcrop<tuint32>(0, 65535, r);</tuint32>
Shinya Kitaoka 120a6e
    outPix->g = (USHORT)tcrop<tuint32>(0, 65535, g);</tuint32>
Shinya Kitaoka 120a6e
    outPix->b = (USHORT)tcrop<tuint32>(0, 65535, b);</tuint32>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    FOR_EACH_PIXEL_64_END_LOOP
Shinya Kitaoka 120a6e
  } else
Shinya Kitaoka 120a6e
    throw TRopException("TRop::xor invalid raster combination");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TRop::crossDissolve(const TRasterP &rup, const TRasterP &rdown,
Shinya Kitaoka 120a6e
                         const TRasterP &rout, UCHAR v) {
Shinya Kitaoka 120a6e
  TRaster32P up32   = rup;
Shinya Kitaoka 120a6e
  TRaster32P down32 = rdown;
Shinya Kitaoka 120a6e
  TRaster32P out32  = rout;
Shinya Kitaoka 120a6e
  TRaster64P up64   = rup;
Shinya Kitaoka 120a6e
  TRaster64P down64 = rdown;
Shinya Kitaoka 120a6e
  TRaster64P out64  = rout;
shun-iwasawa 481b59
  TRasterFP upF     = rup;
shun-iwasawa 481b59
  TRasterFP downF   = rdown;
shun-iwasawa 481b59
  TRasterFP outF    = rout;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (up32 && down32 && out32) {
Shinya Kitaoka 120a6e
    FOR_EACH_PIXEL_32_BEGIN_LOOP
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    outPix->r = (upPix->r * v + downPix->r * (255 - v)) / 255;
Shinya Kitaoka 120a6e
    outPix->g = (upPix->g * v + downPix->g * (255 - v)) / 255;
Shinya Kitaoka 120a6e
    outPix->b = (upPix->b * v + downPix->b * (255 - v)) / 255;
Shinya Kitaoka 120a6e
    outPix->m = (upPix->m * v + downPix->m * (255 - v)) / 255;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    FOR_EACH_PIXEL_32_END_LOOP
Shinya Kitaoka 120a6e
  } else if (up64 && down64 && out64) {
Shinya Kitaoka 120a6e
    USHORT vv = v * 257;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    FOR_EACH_PIXEL_64_BEGIN_LOOP
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    outPix->r = (upPix->r * vv + downPix->r * (65535 - vv)) / 65535;
Shinya Kitaoka 120a6e
    outPix->g = (upPix->g * vv + downPix->g * (65535 - vv)) / 65535;
Shinya Kitaoka 120a6e
    outPix->b = (upPix->b * vv + downPix->b * (65535 - vv)) / 65535;
Shinya Kitaoka 120a6e
    outPix->m = (upPix->m * vv + downPix->m * (65535 - vv)) / 65535;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    FOR_EACH_PIXEL_64_END_LOOP
shun-iwasawa 481b59
  } else if (upF && downF && outF) {
shun-iwasawa 481b59
    float vv = (float)v / 255.0f;
shun-iwasawa 481b59
    FOR_EACH_PIXEL_F_BEGIN_LOOP
shun-iwasawa 481b59
shun-iwasawa 481b59
    outPix->r = upPix->r * vv + downPix->r * (1.f - vv);
shun-iwasawa 481b59
    outPix->g = upPix->g * vv + downPix->g * (1.f - vv);
shun-iwasawa 481b59
    outPix->b = upPix->b * vv + downPix->b * (1.f - vv);
shun-iwasawa 481b59
    outPix->m = upPix->m * vv + downPix->m * (1.f - vv);
shun-iwasawa 481b59
shun-iwasawa 481b59
    FOR_EACH_PIXEL_F_END_LOOP
Shinya Kitaoka 120a6e
  } else
Shinya Kitaoka 120a6e
    throw TRopException("TRop::crossDissolve invalid raster combination");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TRop::darken(const TRasterP &rup, const TRasterP &rdown,
Shinya Kitaoka 120a6e
                  const TRasterP &rout) {
Shinya Kitaoka 120a6e
  TRaster32P up32   = rup;
Shinya Kitaoka 120a6e
  TRaster32P down32 = rdown;
Shinya Kitaoka 120a6e
  TRaster32P out32  = rout;
Shinya Kitaoka 120a6e
  TRaster64P up64   = rup;
Shinya Kitaoka 120a6e
  TRaster64P down64 = rdown;
Shinya Kitaoka 120a6e
  TRaster64P out64  = rout;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (up32 && down32 && out32) {
Shinya Kitaoka 120a6e
    FOR_EACH_PIXEL_32_BEGIN_LOOP
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    double value0 = luminance(upPix);
Shinya Kitaoka 120a6e
    double value1 = luminance(downPix);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (value0 < value1)
Shinya Kitaoka 120a6e
      *outPix = *upPix;
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      *outPix = *downPix;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    FOR_EACH_PIXEL_32_END_LOOP
Shinya Kitaoka 120a6e
  } else if (up64 && down64 && out64) {
Shinya Kitaoka 120a6e
    FOR_EACH_PIXEL_64_BEGIN_LOOP
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    double value0 = luminance(upPix);
Shinya Kitaoka 120a6e
    double value1 = luminance(downPix);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (value0 < value1)
Shinya Kitaoka 120a6e
      *outPix = *upPix;
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      *outPix = *downPix;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    FOR_EACH_PIXEL_64_END_LOOP
Shinya Kitaoka 120a6e
  } else
Shinya Kitaoka 120a6e
    throw TRopException("TRop::darken invalid raster combination");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TRop::lighten(const TRasterP &rup, const TRasterP &rdown,
Shinya Kitaoka 120a6e
                   const TRasterP &rout) {
Shinya Kitaoka 120a6e
  TRaster32P up32   = rup;
Shinya Kitaoka 120a6e
  TRaster32P down32 = rdown;
Shinya Kitaoka 120a6e
  TRaster32P out32  = rout;
Shinya Kitaoka 120a6e
  TRaster64P up64   = rup;
Shinya Kitaoka 120a6e
  TRaster64P down64 = rdown;
Shinya Kitaoka 120a6e
  TRaster64P out64  = rout;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (up32 && down32 && out32) {
Shinya Kitaoka 120a6e
    FOR_EACH_PIXEL_32_BEGIN_LOOP
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    double value0 = luminance(upPix);
Shinya Kitaoka 120a6e
    double value1 = luminance(downPix);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (value0 > value1) {
Shinya Kitaoka 120a6e
      TINT32 r, g, b, m;
Shinya Kitaoka 120a6e
      if (upPix->m == 0)
Shinya Kitaoka 120a6e
        *outPix = *downPix;
Shinya Kitaoka 120a6e
      else {
Shinya Kitaoka 120a6e
        r         = downPix->r + upPix->r;
Shinya Kitaoka 120a6e
        g         = downPix->g + upPix->g;
Shinya Kitaoka 120a6e
        b         = downPix->b + upPix->b;
Shinya Kitaoka 120a6e
        m         = downPix->m + upPix->m;
Shinya Kitaoka 120a6e
        outPix->r = (UCHAR)tcrop<tint32>(r, (TINT32)0, (TINT32)255);</tint32>
Shinya Kitaoka 120a6e
        outPix->g = (UCHAR)tcrop<tint32>(g, (TINT32)0, (TINT32)255);</tint32>
Shinya Kitaoka 120a6e
        outPix->b = (UCHAR)tcrop<tint32>(b, (TINT32)0, (TINT32)255);</tint32>
Shinya Kitaoka 120a6e
        outPix->m = (UCHAR)tcrop<tint32>(m, (TINT32)0, (TINT32)255);</tint32>
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      *outPix = *downPix;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    FOR_EACH_PIXEL_32_END_LOOP
Shinya Kitaoka 120a6e
  } else if (up64 && down64 && out64) {
Shinya Kitaoka 120a6e
    FOR_EACH_PIXEL_64_BEGIN_LOOP
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    double value0 = luminance(upPix);
Shinya Kitaoka 120a6e
    double value1 = luminance(downPix);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (value0 > value1) {
Shinya Kitaoka 120a6e
      TINT32 r, g, b, m;
Shinya Kitaoka 120a6e
      if (upPix->m == 0)
Shinya Kitaoka 120a6e
        *outPix = *downPix;
Shinya Kitaoka 120a6e
      else {
Shinya Kitaoka 120a6e
        r         = downPix->r + upPix->r;
Shinya Kitaoka 120a6e
        g         = downPix->g + upPix->g;
Shinya Kitaoka 120a6e
        b         = downPix->b + upPix->b;
Shinya Kitaoka 120a6e
        m         = downPix->m + upPix->m;
Shinya Kitaoka 120a6e
        outPix->r = (USHORT)tcrop<tint32>(r, (TINT32)0, (TINT32)65535);</tint32>
Shinya Kitaoka 120a6e
        outPix->g = (USHORT)tcrop<tint32>(g, (TINT32)0, (TINT32)65535);</tint32>
Shinya Kitaoka 120a6e
        outPix->b = (USHORT)tcrop<tint32>(b, (TINT32)0, (TINT32)65535);</tint32>
Shinya Kitaoka 120a6e
        outPix->m = (USHORT)tcrop<tint32>(m, (TINT32)0, (TINT32)65535);</tint32>
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      *outPix = *downPix;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    FOR_EACH_PIXEL_64_END_LOOP
Shinya Kitaoka 120a6e
  } else
Shinya Kitaoka 120a6e
    throw TRopException("TRop::lighten invalid raster combination");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TRop::ropmin(const TRasterP &rup, const TRasterP &rdown,
Shinya Kitaoka 120a6e
                  const TRasterP &rout, bool matte) {
Shinya Kitaoka 120a6e
  TRaster32P up32   = rup;
Shinya Kitaoka 120a6e
  TRaster32P down32 = rdown;
Shinya Kitaoka 120a6e
  TRaster32P out32  = rout;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (up32 && down32 && out32) {
Shinya Kitaoka 120a6e
    if (matte) {
Shinya Kitaoka 120a6e
      FOR_EACH_PIXEL_32_BEGIN_LOOP
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      outPix->r = upPix->r < downPix->r ? upPix->r : downPix->r;
Shinya Kitaoka 120a6e
      outPix->g = upPix->g < downPix->g ? upPix->g : downPix->g;
Shinya Kitaoka 120a6e
      outPix->b = upPix->b < downPix->b ? upPix->b : downPix->b;
Shinya Kitaoka 120a6e
      outPix->m = upPix->m < downPix->m ? upPix->m : downPix->m;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      FOR_EACH_PIXEL_32_END_LOOP
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      FOR_EACH_PIXEL_32_BEGIN_LOOP
Shinya Kitaoka 120a6e
      if (upPix->m >= 255) {
Shinya Kitaoka 120a6e
        outPix->r = upPix->r < downPix->r ? upPix->r : downPix->r;
Shinya Kitaoka 120a6e
        outPix->g = upPix->g < downPix->g ? upPix->g : downPix->g;
Shinya Kitaoka 120a6e
        outPix->b = upPix->b < downPix->b ? upPix->b : downPix->b;
Shinya Kitaoka 120a6e
        outPix->m = upPix->m < downPix->m ? upPix->m : downPix->m;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      } else if (upPix->m) {
Shinya Kitaoka 120a6e
        TPixel32 tmp;
Shinya Kitaoka 120a6e
        tmp.r = upPix->r < downPix->r ? upPix->r : downPix->r;
Shinya Kitaoka 120a6e
        tmp.g = upPix->g < downPix->g ? upPix->g : downPix->g;
Shinya Kitaoka 120a6e
        tmp.b = upPix->b < downPix->b ? upPix->b : downPix->b;
Shinya Kitaoka 120a6e
        // tmp.m = upPix->m < downPix->m ? upPix->m : downPix->m;
Shinya Kitaoka 120a6e
        outPix->r = upPix->m * (tmp.r - downPix->r) / 255.0 + downPix->r;
Shinya Kitaoka 120a6e
        outPix->g = upPix->m * (tmp.g - downPix->g) / 255.0 + downPix->g;
Shinya Kitaoka 120a6e
        outPix->b = upPix->m * (tmp.b - downPix->b) / 255.0 + downPix->b;
Shinya Kitaoka 120a6e
        outPix->m = upPix->m * (tmp.m - downPix->m) / 255.0 + downPix->m;
Shinya Kitaoka 120a6e
      } else
Shinya Kitaoka 120a6e
        *outPix = *downPix;
Shinya Kitaoka 120a6e
      FOR_EACH_PIXEL_32_END_LOOP
Shinya Kitaoka 120a6e
    }
shun-iwasawa 481b59
    return;
shun-iwasawa 481b59
  }
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
  TRaster64P up64   = rup;
shun-iwasawa 481b59
  TRaster64P down64 = rdown;
shun-iwasawa 481b59
  TRaster64P out64  = rout;
shun-iwasawa 481b59
shun-iwasawa 481b59
  if (up64 && down64 && out64) {
shun-iwasawa 481b59
    if (matte) {
shun-iwasawa 481b59
      FOR_EACH_PIXEL_64_BEGIN_LOOP
shun-iwasawa 481b59
shun-iwasawa 481b59
      outPix->r = upPix->r < downPix->r ? upPix->r : downPix->r;
shun-iwasawa 481b59
      outPix->g = upPix->g < downPix->g ? upPix->g : downPix->g;
shun-iwasawa 481b59
      outPix->b = upPix->b < downPix->b ? upPix->b : downPix->b;
shun-iwasawa 481b59
      outPix->m = upPix->m < downPix->m ? upPix->m : downPix->m;
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
      FOR_EACH_PIXEL_64_END_LOOP
shun-iwasawa 481b59
    } else {
shun-iwasawa 481b59
      FOR_EACH_PIXEL_32_BEGIN_LOOP
shun-iwasawa 481b59
      if (upPix->m >= 65535) {
Shinya Kitaoka 120a6e
        outPix->r = upPix->r < downPix->r ? upPix->r : downPix->r;
Shinya Kitaoka 120a6e
        outPix->g = upPix->g < downPix->g ? upPix->g : downPix->g;
Shinya Kitaoka 120a6e
        outPix->b = upPix->b < downPix->b ? upPix->b : downPix->b;
Shinya Kitaoka 120a6e
        outPix->m = upPix->m < downPix->m ? upPix->m : downPix->m;
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
      } else if (upPix->m) {
shun-iwasawa 481b59
        TPixel32 tmp;
shun-iwasawa 481b59
        tmp.r = upPix->r < downPix->r ? upPix->r : downPix->r;
shun-iwasawa 481b59
        tmp.g = upPix->g < downPix->g ? upPix->g : downPix->g;
shun-iwasawa 481b59
        tmp.b = upPix->b < downPix->b ? upPix->b : downPix->b;
shun-iwasawa 481b59
        // tmp.m = upPix->m < downPix->m ? upPix->m : downPix->m;
shun-iwasawa 481b59
        outPix->r = upPix->m * (tmp.r - downPix->r) / 65535.0 + downPix->r;
shun-iwasawa 481b59
        outPix->g = upPix->m * (tmp.g - downPix->g) / 65535.0 + downPix->g;
shun-iwasawa 481b59
        outPix->b = upPix->m * (tmp.b - downPix->b) / 65535.0 + downPix->b;
shun-iwasawa 481b59
        outPix->m = upPix->m * (tmp.m - downPix->m) / 65535.0 + downPix->m;
shun-iwasawa 481b59
      } else
shun-iwasawa 481b59
        *outPix = *downPix;
shun-iwasawa 481b59
      FOR_EACH_PIXEL_32_END_LOOP
shun-iwasawa 481b59
    }
shun-iwasawa 481b59
    return;
shun-iwasawa 481b59
  }
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
  TRasterFP upF   = rup;
shun-iwasawa 481b59
  TRasterFP downF = rdown;
shun-iwasawa 481b59
  TRasterFP outF  = rout;
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
  if (upF && downF && outF) {
shun-iwasawa 481b59
    if (matte) {
shun-iwasawa 481b59
      FOR_EACH_PIXEL_F_BEGIN_LOOP
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
      outPix->r = upPix->r < downPix->r ? upPix->r : downPix->r;
shun-iwasawa 481b59
      outPix->g = upPix->g < downPix->g ? upPix->g : downPix->g;
shun-iwasawa 481b59
      outPix->b = upPix->b < downPix->b ? upPix->b : downPix->b;
shun-iwasawa 481b59
      outPix->m = upPix->m < downPix->m ? upPix->m : downPix->m;
shun-iwasawa 481b59
shun-iwasawa 481b59
      FOR_EACH_PIXEL_F_END_LOOP
shun-iwasawa 481b59
    } else {
shun-iwasawa 481b59
      FOR_EACH_PIXEL_F_BEGIN_LOOP
shun-iwasawa 481b59
      if (upPix->m >= 1.f) {
shun-iwasawa 481b59
        outPix->r = upPix->r < downPix->r ? upPix->r : downPix->r;
shun-iwasawa 481b59
        outPix->g = upPix->g < downPix->g ? upPix->g : downPix->g;
shun-iwasawa 481b59
        outPix->b = upPix->b < downPix->b ? upPix->b : downPix->b;
shun-iwasawa 481b59
        outPix->m = upPix->m < downPix->m ? upPix->m : downPix->m;
shun-iwasawa 481b59
shun-iwasawa 481b59
      } else if (upPix->m > 0.f) {
shun-iwasawa 481b59
        TPixelF tmp;
shun-iwasawa 481b59
        tmp.r = upPix->r < downPix->r ? upPix->r : downPix->r;
shun-iwasawa 481b59
        tmp.g = upPix->g < downPix->g ? upPix->g : downPix->g;
shun-iwasawa 481b59
        tmp.b = upPix->b < downPix->b ? upPix->b : downPix->b;
shun-iwasawa 481b59
        // tmp.m = upPix->m < downPix->m ? upPix->m : downPix->m;
shun-iwasawa 481b59
        outPix->r = upPix->m * (tmp.r - downPix->r) + downPix->r;
shun-iwasawa 481b59
        outPix->g = upPix->m * (tmp.g - downPix->g) + downPix->g;
shun-iwasawa 481b59
        outPix->b = upPix->m * (tmp.b - downPix->b) + downPix->b;
shun-iwasawa 481b59
        outPix->m = upPix->m * (tmp.m - downPix->m) + downPix->m;
Shinya Kitaoka 120a6e
      } else
shun-iwasawa 481b59
        *outPix = *downPix;
shun-iwasawa 481b59
      FOR_EACH_PIXEL_F_END_LOOP
Shinya Kitaoka 120a6e
    }
shun-iwasawa 481b59
    return;
shun-iwasawa 481b59
  }
shun-iwasawa 481b59
shun-iwasawa 481b59
  TRasterGR8P up8   = rup;
shun-iwasawa 481b59
  TRasterGR8P down8 = rdown;
shun-iwasawa 481b59
  TRasterGR8P out8  = rout;
shun-iwasawa 481b59
shun-iwasawa 481b59
  if (up8 && down8 && out8) {
shun-iwasawa 481b59
    FOR_EACH_PIXEL_8_BEGIN_LOOP
shun-iwasawa 481b59
shun-iwasawa 481b59
    outPix->value =
shun-iwasawa 481b59
        upPix->value < downPix->value ? upPix->value : downPix->value;
shun-iwasawa 481b59
shun-iwasawa 481b59
    FOR_EACH_PIXEL_8_END_LOOP
shun-iwasawa 481b59
    return;
Shinya Kitaoka 120a6e
  }
shun-iwasawa 481b59
shun-iwasawa 481b59
  throw TRopException("TRop::min invalid raster combination");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TRop::ropmax(const TRasterP &rup, const TRasterP &rdown,
Shinya Kitaoka 120a6e
                  const TRasterP &rout) {
Shinya Kitaoka 120a6e
  TRaster32P up32   = rup;
Shinya Kitaoka 120a6e
  TRaster32P down32 = rdown;
Shinya Kitaoka 120a6e
  TRaster32P out32  = rout;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (up32 && down32 && out32) {
Shinya Kitaoka 120a6e
    FOR_EACH_PIXEL_32_BEGIN_LOOP
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    outPix->r = upPix->r > downPix->r ? upPix->r : downPix->r;
Shinya Kitaoka 120a6e
    outPix->g = upPix->g > downPix->g ? upPix->g : downPix->g;
Shinya Kitaoka 120a6e
    outPix->b = upPix->b > downPix->b ? upPix->b : downPix->b;
Shinya Kitaoka 120a6e
    outPix->m = upPix->m > downPix->m ? upPix->m : downPix->m;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    FOR_EACH_PIXEL_32_END_LOOP
shun-iwasawa 481b59
    return;
shun-iwasawa 481b59
  }
shun-iwasawa 481b59
  TRaster64P up64   = rup;
shun-iwasawa 481b59
  TRaster64P down64 = rdown;
shun-iwasawa 481b59
  TRaster64P out64  = rout;
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
  if (up64 && down64 && out64) {
shun-iwasawa 481b59
    FOR_EACH_PIXEL_64_BEGIN_LOOP
shun-iwasawa 481b59
shun-iwasawa 481b59
    outPix->r = upPix->r > downPix->r ? upPix->r : downPix->r;
shun-iwasawa 481b59
    outPix->g = upPix->g > downPix->g ? upPix->g : downPix->g;
shun-iwasawa 481b59
    outPix->b = upPix->b > downPix->b ? upPix->b : downPix->b;
shun-iwasawa 481b59
    outPix->m = upPix->m > downPix->m ? upPix->m : downPix->m;
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
    FOR_EACH_PIXEL_64_END_LOOP
shun-iwasawa 481b59
    return;
shun-iwasawa 481b59
  }
shun-iwasawa 481b59
  TRasterFP upF   = rup;
shun-iwasawa 481b59
  TRasterFP downF = rdown;
shun-iwasawa 481b59
  TRasterFP outF  = rout;
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
  if (upF && downF && outF) {
shun-iwasawa 481b59
    FOR_EACH_PIXEL_F_BEGIN_LOOP
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
    outPix->r = upPix->r > downPix->r ? upPix->r : downPix->r;
shun-iwasawa 481b59
    outPix->g = upPix->g > downPix->g ? upPix->g : downPix->g;
shun-iwasawa 481b59
    outPix->b = upPix->b > downPix->b ? upPix->b : downPix->b;
shun-iwasawa 481b59
    outPix->m = upPix->m > downPix->m ? upPix->m : downPix->m;
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
    FOR_EACH_PIXEL_F_END_LOOP
shun-iwasawa 481b59
    return;
shun-iwasawa 481b59
  }
shun-iwasawa 481b59
  TRasterGR8P up8   = rup;
shun-iwasawa 481b59
  TRasterGR8P down8 = rdown;
shun-iwasawa 481b59
  TRasterGR8P out8  = rout;
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
  if (up8 && down8 && out8) {
shun-iwasawa 481b59
    FOR_EACH_PIXEL_8_BEGIN_LOOP
shun-iwasawa 481b59
shun-iwasawa 481b59
    outPix->value =
shun-iwasawa 481b59
        upPix->value > downPix->value ? upPix->value : downPix->value;
shun-iwasawa 481b59
shun-iwasawa 481b59
    FOR_EACH_PIXEL_8_END_LOOP
shun-iwasawa 481b59
    return;
Shinya Kitaoka 120a6e
  }
shun-iwasawa 481b59
shun-iwasawa 481b59
  throw TRopException("TRop::max invalid raster combination");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
shun-iwasawa 481b59
/*
Shinya Kitaoka 120a6e
void TRop::linearburn(const TRasterP &rup, const TRasterP &rdown,
Shinya Kitaoka 120a6e
                      const TRasterP &rout) {
Shinya Kitaoka 120a6e
  TRaster32P up32   = rup;
Shinya Kitaoka 120a6e
  TRaster32P down32 = rdown;
Shinya Kitaoka 120a6e
  TRaster32P out32  = rout;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (up32 && down32 && out32) {
Shinya Kitaoka 120a6e
    FOR_EACH_PIXEL_32_BEGIN_LOOP
Shinya Kitaoka 120a6e
    if (upPix->m) {
Shinya Kitaoka 120a6e
      TPixel32 app;
Shinya Kitaoka 120a6e
      if (downPix->m) {
Shinya Kitaoka 120a6e
        TINT32 r, g, b, m;
Shinya Kitaoka 120a6e
        TPixel32 tmpPix;
Shinya Kitaoka 120a6e
        tmpPix = depremultiply(*downPix);
Shinya Kitaoka 120a6e
        r      = tmpPix.r + upPix->r - 255;
Shinya Kitaoka 120a6e
        g      = tmpPix.g + upPix->g - 255;
Shinya Kitaoka 120a6e
        b      = tmpPix.b + upPix->b - 255;
Shinya Kitaoka 120a6e
        m      = tmpPix.m + upPix->m - 255;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        app.r = (UCHAR)tcrop<tint32>(r, (TINT32)0, (TINT32)255);</tint32>
Shinya Kitaoka 120a6e
        app.g = (UCHAR)tcrop<tint32>(g, (TINT32)0, (TINT32)255);</tint32>
Shinya Kitaoka 120a6e
        app.b = (UCHAR)tcrop<tint32>(b, (TINT32)0, (TINT32)255);</tint32>
Shinya Kitaoka 120a6e
        // app.m = (UCHAR)tcrop<tint32> (m, (TINT32)0, (TINT32)255);</tint32>
Shinya Kitaoka 120a6e
        app.m = upPix->m;
Shinya Kitaoka 120a6e
      } else
Shinya Kitaoka 120a6e
        app = *upPix;
Shinya Kitaoka 120a6e
      overPix<tpixel32, uchar="">(*outPix, *downPix, app);</tpixel32,>
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    FOR_EACH_PIXEL_32_END_LOOP
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    TRaster64P up64   = rup;
Shinya Kitaoka 120a6e
    TRaster64P down64 = rdown;
Shinya Kitaoka 120a6e
    TRaster64P out64  = rout;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (up64 && down64 && out64) {
Shinya Kitaoka 120a6e
      FOR_EACH_PIXEL_64_BEGIN_LOOP
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (upPix->m) {
Shinya Kitaoka 120a6e
        TPixel64 app;
Shinya Kitaoka 120a6e
        if (downPix->m) {
Shinya Kitaoka 120a6e
          TINT32 r, g, b, m;
Shinya Kitaoka 120a6e
          TPixel64 tmpPix;
Shinya Kitaoka 120a6e
          tmpPix = depremultiply(*downPix);
Shinya Kitaoka 120a6e
          r      = tmpPix.r + upPix->r - 65535;
Shinya Kitaoka 120a6e
          g      = tmpPix.g + upPix->g - 65535;
Shinya Kitaoka 120a6e
          b      = tmpPix.b + upPix->b - 65535;
Shinya Kitaoka 120a6e
          m      = tmpPix.m + upPix->m - 65535;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
          app.r = (USHORT)tcrop<tint32>(r, 0, 0xffff);</tint32>
Shinya Kitaoka 120a6e
          app.g = (USHORT)tcrop<tint32>(g, 0, 0xffff);</tint32>
Shinya Kitaoka 120a6e
          app.b = (USHORT)tcrop<tint32>(b, 0, 0xffff);</tint32>
Shinya Kitaoka 120a6e
          // app.m = (UCHAR)tcrop<tint32> (m, (TINT32)0, (TINT32)255);</tint32>
Shinya Kitaoka 120a6e
          app.m = upPix->m;
Shinya Kitaoka 120a6e
        } else
Shinya Kitaoka 120a6e
          app = *upPix;
Shinya Kitaoka 120a6e
        overPix<tpixel64, ushort="">(*outPix, *downPix, app);</tpixel64,>
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      FOR_EACH_PIXEL_64_END_LOOP
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      TRasterGR8P up8   = rup;
Shinya Kitaoka 120a6e
      TRasterGR8P down8 = rdown;
Shinya Kitaoka 120a6e
      TRasterGR8P out8  = rout;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (up8 && down8 && out8) {
Shinya Kitaoka 120a6e
        FOR_EACH_PIXEL_8_BEGIN_LOOP
Shinya Kitaoka 120a6e
        USHORT value = troundp(upPix->value + downPix->value - 255);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        outPix->value = (UCHAR)tcrop<ushort>(value, 0, 255);</ushort>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        FOR_EACH_PIXEL_8_END_LOOP
Shinya Kitaoka 120a6e
      } else
Shinya Kitaoka 120a6e
        throw TRopException("TRop::max invalid raster combination");
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TRop::overlay(const TRasterP &rup, const TRasterP &rdown,
Shinya Kitaoka 120a6e
                   const TRasterP &rout) {
Shinya Kitaoka 120a6e
  TRaster32P up32   = rup;
Shinya Kitaoka 120a6e
  TRaster32P down32 = rdown;
Shinya Kitaoka 120a6e
  TRaster32P out32  = rout;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (up32 && down32 && out32) {
Shinya Kitaoka 120a6e
    FOR_EACH_PIXEL_32_BEGIN_LOOP
Shinya Kitaoka 120a6e
    if (upPix->m) {
Shinya Kitaoka 120a6e
      TPixel32 app;
Shinya Kitaoka 120a6e
      TPixel32 tmpPix, tmp2Pix;
Shinya Kitaoka 120a6e
      if (downPix->m) {
Shinya Kitaoka 120a6e
        tmpPix  = *downPix;
Shinya Kitaoka 120a6e
        tmp2Pix = depremultiply(*upPix);
Shinya Kitaoka 120a6e
        if (tmpPix.r < 128)
Shinya Kitaoka 120a6e
          app.r = troundp(2 * tmp2Pix.r * (tmpPix.r / 255.0));
Shinya Kitaoka 120a6e
        else {
Shinya Kitaoka 120a6e
          SHORT r =
Shinya Kitaoka 120a6e
              255 *
Shinya Kitaoka 120a6e
              (1 - 2 * (1.0 - tmpPix.r / 255.0) * (1.0 - tmp2Pix.r / 255.0));
Shinya Kitaoka 120a6e
          app.r = (UCHAR)tcrop<short>(r, 0, 255);</short>
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
        if (tmpPix.g < 128)
Shinya Kitaoka 120a6e
          app.g = troundp(2 * tmp2Pix.g * (tmpPix.g / 255.0));
Shinya Kitaoka 120a6e
        else {
Shinya Kitaoka 120a6e
          SHORT g =
Shinya Kitaoka 120a6e
              255 *
Shinya Kitaoka 120a6e
              (1 - 2 * (1.0 - tmpPix.g / 255.0) * (1.0 - tmp2Pix.g / 255.0));
Shinya Kitaoka 120a6e
          app.g = (UCHAR)tcrop<short>(g, 0, 255);</short>
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
        if (tmpPix.b < 128)
Shinya Kitaoka 120a6e
          app.b = troundp(2 * tmp2Pix.b * (tmpPix.b / 255.0));
Shinya Kitaoka 120a6e
        else {
Shinya Kitaoka 120a6e
          SHORT b =
Shinya Kitaoka 120a6e
              255 *
Shinya Kitaoka 120a6e
              (1 - 2 * (1.0 - tmpPix.b / 255.0) * (1.0 - tmp2Pix.b / 255.0));
Shinya Kitaoka 120a6e
          app.b = (UCHAR)tcrop<short>(b, 0, 255);</short>
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
        app.m = tmp2Pix.m;
Shinya Kitaoka 120a6e
        app   = premultiply(app);
Shinya Kitaoka 120a6e
      } else
Shinya Kitaoka 120a6e
        app = *upPix;
Shinya Kitaoka 120a6e
      overPix<tpixel32, uchar="">(*outPix, *downPix, app);</tpixel32,>
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    FOR_EACH_PIXEL_32_END_LOOP
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    TRaster64P up64   = rup;
Shinya Kitaoka 120a6e
    TRaster64P down64 = rdown;
Shinya Kitaoka 120a6e
    TRaster64P out64  = rout;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (up64 && down64 && out64) {
Shinya Kitaoka 120a6e
      FOR_EACH_PIXEL_64_BEGIN_LOOP
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (upPix->m) {
Shinya Kitaoka 120a6e
        TPixel64 app;
Shinya Kitaoka 120a6e
        TPixel64 tmpPix, tmp2Pix;
Shinya Kitaoka 120a6e
        if (downPix->m) {
Shinya Kitaoka 120a6e
          tmpPix  = *downPix;
Shinya Kitaoka 120a6e
          tmp2Pix = depremultiply(*upPix);
Shinya Kitaoka 120a6e
          if (tmpPix.r < 32768)
Shinya Kitaoka 120a6e
            app.r = troundp(2 * tmp2Pix.r * (tmpPix.r / 65535.0));
Shinya Kitaoka 120a6e
          else {
Shinya Kitaoka 120a6e
            SHORT r = 65535 * (1 -
Shinya Kitaoka 120a6e
                               2 * (1.0 - tmpPix.r / 65535.0) *
Shinya Kitaoka 120a6e
                                   (1.0 - tmp2Pix.r / 65535.0));
Shinya Kitaoka 120a6e
            app.r = (USHORT)tcrop<tint32>(r, 0, 65535);</tint32>
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
          if (tmpPix.g < 32768)
Shinya Kitaoka 120a6e
            app.g = troundp(2 * tmp2Pix.g * (tmpPix.g / 65535.0));
Shinya Kitaoka 120a6e
          else {
Shinya Kitaoka 120a6e
            SHORT g = 65535 * (1 -
Shinya Kitaoka 120a6e
                               2 * (1.0 - tmpPix.g / 65535.0) *
Shinya Kitaoka 120a6e
                                   (1.0 - tmp2Pix.g / 65535.0));
Shinya Kitaoka 120a6e
            app.g = (USHORT)tcrop<tint32>(g, 0, 65535);</tint32>
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
          if (tmpPix.b < 32768)
Shinya Kitaoka 120a6e
            app.b = troundp(2 * tmp2Pix.b * (tmpPix.b / 65535.0));
Shinya Kitaoka 120a6e
          else {
Shinya Kitaoka 120a6e
            SHORT b = 65535 * (1 -
Shinya Kitaoka 120a6e
                               2 * (1.0 - tmpPix.b / 65535.0) *
Shinya Kitaoka 120a6e
                                   (1.0 - tmp2Pix.b / 65535.0));
Shinya Kitaoka 120a6e
            app.b = (USHORT)tcrop<tint32>(b, 0, 65535);</tint32>
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
          app.m = tmp2Pix.m;
Shinya Kitaoka 120a6e
          app   = premultiply(app);
Shinya Kitaoka 120a6e
        } else
Shinya Kitaoka 120a6e
          app = *upPix;
Shinya Kitaoka 120a6e
        overPix<tpixel64, ushort="">(*outPix, *downPix, app);</tpixel64,>
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      FOR_EACH_PIXEL_64_END_LOOP
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      TRasterGR8P up8   = rup;
Shinya Kitaoka 120a6e
      TRasterGR8P down8 = rdown;
Shinya Kitaoka 120a6e
      TRasterGR8P out8  = rout;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (up8 && down8 && out8) {
Shinya Kitaoka 120a6e
        FOR_EACH_PIXEL_8_BEGIN_LOOP
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        USHORT value;
Shinya Kitaoka 120a6e
        if (downPix->value < 128)
Shinya Kitaoka 120a6e
          value = troundp(2 * upPix->value * (downPix->value / 255.0));
Shinya Kitaoka 120a6e
        else
Shinya Kitaoka 120a6e
          value = 255 * (1 -
Shinya Kitaoka 120a6e
                         2 * (1.0 - downPix->value / 255.0) *
Shinya Kitaoka 120a6e
                             (1.0 - upPix->value / 255.0));
Shinya Kitaoka 120a6e
        outPix->value = (UCHAR)tcrop<ushort>(value, 0, 255);</ushort>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        FOR_EACH_PIXEL_8_END_LOOP
Shinya Kitaoka 120a6e
      } else
Shinya Kitaoka 120a6e
        throw TRopException("TRop::max invalid raster combination");
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
shun-iwasawa 481b59
*/
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TRop::premultiply(const TRasterP &ras) {
Shinya Kitaoka 120a6e
  ras->lock();
Shinya Kitaoka 120a6e
  TRaster32P ras32 = ras;
shun-iwasawa 481b59
  TRaster64P ras64 = ras;
shun-iwasawa 481b59
  TRasterFP rasF   = ras;
Shinya Kitaoka 120a6e
  if (ras32) {
Shinya Kitaoka 120a6e
    TPixel32 *endPix, *upPix = 0, *upRow = ras32->pixels();
Shinya Kitaoka 120a6e
    TPixel32 *lastPix =
Shinya Kitaoka 120a6e
        upRow + ras32->getWrap() * (ras32->getLy() - 1) + ras32->getLx();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    while (upPix < lastPix) {
Shinya Kitaoka 120a6e
      upPix  = upRow;
Shinya Kitaoka 120a6e
      endPix = upPix + ras32->getLx();
Shinya Kitaoka 120a6e
      while (upPix < endPix) {
Shinya Kitaoka 120a6e
        premult(*upPix);
Shinya Kitaoka 120a6e
        ++upPix;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      upRow += ras32->getWrap();
Shinya Kitaoka 120a6e
    }
shun-iwasawa 481b59
  } else if (ras64) {
shun-iwasawa 481b59
    TPixel64 *endPix, *upPix = 0, *upRow = ras64->pixels();
shun-iwasawa 481b59
    TPixel64 *lastPix =
shun-iwasawa 481b59
        upRow + ras64->getWrap() * (ras64->getLy() - 1) + ras64->getLx();
shun-iwasawa 481b59
shun-iwasawa 481b59
    while (upPix < lastPix) {
shun-iwasawa 481b59
      upPix  = upRow;
shun-iwasawa 481b59
      endPix = upPix + ras64->getLx();
shun-iwasawa 481b59
      while (upPix < endPix) {
shun-iwasawa 481b59
        premult(*upPix);
shun-iwasawa 481b59
        ++upPix;
Shinya Kitaoka 120a6e
      }
shun-iwasawa 481b59
      upRow += ras64->getWrap();
shun-iwasawa 481b59
    }
shun-iwasawa 481b59
  } else if (rasF) {
shun-iwasawa 481b59
    TPixelF *endPix, *upPix = nullptr, *upRow = rasF->pixels();
shun-iwasawa 481b59
    TPixelF *lastPix =
shun-iwasawa 481b59
        upRow + rasF->getWrap() * (rasF->getLy() - 1) + rasF->getLx();
shun-iwasawa 481b59
shun-iwasawa 481b59
    while (upPix < lastPix) {
shun-iwasawa 481b59
      upPix  = upRow;
shun-iwasawa 481b59
      endPix = upPix + rasF->getLx();
shun-iwasawa 481b59
      while (upPix < endPix) {
shun-iwasawa 481b59
        premult(*upPix);
shun-iwasawa 481b59
        ++upPix;
shun-iwasawa 481b59
      }
shun-iwasawa 481b59
      upRow += rasF->getWrap();
Shinya Kitaoka 120a6e
    }
shun-iwasawa 481b59
  } else {
shun-iwasawa 481b59
    ras->unlock();
shun-iwasawa 481b59
    throw TException("TRop::premultiply invalid raster type");
Shinya Kitaoka 120a6e
  }
shun-iwasawa 481b59
Shinya Kitaoka 120a6e
  ras->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TRop::depremultiply(const TRasterP &ras) {
Shinya Kitaoka 120a6e
  ras->lock();
Shinya Kitaoka 120a6e
  TRaster32P ras32 = ras;
shun-iwasawa 481b59
  TRaster64P ras64 = ras;
shun-iwasawa 481b59
  TRasterFP rasF   = ras;
Shinya Kitaoka 120a6e
  if (ras32) {
Shinya Kitaoka 120a6e
    TPixel32 *endPix, *upPix = 0, *upRow = ras32->pixels();
Shinya Kitaoka 120a6e
    TPixel32 *lastPix =
Shinya Kitaoka 120a6e
        upRow + ras32->getWrap() * (ras32->getLy() - 1) + ras32->getLx();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    while (upPix < lastPix) {
Shinya Kitaoka 120a6e
      upPix  = upRow;
Shinya Kitaoka 120a6e
      endPix = upPix + ras32->getLx();
Shinya Kitaoka 120a6e
      while (upPix < endPix) {
shun_iwasawa 927bc0
        if (upPix->m != 0) depremult(*upPix);
Shinya Kitaoka 120a6e
        ++upPix;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      upRow += ras32->getWrap();
Shinya Kitaoka 120a6e
    }
shun-iwasawa 481b59
  } else if (ras64) {
shun-iwasawa 481b59
    TPixel64 *endPix, *upPix = 0, *upRow = ras64->pixels();
shun-iwasawa 481b59
    TPixel64 *lastPix =
shun-iwasawa 481b59
        upRow + ras64->getWrap() * (ras64->getLy() - 1) + ras64->getLx();
shun-iwasawa 481b59
shun-iwasawa 481b59
    while (upPix < lastPix) {
shun-iwasawa 481b59
      upPix  = upRow;
shun-iwasawa 481b59
      endPix = upPix + ras64->getLx();
shun-iwasawa 481b59
      while (upPix < endPix) {
shun-iwasawa 481b59
        if (upPix->m != 0) depremult(*upPix);
shun-iwasawa 481b59
        ++upPix;
Shinya Kitaoka 120a6e
      }
shun-iwasawa 481b59
      upRow += ras64->getWrap();
shun-iwasawa 481b59
    }
shun-iwasawa 481b59
  } else if (rasF) {
shun-iwasawa 481b59
    TPixelF *endPix, *upPix = nullptr, *upRow = rasF->pixels();
shun-iwasawa 481b59
    TPixelF *lastPix =
shun-iwasawa 481b59
        upRow + rasF->getWrap() * (rasF->getLy() - 1) + rasF->getLx();
shun-iwasawa 481b59
shun-iwasawa 481b59
    while (upPix < lastPix) {
shun-iwasawa 481b59
      upPix  = upRow;
shun-iwasawa 481b59
      endPix = upPix + rasF->getLx();
shun-iwasawa 481b59
      while (upPix < endPix) {
shun-iwasawa 481b59
        if (upPix->m > 0.f) depremult(*upPix);
shun-iwasawa 481b59
        ++upPix;
shun-iwasawa 481b59
      }
shun-iwasawa 481b59
      upRow += rasF->getWrap();
Shinya Kitaoka 120a6e
    }
shun-iwasawa 481b59
  } else {
shun-iwasawa 481b59
    ras->unlock();
shun-iwasawa 481b59
    throw TException("TRop::depremultiply invalid raster type");
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  ras->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
shun_iwasawa 927bc0
void TRop::expandColor(const TRaster32P &ras32, bool precise) {
shun_iwasawa 927bc0
  struct locals {
shun_iwasawa 927bc0
    static void copyRGB(TPixel32 *dst, TPixel32 *src) {
shun_iwasawa 927bc0
      dst->r = src->r;
shun_iwasawa 927bc0
      dst->g = src->g;
shun_iwasawa 927bc0
      dst->b = src->b;
shun_iwasawa 927bc0
    }
shun_iwasawa 927bc0
  };  // locals
shun_iwasawa 927bc0
  ras32->lock();
shun_iwasawa 927bc0
  TPixel32 *endPix, *upPix = 0, *upRow = ras32->pixels();
shun_iwasawa 927bc0
  TPixel32 *lastPix =
shun_iwasawa 927bc0
      upRow + ras32->getWrap() * (ras32->getLy() - 1) + ras32->getLx();
shun_iwasawa 927bc0
  int currentRow = 0;
shun_iwasawa 927bc0
  while (upPix < lastPix) {
shun_iwasawa 927bc0
    upPix  = upRow;
shun_iwasawa 927bc0
    endPix = upPix + ras32->getLx();
shun_iwasawa 927bc0
    while (upPix < endPix) {
shun_iwasawa 927bc0
      if (upPix->m == 0) {
shun_iwasawa 927bc0
        // search 4-neighbor pixels
shun_iwasawa 927bc0
        // left
shun_iwasawa 927bc0
        if (upPix != upRow && (upPix - 1)->m != 0)
shun_iwasawa 927bc0
          locals::copyRGB(upPix, upPix - 1);
shun_iwasawa 927bc0
        // right
shun_iwasawa 927bc0
        else if (upPix != endPix - 1 && (upPix + 1)->m != 0)
shun_iwasawa 927bc0
          locals::copyRGB(upPix, upPix + 1);
shun_iwasawa 927bc0
        // up
shun_iwasawa 927bc0
        else if (currentRow != 0 && (upPix - ras32->getWrap())->m != 0)
shun_iwasawa 927bc0
          locals::copyRGB(upPix, upPix - ras32->getWrap());
shun_iwasawa 927bc0
        // down
shun_iwasawa 927bc0
        else if (currentRow != ras32->getLy() - 1 &&
shun_iwasawa 927bc0
                 (upPix + ras32->getWrap())->m != 0)
shun_iwasawa 927bc0
          locals::copyRGB(upPix, upPix + ras32->getWrap());
shun_iwasawa 927bc0
        // search 8-neighbor pixels
shun_iwasawa 927bc0
        else if (precise) {
shun_iwasawa 927bc0
          // upper left
shun_iwasawa 927bc0
          if (currentRow != 0 && upPix != upRow &&
shun_iwasawa 927bc0
              (upPix - ras32->getWrap() - 1)->m != 0)
shun_iwasawa 927bc0
            locals::copyRGB(upPix, upPix - ras32->getWrap() - 1);
shun_iwasawa 927bc0
          // upper right
shun_iwasawa 927bc0
          else if (currentRow != 0 && upPix != endPix - 1 &&
shun_iwasawa 927bc0
                   (upPix - ras32->getWrap() + 1)->m != 0)
shun_iwasawa 927bc0
            locals::copyRGB(upPix, upPix - ras32->getWrap() + 1);
shun_iwasawa 927bc0
          // lower left
shun_iwasawa 927bc0
          else if (currentRow != ras32->getLy() - 1 && upPix != upRow &&
shun_iwasawa 927bc0
                   (upPix + ras32->getWrap() - 1)->m != 0)
shun_iwasawa 927bc0
            locals::copyRGB(upPix, upPix + ras32->getWrap() - 1);
shun_iwasawa 927bc0
          // lower right
shun_iwasawa 927bc0
          else if (currentRow != ras32->getLy() - 1 && upPix != endPix - 1 &&
shun_iwasawa 927bc0
                   (upPix + ras32->getWrap() + 1)->m != 0)
shun_iwasawa 927bc0
            locals::copyRGB(upPix, upPix + ras32->getWrap() + 1);
shun_iwasawa 927bc0
        }
shun_iwasawa 927bc0
      }
shun_iwasawa 927bc0
      ++upPix;
shun_iwasawa 927bc0
    }
shun_iwasawa 927bc0
    upRow += ras32->getWrap();
shun_iwasawa 927bc0
    currentRow++;
shun_iwasawa 927bc0
  }
shun_iwasawa 927bc0
  ras32->unlock();
shun_iwasawa 927bc0
}
shun_iwasawa 927bc0
shun_iwasawa 927bc0
//-----------------------------------------------------------------------------
shun_iwasawa 927bc0
Shinya Kitaoka 120a6e
void TRop::whiteTransp(const TRasterP &ras) {
Shinya Kitaoka 120a6e
  ras->lock();
Shinya Kitaoka 120a6e
  TRaster32P ras32 = ras;
shun-iwasawa 481b59
  TRaster64P ras64 = ras;
shun-iwasawa 481b59
  TRasterFP rasF   = ras;
Shinya Kitaoka 120a6e
  if (ras32) {
Shinya Kitaoka 120a6e
    TPixel32 *endPix, *upPix = 0, *upRow = ras32->pixels();
Shinya Kitaoka 120a6e
    TPixel32 *lastPix =
Shinya Kitaoka 120a6e
        upRow + ras32->getWrap() * (ras32->getLy() - 1) + ras32->getLx();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    while (upPix < lastPix) {
Shinya Kitaoka 120a6e
      upPix  = upRow;
Shinya Kitaoka 120a6e
      endPix = upPix + ras32->getLx();
Shinya Kitaoka 120a6e
      while (upPix < endPix) {
Shinya Kitaoka 120a6e
        if (*upPix == TPixel::White) *upPix = TPixel::Transparent;
Shinya Kitaoka 120a6e
        ++upPix;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      upRow += ras32->getWrap();
Shinya Kitaoka 120a6e
    }
shun-iwasawa 481b59
  } else if (ras64) {
shun-iwasawa 481b59
    TPixel64 *endPix, *upPix = 0, *upRow = ras64->pixels();
shun-iwasawa 481b59
    TPixel64 *lastPix =
shun-iwasawa 481b59
        upRow + ras64->getWrap() * (ras64->getLy() - 1) + ras64->getLx();
shun-iwasawa 481b59
shun-iwasawa 481b59
    while (upPix < lastPix) {
shun-iwasawa 481b59
      upPix  = upRow;
shun-iwasawa 481b59
      endPix = upPix + ras64->getLx();
shun-iwasawa 481b59
      while (upPix < endPix) {
shun-iwasawa 481b59
        if (*upPix == TPixel64::White) *upPix = TPixel64::Transparent;
shun-iwasawa 481b59
        ++upPix;
Shinya Kitaoka 120a6e
      }
shun-iwasawa 481b59
      upRow += ras64->getWrap();
Shinya Kitaoka 120a6e
    }
shun-iwasawa 481b59
  } else if (rasF) {
shun-iwasawa 481b59
    TPixelF *endPix, *upPix = 0, *upRow = rasF->pixels();
shun-iwasawa 481b59
    TPixelF *lastPix =
shun-iwasawa 481b59
        upRow + rasF->getWrap() * (rasF->getLy() - 1) + rasF->getLx();
shun-iwasawa 481b59
shun-iwasawa 481b59
    while (upPix < lastPix) {
shun-iwasawa 481b59
      upPix  = upRow;
shun-iwasawa 481b59
      endPix = upPix + rasF->getLx();
shun-iwasawa 481b59
      while (upPix < endPix) {
shun-iwasawa 481b59
        if ((*upPix).r >= TPixelF::maxChannelValue &&
shun-iwasawa 481b59
            (*upPix).g >= TPixelF::maxChannelValue &&
shun-iwasawa 481b59
            (*upPix).b >= TPixelF::maxChannelValue)
shun-iwasawa 481b59
          *upPix = TPixelF::Transparent;
shun-iwasawa 481b59
        ++upPix;
shun-iwasawa 481b59
      }
shun-iwasawa 481b59
      upRow += rasF->getWrap();
shun-iwasawa 481b59
    }
shun-iwasawa 481b59
  } else {
shun-iwasawa 481b59
    ras->unlock();
shun-iwasawa 481b59
    throw TException("TRop::premultiply invalid raster type");
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  ras->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
shun_iwasawa 2c0f50
void TRop::applyColorScale(const TRasterP &ras, const TPixel32 &colorScale) {
shun_iwasawa 2c0f50
  ras->lock();
shun_iwasawa 2c0f50
shun_iwasawa 2c0f50
  TRop::depremultiply(ras);
shun_iwasawa 2c0f50
shun_iwasawa 2c0f50
  TRaster32P ras32 = ras;
shun_iwasawa 2c0f50
  int maxCh        = TPixel32::maxChannelValue;
shun_iwasawa 2c0f50
  if (ras32) {
shun_iwasawa 2c0f50
    TPixel32 *endPix, *upPix = 0, *upRow = ras32->pixels();
shun_iwasawa 2c0f50
    TPixel32 *lastPix =
shun_iwasawa 2c0f50
        upRow + ras32->getWrap() * (ras32->getLy() - 1) + ras32->getLx();
shun_iwasawa 2c0f50
shun_iwasawa 2c0f50
    while (upPix < lastPix) {
shun_iwasawa 2c0f50
      upPix  = upRow;
shun_iwasawa 2c0f50
      endPix = upPix + ras32->getLx();
shun_iwasawa 2c0f50
      while (upPix < endPix) {
shun_iwasawa 2c0f50
        int maxCh = TPixel32::maxChannelValue;
shun_iwasawa 2c0f50
        int r  = maxCh - (maxCh - (*upPix).r) * (maxCh - colorScale.r) / maxCh;
shun_iwasawa 2c0f50
        int g  = maxCh - (maxCh - (*upPix).g) * (maxCh - colorScale.g) / maxCh;
shun_iwasawa 2c0f50
        int b  = maxCh - (maxCh - (*upPix).b) * (maxCh - colorScale.b) / maxCh;
shun_iwasawa 2c0f50
        int m  = (*upPix).m * colorScale.m / maxCh;
shun_iwasawa 2c0f50
        *upPix = TPixel32(r, g, b, m);
shun_iwasawa 2c0f50
        ++upPix;
shun_iwasawa 2c0f50
      }
shun_iwasawa 2c0f50
      upRow += ras32->getWrap();
shun_iwasawa 2c0f50
    }
shun_iwasawa 2c0f50
  } else {
shun_iwasawa 2c0f50
    TRaster64P ras64 = ras;
shun_iwasawa 2c0f50
    if (ras64) {
shun_iwasawa 2c0f50
      TPixel64 *endPix, *upPix = 0, *upRow = ras64->pixels();
shun_iwasawa 2c0f50
      TPixel64 *lastPix =
shun_iwasawa 2c0f50
          upRow + ras64->getWrap() * (ras64->getLy() - 1) + ras64->getLx();
shun_iwasawa 2c0f50
shun_iwasawa 2c0f50
      int maxCh64 = TPixel64::maxChannelValue;
shun_iwasawa 2c0f50
      while (upPix < lastPix) {
shun_iwasawa 2c0f50
        upPix  = upRow;
shun_iwasawa 2c0f50
        endPix = upPix + ras64->getLx();
shun_iwasawa 2c0f50
        while (upPix < endPix) {
shun_iwasawa 2c0f50
          int r =
shun_iwasawa 2c0f50
              maxCh64 - (maxCh64 - (*upPix).r) * (maxCh - colorScale.r) / maxCh;
shun_iwasawa 2c0f50
          int g =
shun_iwasawa 2c0f50
              maxCh64 - (maxCh64 - (*upPix).g) * (maxCh - colorScale.g) / maxCh;
shun_iwasawa 2c0f50
          int b =
shun_iwasawa 2c0f50
              maxCh64 - (maxCh64 - (*upPix).b) * (maxCh - colorScale.b) / maxCh;
shun_iwasawa 2c0f50
          int m  = (*upPix).m * colorScale.m / maxCh;
shun_iwasawa 2c0f50
          *upPix = TPixel64(r, g, b, m);
shun_iwasawa 2c0f50
          ++upPix;
shun_iwasawa 2c0f50
        }
shun_iwasawa 2c0f50
        upRow += ras64->getWrap();
shun_iwasawa 2c0f50
      }
shun_iwasawa 2c0f50
    } else {
shun_iwasawa 2c0f50
      ras->unlock();
shun_iwasawa 2c0f50
      throw TException("TRop::premultiply invalid raster type");
shun_iwasawa 2c0f50
    }
shun_iwasawa 2c0f50
  }
shun_iwasawa 2c0f50
  TRop::premultiply(ras);
shun_iwasawa 2c0f50
  ras->unlock();
shun_iwasawa 2c0f50
}
shun_iwasawa 2c0f50
shun_iwasawa 2c0f50
//-----------------------------------------------------------------------------
shun_iwasawa 2c0f50
Toshihiro Shimizu 890ddd
template <typename chan=""></typename>
Shinya Kitaoka 120a6e
const double *premultiplyTable() {
Shinya Kitaoka 120a6e
  static double *table = 0;
Shinya Kitaoka 120a6e
  if (!table) {
Shinya Kitaoka 120a6e
    int maxChannelValue = (std::numeric_limits<chan>::max)();</chan>
Shinya Kitaoka 120a6e
    int chanValuesCount = maxChannelValue + 1;
Shinya Kitaoka 120a6e
    double maxD         = maxChannelValue;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    table = new double[chanValuesCount];
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    for (int i = 0; i < chanValuesCount; ++i) table[i] = i / maxD;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return table;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template DVAPI const double *premultiplyTable<uchar>();</uchar>
Toshihiro Shimizu 890ddd
template DVAPI const double *premultiplyTable<ushort>();</ushort>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename chan=""></typename>
Shinya Kitaoka 120a6e
const double *depremultiplyTable() {
Shinya Kitaoka 120a6e
  static double *table = 0;
Shinya Kitaoka 120a6e
  if (!table) {
Shinya Kitaoka 120a6e
    int maxChannelValue = (std::numeric_limits<chan>::max)();</chan>
Shinya Kitaoka 120a6e
    int chanValuesCount = maxChannelValue + 1;
Shinya Kitaoka 120a6e
    double maxD         = maxChannelValue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    table = new double[chanValuesCount];
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    table[0] = 0.0;
Shinya Kitaoka 120a6e
    for (int i = 1; i < chanValuesCount; ++i) table[i] = maxD / i;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return table;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template DVAPI const double *depremultiplyTable<uchar>();</uchar>
Toshihiro Shimizu 890ddd
template DVAPI const double *depremultiplyTable<ushort>();</ushort>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#undef FOR_EACH_PIXEL_BEGIN_LOOP
Toshihiro Shimizu 890ddd
#undef FOR_EACH_PIXEL_32_BEGIN_LOOP
Toshihiro Shimizu 890ddd
#undef FOR_EACH_PIXEL_64_BEGIN_LOOP
Toshihiro Shimizu 890ddd
#undef FOR_EACH_PIXEL_8_BEGIN_LOOP
Toshihiro Shimizu 890ddd
#undef FOR_EACH_PIXEL_END_LOOP
Toshihiro Shimizu 890ddd
#undef FOR_EACH_PIXEL_32_END_LOOP
Toshihiro Shimizu 890ddd
#undef FOR_EACH_PIXEL_64_END_LOOP
Toshihiro Shimizu 890ddd
#undef FOR_EACH_PIXEL_8_END_LOOP