Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "trop.h"
Toshihiro Shimizu 890ddd
#include "tconvert.h"
shun-iwasawa 481b59
// #include "trastercm.h"
Toshihiro Shimizu 890ddd
#ifndef TNZCORE_LIGHT
Toshihiro Shimizu 890ddd
#include "timagecache.h"
Toshihiro Shimizu 890ddd
#include "ttile.h"
Toshihiro Shimizu 890ddd
#include "trasterimage.h"
Toshihiro Shimizu 890ddd
#include "ttoonzimage.h"
Toshihiro Shimizu 890ddd
#endif
shun-iwasawa 481b59
#include "tpixelutils.h"
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TString TRopException::getMessage() const { return ::to_wstring(message); }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
namespace {
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
bool isOpaque32(TRaster32P &ras) {
Shinya Kitaoka 120a6e
  ras->lock();
Shinya Kitaoka 120a6e
  UCHAR *m0 = &(ras->pixels()->m);
Shinya Kitaoka 120a6e
  if (0 < m0[0] && m0[0] < 255) return false;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int wrap4      = ras->getWrap() * 4;
Shinya Kitaoka 120a6e
  int lx4        = ras->getLx() * 4;
Shinya Kitaoka 120a6e
  const UCHAR cm = *m0;
Shinya Kitaoka 120a6e
  int nrows      = ras->getLy();
Shinya Kitaoka 120a6e
  while (nrows-- > 0) {
Shinya Kitaoka 120a6e
    UCHAR *m1 = m0 + lx4;
Shinya Kitaoka 120a6e
    UCHAR *m  = m0;
Shinya Kitaoka 120a6e
    while (m < m1 && *m == cm) m += 4;
Shinya Kitaoka 120a6e
    if (m < m1) break;
Shinya Kitaoka 120a6e
    m0 += wrap4;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  ras->unlock();
Shinya Kitaoka 120a6e
  return (nrows <= 0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // m_image->setOpaqueFlag(true);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // namespace
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TRop::isOpaque(TRasterP ras) {
Shinya Kitaoka 120a6e
  TRaster32P ras32 = ras;
Shinya Kitaoka 120a6e
  if (ras32)
Shinya Kitaoka 120a6e
    return isOpaque32(ras32);
Shinya Kitaoka 120a6e
  else if (TRasterGR8P(ras))
Shinya Kitaoka 120a6e
    return true;
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    throw TRopException("isOpaque: unsupported pixel type");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef TNZ_MACHINE_CHANNEL_ORDER_MRGB
Shinya Kitaoka 120a6e
void TRop::swapRBChannels(const TRaster32P &r) {
Shinya Kitaoka 120a6e
  int lx = r->getLx();
Shinya Kitaoka 120a6e
  int y  = r->getLy();
Shinya Kitaoka 120a6e
  r->lock();
Shinya Kitaoka 120a6e
  while (--y >= 0) {
Shinya Kitaoka 120a6e
    TPixel32 *pix    = r->pixels(y);
Shinya Kitaoka 120a6e
    TPixel32 *endPix = pix + lx;
Shinya Kitaoka 120a6e
    while (pix < endPix) {
otakuto ed7dcd
      std::swap(pix->r, pix->b);
Shinya Kitaoka 120a6e
      ++pix;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  r->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TRaster32P TRop::copyAndSwapRBChannels(const TRaster32P &srcRaster) {
Shinya Kitaoka 120a6e
  TRaster32P newRaster(srcRaster->getSize());
Shinya Kitaoka 120a6e
  int lx = srcRaster->getLx();
Shinya Kitaoka 120a6e
  int y  = srcRaster->getLy();
Shinya Kitaoka 120a6e
  srcRaster->lock();
Shinya Kitaoka 120a6e
  newRaster->lock();
Shinya Kitaoka 120a6e
  while (--y >= 0) {
Shinya Kitaoka 120a6e
    TPixel32 *pix    = srcRaster->pixels(y);
Shinya Kitaoka 120a6e
    TPixel32 *newpix = newRaster->pixels(y);
Shinya Kitaoka 120a6e
    TPixel32 *endPix = pix + lx;
Shinya Kitaoka 120a6e
    while (pix < endPix) {
Shinya Kitaoka 120a6e
      newpix->r = pix->b;
Shinya Kitaoka 120a6e
      newpix->g = pix->g;
Shinya Kitaoka 120a6e
      newpix->b = pix->r;
Shinya Kitaoka 120a6e
      newpix->m = pix->m;
Shinya Kitaoka 120a6e
      ++pix;
Shinya Kitaoka 120a6e
      ++newpix;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  srcRaster->unlock();
Shinya Kitaoka 120a6e
  newRaster->unlock();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return newRaster;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TRop::copy(TRasterP dst, const TRasterP &src) {
Shinya Kitaoka 120a6e
  assert(!((TRasterCM32P)src) || (TRasterCM32P)dst);
shun-iwasawa 481b59
  if (dst->getPixelSize() == src->getPixelSize()) {
Shinya Kitaoka 120a6e
    dst->copy(src);
shun-iwasawa 481b59
  } else {
Shinya Kitaoka 120a6e
    if (dst->getBounds() != src->getBounds()) {
Shinya Kitaoka 120a6e
      TRect rect = dst->getBounds() * src->getBounds();
Shinya Kitaoka 120a6e
      if (rect.isEmpty()) return;
Shinya Kitaoka 120a6e
      TRop::convert(dst->extract(rect), src->extract(rect));
Shinya Kitaoka 120a6e
    } else
Shinya Kitaoka 120a6e
      TRop::convert(dst, src);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
template <class q=""></class>
Shinya Kitaoka 120a6e
class Gamma_Lut {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  std::vector<q> m_table;</q>
Shinya Kitaoka 120a6e
  Gamma_Lut(int insteps, int outsteps, double gamma) {
Shinya Kitaoka 120a6e
    double inspace = (double)(insteps);
Shinya Kitaoka 120a6e
    for (int i = 0; i <= insteps; i++)
Shinya Kitaoka 120a6e
      m_table.push_back(
Shinya Kitaoka 120a6e
          (Q)((outsteps) * (pow(i / inspace, 1.0 / gamma)) + 0.5));
Shinya Kitaoka 120a6e
  }
shun-iwasawa 481b59
  Gamma_Lut(int insteps, double gamma) {  // compute in 0-1
shun-iwasawa 481b59
    float inspace = (float)(insteps);
shun-iwasawa 481b59
    for (int i = 0; i <= insteps; i++)
shun-iwasawa 481b59
      m_table.push_back((Q)(pow(i / inspace, 1.f / (float)gamma)));
shun-iwasawa 481b59
  }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <class class="" q="" t,=""></class>
Shinya Kitaoka 120a6e
void doGammaCorrect(TRasterPT<t> raster, double gamma) {</t>
Shinya Kitaoka 120a6e
  Gamma_Lut<q> lut(T::maxChannelValue, T::maxChannelValue, gamma);</q>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int j;
Shinya Kitaoka 120a6e
  for (j = 0; j < raster->getLy(); j++) {
Shinya Kitaoka 120a6e
    T *pix    = raster->pixels(j);
Shinya Kitaoka 120a6e
    T *endPix = pix + raster->getLx();
Shinya Kitaoka 120a6e
    while (pix < endPix) {
Shinya Kitaoka 120a6e
      pix->r = lut.m_table[pix->r];
Shinya Kitaoka 120a6e
      pix->b = lut.m_table[pix->b];
Shinya Kitaoka 120a6e
      pix->g = lut.m_table[pix->g];
Shinya Kitaoka 120a6e
      /*if(pix->m != T::maxChannelValue)
Toshihiro Shimizu 890ddd
{
Shinya Kitaoka 120a6e
pix->r= pix->r*pix->m/T::maxChannelValue;
Shinya Kitaoka 120a6e
pix->g= pix->g*pix->m/T::maxChannelValue;
Shinya Kitaoka 120a6e
pix->b= pix->b*pix->m/T::maxChannelValue;
Shinya Kitaoka 120a6e
}*/
Rozhuk Ivan 823a31
      pix++;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
shun-iwasawa 481b59
shun-iwasawa 481b59
template <>
shun-iwasawa 481b59
void doGammaCorrect<tpixelf, float="">(TRasterFP raster, double gamma) {</tpixelf,>
shun-iwasawa 481b59
  Gamma_Lut<float> lut(TPixel64::maxChannelValue, gamma);  // compute in 0.0-1.0</float>
shun-iwasawa 481b59
  double step      = 1.0 / double(TPixel64::maxChannelValue);
shun-iwasawa 481b59
  double invGamma  = 1.0 / gamma;
shun-iwasawa 481b59
  auto getLutValue = [&](float val) {
shun-iwasawa 481b59
    if (val < 0.f)
shun-iwasawa 481b59
      return val;  // keep the negative input unchanged (the same behavior as
shun-iwasawa 481b59
                   // Nuke)
shun-iwasawa 481b59
    else if (val >= 1.f)
shun-iwasawa 481b59
      return std::pow(val, (float)invGamma);
shun-iwasawa 481b59
    float v     = val * float(TPixel64::maxChannelValue);
shun-iwasawa 481b59
    int id      = (int)tfloor(v);
shun-iwasawa 481b59
    float ratio = v - float(id);
shun-iwasawa 481b59
    return lut.m_table[id] * (1.f - ratio) + lut.m_table[id + 1] * ratio;
shun-iwasawa 481b59
  };
shun-iwasawa 481b59
shun-iwasawa 481b59
  // ? doesn't it need to consider alpha ?
shun-iwasawa 481b59
  for (int j = 0; j < raster->getLy(); j++) {
shun-iwasawa 481b59
    TPixelF *pix    = raster->pixels(j);
shun-iwasawa 481b59
    TPixelF *endPix = pix + raster->getLx();
shun-iwasawa 481b59
    while (pix < endPix) {
shun-iwasawa 481b59
      pix->r = getLutValue(pix->r);
shun-iwasawa 481b59
      pix->g = getLutValue(pix->g);
shun-iwasawa 481b59
      pix->b = getLutValue(pix->b);
shun-iwasawa 481b59
      pix++;
shun-iwasawa 481b59
    }
shun-iwasawa 481b59
  }
shun-iwasawa 481b59
}
shun-iwasawa 481b59
Toshihiro Shimizu 890ddd
template <class class="" q="" t,=""></class>
Shinya Kitaoka 120a6e
void doGammaCorrectRGBM(TRasterPT<t> raster, double gammar, double gammag,</t>
Shinya Kitaoka 120a6e
                        double gammab, double gammam) {
Shinya Kitaoka 120a6e
  Gamma_Lut<q> lutr(T::maxChannelValue, T::maxChannelValue, gammar);</q>
Shinya Kitaoka 120a6e
  Gamma_Lut<q> lutg(T::maxChannelValue, T::maxChannelValue, gammag);</q>
Shinya Kitaoka 120a6e
  Gamma_Lut<q> lutb(T::maxChannelValue, T::maxChannelValue, gammab);</q>
Shinya Kitaoka 120a6e
  Gamma_Lut<q> lutm(T::maxChannelValue, T::maxChannelValue, gammam);</q>
Shinya Kitaoka 120a6e
  int j;
Shinya Kitaoka 120a6e
  for (j = 0; j < raster->getLy(); j++) {
Shinya Kitaoka 120a6e
    T *pix    = raster->pixels(j);
Shinya Kitaoka 120a6e
    T *endPix = pix + raster->getLx();
Shinya Kitaoka 120a6e
    while (pix < endPix) {
Shinya Kitaoka 120a6e
      pix->r = lutr.m_table[pix->r];
Shinya Kitaoka 120a6e
      pix->g = lutg.m_table[pix->g];
Shinya Kitaoka 120a6e
      pix->b = lutb.m_table[pix->b];
Shinya Kitaoka 120a6e
      pix->m = lutm.m_table[pix->m];
Shinya Kitaoka 120a6e
      /*if(pix->m != T::maxChannelValue)
Toshihiro Shimizu 890ddd
{
Shinya Kitaoka 120a6e
pix->r= pix->r*pix->m/T::maxChannelValue;
Shinya Kitaoka 120a6e
pix->g= pix->g*pix->m/T::maxChannelValue;
Shinya Kitaoka 120a6e
pix->b= pix->b*pix->m/T::maxChannelValue;
Shinya Kitaoka 120a6e
}*/
Rozhuk Ivan 823a31
      pix++;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
shun-iwasawa 481b59
shun-iwasawa 481b59
template <>
shun-iwasawa 481b59
void doGammaCorrectRGBM<tpixelf, float="">(TRasterFP raster, double gammar,</tpixelf,>
shun-iwasawa 481b59
                                        double gammag, double gammab,
shun-iwasawa 481b59
                                        double gammam) {
shun-iwasawa 481b59
  double invGammaR = 1.0 / gammar;
shun-iwasawa 481b59
  double invGammaG = 1.0 / gammag;
shun-iwasawa 481b59
  double invGammaB = 1.0 / gammab;
shun-iwasawa 481b59
  double invGammaM = 1.0 / gammam;
shun-iwasawa 481b59
  for (int j = 0; j < raster->getLy(); j++) {
shun-iwasawa 481b59
    TPixelF *pix    = raster->pixels(j);
shun-iwasawa 481b59
    TPixelF *endPix = pix + raster->getLx();
shun-iwasawa 481b59
    while (pix < endPix) {
shun-iwasawa 481b59
      // keep the negative input unchanged (the same behavior as Nuke)
shun-iwasawa 481b59
      if (pix->r > 0.f) pix->r = (float)std::pow(pix->r, invGammaR);
shun-iwasawa 481b59
      if (pix->g > 0.f) pix->g = (float)std::pow(pix->g, invGammaG);
shun-iwasawa 481b59
      if (pix->b > 0.f) pix->b = (float)std::pow(pix->b, invGammaB);
shun-iwasawa 481b59
      if (pix->m > 0.f) pix->m = (float)std::pow(pix->m, invGammaM);
shun-iwasawa 481b59
      pix++;
shun-iwasawa 481b59
    }
shun-iwasawa 481b59
  }
Toshihiro Shimizu 890ddd
}
shun-iwasawa 481b59
shun-iwasawa 481b59
}  // namespace
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TRop::gammaCorrect(TRasterP raster, double gamma) {
Shinya Kitaoka 120a6e
  if (gamma <= 0) gamma = 0.01;
Shinya Kitaoka 120a6e
  raster->lock();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if ((TRaster32P)raster)
Shinya Kitaoka 120a6e
    doGammaCorrect<tpixel32, uchar="">(raster, gamma);</tpixel32,>
Shinya Kitaoka 120a6e
  else if ((TRaster64P)raster)
Shinya Kitaoka 120a6e
    doGammaCorrect<tpixel64, ushort="">(raster, gamma);</tpixel64,>
shun-iwasawa 481b59
  else if ((TRasterFP)raster)
shun-iwasawa 481b59
    doGammaCorrect<tpixelf, float="">(raster, gamma);</tpixelf,>
Shinya Kitaoka 120a6e
  else {
Shinya Kitaoka 120a6e
    raster->unlock();
Shinya Kitaoka 120a6e
    throw TRopException("isOpaque: unsupported pixel type");
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  raster->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TRop::gammaCorrectRGBM(TRasterP raster, double gammar, double gammag,
Shinya Kitaoka 120a6e
                            double gammab, double gammam) {
Shinya Kitaoka 120a6e
  if (gammar <= 0) gammar = 0.01;
Shinya Kitaoka 120a6e
  if (gammag <= 0) gammag = 0.01;
Shinya Kitaoka 120a6e
  if (gammab <= 0) gammab = 0.01;
Shinya Kitaoka 120a6e
  if (gammam <= 0) gammam = 0.01;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  raster->lock();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if ((TRaster32P)raster)
Shinya Kitaoka 120a6e
    doGammaCorrectRGBM<tpixel32, uchar="">(raster, gammar, gammag, gammab, gammam);</tpixel32,>
Shinya Kitaoka 120a6e
  else if ((TRaster64P)raster)
Shinya Kitaoka 120a6e
    doGammaCorrectRGBM<tpixel64, ushort="">(raster, gammar, gammag, gammab,</tpixel64,>
Shinya Kitaoka 120a6e
                                         gammam);
shun-iwasawa 481b59
  else if ((TRasterFP)raster)
shun-iwasawa 481b59
    doGammaCorrectRGBM<tpixelf, float="">(raster, gammar, gammag, gammab, gammam);</tpixelf,>
Shinya Kitaoka 120a6e
  else {
Shinya Kitaoka 120a6e
    raster->unlock();
Shinya Kitaoka 120a6e
    throw TRopException("isOpaque: unsupported pixel type");
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  raster->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <class t=""></class>
Shinya Kitaoka 120a6e
void doSetChannel(const TRasterPT<t> &rin, const TRasterPT<t> &rout,</t></t>
Shinya Kitaoka 120a6e
                  UCHAR channel, bool greytones) {
Shinya Kitaoka 120a6e
  int lx = rin->getLx();
Shinya Kitaoka 120a6e
  int ly = rout->getLy();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int i, j;
Shinya Kitaoka 120a6e
  for (i = 0; i < ly; i++) {
Shinya Kitaoka 120a6e
    T *pixin  = rin->pixels(i);
Shinya Kitaoka 120a6e
    T *pixout = rout->pixels(i);
Shinya Kitaoka 120a6e
    if (greytones || channel == TRop::MChan) {
Shinya Kitaoka 120a6e
      switch (channel) {
Shinya Kitaoka 120a6e
      case TRop::RChan:
Shinya Kitaoka 120a6e
        for (j = 0; j < lx; j++, pixin++, pixout++)
Shinya Kitaoka 120a6e
          pixout->r = pixout->g = pixout->b = pixout->m = pixin->r;
Shinya Kitaoka 120a6e
        break;
Shinya Kitaoka 120a6e
      case TRop::GChan:
Shinya Kitaoka 120a6e
        for (j = 0; j < lx; j++, pixin++, pixout++)
Shinya Kitaoka 120a6e
          pixout->r = pixout->g = pixout->b = pixout->m = pixin->g;
Shinya Kitaoka 120a6e
        break;
Shinya Kitaoka 120a6e
      case TRop::BChan:
Shinya Kitaoka 120a6e
        for (j = 0; j < lx; j++, pixin++, pixout++)
Shinya Kitaoka 120a6e
          pixout->r = pixout->g = pixout->b = pixout->m = pixin->b;
Shinya Kitaoka 120a6e
        break;
Shinya Kitaoka 120a6e
      case TRop::MChan:
Shinya Kitaoka 120a6e
        for (j = 0; j < lx; j++, pixin++, pixout++)
Shinya Kitaoka 120a6e
          pixout->r = pixout->g = pixout->b = pixout->m = pixin->m;
Shinya Kitaoka 120a6e
        break;
Shinya Kitaoka 120a6e
      default:
Shinya Kitaoka 120a6e
        assert(false);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      for (j = 0; j < lx; j++, pixin++, pixout++) {
Shinya Kitaoka 120a6e
        pixout->r = channel & TRop::RChan ? pixin->r : 0;
Shinya Kitaoka 120a6e
        pixout->b = channel & TRop::BChan ? pixin->b : 0;
Shinya Kitaoka 120a6e
        pixout->g = channel & TRop::GChan ? pixin->g : 0;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TRop::setChannel(const TRasterP &rin, TRasterP rout, UCHAR chan,
Shinya Kitaoka 120a6e
                      bool greytones) {
Shinya Kitaoka 120a6e
  assert(rin->getSize() == rout->getSize());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  rout->lock();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if ((TRaster32P)rin && (TRaster32P)rout)
Shinya Kitaoka 120a6e
    doSetChannel<tpixel32>(rin, rout, chan, greytones);</tpixel32>
Shinya Kitaoka 120a6e
  else if ((TRaster64P)rin && (TRaster64P)rout)
Shinya Kitaoka 120a6e
    doSetChannel<tpixel64>(rin, rout, chan, greytones);</tpixel64>
shun-iwasawa 481b59
  else if ((TRasterFP)rin && (TRasterFP)rout)
shun-iwasawa 481b59
    doSetChannel<tpixelf>(rin, rout, chan, greytones);</tpixelf>
Shinya Kitaoka 120a6e
  else {
Shinya Kitaoka 120a6e
    rout->unlock();
Shinya Kitaoka 120a6e
    throw TRopException("setChannel: unsupported pixel type");
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  rout->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TRasterP TRop::shrink(TRasterP rin, int shrink) {
Shinya Kitaoka 120a6e
  int pixelSize = rin->getPixelSize();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int lx = (rin->getLx() - 1) / shrink + 1;
Shinya Kitaoka 120a6e
  int ly = (rin->getLy() - 1) / shrink + 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRasterP rout;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if ((TRaster32P)rin)
Shinya Kitaoka 120a6e
    rout = TRaster32P(lx, ly);
Shinya Kitaoka 120a6e
  else if ((TRaster64P)rin)
shun-iwasawa 481b59
    rout = TRaster64P(lx, ly);
Shinya Kitaoka 120a6e
  if ((TRasterCM32P)rin) rout = TRasterCM32P(lx, ly);
shun-iwasawa 481b59
  if ((TRasterGR8P)rin) rout = TRasterGR8P(lx, ly);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int i, j;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (i = 0; i < ly; i++) {
Shinya Kitaoka 120a6e
    UCHAR *bufin =
Shinya Kitaoka 120a6e
        (UCHAR *)rin->getRawData() + (i * shrink) * rin->getWrap() * pixelSize;
Shinya Kitaoka 120a6e
    UCHAR *bufout =
Shinya Kitaoka 120a6e
        (UCHAR *)rout->getRawData() + i * rout->getWrap() * pixelSize;
Shinya Kitaoka 120a6e
    for (j = 0; j < lx; j++) {
Shinya Kitaoka 120a6e
      memcpy(bufout, bufin, pixelSize);
Shinya Kitaoka 120a6e
      bufin += shrink * pixelSize;
Shinya Kitaoka 120a6e
      bufout += pixelSize;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return rout;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <class t=""></class>
Shinya Kitaoka 120a6e
void doMakeStereoRaster(const TRasterPT<t> &rleft, const TRasterPT<t> &rright) {</t></t>
Shinya Kitaoka 120a6e
  int lx = rleft->getLx();
Shinya Kitaoka 120a6e
  int ly = rright->getLy();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (int i = 0; i < ly; i++) {
Shinya Kitaoka 120a6e
    T *pixl = rleft->pixels(i);
Shinya Kitaoka 120a6e
    T *pixr = rright->pixels(i);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    for (int j = 0; j < lx; j++, pixl++, pixr++) {
Shinya Kitaoka 120a6e
      pixl->g = pixr->g;
Shinya Kitaoka 120a6e
      pixl->b = pixr->b;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TRop::makeStereoRaster(const TRasterP &left, const TRasterP &right) {
Shinya Kitaoka 120a6e
  assert(left->getSize() == right->getSize());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  left->lock();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if ((TRaster32P)left && (TRaster32P)right)
Shinya Kitaoka 120a6e
    doMakeStereoRaster<tpixel32>(left, right);</tpixel32>
Shinya Kitaoka 120a6e
  else if ((TRaster64P)left && (TRaster64P)right)
Shinya Kitaoka 120a6e
    doMakeStereoRaster<tpixel64>(left, right);</tpixel64>
Shinya Kitaoka 120a6e
  else {
Shinya Kitaoka 120a6e
    left->unlock();
Shinya Kitaoka 120a6e
    throw TRopException("setChannel: unsupported pixel type");
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  left->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
#ifndef TNZCORE_LIGHT
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TTile::addInCache(const TRasterP &raster) {
Shinya Kitaoka 120a6e
  if (!raster) {
Shinya Kitaoka 120a6e
    m_rasterId = "";
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  TRasterP rin;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_rasterId = TImageCache::instance()->getUniqueId();
Shinya Kitaoka 120a6e
  if (raster->getParent()) {
Shinya Kitaoka 120a6e
    rin = raster->getParent();
Shinya Kitaoka 120a6e
    unsigned long offs =
Shinya Kitaoka 120a6e
        (raster->getRawData() - raster->getParent()->getRawData()) /
Shinya Kitaoka 120a6e
        raster->getPixelSize();
Shinya Kitaoka 120a6e
    m_subRect =
Shinya Kitaoka 120a6e
        TRect(TPoint(offs % raster->getWrap(), offs / raster->getWrap()),
Shinya Kitaoka 120a6e
              raster->getSize());
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    m_subRect = raster->getBounds();
Shinya Kitaoka 120a6e
    rin       = raster;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if ((TRasterCM32P)rin)
Shinya Kitaoka 120a6e
    TImageCache::instance()->add(m_rasterId,
Shinya Kitaoka 120a6e
                                 TToonzImageP(rin, rin->getBounds()));
Shinya Kitaoka 120a6e
  else if ((TRaster32P)rin || (TRaster64P)rin)
Shinya Kitaoka 120a6e
    TImageCache::instance()->add(m_rasterId, TRasterImageP(rin));
Shinya Kitaoka 120a6e
  else if ((TRasterGR8P)rin || (TRasterGR16P)rin)
Shinya Kitaoka 120a6e
    TImageCache::instance()->add(m_rasterId, TRasterImageP(rin));
shun-iwasawa 481b59
  else if ((TRasterFP)rin)
shun-iwasawa 481b59
    TImageCache::instance()->add(m_rasterId, TRasterImageP(rin));
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    assert(false);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TTile::TTile(const TRasterP &raster) : m_pos(), m_subRect() {
Shinya Kitaoka 120a6e
  addInCache(raster);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TTile::TTile(const TRasterP &raster, TPointD pos) : m_pos(pos), m_subRect() {
Shinya Kitaoka 120a6e
  addInCache(raster);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TTile::setRaster(const TRasterP &raster) {
Shinya Kitaoka 120a6e
  if (m_rasterId != "") TImageCache::instance()->remove(m_rasterId);
Shinya Kitaoka 120a6e
  m_subRect = TRect();
Shinya Kitaoka 120a6e
  addInCache(raster);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TTile::~TTile() {
Shinya Kitaoka 120a6e
  if (!m_rasterId.empty()) TImageCache::instance()->remove(m_rasterId);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#endif
shun-iwasawa 481b59
shun-iwasawa 481b59
//-------------------------------------------------------------------
shun-iwasawa 481b59
shun-iwasawa 481b59
namespace {
shun-iwasawa 481b59
template <class q=""></class>
shun-iwasawa 481b59
class Linear_Lut {
shun-iwasawa 481b59
public:
shun-iwasawa 481b59
  inline double toLinear(double val, double gamma) {
shun-iwasawa 481b59
    return std::pow(val, gamma);
shun-iwasawa 481b59
    // if (val <= 0.04045)
shun-iwasawa 481b59
    //   return val / 12.92;
shun-iwasawa 481b59
    // else
shun-iwasawa 481b59
    //   return std::pow((val + 0.055) / 1.055, 2.4);
shun-iwasawa 481b59
  }
shun-iwasawa 481b59
shun-iwasawa 481b59
  std::vector<q> m_table;</q>
shun-iwasawa 481b59
  Linear_Lut(int insteps, int outsteps, double gamma) {
shun-iwasawa 481b59
    double inspace = (double)(insteps);
shun-iwasawa 481b59
    for (int i = 0; i <= insteps; i++) {
shun-iwasawa 481b59
      m_table.push_back(
shun-iwasawa 481b59
          (Q)((outsteps)*toLinear((double)i / inspace, gamma) + 0.5));
shun-iwasawa 481b59
    }
shun-iwasawa 481b59
  }
shun-iwasawa 481b59
  Linear_Lut(int insteps, double gamma) {  // compute in 0-1
shun-iwasawa 481b59
    double inspace = (double)(insteps);
shun-iwasawa 481b59
    for (int i = 0; i <= insteps; i++)
shun-iwasawa 481b59
      m_table.push_back((Q)(toLinear((double)i / inspace, gamma)));
shun-iwasawa 481b59
  }
shun-iwasawa 481b59
};
shun-iwasawa 481b59
shun-iwasawa 481b59
template <class class="" q="" t,=""></class>
shun-iwasawa 481b59
void doLinearRGB(TRasterPT<t> raster, double gamma) {</t>
shun-iwasawa 481b59
  Linear_Lut<q> lut(T::maxChannelValue, T::maxChannelValue, gamma);</q>
shun-iwasawa 481b59
shun-iwasawa 481b59
  int j;
shun-iwasawa 481b59
  for (j = 0; j < raster->getLy(); j++) {
shun-iwasawa 481b59
    T *pix    = raster->pixels(j);
shun-iwasawa 481b59
    T *endPix = pix + raster->getLx();
shun-iwasawa 481b59
    while (pix < endPix) {
shun-iwasawa 481b59
      if (pix->m > 0) {
shun-iwasawa 481b59
        pix->r = lut.m_table[pix->r];
shun-iwasawa 481b59
        pix->b = lut.m_table[pix->b];
shun-iwasawa 481b59
        pix->g = lut.m_table[pix->g];
shun-iwasawa 481b59
      }
shun-iwasawa 481b59
      pix++;
shun-iwasawa 481b59
    }
shun-iwasawa 481b59
  }
shun-iwasawa 481b59
}
shun-iwasawa 481b59
shun-iwasawa 481b59
template <>
shun-iwasawa 481b59
void doLinearRGB<tpixelf, float="">(TRasterFP raster, double gamma) {</tpixelf,>
shun-iwasawa 481b59
  Linear_Lut<float> lut(TPixel64::maxChannelValue,</float>
shun-iwasawa 481b59
                        gamma);  // compute in 0.0-1.0
shun-iwasawa 481b59
shun-iwasawa 481b59
  double step      = 1.0 / double(TPixel64::maxChannelValue);
shun-iwasawa 481b59
  auto getLutValue = [&](float val) {
shun-iwasawa 481b59
    if (val < 0.f)
shun-iwasawa 481b59
      return val;  // keep the negative input unchanged (the same behavior as
shun-iwasawa 481b59
                   // Nuke)
shun-iwasawa 481b59
    else if (val >= 1.f)
shun-iwasawa 481b59
      return (float)lut.toLinear(val, gamma);
shun-iwasawa 481b59
    float v     = val * float(TPixel64::maxChannelValue);
shun-iwasawa 481b59
    int id      = (int)tfloor(v);
shun-iwasawa 481b59
    float ratio = v - float(id);
shun-iwasawa 481b59
    return lut.m_table[id] * (1.f - ratio) + lut.m_table[id + 1] * ratio;
shun-iwasawa 481b59
  };
shun-iwasawa 481b59
shun-iwasawa 481b59
  for (int j = 0; j < raster->getLy(); j++) {
shun-iwasawa 481b59
    TPixelF *pix    = raster->pixels(j);
shun-iwasawa 481b59
    TPixelF *endPix = pix + raster->getLx();
shun-iwasawa 481b59
    while (pix < endPix) {
shun-iwasawa 481b59
      if (pix->m > 0.f) {
shun-iwasawa 481b59
        pix->r = getLutValue(pix->r);
shun-iwasawa 481b59
        pix->g = getLutValue(pix->g);
shun-iwasawa 481b59
        pix->b = getLutValue(pix->b);
shun-iwasawa 481b59
      }
shun-iwasawa 481b59
      pix++;
shun-iwasawa 481b59
    }
shun-iwasawa 481b59
  }
shun-iwasawa 481b59
}
shun-iwasawa 481b59
shun-iwasawa 481b59
template <class q=""></class>
shun-iwasawa 481b59
class sRGB_Lut {
shun-iwasawa 481b59
public:
shun-iwasawa 481b59
  inline double to_sRGB(double lin, double gamma) {
shun-iwasawa 481b59
    double inv_gamma = 1.0 / gamma;
shun-iwasawa 481b59
    return std::pow(lin, inv_gamma);
shun-iwasawa 481b59
    // if (lin <= 0.0031308)
shun-iwasawa 481b59
    //   return 12.92 * lin;
shun-iwasawa 481b59
    // else
shun-iwasawa 481b59
    //   return 1.055 * std::pow(lin, 1.0 / 2.4) - 0.055;
shun-iwasawa 481b59
  }
shun-iwasawa 481b59
  std::vector<q> m_table;</q>
shun-iwasawa 481b59
shun-iwasawa 481b59
  sRGB_Lut(int insteps, int outsteps, double gamma) {
shun-iwasawa 481b59
    double inspace = (double)(insteps);
shun-iwasawa 481b59
    for (int i = 0; i <= insteps; i++) {
shun-iwasawa 481b59
      m_table.push_back(
shun-iwasawa 481b59
          (Q)((outsteps)*to_sRGB((double)i / inspace, gamma) + 0.5));
shun-iwasawa 481b59
    }
shun-iwasawa 481b59
  }
shun-iwasawa 481b59
  sRGB_Lut(int insteps, double gamma) {  // compute in 0-1
shun-iwasawa 481b59
    double inspace = (double)(insteps);
shun-iwasawa 481b59
    for (int i = 0; i <= insteps; i++)
shun-iwasawa 481b59
      m_table.push_back((Q)(to_sRGB((double)i / inspace, gamma)));
shun-iwasawa 481b59
  }
shun-iwasawa 481b59
};
shun-iwasawa 481b59
shun-iwasawa 481b59
template <class class="" q="" t,=""></class>
shun-iwasawa 481b59
void do_sRGB(TRasterPT<t> raster, double gamma) {</t>
shun-iwasawa 481b59
  sRGB_Lut<q> lut(T::maxChannelValue, T::maxChannelValue, gamma);</q>
shun-iwasawa 481b59
shun-iwasawa 481b59
  int j;
shun-iwasawa 481b59
  for (j = 0; j < raster->getLy(); j++) {
shun-iwasawa 481b59
    T *pix    = raster->pixels(j);
shun-iwasawa 481b59
    T *endPix = pix + raster->getLx();
shun-iwasawa 481b59
    while (pix < endPix) {
shun-iwasawa 481b59
      if (pix->m > 0) {
shun-iwasawa 481b59
        pix->r = lut.m_table[pix->r];
shun-iwasawa 481b59
        pix->b = lut.m_table[pix->b];
shun-iwasawa 481b59
        pix->g = lut.m_table[pix->g];
shun-iwasawa 481b59
      }
shun-iwasawa 481b59
      pix++;
shun-iwasawa 481b59
    }
shun-iwasawa 481b59
  }
shun-iwasawa 481b59
}
shun-iwasawa 481b59
shun-iwasawa 481b59
template <>
shun-iwasawa 481b59
void do_sRGB<tpixelf, float="">(TRasterFP raster, double gamma) {</tpixelf,>
shun-iwasawa 481b59
  sRGB_Lut<float> lut(TPixel64::maxChannelValue, gamma);  // compute in 0.0-1.0</float>
shun-iwasawa 481b59
shun-iwasawa 481b59
  double step      = 1.0 / double(TPixel64::maxChannelValue);
shun-iwasawa 481b59
  auto getLutValue = [&](float val) {
shun-iwasawa 481b59
    if (val < 0.f)
shun-iwasawa 481b59
      return val;  // keep the negative input unchanged (the same behavior as
shun-iwasawa 481b59
                   // Nuke)
shun-iwasawa 481b59
    else if (val >= 1.f)
shun-iwasawa 481b59
      return (float)lut.to_sRGB(val, gamma);
shun-iwasawa 481b59
    float v     = val * float(TPixel64::maxChannelValue);
shun-iwasawa 481b59
    int id      = (int)tfloor(v);
shun-iwasawa 481b59
    float ratio = v - float(id);
shun-iwasawa 481b59
    return lut.m_table[id] * (1.f - ratio) + lut.m_table[id + 1] * ratio;
shun-iwasawa 481b59
  };
shun-iwasawa 481b59
shun-iwasawa 481b59
  for (int j = 0; j < raster->getLy(); j++) {
shun-iwasawa 481b59
    TPixelF *pix    = raster->pixels(j);
shun-iwasawa 481b59
    TPixelF *endPix = pix + raster->getLx();
shun-iwasawa 481b59
    while (pix < endPix) {
shun-iwasawa 481b59
      if (pix->m > 0.f) {
shun-iwasawa 481b59
        pix->r = getLutValue(pix->r);
shun-iwasawa 481b59
        pix->g = getLutValue(pix->g);
shun-iwasawa 481b59
        pix->b = getLutValue(pix->b);
shun-iwasawa 481b59
      }
shun-iwasawa 481b59
      pix++;
shun-iwasawa 481b59
    }
shun-iwasawa 481b59
  }
shun-iwasawa 481b59
}
shun-iwasawa 481b59
shun-iwasawa 481b59
}  // namespace
shun-iwasawa 481b59
shun-iwasawa 481b59
void TRop::toLinearRGB(TRasterP raster, double gamma,
shun-iwasawa 481b59
                       bool sourceIsPremultiplied) {
shun-iwasawa 481b59
  // if raster is already in linear color space, do nothing
shun-iwasawa 481b59
  if (raster->isLinear()) return;
shun-iwasawa 481b59
shun-iwasawa 481b59
  raster->lock();
shun-iwasawa 481b59
shun-iwasawa 481b59
  if (sourceIsPremultiplied) TRop::depremultiply(raster);
shun-iwasawa 481b59
shun-iwasawa 481b59
  if ((TRaster32P)raster)
shun-iwasawa 481b59
    doLinearRGB<tpixel32, uchar="">(raster, gamma);</tpixel32,>
shun-iwasawa 481b59
  else if ((TRaster64P)raster)
shun-iwasawa 481b59
    doLinearRGB<tpixel64, ushort="">(raster, gamma);</tpixel64,>
shun-iwasawa 481b59
  else if ((TRasterFP)raster)
shun-iwasawa 481b59
    doLinearRGB<tpixelf, float="">(raster, gamma);</tpixelf,>
shun-iwasawa 481b59
  else {
shun-iwasawa 481b59
    raster->unlock();
shun-iwasawa 481b59
    throw TRopException("toLinearRGB: unsupported pixel type");
shun-iwasawa 481b59
  }
shun-iwasawa 481b59
shun-iwasawa 481b59
  raster->setLinear(true);
shun-iwasawa 481b59
shun-iwasawa 481b59
  if (sourceIsPremultiplied) TRop::premultiply(raster);
shun-iwasawa 481b59
shun-iwasawa 481b59
  raster->unlock();
shun-iwasawa 481b59
}
shun-iwasawa 481b59
shun-iwasawa 481b59
void TRop::tosRGB(TRasterP raster, double gamma, bool sourceIsPremultiplied) {
shun-iwasawa 481b59
  // if raster is already in sRGB color space, do nothing
shun-iwasawa 481b59
  if (!raster->isLinear()) return;
shun-iwasawa 481b59
shun-iwasawa 481b59
  raster->lock();
shun-iwasawa 481b59
shun-iwasawa 481b59
  if (sourceIsPremultiplied) TRop::depremultiply(raster);
shun-iwasawa 481b59
shun-iwasawa 481b59
  if ((TRaster32P)raster)
shun-iwasawa 481b59
    do_sRGB<tpixel32, uchar="">(raster, gamma);</tpixel32,>
shun-iwasawa 481b59
  else if ((TRaster64P)raster)
shun-iwasawa 481b59
    do_sRGB<tpixel64, ushort="">(raster, gamma);</tpixel64,>
shun-iwasawa 481b59
  else if ((TRasterFP)raster)
shun-iwasawa 481b59
    do_sRGB<tpixelf, float="">(raster, gamma);</tpixelf,>
shun-iwasawa 481b59
  else {
shun-iwasawa 481b59
    raster->unlock();
shun-iwasawa 481b59
    throw TRopException("tosRGB: unsupported pixel type");
shun-iwasawa 481b59
  }
shun-iwasawa 481b59
shun-iwasawa 481b59
  raster->setLinear(false);
shun-iwasawa 481b59
shun-iwasawa 481b59
  if (sourceIsPremultiplied) TRop::premultiply(raster);
shun-iwasawa 481b59
shun-iwasawa 481b59
  raster->unlock();
shun-iwasawa 481b59
}
shun-iwasawa 481b59
shun-iwasawa 481b59
namespace {
shun-iwasawa 481b59
template <class t=""></class>
shun-iwasawa 481b59
void do_adjustGain(TRasterPT<t> raster, const float gainScale) {</t>
shun-iwasawa 481b59
  int j;
shun-iwasawa 481b59
  for (j = 0; j < raster->getLy(); j++) {
shun-iwasawa 481b59
    T *pix    = raster->pixels(j);
shun-iwasawa 481b59
    T *endPix = pix + raster->getLx();
shun-iwasawa 481b59
    while (pix < endPix) {
shun-iwasawa 481b59
      if (pix->m > 0) {
shun-iwasawa 481b59
        float val;
shun-iwasawa 481b59
        val    = (float)pix->r * gainScale + 0.5f;
shun-iwasawa 481b59
        pix->r = (typename T::Channel)((val > (float)T::maxChannelValue)
shun-iwasawa 481b59
                                           ? (float)T::maxChannelValue
shun-iwasawa 481b59
                                           : val);
shun-iwasawa 481b59
        val    = (float)pix->g * gainScale + 0.5f;
shun-iwasawa 481b59
        pix->g = (typename T::Channel)((val > (float)T::maxChannelValue)
shun-iwasawa 481b59
                                           ? (float)T::maxChannelValue
shun-iwasawa 481b59
                                           : val);
shun-iwasawa 481b59
        val    = (float)pix->b * gainScale + 0.5f;
shun-iwasawa 481b59
        pix->b = (typename T::Channel)((val > (float)T::maxChannelValue)
shun-iwasawa 481b59
                                           ? (float)T::maxChannelValue
shun-iwasawa 481b59
                                           : val);
shun-iwasawa 481b59
      }
shun-iwasawa 481b59
      pix++;
shun-iwasawa 481b59
    }
shun-iwasawa 481b59
  }
shun-iwasawa 481b59
}
shun-iwasawa 481b59
shun-iwasawa 481b59
template <>
shun-iwasawa 481b59
void do_adjustGain<tpixelf>(TRasterFP raster, const float gainScale) {</tpixelf>
shun-iwasawa 481b59
  for (int j = 0; j < raster->getLy(); j++) {
shun-iwasawa 481b59
    TPixelF *pix    = raster->pixels(j);
shun-iwasawa 481b59
    TPixelF *endPix = pix + raster->getLx();
shun-iwasawa 481b59
    while (pix < endPix) {
shun-iwasawa 481b59
      if (pix->m > 0.f) {
shun-iwasawa 481b59
        pix->r *= gainScale;
shun-iwasawa 481b59
        pix->g *= gainScale;
shun-iwasawa 481b59
        pix->b *= gainScale;
shun-iwasawa 481b59
      }
shun-iwasawa 481b59
      pix++;
shun-iwasawa 481b59
    }
shun-iwasawa 481b59
  }
shun-iwasawa 481b59
}
shun-iwasawa 481b59
}  // namespace
shun-iwasawa 481b59
shun-iwasawa 481b59
// used in the gain adjustment feature of the flipbook
shun-iwasawa 481b59
void TRop::adjustGain(TRasterP raster, int gainStep, double gamma) {
shun-iwasawa 481b59
  if (gainStep == 0) return;
shun-iwasawa 481b59
shun-iwasawa 481b59
  std::cout << "adjustGain gamma = " << gamma << std::endl;
shun-iwasawa 481b59
  float gainScale = std::pow(2., (double)gainStep / 2.);
shun-iwasawa 481b59
shun-iwasawa 481b59
  raster->lock();
shun-iwasawa 481b59
shun-iwasawa 481b59
  TRop::depremultiply(raster);
shun-iwasawa 481b59
shun-iwasawa 481b59
  TRop::toLinearRGB(raster, gamma, false);
shun-iwasawa 481b59
shun-iwasawa 481b59
  if ((TRaster32P)raster)
shun-iwasawa 481b59
    do_adjustGain<tpixel32>(raster, gainScale);</tpixel32>
shun-iwasawa 481b59
  else if ((TRaster64P)raster)
shun-iwasawa 481b59
    do_adjustGain<tpixel64>(raster, gainScale);</tpixel64>
shun-iwasawa 481b59
  else if ((TRasterFP)raster)
shun-iwasawa 481b59
    do_adjustGain<tpixelf>(raster, gainScale);</tpixelf>
shun-iwasawa 481b59
  else {
shun-iwasawa 481b59
    raster->unlock();
shun-iwasawa 481b59
    throw TRopException("isOpaque: unsupported pixel type");
shun-iwasawa 481b59
  }
shun-iwasawa 481b59
shun-iwasawa 481b59
  TRop::tosRGB(raster, gamma, false);
shun-iwasawa 481b59
shun-iwasawa 481b59
  TRop::premultiply(raster);
shun-iwasawa 481b59
shun-iwasawa 481b59
  raster->unlock();
shun-iwasawa 481b59
}