#include "trop.h" #include "tconvert.h" //#include "trastercm.h" #ifndef TNZCORE_LIGHT #include "timagecache.h" #include "ttile.h" #include "trasterimage.h" #include "ttoonzimage.h" #endif TString TRopException::getMessage() const { return toWideString(message); } namespace { bool isOpaque32(TRaster32P &ras) { ras->lock(); UCHAR *m0 = &(ras->pixels()->m); if (0 < m0[0] && m0[0] < 255) return false; int wrap4 = ras->getWrap() * 4; int lx4 = ras->getLx() * 4; const UCHAR cm = *m0; int nrows = ras->getLy(); while (nrows-- > 0) { UCHAR *m1 = m0 + lx4; UCHAR *m = m0; while (m < m1 && *m == cm) m += 4; if (m < m1) break; m0 += wrap4; } ras->unlock(); return (nrows <= 0); //m_image->setOpaqueFlag(true); } } //namespace bool TRop::isOpaque(TRasterP ras) { TRaster32P ras32 = ras; if (ras32) return isOpaque32(ras32); else if (TRasterGR8P(ras)) return true; else throw TRopException("isOpaque: unsupported pixel type"); } #ifdef TNZ_MACHINE_CHANNEL_ORDER_MRGB void TRop::swapRBChannels(const TRaster32P &r) { int lx = r->getLx(); int y = r->getLy(); r->lock(); while (--y >= 0) { TPixel32 *pix = r->pixels(y); TPixel32 *endPix = pix + lx; while (pix < endPix) { tswap(pix->r, pix->b); ++pix; } } r->unlock(); } #endif TRaster32P TRop::copyAndSwapRBChannels(const TRaster32P &srcRaster) { TRaster32P newRaster(srcRaster->getSize()); int lx = srcRaster->getLx(); int y = srcRaster->getLy(); srcRaster->lock(); newRaster->lock(); while (--y >= 0) { TPixel32 *pix = srcRaster->pixels(y); TPixel32 *newpix = newRaster->pixels(y); TPixel32 *endPix = pix + lx; while (pix < endPix) { newpix->r = pix->b; newpix->g = pix->g; newpix->b = pix->r; newpix->m = pix->m; ++pix; ++newpix; } } srcRaster->unlock(); newRaster->unlock(); return newRaster; } void TRop::copy(TRasterP dst, const TRasterP &src) { assert(!((TRasterCM32P)src) || (TRasterCM32P)dst); if (dst->getPixelSize() == src->getPixelSize()) dst->copy(src); else { if (dst->getBounds() != src->getBounds()) { TRect rect = dst->getBounds() * src->getBounds(); if (rect.isEmpty()) return; TRop::convert(dst->extract(rect), src->extract(rect)); } else TRop::convert(dst, src); } } //------------------------------------------------------------------- namespace { template class Gamma_Lut { public: vector m_table; Gamma_Lut(int insteps, int outsteps, double gamma) { double inspace = (double)(insteps); for (int i = 0; i <= insteps; i++) m_table.push_back((Q)((outsteps) * (pow(i / inspace, 1.0 / gamma)) + 0.5)); } }; template void doGammaCorrect(TRasterPT raster, double gamma) { Gamma_Lut lut(T::maxChannelValue, T::maxChannelValue, gamma); int j; for (j = 0; j < raster->getLy(); j++) { T *pix = raster->pixels(j); T *endPix = pix + raster->getLx(); while (pix < endPix) { pix->r = lut.m_table[pix->r]; pix->b = lut.m_table[pix->b]; pix->g = lut.m_table[pix->g]; /*if(pix->m != T::maxChannelValue) { pix->r= pix->r*pix->m/T::maxChannelValue; pix->g= pix->g*pix->m/T::maxChannelValue; pix->b= pix->b*pix->m/T::maxChannelValue; }*/ *pix++; } } } template void doGammaCorrectRGBM(TRasterPT raster, double gammar, double gammag, double gammab, double gammam) { Gamma_Lut lutr(T::maxChannelValue, T::maxChannelValue, gammar); Gamma_Lut lutg(T::maxChannelValue, T::maxChannelValue, gammag); Gamma_Lut lutb(T::maxChannelValue, T::maxChannelValue, gammab); Gamma_Lut lutm(T::maxChannelValue, T::maxChannelValue, gammam); int j; for (j = 0; j < raster->getLy(); j++) { T *pix = raster->pixels(j); T *endPix = pix + raster->getLx(); while (pix < endPix) { pix->r = lutr.m_table[pix->r]; pix->g = lutg.m_table[pix->g]; pix->b = lutb.m_table[pix->b]; pix->m = lutm.m_table[pix->m]; /*if(pix->m != T::maxChannelValue) { pix->r= pix->r*pix->m/T::maxChannelValue; pix->g= pix->g*pix->m/T::maxChannelValue; pix->b= pix->b*pix->m/T::maxChannelValue; }*/ *pix++; } } } } //------------------------------------------------------------------- void TRop::gammaCorrect(TRasterP raster, double gamma) { if (gamma <= 0) gamma = 0.01; raster->lock(); if ((TRaster32P)raster) doGammaCorrect(raster, gamma); else if ((TRaster64P)raster) doGammaCorrect(raster, gamma); else { raster->unlock(); throw TRopException("isOpaque: unsupported pixel type"); } raster->unlock(); } //------------------------------------------------------------------- void TRop::gammaCorrectRGBM(TRasterP raster, double gammar, double gammag, double gammab, double gammam) { if (gammar <= 0) gammar = 0.01; if (gammag <= 0) gammag = 0.01; if (gammab <= 0) gammab = 0.01; if (gammam <= 0) gammam = 0.01; raster->lock(); if ((TRaster32P)raster) doGammaCorrectRGBM(raster, gammar, gammag, gammab, gammam); else if ((TRaster64P)raster) doGammaCorrectRGBM(raster, gammar, gammag, gammab, gammam); else { raster->unlock(); throw TRopException("isOpaque: unsupported pixel type"); } raster->unlock(); } //------------------------------------------------------------------- template void doSetChannel(const TRasterPT &rin, const TRasterPT &rout, UCHAR channel, bool greytones) { int lx = rin->getLx(); int ly = rout->getLy(); int i, j; for (i = 0; i < ly; i++) { T *pixin = rin->pixels(i); T *pixout = rout->pixels(i); if (greytones || channel == TRop::MChan) { switch (channel) { case TRop::RChan: for (j = 0; j < lx; j++, pixin++, pixout++) pixout->r = pixout->g = pixout->b = pixout->m = pixin->r; break; case TRop::GChan: for (j = 0; j < lx; j++, pixin++, pixout++) pixout->r = pixout->g = pixout->b = pixout->m = pixin->g; break; case TRop::BChan: for (j = 0; j < lx; j++, pixin++, pixout++) pixout->r = pixout->g = pixout->b = pixout->m = pixin->b; break; case TRop::MChan: for (j = 0; j < lx; j++, pixin++, pixout++) pixout->r = pixout->g = pixout->b = pixout->m = pixin->m; break; default: assert(false); } } else { for (j = 0; j < lx; j++, pixin++, pixout++) { pixout->r = channel & TRop::RChan ? pixin->r : 0; pixout->b = channel & TRop::BChan ? pixin->b : 0; pixout->g = channel & TRop::GChan ? pixin->g : 0; } } } } //------------------------------------------------------------------- void TRop::setChannel(const TRasterP &rin, TRasterP rout, UCHAR chan, bool greytones) { assert(rin->getSize() == rout->getSize()); rout->lock(); if ((TRaster32P)rin && (TRaster32P)rout) doSetChannel(rin, rout, chan, greytones); else if ((TRaster64P)rin && (TRaster64P)rout) doSetChannel(rin, rout, chan, greytones); else { rout->unlock(); throw TRopException("setChannel: unsupported pixel type"); } rout->unlock(); } //------------------------------------------------------------------- TRasterP TRop::shrink(TRasterP rin, int shrink) { int pixelSize = rin->getPixelSize(); int lx = (rin->getLx() - 1) / shrink + 1; int ly = (rin->getLy() - 1) / shrink + 1; TRasterP rout; if ((TRaster32P)rin) rout = TRaster32P(lx, ly); else if ((TRaster64P)rin) rout = TRaster64P(lx, ly); if ((TRasterCM32P)rin) rout = TRasterCM32P(lx, ly); if ((TRasterGR8P)rin) rout = TRasterGR8P(lx, ly); int i, j; for (i = 0; i < ly; i++) { UCHAR *bufin = (UCHAR *)rin->getRawData() + (i * shrink) * rin->getWrap() * pixelSize; UCHAR *bufout = (UCHAR *)rout->getRawData() + i * rout->getWrap() * pixelSize; for (j = 0; j < lx; j++) { memcpy(bufout, bufin, pixelSize); bufin += shrink * pixelSize; bufout += pixelSize; } } return rout; } //------------------------------------------------------------------- template void doMakeStereoRaster(const TRasterPT &rleft, const TRasterPT &rright) { int lx = rleft->getLx(); int ly = rright->getLy(); for (int i = 0; i < ly; i++) { T *pixl = rleft->pixels(i); T *pixr = rright->pixels(i); for (int j = 0; j < lx; j++, pixl++, pixr++) { pixl->g = pixr->g; pixl->b = pixr->b; } } } //--------------------------------------- void TRop::makeStereoRaster(const TRasterP &left, const TRasterP &right) { assert(left->getSize() == right->getSize()); left->lock(); if ((TRaster32P)left && (TRaster32P)right) doMakeStereoRaster(left, right); else if ((TRaster64P)left && (TRaster64P)right) doMakeStereoRaster(left, right); else { left->unlock(); throw TRopException("setChannel: unsupported pixel type"); } left->unlock(); } //------------------------------------------------------------------- #ifndef TNZCORE_LIGHT void TTile::addInCache(const TRasterP &raster) { if (!raster) { m_rasterId = ""; return; } TRasterP rin; m_rasterId = TImageCache::instance()->getUniqueId(); if (raster->getParent()) { rin = raster->getParent(); unsigned long offs = (raster->getRawData() - raster->getParent()->getRawData()) / raster->getPixelSize(); m_subRect = TRect(TPoint(offs % raster->getWrap(), offs / raster->getWrap()), raster->getSize()); } else { m_subRect = raster->getBounds(); rin = raster; } if ((TRasterCM32P)rin) TImageCache::instance()->add(m_rasterId, TToonzImageP(rin, rin->getBounds())); else if ((TRaster32P)rin || (TRaster64P)rin) TImageCache::instance()->add(m_rasterId, TRasterImageP(rin)); else if ((TRasterGR8P)rin || (TRasterGR16P)rin) TImageCache::instance()->add(m_rasterId, TRasterImageP(rin)); else assert(false); } TTile::TTile(const TRasterP &raster) : m_pos(), m_subRect() { addInCache(raster); } TTile::TTile(const TRasterP &raster, TPointD pos) : m_pos(pos), m_subRect() { addInCache(raster); } void TTile::setRaster(const TRasterP &raster) { if (m_rasterId != "") TImageCache::instance()->remove(m_rasterId); m_subRect = TRect(); addInCache(raster); } TTile::~TTile() { if (!m_rasterId.empty()) TImageCache::instance()->remove(m_rasterId); } #endif