Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "trop.h"
Toshihiro Shimizu 890ddd
#include "loop_macros.h"
Toshihiro Shimizu 890ddd
#include "tpixelutils.h"
Campbell Barton 8c6c57
#include "quickputP.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifndef TNZCORE_LIGHT
Toshihiro Shimizu 890ddd
#include "tpalette.h"
Toshihiro Shimizu 890ddd
#include "tcolorstyles.h"
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
#ifndef __sgi
Toshihiro Shimizu 890ddd
#include <algorithm>
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// The following must be old IRIX code. Should be re-tested.
Shinya Kitaoka 120a6e
// It seems that gcc compiles it, but requiring a LOT of
Shinya Kitaoka 120a6e
// resources... very suspect...
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*#ifdef __LP64__
Toshihiro Shimizu 890ddd
#include "optimize_for_lp64.h"
Toshihiro Shimizu 890ddd
#endif*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef OPTIMIZE_FOR_LP64
Shinya Kitaoka 120a6e
void quickResample_optimized(const TRasterP &dn, const TRasterP &up,
Shinya Kitaoka 120a6e
                             const TAffine &aff,
Shinya Kitaoka 120a6e
                             TRop::ResampleFilterType filterType);
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
inline TPixel32 applyColorScale(const TPixel32 &color,
Shinya Kitaoka 120a6e
                                const TPixel32 &colorScale,
Shinya Kitaoka 120a6e
                                bool toBePremultiplied = false) {
Shinya Kitaoka 120a6e
  /*--
shun-iwasawa 443318
   * Prevent colors from being darkened when quickputting a semi-transparent
shun-iwasawa 443318
   * raster on the Viewer
Shinya Kitaoka 120a6e
   * --*/
Shinya Kitaoka 120a6e
  if (colorScale.r == 0 && colorScale.g == 0 && colorScale.b == 0) {
Shinya Kitaoka 120a6e
    /*--
shun-iwasawa 443318
     * When toBePremultiplied is ON, Premultiply is done later, so it is not
shun-iwasawa 443318
     * done here.
Shinya Kitaoka 120a6e
     * --*/
Shinya Kitaoka 120a6e
    if (toBePremultiplied)
Shinya Kitaoka 120a6e
      return TPixel32(color.r, color.g, color.b, color.m * colorScale.m / 255);
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      return TPixel32(
Shinya Kitaoka 120a6e
          color.r * colorScale.m / 255, color.g * colorScale.m / 255,
Shinya Kitaoka 120a6e
          color.b * colorScale.m / 255, color.m * colorScale.m / 255);
Shinya Kitaoka 120a6e
  }
shun_iwasawa a3cdd8
  int r = 255 - (255 - color.r) * (255 - colorScale.r) / 255;
shun_iwasawa a3cdd8
  int g = 255 - (255 - color.g) * (255 - colorScale.g) / 255;
shun_iwasawa a3cdd8
  int b = 255 - (255 - color.b) * (255 - colorScale.b) / 255;
shun_iwasawa a3cdd8
  return premultiply(TPixel32(r, g, b, color.m * colorScale.m / 255));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline TPixel32 applyColorScaleCMapped(const TPixel32 &color,
Shinya Kitaoka 120a6e
                                       const TPixel32 &colorScale) {
shun_iwasawa a3cdd8
  int r = 255 - (255 - color.r) * (255 - colorScale.r) / 255;
shun_iwasawa a3cdd8
  int g = 255 - (255 - color.g) * (255 - colorScale.g) / 255;
shun_iwasawa a3cdd8
  int b = 255 - (255 - color.b) * (255 - colorScale.b) / 255;
shun_iwasawa a3cdd8
  return premultiply(TPixel32(r, g, b, color.m * colorScale.m / 255));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void doQuickPutFilter(const TRaster32P &dn, const TRaster32P &up,
Shinya Kitaoka 120a6e
                      const TAffine &aff) {
Shinya Kitaoka 120a6e
  //  se aff e' degenere la controimmagine di up e' un segmento (o un punto)
Shinya Kitaoka 120a6e
  if ((aff.a11 * aff.a22 - aff.a12 * aff.a21) == 0) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  contatore bit di shift
Shinya Kitaoka 120a6e
  const int PADN = 16;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  maschera del filtro bilineare
Shinya Kitaoka 120a6e
  const int MASKN = (1 << PADN) - 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  max dimensioni di up gestibili (limite imposto dal numero di bit
Shinya Kitaoka 120a6e
  //  disponibili per la parte intera di xL, yL)
Shinya Kitaoka 120a6e
  assert(std::max(up->getLx(), up->getLy()) <
Shinya Kitaoka 120a6e
         (1 << (8 * sizeof(int) - PADN - 1)));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRectD boundingBoxD = TRectD(convert(dn->getSize())) *
Shinya Kitaoka 120a6e
                        (aff * TRectD(0, 0, up->getLx() - 2, up->getLy() - 2));
Shinya Kitaoka 120a6e
  //  clipping
Shinya Kitaoka 120a6e
  if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1)
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping y su dn
Shinya Kitaoka 120a6e
  int yMin = std::max(tfloor(boundingBoxD.y0), 0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping y su dn
Shinya Kitaoka 120a6e
  int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping x su dn
Shinya Kitaoka 120a6e
  int xMin = std::max(tfloor(boundingBoxD.x0), 0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping x su dn
Shinya Kitaoka 120a6e
  int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TAffine invAff = inv(aff);  //  inversa di aff
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  nel disegnare la y-esima scanline di dn, il passaggio al pixel successivo
Shinya Kitaoka 120a6e
  //  comporta l'incremento (deltaXD, deltaYD) delle coordinate del pixel
Shinya Kitaoka 120a6e
  //  corrispondente di up
Shinya Kitaoka 120a6e
  double deltaXD = invAff.a11;
Shinya Kitaoka 120a6e
  double deltaYD = invAff.a21;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  deltaXD "TLonghizzato" (round)
Shinya Kitaoka 120a6e
  int deltaXL = tround(deltaXD * (1 << PADN));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  deltaYD "TLonghizzato" (round)
Shinya Kitaoka 120a6e
  int deltaYL = tround(deltaYD * (1 << PADN));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  se aff "TLonghizzata" (round) e' degenere la controimmagine di up e' un
Shinya Kitaoka 120a6e
  // segmento (o un punto)
Shinya Kitaoka 120a6e
  if ((deltaXL == 0) && (deltaYL == 0)) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //	naturale predecessore di up->getLx() - 1
Shinya Kitaoka 120a6e
  int lxPred = (up->getLx() - 2) * (1 << PADN);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //	naturale predecessore di up->getLy() - 1
Shinya Kitaoka 120a6e
  int lyPred = (up->getLy() - 2) * (1 << PADN);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int dnWrap = dn->getWrap();
Shinya Kitaoka 120a6e
  int upWrap = up->getWrap();
Shinya Kitaoka 120a6e
  dn->lock();
Shinya Kitaoka 120a6e
  up->lock();
Shinya Kitaoka 120a6e
  TPixel32 *dnRow     = dn->pixels(yMin);
Shinya Kitaoka 120a6e
  TPixel32 *upBasePix = up->pixels();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  scorre le scanline di boundingBoxD
Shinya Kitaoka 120a6e
  for (int y = yMin; y <= yMax; y++, dnRow += dnWrap) {
Shinya Kitaoka 120a6e
    //	(1)    equazione k-parametrica della y-esima
Shinya Kitaoka 120a6e
    //               scanline di boundingBoxD:
Shinya Kitaoka 120a6e
    //	       (xMin, y) + k*(1, 0),  k = 0, ..., (xMax - xMin)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //	(2)    equazione k-parametrica dell'immagine mediante
Shinya Kitaoka 120a6e
    //               invAff di (1):
Shinya Kitaoka 120a6e
    //	       invAff*(xMin, y) + k*(deltaXD, deltaYD),
Shinya Kitaoka 120a6e
    //	       k = kMin, ..., kMax
Shinya Kitaoka 120a6e
    //               con 0 <= kMin <= kMax <= (xMax - xMin)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  calcola kMin, kMax per la scanline corrente intersecando la (2)
Shinya Kitaoka 120a6e
    //  con i lati di up
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  il segmento [a, b] di up e' la controimmagine mediante aff
Shinya Kitaoka 120a6e
    //  della porzione di scanline  [ (xMin, y), (xMax, y) ] di dn
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //        TPointD b = invAff*TPointD(xMax, y);
Shinya Kitaoka 120a6e
    TPointD a = invAff * TPointD(xMin, y);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //	(xL0, yL0) sono le coordinate di a in versione "TLonghizzata"
Shinya Kitaoka 120a6e
    //	0 <= xL0 + k*deltaXL
Shinya Kitaoka 120a6e
    //          <= (up->getLx() - 2)*(1<
Shinya Kitaoka 120a6e
    //          <= kMinX
Shinya Kitaoka 120a6e
    //          <= kMin
Shinya Kitaoka 120a6e
    //          <= k
Shinya Kitaoka 120a6e
    //          <= kMax
Shinya Kitaoka 120a6e
    //          <= kMaxX
Shinya Kitaoka 120a6e
    //          <= (xMax - xMin)
Shinya Kitaoka 120a6e
    //
Shinya Kitaoka 120a6e
    //	0 <= yL0 + k*deltaYL
Shinya Kitaoka 120a6e
    //          <= (up->getLy() - 2)*(1<
Shinya Kitaoka 120a6e
    //          <= kMinY
Shinya Kitaoka 120a6e
    //          <= kMin
Shinya Kitaoka 120a6e
    //          <= k
Shinya Kitaoka 120a6e
    //          <= kMax
Shinya Kitaoka 120a6e
    //          <= kMaxY
Shinya Kitaoka 120a6e
    //          <= (yMax - yMin)
Shinya Kitaoka 120a6e
    int xL0 = tround(a.x * (1 << PADN));  //  xL0 inizializzato
Shinya Kitaoka 120a6e
    int yL0 = tround(a.y * (1 << PADN));  //  yL0 inizializzato
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  calcola kMinX, kMaxX, kMinY, kMaxY
Shinya Kitaoka 120a6e
    int kMinX = 0, kMaxX = xMax - xMin;  //  clipping su dn
Shinya Kitaoka 120a6e
    int kMinY = 0, kMaxY = yMax - yMin;  //  clipping su dn
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //        0 <= xL0 + k*deltaXL <= (up->getLx() - 2)*(1<<PADN)
Shinya Kitaoka 120a6e
    //                   <=>
Shinya Kitaoka 120a6e
    //        0 <= xL0 + k*deltaXL <= lxPred
Shinya Kitaoka 120a6e
    //
Shinya Kitaoka 120a6e
    //
Shinya Kitaoka 120a6e
    //	0 <= yL0 + k*deltaYL <= (up->getLy() - 2)*(1<<PADN)
Shinya Kitaoka 120a6e
    //                   <=>
Shinya Kitaoka 120a6e
    //        0 <= yL0 + k*deltaYL <= lyPred
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  calcola kMinX, kMaxX
Shinya Kitaoka 120a6e
    if (deltaXL == 0) {
Shinya Kitaoka 120a6e
      //  [a, b] verticale esterno ad up contratto
Shinya Kitaoka 120a6e
      if ((xL0 < 0) || (lxPred < xL0)) continue;
Shinya Kitaoka 120a6e
      //  altrimenti usa solo
Shinya Kitaoka 120a6e
      //  kMinY, kMaxY ((deltaXL != 0) || (deltaYL != 0))
Shinya Kitaoka 120a6e
    } else if (deltaXL > 0) {
Shinya Kitaoka 120a6e
      if (lxPred < xL0)  //  [a, b] esterno ad up+(bordo destro)
Shinya Kitaoka 120a6e
        continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      kMaxX = (lxPred - xL0) / deltaXL;  //  floor
Shinya Kitaoka 120a6e
      if (xL0 < 0) {
Shinya Kitaoka 120a6e
        kMinX = ((-xL0) + deltaXL - 1) / deltaXL;  //  ceil
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else  //  (deltaXL < 0)
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      if (xL0 < 0)  //  [a, b] esterno ad up contratto
Shinya Kitaoka 120a6e
        continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      kMaxX = xL0 / (-deltaXL);  //  floor
Shinya Kitaoka 120a6e
      if (lxPred < xL0) {
Shinya Kitaoka 120a6e
        kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL);  //  ceil
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  calcola kMinY, kMaxY
Shinya Kitaoka 120a6e
    if (deltaYL == 0) {
Shinya Kitaoka 120a6e
      //  [a, b] orizzontale esterno ad up contratto
Shinya Kitaoka 120a6e
      if ((yL0 < 0) || (lyPred < yL0)) continue;
Shinya Kitaoka 120a6e
      //  altrimenti usa solo
Shinya Kitaoka 120a6e
      //  kMinX, kMaxX ((deltaXL != 0) || (deltaYL != 0))
Shinya Kitaoka 120a6e
    } else if (deltaYL > 0) {
Shinya Kitaoka 120a6e
      if (lyPred < yL0)  //  [a, b] esterno ad up contratto
Shinya Kitaoka 120a6e
        continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      kMaxY = (lyPred - yL0) / deltaYL;  //  floor
Shinya Kitaoka 120a6e
      if (yL0 < 0) {
Shinya Kitaoka 120a6e
        kMinY = ((-yL0) + deltaYL - 1) / deltaYL;  //  ceil
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else  //  (deltaYL < 0)
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      if (yL0 < 0)  //  [a, b] esterno ad up contratto
Shinya Kitaoka 120a6e
        continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      kMaxY = yL0 / (-deltaYL);  //  floor
Shinya Kitaoka 120a6e
      if (lyPred < yL0) {
Shinya Kitaoka 120a6e
        kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL);  //  ceil
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  calcola kMin, kMax effettuando anche il clipping su dn
Shinya Kitaoka 120a6e
    int kMin = std::max({kMinX, kMinY, (int)0});
Shinya Kitaoka 120a6e
    int kMax = std::min({kMaxX, kMaxY, xMax - xMin});
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TPixel32 *dnPix    = dnRow + xMin + kMin;
Shinya Kitaoka 120a6e
    TPixel32 *dnEndPix = dnRow + xMin + kMax + 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  (xL, yL) sono le coordinate (inizializzate per il round)
Shinya Kitaoka 120a6e
    //  in versione "TLonghizzata"
Shinya Kitaoka 120a6e
    //	del pixel corrente di up
Shinya Kitaoka 120a6e
    int xL = xL0 + (kMin - 1) * deltaXL;  //  inizializza xL
Shinya Kitaoka 120a6e
    int yL = yL0 + (kMin - 1) * deltaYL;  //  inizializza yL
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  scorre i pixel sulla y-esima scanline di boundingBoxD
Shinya Kitaoka 120a6e
    for (; dnPix < dnEndPix; ++dnPix) {
Shinya Kitaoka 120a6e
      xL += deltaXL;
Shinya Kitaoka 120a6e
      yL += deltaYL;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      //  il punto di up TPointD(xL/(1<
Shinya Kitaoka 120a6e
      //  e' approssimato con (xI, yI)
Shinya Kitaoka 120a6e
      int xI = xL >> PADN;  //	troncato
Shinya Kitaoka 120a6e
      int yI = yL >> PADN;  //	troncato
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      assert((0 <= xI) && (xI <= up->getLx() - 1) && (0 <= yI) &&
Shinya Kitaoka 120a6e
             (yI <= up->getLy() - 1));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      //  (xI, yI)
Shinya Kitaoka 120a6e
      TPixel32 *upPix00 = upBasePix + (yI * upWrap + xI);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      //  (xI + 1, yI)
Shinya Kitaoka 120a6e
      TPixel32 *upPix10 = upPix00 + 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      //  (xI, yI + 1)
Shinya Kitaoka 120a6e
      TPixel32 *upPix01 = upPix00 + upWrap;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      //  (xI + 1, yI + 1)
Shinya Kitaoka 120a6e
      TPixel32 *upPix11 = upPix00 + upWrap + 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      //  filtro bilineare 4 pixels: calcolo dei pesi
Shinya Kitaoka 120a6e
      int xWeight1 = (xL & MASKN);
Shinya Kitaoka 120a6e
      int xWeight0 = (1 << PADN) - xWeight1;
Shinya Kitaoka 120a6e
      int yWeight1 = (yL & MASKN);
Shinya Kitaoka 120a6e
      int yWeight0 = (1 << PADN) - yWeight1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      //  filtro bilineare 4 pixels: media pesata sui singoli canali
Shinya Kitaoka 120a6e
      int rColDownTmp =
Shinya Kitaoka 120a6e
          (xWeight0 * (upPix00->r) + xWeight1 * ((upPix10)->r)) >> PADN;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      int gColDownTmp =
Shinya Kitaoka 120a6e
          (xWeight0 * (upPix00->g) + xWeight1 * ((upPix10)->g)) >> PADN;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      int bColDownTmp =
Shinya Kitaoka 120a6e
          (xWeight0 * (upPix00->b) + xWeight1 * ((upPix10)->b)) >> PADN;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      int rColUpTmp =
Shinya Kitaoka 120a6e
          (xWeight0 * ((upPix01)->r) + xWeight1 * ((upPix11)->r)) >> PADN;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      int gColUpTmp =
Shinya Kitaoka 120a6e
          (xWeight0 * ((upPix01)->g) + xWeight1 * ((upPix11)->g)) >> PADN;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      int bColUpTmp =
Shinya Kitaoka 120a6e
          (xWeight0 * ((upPix01)->b) + xWeight1 * ((upPix11)->b)) >> PADN;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      unsigned char rCol =
Shinya Kitaoka 120a6e
          (unsigned char)((yWeight0 * rColDownTmp + yWeight1 * rColUpTmp) >>
Shinya Kitaoka 120a6e
                          PADN);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      unsigned char gCol =
Shinya Kitaoka 120a6e
          (unsigned char)((yWeight0 * gColDownTmp + yWeight1 * gColUpTmp) >>
Shinya Kitaoka 120a6e
                          PADN);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      unsigned char bCol =
Shinya Kitaoka 120a6e
          (unsigned char)((yWeight0 * bColDownTmp + yWeight1 * bColUpTmp) >>
Shinya Kitaoka 120a6e
                          PADN);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      TPixel32 upPix = TPixel32(rCol, gCol, bCol, upPix00->m);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (upPix.m == 0)
Shinya Kitaoka 120a6e
        continue;
Shinya Kitaoka 120a6e
      else if (upPix.m == 255)
Shinya Kitaoka 120a6e
        *dnPix = upPix;
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        *dnPix = quickOverPix(*dnPix, upPix);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  dn->unlock();
Shinya Kitaoka 120a6e
  up->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void doQuickPutNoFilter(const TRaster32P &dn, const TRaster32P &up,
Shinya Kitaoka 120a6e
                        const TAffine &aff, const TPixel32 &colorScale,
Shinya Kitaoka 120a6e
                        bool doPremultiply, bool whiteTransp, bool firstColumn,
Shinya Kitaoka 120a6e
                        bool doRasterDarkenBlendedView) {
Shinya Kitaoka 120a6e
  //  se aff := TAffine(sx, 0, tx, 0, sy, ty) e' degenere la controimmagine
Shinya Kitaoka 120a6e
  //  di up e' un segmento (o un punto)
Shinya Kitaoka 120a6e
  if ((aff.a11 * aff.a22 - aff.a12 * aff.a21) == 0) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  contatore bit di shift
Shinya Kitaoka 120a6e
  const int PADN = 16;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  max dimensioni di up gestibili (limite imposto dal numero di bit
Shinya Kitaoka 120a6e
  //  disponibili per la parte intera di xL, yL)
Shinya Kitaoka 120a6e
  assert(std::max(up->getLx(), up->getLy()) <
Shinya Kitaoka 120a6e
         (1 << (8 * sizeof(int) - PADN - 1)));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRectD boundingBoxD =
Shinya Kitaoka 120a6e
      TRectD(convert(dn->getBounds())) *
Shinya Kitaoka 120a6e
      (aff * TRectD(-0.5, -0.5, up->getLx() - 0.5, up->getLy() - 0.5));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping
Shinya Kitaoka 120a6e
  if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1)
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping y su dn
Shinya Kitaoka 120a6e
  int yMin = std::max(tfloor(boundingBoxD.y0), 0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping y su dn
Shinya Kitaoka 120a6e
  int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping x su dn
Shinya Kitaoka 120a6e
  int xMin = std::max(tfloor(boundingBoxD.x0), 0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping x su dn
Shinya Kitaoka 120a6e
  int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  inversa di aff
Shinya Kitaoka 120a6e
  TAffine invAff = inv(aff);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  nel disegnare la y-esima scanline di dn, il passaggio al pixel
Shinya Kitaoka 120a6e
  //  successivo comporta l'incremento (deltaXD, deltaYD) delle coordinate del
Shinya Kitaoka 120a6e
  //  pixel corrispondente di up
Shinya Kitaoka 120a6e
  double deltaXD = invAff.a11;
Shinya Kitaoka 120a6e
  double deltaYD = invAff.a21;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  deltaXD "TLonghizzato" (round)
Shinya Kitaoka 120a6e
  int deltaXL = tround(deltaXD * (1 << PADN));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  deltaYD "TLonghizzato" (round)
Shinya Kitaoka 120a6e
  int deltaYL = tround(deltaYD * (1 << PADN));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  se aff "TLonghizzata" (round) e' degenere la controimmagine di up e' un
Shinya Kitaoka 120a6e
  //  segmento (o un punto)
Shinya Kitaoka 120a6e
  if ((deltaXL == 0) && (deltaYL == 0)) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  TINT32 predecessore di up->getLx()
Shinya Kitaoka 120a6e
  int lxPred = up->getLx() * (1 << PADN) - 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  TINT32 predecessore di up->getLy()
Shinya Kitaoka 120a6e
  int lyPred = up->getLy() * (1 << PADN) - 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int dnWrap = dn->getWrap();
Shinya Kitaoka 120a6e
  int upWrap = up->getWrap();
Shinya Kitaoka 120a6e
  dn->lock();
Shinya Kitaoka 120a6e
  up->lock();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TPixel32 *dnRow     = dn->pixels(yMin);
Shinya Kitaoka 120a6e
  TPixel32 *upBasePix = up->pixels();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  scorre le scanline di boundingBoxD
Shinya Kitaoka 120a6e
  for (int y = yMin; y <= yMax; y++, dnRow += dnWrap) {
Shinya Kitaoka 120a6e
    //  (1)  equazione k-parametrica della y-esima scanline di boundingBoxD:
Shinya Kitaoka 120a6e
    //       (xMin, y) + k*(1, 0),  k = 0, ..., (xMax - xMin)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  (2)  equazione k-parametrica dell'immagine mediante invAff di (1):
Shinya Kitaoka 120a6e
    //       invAff*(xMin, y) + k*(deltaXD, deltaYD),
Shinya Kitaoka 120a6e
    //       k = kMin, ..., kMax con 0 <= kMin <= kMax <= (xMax - xMin)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  calcola kMin, kMax per la scanline corrente
Shinya Kitaoka 120a6e
    //  intersecando la (2) con i lati di up
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  il segmento [a, b] di up e' la controimmagine mediante aff della
Shinya Kitaoka 120a6e
    //  porzione di scanline  [ (xMin, y), (xMax, y) ] di dn
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  TPointD b = invAff*TPointD(xMax, y);
Shinya Kitaoka 120a6e
    TPointD a = invAff * TPointD(xMin, y);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  (xL0, yL0) sono le coordinate di a (inizializzate per il round)
Shinya Kitaoka 120a6e
    //  in versione "TLonghizzata"
Shinya Kitaoka 120a6e
    //  0 <= xL0 + k*deltaXL
Shinya Kitaoka 120a6e
    //    <  up->getLx()*(1<<PADN)
Shinya Kitaoka 120a6e
    //
Shinya Kitaoka 120a6e
    //  0 <= kMinX
Shinya Kitaoka 120a6e
    //    <= kMin
Shinya Kitaoka 120a6e
    //    <= k
Shinya Kitaoka 120a6e
    //    <= kMax
Shinya Kitaoka 120a6e
    //    <= kMaxX
Shinya Kitaoka 120a6e
    //    <= (xMax - xMin)
Shinya Kitaoka 120a6e
    //
Shinya Kitaoka 120a6e
    //  0 <= yL0 + k*deltaYL
Shinya Kitaoka 120a6e
    //    < up->getLy()*(1<<PADN)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  0 <= kMinY
Shinya Kitaoka 120a6e
    //    <= kMin
Shinya Kitaoka 120a6e
    //    <= k
Shinya Kitaoka 120a6e
    //    <= kMax
Shinya Kitaoka 120a6e
    //    <= kMaxY
Shinya Kitaoka 120a6e
    //    <= (xMax - xMin)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  xL0 inizializzato per il round
Shinya Kitaoka 120a6e
    int xL0 = tround((a.x + 0.5) * (1 << PADN));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  yL0 inizializzato per il round
Shinya Kitaoka 120a6e
    int yL0 = tround((a.y + 0.5) * (1 << PADN));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  calcola kMinX, kMaxX, kMinY, kMaxY
Shinya Kitaoka 120a6e
    int kMinX = 0, kMaxX = xMax - xMin;  //  clipping su dn
Shinya Kitaoka 120a6e
    int kMinY = 0, kMaxY = xMax - xMin;  //  clipping su dn
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  0 <= xL0 + k*deltaXL
Shinya Kitaoka 120a6e
    //    < up->getLx()*(1<<PADN)
Shinya Kitaoka 120a6e
    //           <=>
Shinya Kitaoka 120a6e
    //  0 <= xL0 + k*deltaXL
Shinya Kitaoka 120a6e
    //    <= lxPred
Shinya Kitaoka 120a6e
    //
Shinya Kitaoka 120a6e
    //  0 <= yL0 + k*deltaYL
Shinya Kitaoka 120a6e
    //    < up->getLy()*(1<<PADN)
Shinya Kitaoka 120a6e
    //           <=>
Shinya Kitaoka 120a6e
    //  0 <= yL0 + k*deltaYL
Shinya Kitaoka 120a6e
    //    <= lyPred
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  calcola kMinX, kMaxX
Shinya Kitaoka 120a6e
    if (deltaXL == 0) {
Shinya Kitaoka 120a6e
      // [a, b] verticale esterno ad up+(bordo destro/basso)
Shinya Kitaoka 120a6e
      if ((xL0 < 0) || (lxPred < xL0)) continue;
Shinya Kitaoka 120a6e
      //  altrimenti usa solo
Shinya Kitaoka 120a6e
      //  kMinY, kMaxY ((deltaXL != 0) || (deltaYL != 0))
Shinya Kitaoka 120a6e
    } else if (deltaXL > 0) {
Shinya Kitaoka 120a6e
      //  [a, b] esterno ad up+(bordo destro/basso)
Shinya Kitaoka 120a6e
      if (lxPred < xL0) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      kMaxX = (lxPred - xL0) / deltaXL;  //  floor
Shinya Kitaoka 120a6e
      if (xL0 < 0) {
Shinya Kitaoka 120a6e
        kMinX = ((-xL0) + deltaXL - 1) / deltaXL;  //  ceil
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else  //  (deltaXL < 0)
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      //  [a, b] esterno ad up+(bordo destro/basso)
Shinya Kitaoka 120a6e
      if (xL0 < 0) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      kMaxX = xL0 / (-deltaXL);  //  floor
Shinya Kitaoka 120a6e
      if (lxPred < xL0) {
Shinya Kitaoka 120a6e
        kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL);  //  ceil
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  calcola kMinY, kMaxY
Shinya Kitaoka 120a6e
    if (deltaYL == 0) {
Shinya Kitaoka 120a6e
      //  [a, b] orizzontale esterno ad up+(bordo destro/basso)
Shinya Kitaoka 120a6e
      if ((yL0 < 0) || (lyPred < yL0)) continue;
Shinya Kitaoka 120a6e
      // altrimenti usa solo
Shinya Kitaoka 120a6e
      // kMinX, kMaxX ((deltaXL != 0) || (deltaYL != 0))
Shinya Kitaoka 120a6e
    } else if (deltaYL > 0) {
Shinya Kitaoka 120a6e
      //  [a, b] esterno ad up+(bordo destro/basso)
Shinya Kitaoka 120a6e
      if (lyPred < yL0) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      kMaxY = (lyPred - yL0) / deltaYL;  //  floor
Shinya Kitaoka 120a6e
      if (yL0 < 0) {
Shinya Kitaoka 120a6e
        kMinY = ((-yL0) + deltaYL - 1) / deltaYL;  //  ceil
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else  //  (deltaYL < 0)
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      //  [a, b] esterno ad up+(bordo destro/basso)
Shinya Kitaoka 120a6e
      if (yL0 < 0) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      kMaxY = yL0 / (-deltaYL);  //  floor
Shinya Kitaoka 120a6e
      if (lyPred < yL0) {
Shinya Kitaoka 120a6e
        kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL);  //  ceil
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  calcola kMin, kMax effettuando anche il clippind su dn
Shinya Kitaoka 120a6e
    int kMin = std::max({kMinX, kMinY, (int)0});
Shinya Kitaoka 120a6e
    int kMax = std::min({kMaxX, kMaxY, xMax - xMin});
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TPixel32 *dnPix    = dnRow + xMin + kMin;
Shinya Kitaoka 120a6e
    TPixel32 *dnEndPix = dnRow + xMin + kMax + 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  (xL, yL) sono le coordinate (inizializzate per il round)
Shinya Kitaoka 120a6e
    //  in versione "TLonghizzata" del pixel corrente di up
Shinya Kitaoka 120a6e
    int xL = xL0 + (kMin - 1) * deltaXL;  //  inizializza xL
Shinya Kitaoka 120a6e
    int yL = yL0 + (kMin - 1) * deltaYL;  //  inizializza yL
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  scorre i pixel sulla y-esima scanline di boundingBoxD
Shinya Kitaoka 120a6e
    for (; dnPix < dnEndPix; ++dnPix) {
Shinya Kitaoka 120a6e
      xL += deltaXL;
Shinya Kitaoka 120a6e
      yL += deltaYL;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      //  il punto di up TPointD(xL/(1<
Shinya Kitaoka 120a6e
      //  approssimato con (xI, yI)
Shinya Kitaoka 120a6e
      int xI = xL >> PADN;  //  round
Shinya Kitaoka 120a6e
      int yI = yL >> PADN;  //  round
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      assert((0 <= xI) && (xI <= up->getLx() - 1) && (0 <= yI) &&
Shinya Kitaoka 120a6e
             (yI <= up->getLy() - 1));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      TPixel32 upPix = *(upBasePix + (yI * upWrap + xI));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (firstColumn) upPix.m = 255;
Shinya Kitaoka 120a6e
      if (upPix.m == 0 || (whiteTransp && upPix == TPixel::White)) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (colorScale != TPixel32::Black)
Shinya Kitaoka 120a6e
        upPix = applyColorScale(upPix, colorScale, doPremultiply);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (doRasterDarkenBlendedView)
Shinya Kitaoka 120a6e
        *dnPix = quickOverPixDarkenBlended(*dnPix, upPix);
Shinya Kitaoka 120a6e
      else {
Shinya Kitaoka 120a6e
        if (upPix.m == 255)
Shinya Kitaoka 120a6e
          *dnPix = upPix;
Shinya Kitaoka 120a6e
        else if (doPremultiply)
Shinya Kitaoka 120a6e
          *dnPix = quickOverPixPremult(*dnPix, upPix);
Shinya Kitaoka 120a6e
        else
Shinya Kitaoka 120a6e
          *dnPix = quickOverPix(*dnPix, upPix);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  dn->unlock();
Shinya Kitaoka 120a6e
  up->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void doQuickPutNoFilter(const TRaster32P &dn, const TRaster64P &up,
Shinya Kitaoka 120a6e
                        const TAffine &aff, bool doPremultiply,
Shinya Kitaoka 120a6e
                        bool firstColumn) {
Shinya Kitaoka 120a6e
  //  se aff := TAffine(sx, 0, tx, 0, sy, ty) e' degenere la controimmagine
Shinya Kitaoka 120a6e
  //  di up e' un segmento (o un punto)
Shinya Kitaoka 120a6e
  if ((aff.a11 * aff.a22 - aff.a12 * aff.a21) == 0) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  contatore bit di shift
Shinya Kitaoka 120a6e
  const int PADN = 16;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  max dimensioni di up gestibili (limite imposto dal numero di bit
Shinya Kitaoka 120a6e
  //  disponibili per la parte intera di xL, yL)
Shinya Kitaoka 120a6e
  assert(std::max(up->getLx(), up->getLy()) <
Shinya Kitaoka 120a6e
         (1 << (8 * sizeof(int) - PADN - 1)));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRectD boundingBoxD =
Shinya Kitaoka 120a6e
      TRectD(convert(dn->getBounds())) *
Shinya Kitaoka 120a6e
      (aff * TRectD(-0.5, -0.5, up->getLx() - 0.5, up->getLy() - 0.5));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping
Shinya Kitaoka 120a6e
  if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1)
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping y su dn
Shinya Kitaoka 120a6e
  int yMin = std::max(tfloor(boundingBoxD.y0), 0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping y su dn
Shinya Kitaoka 120a6e
  int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping x su dn
Shinya Kitaoka 120a6e
  int xMin = std::max(tfloor(boundingBoxD.x0), 0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping x su dn
Shinya Kitaoka 120a6e
  int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  inversa di aff
Shinya Kitaoka 120a6e
  TAffine invAff = inv(aff);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  nel disegnare la y-esima scanline di dn, il passaggio al pixel
Shinya Kitaoka 120a6e
  //  successivo comporta l'incremento (deltaXD, deltaYD) delle coordinate del
Shinya Kitaoka 120a6e
  //  pixel corrispondente di up
Shinya Kitaoka 120a6e
  double deltaXD = invAff.a11;
Shinya Kitaoka 120a6e
  double deltaYD = invAff.a21;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  deltaXD "TLonghizzato" (round)
Shinya Kitaoka 120a6e
  int deltaXL = tround(deltaXD * (1 << PADN));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  deltaYD "TLonghizzato" (round)
Shinya Kitaoka 120a6e
  int deltaYL = tround(deltaYD * (1 << PADN));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  se aff "TLonghizzata" (round) e' degenere la controimmagine di up e' un
Shinya Kitaoka 120a6e
  //  segmento (o un punto)
Shinya Kitaoka 120a6e
  if ((deltaXL == 0) && (deltaYL == 0)) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  TINT32 predecessore di up->getLx()
Shinya Kitaoka 120a6e
  int lxPred = up->getLx() * (1 << PADN) - 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  TINT32 predecessore di up->getLy()
Shinya Kitaoka 120a6e
  int lyPred = up->getLy() * (1 << PADN) - 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int dnWrap = dn->getWrap();
Shinya Kitaoka 120a6e
  int upWrap = up->getWrap();
Shinya Kitaoka 120a6e
  dn->lock();
Shinya Kitaoka 120a6e
  up->lock();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TPixel32 *dnRow     = dn->pixels(yMin);
Shinya Kitaoka 120a6e
  TPixel64 *upBasePix = up->pixels();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  scorre le scanline di boundingBoxD
Shinya Kitaoka 120a6e
  for (int y = yMin; y <= yMax; y++, dnRow += dnWrap) {
Shinya Kitaoka 120a6e
    //  (1)  equazione k-parametrica della y-esima scanline di boundingBoxD:
Shinya Kitaoka 120a6e
    //       (xMin, y) + k*(1, 0),  k = 0, ..., (xMax - xMin)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  (2)  equazione k-parametrica dell'immagine mediante invAff di (1):
Shinya Kitaoka 120a6e
    //       invAff*(xMin, y) + k*(deltaXD, deltaYD),
Shinya Kitaoka 120a6e
    //       k = kMin, ..., kMax con 0 <= kMin <= kMax <= (xMax - xMin)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  calcola kMin, kMax per la scanline corrente
Shinya Kitaoka 120a6e
    //  intersecando la (2) con i lati di up
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  il segmento [a, b] di up e' la controimmagine mediante aff della
Shinya Kitaoka 120a6e
    //  porzione di scanline  [ (xMin, y), (xMax, y) ] di dn
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  TPointD b = invAff*TPointD(xMax, y);
Shinya Kitaoka 120a6e
    TPointD a = invAff * TPointD(xMin, y);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  (xL0, yL0) sono le coordinate di a (inizializzate per il round)
Shinya Kitaoka 120a6e
    //  in versione "TLonghizzata"
Shinya Kitaoka 120a6e
    //  0 <= xL0 + k*deltaXL
Shinya Kitaoka 120a6e
    //    <  up->getLx()*(1<<PADN)
Shinya Kitaoka 120a6e
    //
Shinya Kitaoka 120a6e
    //  0 <= kMinX
Shinya Kitaoka 120a6e
    //    <= kMin
Shinya Kitaoka 120a6e
    //    <= k
Shinya Kitaoka 120a6e
    //    <= kMax
Shinya Kitaoka 120a6e
    //    <= kMaxX
Shinya Kitaoka 120a6e
    //    <= (xMax - xMin)
Shinya Kitaoka 120a6e
    //
Shinya Kitaoka 120a6e
    //  0 <= yL0 + k*deltaYL
Shinya Kitaoka 120a6e
    //    < up->getLy()*(1<<PADN)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  0 <= kMinY
Shinya Kitaoka 120a6e
    //    <= kMin
Shinya Kitaoka 120a6e
    //    <= k
Shinya Kitaoka 120a6e
    //    <= kMax
Shinya Kitaoka 120a6e
    //    <= kMaxY
Shinya Kitaoka 120a6e
    //    <= (xMax - xMin)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  xL0 inizializzato per il round
Shinya Kitaoka 120a6e
    int xL0 = tround((a.x + 0.5) * (1 << PADN));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  yL0 inizializzato per il round
Shinya Kitaoka 120a6e
    int yL0 = tround((a.y + 0.5) * (1 << PADN));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  calcola kMinX, kMaxX, kMinY, kMaxY
Shinya Kitaoka 120a6e
    int kMinX = 0, kMaxX = xMax - xMin;  //  clipping su dn
Shinya Kitaoka 120a6e
    int kMinY = 0, kMaxY = xMax - xMin;  //  clipping su dn
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  0 <= xL0 + k*deltaXL
Shinya Kitaoka 120a6e
    //    < up->getLx()*(1<<PADN)
Shinya Kitaoka 120a6e
    //           <=>
Shinya Kitaoka 120a6e
    //  0 <= xL0 + k*deltaXL
Shinya Kitaoka 120a6e
    //    <= lxPred
Shinya Kitaoka 120a6e
    //
Shinya Kitaoka 120a6e
    //  0 <= yL0 + k*deltaYL
Shinya Kitaoka 120a6e
    //    < up->getLy()*(1<<PADN)
Shinya Kitaoka 120a6e
    //           <=>
Shinya Kitaoka 120a6e
    //  0 <= yL0 + k*deltaYL
Shinya Kitaoka 120a6e
    //    <= lyPred
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  calcola kMinX, kMaxX
Shinya Kitaoka 120a6e
    if (deltaXL == 0) {
Shinya Kitaoka 120a6e
      // [a, b] verticale esterno ad up+(bordo destro/basso)
Shinya Kitaoka 120a6e
      if ((xL0 < 0) || (lxPred < xL0)) continue;
Shinya Kitaoka 120a6e
      //  altrimenti usa solo
Shinya Kitaoka 120a6e
      //  kMinY, kMaxY ((deltaXL != 0) || (deltaYL != 0))
Shinya Kitaoka 120a6e
    } else if (deltaXL > 0) {
Shinya Kitaoka 120a6e
      //  [a, b] esterno ad up+(bordo destro/basso)
Shinya Kitaoka 120a6e
      if (lxPred < xL0) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      kMaxX = (lxPred - xL0) / deltaXL;  //  floor
Shinya Kitaoka 120a6e
      if (xL0 < 0) {
Shinya Kitaoka 120a6e
        kMinX = ((-xL0) + deltaXL - 1) / deltaXL;  //  ceil
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else  //  (deltaXL < 0)
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      //  [a, b] esterno ad up+(bordo destro/basso)
Shinya Kitaoka 120a6e
      if (xL0 < 0) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      kMaxX = xL0 / (-deltaXL);  //  floor
Shinya Kitaoka 120a6e
      if (lxPred < xL0) {
Shinya Kitaoka 120a6e
        kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL);  //  ceil
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  calcola kMinY, kMaxY
Shinya Kitaoka 120a6e
    if (deltaYL == 0) {
Shinya Kitaoka 120a6e
      //  [a, b] orizzontale esterno ad up+(bordo destro/basso)
Shinya Kitaoka 120a6e
      if ((yL0 < 0) || (lyPred < yL0)) continue;
Shinya Kitaoka 120a6e
      // altrimenti usa solo
Shinya Kitaoka 120a6e
      // kMinX, kMaxX ((deltaXL != 0) || (deltaYL != 0))
Shinya Kitaoka 120a6e
    } else if (deltaYL > 0) {
Shinya Kitaoka 120a6e
      //  [a, b] esterno ad up+(bordo destro/basso)
Shinya Kitaoka 120a6e
      if (lyPred < yL0) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      kMaxY = (lyPred - yL0) / deltaYL;  //  floor
Shinya Kitaoka 120a6e
      if (yL0 < 0) {
Shinya Kitaoka 120a6e
        kMinY = ((-yL0) + deltaYL - 1) / deltaYL;  //  ceil
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else  //  (deltaYL < 0)
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      //  [a, b] esterno ad up+(bordo destro/basso)
Shinya Kitaoka 120a6e
      if (yL0 < 0) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      kMaxY = yL0 / (-deltaYL);  //  floor
Shinya Kitaoka 120a6e
      if (lyPred < yL0) {
Shinya Kitaoka 120a6e
        kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL);  //  ceil
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  calcola kMin, kMax effettuando anche il clippind su dn
Shinya Kitaoka 120a6e
    int kMin = std::max({kMinX, kMinY, (int)0});
Shinya Kitaoka 120a6e
    int kMax = std::min({kMaxX, kMaxY, xMax - xMin});
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TPixel32 *dnPix    = dnRow + xMin + kMin;
Shinya Kitaoka 120a6e
    TPixel32 *dnEndPix = dnRow + xMin + kMax + 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  (xL, yL) sono le coordinate (inizializzate per il round)
Shinya Kitaoka 120a6e
    //  in versione "TLonghizzata" del pixel corrente di up
Shinya Kitaoka 120a6e
    int xL = xL0 + (kMin - 1) * deltaXL;  //  inizializza xL
Shinya Kitaoka 120a6e
    int yL = yL0 + (kMin - 1) * deltaYL;  //  inizializza yL
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  scorre i pixel sulla y-esima scanline di boundingBoxD
Shinya Kitaoka 120a6e
    for (; dnPix < dnEndPix; ++dnPix) {
Shinya Kitaoka 120a6e
      xL += deltaXL;
Shinya Kitaoka 120a6e
      yL += deltaYL;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      //  il punto di up TPointD(xL/(1<
Shinya Kitaoka 120a6e
      //  approssimato con (xI, yI)
Shinya Kitaoka 120a6e
      int xI = xL >> PADN;  //  round
Shinya Kitaoka 120a6e
      int yI = yL >> PADN;  //  round
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      assert((0 <= xI) && (xI <= up->getLx() - 1) && (0 <= yI) &&
Shinya Kitaoka 120a6e
             (yI <= up->getLy() - 1));
Shinya Kitaoka 120a6e
shun-iwasawa 84ffc5
      TPixel64 *upPix = upBasePix + (yI * upWrap + xI);
Shinya Kitaoka 120a6e
      if (firstColumn) upPix->m = 65535;
Shinya Kitaoka 120a6e
      if (upPix->m == 0)
Shinya Kitaoka 120a6e
        continue;
Shinya Kitaoka 120a6e
      else if (upPix->m == 65535)
Shinya Kitaoka 120a6e
        *dnPix = PixelConverter<TPixel32>::from(*upPix);
Shinya Kitaoka 120a6e
      else if (doPremultiply)
Shinya Kitaoka 120a6e
        *dnPix =
Shinya Kitaoka 120a6e
            quickOverPixPremult(*dnPix, PixelConverter<TPixel32>::from(*upPix));
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        *dnPix = quickOverPix(*dnPix, PixelConverter<TPixel32>::from(*upPix));
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  dn->unlock();
Shinya Kitaoka 120a6e
  up->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void doQuickPutNoFilter(const TRaster32P &dn, const TRasterGR8P &up,
Shinya Kitaoka 120a6e
                        const TAffine &aff, const TPixel32 &colorScale) {
Shinya Kitaoka 120a6e
  if ((aff.a11 * aff.a22 - aff.a12 * aff.a21) == 0) return;
Shinya Kitaoka 120a6e
  const int PADN = 16;
Shinya Kitaoka 120a6e
  assert(std::max(up->getLx(), up->getLy()) <
Shinya Kitaoka 120a6e
         (1 << (8 * sizeof(int) - PADN - 1)));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TRectD boundingBoxD =
Shinya Kitaoka 120a6e
      TRectD(convert(dn->getBounds())) *
Shinya Kitaoka 120a6e
      (aff * TRectD(-0.5, -0.5, up->getLx() - 0.5, up->getLy() - 0.5));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1)
Shinya Kitaoka 120a6e
    return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int yMin = std::max(tfloor(boundingBoxD.y0), 0);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int xMin = std::max(tfloor(boundingBoxD.x0), 0);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TAffine invAff = inv(aff);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  double deltaXD = invAff.a11;
Shinya Kitaoka 120a6e
  double deltaYD = invAff.a21;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int deltaXL = tround(deltaXD * (1 << PADN));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int deltaYL = tround(deltaYD * (1 << PADN));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if ((deltaXL == 0) && (deltaYL == 0)) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int lxPred = up->getLx() * (1 << PADN) - 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int lyPred = up->getLy() * (1 << PADN) - 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int dnWrap = dn->getWrap();
Shinya Kitaoka 120a6e
  int upWrap = up->getWrap();
Shinya Kitaoka 120a6e
  dn->lock();
Shinya Kitaoka 120a6e
  up->lock();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TPixel32 *dnRow      = dn->pixels(yMin);
Shinya Kitaoka 120a6e
  TPixelGR8 *upBasePix = up->pixels();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (int y = yMin; y <= yMax; y++, dnRow += dnWrap) {
Shinya Kitaoka 120a6e
    TPointD a = invAff * TPointD(xMin, y);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    int xL0 = tround((a.x + 0.5) * (1 << PADN));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    int yL0 = tround((a.y + 0.5) * (1 << PADN));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    int kMinX = 0, kMaxX = xMax - xMin;  //  clipping su dn
Shinya Kitaoka 120a6e
    int kMinY = 0, kMaxY = xMax - xMin;  //  clipping su dn
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (deltaXL == 0) {
Shinya Kitaoka 120a6e
      if ((xL0 < 0) || (lxPred < xL0)) continue;
Shinya Kitaoka 120a6e
    } else if (deltaXL > 0) {
Shinya Kitaoka 120a6e
      if (lxPred < xL0) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      kMaxX = (lxPred - xL0) / deltaXL;  //  floor
Shinya Kitaoka 120a6e
      if (xL0 < 0) {
Shinya Kitaoka 120a6e
        kMinX = ((-xL0) + deltaXL - 1) / deltaXL;  //  ceil
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else  //  (deltaXL < 0)
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      //  [a, b] esterno ad up+(bordo destro/basso)
Shinya Kitaoka 120a6e
      if (xL0 < 0) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      kMaxX = xL0 / (-deltaXL);  //  floor
Shinya Kitaoka 120a6e
      if (lxPred < xL0) {
Shinya Kitaoka 120a6e
        kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL);  //  ceil
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  calcola kMinY, kMaxY
Shinya Kitaoka 120a6e
    if (deltaYL == 0) {
Shinya Kitaoka 120a6e
      //  [a, b] orizzontale esterno ad up+(bordo destro/basso)
Shinya Kitaoka 120a6e
      if ((yL0 < 0) || (lyPred < yL0)) continue;
Shinya Kitaoka 120a6e
      // altrimenti usa solo
Shinya Kitaoka 120a6e
      // kMinX, kMaxX ((deltaXL != 0) || (deltaYL != 0))
Shinya Kitaoka 120a6e
    } else if (deltaYL > 0) {
Shinya Kitaoka 120a6e
      //  [a, b] esterno ad up+(bordo destro/basso)
Shinya Kitaoka 120a6e
      if (lyPred < yL0) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      kMaxY = (lyPred - yL0) / deltaYL;  //  floor
Shinya Kitaoka 120a6e
      if (yL0 < 0) {
Shinya Kitaoka 120a6e
        kMinY = ((-yL0) + deltaYL - 1) / deltaYL;  //  ceil
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else  //  (deltaYL < 0)
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      //  [a, b] esterno ad up+(bordo destro/basso)
Shinya Kitaoka 120a6e
      if (yL0 < 0) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      kMaxY = yL0 / (-deltaYL);  //  floor
Shinya Kitaoka 120a6e
      if (lyPred < yL0) {
Shinya Kitaoka 120a6e
        kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL);  //  ceil
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  calcola kMin, kMax effettuando anche il clippind su dn
Shinya Kitaoka 120a6e
    int kMin = std::max({kMinX, kMinY, (int)0});
Shinya Kitaoka 120a6e
    int kMax = std::min({kMaxX, kMaxY, xMax - xMin});
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TPixel32 *dnPix    = dnRow + xMin + kMin;
Shinya Kitaoka 120a6e
    TPixel32 *dnEndPix = dnRow + xMin + kMax + 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  (xL, yL) sono le coordinate (inizializzate per il round)
Shinya Kitaoka 120a6e
    //  in versione "TLonghizzata" del pixel corrente di up
Shinya Kitaoka 120a6e
    int xL = xL0 + (kMin - 1) * deltaXL;  //  inizializza xL
Shinya Kitaoka 120a6e
    int yL = yL0 + (kMin - 1) * deltaYL;  //  inizializza yL
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  scorre i pixel sulla y-esima scanline di boundingBoxD
Shinya Kitaoka 120a6e
    for (; dnPix < dnEndPix; ++dnPix) {
Shinya Kitaoka 120a6e
      xL += deltaXL;
Shinya Kitaoka 120a6e
      yL += deltaYL;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      //  il punto di up TPointD(xL/(1<
Shinya Kitaoka 120a6e
      //  approssimato con (xI, yI)
Shinya Kitaoka 120a6e
      int xI = xL >> PADN;  //  round
Shinya Kitaoka 120a6e
      int yI = yL >> PADN;  //  round
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      assert((0 <= xI) && (xI <= up->getLx() - 1) && (0 <= yI) &&
Shinya Kitaoka 120a6e
             (yI <= up->getLy() - 1));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      TPixelGR8 *upPix = upBasePix + (yI * upWrap + xI);
Shinya Kitaoka 120a6e
      if (colorScale == TPixel32::Black) {
Shinya Kitaoka 120a6e
        if (upPix->value == 0)
Shinya Kitaoka 120a6e
          dnPix->r = dnPix->g = dnPix->b = 0;
Shinya Kitaoka 120a6e
        else if (upPix->value == 255)
Shinya Kitaoka 120a6e
          dnPix->r = dnPix->g = dnPix->b = upPix->value;
Shinya Kitaoka 120a6e
        else
Shinya Kitaoka 120a6e
          *dnPix = quickOverPix(*dnPix, *upPix);
Shinya Kitaoka 120a6e
        dnPix->m = 255;
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        TPixel32 upPix32(upPix->value, upPix->value, upPix->value, 255);
Shinya Kitaoka 120a6e
        upPix32 = applyColorScale(upPix32, colorScale);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        if (upPix32.m == 255)
Shinya Kitaoka 120a6e
          *dnPix = upPix32;
Shinya Kitaoka 120a6e
        else
Shinya Kitaoka 120a6e
          *dnPix = quickOverPix(*dnPix, upPix32);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  dn->unlock();
Shinya Kitaoka 120a6e
  up->unlock();
Toshihiro Shimizu 890ddd
}
shun-iwasawa 215a5b
//=============================================================================
shun-iwasawa 215a5b
//=============================================================================
shun-iwasawa 215a5b
shun-iwasawa 215a5b
void doQuickPutNoFilter(const TRaster64P &dn, const TRaster64P &up,
shun-iwasawa 215a5b
                        const TAffine &aff, bool doPremultiply,
shun-iwasawa 215a5b
                        bool firstColumn) {
shun-iwasawa 215a5b
  //  se aff := TAffine(sx, 0, tx, 0, sy, ty) e' degenere la controimmagine
shun-iwasawa 215a5b
  //  di up e' un segmento (o un punto)
shun-iwasawa 215a5b
  if ((aff.a11 * aff.a22 - aff.a12 * aff.a21) == 0) return;
shun-iwasawa 215a5b
shun-iwasawa 215a5b
  //  contatore bit di shift
shun-iwasawa 215a5b
  const int PADN = 16;
shun-iwasawa 215a5b
shun-iwasawa 215a5b
  //  max dimensioni di up gestibili (limite imposto dal numero di bit
shun-iwasawa 215a5b
  //  disponibili per la parte intera di xL, yL)
shun-iwasawa 215a5b
  assert(std::max(up->getLx(), up->getLy()) <
shun-iwasawa 215a5b
         (1 << (8 * sizeof(int) - PADN - 1)));
shun-iwasawa 215a5b
shun-iwasawa 215a5b
  TRectD boundingBoxD =
shun-iwasawa 215a5b
      TRectD(convert(dn->getBounds())) *
shun-iwasawa 215a5b
      (aff * TRectD(-0.5, -0.5, up->getLx() - 0.5, up->getLy() - 0.5));
shun-iwasawa 215a5b
shun-iwasawa 215a5b
  //  clipping
shun-iwasawa 215a5b
  if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1)
shun-iwasawa 215a5b
    return;
shun-iwasawa 215a5b
shun-iwasawa 215a5b
  //  clipping y su dn
shun-iwasawa 215a5b
  int yMin = std::max(tfloor(boundingBoxD.y0), 0);
shun-iwasawa 215a5b
shun-iwasawa 215a5b
  //  clipping y su dn
shun-iwasawa 215a5b
  int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1);
shun-iwasawa 215a5b
shun-iwasawa 215a5b
  //  clipping x su dn
shun-iwasawa 215a5b
  int xMin = std::max(tfloor(boundingBoxD.x0), 0);
shun-iwasawa 215a5b
shun-iwasawa 215a5b
  //  clipping x su dn
shun-iwasawa 215a5b
  int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1);
shun-iwasawa 215a5b
shun-iwasawa 215a5b
  //  inversa di aff
shun-iwasawa 215a5b
  TAffine invAff = inv(aff);
shun-iwasawa 215a5b
shun-iwasawa 215a5b
  //  nel disegnare la y-esima scanline di dn, il passaggio al pixel
shun-iwasawa 215a5b
  //  successivo comporta l'incremento (deltaXD, deltaYD) delle coordinate del
shun-iwasawa 215a5b
  //  pixel corrispondente di up
shun-iwasawa 215a5b
  double deltaXD = invAff.a11;
shun-iwasawa 215a5b
  double deltaYD = invAff.a21;
shun-iwasawa 215a5b
shun-iwasawa 215a5b
  //  deltaXD "TLonghizzato" (round)
shun-iwasawa 215a5b
  int deltaXL = tround(deltaXD * (1 << PADN));
shun-iwasawa 215a5b
shun-iwasawa 215a5b
  //  deltaYD "TLonghizzato" (round)
shun-iwasawa 215a5b
  int deltaYL = tround(deltaYD * (1 << PADN));
shun-iwasawa 215a5b
shun-iwasawa 215a5b
  //  se aff "TLonghizzata" (round) e' degenere la controimmagine di up e' un
shun-iwasawa 215a5b
  //  segmento (o un punto)
shun-iwasawa 215a5b
  if ((deltaXL == 0) && (deltaYL == 0)) return;
shun-iwasawa 215a5b
shun-iwasawa 215a5b
  //  TINT32 predecessore di up->getLx()
shun-iwasawa 215a5b
  int lxPred = up->getLx() * (1 << PADN) - 1;
shun-iwasawa 215a5b
shun-iwasawa 215a5b
  //  TINT32 predecessore di up->getLy()
shun-iwasawa 215a5b
  int lyPred = up->getLy() * (1 << PADN) - 1;
shun-iwasawa 215a5b
shun-iwasawa 215a5b
  int dnWrap = dn->getWrap();
shun-iwasawa 215a5b
  int upWrap = up->getWrap();
shun-iwasawa 215a5b
  dn->lock();
shun-iwasawa 215a5b
  up->lock();
shun-iwasawa 215a5b
shun-iwasawa 215a5b
  TPixel64 *dnRow     = dn->pixels(yMin);
shun-iwasawa 215a5b
  TPixel64 *upBasePix = up->pixels();
shun-iwasawa 215a5b
shun-iwasawa 215a5b
  //  scorre le scanline di boundingBoxD
shun-iwasawa 215a5b
  for (int y = yMin; y <= yMax; y++, dnRow += dnWrap) {
shun-iwasawa 215a5b
    //  (1)  equazione k-parametrica della y-esima scanline di boundingBoxD:
shun-iwasawa 215a5b
    //       (xMin, y) + k*(1, 0),  k = 0, ..., (xMax - xMin)
shun-iwasawa 215a5b
shun-iwasawa 215a5b
    //  (2)  equazione k-parametrica dell'immagine mediante invAff di (1):
shun-iwasawa 215a5b
    //       invAff*(xMin, y) + k*(deltaXD, deltaYD),
shun-iwasawa 215a5b
    //       k = kMin, ..., kMax con 0 <= kMin <= kMax <= (xMax - xMin)
shun-iwasawa 215a5b
shun-iwasawa 215a5b
    //  calcola kMin, kMax per la scanline corrente
shun-iwasawa 215a5b
    //  intersecando la (2) con i lati di up
shun-iwasawa 215a5b
shun-iwasawa 215a5b
    //  il segmento [a, b] di up e' la controimmagine mediante aff della
shun-iwasawa 215a5b
    //  porzione di scanline  [ (xMin, y), (xMax, y) ] di dn
shun-iwasawa 215a5b
shun-iwasawa 215a5b
    //  TPointD b = invAff*TPointD(xMax, y);
shun-iwasawa 215a5b
    TPointD a = invAff * TPointD(xMin, y);
shun-iwasawa 215a5b
shun-iwasawa 215a5b
    //  (xL0, yL0) sono le coordinate di a (inizializzate per il round)
shun-iwasawa 215a5b
    //  in versione "TLonghizzata"
shun-iwasawa 215a5b
    //  0 <= xL0 + k*deltaXL
shun-iwasawa 215a5b
    //    <  up->getLx()*(1<<PADN)
shun-iwasawa 215a5b
    //
shun-iwasawa 215a5b
    //  0 <= kMinX
shun-iwasawa 215a5b
    //    <= kMin
shun-iwasawa 215a5b
    //    <= k
shun-iwasawa 215a5b
    //    <= kMax
shun-iwasawa 215a5b
    //    <= kMaxX
shun-iwasawa 215a5b
    //    <= (xMax - xMin)
shun-iwasawa 215a5b
    //
shun-iwasawa 215a5b
    //  0 <= yL0 + k*deltaYL
shun-iwasawa 215a5b
    //    < up->getLy()*(1<<PADN)
shun-iwasawa 215a5b
shun-iwasawa 215a5b
    //  0 <= kMinY
shun-iwasawa 215a5b
    //    <= kMin
shun-iwasawa 215a5b
    //    <= k
shun-iwasawa 215a5b
    //    <= kMax
shun-iwasawa 215a5b
    //    <= kMaxY
shun-iwasawa 215a5b
    //    <= (xMax - xMin)
shun-iwasawa 215a5b
shun-iwasawa 215a5b
    //  xL0 inizializzato per il round
shun-iwasawa 215a5b
    int xL0 = tround((a.x + 0.5) * (1 << PADN));
shun-iwasawa 215a5b
shun-iwasawa 215a5b
    //  yL0 inizializzato per il round
shun-iwasawa 215a5b
    int yL0 = tround((a.y + 0.5) * (1 << PADN));
shun-iwasawa 215a5b
shun-iwasawa 215a5b
    //  calcola kMinX, kMaxX, kMinY, kMaxY
shun-iwasawa 215a5b
    int kMinX = 0, kMaxX = xMax - xMin;  //  clipping su dn
shun-iwasawa 215a5b
    int kMinY = 0, kMaxY = xMax - xMin;  //  clipping su dn
shun-iwasawa 215a5b
shun-iwasawa 215a5b
    //  0 <= xL0 + k*deltaXL
shun-iwasawa 215a5b
    //    < up->getLx()*(1<<PADN)
shun-iwasawa 215a5b
    //           <=>
shun-iwasawa 215a5b
    //  0 <= xL0 + k*deltaXL
shun-iwasawa 215a5b
    //    <= lxPred
shun-iwasawa 215a5b
    //
shun-iwasawa 215a5b
    //  0 <= yL0 + k*deltaYL
shun-iwasawa 215a5b
    //    < up->getLy()*(1<<PADN)
shun-iwasawa 215a5b
    //           <=>
shun-iwasawa 215a5b
    //  0 <= yL0 + k*deltaYL
shun-iwasawa 215a5b
    //    <= lyPred
shun-iwasawa 215a5b
shun-iwasawa 215a5b
    //  calcola kMinX, kMaxX
shun-iwasawa 215a5b
    if (deltaXL == 0) {
shun-iwasawa 215a5b
      // [a, b] verticale esterno ad up+(bordo destro/basso)
shun-iwasawa 215a5b
      if ((xL0 < 0) || (lxPred < xL0)) continue;
shun-iwasawa 215a5b
      //  altrimenti usa solo
shun-iwasawa 215a5b
      //  kMinY, kMaxY ((deltaXL != 0) || (deltaYL != 0))
shun-iwasawa 215a5b
    } else if (deltaXL > 0) {
shun-iwasawa 215a5b
      //  [a, b] esterno ad up+(bordo destro/basso)
shun-iwasawa 215a5b
      if (lxPred < xL0) continue;
shun-iwasawa 215a5b
shun-iwasawa 215a5b
      kMaxX = (lxPred - xL0) / deltaXL;  //  floor
shun-iwasawa 215a5b
      if (xL0 < 0) {
shun-iwasawa 215a5b
        kMinX = ((-xL0) + deltaXL - 1) / deltaXL;  //  ceil
shun-iwasawa 215a5b
      }
shun-iwasawa 215a5b
    } else  //  (deltaXL < 0)
shun-iwasawa 215a5b
    {
shun-iwasawa 215a5b
      //  [a, b] esterno ad up+(bordo destro/basso)
shun-iwasawa 215a5b
      if (xL0 < 0) continue;
shun-iwasawa 215a5b
shun-iwasawa 215a5b
      kMaxX = xL0 / (-deltaXL);  //  floor
shun-iwasawa 215a5b
      if (lxPred < xL0) {
shun-iwasawa 215a5b
        kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL);  //  ceil
shun-iwasawa 215a5b
      }
shun-iwasawa 215a5b
    }
shun-iwasawa 215a5b
shun-iwasawa 215a5b
    //  calcola kMinY, kMaxY
shun-iwasawa 215a5b
    if (deltaYL == 0) {
shun-iwasawa 215a5b
      //  [a, b] orizzontale esterno ad up+(bordo destro/basso)
shun-iwasawa 215a5b
      if ((yL0 < 0) || (lyPred < yL0)) continue;
shun-iwasawa 215a5b
      // altrimenti usa solo
shun-iwasawa 215a5b
      // kMinX, kMaxX ((deltaXL != 0) || (deltaYL != 0))
shun-iwasawa 215a5b
    } else if (deltaYL > 0) {
shun-iwasawa 215a5b
      //  [a, b] esterno ad up+(bordo destro/basso)
shun-iwasawa 215a5b
      if (lyPred < yL0) continue;
shun-iwasawa 215a5b
shun-iwasawa 215a5b
      kMaxY = (lyPred - yL0) / deltaYL;  //  floor
shun-iwasawa 215a5b
      if (yL0 < 0) {
shun-iwasawa 215a5b
        kMinY = ((-yL0) + deltaYL - 1) / deltaYL;  //  ceil
shun-iwasawa 215a5b
      }
shun-iwasawa 215a5b
    } else  //  (deltaYL < 0)
shun-iwasawa 215a5b
    {
shun-iwasawa 215a5b
      //  [a, b] esterno ad up+(bordo destro/basso)
shun-iwasawa 215a5b
      if (yL0 < 0) continue;
shun-iwasawa 215a5b
shun-iwasawa 215a5b
      kMaxY = yL0 / (-deltaYL);  //  floor
shun-iwasawa 215a5b
      if (lyPred < yL0) {
shun-iwasawa 215a5b
        kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL);  //  ceil
shun-iwasawa 215a5b
      }
shun-iwasawa 215a5b
    }
shun-iwasawa 215a5b
shun-iwasawa 215a5b
    //  calcola kMin, kMax effettuando anche il clippind su dn
shun-iwasawa 215a5b
    int kMin = std::max({kMinX, kMinY, (int)0});
shun-iwasawa 215a5b
    int kMax = std::min({kMaxX, kMaxY, xMax - xMin});
shun-iwasawa 215a5b
shun-iwasawa 215a5b
    TPixel64 *dnPix    = dnRow + xMin + kMin;
shun-iwasawa 215a5b
    TPixel64 *dnEndPix = dnRow + xMin + kMax + 1;
shun-iwasawa 215a5b
shun-iwasawa 215a5b
    //  (xL, yL) sono le coordinate (inizializzate per il round)
shun-iwasawa 215a5b
    //  in versione "TLonghizzata" del pixel corrente di up
shun-iwasawa 215a5b
    int xL = xL0 + (kMin - 1) * deltaXL;  //  inizializza xL
shun-iwasawa 215a5b
    int yL = yL0 + (kMin - 1) * deltaYL;  //  inizializza yL
shun-iwasawa 215a5b
shun-iwasawa 215a5b
    //  scorre i pixel sulla y-esima scanline di boundingBoxD
shun-iwasawa 215a5b
    for (; dnPix < dnEndPix; ++dnPix) {
shun-iwasawa 215a5b
      xL += deltaXL;
shun-iwasawa 215a5b
      yL += deltaYL;
shun-iwasawa 215a5b
shun-iwasawa 215a5b
      //  il punto di up TPointD(xL/(1<
shun-iwasawa 215a5b
      //  approssimato con (xI, yI)
shun-iwasawa 215a5b
      int xI = xL >> PADN;  //  round
shun-iwasawa 215a5b
      int yI = yL >> PADN;  //  round
shun-iwasawa 215a5b
shun-iwasawa 215a5b
      assert((0 <= xI) && (xI <= up->getLx() - 1) && (0 <= yI) &&
shun-iwasawa 215a5b
             (yI <= up->getLy() - 1));
shun-iwasawa 215a5b
shun-iwasawa 215a5b
      TPixel64 upPix = *(upBasePix + (yI * upWrap + xI));
shun-iwasawa 215a5b
shun-iwasawa 215a5b
      if (firstColumn) upPix.m = 65535;
shun-iwasawa 215a5b
      if (upPix.m == 0) continue;
shun-iwasawa 215a5b
shun-iwasawa 215a5b
      if (upPix.m == 65535)
shun-iwasawa 215a5b
        *dnPix = upPix;
shun-iwasawa 215a5b
      else if (doPremultiply)
shun-iwasawa 215a5b
        *dnPix = quickOverPixPremult(*dnPix, upPix);
shun-iwasawa 215a5b
      else
shun-iwasawa 215a5b
        *dnPix = quickOverPix(*dnPix, upPix);
shun-iwasawa 215a5b
    }
shun-iwasawa 215a5b
  }
shun-iwasawa 215a5b
  dn->unlock();
shun-iwasawa 215a5b
  up->unlock();
shun-iwasawa 215a5b
}
shun-iwasawa 481b59
shun-iwasawa 481b59
//=============================================================================
shun-iwasawa 481b59
shun-iwasawa 481b59
void doQuickPutNoFilter(const TRaster64P &dn, const TRasterFP &up,
shun-iwasawa 481b59
                        const TAffine &aff, bool doPremultiply,
shun-iwasawa 481b59
                        bool firstColumn) {
shun-iwasawa 481b59
  //  se aff := TAffine(sx, 0, tx, 0, sy, ty) e' degenere la controimmagine
shun-iwasawa 481b59
  //  di up e' un segmento (o un punto)
shun-iwasawa 481b59
  if ((aff.a11 * aff.a22 - aff.a12 * aff.a21) == 0) return;
shun-iwasawa 481b59
shun-iwasawa 481b59
  //  contatore bit di shift
shun-iwasawa 481b59
  const int PADN = 16;
shun-iwasawa 481b59
shun-iwasawa 481b59
  //  max dimensioni di up gestibili (limite imposto dal numero di bit
shun-iwasawa 481b59
  //  disponibili per la parte intera di xL, yL)
shun-iwasawa 481b59
  assert(std::max(up->getLx(), up->getLy()) <
shun-iwasawa 481b59
         (1 << (8 * sizeof(int) - PADN - 1)));
shun-iwasawa 481b59
shun-iwasawa 481b59
  TRectD boundingBoxD =
shun-iwasawa 481b59
      TRectD(convert(dn->getBounds())) *
shun-iwasawa 481b59
      (aff * TRectD(-0.5, -0.5, up->getLx() - 0.5, up->getLy() - 0.5));
shun-iwasawa 481b59
shun-iwasawa 481b59
  //  clipping
shun-iwasawa 481b59
  if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1)
shun-iwasawa 481b59
    return;
shun-iwasawa 481b59
shun-iwasawa 481b59
  //  clipping y su dn
shun-iwasawa 481b59
  int yMin = std::max(tfloor(boundingBoxD.y0), 0);
shun-iwasawa 481b59
shun-iwasawa 481b59
  //  clipping y su dn
shun-iwasawa 481b59
  int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1);
shun-iwasawa 481b59
shun-iwasawa 481b59
  //  clipping x su dn
shun-iwasawa 481b59
  int xMin = std::max(tfloor(boundingBoxD.x0), 0);
shun-iwasawa 481b59
shun-iwasawa 481b59
  //  clipping x su dn
shun-iwasawa 481b59
  int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1);
shun-iwasawa 481b59
shun-iwasawa 481b59
  //  inversa di aff
shun-iwasawa 481b59
  TAffine invAff = inv(aff);
shun-iwasawa 481b59
shun-iwasawa 481b59
  //  nel disegnare la y-esima scanline di dn, il passaggio al pixel
shun-iwasawa 481b59
  //  successivo comporta l'incremento (deltaXD, deltaYD) delle coordinate del
shun-iwasawa 481b59
  //  pixel corrispondente di up
shun-iwasawa 481b59
  double deltaXD = invAff.a11;
shun-iwasawa 481b59
  double deltaYD = invAff.a21;
shun-iwasawa 481b59
shun-iwasawa 481b59
  //  deltaXD "TLonghizzato" (round)
shun-iwasawa 481b59
  int deltaXL = tround(deltaXD * (1 << PADN));
shun-iwasawa 481b59
shun-iwasawa 481b59
  //  deltaYD "TLonghizzato" (round)
shun-iwasawa 481b59
  int deltaYL = tround(deltaYD * (1 << PADN));
shun-iwasawa 481b59
shun-iwasawa 481b59
  //  se aff "TLonghizzata" (round) e' degenere la controimmagine di up e' un
shun-iwasawa 481b59
  //  segmento (o un punto)
shun-iwasawa 481b59
  if ((deltaXL == 0) && (deltaYL == 0)) return;
shun-iwasawa 481b59
shun-iwasawa 481b59
  //  TINT32 predecessore di up->getLx()
shun-iwasawa 481b59
  int lxPred = up->getLx() * (1 << PADN) - 1;
shun-iwasawa 481b59
shun-iwasawa 481b59
  //  TINT32 predecessore di up->getLy()
shun-iwasawa 481b59
  int lyPred = up->getLy() * (1 << PADN) - 1;
shun-iwasawa 481b59
shun-iwasawa 481b59
  int dnWrap = dn->getWrap();
shun-iwasawa 481b59
  int upWrap = up->getWrap();
shun-iwasawa 481b59
  dn->lock();
shun-iwasawa 481b59
  up->lock();
shun-iwasawa 481b59
shun-iwasawa 481b59
  TPixel64 *dnRow    = dn->pixels(yMin);
shun-iwasawa 481b59
  TPixelF *upBasePix = up->pixels();
shun-iwasawa 481b59
shun-iwasawa 481b59
  //  scorre le scanline di boundingBoxD
shun-iwasawa 481b59
  for (int y = yMin; y <= yMax; y++, dnRow += dnWrap) {
shun-iwasawa 481b59
    //  (1)  equazione k-parametrica della y-esima scanline di boundingBoxD:
shun-iwasawa 481b59
    //       (xMin, y) + k*(1, 0),  k = 0, ..., (xMax - xMin)
shun-iwasawa 481b59
shun-iwasawa 481b59
    //  (2)  equazione k-parametrica dell'immagine mediante invAff di (1):
shun-iwasawa 481b59
    //       invAff*(xMin, y) + k*(deltaXD, deltaYD),
shun-iwasawa 481b59
    //       k = kMin, ..., kMax con 0 <= kMin <= kMax <= (xMax - xMin)
shun-iwasawa 481b59
shun-iwasawa 481b59
    //  calcola kMin, kMax per la scanline corrente
shun-iwasawa 481b59
    //  intersecando la (2) con i lati di up
shun-iwasawa 481b59
shun-iwasawa 481b59
    //  il segmento [a, b] di up e' la controimmagine mediante aff della
shun-iwasawa 481b59
    //  porzione di scanline  [ (xMin, y), (xMax, y) ] di dn
shun-iwasawa 481b59
shun-iwasawa 481b59
    //  TPointD b = invAff*TPointD(xMax, y);
shun-iwasawa 481b59
    TPointD a = invAff * TPointD(xMin, y);
shun-iwasawa 481b59
shun-iwasawa 481b59
    //  (xL0, yL0) sono le coordinate di a (inizializzate per il round)
shun-iwasawa 481b59
    //  in versione "TLonghizzata"
shun-iwasawa 481b59
    //  0 <= xL0 + k*deltaXL
shun-iwasawa 481b59
    //    <  up->getLx()*(1<<PADN)
shun-iwasawa 481b59
    //
shun-iwasawa 481b59
    //  0 <= kMinX
shun-iwasawa 481b59
    //    <= kMin
shun-iwasawa 481b59
    //    <= k
shun-iwasawa 481b59
    //    <= kMax
shun-iwasawa 481b59
    //    <= kMaxX
shun-iwasawa 481b59
    //    <= (xMax - xMin)
shun-iwasawa 481b59
    //
shun-iwasawa 481b59
    //  0 <= yL0 + k*deltaYL
shun-iwasawa 481b59
    //    < up->getLy()*(1<<PADN)
shun-iwasawa 481b59
shun-iwasawa 481b59
    //  0 <= kMinY
shun-iwasawa 481b59
    //    <= kMin
shun-iwasawa 481b59
    //    <= k
shun-iwasawa 481b59
    //    <= kMax
shun-iwasawa 481b59
    //    <= kMaxY
shun-iwasawa 481b59
    //    <= (xMax - xMin)
shun-iwasawa 481b59
shun-iwasawa 481b59
    //  xL0 inizializzato per il round
shun-iwasawa 481b59
    int xL0 = tround((a.x + 0.5) * (1 << PADN));
shun-iwasawa 481b59
shun-iwasawa 481b59
    //  yL0 inizializzato per il round
shun-iwasawa 481b59
    int yL0 = tround((a.y + 0.5) * (1 << PADN));
shun-iwasawa 481b59
shun-iwasawa 481b59
    //  calcola kMinX, kMaxX, kMinY, kMaxY
shun-iwasawa 481b59
    int kMinX = 0, kMaxX = xMax - xMin;  //  clipping su dn
shun-iwasawa 481b59
    int kMinY = 0, kMaxY = xMax - xMin;  //  clipping su dn
shun-iwasawa 481b59
shun-iwasawa 481b59
    //  0 <= xL0 + k*deltaXL
shun-iwasawa 481b59
    //    < up->getLx()*(1<<PADN)
shun-iwasawa 481b59
    //           <=>
shun-iwasawa 481b59
    //  0 <= xL0 + k*deltaXL
shun-iwasawa 481b59
    //    <= lxPred
shun-iwasawa 481b59
    //
shun-iwasawa 481b59
    //  0 <= yL0 + k*deltaYL
shun-iwasawa 481b59
    //    < up->getLy()*(1<<PADN)
shun-iwasawa 481b59
    //           <=>
shun-iwasawa 481b59
    //  0 <= yL0 + k*deltaYL
shun-iwasawa 481b59
    //    <= lyPred
shun-iwasawa 481b59
shun-iwasawa 481b59
    //  calcola kMinX, kMaxX
shun-iwasawa 481b59
    if (deltaXL == 0) {
shun-iwasawa 481b59
      // [a, b] verticale esterno ad up+(bordo destro/basso)
shun-iwasawa 481b59
      if ((xL0 < 0) || (lxPred < xL0)) continue;
shun-iwasawa 481b59
      //  altrimenti usa solo
shun-iwasawa 481b59
      //  kMinY, kMaxY ((deltaXL != 0) || (deltaYL != 0))
shun-iwasawa 481b59
    } else if (deltaXL > 0) {
shun-iwasawa 481b59
      //  [a, b] esterno ad up+(bordo destro/basso)
shun-iwasawa 481b59
      if (lxPred < xL0) continue;
shun-iwasawa 481b59
shun-iwasawa 481b59
      kMaxX = (lxPred - xL0) / deltaXL;  //  floor
shun-iwasawa 481b59
      if (xL0 < 0) {
shun-iwasawa 481b59
        kMinX = ((-xL0) + deltaXL - 1) / deltaXL;  //  ceil
shun-iwasawa 481b59
      }
shun-iwasawa 481b59
    } else  //  (deltaXL < 0)
shun-iwasawa 481b59
    {
shun-iwasawa 481b59
      //  [a, b] esterno ad up+(bordo destro/basso)
shun-iwasawa 481b59
      if (xL0 < 0) continue;
shun-iwasawa 481b59
shun-iwasawa 481b59
      kMaxX = xL0 / (-deltaXL);  //  floor
shun-iwasawa 481b59
      if (lxPred < xL0) {
shun-iwasawa 481b59
        kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL);  //  ceil
shun-iwasawa 481b59
      }
shun-iwasawa 481b59
    }
shun-iwasawa 481b59
shun-iwasawa 481b59
    //  calcola kMinY, kMaxY
shun-iwasawa 481b59
    if (deltaYL == 0) {
shun-iwasawa 481b59
      //  [a, b] orizzontale esterno ad up+(bordo destro/basso)
shun-iwasawa 481b59
      if ((yL0 < 0) || (lyPred < yL0)) continue;
shun-iwasawa 481b59
      // altrimenti usa solo
shun-iwasawa 481b59
      // kMinX, kMaxX ((deltaXL != 0) || (deltaYL != 0))
shun-iwasawa 481b59
    } else if (deltaYL > 0) {
shun-iwasawa 481b59
      //  [a, b] esterno ad up+(bordo destro/basso)
shun-iwasawa 481b59
      if (lyPred < yL0) continue;
shun-iwasawa 481b59
shun-iwasawa 481b59
      kMaxY = (lyPred - yL0) / deltaYL;  //  floor
shun-iwasawa 481b59
      if (yL0 < 0) {
shun-iwasawa 481b59
        kMinY = ((-yL0) + deltaYL - 1) / deltaYL;  //  ceil
shun-iwasawa 481b59
      }
shun-iwasawa 481b59
    } else  //  (deltaYL < 0)
shun-iwasawa 481b59
    {
shun-iwasawa 481b59
      //  [a, b] esterno ad up+(bordo destro/basso)
shun-iwasawa 481b59
      if (yL0 < 0) continue;
shun-iwasawa 481b59
shun-iwasawa 481b59
      kMaxY = yL0 / (-deltaYL);  //  floor
shun-iwasawa 481b59
      if (lyPred < yL0) {
shun-iwasawa 481b59
        kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL);  //  ceil
shun-iwasawa 481b59
      }
shun-iwasawa 481b59
    }
shun-iwasawa 481b59
shun-iwasawa 481b59
    //  calcola kMin, kMax effettuando anche il clippind su dn
shun-iwasawa 481b59
    int kMin = std::max({kMinX, kMinY, (int)0});
shun-iwasawa 481b59
    int kMax = std::min({kMaxX, kMaxY, xMax - xMin});
shun-iwasawa 481b59
shun-iwasawa 481b59
    TPixel64 *dnPix    = dnRow + xMin + kMin;
shun-iwasawa 481b59
    TPixel64 *dnEndPix = dnRow + xMin + kMax + 1;
shun-iwasawa 481b59
shun-iwasawa 481b59
    //  (xL, yL) sono le coordinate (inizializzate per il round)
shun-iwasawa 481b59
    //  in versione "TLonghizzata" del pixel corrente di up
shun-iwasawa 481b59
    int xL = xL0 + (kMin - 1) * deltaXL;  //  inizializza xL
shun-iwasawa 481b59
    int yL = yL0 + (kMin - 1) * deltaYL;  //  inizializza yL
shun-iwasawa 481b59
shun-iwasawa 481b59
    //  scorre i pixel sulla y-esima scanline di boundingBoxD
shun-iwasawa 481b59
    for (; dnPix < dnEndPix; ++dnPix) {
shun-iwasawa 481b59
      xL += deltaXL;
shun-iwasawa 481b59
      yL += deltaYL;
shun-iwasawa 481b59
shun-iwasawa 481b59
      //  il punto di up TPointD(xL/(1<
shun-iwasawa 481b59
      //  approssimato con (xI, yI)
shun-iwasawa 481b59
      int xI = xL >> PADN;  //  round
shun-iwasawa 481b59
      int yI = yL >> PADN;  //  round
shun-iwasawa 481b59
shun-iwasawa 481b59
      assert((0 <= xI) && (xI <= up->getLx() - 1) && (0 <= yI) &&
shun-iwasawa 481b59
             (yI <= up->getLy() - 1));
shun-iwasawa 481b59
shun-iwasawa 481b59
      TPixelF upPix = *(upBasePix + (yI * upWrap + xI));
shun-iwasawa 481b59
shun-iwasawa 481b59
      if (firstColumn) upPix.m = 1.0;
shun-iwasawa 481b59
      if (upPix.m <= 0.0) continue;
shun-iwasawa 481b59
shun-iwasawa 481b59
      TPixel64 upPix64 = toPixel64(upPix);
shun-iwasawa 481b59
      if (upPix.m >= 1.f)
shun-iwasawa 481b59
        *dnPix = upPix64;
shun-iwasawa 481b59
      else if (doPremultiply)
shun-iwasawa 481b59
        *dnPix = quickOverPixPremult(*dnPix, upPix64);
shun-iwasawa 481b59
      else
shun-iwasawa 481b59
        *dnPix = quickOverPix(*dnPix, upPix64);
shun-iwasawa 481b59
    }
shun-iwasawa 481b59
  }
shun-iwasawa 481b59
  dn->unlock();
shun-iwasawa 481b59
  up->unlock();
shun-iwasawa 481b59
}
shun-iwasawa 481b59
shun-iwasawa 481b59
//=============================================================================
shun-iwasawa 481b59
shun-iwasawa 481b59
void doQuickPutNoFilter(const TRasterFP &dn, const TRasterFP &up,
shun-iwasawa 481b59
                        const TAffine &aff, bool doPremultiply,
shun-iwasawa 481b59
                        bool firstColumn) {
shun-iwasawa 481b59
  //  se aff := TAffine(sx, 0, tx, 0, sy, ty) e' degenere la controimmagine
shun-iwasawa 481b59
  //  di up e' un segmento (o un punto)
shun-iwasawa 481b59
  if ((aff.a11 * aff.a22 - aff.a12 * aff.a21) == 0) return;
shun-iwasawa 481b59
shun-iwasawa 481b59
  //  contatore bit di shift
shun-iwasawa 481b59
  const int PADN = 16;
shun-iwasawa 481b59
shun-iwasawa 481b59
  //  max dimensioni di up gestibili (limite imposto dal numero di bit
shun-iwasawa 481b59
  //  disponibili per la parte intera di xL, yL)
shun-iwasawa 481b59
  assert(std::max(up->getLx(), up->getLy()) <
shun-iwasawa 481b59
         (1 << (8 * sizeof(int) - PADN - 1)));
shun-iwasawa 481b59
shun-iwasawa 481b59
  TRectD boundingBoxD =
shun-iwasawa 481b59
      TRectD(convert(dn->getBounds())) *
shun-iwasawa 481b59
      (aff * TRectD(-0.5, -0.5, up->getLx() - 0.5, up->getLy() - 0.5));
shun-iwasawa 481b59
shun-iwasawa 481b59
  //  clipping
shun-iwasawa 481b59
  if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1)
shun-iwasawa 481b59
    return;
shun-iwasawa 481b59
shun-iwasawa 481b59
  //  clipping y su dn
shun-iwasawa 481b59
  int yMin = std::max(tfloor(boundingBoxD.y0), 0);
shun-iwasawa 481b59
shun-iwasawa 481b59
  //  clipping y su dn
shun-iwasawa 481b59
  int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1);
shun-iwasawa 481b59
shun-iwasawa 481b59
  //  clipping x su dn
shun-iwasawa 481b59
  int xMin = std::max(tfloor(boundingBoxD.x0), 0);
shun-iwasawa 481b59
shun-iwasawa 481b59
  //  clipping x su dn
shun-iwasawa 481b59
  int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1);
shun-iwasawa 481b59
shun-iwasawa 481b59
  //  inversa di aff
shun-iwasawa 481b59
  TAffine invAff = inv(aff);
shun-iwasawa 481b59
shun-iwasawa 481b59
  //  nel disegnare la y-esima scanline di dn, il passaggio al pixel
shun-iwasawa 481b59
  //  successivo comporta l'incremento (deltaXD, deltaYD) delle coordinate del
shun-iwasawa 481b59
  //  pixel corrispondente di up
shun-iwasawa 481b59
  double deltaXD = invAff.a11;
shun-iwasawa 481b59
  double deltaYD = invAff.a21;
shun-iwasawa 481b59
shun-iwasawa 481b59
  //  deltaXD "TLonghizzato" (round)
shun-iwasawa 481b59
  int deltaXL = tround(deltaXD * (1 << PADN));
shun-iwasawa 481b59
shun-iwasawa 481b59
  //  deltaYD "TLonghizzato" (round)
shun-iwasawa 481b59
  int deltaYL = tround(deltaYD * (1 << PADN));
shun-iwasawa 481b59
shun-iwasawa 481b59
  //  se aff "TLonghizzata" (round) e' degenere la controimmagine di up e' un
shun-iwasawa 481b59
  //  segmento (o un punto)
shun-iwasawa 481b59
  if ((deltaXL == 0) && (deltaYL == 0)) return;
shun-iwasawa 481b59
shun-iwasawa 481b59
  //  TINT32 predecessore di up->getLx()
shun-iwasawa 481b59
  int lxPred = up->getLx() * (1 << PADN) - 1;
shun-iwasawa 481b59
shun-iwasawa 481b59
  //  TINT32 predecessore di up->getLy()
shun-iwasawa 481b59
  int lyPred = up->getLy() * (1 << PADN) - 1;
shun-iwasawa 481b59
shun-iwasawa 481b59
  int dnWrap = dn->getWrap();
shun-iwasawa 481b59
  int upWrap = up->getWrap();
shun-iwasawa 481b59
  dn->lock();
shun-iwasawa 481b59
  up->lock();
shun-iwasawa 481b59
shun-iwasawa 481b59
  TPixelF *dnRow     = dn->pixels(yMin);
shun-iwasawa 481b59
  TPixelF *upBasePix = up->pixels();
shun-iwasawa 481b59
shun-iwasawa 481b59
  //  scorre le scanline di boundingBoxD
shun-iwasawa 481b59
  for (int y = yMin; y <= yMax; y++, dnRow += dnWrap) {
shun-iwasawa 481b59
    //  (1)  equazione k-parametrica della y-esima scanline di boundingBoxD:
shun-iwasawa 481b59
    //       (xMin, y) + k*(1, 0),  k = 0, ..., (xMax - xMin)
shun-iwasawa 481b59
shun-iwasawa 481b59
    //  (2)  equazione k-parametrica dell'immagine mediante invAff di (1):
shun-iwasawa 481b59
    //       invAff*(xMin, y) + k*(deltaXD, deltaYD),
shun-iwasawa 481b59
    //       k = kMin, ..., kMax con 0 <= kMin <= kMax <= (xMax - xMin)
shun-iwasawa 481b59
shun-iwasawa 481b59
    //  calcola kMin, kMax per la scanline corrente
shun-iwasawa 481b59
    //  intersecando la (2) con i lati di up
shun-iwasawa 481b59
shun-iwasawa 481b59
    //  il segmento [a, b] di up e' la controimmagine mediante aff della
shun-iwasawa 481b59
    //  porzione di scanline  [ (xMin, y), (xMax, y) ] di dn
shun-iwasawa 481b59
shun-iwasawa 481b59
    //  TPointD b = invAff*TPointD(xMax, y);
shun-iwasawa 481b59
    TPointD a = invAff * TPointD(xMin, y);
shun-iwasawa 481b59
shun-iwasawa 481b59
    //  (xL0, yL0) sono le coordinate di a (inizializzate per il round)
shun-iwasawa 481b59
    //  in versione "TLonghizzata"
shun-iwasawa 481b59
    //  0 <= xL0 + k*deltaXL
shun-iwasawa 481b59
    //    <  up->getLx()*(1<<PADN)
shun-iwasawa 481b59
    //
shun-iwasawa 481b59
    //  0 <= kMinX
shun-iwasawa 481b59
    //    <= kMin
shun-iwasawa 481b59
    //    <= k
shun-iwasawa 481b59
    //    <= kMax
shun-iwasawa 481b59
    //    <= kMaxX
shun-iwasawa 481b59
    //    <= (xMax - xMin)
shun-iwasawa 481b59
    //
shun-iwasawa 481b59
    //  0 <= yL0 + k*deltaYL
shun-iwasawa 481b59
    //    < up->getLy()*(1<<PADN)
shun-iwasawa 481b59
shun-iwasawa 481b59
    //  0 <= kMinY
shun-iwasawa 481b59
    //    <= kMin
shun-iwasawa 481b59
    //    <= k
shun-iwasawa 481b59
    //    <= kMax
shun-iwasawa 481b59
    //    <= kMaxY
shun-iwasawa 481b59
    //    <= (xMax - xMin)
shun-iwasawa 481b59
shun-iwasawa 481b59
    //  xL0 inizializzato per il round
shun-iwasawa 481b59
    int xL0 = tround((a.x + 0.5) * (1 << PADN));
shun-iwasawa 481b59
shun-iwasawa 481b59
    //  yL0 inizializzato per il round
shun-iwasawa 481b59
    int yL0 = tround((a.y + 0.5) * (1 << PADN));
shun-iwasawa 481b59
shun-iwasawa 481b59
    //  calcola kMinX, kMaxX, kMinY, kMaxY
shun-iwasawa 481b59
    int kMinX = 0, kMaxX = xMax - xMin;  //  clipping su dn
shun-iwasawa 481b59
    int kMinY = 0, kMaxY = xMax - xMin;  //  clipping su dn
shun-iwasawa 481b59
shun-iwasawa 481b59
    //  0 <= xL0 + k*deltaXL
shun-iwasawa 481b59
    //    < up->getLx()*(1<<PADN)
shun-iwasawa 481b59
    //           <=>
shun-iwasawa 481b59
    //  0 <= xL0 + k*deltaXL
shun-iwasawa 481b59
    //    <= lxPred
shun-iwasawa 481b59
    //
shun-iwasawa 481b59
    //  0 <= yL0 + k*deltaYL
shun-iwasawa 481b59
    //    < up->getLy()*(1<<PADN)
shun-iwasawa 481b59
    //           <=>
shun-iwasawa 481b59
    //  0 <= yL0 + k*deltaYL
shun-iwasawa 481b59
    //    <= lyPred
shun-iwasawa 481b59
shun-iwasawa 481b59
    //  calcola kMinX, kMaxX
shun-iwasawa 481b59
    if (deltaXL == 0) {
shun-iwasawa 481b59
      // [a, b] verticale esterno ad up+(bordo destro/basso)
shun-iwasawa 481b59
      if ((xL0 < 0) || (lxPred < xL0)) continue;
shun-iwasawa 481b59
      //  altrimenti usa solo
shun-iwasawa 481b59
      //  kMinY, kMaxY ((deltaXL != 0) || (deltaYL != 0))
shun-iwasawa 481b59
    } else if (deltaXL > 0) {
shun-iwasawa 481b59
      //  [a, b] esterno ad up+(bordo destro/basso)
shun-iwasawa 481b59
      if (lxPred < xL0) continue;
shun-iwasawa 481b59
shun-iwasawa 481b59
      kMaxX = (lxPred - xL0) / deltaXL;  //  floor
shun-iwasawa 481b59
      if (xL0 < 0) {
shun-iwasawa 481b59
        kMinX = ((-xL0) + deltaXL - 1) / deltaXL;  //  ceil
shun-iwasawa 481b59
      }
shun-iwasawa 481b59
    } else  //  (deltaXL < 0)
shun-iwasawa 481b59
    {
shun-iwasawa 481b59
      //  [a, b] esterno ad up+(bordo destro/basso)
shun-iwasawa 481b59
      if (xL0 < 0) continue;
shun-iwasawa 481b59
shun-iwasawa 481b59
      kMaxX = xL0 / (-deltaXL);  //  floor
shun-iwasawa 481b59
      if (lxPred < xL0) {
shun-iwasawa 481b59
        kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL);  //  ceil
shun-iwasawa 481b59
      }
shun-iwasawa 481b59
    }
shun-iwasawa 481b59
shun-iwasawa 481b59
    //  calcola kMinY, kMaxY
shun-iwasawa 481b59
    if (deltaYL == 0) {
shun-iwasawa 481b59
      //  [a, b] orizzontale esterno ad up+(bordo destro/basso)
shun-iwasawa 481b59
      if ((yL0 < 0) || (lyPred < yL0)) continue;
shun-iwasawa 481b59
      // altrimenti usa solo
shun-iwasawa 481b59
      // kMinX, kMaxX ((deltaXL != 0) || (deltaYL != 0))
shun-iwasawa 481b59
    } else if (deltaYL > 0) {
shun-iwasawa 481b59
      //  [a, b] esterno ad up+(bordo destro/basso)
shun-iwasawa 481b59
      if (lyPred < yL0) continue;
shun-iwasawa 481b59
shun-iwasawa 481b59
      kMaxY = (lyPred - yL0) / deltaYL;  //  floor
shun-iwasawa 481b59
      if (yL0 < 0) {
shun-iwasawa 481b59
        kMinY = ((-yL0) + deltaYL - 1) / deltaYL;  //  ceil
shun-iwasawa 481b59
      }
shun-iwasawa 481b59
    } else  //  (deltaYL < 0)
shun-iwasawa 481b59
    {
shun-iwasawa 481b59
      //  [a, b] esterno ad up+(bordo destro/basso)
shun-iwasawa 481b59
      if (yL0 < 0) continue;
shun-iwasawa 481b59
shun-iwasawa 481b59
      kMaxY = yL0 / (-deltaYL);  //  floor
shun-iwasawa 481b59
      if (lyPred < yL0) {
shun-iwasawa 481b59
        kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL);  //  ceil
shun-iwasawa 481b59
      }
shun-iwasawa 481b59
    }
shun-iwasawa 481b59
shun-iwasawa 481b59
    //  calcola kMin, kMax effettuando anche il clippind su dn
shun-iwasawa 481b59
    int kMin = std::max({kMinX, kMinY, (int)0});
shun-iwasawa 481b59
    int kMax = std::min({kMaxX, kMaxY, xMax - xMin});
shun-iwasawa 481b59
shun-iwasawa 481b59
    TPixelF *dnPix    = dnRow + xMin + kMin;
shun-iwasawa 481b59
    TPixelF *dnEndPix = dnRow + xMin + kMax + 1;
shun-iwasawa 481b59
shun-iwasawa 481b59
    //  (xL, yL) sono le coordinate (inizializzate per il round)
shun-iwasawa 481b59
    //  in versione "TLonghizzata" del pixel corrente di up
shun-iwasawa 481b59
    int xL = xL0 + (kMin - 1) * deltaXL;  //  inizializza xL
shun-iwasawa 481b59
    int yL = yL0 + (kMin - 1) * deltaYL;  //  inizializza yL
shun-iwasawa 481b59
shun-iwasawa 481b59
    //  scorre i pixel sulla y-esima scanline di boundingBoxD
shun-iwasawa 481b59
    for (; dnPix < dnEndPix; ++dnPix) {
shun-iwasawa 481b59
      xL += deltaXL;
shun-iwasawa 481b59
      yL += deltaYL;
shun-iwasawa 481b59
shun-iwasawa 481b59
      //  il punto di up TPointD(xL/(1<
shun-iwasawa 481b59
      //  approssimato con (xI, yI)
shun-iwasawa 481b59
      int xI = xL >> PADN;  //  round
shun-iwasawa 481b59
      int yI = yL >> PADN;  //  round
shun-iwasawa 481b59
shun-iwasawa 481b59
      assert((0 <= xI) && (xI <= up->getLx() - 1) && (0 <= yI) &&
shun-iwasawa 481b59
             (yI <= up->getLy() - 1));
shun-iwasawa 481b59
shun-iwasawa 481b59
      TPixelF upPix = *(upBasePix + (yI * upWrap + xI));
shun-iwasawa 481b59
shun-iwasawa 481b59
      if (firstColumn) upPix.m = 1.0;
shun-iwasawa 481b59
      if (upPix.m <= 0.0) continue;
shun-iwasawa 481b59
shun-iwasawa 481b59
      if (upPix.m >= 1.f)
shun-iwasawa 481b59
        *dnPix = upPix;
shun-iwasawa 481b59
      else if (doPremultiply)
shun-iwasawa 481b59
        *dnPix = quickOverPixPremult(*dnPix, upPix);
shun-iwasawa 481b59
      else
shun-iwasawa 481b59
        *dnPix = quickOverPix(*dnPix, upPix);
shun-iwasawa 481b59
    }
shun-iwasawa 481b59
  }
shun-iwasawa 481b59
  dn->unlock();
shun-iwasawa 481b59
  up->unlock();
shun-iwasawa 481b59
}
shun-iwasawa 481b59
shun-iwasawa 215a5b
//=============================================================================
shun-iwasawa 215a5b
shun-iwasawa 215a5b
void doQuickPutNoFilter(const TRaster64P &dn, const TRaster32P &up,
shun-iwasawa 215a5b
                        const TAffine &aff, bool doPremultiply,
shun-iwasawa 215a5b
                        bool firstColumn) {
shun-iwasawa 215a5b
  //  se aff := TAffine(sx, 0, tx, 0, sy, ty) e' degenere la controimmagine
shun-iwasawa 215a5b
  //  di up e' un segmento (o un punto)
shun-iwasawa 215a5b
  if ((aff.a11 * aff.a22 - aff.a12 * aff.a21) == 0) return;
shun-iwasawa 215a5b
shun-iwasawa 215a5b
  //  contatore bit di shift
shun-iwasawa 215a5b
  const int PADN = 16;
shun-iwasawa 215a5b
shun-iwasawa 215a5b
  //  max dimensioni di up gestibili (limite imposto dal numero di bit
shun-iwasawa 215a5b
  //  disponibili per la parte intera di xL, yL)
shun-iwasawa 215a5b
  assert(std::max(up->getLx(), up->getLy()) <
shun-iwasawa 215a5b
         (1 << (8 * sizeof(int) - PADN - 1)));
shun-iwasawa 215a5b
shun-iwasawa 215a5b
  TRectD boundingBoxD =
shun-iwasawa 215a5b
      TRectD(convert(dn->getBounds())) *
shun-iwasawa 215a5b
      (aff * TRectD(-0.5, -0.5, up->getLx() - 0.5, up->getLy() - 0.5));
shun-iwasawa 215a5b
shun-iwasawa 215a5b
  //  clipping
shun-iwasawa 215a5b
  if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1)
shun-iwasawa 215a5b
    return;
shun-iwasawa 215a5b
shun-iwasawa 215a5b
  //  clipping y su dn
shun-iwasawa 215a5b
  int yMin = std::max(tfloor(boundingBoxD.y0), 0);
shun-iwasawa 215a5b
shun-iwasawa 215a5b
  //  clipping y su dn
shun-iwasawa 215a5b
  int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1);
shun-iwasawa 215a5b
shun-iwasawa 215a5b
  //  clipping x su dn
shun-iwasawa 215a5b
  int xMin = std::max(tfloor(boundingBoxD.x0), 0);
shun-iwasawa 215a5b
shun-iwasawa 215a5b
  //  clipping x su dn
shun-iwasawa 215a5b
  int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1);
shun-iwasawa 215a5b
shun-iwasawa 215a5b
  //  inversa di aff
shun-iwasawa 215a5b
  TAffine invAff = inv(aff);
shun-iwasawa 215a5b
shun-iwasawa 215a5b
  //  nel disegnare la y-esima scanline di dn, il passaggio al pixel
shun-iwasawa 215a5b
  //  successivo comporta l'incremento (deltaXD, deltaYD) delle coordinate del
shun-iwasawa 215a5b
  //  pixel corrispondente di up
shun-iwasawa 215a5b
  double deltaXD = invAff.a11;
shun-iwasawa 215a5b
  double deltaYD = invAff.a21;
shun-iwasawa 215a5b
shun-iwasawa 215a5b
  //  deltaXD "TLonghizzato" (round)
shun-iwasawa 215a5b
  int deltaXL = tround(deltaXD * (1 << PADN));
shun-iwasawa 215a5b
shun-iwasawa 215a5b
  //  deltaYD "TLonghizzato" (round)
shun-iwasawa 215a5b
  int deltaYL = tround(deltaYD * (1 << PADN));
shun-iwasawa 215a5b
shun-iwasawa 215a5b
  //  se aff "TLonghizzata" (round) e' degenere la controimmagine di up e' un
shun-iwasawa 215a5b
  //  segmento (o un punto)
shun-iwasawa 215a5b
  if ((deltaXL == 0) && (deltaYL == 0)) return;
shun-iwasawa 215a5b
shun-iwasawa 215a5b
  //  TINT32 predecessore di up->getLx()
shun-iwasawa 215a5b
  int lxPred = up->getLx() * (1 << PADN) - 1;
shun-iwasawa 215a5b
shun-iwasawa 215a5b
  //  TINT32 predecessore di up->getLy()
shun-iwasawa 215a5b
  int lyPred = up->getLy() * (1 << PADN) - 1;
shun-iwasawa 215a5b
shun-iwasawa 215a5b
  int dnWrap = dn->getWrap();
shun-iwasawa 215a5b
  int upWrap = up->getWrap();
shun-iwasawa 215a5b
  dn->lock();
shun-iwasawa 215a5b
  up->lock();
shun-iwasawa 215a5b
shun-iwasawa 215a5b
  TPixel64 *dnRow     = dn->pixels(yMin);
shun-iwasawa 215a5b
  TPixel32 *upBasePix = up->pixels();
shun-iwasawa 215a5b
shun-iwasawa 215a5b
  //  scorre le scanline di boundingBoxD
shun-iwasawa 215a5b
  for (int y = yMin; y <= yMax; y++, dnRow += dnWrap) {
shun-iwasawa 215a5b
    //  (1)  equazione k-parametrica della y-esima scanline di boundingBoxD:
shun-iwasawa 215a5b
    //       (xMin, y) + k*(1, 0),  k = 0, ..., (xMax - xMin)
shun-iwasawa 215a5b
shun-iwasawa 215a5b
    //  (2)  equazione k-parametrica dell'immagine mediante invAff di (1):
shun-iwasawa 215a5b
    //       invAff*(xMin, y) + k*(deltaXD, deltaYD),
shun-iwasawa 215a5b
    //       k = kMin, ..., kMax con 0 <= kMin <= kMax <= (xMax - xMin)
shun-iwasawa 215a5b
shun-iwasawa 215a5b
    //  calcola kMin, kMax per la scanline corrente
shun-iwasawa 215a5b
    //  intersecando la (2) con i lati di up
shun-iwasawa 215a5b
shun-iwasawa 215a5b
    //  il segmento [a, b] di up e' la controimmagine mediante aff della
shun-iwasawa 215a5b
    //  porzione di scanline  [ (xMin, y), (xMax, y) ] di dn
shun-iwasawa 215a5b
shun-iwasawa 215a5b
    //  TPointD b = invAff*TPointD(xMax, y);
shun-iwasawa 215a5b
    TPointD a = invAff * TPointD(xMin, y);
shun-iwasawa 215a5b
shun-iwasawa 215a5b
    //  (xL0, yL0) sono le coordinate di a (inizializzate per il round)
shun-iwasawa 215a5b
    //  in versione "TLonghizzata"
shun-iwasawa 215a5b
    //  0 <= xL0 + k*deltaXL
shun-iwasawa 215a5b
    //    <  up->getLx()*(1<<PADN)
shun-iwasawa 215a5b
    //
shun-iwasawa 215a5b
    //  0 <= kMinX
shun-iwasawa 215a5b
    //    <= kMin
shun-iwasawa 215a5b
    //    <= k
shun-iwasawa 215a5b
    //    <= kMax
shun-iwasawa 215a5b
    //    <= kMaxX
shun-iwasawa 215a5b
    //    <= (xMax - xMin)
shun-iwasawa 215a5b
    //
shun-iwasawa 215a5b
    //  0 <= yL0 + k*deltaYL
shun-iwasawa 215a5b
    //    < up->getLy()*(1<<PADN)
shun-iwasawa 215a5b
shun-iwasawa 215a5b
    //  0 <= kMinY
shun-iwasawa 215a5b
    //    <= kMin
shun-iwasawa 215a5b
    //    <= k
shun-iwasawa 215a5b
    //    <= kMax
shun-iwasawa 215a5b
    //    <= kMaxY
shun-iwasawa 215a5b
    //    <= (xMax - xMin)
shun-iwasawa 215a5b
shun-iwasawa 215a5b
    //  xL0 inizializzato per il round
shun-iwasawa 215a5b
    int xL0 = tround((a.x + 0.5) * (1 << PADN));
shun-iwasawa 215a5b
shun-iwasawa 215a5b
    //  yL0 inizializzato per il round
shun-iwasawa 215a5b
    int yL0 = tround((a.y + 0.5) * (1 << PADN));
shun-iwasawa 215a5b
shun-iwasawa 215a5b
    //  calcola kMinX, kMaxX, kMinY, kMaxY
shun-iwasawa 215a5b
    int kMinX = 0, kMaxX = xMax - xMin;  //  clipping su dn
shun-iwasawa 215a5b
    int kMinY = 0, kMaxY = xMax - xMin;  //  clipping su dn
shun-iwasawa 215a5b
shun-iwasawa 215a5b
    //  0 <= xL0 + k*deltaXL
shun-iwasawa 215a5b
    //    < up->getLx()*(1<<PADN)
shun-iwasawa 215a5b
    //           <=>
shun-iwasawa 215a5b
    //  0 <= xL0 + k*deltaXL
shun-iwasawa 215a5b
    //    <= lxPred
shun-iwasawa 215a5b
    //
shun-iwasawa 215a5b
    //  0 <= yL0 + k*deltaYL
shun-iwasawa 215a5b
    //    < up->getLy()*(1<<PADN)
shun-iwasawa 215a5b
    //           <=>
shun-iwasawa 215a5b
    //  0 <= yL0 + k*deltaYL
shun-iwasawa 215a5b
    //    <= lyPred
shun-iwasawa 215a5b
shun-iwasawa 215a5b
    //  calcola kMinX, kMaxX
shun-iwasawa 215a5b
    if (deltaXL == 0) {
shun-iwasawa 215a5b
      // [a, b] verticale esterno ad up+(bordo destro/basso)
shun-iwasawa 215a5b
      if ((xL0 < 0) || (lxPred < xL0)) continue;
shun-iwasawa 215a5b
      //  altrimenti usa solo
shun-iwasawa 215a5b
      //  kMinY, kMaxY ((deltaXL != 0) || (deltaYL != 0))
shun-iwasawa 215a5b
    } else if (deltaXL > 0) {
shun-iwasawa 215a5b
      //  [a, b] esterno ad up+(bordo destro/basso)
shun-iwasawa 215a5b
      if (lxPred < xL0) continue;
shun-iwasawa 215a5b
shun-iwasawa 215a5b
      kMaxX = (lxPred - xL0) / deltaXL;  //  floor
shun-iwasawa 215a5b
      if (xL0 < 0) {
shun-iwasawa 215a5b
        kMinX = ((-xL0) + deltaXL - 1) / deltaXL;  //  ceil
shun-iwasawa 215a5b
      }
shun-iwasawa 215a5b
    } else  //  (deltaXL < 0)
shun-iwasawa 215a5b
    {
shun-iwasawa 215a5b
      //  [a, b] esterno ad up+(bordo destro/basso)
shun-iwasawa 215a5b
      if (xL0 < 0) continue;
shun-iwasawa 215a5b
shun-iwasawa 215a5b
      kMaxX = xL0 / (-deltaXL);  //  floor
shun-iwasawa 215a5b
      if (lxPred < xL0) {
shun-iwasawa 215a5b
        kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL);  //  ceil
shun-iwasawa 215a5b
      }
shun-iwasawa 215a5b
    }
shun-iwasawa 215a5b
shun-iwasawa 215a5b
    //  calcola kMinY, kMaxY
shun-iwasawa 215a5b
    if (deltaYL == 0) {
shun-iwasawa 215a5b
      //  [a, b] orizzontale esterno ad up+(bordo destro/basso)
shun-iwasawa 215a5b
      if ((yL0 < 0) || (lyPred < yL0)) continue;
shun-iwasawa 215a5b
      // altrimenti usa solo
shun-iwasawa 215a5b
      // kMinX, kMaxX ((deltaXL != 0) || (deltaYL != 0))
shun-iwasawa 215a5b
    } else if (deltaYL > 0) {
shun-iwasawa 215a5b
      //  [a, b] esterno ad up+(bordo destro/basso)
shun-iwasawa 215a5b
      if (lyPred < yL0) continue;
shun-iwasawa 215a5b
shun-iwasawa 215a5b
      kMaxY = (lyPred - yL0) / deltaYL;  //  floor
shun-iwasawa 215a5b
      if (yL0 < 0) {
shun-iwasawa 215a5b
        kMinY = ((-yL0) + deltaYL - 1) / deltaYL;  //  ceil
shun-iwasawa 215a5b
      }
shun-iwasawa 215a5b
    } else  //  (deltaYL < 0)
shun-iwasawa 215a5b
    {
shun-iwasawa 215a5b
      //  [a, b] esterno ad up+(bordo destro/basso)
shun-iwasawa 215a5b
      if (yL0 < 0) continue;
shun-iwasawa 215a5b
shun-iwasawa 215a5b
      kMaxY = yL0 / (-deltaYL);  //  floor
shun-iwasawa 215a5b
      if (lyPred < yL0) {
shun-iwasawa 215a5b
        kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL);  //  ceil
shun-iwasawa 215a5b
      }
shun-iwasawa 215a5b
    }
shun-iwasawa 215a5b
shun-iwasawa 215a5b
    //  calcola kMin, kMax effettuando anche il clippind su dn
shun-iwasawa 215a5b
    int kMin = std::max({kMinX, kMinY, (int)0});
shun-iwasawa 215a5b
    int kMax = std::min({kMaxX, kMaxY, xMax - xMin});
shun-iwasawa 215a5b
shun-iwasawa 215a5b
    TPixel64 *dnPix    = dnRow + xMin + kMin;
shun-iwasawa 215a5b
    TPixel64 *dnEndPix = dnRow + xMin + kMax + 1;
shun-iwasawa 215a5b
shun-iwasawa 215a5b
    //  (xL, yL) sono le coordinate (inizializzate per il round)
shun-iwasawa 215a5b
    //  in versione "TLonghizzata" del pixel corrente di up
shun-iwasawa 215a5b
    int xL = xL0 + (kMin - 1) * deltaXL;  //  inizializza xL
shun-iwasawa 215a5b
    int yL = yL0 + (kMin - 1) * deltaYL;  //  inizializza yL
shun-iwasawa 215a5b
shun-iwasawa 215a5b
    //  scorre i pixel sulla y-esima scanline di boundingBoxD
shun-iwasawa 215a5b
    for (; dnPix < dnEndPix; ++dnPix) {
shun-iwasawa 215a5b
      xL += deltaXL;
shun-iwasawa 215a5b
      yL += deltaYL;
shun-iwasawa 215a5b
shun-iwasawa 215a5b
      //  il punto di up TPointD(xL/(1<
shun-iwasawa 215a5b
      //  approssimato con (xI, yI)
shun-iwasawa 215a5b
      int xI = xL >> PADN;  //  round
shun-iwasawa 215a5b
      int yI = yL >> PADN;  //  round
shun-iwasawa 215a5b
shun-iwasawa 215a5b
      assert((0 <= xI) && (xI <= up->getLx() - 1) && (0 <= yI) &&
shun-iwasawa 215a5b
             (yI <= up->getLy() - 1));
shun-iwasawa 215a5b
shun-iwasawa 215a5b
      TPixel32 upPix = *(upBasePix + (yI * upWrap + xI));
shun-iwasawa 215a5b
shun-iwasawa 215a5b
      if (firstColumn) upPix.m = 255;
shun-iwasawa 215a5b
      if (upPix.m == 0) continue;
shun-iwasawa 215a5b
shun-iwasawa 215a5b
      TPixel64 upPix64 = toPixel64(upPix);
shun-iwasawa 215a5b
      if (upPix.m == 255)
shun-iwasawa 215a5b
        *dnPix = upPix64;
shun-iwasawa 215a5b
      else if (doPremultiply)
shun-iwasawa 215a5b
        *dnPix = quickOverPixPremult(*dnPix, upPix64);
shun-iwasawa 215a5b
      else
shun-iwasawa 215a5b
        *dnPix = quickOverPix(*dnPix, upPix64);
shun-iwasawa 215a5b
    }
shun-iwasawa 215a5b
  }
shun-iwasawa 215a5b
  dn->unlock();
shun-iwasawa 215a5b
  up->unlock();
shun-iwasawa 215a5b
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void doQuickPutFilter(const TRaster32P &dn, const TRaster32P &up, double sx,
Shinya Kitaoka 120a6e
                      double sy, double tx, double ty) {
Shinya Kitaoka 120a6e
  //  se aff := TAffine(sx, 0, tx, 0, sy, ty) e' degenere la controimmagine
Shinya Kitaoka 120a6e
  //  di up e' un segmento (o un punto)
Shinya Kitaoka 120a6e
  if ((sx == 0) || (sy == 0)) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  contatore bit di shift
Shinya Kitaoka 120a6e
  const int PADN = 16;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  maschera del filtro bilineare
Shinya Kitaoka 120a6e
  const int MASKN = (1 << PADN) - 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  assert(std::max(up->getLx(), up->getLy()) <
Shinya Kitaoka 120a6e
         (1 << (8 * sizeof(int) - PADN - 1)));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  max dimensioni di up gestibili (limite imposto dal numero di bit
Shinya Kitaoka 120a6e
  //  disponibili per la parte intera di xL, yL)
Shinya Kitaoka 120a6e
  TAffine aff(sx, 0, tx, 0, sy, ty);
Shinya Kitaoka 120a6e
  TRectD boundingBoxD = TRectD(convert(dn->getSize())) *
Shinya Kitaoka 120a6e
                        (aff * TRectD(0, 0, up->getLx() - 2, up->getLy() - 2));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping
Shinya Kitaoka 120a6e
  if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1)
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping y su dn
Shinya Kitaoka 120a6e
  int yMin = std::max(tfloor(boundingBoxD.y0), 0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping y su dn
Shinya Kitaoka 120a6e
  int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping x su dn
Shinya Kitaoka 120a6e
  int xMin = std::max(tfloor(boundingBoxD.x0), 0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping x su dn
Shinya Kitaoka 120a6e
  int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  inversa di aff
Shinya Kitaoka 120a6e
  TAffine invAff = inv(aff);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //	nello scorrere le scanline di boundingBoxD, il passaggio alla scanline
Shinya Kitaoka 120a6e
  //    successiva comporta l'incremento (0, deltaYD) delle coordinate dei
Shinya Kitaoka 120a6e
  //    pixels corrispondenti di up
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //    nel disegnare la y-esima scanline di dn, il passaggio al pixel
Shinya Kitaoka 120a6e
  //    successivo comporta l'incremento (deltaXD, 0) delle coordinate del
Shinya Kitaoka 120a6e
  //    pixel corrispondente di up
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double deltaXD = invAff.a11;
Shinya Kitaoka 120a6e
  double deltaYD = invAff.a22;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  deltaXD "TLonghizzato" (round)
Shinya Kitaoka 120a6e
  int deltaXL = tround(deltaXD * (1 << PADN));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  deltaYD "TLonghizzato" (round)
Shinya Kitaoka 120a6e
  int deltaYL = tround(deltaYD * (1 << PADN));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  se aff "TLonghizzata" (round) e' degenere la controimmagine di up e' un
Shinya Kitaoka 120a6e
  //  segmento (o un punto)
Shinya Kitaoka 120a6e
  if ((deltaXL == 0) || (deltaYL == 0)) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //	(1)  equazione (kX, kY)-parametrica di boundingBoxD:
Shinya Kitaoka 120a6e
  //	       (xMin, yMin) + kX*(1, 0) + kY*(0, 1),
Shinya Kitaoka 120a6e
  //	         kX = 0, ..., (xMax - xMin),
Shinya Kitaoka 120a6e
  //             kY = 0, ..., (yMax - yMin)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //	(2)  equazione (kX, kY)-parametrica dell'immagine
Shinya Kitaoka 120a6e
  //         mediante invAff di (1):
Shinya Kitaoka 120a6e
  //	       invAff*(xMin, yMin) + kX*(deltaXD, 0) + kY*(0, deltaYD),
Shinya Kitaoka 120a6e
  //	         kX = kMinX, ..., kMaxX
Shinya Kitaoka 120a6e
  //               con 0 <= kMinX <= kMaxX <= (xMax - xMin)
Shinya Kitaoka 120a6e
  //
Shinya Kitaoka 120a6e
  //	         kY = kMinY, ..., kMaxY
Shinya Kitaoka 120a6e
  //               con 0 <= kMinY <= kMaxY <= (yMax - yMin)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  calcola kMinX, kMaxX, kMinY, kMaxY intersecando la (2) con i lati di up
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  il segmento [a, b] di up (con gli estremi eventualmente invertiti) e'
Shinya Kitaoka 120a6e
  //  la controimmagine
Shinya Kitaoka 120a6e
  //  mediante aff della porzione di scanline  [ (xMin, yMin), (xMax, yMin) ]
Shinya Kitaoka 120a6e
  //  di dn
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  TPointD b = invAff*TPointD(xMax, yMin);
Shinya Kitaoka 120a6e
  TPointD a = invAff * TPointD(xMin, yMin);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  (xL0, yL0) sono le coordinate di a (inizializzate per il round) in
Shinya Kitaoka 120a6e
  //  versione "TLonghizzata"
Shinya Kitaoka 120a6e
  //
Shinya Kitaoka 120a6e
  //    0 <= xL0 + kX*deltaXL
Shinya Kitaoka 120a6e
  //      <= (up->getLx() - 2)*(1<<PADN),
Shinya Kitaoka 120a6e
  //    0 <= kMinX <= kX
Shinya Kitaoka 120a6e
  //      <= kMaxX <= (xMax - xMin)
Shinya Kitaoka 120a6e
  //
Shinya Kitaoka 120a6e
  //	0 <= yL0 + kY*deltaYL
Shinya Kitaoka 120a6e
  //      <= (up->getLy() - 2)*(1<<PADN),
Shinya Kitaoka 120a6e
  //    0 <= kMinY <= kY
Shinya Kitaoka 120a6e
  //      <= kMaxY <= (yMax - yMin)
Shinya Kitaoka 120a6e
  int xL0 = tround(a.x * (1 << PADN));  //  xL0 inizializzato
Shinya Kitaoka 120a6e
  int yL0 = tround(a.y * (1 << PADN));  //  yL0 inizializzato
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  calcola kMinY, kMaxY, kMinX, kMaxX intersecando la (2) con i lati
Shinya Kitaoka 120a6e
  //  di up
Shinya Kitaoka 120a6e
  int kMinX = 0, kMaxX = xMax - xMin;  //  clipping su dn
Shinya Kitaoka 120a6e
  int kMinY = 0, kMaxY = yMax - yMin;  //  clipping su dn
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  TINT32 predecessore di (up->getLx() - 1)
Shinya Kitaoka 120a6e
  int lxPred = (up->getLx() - 2) * (1 << PADN);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  TINT32 predecessore di (up->getLy() - 1)
Shinya Kitaoka 120a6e
  int lyPred = (up->getLy() - 2) * (1 << PADN);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  0 <= xL0 + k*deltaXL
Shinya Kitaoka 120a6e
  //    <= (up->getLx() - 2)*(1<<PADN)
Shinya Kitaoka 120a6e
  //             <=>
Shinya Kitaoka 120a6e
  //  0 <= xL0 + k*deltaXL <= lxPred
Shinya Kitaoka 120a6e
  //
Shinya Kitaoka 120a6e
  //  0 <= yL0 + k*deltaYL
Shinya Kitaoka 120a6e
  //    <= (up->getLy() - 2)*(1<<PADN)
Shinya Kitaoka 120a6e
  //             <=>
Shinya Kitaoka 120a6e
  //  0 <= yL0 + k*deltaYL <= lyPred
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  calcola kMinY, kMaxY intersecando la (2) con
Shinya Kitaoka 120a6e
  //  i lati (y = yMin) e (y = yMax) di up
Shinya Kitaoka 120a6e
  if (deltaYL > 0)  //  (deltaYL != 0)
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    //  [a, b] interno ad up contratto
Shinya Kitaoka 120a6e
    assert(yL0 <= lyPred);
Shinya Kitaoka 120a6e
    kMaxY = (lyPred - yL0) / deltaYL;  //  floor
Shinya Kitaoka 120a6e
    if (yL0 < 0) {
Shinya Kitaoka 120a6e
      kMinY = ((-yL0) + deltaYL - 1) / deltaYL;  //  ceil
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else  //  (deltaYL < 0)
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    //  [a, b] interno ad up contratto
Shinya Kitaoka 120a6e
    assert(0 <= yL0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    kMaxY = yL0 / (-deltaYL);  //  floor
Shinya Kitaoka 120a6e
    if (lyPred < yL0) {
Shinya Kitaoka 120a6e
      kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL);  //  ceil
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  //	calcola kMinY, kMaxY effettuando anche il clippind su dn
Shinya Kitaoka 120a6e
  kMinY = std::max(kMinY, (int)0);
Shinya Kitaoka 120a6e
  kMaxY = std::min(kMaxY, yMax - yMin);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  calcola kMinX, kMaxX intersecando la (2) con
Shinya Kitaoka 120a6e
  //  i lati (x = xMin) e (x = xMax) di up
Shinya Kitaoka 120a6e
  if (deltaXL > 0)  //  (deltaXL != 0)
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    //  [a, b] interno ad up contratto
Shinya Kitaoka 120a6e
    assert(xL0 <= lxPred);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    kMaxX = (lxPred - xL0) / deltaXL;  //  floor
Shinya Kitaoka 120a6e
    if (xL0 < 0) {
Shinya Kitaoka 120a6e
      kMinX = ((-xL0) + deltaXL - 1) / deltaXL;  //  ceil
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else  //  (deltaXL < 0)
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    //  [a, b] interno ad up contratto
Shinya Kitaoka 120a6e
    assert(0 <= xL0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    kMaxX = xL0 / (-deltaXL);  //  floor
Shinya Kitaoka 120a6e
    if (lxPred < xL0) {
Shinya Kitaoka 120a6e
      kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL);  //  ceil
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  //  calcola kMinX, kMaxX effettuando anche il clippind su dn
Shinya Kitaoka 120a6e
  kMinX = std::max(kMinX, (int)0);
Shinya Kitaoka 120a6e
  kMaxX = std::min(kMaxX, xMax - xMin);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int dnWrap = dn->getWrap();
Shinya Kitaoka 120a6e
  int upWrap = up->getWrap();
Shinya Kitaoka 120a6e
  dn->lock();
Shinya Kitaoka 120a6e
  up->lock();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TPixel32 *upBasePix = up->pixels();
Shinya Kitaoka 120a6e
  TPixel32 *dnRow     = dn->pixels(yMin + kMinY);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  (xL, yL) sono le coordinate (inizializzate per il round)
Shinya Kitaoka 120a6e
  //  in versione "TLonghizzata" del pixel corrente di up
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  inizializza yL
Shinya Kitaoka 120a6e
  int yL = yL0 + (kMinY - 1) * deltaYL;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  scorre le scanline di boundingBoxD
Shinya Kitaoka 120a6e
  for (int kY = kMinY; kY <= kMaxY; kY++, dnRow += dnWrap) {
Shinya Kitaoka 120a6e
    //  inizializza xL
Shinya Kitaoka 120a6e
    int xL = xL0 + (kMinX - 1) * deltaXL;
Shinya Kitaoka 120a6e
    yL += deltaYL;
Shinya Kitaoka 120a6e
    //  il punto di up TPointD(xL/(1<
Shinya Kitaoka 120a6e
    //  con (xI, yI)
Shinya Kitaoka 120a6e
    int yI = yL >> PADN;  //  troncato
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  filtro bilineare 4 pixels: calcolo degli y-pesi
Shinya Kitaoka 120a6e
    int yWeight1 = (yL & MASKN);
Shinya Kitaoka 120a6e
    int yWeight0 = (1 << PADN) - yWeight1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TPixel32 *dnPix    = dnRow + xMin + kMinX;
Shinya Kitaoka 120a6e
    TPixel32 *dnEndPix = dnRow + xMin + kMaxX + 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  scorre i pixel sulla (yMin + kY)-esima scanline di dn
Shinya Kitaoka 120a6e
    for (; dnPix < dnEndPix; ++dnPix) {
Shinya Kitaoka 120a6e
      xL += deltaXL;
Shinya Kitaoka 120a6e
      //  il punto di up TPointD(xL/(1<
Shinya Kitaoka 120a6e
      //  approssimato con (xI, yI)
Shinya Kitaoka 120a6e
      int xI = xL >> PADN;  //  troncato
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      assert((0 <= xI) && (xI <= up->getLx() - 1) && (0 <= yI) &&
Shinya Kitaoka 120a6e
             (yI <= up->getLy() - 1));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      //  (xI, yI)
Shinya Kitaoka 120a6e
      TPixel32 *upPix00 = upBasePix + (yI * upWrap + xI);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      //  (xI + 1, yI)
Shinya Kitaoka 120a6e
      TPixel32 *upPix10 = upPix00 + 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      //  (xI, yI + 1)
Shinya Kitaoka 120a6e
      TPixel32 *upPix01 = upPix00 + upWrap;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      //  (xI + 1, yI + 1)
Shinya Kitaoka 120a6e
      TPixel32 *upPix11 = upPix00 + upWrap + 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      //  filtro bilineare 4 pixels: calcolo degli x-pesi
Shinya Kitaoka 120a6e
      int xWeight1 = (xL & MASKN);
Shinya Kitaoka 120a6e
      int xWeight0 = (1 << PADN) - xWeight1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      //  filtro bilineare 4 pixels: media pesata sui singoli canali
Shinya Kitaoka 120a6e
      int rColDownTmp =
Shinya Kitaoka 120a6e
          (xWeight0 * (upPix00->r) + xWeight1 * ((upPix10)->r)) >> PADN;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      int gColDownTmp =
Shinya Kitaoka 120a6e
          (xWeight0 * (upPix00->g) + xWeight1 * ((upPix10)->g)) >> PADN;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      int bColDownTmp =
Shinya Kitaoka 120a6e
          (xWeight0 * (upPix00->b) + xWeight1 * ((upPix10)->b)) >> PADN;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      int rColUpTmp =
Shinya Kitaoka 120a6e
          (xWeight0 * ((upPix01)->r) + xWeight1 * ((upPix11)->r)) >> PADN;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      int gColUpTmp =
Shinya Kitaoka 120a6e
          (xWeight0 * ((upPix01)->g) + xWeight1 * ((upPix11)->g)) >> PADN;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      int bColUpTmp =
Shinya Kitaoka 120a6e
          (xWeight0 * ((upPix01)->b) + xWeight1 * ((upPix11)->b)) >> PADN;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      unsigned char rCol =
Shinya Kitaoka 120a6e
          (unsigned char)((yWeight0 * rColDownTmp + yWeight1 * rColUpTmp) >>
Shinya Kitaoka 120a6e
                          PADN);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      unsigned char gCol =
Shinya Kitaoka 120a6e
          (unsigned char)((yWeight0 * gColDownTmp + yWeight1 * gColUpTmp) >>
Shinya Kitaoka 120a6e
                          PADN);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      unsigned char bCol =
Shinya Kitaoka 120a6e
          (unsigned char)((yWeight0 * bColDownTmp + yWeight1 * bColUpTmp) >>
Shinya Kitaoka 120a6e
                          PADN);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      TPixel32 upPix = TPixel32(rCol, gCol, bCol, upPix00->m);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (upPix.m == 0)
Shinya Kitaoka 120a6e
        continue;
Shinya Kitaoka 120a6e
      else if (upPix.m == 255)
Shinya Kitaoka 120a6e
        *dnPix = upPix;
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        *dnPix = quickOverPix(*dnPix, upPix);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  dn->unlock();
Shinya Kitaoka 120a6e
  up->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
//=============================================================================
Shinya Kitaoka 120a6e
void doQuickPutNoFilter(const TRaster32P &dn, const TRaster32P &up, double sx,
Shinya Kitaoka 120a6e
                        double sy, double tx, double ty,
Shinya Kitaoka 120a6e
                        const TPixel32 &colorScale, bool doPremultiply,
Shinya Kitaoka 120a6e
                        bool whiteTransp, bool firstColumn,
Shinya Kitaoka 120a6e
                        bool doRasterDarkenBlendedView) {
Shinya Kitaoka 120a6e
  //  se aff := TAffine(sx, 0, tx, 0, sy, ty) e' degenere la controimmagine
Shinya Kitaoka 120a6e
  //  di up e' un segmento (o un punto)
Shinya Kitaoka 120a6e
  if ((sx == 0) || (sy == 0)) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  contatore bit di shift
Shinya Kitaoka 120a6e
  const int PADN = 16;
Shinya Kitaoka 120a6e
  assert(std::max(up->getLx(), up->getLy()) <
Shinya Kitaoka 120a6e
         (1 << (8 * sizeof(int) - PADN - 1)));
Shinya Kitaoka 120a6e
  //  max dimensioni di up gestibili (limite imposto dal numero di bit
Shinya Kitaoka 120a6e
  // disponibili per la parte intera di xL, yL)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TAffine aff(sx, 0, tx, 0, sy, ty);
Shinya Kitaoka 120a6e
  TRectD boundingBoxD =
Shinya Kitaoka 120a6e
      TRectD(convert(dn->getBounds())) *
Shinya Kitaoka 120a6e
      (aff * TRectD(-0.5, -0.5, up->getLx() - 0.5, up->getLy() - 0.5));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping
Shinya Kitaoka 120a6e
  if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1)
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping y su dn
Shinya Kitaoka 120a6e
  int yMin = std::max(tfloor(boundingBoxD.y0), 0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping y su dn
Shinya Kitaoka 120a6e
  int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping x su dn
Shinya Kitaoka 120a6e
  int xMin = std::max(tfloor(boundingBoxD.x0), 0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping x su dn
Shinya Kitaoka 120a6e
  int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TAffine invAff = inv(aff);  //  inversa di aff
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  nello scorrere le scanline di boundingBoxD, il passaggio alla scanline
Shinya Kitaoka 120a6e
  //  successiva comporta l'incremento (0, deltaYD) delle coordinate dei
Shinya Kitaoka 120a6e
  //  pixels corrispondenti di up
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  nel disegnare la y-esima scanline di dn, il passaggio al pixel
Shinya Kitaoka 120a6e
  //  successivo comporta l'incremento (deltaXD, 0) delle coordinate del
Shinya Kitaoka 120a6e
  //  pixel corrispondente di up
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double deltaXD = invAff.a11;
Shinya Kitaoka 120a6e
  double deltaYD = invAff.a22;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  deltaXD "TLonghizzato" (round)
Shinya Kitaoka 120a6e
  int deltaXL = tround(deltaXD * (1 << PADN));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  deltaYD "TLonghizzato" (round)
Shinya Kitaoka 120a6e
  int deltaYL = tround(deltaYD * (1 << PADN));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  se aff "TLonghizzata" (round) e' degenere la controimmagine di up e' un
Shinya Kitaoka 120a6e
  //  segmento (o un punto)
Shinya Kitaoka 120a6e
  if ((deltaXL == 0) || (deltaYL == 0)) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //	(1)  equazione (kX, kY)-parametrica di boundingBoxD:
Shinya Kitaoka 120a6e
  //	       (xMin, yMin) + kX*(1, 0) + kY*(0, 1),
Shinya Kitaoka 120a6e
  //	         kX = 0, ..., (xMax - xMin),
Shinya Kitaoka 120a6e
  //             kY = 0, ..., (yMax - yMin)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //	(2)  equazione (kX, kY)-parametrica dell'immagine
Shinya Kitaoka 120a6e
  //         mediante invAff di (1):
Shinya Kitaoka 120a6e
  //	       invAff*(xMin, yMin) + kX*(deltaXD, 0) + kY*(0, deltaYD),
Shinya Kitaoka 120a6e
  //	         kX = kMinX, ..., kMaxX
Shinya Kitaoka 120a6e
  //             con 0 <= kMinX <= kMaxX <= (xMax - xMin)
Shinya Kitaoka 120a6e
  //
Shinya Kitaoka 120a6e
  //             kY = kMinY, ..., kMaxY
Shinya Kitaoka 120a6e
  //             con 0 <= kMinY <= kMaxY <= (yMax - yMin)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  calcola kMinX, kMaxX, kMinY, kMaxY intersecando la (2) con i lati di up
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  il segmento [a, b] di up e' la controimmagine mediante aff della
Shinya Kitaoka 120a6e
  // porzione di scanline  [ (xMin, yMin), (xMax, yMin) ] di dn
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  TPointD b = invAff*TPointD(xMax, yMin);
Shinya Kitaoka 120a6e
  TPointD a = invAff * TPointD(xMin, yMin);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  (xL0, yL0) sono le coordinate di a (inizializzate per il round)
Shinya Kitaoka 120a6e
  // in versione "TLonghizzata"
Shinya Kitaoka 120a6e
  //	0 <= xL0 + kX*deltaXL
Shinya Kitaoka 120a6e
  //      < up->getLx()*(1<<PADN),
Shinya Kitaoka 120a6e
  //
Shinya Kitaoka 120a6e
  //    0 <= kMinX
Shinya Kitaoka 120a6e
  //      <= kX
Shinya Kitaoka 120a6e
  //      <= kMaxX
Shinya Kitaoka 120a6e
  //      <= (xMax - xMin)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //	0 <= yL0 + kY*deltaYL
Shinya Kitaoka 120a6e
  //      < up->getLy()*(1<<PADN),
Shinya Kitaoka 120a6e
  //
Shinya Kitaoka 120a6e
  //    0 <= kMinY
Shinya Kitaoka 120a6e
  //      <= kY
Shinya Kitaoka 120a6e
  //      <= kMaxY
Shinya Kitaoka 120a6e
  //      <= (yMax - yMin)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  xL0 inizializzato per il round
Shinya Kitaoka 120a6e
  int xL0 = tround((a.x + 0.5) * (1 << PADN));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  yL0 inizializzato per il round
Shinya Kitaoka 120a6e
  int yL0 = tround((a.y + 0.5) * (1 << PADN));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  calcola kMinY, kMaxY, kMinX, kMaxX intersecando la (2) con i lati di up
Shinya Kitaoka 120a6e
  int kMinX = 0, kMaxX = xMax - xMin;  //  clipping su dn
Shinya Kitaoka 120a6e
  int kMinY = 0, kMaxY = yMax - yMin;  //  clipping su dn
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  TINT32 predecessore di up->getLx()
Shinya Kitaoka 120a6e
  int lxPred = up->getLx() * (1 << PADN) - 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  TINT32 predecessore di up->getLy()
Shinya Kitaoka 120a6e
  int lyPred = up->getLy() * (1 << PADN) - 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  0 <= xL0 + k*deltaXL < up->getLx()*(1<<PADN)
Shinya Kitaoka 120a6e
  //            <=>
Shinya Kitaoka 120a6e
  //  0 <= xL0 + k*deltaXL <= lxPred
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  0 <= yL0 + k*deltaYL < up->getLy()*(1<<PADN)
Shinya Kitaoka 120a6e
  //            <=>
Shinya Kitaoka 120a6e
  //  0 <= yL0 + k*deltaYL <= lyPred
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  calcola kMinY, kMaxY intersecando la (2) con i lati
Shinya Kitaoka 120a6e
  //  (y = yMin) e (y = yMax) di up
Shinya Kitaoka 120a6e
  if (deltaYL > 0)  //  (deltaYL != 0)
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    //  [a, b] interno ad up+(bordo destro/basso)
Shinya Kitaoka 120a6e
    assert(yL0 <= lyPred);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    kMaxY = (lyPred - yL0) / deltaYL;  //  floor
Shinya Kitaoka 120a6e
    if (yL0 < 0) {
Shinya Kitaoka 120a6e
      kMinY = ((-yL0) + deltaYL - 1) / deltaYL;  //  ceil
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else  //  (deltaYL < 0)
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    //  [a, b] interno ad up+(bordo destro/basso)
Shinya Kitaoka 120a6e
    assert(0 <= yL0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    kMaxY = yL0 / (-deltaYL);  //  floor
Shinya Kitaoka 120a6e
    if (lyPred < yL0) {
Shinya Kitaoka 120a6e
      kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL);  //  ceil
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  //  calcola kMinY, kMaxY effettuando anche il clippind su dn
Shinya Kitaoka 120a6e
  kMinY = std::max(kMinY, (int)0);
Shinya Kitaoka 120a6e
  kMaxY = std::min(kMaxY, yMax - yMin);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  calcola kMinX, kMaxX intersecando la (2) con i lati
Shinya Kitaoka 120a6e
  //  (x = xMin) e (x = xMax) di up
Shinya Kitaoka 120a6e
  if (deltaXL > 0)  //  (deltaXL != 0)
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    //  [a, b] interno ad up+(bordo destro/basso)
Shinya Kitaoka 120a6e
    assert(xL0 <= lxPred);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    kMaxX = (lxPred - xL0) / deltaXL;  //  floor
Shinya Kitaoka 120a6e
    if (xL0 < 0) {
Shinya Kitaoka 120a6e
      kMinX = ((-xL0) + deltaXL - 1) / deltaXL;  //  ceil
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else  //  (deltaXL < 0)
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    //  [a, b] interno ad up+(bordo destro/basso)
Shinya Kitaoka 120a6e
    assert(0 <= xL0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    kMaxX = xL0 / (-deltaXL);  //  floor
Shinya Kitaoka 120a6e
    if (lxPred < xL0) {
Shinya Kitaoka 120a6e
      kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL);  //  ceil
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  //  calcola kMinX, kMaxX effettuando anche il clippind su dn
Shinya Kitaoka 120a6e
  kMinX = std::max(kMinX, (int)0);
Shinya Kitaoka 120a6e
  kMaxX = std::min(kMaxX, xMax - xMin);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int dnWrap = dn->getWrap();
Shinya Kitaoka 120a6e
  int upWrap = up->getWrap();
Shinya Kitaoka 120a6e
  dn->lock();
Shinya Kitaoka 120a6e
  up->lock();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TPixel32 *upBasePix = up->pixels();
Shinya Kitaoka 120a6e
  TPixel32 *dnRow     = dn->pixels(yMin + kMinY);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  (xL, yL) sono le coordinate (inizializzate per il round)
Shinya Kitaoka 120a6e
  //  in versione "TLonghizzata" del pixel corrente di up
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  inizializza yL
Shinya Kitaoka 120a6e
  int yL = yL0 + (kMinY - 1) * deltaYL;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  scorre le scanline di boundingBoxD
Shinya Kitaoka 120a6e
  for (int kY = kMinY; kY <= kMaxY; kY++, dnRow += dnWrap) {
Shinya Kitaoka 120a6e
    //  inizializza xL
Shinya Kitaoka 120a6e
    int xL = xL0 + (kMinX - 1) * deltaXL;
Shinya Kitaoka 120a6e
    yL += deltaYL;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  il punto di up TPointD(xL/(1<
Shinya Kitaoka 120a6e
    //  con (xI, yI)
Shinya Kitaoka 120a6e
    int yI = yL >> PADN;  //  round
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TPixel32 *dnPix    = dnRow + xMin + kMinX;
Shinya Kitaoka 120a6e
    TPixel32 *dnEndPix = dnRow + xMin + kMaxX + 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  scorre i pixel sulla (yMin + kY)-esima scanline di dn
Shinya Kitaoka 120a6e
    for (; dnPix < dnEndPix; ++dnPix) {
Shinya Kitaoka 120a6e
      xL += deltaXL;
Shinya Kitaoka 120a6e
      //  il punto di up TPointD(xL/(1<
Shinya Kitaoka 120a6e
      //  approssimato con (xI, yI)
Shinya Kitaoka 120a6e
      int xI = xL >> PADN;  //	round
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      assert((0 <= xI) && (xI <= up->getLx() - 1) && (0 <= yI) &&
Shinya Kitaoka 120a6e
             (yI <= up->getLy() - 1));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      TPixel32 upPix = *(upBasePix + (yI * upWrap + xI));
Shinya Kitaoka 120a6e
shun-iwasawa 443318
      if (firstColumn) upPix.m = 255;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (upPix.m == 0 || (whiteTransp && upPix == TPixel::White)) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (colorScale != TPixel32::Black)
Shinya Kitaoka 120a6e
        upPix = applyColorScale(upPix, colorScale, doPremultiply);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (doRasterDarkenBlendedView)
Shinya Kitaoka 120a6e
        *dnPix = quickOverPixDarkenBlended(*dnPix, upPix);
Shinya Kitaoka 120a6e
      else {
Shinya Kitaoka 120a6e
        if (upPix.m == 255)
Shinya Kitaoka 120a6e
          *dnPix = upPix;
Shinya Kitaoka 120a6e
        else if (doPremultiply)
Shinya Kitaoka 120a6e
          *dnPix = quickOverPixPremult(*dnPix, upPix);
Shinya Kitaoka 120a6e
        else
Shinya Kitaoka 120a6e
          *dnPix = quickOverPix(*dnPix, upPix);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  dn->unlock();
Shinya Kitaoka 120a6e
  up->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Shinya Kitaoka 120a6e
void doQuickPutNoFilter(const TRaster32P &dn, const TRasterGR8P &up, double sx,
Shinya Kitaoka 120a6e
                        double sy, double tx, double ty,
Shinya Kitaoka 120a6e
                        const TPixel32 &colorScale) {
Shinya Kitaoka 120a6e
  if ((sx == 0) || (sy == 0)) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  const int PADN = 16;
Shinya Kitaoka 120a6e
  assert(std::max(up->getLx(), up->getLy()) <
Shinya Kitaoka 120a6e
         (1 << (8 * sizeof(int) - PADN - 1)));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TAffine aff(sx, 0, tx, 0, sy, ty);
Shinya Kitaoka 120a6e
  TRectD boundingBoxD =
Shinya Kitaoka 120a6e
      TRectD(convert(dn->getBounds())) *
Shinya Kitaoka 120a6e
      (aff * TRectD(-0.5, -0.5, up->getLx() - 0.5, up->getLy() - 0.5));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1)
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int yMin = std::max(tfloor(boundingBoxD.y0), 0);
Shinya Kitaoka 120a6e
  int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1);
Shinya Kitaoka 120a6e
  int xMin = std::max(tfloor(boundingBoxD.x0), 0);
Shinya Kitaoka 120a6e
  int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TAffine invAff = inv(aff);  //  inversa di aff
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double deltaXD = invAff.a11;
Shinya Kitaoka 120a6e
  double deltaYD = invAff.a22;
Shinya Kitaoka 120a6e
  int deltaXL    = tround(deltaXD * (1 << PADN));
Shinya Kitaoka 120a6e
  int deltaYL    = tround(deltaYD * (1 << PADN));
Shinya Kitaoka 120a6e
  if ((deltaXL == 0) || (deltaYL == 0)) return;
Shinya Kitaoka 120a6e
  TPointD a = invAff * TPointD(xMin, yMin);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int xL0   = tround((a.x + 0.5) * (1 << PADN));
Shinya Kitaoka 120a6e
  int yL0   = tround((a.y + 0.5) * (1 << PADN));
Shinya Kitaoka 120a6e
  int kMinX = 0, kMaxX = xMax - xMin;  //  clipping su dn
Shinya Kitaoka 120a6e
  int kMinY = 0, kMaxY = yMax - yMin;  //  clipping su dn
Shinya Kitaoka 120a6e
  int lxPred = up->getLx() * (1 << PADN) - 1;
Shinya Kitaoka 120a6e
  int lyPred = up->getLy() * (1 << PADN) - 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (deltaYL > 0)  //  (deltaYL != 0)
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    assert(yL0 <= lyPred);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    kMaxY = (lyPred - yL0) / deltaYL;  //  floor
Shinya Kitaoka 120a6e
    if (yL0 < 0) {
Shinya Kitaoka 120a6e
      kMinY = ((-yL0) + deltaYL - 1) / deltaYL;  //  ceil
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else  //  (deltaYL < 0)
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    assert(0 <= yL0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    kMaxY = yL0 / (-deltaYL);  //  floor
Shinya Kitaoka 120a6e
    if (lyPred < yL0) {
Shinya Kitaoka 120a6e
      kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL);  //  ceil
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  kMinY = std::max(kMinY, (int)0);
Shinya Kitaoka 120a6e
  kMaxY = std::min(kMaxY, yMax - yMin);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (deltaXL > 0)  //  (deltaXL != 0)
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    assert(xL0 <= lxPred);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    kMaxX = (lxPred - xL0) / deltaXL;  //  floor
Shinya Kitaoka 120a6e
    if (xL0 < 0) {
Shinya Kitaoka 120a6e
      kMinX = ((-xL0) + deltaXL - 1) / deltaXL;  //  ceil
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else  //  (deltaXL < 0)
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    assert(0 <= xL0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    kMaxX = xL0 / (-deltaXL);  //  floor
Shinya Kitaoka 120a6e
    if (lxPred < xL0) {
Shinya Kitaoka 120a6e
      kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL);  //  ceil
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  kMinX = std::max(kMinX, (int)0);
Shinya Kitaoka 120a6e
  kMaxX = std::min(kMaxX, xMax - xMin);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int dnWrap = dn->getWrap();
Shinya Kitaoka 120a6e
  int upWrap = up->getWrap();
Shinya Kitaoka 120a6e
  dn->lock();
Shinya Kitaoka 120a6e
  up->lock();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TPixelGR8 *upBasePix = up->pixels();
Shinya Kitaoka 120a6e
  TPixel32 *dnRow      = dn->pixels(yMin + kMinY);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int yL = yL0 + (kMinY - 1) * deltaYL;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (int kY = kMinY; kY <= kMaxY; kY++, dnRow += dnWrap) {
Shinya Kitaoka 120a6e
    //  inizializza xL
Shinya Kitaoka 120a6e
    int xL = xL0 + (kMinX - 1) * deltaXL;
Shinya Kitaoka 120a6e
    yL += deltaYL;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  il punto di up TPointD(xL/(1<
Shinya Kitaoka 120a6e
    //  con (xI, yI)
Shinya Kitaoka 120a6e
    int yI = yL >> PADN;  //  round
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TPixel32 *dnPix    = dnRow + xMin + kMinX;
Shinya Kitaoka 120a6e
    TPixel32 *dnEndPix = dnRow + xMin + kMaxX + 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  scorre i pixel sulla (yMin + kY)-esima scanline di dn
Shinya Kitaoka 120a6e
    for (; dnPix < dnEndPix; ++dnPix) {
Shinya Kitaoka 120a6e
      xL += deltaXL;
Shinya Kitaoka 120a6e
      int xI = xL >> PADN;  //	round
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      assert((0 <= xI) && (xI <= up->getLx() - 1) && (0 <= yI) &&
Shinya Kitaoka 120a6e
             (yI <= up->getLy() - 1));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      TPixelGR8 *upPix = upBasePix + (yI * upWrap + xI);
Shinya Kitaoka 120a6e
      if (colorScale == TPixel32::Black) {
Shinya Kitaoka 120a6e
        dnPix->r = dnPix->g = dnPix->b = upPix->value;
Shinya Kitaoka 120a6e
        dnPix->m                       = 255;
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        TPixel32 upPix32(upPix->value, upPix->value, upPix->value, 255);
Shinya Kitaoka 120a6e
        upPix32 = applyColorScale(upPix32, colorScale);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        if (upPix32.m == 255)
Shinya Kitaoka 120a6e
          *dnPix = upPix32;
Shinya Kitaoka 120a6e
        else
Shinya Kitaoka 120a6e
          *dnPix = quickOverPix(*dnPix, upPix32);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      /*
Shinya Kitaoka 120a6e
if (upPix->value == 0)
Shinya Kitaoka 120a6e
dnPix->r = dnPix->g = dnPix->b = dnPix->m = upPix->value;
Shinya Kitaoka 120a6e
else if (upPix->value == 255)
Shinya Kitaoka 120a6e
dnPix->r = dnPix->g = dnPix->b = dnPix->m = upPix->value;
Shinya Kitaoka 120a6e
else
Shinya Kitaoka 120a6e
*dnPix = quickOverPix(*dnPix, *upPix);
Shinya Kitaoka 120a6e
*/
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  dn->unlock();
Shinya Kitaoka 120a6e
  up->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void doQuickResampleFilter(const TRaster32P &dn, const TRaster32P &up,
Shinya Kitaoka 120a6e
                           const TAffine &aff) {
Shinya Kitaoka 120a6e
  //  se aff e' degenere la controimmagine di up e' un segmento (o un punto)
Shinya Kitaoka 120a6e
  if ((aff.a11 * aff.a22 - aff.a12 * aff.a21) == 0) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  contatore bit di shift
Shinya Kitaoka 120a6e
  const int PADN = 16;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  maschera del filtro bilineare
Shinya Kitaoka 120a6e
  const int MASKN = (1 << PADN) - 1;
Shinya Kitaoka 120a6e
  assert(std::max(up->getLx(), up->getLy()) <
Shinya Kitaoka 120a6e
         (1 << (8 * sizeof(int) - PADN - 1)));
Shinya Kitaoka 120a6e
  //  max dimensioni di up gestibili (limite imposto dal numero di bit
Shinya Kitaoka 120a6e
  //  disponibili per la parte intera di xL, yL)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRectD boundingBoxD = TRectD(convert(dn->getSize())) *
Shinya Kitaoka 120a6e
                        (aff * TRectD(0, 0, up->getLx() - 2, up->getLy() - 2));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping
Shinya Kitaoka 120a6e
  if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1)
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping y su dn
Shinya Kitaoka 120a6e
  int yMin = std::max(tfloor(boundingBoxD.y0), 0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping y su dn
Shinya Kitaoka 120a6e
  int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping x su dn
Shinya Kitaoka 120a6e
  int xMin = std::max(tfloor(boundingBoxD.x0), 0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping x su dn
Shinya Kitaoka 120a6e
  int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TAffine invAff = inv(aff);  //  inversa di aff
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  nel disegnare la y-esima scanline di dn, il passaggio al pixel
Shinya Kitaoka 120a6e
  //  successivo comporta l'incremento (deltaXD, deltaYD) delle coordinate
Shinya Kitaoka 120a6e
  //  del pixel corrispondente di up
Shinya Kitaoka 120a6e
  double deltaXD = invAff.a11;
Shinya Kitaoka 120a6e
  double deltaYD = invAff.a21;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  deltaXD "TLonghizzato" (round)
Shinya Kitaoka 120a6e
  int deltaXL = tround(deltaXD * (1 << PADN));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  deltaYD "TLonghizzato" (round)
Shinya Kitaoka 120a6e
  int deltaYL = tround(deltaYD * (1 << PADN));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  se aff "TLonghizzata" (round) e' degenere la controimmagine di up e' un
Shinya Kitaoka 120a6e
  //  segmento (o un punto)
Shinya Kitaoka 120a6e
  if ((deltaXL == 0) && (deltaYL == 0)) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // naturale predecessore di up->getLx() - 1
Shinya Kitaoka 120a6e
  int lxPred = (up->getLx() - 2) * (1 << PADN);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  naturale predecessore di up->getLy() - 1
Shinya Kitaoka 120a6e
  int lyPred = (up->getLy() - 2) * (1 << PADN);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int dnWrap = dn->getWrap();
Shinya Kitaoka 120a6e
  int upWrap = up->getWrap();
Shinya Kitaoka 120a6e
  dn->lock();
Shinya Kitaoka 120a6e
  up->lock();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TPixel32 *dnRow     = dn->pixels(yMin);
Shinya Kitaoka 120a6e
  TPixel32 *upBasePix = up->pixels();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  scorre le scanline di boundingBoxD
Shinya Kitaoka 120a6e
  for (int y = yMin; y <= yMax; y++, dnRow += dnWrap) {
Shinya Kitaoka 120a6e
    //  (1)  equazione k-parametrica della y-esima scanline di boundingBoxD:
Shinya Kitaoka 120a6e
    //         (xMin, y) + k*(1, 0),  k = 0, ..., (xMax - xMin)
Shinya Kitaoka 120a6e
    //
Shinya Kitaoka 120a6e
    //  (2)  equazione k-parametrica dell'immagine mediante invAff di (1):
Shinya Kitaoka 120a6e
    //         invAff*(xMin, y) + k*(deltaXD, deltaYD),
Shinya Kitaoka 120a6e
    //           k = kMin, ..., kMax
Shinya Kitaoka 120a6e
    //           con 0 <= kMin <= kMax <= (xMax - xMin)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  calcola kMin, kMax per la scanline corrente intersecando
Shinya Kitaoka 120a6e
    //  la (2) con i lati di up
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  il segmento [a, b] di up e' la controimmagine mediante aff della
Shinya Kitaoka 120a6e
    //  porzione di scanline  [ (xMin, y), (xMax, y) ] di dn
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  TPointD b = invAff*TPointD(xMax, y);
Shinya Kitaoka 120a6e
    TPointD a = invAff * TPointD(xMin, y);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  (xL0, yL0) sono le coordinate di a in versione "TLonghizzata"
Shinya Kitaoka 120a6e
    //  0 <= xL0 + k*deltaXL
Shinya Kitaoka 120a6e
    //    <= (up->getLx() - 2)*(1<<PADN),
Shinya Kitaoka 120a6e
    //  0 <= kMinX
Shinya Kitaoka 120a6e
    //    <= kMin
Shinya Kitaoka 120a6e
    //    <= k
Shinya Kitaoka 120a6e
    //    <= kMax
Shinya Kitaoka 120a6e
    //    <= kMaxX
Shinya Kitaoka 120a6e
    //    <= (xMax - xMin)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  0 <= yL0 + k*deltaYL
Shinya Kitaoka 120a6e
    //    <= (up->getLy() - 2)*(1<<PADN),
Shinya Kitaoka 120a6e
    //  0 <= kMinY
Shinya Kitaoka 120a6e
    //    <= kMin
Shinya Kitaoka 120a6e
    //    <= k
Shinya Kitaoka 120a6e
    //    <= kMax
Shinya Kitaoka 120a6e
    //    <= kMaxY
Shinya Kitaoka 120a6e
    //    <= (xMax - xMin)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  xL0 inizializzato
Shinya Kitaoka 120a6e
    int xL0 = tround(a.x * (1 << PADN));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  yL0 inizializzato
Shinya Kitaoka 120a6e
    int yL0 = tround(a.y * (1 << PADN));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  calcola kMinX, kMaxX, kMinY, kMaxY
Shinya Kitaoka 120a6e
    int kMinX = 0, kMaxX = xMax - xMin;  //  clipping su dn
Shinya Kitaoka 120a6e
    int kMinY = 0, kMaxY = xMax - xMin;  //  clipping su dn
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  0 <= xL0 + k*deltaXL <= (up->getLx() - 2)*(1<<PADN)
Shinya Kitaoka 120a6e
    //             <=>
Shinya Kitaoka 120a6e
    //  0 <= xL0 + k*deltaXL <= lxPred
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  0 <= yL0 + k*deltaYL <= (up->getLy() - 2)*(1<<PADN)
Shinya Kitaoka 120a6e
    //             <=>
Shinya Kitaoka 120a6e
    //  0 <= yL0 + k*deltaYL <= lyPred
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  calcola kMinX, kMaxX
Shinya Kitaoka 120a6e
    if (deltaXL == 0) {
Shinya Kitaoka 120a6e
      //  [a, b] verticale esterno ad up contratto
Shinya Kitaoka 120a6e
      if ((xL0 < 0) || (lxPred < xL0)) continue;
Shinya Kitaoka 120a6e
      //  altrimenti usa solo
Shinya Kitaoka 120a6e
      //  kMinY, kMaxY ((deltaXL != 0) || (deltaYL != 0))
Shinya Kitaoka 120a6e
    } else if (deltaXL > 0) {
Shinya Kitaoka 120a6e
      //  [a, b] esterno ad up+(bordo destro)
Shinya Kitaoka 120a6e
      if (lxPred < xL0) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      kMaxX = (lxPred - xL0) / deltaXL;  //  floor
Shinya Kitaoka 120a6e
      if (xL0 < 0) {
Shinya Kitaoka 120a6e
        kMinX = ((-xL0) + deltaXL - 1) / deltaXL;  //  ceil
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else  //  (deltaXL < 0)
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      //  [a, b] esterno ad up contratto
Shinya Kitaoka 120a6e
      if (xL0 < 0) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      kMaxX = xL0 / (-deltaXL);  //  floor
Shinya Kitaoka 120a6e
      if (lxPred < xL0) {
Shinya Kitaoka 120a6e
        kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL);  //  ceil
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  calcola kMinY, kMaxY
Shinya Kitaoka 120a6e
    if (deltaYL == 0) {
Shinya Kitaoka 120a6e
      // [a, b] orizzontale esterno ad up contratto
Shinya Kitaoka 120a6e
      if ((yL0 < 0) || (lyPred < yL0)) continue;
Shinya Kitaoka 120a6e
      //  altrimenti usa solo
Shinya Kitaoka 120a6e
      //  kMinX, kMaxX ((deltaXL != 0) || (deltaYL != 0))
Shinya Kitaoka 120a6e
    } else if (deltaYL > 0) {
Shinya Kitaoka 120a6e
      //  [a, b] esterno ad up contratto
Shinya Kitaoka 120a6e
      if (lyPred < yL0) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      kMaxY = (lyPred - yL0) / deltaYL;  //  floor
Shinya Kitaoka 120a6e
      if (yL0 < 0) {
Shinya Kitaoka 120a6e
        kMinY = ((-yL0) + deltaYL - 1) / deltaYL;  //  ceil
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else  //  (deltaYL < 0)
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      //  [a, b] esterno ad up contratto
Shinya Kitaoka 120a6e
      if (yL0 < 0) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      kMaxY = yL0 / (-deltaYL);  //  floor
Shinya Kitaoka 120a6e
      if (lyPred < yL0) {
Shinya Kitaoka 120a6e
        kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL);  //  ceil
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  calcola kMin, kMax effettuando anche il clippind su dn
Shinya Kitaoka 120a6e
    int kMin = std::max({kMinX, kMinY, (int)0});
Shinya Kitaoka 120a6e
    int kMax = std::min({kMaxX, kMaxY, xMax - xMin});
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TPixel32 *dnPix    = dnRow + xMin + kMin;
Shinya Kitaoka 120a6e
    TPixel32 *dnEndPix = dnRow + xMin + kMax + 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  (xL, yL) sono le coordinate (inizializzate per il round)
Shinya Kitaoka 120a6e
    //  in versione "longhizzata" del pixel corrente di up
Shinya Kitaoka 120a6e
    int xL = xL0 + (kMin - 1) * deltaXL;  //  inizializza xL
Shinya Kitaoka 120a6e
    int yL = yL0 + (kMin - 1) * deltaYL;  //  inizializza yL
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  scorre i pixel sulla y-esima scanline di boundingBoxD
Shinya Kitaoka 120a6e
    for (; dnPix < dnEndPix; ++dnPix) {
Shinya Kitaoka 120a6e
      xL += deltaXL;
Shinya Kitaoka 120a6e
      yL += deltaYL;
Shinya Kitaoka 120a6e
      //  il punto di up TPointD(xL/(1<
Shinya Kitaoka 120a6e
      //  approssimato con (xI, yI)
Shinya Kitaoka 120a6e
      int xI = xL >> PADN;  //	troncato
Shinya Kitaoka 120a6e
      int yI = yL >> PADN;  //	troncato
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      assert((0 <= xI) && (xI <= up->getLx() - 1) && (0 <= yI) &&
Shinya Kitaoka 120a6e
             (yI <= up->getLy() - 1));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      //  (xI, yI)
Shinya Kitaoka 120a6e
      TPixel32 *upPix00 = upBasePix + (yI * upWrap + xI);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      //  (xI + 1, yI)
Shinya Kitaoka 120a6e
      TPixel32 *upPix10 = upPix00 + 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      //  (xI, yI + 1)
Shinya Kitaoka 120a6e
      TPixel32 *upPix01 = upPix00 + upWrap;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      //  (xI + 1, yI + 1)
Shinya Kitaoka 120a6e
      TPixel32 *upPix11 = upPix00 + upWrap + 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      //  filtro bilineare 4 pixels: calcolo dei pesi
Shinya Kitaoka 120a6e
      int xWeight1 = (xL & MASKN);
Shinya Kitaoka 120a6e
      int xWeight0 = (1 << PADN) - xWeight1;
Shinya Kitaoka 120a6e
      int yWeight1 = (yL & MASKN);
Shinya Kitaoka 120a6e
      int yWeight0 = (1 << PADN) - yWeight1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      //  filtro bilineare 4 pixels: media pesata sui singoli canali
Shinya Kitaoka 120a6e
      int rColDownTmp =
Shinya Kitaoka 120a6e
          (xWeight0 * (upPix00->r) + xWeight1 * ((upPix10)->r)) >> PADN;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      int gColDownTmp =
Shinya Kitaoka 120a6e
          (xWeight0 * (upPix00->g) + xWeight1 * ((upPix10)->g)) >> PADN;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      int bColDownTmp =
Shinya Kitaoka 120a6e
          (xWeight0 * (upPix00->b) + xWeight1 * ((upPix10)->b)) >> PADN;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      int mColDownTmp =
Shinya Kitaoka 120a6e
          (xWeight0 * (upPix00->m) + xWeight1 * ((upPix10)->m)) >> PADN;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      int rColUpTmp =
Shinya Kitaoka 120a6e
          (xWeight0 * ((upPix01)->r) + xWeight1 * ((upPix11)->r)) >> PADN;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      int gColUpTmp =
Shinya Kitaoka 120a6e
          (xWeight0 * ((upPix01)->g) + xWeight1 * ((upPix11)->g)) >> PADN;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      int bColUpTmp =
Shinya Kitaoka 120a6e
          (xWeight0 * ((upPix01)->b) + xWeight1 * ((upPix11)->b)) >> PADN;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      int mColUpTmp =
Shinya Kitaoka 120a6e
          (xWeight0 * ((upPix01)->m) + xWeight1 * ((upPix11)->m)) >> PADN;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      dnPix->r =
Shinya Kitaoka 120a6e
          (unsigned char)((yWeight0 * rColDownTmp + yWeight1 * rColUpTmp) >>
Shinya Kitaoka 120a6e
                          PADN);
Shinya Kitaoka 120a6e
      dnPix->g =
Shinya Kitaoka 120a6e
          (unsigned char)((yWeight0 * gColDownTmp + yWeight1 * gColUpTmp) >>
Shinya Kitaoka 120a6e
                          PADN);
Shinya Kitaoka 120a6e
      dnPix->b =
Shinya Kitaoka 120a6e
          (unsigned char)((yWeight0 * bColDownTmp + yWeight1 * bColUpTmp) >>
Shinya Kitaoka 120a6e
                          PADN);
Shinya Kitaoka 120a6e
      dnPix->m =
Shinya Kitaoka 120a6e
          (unsigned char)((yWeight0 * mColDownTmp + yWeight1 * mColUpTmp) >>
Shinya Kitaoka 120a6e
                          PADN);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  dn->unlock();
Shinya Kitaoka 120a6e
  up->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void doQuickResampleFilter(const TRaster32P &dn, const TRasterGR8P &up,
Shinya Kitaoka 120a6e
                           const TAffine &aff) {
Shinya Kitaoka 120a6e
  if ((aff.a11 * aff.a22 - aff.a12 * aff.a21) == 0) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  const int PADN = 16;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  const int MASKN = (1 << PADN) - 1;
Shinya Kitaoka 120a6e
  assert(std::max(up->getLx(), up->getLy()) <
Shinya Kitaoka 120a6e
         (1 << (8 * sizeof(int) - PADN - 1)));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRectD boundingBoxD = TRectD(convert(dn->getSize())) *
Shinya Kitaoka 120a6e
                        (aff * TRectD(0, 0, up->getLx() - 2, up->getLy() - 2));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping
Shinya Kitaoka 120a6e
  if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1)
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int yMin = std::max(tfloor(boundingBoxD.y0), 0);
Shinya Kitaoka 120a6e
  int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1);
Shinya Kitaoka 120a6e
  int xMin = std::max(tfloor(boundingBoxD.x0), 0);
Shinya Kitaoka 120a6e
  int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TAffine invAff = inv(aff);  //  inversa di aff
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double deltaXD = invAff.a11;
Shinya Kitaoka 120a6e
  double deltaYD = invAff.a21;
Shinya Kitaoka 120a6e
  int deltaXL    = tround(deltaXD * (1 << PADN));
Shinya Kitaoka 120a6e
  int deltaYL    = tround(deltaYD * (1 << PADN));
Shinya Kitaoka 120a6e
  if ((deltaXL == 0) && (deltaYL == 0)) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int lxPred = (up->getLx() - 2) * (1 << PADN);
Shinya Kitaoka 120a6e
  int lyPred = (up->getLy() - 2) * (1 << PADN);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int dnWrap = dn->getWrap();
Shinya Kitaoka 120a6e
  int upWrap = up->getWrap();
Shinya Kitaoka 120a6e
  dn->lock();
Shinya Kitaoka 120a6e
  up->lock();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TPixel32 *dnRow      = dn->pixels(yMin);
Shinya Kitaoka 120a6e
  TPixelGR8 *upBasePix = up->pixels();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (int y = yMin; y <= yMax; y++, dnRow += dnWrap) {
Shinya Kitaoka 120a6e
    TPointD a = invAff * TPointD(xMin, y);
Shinya Kitaoka 120a6e
    int xL0   = tround(a.x * (1 << PADN));
Shinya Kitaoka 120a6e
    int yL0   = tround(a.y * (1 << PADN));
Shinya Kitaoka 120a6e
    int kMinX = 0, kMaxX = xMax - xMin;  //  clipping su dn
Shinya Kitaoka 120a6e
    int kMinY = 0, kMaxY = xMax - xMin;  //  clipping su dn
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (deltaXL == 0) {
Shinya Kitaoka 120a6e
      if ((xL0 < 0) || (lxPred < xL0)) continue;
Shinya Kitaoka 120a6e
    } else if (deltaXL > 0) {
Shinya Kitaoka 120a6e
      if (lxPred < xL0) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      kMaxX = (lxPred - xL0) / deltaXL;  //  floor
Shinya Kitaoka 120a6e
      if (xL0 < 0) {
Shinya Kitaoka 120a6e
        kMinX = ((-xL0) + deltaXL - 1) / deltaXL;  //  ceil
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      if (xL0 < 0) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      kMaxX = xL0 / (-deltaXL);  //  floor
Shinya Kitaoka 120a6e
      if (lxPred < xL0) {
Shinya Kitaoka 120a6e
        kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL);  //  ceil
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (deltaYL == 0) {
Shinya Kitaoka 120a6e
      if ((yL0 < 0) || (lyPred < yL0)) continue;
Shinya Kitaoka 120a6e
    } else if (deltaYL > 0) {
Shinya Kitaoka 120a6e
      if (lyPred < yL0) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      kMaxY = (lyPred - yL0) / deltaYL;  //  floor
Shinya Kitaoka 120a6e
      if (yL0 < 0) {
Shinya Kitaoka 120a6e
        kMinY = ((-yL0) + deltaYL - 1) / deltaYL;  //  ceil
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else  //  (deltaYL < 0)
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      if (yL0 < 0) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      kMaxY = yL0 / (-deltaYL);  //  floor
Shinya Kitaoka 120a6e
      if (lyPred < yL0) {
Shinya Kitaoka 120a6e
        kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL);  //  ceil
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    int kMin = std::max({kMinX, kMinY, (int)0});
Shinya Kitaoka 120a6e
    int kMax = std::min({kMaxX, kMaxY, xMax - xMin});
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TPixel32 *dnPix    = dnRow + xMin + kMin;
Shinya Kitaoka 120a6e
    TPixel32 *dnEndPix = dnRow + xMin + kMax + 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    int xL = xL0 + (kMin - 1) * deltaXL;  //  inizializza xL
Shinya Kitaoka 120a6e
    int yL = yL0 + (kMin - 1) * deltaYL;  //  inizializza yL
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    for (; dnPix < dnEndPix; ++dnPix) {
Shinya Kitaoka 120a6e
      xL += deltaXL;
Shinya Kitaoka 120a6e
      yL += deltaYL;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      int xI = xL >> PADN;  //	troncato
Shinya Kitaoka 120a6e
      int yI = yL >> PADN;  //	troncato
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      assert((0 <= xI) && (xI <= up->getLx() - 1) && (0 <= yI) &&
Shinya Kitaoka 120a6e
             (yI <= up->getLy() - 1));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      //  (xI, yI)
Shinya Kitaoka 120a6e
      TPixelGR8 *upPix00 = upBasePix + (yI * upWrap + xI);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      //  (xI + 1, yI)
Shinya Kitaoka 120a6e
      TPixelGR8 *upPix10 = upPix00 + 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      //  (xI, yI + 1)
Shinya Kitaoka 120a6e
      TPixelGR8 *upPix01 = upPix00 + upWrap;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      //  (xI + 1, yI + 1)
Shinya Kitaoka 120a6e
      TPixelGR8 *upPix11 = upPix00 + upWrap + 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      //  filtro bilineare 4 pixels: calcolo dei pesi
Shinya Kitaoka 120a6e
      int xWeight1 = (xL & MASKN);
Shinya Kitaoka 120a6e
      int xWeight0 = (1 << PADN) - xWeight1;
Shinya Kitaoka 120a6e
      int yWeight1 = (yL & MASKN);
Shinya Kitaoka 120a6e
      int yWeight0 = (1 << PADN) - yWeight1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      //  filtro bilineare 4 pixels: media pesata sui singoli canali
Shinya Kitaoka 120a6e
      int colDownTmp =
Shinya Kitaoka 120a6e
          (xWeight0 * (upPix00->value) + xWeight1 * ((upPix10)->value)) >> PADN;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      int colUpTmp =
Shinya Kitaoka 120a6e
          (xWeight0 * ((upPix01)->value) + xWeight1 * ((upPix11)->value)) >>
Shinya Kitaoka 120a6e
          PADN;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      dnPix->r = dnPix->g = dnPix->b =
Shinya Kitaoka 120a6e
          (unsigned char)((yWeight0 * colDownTmp + yWeight1 * colUpTmp) >>
Shinya Kitaoka 120a6e
                          PADN);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      dnPix->m = 255;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  dn->unlock();
Shinya Kitaoka 120a6e
  up->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void doQuickResampleColorFilter(const TRaster32P &dn, const TRaster32P &up,
Shinya Kitaoka 120a6e
                                const TAffine &aff, UCHAR colorMask) {
Shinya Kitaoka 120a6e
  if ((aff.a11 * aff.a22 - aff.a12 * aff.a21) == 0) return;
Shinya Kitaoka 120a6e
  const int PADN = 16;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  assert(std::max(up->getLx(), up->getLy()) <
Shinya Kitaoka 120a6e
         (1 << (8 * sizeof(int) - PADN - 1)));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRectD boundingBoxD =
Shinya Kitaoka 120a6e
      TRectD(convert(dn->getBounds())) *
Shinya Kitaoka 120a6e
      (aff * TRectD(-0.5, -0.5, up->getLx() - 0.5, up->getLy() - 0.5));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1)
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int yMin = std::max(tfloor(boundingBoxD.y0), 0);  //  clipping y su dn
Shinya Kitaoka 120a6e
  int yMax =
Shinya Kitaoka 120a6e
      std::min(tceil(boundingBoxD.y1), dn->getLy() - 1);  //  clipping y su dn
Shinya Kitaoka 120a6e
  int xMin = std::max(tfloor(boundingBoxD.x0), 0);        //  clipping x su dn
Shinya Kitaoka 120a6e
  int xMax =
Shinya Kitaoka 120a6e
      std::min(tceil(boundingBoxD.x1), dn->getLx() - 1);  //  clipping x su dn
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TAffine invAff = inv(aff);  //  inversa di aff
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double deltaXD = invAff.a11;
Shinya Kitaoka 120a6e
  double deltaYD = invAff.a21;
Shinya Kitaoka 120a6e
  int deltaXL =
Shinya Kitaoka 120a6e
      tround(deltaXD * (1 << PADN));  //  deltaXD "TLonghizzato" (round)
Shinya Kitaoka 120a6e
  int deltaYL =
Shinya Kitaoka 120a6e
      tround(deltaYD * (1 << PADN));  //  deltaYD "TLonghizzato" (round)
Shinya Kitaoka 120a6e
  if ((deltaXL == 0) && (deltaYL == 0)) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int lxPred =
Shinya Kitaoka 120a6e
      up->getLx() * (1 << PADN) - 1;  //  TINT32 predecessore di up->getLx()
Shinya Kitaoka 120a6e
  int lyPred =
Shinya Kitaoka 120a6e
      up->getLy() * (1 << PADN) - 1;  //  TINT32 predecessore di up->getLy()
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int dnWrap = dn->getWrap();
Shinya Kitaoka 120a6e
  int upWrap = up->getWrap();
Shinya Kitaoka 120a6e
  dn->lock();
Shinya Kitaoka 120a6e
  up->lock();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TPixel32 *dnRow     = dn->pixels(yMin);
Shinya Kitaoka 120a6e
  TPixel32 *upBasePix = up->pixels();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (int y = yMin; y <= yMax; y++, dnRow += dnWrap) {
Shinya Kitaoka 120a6e
    TPointD a = invAff * TPointD(xMin, y);
Shinya Kitaoka 120a6e
    int xL0   = tround((a.x + 0.5) * (1 << PADN));
Shinya Kitaoka 120a6e
    int yL0   = tround((a.y + 0.5) * (1 << PADN));
Shinya Kitaoka 120a6e
    int kMinX = 0, kMaxX = xMax - xMin;  //  clipping su dn
Shinya Kitaoka 120a6e
    int kMinY = 0, kMaxY = xMax - xMin;  //  clipping su dn
Shinya Kitaoka 120a6e
    if (deltaXL == 0) {
Shinya Kitaoka 120a6e
      if ((xL0 < 0) || (lxPred < xL0)) continue;
Shinya Kitaoka 120a6e
    } else if (deltaXL > 0) {
Shinya Kitaoka 120a6e
      if (lxPred < xL0) continue;
Shinya Kitaoka 120a6e
shun-iwasawa 84ffc5
      kMaxX = (lxPred - xL0) / deltaXL;                       //  floor
Shinya Kitaoka 120a6e
      if (xL0 < 0) kMinX = ((-xL0) + deltaXL - 1) / deltaXL;  //  ceil
Shinya Kitaoka 120a6e
    } else                                                    //  (deltaXL < 0)
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      if (xL0 < 0) continue;
Shinya Kitaoka 120a6e
      kMaxX = xL0 / (-deltaXL);  //  floor
Shinya Kitaoka 120a6e
      if (lxPred < xL0)
Shinya Kitaoka 120a6e
        kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL);  //  ceil
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    if (deltaYL == 0) {
Shinya Kitaoka 120a6e
      if ((yL0 < 0) || (lyPred < yL0)) continue;
Shinya Kitaoka 120a6e
    } else if (deltaYL > 0) {
Shinya Kitaoka 120a6e
      if (lyPred < yL0) continue;
Shinya Kitaoka 120a6e
shun-iwasawa 84ffc5
      kMaxY = (lyPred - yL0) / deltaYL;                       //  floor
Shinya Kitaoka 120a6e
      if (yL0 < 0) kMinY = ((-yL0) + deltaYL - 1) / deltaYL;  //  ceil
Shinya Kitaoka 120a6e
    } else                                                    //  (deltaYL < 0)
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      if (yL0 < 0) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      kMaxY = yL0 / (-deltaYL);  //  floor
Shinya Kitaoka 120a6e
      if (lyPred < yL0)
Shinya Kitaoka 120a6e
        kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL);  //  ceil
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    int kMin           = std::max({kMinX, kMinY, (int)0});
Shinya Kitaoka 120a6e
    int kMax           = std::min({kMaxX, kMaxY, xMax - xMin});
Shinya Kitaoka 120a6e
    TPixel32 *dnPix    = dnRow + xMin + kMin;
Shinya Kitaoka 120a6e
    TPixel32 *dnEndPix = dnRow + xMin + kMax + 1;
Shinya Kitaoka 120a6e
    int xL             = xL0 + (kMin - 1) * deltaXL;  //  inizializza xL
Shinya Kitaoka 120a6e
    int yL             = yL0 + (kMin - 1) * deltaYL;  //  inizializza yL
Shinya Kitaoka 120a6e
    for (; dnPix < dnEndPix; ++dnPix) {
Shinya Kitaoka 120a6e
      xL += deltaXL;
Shinya Kitaoka 120a6e
      yL += deltaYL;
Shinya Kitaoka 120a6e
      int xI = xL >> PADN;  //  round
Shinya Kitaoka 120a6e
      int yI = yL >> PADN;  //  round
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      assert((0 <= xI) && (xI <= up->getLx() - 1) && (0 <= yI) &&
Shinya Kitaoka 120a6e
             (yI <= up->getLy() - 1));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (colorMask == TRop::MChan)
Shinya Kitaoka 120a6e
        dnPix->r = dnPix->g = dnPix->b = (upBasePix + (yI * upWrap + xI))->m;
Shinya Kitaoka 120a6e
      else {
Shinya Kitaoka 120a6e
        TPixel32 *pix = upBasePix + (yI * upWrap + xI);
Shinya Kitaoka 120a6e
        dnPix->r      = ((colorMask & TRop::RChan) ? pix->r : 0);
Shinya Kitaoka 120a6e
        dnPix->g      = ((colorMask & TRop::GChan) ? pix->g : 0);
Shinya Kitaoka 120a6e
        dnPix->b      = ((colorMask & TRop::BChan) ? pix->b : 0);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      dnPix->m = 255;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  dn->unlock();
Shinya Kitaoka 120a6e
  up->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void doQuickResampleColorFilter(const TRaster32P &dn, const TRaster64P &up,
Shinya Kitaoka 120a6e
                                const TAffine &aff, UCHAR colorMask) {
Shinya Kitaoka 120a6e
  if ((aff.a11 * aff.a22 - aff.a12 * aff.a21) == 0) return;
Shinya Kitaoka 120a6e
  const int PADN = 16;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  assert(std::max(up->getLx(), up->getLy()) <
Shinya Kitaoka 120a6e
         (1 << (8 * sizeof(int) - PADN - 1)));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRectD boundingBoxD =
Shinya Kitaoka 120a6e
      TRectD(convert(dn->getBounds())) *
Shinya Kitaoka 120a6e
      (aff * TRectD(-0.5, -0.5, up->getLx() - 0.5, up->getLy() - 0.5));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1)
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int yMin = std::max(tfloor(boundingBoxD.y0), 0);  //  clipping y su dn
Shinya Kitaoka 120a6e
  int yMax =
Shinya Kitaoka 120a6e
      std::min(tceil(boundingBoxD.y1), dn->getLy() - 1);  //  clipping y su dn
Shinya Kitaoka 120a6e
  int xMin = std::max(tfloor(boundingBoxD.x0), 0);        //  clipping x su dn
Shinya Kitaoka 120a6e
  int xMax =
Shinya Kitaoka 120a6e
      std::min(tceil(boundingBoxD.x1), dn->getLx() - 1);  //  clipping x su dn
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TAffine invAff = inv(aff);  //  inversa di aff
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double deltaXD = invAff.a11;
Shinya Kitaoka 120a6e
  double deltaYD = invAff.a21;
Shinya Kitaoka 120a6e
  int deltaXL =
Shinya Kitaoka 120a6e
      tround(deltaXD * (1 << PADN));  //  deltaXD "TLonghizzato" (round)
Shinya Kitaoka 120a6e
  int deltaYL =
Shinya Kitaoka 120a6e
      tround(deltaYD * (1 << PADN));  //  deltaYD "TLonghizzato" (round)
Shinya Kitaoka 120a6e
  if ((deltaXL == 0) && (deltaYL == 0)) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int lxPred =
Shinya Kitaoka 120a6e
      up->getLx() * (1 << PADN) - 1;  //  TINT32 predecessore di up->getLx()
Shinya Kitaoka 120a6e
  int lyPred =
Shinya Kitaoka 120a6e
      up->getLy() * (1 << PADN) - 1;  //  TINT32 predecessore di up->getLy()
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int dnWrap = dn->getWrap();
Shinya Kitaoka 120a6e
  int upWrap = up->getWrap();
Shinya Kitaoka 120a6e
  dn->lock();
Shinya Kitaoka 120a6e
  up->lock();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TPixel32 *dnRow     = dn->pixels(yMin);
Shinya Kitaoka 120a6e
  TPixel64 *upBasePix = up->pixels();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (int y = yMin; y <= yMax; y++, dnRow += dnWrap) {
Shinya Kitaoka 120a6e
    TPointD a = invAff * TPointD(xMin, y);
Shinya Kitaoka 120a6e
    int xL0   = tround((a.x + 0.5) * (1 << PADN));
Shinya Kitaoka 120a6e
    int yL0   = tround((a.y + 0.5) * (1 << PADN));
Shinya Kitaoka 120a6e
    int kMinX = 0, kMaxX = xMax - xMin;  //  clipping su dn
Shinya Kitaoka 120a6e
    int kMinY = 0, kMaxY = xMax - xMin;  //  clipping su dn
Shinya Kitaoka 120a6e
    if (deltaXL == 0) {
Shinya Kitaoka 120a6e
      if ((xL0 < 0) || (lxPred < xL0)) continue;
Shinya Kitaoka 120a6e
    } else if (deltaXL > 0) {
Shinya Kitaoka 120a6e
      if (lxPred < xL0) continue;
Shinya Kitaoka 120a6e
shun-iwasawa 84ffc5
      kMaxX = (lxPred - xL0) / deltaXL;                       //  floor
Shinya Kitaoka 120a6e
      if (xL0 < 0) kMinX = ((-xL0) + deltaXL - 1) / deltaXL;  //  ceil
Shinya Kitaoka 120a6e
    } else                                                    //  (deltaXL < 0)
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      if (xL0 < 0) continue;
Shinya Kitaoka 120a6e
      kMaxX = xL0 / (-deltaXL);  //  floor
Shinya Kitaoka 120a6e
      if (lxPred < xL0)
Shinya Kitaoka 120a6e
        kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL);  //  ceil
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    if (deltaYL == 0) {
Shinya Kitaoka 120a6e
      if ((yL0 < 0) || (lyPred < yL0)) continue;
Shinya Kitaoka 120a6e
    } else if (deltaYL > 0) {
Shinya Kitaoka 120a6e
      if (lyPred < yL0) continue;
Shinya Kitaoka 120a6e
shun-iwasawa 84ffc5
      kMaxY = (lyPred - yL0) / deltaYL;                       //  floor
Shinya Kitaoka 120a6e
      if (yL0 < 0) kMinY = ((-yL0) + deltaYL - 1) / deltaYL;  //  ceil
Shinya Kitaoka 120a6e
    } else                                                    //  (deltaYL < 0)
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      if (yL0 < 0) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      kMaxY = yL0 / (-deltaYL);  //  floor
Shinya Kitaoka 120a6e
      if (lyPred < yL0)
Shinya Kitaoka 120a6e
        kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL);  //  ceil
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    int kMin           = std::max({kMinX, kMinY, (int)0});
Shinya Kitaoka 120a6e
    int kMax           = std::min({kMaxX, kMaxY, xMax - xMin});
Shinya Kitaoka 120a6e
    TPixel32 *dnPix    = dnRow + xMin + kMin;
Shinya Kitaoka 120a6e
    TPixel32 *dnEndPix = dnRow + xMin + kMax + 1;
Shinya Kitaoka 120a6e
    int xL             = xL0 + (kMin - 1) * deltaXL;  //  inizializza xL
Shinya Kitaoka 120a6e
    int yL             = yL0 + (kMin - 1) * deltaYL;  //  inizializza yL
Shinya Kitaoka 120a6e
    for (; dnPix < dnEndPix; ++dnPix) {
Shinya Kitaoka 120a6e
      xL += deltaXL;
Shinya Kitaoka 120a6e
      yL += deltaYL;
Shinya Kitaoka 120a6e
      int xI = xL >> PADN;  //  round
Shinya Kitaoka 120a6e
      int yI = yL >> PADN;  //  round
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      assert((0 <= xI) && (xI <= up->getLx() - 1) && (0 <= yI) &&
Shinya Kitaoka 120a6e
             (yI <= up->getLy() - 1));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (colorMask == TRop::MChan)
Shinya Kitaoka 120a6e
        dnPix->r = dnPix->g = dnPix->b =
Shinya Kitaoka 120a6e
            byteFromUshort((upBasePix + (yI * upWrap + xI))->m);
Shinya Kitaoka 120a6e
      else {
Shinya Kitaoka 120a6e
        TPixel64 *pix = upBasePix + (yI * upWrap + xI);
Shinya Kitaoka 120a6e
        dnPix->r = byteFromUshort(((colorMask & TRop::RChan) ? pix->r : 0));
Shinya Kitaoka 120a6e
        dnPix->g = byteFromUshort(((colorMask & TRop::GChan) ? pix->g : 0));
Shinya Kitaoka 120a6e
        dnPix->b = byteFromUshort(((colorMask & TRop::BChan) ? pix->b : 0));
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      dnPix->m = 255;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  dn->unlock();
Shinya Kitaoka 120a6e
  up->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void doQuickResampleFilter(const TRaster32P &dn, const TRaster32P &up,
Shinya Kitaoka 120a6e
                           double sx, double sy, double tx, double ty) {
Shinya Kitaoka 120a6e
  //  se aff := TAffine(sx, 0, tx, 0, sy, ty) e' degenere la controimmagine
Shinya Kitaoka 120a6e
  //  di up e' un segmento (o un punto)
Shinya Kitaoka 120a6e
  if ((sx == 0) || (sy == 0)) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //  contatore bit di shift
Shinya Kitaoka 120a6e
  const int PADN = 16;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //  maschera del filtro bilineare
Shinya Kitaoka 120a6e
  const int MASKN = (1 << PADN) - 1;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //  max dimensioni di up gestibili (limite imposto dal numero di bit
Shinya Kitaoka 120a6e
  // disponibili per la parte intera di xL, yL)
Shinya Kitaoka 120a6e
  assert(std::max(up->getLx(), up->getLy()) <
Shinya Kitaoka 120a6e
         (1 << (8 * sizeof(int) - PADN - 1)));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TAffine aff(sx, 0, tx, 0, sy, ty);
Shinya Kitaoka 120a6e
  TRectD boundingBoxD =
Shinya Kitaoka 120a6e
      TRectD(convert(dn->getSize())) *
Shinya Kitaoka 120a6e
      (aff * TRectD(0, 0, up->getLx() - /*1*/ 2, up->getLy() - /*1*/ 2));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping
Shinya Kitaoka 120a6e
  if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1)
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping y su dn
Shinya Kitaoka 120a6e
  int yMin = std::max(tfloor(boundingBoxD.y0), 0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping y su dn
Shinya Kitaoka 120a6e
  int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping x su dn
Shinya Kitaoka 120a6e
  int xMin = std::max(tfloor(boundingBoxD.x0), 0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping x su dn
Shinya Kitaoka 120a6e
  int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  inversa di aff
Shinya Kitaoka 120a6e
  TAffine invAff = inv(aff);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  nello scorrere le scanline di boundingBoxD, il passaggio alla scanline
Shinya Kitaoka 120a6e
  //  successiva comporta l'incremento (0, deltaYD) delle coordinate dei
Shinya Kitaoka 120a6e
  //  pixels corrispondenti di up
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  nel disegnare la y-esima scanline di dn, il passaggio al pixel
Shinya Kitaoka 120a6e
  //  successivo comporta l'incremento (deltaXD, 0) delle coordinate del
Shinya Kitaoka 120a6e
  //  pixel corrispondente di up
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double deltaXD = invAff.a11;
Shinya Kitaoka 120a6e
  double deltaYD = invAff.a22;
Shinya Kitaoka 120a6e
  int deltaXL =
Shinya Kitaoka 120a6e
      tround(deltaXD * (1 << PADN));  //  deltaXD "TLonghizzato" (round)
Shinya Kitaoka 120a6e
  int deltaYL =
Shinya Kitaoka 120a6e
      tround(deltaYD * (1 << PADN));  //  deltaYD "TLonghizzato" (round)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  se aff "TLonghizzata" (round) e' degenere la controimmagine di up e'
Shinya Kitaoka 120a6e
  //  un segmento (o un punto)
Shinya Kitaoka 120a6e
  if ((deltaXL == 0) || (deltaYL == 0)) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  (1)  equazione (kX, kY)-parametrica di boundingBoxD:
Shinya Kitaoka 120a6e
  //         (xMin, yMin) + kX*(1, 0) + kY*(0, 1),
Shinya Kitaoka 120a6e
  //           kX = 0, ..., (xMax - xMin),
Shinya Kitaoka 120a6e
  //           kY = 0, ..., (yMax - yMin)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  (2)  equazione (kX, kY)-parametrica dell'immagine mediante invAff di (1):
Shinya Kitaoka 120a6e
  //         invAff*(xMin, yMin) + kX*(deltaXD, 0) + kY*(0, deltaYD),
Shinya Kitaoka 120a6e
  //           kX = kMinX, ..., kMaxX
Shinya Kitaoka 120a6e
  //             con 0 <= kMinX <= kMaxX <= (xMax - xMin)
Shinya Kitaoka 120a6e
  //
Shinya Kitaoka 120a6e
  //           kY = kMinY, ..., kMaxY
Shinya Kitaoka 120a6e
  //             con 0 <= kMinY <= kMaxY <= (yMax - yMin)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  calcola kMinX, kMaxX, kMinY, kMaxY intersecando la (2) con i lati di up
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  il segmento [a, b] di up (con gli estremi eventualmente invertiti) e'
Shinya Kitaoka 120a6e
  //  la controimmagine mediante aff della porzione di scanline
Shinya Kitaoka 120a6e
  //  [ (xMin, yMin), (xMax, yMin) ] di dn
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  TPointD b = invAff*TPointD(xMax, yMin);
Shinya Kitaoka 120a6e
  TPointD a = invAff * TPointD(xMin, yMin);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  (xL0, yL0) sono le coordinate di a (inizializzate per il round)
Shinya Kitaoka 120a6e
  //  in versione "TLonghizzata"
Shinya Kitaoka 120a6e
  //  0 <= xL0 + kX*deltaXL <= (up->getLx() - 2)*(1<<PADN),
Shinya Kitaoka 120a6e
  //  0 <= kMinX <= kX <= kMaxX <= (xMax - xMin)
Shinya Kitaoka 120a6e
  //  0 <= yL0 + kY*deltaYL <= (up->getLy() - 2)*(1<<PADN),
Shinya Kitaoka 120a6e
  //  0 <= kMinY <= kY <= kMaxY <= (yMax - yMin)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int xL0 = tround(a.x * (1 << PADN));  //  xL0 inizializzato
Shinya Kitaoka 120a6e
  int yL0 = tround(a.y * (1 << PADN));  //  yL0 inizializzato
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  calcola kMinY, kMaxY, kMinX, kMaxX intersecando la (2) con i lati di up
Shinya Kitaoka 120a6e
  int kMinX = 0, kMaxX = xMax - xMin;  //  clipping su dn
Shinya Kitaoka 120a6e
  int kMinY = 0, kMaxY = yMax - yMin;  //  clipping su dn
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  TINT32 predecessore di (up->getLx() - 1)
Shinya Kitaoka 120a6e
  int lxPred = (up->getLx() - /*1*/ 2) * (1 << PADN);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  TINT32 predecessore di (up->getLy() - 1)
Shinya Kitaoka 120a6e
  int lyPred = (up->getLy() - /*1*/ 2) * (1 << PADN);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  0 <= xL0 + k*deltaXL <= (up->getLx() - 2)*(1<<PADN)
Shinya Kitaoka 120a6e
  //               <=>
Shinya Kitaoka 120a6e
  //  0 <= xL0 + k*deltaXL <= lxPred
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  0 <= yL0 + k*deltaYL <= (up->getLy() - 2)*(1<<PADN)
Shinya Kitaoka 120a6e
  //               <=>
Shinya Kitaoka 120a6e
  //  0 <= yL0 + k*deltaYL <= lyPred
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  calcola kMinY, kMaxY intersecando la (2) con i lati
Shinya Kitaoka 120a6e
  //  (y = yMin) e (y = yMax) di up
Shinya Kitaoka 120a6e
  if (deltaYL > 0)  //  (deltaYL != 0)
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    //  [a, b] interno ad up contratto
Shinya Kitaoka 120a6e
    assert(yL0 <= lyPred);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    kMaxY = (lyPred - yL0) / deltaYL;  //  floor
Shinya Kitaoka 120a6e
    if (yL0 < 0) {
Shinya Kitaoka 120a6e
      kMinY = ((-yL0) + deltaYL - 1) / deltaYL;  //  ceil
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else  //  (deltaYL < 0)
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    //  [a, b] interno ad up contratto
Shinya Kitaoka 120a6e
    assert(0 <= yL0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    kMaxY = yL0 / (-deltaYL);  //  floor
Shinya Kitaoka 120a6e
    if (lyPred < yL0) {
Shinya Kitaoka 120a6e
      kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL);  //  ceil
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  //  calcola kMinY, kMaxY effettuando anche il clippind su dn
Shinya Kitaoka 120a6e
  kMinY = std::max(kMinY, (int)0);
Shinya Kitaoka 120a6e
  kMaxY = std::min(kMaxY, yMax - yMin);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  calcola kMinX, kMaxX intersecando la (2) con i lati
Shinya Kitaoka 120a6e
  //  (x = xMin) e (x = xMax) di up
Shinya Kitaoka 120a6e
  if (deltaXL > 0)  //  (deltaXL != 0)
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    //  [a, b] interno ad up contratto
Shinya Kitaoka 120a6e
    assert(xL0 <= lxPred);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    kMaxX = (lxPred - xL0) / deltaXL;  //  floor
Shinya Kitaoka 120a6e
    if (xL0 < 0) {
Shinya Kitaoka 120a6e
      kMinX = ((-xL0) + deltaXL - 1) / deltaXL;  //  ceil
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else  //  (deltaXL < 0)
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    //  [a, b] interno ad up contratto
Shinya Kitaoka 120a6e
    assert(0 <= xL0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    kMaxX = xL0 / (-deltaXL);  //  floor
Shinya Kitaoka 120a6e
    if (lxPred < xL0) {
Shinya Kitaoka 120a6e
      kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL);  //  ceil
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  //  calcola kMinX, kMaxX effettuando anche il clippind su dn
Shinya Kitaoka 120a6e
  kMinX = std::max(kMinX, (int)0);
Shinya Kitaoka 120a6e
  kMaxX = std::min(kMaxX, xMax - xMin);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int dnWrap = dn->getWrap();
Shinya Kitaoka 120a6e
  int upWrap = up->getWrap();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  dn->lock();
Shinya Kitaoka 120a6e
  up->lock();
Shinya Kitaoka 120a6e
  TPixel32 *upBasePix = up->pixels();
Shinya Kitaoka 120a6e
  TPixel32 *dnRow     = dn->pixels(yMin + kMinY);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  (xL, yL) sono le coordinate (inizializzate per il round)
Shinya Kitaoka 120a6e
  //  in versione "TLonghizzata"
Shinya Kitaoka 120a6e
  //  del pixel corrente di up
Shinya Kitaoka 120a6e
  int yL = yL0 + (kMinY - 1) * deltaYL;  //  inizializza yL
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  scorre le scanline di boundingBoxD
Shinya Kitaoka 120a6e
  for (int kY = kMinY; kY <= kMaxY; kY++, dnRow += dnWrap) {
Shinya Kitaoka 120a6e
    int xL = xL0 + (kMinX - 1) * deltaXL;  //  inizializza xL
Shinya Kitaoka 120a6e
    yL += deltaYL;
Shinya Kitaoka 120a6e
    //  il punto di up TPointD(xL/(1<
Shinya Kitaoka 120a6e
    //  con (xI, yI)
Shinya Kitaoka 120a6e
    int yI = yL >> PADN;  //  troncato
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  filtro bilineare 4 pixels: calcolo degli y-pesi
Shinya Kitaoka 120a6e
    int yWeight1 = (yL & MASKN);
Shinya Kitaoka 120a6e
    int yWeight0 = (1 << PADN) - yWeight1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TPixel32 *dnPix    = dnRow + xMin + kMinX;
Shinya Kitaoka 120a6e
    TPixel32 *dnEndPix = dnRow + xMin + kMaxX + 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  scorre i pixel sulla (yMin + kY)-esima scanline di dn
Shinya Kitaoka 120a6e
    for (; dnPix < dnEndPix; ++dnPix) {
Shinya Kitaoka 120a6e
      xL += deltaXL;
Shinya Kitaoka 120a6e
      //  il punto di up TPointD(xL/(1<
Shinya Kitaoka 120a6e
      //  approssimato con (xI, yI)
Shinya Kitaoka 120a6e
      int xI = xL >> PADN;  //  troncato
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      assert((0 <= xI) && (xI <= up->getLx() - 1) && (0 <= yI) &&
Shinya Kitaoka 120a6e
             (yI <= up->getLy() - 1));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      //  (xI, yI)
Shinya Kitaoka 120a6e
      TPixel32 *upPix00 = upBasePix + (yI * upWrap + xI);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      //  (xI + 1, yI)
Shinya Kitaoka 120a6e
      TPixel32 *upPix10 = upPix00 + 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      //  (xI, yI + 1)
Shinya Kitaoka 120a6e
      TPixel32 *upPix01 = upPix00 + upWrap;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      //  (xI + 1, yI + 1)
Shinya Kitaoka 120a6e
      TPixel32 *upPix11 = upPix00 + upWrap + 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      //  filtro bilineare 4 pixels: calcolo degli x-pesi
Shinya Kitaoka 120a6e
      int xWeight1 = (xL & MASKN);
Shinya Kitaoka 120a6e
      int xWeight0 = (1 << PADN) - xWeight1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      //  filtro bilineare 4 pixels: media pesata sui singoli canali
Shinya Kitaoka 120a6e
      int rColDownTmp =
Shinya Kitaoka 120a6e
          (xWeight0 * (upPix00->r) + xWeight1 * ((upPix10)->r)) >> PADN;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      int gColDownTmp =
Shinya Kitaoka 120a6e
          (xWeight0 * (upPix00->g) + xWeight1 * ((upPix10)->g)) >> PADN;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      int bColDownTmp =
Shinya Kitaoka 120a6e
          (xWeight0 * (upPix00->b) + xWeight1 * ((upPix10)->b)) >> PADN;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      int mColDownTmp =
Shinya Kitaoka 120a6e
          (xWeight0 * (upPix00->m) + xWeight1 * ((upPix10)->m)) >> PADN;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      int rColUpTmp =
Shinya Kitaoka 120a6e
          (xWeight0 * ((upPix01)->r) + xWeight1 * ((upPix11)->r)) >> PADN;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      int gColUpTmp =
Shinya Kitaoka 120a6e
          (xWeight0 * ((upPix01)->g) + xWeight1 * ((upPix11)->g)) >> PADN;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      int bColUpTmp =
Shinya Kitaoka 120a6e
          (xWeight0 * ((upPix01)->b) + xWeight1 * ((upPix11)->b)) >> PADN;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      int mColUpTmp =
Shinya Kitaoka 120a6e
          (xWeight0 * ((upPix01)->m) + xWeight1 * ((upPix11)->m)) >> PADN;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      dnPix->r =
Shinya Kitaoka 120a6e
          (unsigned char)((yWeight0 * rColDownTmp + yWeight1 * rColUpTmp) >>
Shinya Kitaoka 120a6e
                          PADN);
Shinya Kitaoka 120a6e
      dnPix->g =
Shinya Kitaoka 120a6e
          (unsigned char)((yWeight0 * gColDownTmp + yWeight1 * gColUpTmp) >>
Shinya Kitaoka 120a6e
                          PADN);
Shinya Kitaoka 120a6e
      dnPix->b =
Shinya Kitaoka 120a6e
          (unsigned char)((yWeight0 * bColDownTmp + yWeight1 * bColUpTmp) >>
Shinya Kitaoka 120a6e
                          PADN);
Shinya Kitaoka 120a6e
      dnPix->m =
Shinya Kitaoka 120a6e
          (unsigned char)((yWeight0 * mColDownTmp + yWeight1 * mColUpTmp) >>
Shinya Kitaoka 120a6e
                          PADN);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  dn->unlock();
Shinya Kitaoka 120a6e
  up->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void doQuickResampleFilter(const TRaster32P &dn, const TRasterGR8P &up,
Shinya Kitaoka 120a6e
                           double sx, double sy, double tx, double ty) {
Shinya Kitaoka 120a6e
  //  se aff := TAffine(sx, 0, tx, 0, sy, ty) e' degenere la controimmagine
Shinya Kitaoka 120a6e
  //  di up e' un segmento (o un punto)
Shinya Kitaoka 120a6e
  if ((sx == 0) || (sy == 0)) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //  contatore bit di shift
Shinya Kitaoka 120a6e
  const int PADN = 16;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //  maschera del filtro bilineare
Shinya Kitaoka 120a6e
  const int MASKN = (1 << PADN) - 1;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //  max dimensioni di up gestibili (limite imposto dal numero di bit
Shinya Kitaoka 120a6e
  // disponibili per la parte intera di xL, yL)
Shinya Kitaoka 120a6e
  assert(std::max(up->getLx(), up->getLy()) <
Shinya Kitaoka 120a6e
         (1 << (8 * sizeof(int) - PADN - 1)));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TAffine aff(sx, 0, tx, 0, sy, ty);
Shinya Kitaoka 120a6e
  TRectD boundingBoxD =
Shinya Kitaoka 120a6e
      TRectD(convert(dn->getSize())) *
Shinya Kitaoka 120a6e
      (aff * TRectD(0, 0, up->getLx() - /*1*/ 2, up->getLy() - /*1*/ 2));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping
Shinya Kitaoka 120a6e
  if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1)
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping y su dn
Shinya Kitaoka 120a6e
  int yMin = std::max(tfloor(boundingBoxD.y0), 0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping y su dn
Shinya Kitaoka 120a6e
  int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping x su dn
Shinya Kitaoka 120a6e
  int xMin = std::max(tfloor(boundingBoxD.x0), 0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping x su dn
Shinya Kitaoka 120a6e
  int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  inversa di aff
Shinya Kitaoka 120a6e
  TAffine invAff = inv(aff);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  nello scorrere le scanline di boundingBoxD, il passaggio alla scanline
Shinya Kitaoka 120a6e
  //  successiva comporta l'incremento (0, deltaYD) delle coordinate dei
Shinya Kitaoka 120a6e
  //  pixels corrispondenti di up
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  nel disegnare la y-esima scanline di dn, il passaggio al pixel
Shinya Kitaoka 120a6e
  //  successivo comporta l'incremento (deltaXD, 0) delle coordinate del
Shinya Kitaoka 120a6e
  //  pixel corrispondente di up
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double deltaXD = invAff.a11;
Shinya Kitaoka 120a6e
  double deltaYD = invAff.a22;
Shinya Kitaoka 120a6e
  int deltaXL =
Shinya Kitaoka 120a6e
      tround(deltaXD * (1 << PADN));  //  deltaXD "TLonghizzato" (round)
Shinya Kitaoka 120a6e
  int deltaYL =
Shinya Kitaoka 120a6e
      tround(deltaYD * (1 << PADN));  //  deltaYD "TLonghizzato" (round)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  se aff "TLonghizzata" (round) e' degenere la controimmagine di up e'
Shinya Kitaoka 120a6e
  //  un segmento (o un punto)
Shinya Kitaoka 120a6e
  if ((deltaXL == 0) || (deltaYL == 0)) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  (1)  equazione (kX, kY)-parametrica di boundingBoxD:
Shinya Kitaoka 120a6e
  //         (xMin, yMin) + kX*(1, 0) + kY*(0, 1),
Shinya Kitaoka 120a6e
  //           kX = 0, ..., (xMax - xMin),
Shinya Kitaoka 120a6e
  //           kY = 0, ..., (yMax - yMin)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  (2)  equazione (kX, kY)-parametrica dell'immagine mediante invAff di (1):
Shinya Kitaoka 120a6e
  //         invAff*(xMin, yMin) + kX*(deltaXD, 0) + kY*(0, deltaYD),
Shinya Kitaoka 120a6e
  //           kX = kMinX, ..., kMaxX
Shinya Kitaoka 120a6e
  //             con 0 <= kMinX <= kMaxX <= (xMax - xMin)
Shinya Kitaoka 120a6e
  //
Shinya Kitaoka 120a6e
  //           kY = kMinY, ..., kMaxY
Shinya Kitaoka 120a6e
  //             con 0 <= kMinY <= kMaxY <= (yMax - yMin)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  calcola kMinX, kMaxX, kMinY, kMaxY intersecando la (2) con i lati di up
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  il segmento [a, b] di up (con gli estremi eventualmente invertiti) e'
Shinya Kitaoka 120a6e
  //  la controimmagine mediante aff della porzione di scanline
Shinya Kitaoka 120a6e
  //  [ (xMin, yMin), (xMax, yMin) ] di dn
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  TPointD b = invAff*TPointD(xMax, yMin);
Shinya Kitaoka 120a6e
  TPointD a = invAff * TPointD(xMin, yMin);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  (xL0, yL0) sono le coordinate di a (inizializzate per il round)
Shinya Kitaoka 120a6e
  //  in versione "TLonghizzata"
Shinya Kitaoka 120a6e
  //  0 <= xL0 + kX*deltaXL <= (up->getLx() - 2)*(1<<PADN),
Shinya Kitaoka 120a6e
  //  0 <= kMinX <= kX <= kMaxX <= (xMax - xMin)
Shinya Kitaoka 120a6e
  //  0 <= yL0 + kY*deltaYL <= (up->getLy() - 2)*(1<<PADN),
Shinya Kitaoka 120a6e
  //  0 <= kMinY <= kY <= kMaxY <= (yMax - yMin)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int xL0 = tround(a.x * (1 << PADN));  //  xL0 inizializzato
Shinya Kitaoka 120a6e
  int yL0 = tround(a.y * (1 << PADN));  //  yL0 inizializzato
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  calcola kMinY, kMaxY, kMinX, kMaxX intersecando la (2) con i lati di up
Shinya Kitaoka 120a6e
  int kMinX = 0, kMaxX = xMax - xMin;  //  clipping su dn
Shinya Kitaoka 120a6e
  int kMinY = 0, kMaxY = yMax - yMin;  //  clipping su dn
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  TINT32 predecessore di (up->getLx() - 1)
Shinya Kitaoka 120a6e
  int lxPred = (up->getLx() - /*1*/ 2) * (1 << PADN);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  TINT32 predecessore di (up->getLy() - 1)
Shinya Kitaoka 120a6e
  int lyPred = (up->getLy() - /*1*/ 2) * (1 << PADN);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  0 <= xL0 + k*deltaXL <= (up->getLx() - 2)*(1<<PADN)
Shinya Kitaoka 120a6e
  //               <=>
Shinya Kitaoka 120a6e
  //  0 <= xL0 + k*deltaXL <= lxPred
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  0 <= yL0 + k*deltaYL <= (up->getLy() - 2)*(1<<PADN)
Shinya Kitaoka 120a6e
  //               <=>
Shinya Kitaoka 120a6e
  //  0 <= yL0 + k*deltaYL <= lyPred
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  calcola kMinY, kMaxY intersecando la (2) con i lati
Shinya Kitaoka 120a6e
  //  (y = yMin) e (y = yMax) di up
Shinya Kitaoka 120a6e
  if (deltaYL > 0)  //  (deltaYL != 0)
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    //  [a, b] interno ad up contratto
Shinya Kitaoka 120a6e
    assert(yL0 <= lyPred);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    kMaxY = (lyPred - yL0) / deltaYL;  //  floor
Shinya Kitaoka 120a6e
    if (yL0 < 0) {
Shinya Kitaoka 120a6e
      kMinY = ((-yL0) + deltaYL - 1) / deltaYL;  //  ceil
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else  //  (deltaYL < 0)
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    //  [a, b] interno ad up contratto
Shinya Kitaoka 120a6e
    assert(0 <= yL0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    kMaxY = yL0 / (-deltaYL);  //  floor
Shinya Kitaoka 120a6e
    if (lyPred < yL0) {
Shinya Kitaoka 120a6e
      kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL);  //  ceil
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  //  calcola kMinY, kMaxY effettuando anche il clippind su dn
Shinya Kitaoka 120a6e
  kMinY = std::max(kMinY, (int)0);
Shinya Kitaoka 120a6e
  kMaxY = std::min(kMaxY, yMax - yMin);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  calcola kMinX, kMaxX intersecando la (2) con i lati
Shinya Kitaoka 120a6e
  //  (x = xMin) e (x = xMax) di up
Shinya Kitaoka 120a6e
  if (deltaXL > 0)  //  (deltaXL != 0)
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    //  [a, b] interno ad up contratto
Shinya Kitaoka 120a6e
    assert(xL0 <= lxPred);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    kMaxX = (lxPred - xL0) / deltaXL;  //  floor
Shinya Kitaoka 120a6e
    if (xL0 < 0) {
Shinya Kitaoka 120a6e
      kMinX = ((-xL0) + deltaXL - 1) / deltaXL;  //  ceil
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else  //  (deltaXL < 0)
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    //  [a, b] interno ad up contratto
Shinya Kitaoka 120a6e
    assert(0 <= xL0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    kMaxX = xL0 / (-deltaXL);  //  floor
Shinya Kitaoka 120a6e
    if (lxPred < xL0) {
Shinya Kitaoka 120a6e
      kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL);  //  ceil
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  //  calcola kMinX, kMaxX effettuando anche il clippind su dn
Shinya Kitaoka 120a6e
  kMinX = std::max(kMinX, (int)0);
Shinya Kitaoka 120a6e
  kMaxX = std::min(kMaxX, xMax - xMin);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int dnWrap = dn->getWrap();
Shinya Kitaoka 120a6e
  int upWrap = up->getWrap();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  dn->lock();
Shinya Kitaoka 120a6e
  up->lock();
Shinya Kitaoka 120a6e
  TPixelGR8 *upBasePix = up->pixels();
Shinya Kitaoka 120a6e
  TPixel32 *dnRow      = dn->pixels(yMin + kMinY);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  (xL, yL) sono le coordinate (inizializzate per il round)
Shinya Kitaoka 120a6e
  //  in versione "TLonghizzata"
Shinya Kitaoka 120a6e
  //  del pixel corrente di up
Shinya Kitaoka 120a6e
  int yL = yL0 + (kMinY - 1) * deltaYL;  //  inizializza yL
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  scorre le scanline di boundingBoxD
Shinya Kitaoka 120a6e
  for (int kY = kMinY; kY <= kMaxY; kY++, dnRow += dnWrap) {
Shinya Kitaoka 120a6e
    int xL = xL0 + (kMinX - 1) * deltaXL;  //  inizializza xL
Shinya Kitaoka 120a6e
    yL += deltaYL;
Shinya Kitaoka 120a6e
    //  il punto di up TPointD(xL/(1<
Shinya Kitaoka 120a6e
    //  con (xI, yI)
Shinya Kitaoka 120a6e
    int yI = yL >> PADN;  //  troncato
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  filtro bilineare 4 pixels: calcolo degli y-pesi
Shinya Kitaoka 120a6e
    int yWeight1 = (yL & MASKN);
Shinya Kitaoka 120a6e
    int yWeight0 = (1 << PADN) - yWeight1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TPixel32 *dnPix    = dnRow + xMin + kMinX;
Shinya Kitaoka 120a6e
    TPixel32 *dnEndPix = dnRow + xMin + kMaxX + 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  scorre i pixel sulla (yMin + kY)-esima scanline di dn
Shinya Kitaoka 120a6e
    for (; dnPix < dnEndPix; ++dnPix) {
Shinya Kitaoka 120a6e
      xL += deltaXL;
Shinya Kitaoka 120a6e
      //  il punto di up TPointD(xL/(1<
Shinya Kitaoka 120a6e
      //  approssimato con (xI, yI)
Shinya Kitaoka 120a6e
      int xI = xL >> PADN;  //  troncato
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      assert((0 <= xI) && (xI <= up->getLx() - 1) && (0 <= yI) &&
Shinya Kitaoka 120a6e
             (yI <= up->getLy() - 1));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      //  (xI, yI)
Shinya Kitaoka 120a6e
      TPixelGR8 *upPix00 = upBasePix + (yI * upWrap + xI);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      //  (xI + 1, yI)
Shinya Kitaoka 120a6e
      TPixelGR8 *upPix10 = upPix00 + 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      //  (xI, yI + 1)
Shinya Kitaoka 120a6e
      TPixelGR8 *upPix01 = upPix00 + upWrap;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      //  (xI + 1, yI + 1)
Shinya Kitaoka 120a6e
      TPixelGR8 *upPix11 = upPix00 + upWrap + 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      //  filtro bilineare 4 pixels: calcolo degli x-pesi
Shinya Kitaoka 120a6e
      int xWeight1 = (xL & MASKN);
Shinya Kitaoka 120a6e
      int xWeight0 = (1 << PADN) - xWeight1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      //  filtro bilineare 4 pixels: media pesata sui singoli canali
Shinya Kitaoka 120a6e
      int colDownTmp =
Shinya Kitaoka 120a6e
          (xWeight0 * (upPix00->value) + xWeight1 * (upPix10->value)) >> PADN;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      int colUpTmp =
Shinya Kitaoka 120a6e
          (xWeight0 * ((upPix01)->value) + xWeight1 * (upPix11->value)) >> PADN;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      dnPix->m = 255;
Shinya Kitaoka 120a6e
      dnPix->r = dnPix->g = dnPix->b =
Shinya Kitaoka 120a6e
          (unsigned char)((yWeight0 * colDownTmp + yWeight1 * colUpTmp) >>
Shinya Kitaoka 120a6e
                          PADN);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  dn->unlock();
Shinya Kitaoka 120a6e
  up->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
template <typename PIX>
Shinya Kitaoka 120a6e
void doQuickResampleNoFilter(const TRasterPT<PIX> &dn, const TRasterPT<PIX> &up,
Shinya Kitaoka 120a6e
                             double sx, double sy, double tx, double ty) {
Shinya Kitaoka 120a6e
  //  se aff := TAffine(sx, 0, tx, 0, sy, ty) e' degenere la controimmagine
Shinya Kitaoka 120a6e
  //  di up e' un segmento (o un punto)
Shinya Kitaoka 120a6e
  if ((sx == 0) || (sy == 0)) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  contatore bit di shift
Shinya Kitaoka 120a6e
  const int PADN = 16;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  max dimensioni di up gestibili (limite imposto dal numero di bit
Shinya Kitaoka 120a6e
  //  disponibili per la parte intera di xL, yL)
Shinya Kitaoka 120a6e
  assert(std::max(up->getLx(), up->getLy()) <
Shinya Kitaoka 120a6e
         (1 << (8 * sizeof(int) - PADN - 1)));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TAffine aff(sx, 0, tx, 0, sy, ty);
Shinya Kitaoka 120a6e
  TRectD boundingBoxD =
Shinya Kitaoka 120a6e
      TRectD(convert(dn->getBounds())) *
Shinya Kitaoka 120a6e
      (aff * TRectD(-0.5, -0.5, up->getLx() - 0.5, up->getLy() - 0.5));
Shinya Kitaoka 120a6e
  //  clipping
Shinya Kitaoka 120a6e
  if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1)
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping y su dn
Shinya Kitaoka 120a6e
  int yMin = std::max(tfloor(boundingBoxD.y0), 0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping y su dn
Shinya Kitaoka 120a6e
  int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping x su dn
Shinya Kitaoka 120a6e
  int xMin = std::max(tfloor(boundingBoxD.x0), 0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping x su dn
Shinya Kitaoka 120a6e
  int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TAffine invAff = inv(aff);  //  inversa di aff
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  nello scorrere le scanline di boundingBoxD, il passaggio alla scanline
Shinya Kitaoka 120a6e
  //  successiva comporta l'incremento (0, deltaYD) delle coordinate dei
Shinya Kitaoka 120a6e
  //  pixels corrispondenti di up
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  nel disegnare la y-esima scanline di dn, il passaggio al pixel
Shinya Kitaoka 120a6e
  //  successivo comporta l'incremento (deltaXD, 0) delle coordinate del
Shinya Kitaoka 120a6e
  //  pixel corrispondente di up
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double deltaXD = invAff.a11;
Shinya Kitaoka 120a6e
  double deltaYD = invAff.a22;
Shinya Kitaoka 120a6e
  int deltaXL =
Shinya Kitaoka 120a6e
      tround(deltaXD * (1 << PADN));  //  deltaXD "TLonghizzato" (round)
Shinya Kitaoka 120a6e
  int deltaYL =
Shinya Kitaoka 120a6e
      tround(deltaYD * (1 << PADN));  //  deltaYD "TLonghizzato" (round)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  se aff "TLonghizzata" (round) e' degenere la controimmagine di up e' un
Shinya Kitaoka 120a6e
  //  segmento (o un punto)
Shinya Kitaoka 120a6e
  if ((deltaXL == 0) || (deltaYL == 0)) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  (1)  equazione (kX, kY)-parametrica di boundingBoxD:
Shinya Kitaoka 120a6e
  //         (xMin, yMin) + kX*(1, 0) + kY*(0, 1),
Shinya Kitaoka 120a6e
  //           kX = 0, ..., (xMax - xMin),
Shinya Kitaoka 120a6e
  //           kY = 0, ..., (yMax - yMin)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  (2)  equazione (kX, kY)-parametrica dell'immagine mediante invAff di (1):
Shinya Kitaoka 120a6e
  //         invAff*(xMin, yMin) + kX*(deltaXD, 0) + kY*(0, deltaYD),
Shinya Kitaoka 120a6e
  //           kX = kMinX, ..., kMaxX
Shinya Kitaoka 120a6e
  //             con 0 <= kMinX <= kMaxX <= (xMax - xMin)
Shinya Kitaoka 120a6e
  //           kY = kMinY, ..., kMaxY
Shinya Kitaoka 120a6e
  //             con 0 <= kMinY <= kMaxY <= (yMax - yMin)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  calcola kMinX, kMaxX, kMinY, kMaxY intersecando la (2) con i lati di up
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  il segmento [a, b] di up e' la controimmagine mediante aff della
Shinya Kitaoka 120a6e
  //  porzione di scanline  [ (xMin, yMin), (xMax, yMin) ] di dn
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  TPointD b = invAff*TPointD(xMax, yMin);
Shinya Kitaoka 120a6e
  TPointD a = invAff * TPointD(xMin, yMin);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  (xL0, yL0) sono le coordinate di a (inizializzate per il round)
Shinya Kitaoka 120a6e
  //  in versione "TLonghizzata"
Shinya Kitaoka 120a6e
  //  0 <= xL0 + kX*deltaXL < up->getLx()*(1<<PADN),
Shinya Kitaoka 120a6e
  //  0 <= kMinX <= kX <= kMaxX <= (xMax - xMin)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  0 <= yL0 + kY*deltaYL < up->getLy()*(1<<PADN),
Shinya Kitaoka 120a6e
  //  0 <= kMinY <= kY <= kMaxY <= (yMax - yMin)
Shinya Kitaoka 120a6e
  int xL0 =
Shinya Kitaoka 120a6e
      tround((a.x + 0.5) * (1 << PADN));  //  xL0 inizializzato per il round
Shinya Kitaoka 120a6e
  int yL0 =
Shinya Kitaoka 120a6e
      tround((a.y + 0.5) * (1 << PADN));  //  yL0 inizializzato per il round
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  calcola kMinY, kMaxY, kMinX, kMaxX intersecando la (2) con i lati di up
Shinya Kitaoka 120a6e
  int kMinX = 0, kMaxX = xMax - xMin;  //  clipping su dn
Shinya Kitaoka 120a6e
  int kMinY = 0, kMaxY = yMax - yMin;  //  clipping su dn
Shinya Kitaoka 120a6e
  int lxPred =
Shinya Kitaoka 120a6e
      up->getLx() * (1 << PADN) - 1;  //  TINT32 predecessore di up->getLx()
Shinya Kitaoka 120a6e
  int lyPred =
Shinya Kitaoka 120a6e
      up->getLy() * (1 << PADN) - 1;  //  TINT32 predecessore di up->getLy()
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  0 <= xL0 + k*deltaXL < up->getLx()*(1<<PADN)
Shinya Kitaoka 120a6e
  //                  <=>
Shinya Kitaoka 120a6e
  //  0 <= xL0 + k*deltaXL <= lxPred
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  0 <= yL0 + k*deltaYL < up->getLy()*(1<<PADN)
Shinya Kitaoka 120a6e
  //                  <=>
Shinya Kitaoka 120a6e
  //  0 <= yL0 + k*deltaYL <= lyPred
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  calcola kMinY, kMaxY  intersecando la (2) con i lati
Shinya Kitaoka 120a6e
  //  (y = yMin) e (y = yMax) di up
Shinya Kitaoka 120a6e
  if (deltaYL > 0)  //  (deltaYL != 0)
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    assert(yL0 <= lyPred);  //  [a, b] interno ad up+(bordo destro/basso)
Shinya Kitaoka 120a6e
    kMaxY = (lyPred - yL0) / deltaYL;  //  floor
Shinya Kitaoka 120a6e
    if (yL0 < 0) {
Shinya Kitaoka 120a6e
      kMinY = ((-yL0) + deltaYL - 1) / deltaYL;  //  ceil
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else  //  (deltaYL < 0)
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    //  [a, b] interno ad up+(bordo destro/basso)
Shinya Kitaoka 120a6e
    assert(0 <= yL0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    kMaxY = yL0 / (-deltaYL);  //  floor
Shinya Kitaoka 120a6e
    if (lyPred < yL0) {
Shinya Kitaoka 120a6e
      kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL);  //  ceil
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  //	calcola kMinY, kMaxY effettuando anche il clippind su dn
Shinya Kitaoka 120a6e
  kMinY = std::max(kMinY, (int)0);
Shinya Kitaoka 120a6e
  kMaxY = std::min(kMaxY, yMax - yMin);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  calcola kMinX, kMaxX  intersecando la (2) con i lati
Shinya Kitaoka 120a6e
  //  (x = xMin) e (x = xMax) di up
Shinya Kitaoka 120a6e
  if (deltaXL > 0)  //  (deltaXL != 0)
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    //  [a, b] interno ad up+(bordo destro/basso)
Shinya Kitaoka 120a6e
    assert(xL0 <= lxPred);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    kMaxX = (lxPred - xL0) / deltaXL;  //  floor
Shinya Kitaoka 120a6e
    if (xL0 < 0) {
Shinya Kitaoka 120a6e
      kMinX = ((-xL0) + deltaXL - 1) / deltaXL;  //  ceil
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else  //  (deltaXL < 0)
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    //  [a, b] interno ad up+(bordo destro/basso)
Shinya Kitaoka 120a6e
    assert(0 <= xL0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    kMaxX = xL0 / (-deltaXL);  //  floor
Shinya Kitaoka 120a6e
    if (lxPred < xL0) {
Shinya Kitaoka 120a6e
      kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL);  //  ceil
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  //  calcola kMinX, kMaxX effettuando anche il clippind su dn
Shinya Kitaoka 120a6e
  kMinX = std::max(kMinX, (int)0);
Shinya Kitaoka 120a6e
  kMaxX = std::min(kMaxX, xMax - xMin);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int dnWrap = dn->getWrap();
Shinya Kitaoka 120a6e
  int upWrap = up->getWrap();
Shinya Kitaoka 120a6e
  dn->lock();
Shinya Kitaoka 120a6e
  up->lock();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  PIX *upBasePix = up->pixels();
Shinya Kitaoka 120a6e
  PIX *dnRow     = dn->pixels(yMin + kMinY);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  (xL, yL) sono le coordinate (inizializzate per il round)
Shinya Kitaoka 120a6e
  //  in versione "TLonghizzata" del pixel corrente di up
Shinya Kitaoka 120a6e
  int yL = yL0 + (kMinY - 1) * deltaYL;  //  inizializza yL
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  scorre le scanline di boundingBoxD
Shinya Kitaoka 120a6e
  for (int kY = kMinY; kY <= kMaxY; kY++, dnRow += dnWrap) {
Shinya Kitaoka 120a6e
    int xL = xL0 + (kMinX - 1) * deltaXL;  //  inizializza xL
Shinya Kitaoka 120a6e
    yL += deltaYL;
Shinya Kitaoka 120a6e
    //  il punto di up TPointD(xL/(1<
Shinya Kitaoka 120a6e
    //  con (xI, yI)
Shinya Kitaoka 120a6e
    int yI = yL >> PADN;  //  round
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    PIX *dnPix    = dnRow + xMin + kMinX;
Shinya Kitaoka 120a6e
    PIX *dnEndPix = dnRow + xMin + kMaxX + 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  scorre i pixel sulla (yMin + kY)-esima scanline di dn
Shinya Kitaoka 120a6e
    for (; dnPix < dnEndPix; ++dnPix) {
Shinya Kitaoka 120a6e
      xL += deltaXL;
Shinya Kitaoka 120a6e
      //  il punto di up TPointD(xL/(1<
Shinya Kitaoka 120a6e
      //  approssimato con (xI, yI)
Shinya Kitaoka 120a6e
      int xI = xL >> PADN;  //  round
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      assert((0 <= xI) && (xI <= up->getLx() - 1) && (0 <= yI) &&
Shinya Kitaoka 120a6e
             (yI <= up->getLy() - 1));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      *dnPix = *(upBasePix + (yI * upWrap + xI));
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  dn->unlock();
Shinya Kitaoka 120a6e
  up->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifndef TNZCORE_LIGHT
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
// doQuickPutCmapped
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void doQuickPutCmapped(const TRaster32P &dn, const TRasterCM32P &up,
Shinya Kitaoka 120a6e
                       const TPaletteP &palette, const TAffine &aff,
Shinya Kitaoka 120a6e
                       const TPixel32 &globalColorScale, bool inksOnly) {
Shinya Kitaoka 120a6e
  //  se aff := TAffine(sx, 0, tx, 0, sy, ty) e' degenere la controimmagine
Shinya Kitaoka 120a6e
  //  di up e' un segmento (o un punto)
Shinya Kitaoka 120a6e
  if ((aff.a11 * aff.a22 - aff.a12 * aff.a21) == 0) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //  contatore bit di shift
Shinya Kitaoka 120a6e
  const int PADN = 16;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //  max dimensioni di up gestibili (limite imposto dal numero di bit
Shinya Kitaoka 120a6e
  //  disponibili per la parte intera di xL, yL)
Shinya Kitaoka 120a6e
  assert(std::max(up->getLx(), up->getLy()) <
Shinya Kitaoka 120a6e
         (1 << (8 * sizeof(int) - PADN - 1)));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRectD boundingBoxD =
Shinya Kitaoka 120a6e
      TRectD(convert(dn->getBounds())) *
Shinya Kitaoka 120a6e
      (aff * TRectD(-0.5, -0.5, up->getLx() - 0.5, up->getLy() - 0.5));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping
Shinya Kitaoka 120a6e
  if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1)
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping y su dn
Shinya Kitaoka 120a6e
  int yMin = std::max(tfloor(boundingBoxD.y0), 0);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //  clipping y su dn
Shinya Kitaoka 120a6e
  int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping x su dn
Shinya Kitaoka 120a6e
  int xMin = std::max(tfloor(boundingBoxD.x0), 0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping x su dn
Shinya Kitaoka 120a6e
  int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  inversa di aff
Shinya Kitaoka 120a6e
  TAffine invAff = inv(aff);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  nel disegnare la y-esima scanline di dn, il passaggio al pixel
Shinya Kitaoka 120a6e
  //  successivo comporta l'incremento (deltaXD, deltaYD) delle coordinate del
Shinya Kitaoka 120a6e
  //  pixel corrispondente di up
Shinya Kitaoka 120a6e
  double deltaXD = invAff.a11;
Shinya Kitaoka 120a6e
  double deltaYD = invAff.a21;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  deltaXD "TLonghizzato" (round)
Shinya Kitaoka 120a6e
  int deltaXL = tround(deltaXD * (1 << PADN));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  deltaYD "TLonghizzato" (round)
Shinya Kitaoka 120a6e
  int deltaYL = tround(deltaYD * (1 << PADN));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  se aff "TLonghizzata" (round) e' degenere la controimmagine di up e' un
Shinya Kitaoka 120a6e
  //  segmento (o un punto)
Shinya Kitaoka 120a6e
  if ((deltaXL == 0) && (deltaYL == 0)) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  TINT32 predecessore di up->getLx()
Shinya Kitaoka 120a6e
  int lxPred = up->getLx() * (1 << PADN) - 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  TINT32 predecessore di up->getLy()
Shinya Kitaoka 120a6e
  int lyPred = up->getLy() * (1 << PADN) - 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int dnWrap = dn->getWrap();
Shinya Kitaoka 120a6e
  int upWrap = up->getWrap();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::vector<TPixel32> colors(palette->getStyleCount());
Shinya Kitaoka 120a6e
  // vector<TPixel32> inks(palette->getStyleCount());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (globalColorScale != TPixel::Black)
shun-iwasawa 84ffc5
    for (int i = 0; i < palette->getStyleCount(); i++)
Shinya Kitaoka 120a6e
      colors[i] = applyColorScaleCMapped(
Shinya Kitaoka 120a6e
          palette->getStyle(i)->getAverageColor(), globalColorScale);
Shinya Kitaoka 120a6e
  else
shun-iwasawa 84ffc5
    for (int i = 0; i < palette->getStyleCount(); i++)
Shinya Kitaoka 120a6e
      colors[i] = ::premultiply(palette->getStyle(i)->getAverageColor());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  dn->lock();
Shinya Kitaoka 120a6e
  up->lock();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TPixel32 *dnRow       = dn->pixels(yMin);
Shinya Kitaoka 120a6e
  TPixelCM32 *upBasePix = up->pixels();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  scorre le scanline di boundingBoxD
Shinya Kitaoka 120a6e
  for (int y = yMin; y <= yMax; y++, dnRow += dnWrap) {
Shinya Kitaoka 120a6e
    //  (1)  equazione k-parametrica della y-esima scanline di boundingBoxD:
Shinya Kitaoka 120a6e
    //       (xMin, y) + k*(1, 0),  k = 0, ..., (xMax - xMin)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  (2)  equazione k-parametrica dell'immagine mediante invAff di (1):
Shinya Kitaoka 120a6e
    //       invAff*(xMin, y) + k*(deltaXD, deltaYD),
Shinya Kitaoka 120a6e
    //       k = kMin, ..., kMax con 0 <= kMin <= kMax <= (xMax - xMin)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  calcola kMin, kMax per la scanline corrente
Shinya Kitaoka 120a6e
    //  intersecando la (2) con i lati di up
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  il segmento [a, b] di up e' la controimmagine mediante aff della
Shinya Kitaoka 120a6e
    //  porzione di scanline  [ (xMin, y), (xMax, y) ] di dn
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  TPointD b = invAff*TPointD(xMax, y);
Shinya Kitaoka 120a6e
    TPointD a = invAff * TPointD(xMin, y);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  (xL0, yL0) sono le coordinate di a (inizializzate per il round)
Shinya Kitaoka 120a6e
    //  in versione "TLonghizzata"
Shinya Kitaoka 120a6e
    //  0 <= xL0 + k*deltaXL
Shinya Kitaoka 120a6e
    //    <  up->getLx()*(1<<PADN)
Shinya Kitaoka 120a6e
    //
Shinya Kitaoka 120a6e
    //  0 <= kMinX
Shinya Kitaoka 120a6e
    //    <= kMin
Shinya Kitaoka 120a6e
    //    <= k
Shinya Kitaoka 120a6e
    //    <= kMax
Shinya Kitaoka 120a6e
    //    <= kMaxX
Shinya Kitaoka 120a6e
    //    <= (xMax - xMin)
Shinya Kitaoka 120a6e
    //
Shinya Kitaoka 120a6e
    //  0 <= yL0 + k*deltaYL
Shinya Kitaoka 120a6e
    //    < up->getLy()*(1<<PADN)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  0 <= kMinY
Shinya Kitaoka 120a6e
    //    <= kMin
Shinya Kitaoka 120a6e
    //    <= k
Shinya Kitaoka 120a6e
    //    <= kMax
Shinya Kitaoka 120a6e
    //    <= kMaxY
Shinya Kitaoka 120a6e
    //    <= (xMax - xMin)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  xL0 inizializzato per il round
Shinya Kitaoka 120a6e
    int xL0 = tround((a.x + 0.5) * (1 << PADN));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  yL0 inizializzato per il round
Shinya Kitaoka 120a6e
    int yL0 = tround((a.y + 0.5) * (1 << PADN));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  calcola kMinX, kMaxX, kMinY, kMaxY
Shinya Kitaoka 120a6e
    int kMinX = 0, kMaxX = xMax - xMin;  //  clipping su dn
Shinya Kitaoka 120a6e
    int kMinY = 0, kMaxY = xMax - xMin;  //  clipping su dn
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  0 <= xL0 + k*deltaXL
Shinya Kitaoka 120a6e
    //    < up->getLx()*(1<<PADN)
Shinya Kitaoka 120a6e
    //           <=>
Shinya Kitaoka 120a6e
    //  0 <= xL0 + k*deltaXL
Shinya Kitaoka 120a6e
    //    <= lxPred
Shinya Kitaoka 120a6e
    //
Shinya Kitaoka 120a6e
    //  0 <= yL0 + k*deltaYL
Shinya Kitaoka 120a6e
    //    < up->getLy()*(1<<PADN)
Shinya Kitaoka 120a6e
    //           <=>
Shinya Kitaoka 120a6e
    //  0 <= yL0 + k*deltaYL
Shinya Kitaoka 120a6e
    //    <= lyPred
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  calcola kMinX, kMaxX
Shinya Kitaoka 120a6e
    if (deltaXL == 0) {
Shinya Kitaoka 120a6e
      // [a, b] verticale esterno ad up+(bordo destro/basso)
Shinya Kitaoka 120a6e
      if ((xL0 < 0) || (lxPred < xL0)) continue;
Shinya Kitaoka 120a6e
      //  altrimenti usa solo
Shinya Kitaoka 120a6e
      //  kMinY, kMaxY ((deltaXL != 0) || (deltaYL != 0))
Shinya Kitaoka 120a6e
    } else if (deltaXL > 0) {
Shinya Kitaoka 120a6e
      //  [a, b] esterno ad up+(bordo destro/basso)
Shinya Kitaoka 120a6e
      if (lxPred < xL0) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      kMaxX = (lxPred - xL0) / deltaXL;  //  floor
Shinya Kitaoka 120a6e
      if (xL0 < 0) {
Shinya Kitaoka 120a6e
        kMinX = ((-xL0) + deltaXL - 1) / deltaXL;  //  ceil
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else  //  (deltaXL < 0)
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      //  [a, b] esterno ad up+(bordo destro/basso)
Shinya Kitaoka 120a6e
      if (xL0 < 0) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      kMaxX = xL0 / (-deltaXL);  //  floor
Shinya Kitaoka 120a6e
      if (lxPred < xL0) {
Shinya Kitaoka 120a6e
        kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL);  //  ceil
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  calcola kMinY, kMaxY
Shinya Kitaoka 120a6e
    if (deltaYL == 0) {
Shinya Kitaoka 120a6e
      //  [a, b] orizzontale esterno ad up+(bordo destro/basso)
Shinya Kitaoka 120a6e
      if ((yL0 < 0) || (lyPred < yL0)) continue;
Shinya Kitaoka 120a6e
      // altrimenti usa solo
Shinya Kitaoka 120a6e
      // kMinX, kMaxX ((deltaXL != 0) || (deltaYL != 0))
Shinya Kitaoka 120a6e
    } else if (deltaYL > 0) {
Shinya Kitaoka 120a6e
      //  [a, b] esterno ad up+(bordo destro/basso)
Shinya Kitaoka 120a6e
      if (lyPred < yL0) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      kMaxY = (lyPred - yL0) / deltaYL;  //  floor
Shinya Kitaoka 120a6e
      if (yL0 < 0) {
Shinya Kitaoka 120a6e
        kMinY = ((-yL0) + deltaYL - 1) / deltaYL;  //  ceil
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else  //  (deltaYL < 0)
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      //  [a, b] esterno ad up+(bordo destro/basso)
Shinya Kitaoka 120a6e
      if (yL0 < 0) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      kMaxY = yL0 / (-deltaYL);  //  floor
Shinya Kitaoka 120a6e
      if (lyPred < yL0) {
Shinya Kitaoka 120a6e
        kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL);  //  ceil
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  calcola kMin, kMax effettuando anche il clippind su dn
Shinya Kitaoka 120a6e
    int kMin = std::max({kMinX, kMinY, (int)0});
Shinya Kitaoka 120a6e
    int kMax = std::min({kMaxX, kMaxY, xMax - xMin});
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TPixel32 *dnPix    = dnRow + xMin + kMin;
Shinya Kitaoka 120a6e
    TPixel32 *dnEndPix = dnRow + xMin + kMax + 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  (xL, yL) sono le coordinate (inizializzate per il round)
Shinya Kitaoka 120a6e
    //  in versione "TLonghizzata" del pixel corrente di up
Shinya Kitaoka 120a6e
    int xL = xL0 + (kMin - 1) * deltaXL;  //  inizializza xL
Shinya Kitaoka 120a6e
    int yL = yL0 + (kMin - 1) * deltaYL;  //  inizializza yL
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  scorre i pixel sulla y-esima scanline di boundingBoxD
Shinya Kitaoka 120a6e
    for (; dnPix < dnEndPix; ++dnPix) {
Shinya Kitaoka 120a6e
      xL += deltaXL;
Shinya Kitaoka 120a6e
      yL += deltaYL;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      //  il punto di up TPointD(xL/(1<
Shinya Kitaoka 120a6e
      //  approssimato con (xI, yI)
Shinya Kitaoka 120a6e
      int xI = xL >> PADN;  //  round
Shinya Kitaoka 120a6e
      int yI = yL >> PADN;  //  round
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      assert((0 <= xI) && (xI <= up->getLx() - 1) && (0 <= yI) &&
Shinya Kitaoka 120a6e
             (yI <= up->getLy() - 1));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      TPixelCM32 *upPix = upBasePix + (yI * upWrap + xI);
Shinya Kitaoka 120a6e
      int t             = upPix->getTone();
Shinya Kitaoka 120a6e
      int p             = upPix->getPaint();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (t == 0xff && p == 0)
Shinya Kitaoka 120a6e
        continue;
Shinya Kitaoka 120a6e
      else {
Shinya Kitaoka 120a6e
        int i = upPix->getInk();
Shinya Kitaoka 120a6e
        TPixel32 colorUp;
Shinya Kitaoka 120a6e
        if (inksOnly) switch (t) {
Shinya Kitaoka 120a6e
          case 0:
Shinya Kitaoka 120a6e
            colorUp = colors[i];
Shinya Kitaoka 120a6e
            break;
Shinya Kitaoka 120a6e
          case 255:
Shinya Kitaoka 120a6e
            colorUp = TPixel::Transparent;
Shinya Kitaoka 120a6e
            break;
Shinya Kitaoka 120a6e
          default:
Shinya Kitaoka 120a6e
            colorUp = antialias(colors[i], 255 - t);
Shinya Kitaoka 120a6e
            break;
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
        else
Shinya Kitaoka 120a6e
          switch (t) {
Shinya Kitaoka 120a6e
          case 0:
Shinya Kitaoka 120a6e
            colorUp = colors[i];
Shinya Kitaoka 120a6e
            break;
Shinya Kitaoka 120a6e
          case 255:
Shinya Kitaoka 120a6e
            colorUp = colors[p];
Shinya Kitaoka 120a6e
            break;
Shinya Kitaoka 120a6e
          default:
Shinya Kitaoka 120a6e
            colorUp = blend(colors[i], colors[p], t, TPixelCM32::getMaxTone());
Shinya Kitaoka 120a6e
            break;
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        if (colorUp.m == 255)
Shinya Kitaoka 120a6e
          *dnPix = colorUp;
Shinya Kitaoka 120a6e
        else if (colorUp.m != 0)
Shinya Kitaoka 120a6e
          *dnPix = quickOverPix(*dnPix, colorUp);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  dn->unlock();
Shinya Kitaoka 120a6e
  up->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
// doQuickPutCmapped + transparencyCheck + inkCheck + paintcheck
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
TPixel TransparencyCheckBlackBgInk = TPixel(255,255,255); //bg
Toshihiro Shimizu 890ddd
TPixel TransparencyCheckWhiteBgInk = TPixel(0,0,0);    //ink
Toshihiro Shimizu 890ddd
TPixel TransparencyCheckPaint = TPixel(127,127,127);  //paint*/
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void doQuickPutCmapped(const TRaster32P &dn, const TRasterCM32P &up,
Shinya Kitaoka 120a6e
                       const TPaletteP &palette, const TAffine &aff,
Shinya Kitaoka 120a6e
                       const TRop::CmappedQuickputSettings &s)
Shinya Kitaoka 120a6e
/*const TPixel32& globalColorScale,
Shinya Kitaoka 120a6e
                 bool inksOnly,
Shinya Kitaoka 120a6e
                 bool transparencyCheck,
Shinya Kitaoka 120a6e
                 bool blackBgCheck,
Shinya Kitaoka 120a6e
                 int inkIndex,
Shinya Kitaoka 120a6e
                 int paintIndex)*/
Toshihiro Shimizu 890ddd
{
Shinya Kitaoka 120a6e
  if ((aff.a11 * aff.a22 - aff.a12 * aff.a21) == 0) return;
Shinya Kitaoka 120a6e
  const int PADN = 16;
Shinya Kitaoka 120a6e
  assert(std::max(up->getLx(), up->getLy()) <
Shinya Kitaoka 120a6e
         (1 << (8 * sizeof(int) - PADN - 1)));
Shinya Kitaoka 120a6e
  TRectD boundingBoxD =
Shinya Kitaoka 120a6e
      TRectD(convert(dn->getBounds())) *
Shinya Kitaoka 120a6e
      (aff * TRectD(-0.5, -0.5, up->getLx() - 0.5, up->getLy() - 0.5));
Shinya Kitaoka 120a6e
  if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1)
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  int yMin       = std::max(tfloor(boundingBoxD.y0), 0);
Shinya Kitaoka 120a6e
  int yMax       = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1);
Shinya Kitaoka 120a6e
  int xMin       = std::max(tfloor(boundingBoxD.x0), 0);
Shinya Kitaoka 120a6e
  int xMax       = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1);
Shinya Kitaoka 120a6e
  TAffine invAff = inv(aff);
Shinya Kitaoka 120a6e
  double deltaXD = invAff.a11;
Shinya Kitaoka 120a6e
  double deltaYD = invAff.a21;
Shinya Kitaoka 120a6e
  int deltaXL    = tround(deltaXD * (1 << PADN));
Shinya Kitaoka 120a6e
  int deltaYL    = tround(deltaYD * (1 << PADN));
Shinya Kitaoka 120a6e
  if ((deltaXL == 0) && (deltaYL == 0)) return;
Shinya Kitaoka 120a6e
  int lxPred = up->getLx() * (1 << PADN) - 1;
Shinya Kitaoka 120a6e
  int lyPred = up->getLy() * (1 << PADN) - 1;
Shinya Kitaoka 120a6e
  int dnWrap = dn->getWrap();
Shinya Kitaoka 120a6e
  int upWrap = up->getWrap();
Shinya Kitaoka 120a6e
  std::vector<TPixel32> paints(palette->getStyleCount());
Shinya Kitaoka 120a6e
  std::vector<TPixel32> inks(palette->getStyleCount());
Shinya Kitaoka 120a6e
Jeremy Bullock ff7b10
  if (s.m_transparencyCheck && !s.m_isOnionSkin) {
Shinya Kitaoka 120a6e
    for (int i = 0; i < palette->getStyleCount(); i++) {
shun-iwasawa 963308
      // if the style's autopaint flag is ON, show its original color
shun-iwasawa 963308
      // so that users can easily find lines left unpainted.
shun-iwasawa 963308
      if (i == s.m_gapCheckIndex || palette->getStyle(i)->getFlags() != 0) {
Jeremy Bullock ff7b10
        paints[i] = inks[i] = applyColorScaleCMapped(
Jeremy Bullock ff7b10
            palette->getStyle(i)->getAverageColor(), s.m_globalColorScale);
Jeremy Bullock ff7b10
      } else {
Jeremy Bullock ff7b10
        paints[i] = s.m_transpCheckPaint;
Jeremy Bullock ff7b10
        inks[i]   = s.m_blackBgCheck ? s.m_transpCheckBg : s.m_transpCheckInk;
Jeremy Bullock ff7b10
      }
Shinya Kitaoka 120a6e
    }
Jeremy Bullock ff7b10
  } else if (s.m_globalColorScale == TPixel::Black)
shun-iwasawa 84ffc5
    for (int i = 0; i < palette->getStyleCount(); i++)
Shinya Kitaoka 120a6e
      paints[i] = inks[i] =
Shinya Kitaoka 120a6e
          ::premultiply(palette->getStyle(i)->getAverageColor());
Shinya Kitaoka 120a6e
  else
shun-iwasawa 84ffc5
    for (int i = 0; i < palette->getStyleCount(); i++)
Shinya Kitaoka 120a6e
      paints[i] = inks[i] = applyColorScaleCMapped(
Shinya Kitaoka 120a6e
          palette->getStyle(i)->getAverageColor(), s.m_globalColorScale);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  dn->lock();
Shinya Kitaoka 120a6e
  up->lock();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TPixel32 *dnRow       = dn->pixels(yMin);
Shinya Kitaoka 120a6e
  TPixelCM32 *upBasePix = up->pixels();
Shinya Kitaoka 120a6e
  for (int y = yMin; y <= yMax; y++, dnRow += dnWrap) {
Shinya Kitaoka 120a6e
    TPointD a = invAff * TPointD(xMin, y);
Shinya Kitaoka 120a6e
    int xL0   = tround((a.x + 0.5) * (1 << PADN));
Shinya Kitaoka 120a6e
    int yL0   = tround((a.y + 0.5) * (1 << PADN));
Shinya Kitaoka 120a6e
    int kMinX = 0, kMaxX = xMax - xMin;
Shinya Kitaoka 120a6e
    int kMinY = 0, kMaxY = xMax - xMin;
Shinya Kitaoka 120a6e
    if (deltaXL == 0) {
Shinya Kitaoka 120a6e
      if ((xL0 < 0) || (lxPred < xL0)) continue;
Shinya Kitaoka 120a6e
    } else if (deltaXL > 0) {
Shinya Kitaoka 120a6e
      if (lxPred < xL0) continue;
Shinya Kitaoka 120a6e
shun-iwasawa 84ffc5
      kMaxX = (lxPred - xL0) / deltaXL;                       //  floor
Shinya Kitaoka 120a6e
      if (xL0 < 0) kMinX = ((-xL0) + deltaXL - 1) / deltaXL;  //  ceil
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      if (xL0 < 0) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      kMaxX = xL0 / (-deltaXL);  //  floor
Shinya Kitaoka 120a6e
      if (lxPred < xL0)
Shinya Kitaoka 120a6e
        kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL);  //  ceil
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    if (deltaYL == 0) {
Shinya Kitaoka 120a6e
      if ((yL0 < 0) || (lyPred < yL0)) continue;
Shinya Kitaoka 120a6e
    } else if (deltaYL > 0) {
Shinya Kitaoka 120a6e
      if (lyPred < yL0) continue;
Shinya Kitaoka 120a6e
shun-iwasawa 84ffc5
      kMaxY = (lyPred - yL0) / deltaYL;
Shinya Kitaoka 120a6e
      if (yL0 < 0) kMinY = ((-yL0) + deltaYL - 1) / deltaYL;
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      if (yL0 < 0) continue;
Shinya Kitaoka 120a6e
      kMaxY = yL0 / (-deltaYL);  //  floor
Shinya Kitaoka 120a6e
      if (lyPred < yL0)
Shinya Kitaoka 120a6e
        kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL);  //  ceil
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    int kMin = std::max({kMinX, kMinY, (int)0});
Shinya Kitaoka 120a6e
    int kMax = std::min({kMaxX, kMaxY, xMax - xMin});
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TPixel32 *dnPix    = dnRow + xMin + kMin;
Shinya Kitaoka 120a6e
    TPixel32 *dnEndPix = dnRow + xMin + kMax + 1;
Shinya Kitaoka 120a6e
    int xL             = xL0 + (kMin - 1) * deltaXL;
Shinya Kitaoka 120a6e
    int yL             = yL0 + (kMin - 1) * deltaYL;
Shinya Kitaoka 120a6e
    for (; dnPix < dnEndPix; ++dnPix) {
Shinya Kitaoka 120a6e
      xL += deltaXL;
Shinya Kitaoka 120a6e
      yL += deltaYL;
Shinya Kitaoka 120a6e
      int xI = xL >> PADN;
Shinya Kitaoka 120a6e
      int yI = yL >> PADN;
Shinya Kitaoka 120a6e
      assert((0 <= xI) && (xI <= up->getLx() - 1) && (0 <= yI) &&
Shinya Kitaoka 120a6e
             (yI <= up->getLy() - 1));
Shinya Kitaoka 120a6e
      TPixelCM32 *upPix = upBasePix + (yI * upWrap + xI);
Shinya Kitaoka 120a6e
      int t             = upPix->getTone();
Shinya Kitaoka 120a6e
      int p             = upPix->getPaint();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (t == 0xff && p == 0)
Shinya Kitaoka 120a6e
        continue;
Shinya Kitaoka 120a6e
      else {
Shinya Kitaoka 120a6e
        int i = upPix->getInk();
Shinya Kitaoka 120a6e
        TPixel32 colorUp;
Shinya Kitaoka 120a6e
        if (s.m_inksOnly) switch (t) {
Shinya Kitaoka 120a6e
          case 0:
Shinya Kitaoka 120a6e
            colorUp = (i == s.m_inkIndex) ? TPixel::Red : inks[i];
Shinya Kitaoka 120a6e
            break;
Shinya Kitaoka 120a6e
          case 255:
Shinya Kitaoka 120a6e
            colorUp = TPixel::Transparent;
Shinya Kitaoka 120a6e
            break;
Shinya Kitaoka 120a6e
          default: {
Shinya Kitaoka 120a6e
            TPixel inkColor;
Shinya Kitaoka 120a6e
            if (i == s.m_inkIndex) {
Shinya Kitaoka 120a6e
              inkColor = TPixel::Red;
Shinya Kitaoka 120a6e
              if (p == 0) {
Shinya Kitaoka 120a6e
                t = t / 2;  // transparency check(for a bug!) darken
Shinya Kitaoka 120a6e
                            // semitrasparent pixels; ghibli likes it, and wants
Shinya Kitaoka 120a6e
                            // it also for ink checks...
Shinya Kitaoka 120a6e
                // otherwise, ramps goes always from reds towards grey...
Shinya Kitaoka 120a6e
              }
Shinya Kitaoka 120a6e
            } else
Shinya Kitaoka 120a6e
              inkColor = inks[i];
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
            colorUp = antialias(inkColor, 255 - t);
Shinya Kitaoka 120a6e
            break;
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
        else
Shinya Kitaoka 120a6e
          switch (t) {
Shinya Kitaoka 120a6e
          case 0:
Shinya Kitaoka 120a6e
            colorUp = (i == s.m_inkIndex) ? TPixel::Red : inks[i];
Shinya Kitaoka 120a6e
            break;
Shinya Kitaoka 120a6e
          case 255:
Shinya Kitaoka 120a6e
            colorUp = (p == s.m_paintIndex) ? TPixel::Red : paints[p];
Shinya Kitaoka 120a6e
            break;
Shinya Kitaoka 120a6e
          default: {
Shinya Kitaoka 120a6e
            TPixel paintColor = (p == s.m_paintIndex) ? TPixel::Red : paints[p];
Shinya Kitaoka 120a6e
            TPixel inkColor;
Shinya Kitaoka 120a6e
            if (i == s.m_inkIndex) {
Shinya Kitaoka 120a6e
              inkColor = TPixel::Red;
Shinya Kitaoka 120a6e
              if (p == 0) {
Shinya Kitaoka 120a6e
                paintColor = TPixel::Transparent;
Shinya Kitaoka 120a6e
              }
Shinya Kitaoka 120a6e
            } else
Shinya Kitaoka 120a6e
              inkColor = inks[i];
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
            if (s.m_transparencyCheck) t = t / 2;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
            colorUp = blend(inkColor, paintColor, t, TPixelCM32::getMaxTone());
Shinya Kitaoka 120a6e
            break;
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        if (colorUp.m == 255)
Shinya Kitaoka 120a6e
          *dnPix = colorUp;
Shinya Kitaoka 120a6e
        else if (colorUp.m != 0)
Shinya Kitaoka 120a6e
          *dnPix = quickOverPix(*dnPix, colorUp);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  dn->unlock();
Shinya Kitaoka 120a6e
  up->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
//=============================================================================
Shinya Kitaoka 120a6e
void doQuickPutCmapped(const TRaster32P &dn, const TRasterCM32P &up,
Shinya Kitaoka 120a6e
                       const TPaletteP &palette, double sx, double sy,
Shinya Kitaoka 120a6e
                       double tx, double ty, const TPixel32 &globalColorScale,
Shinya Kitaoka 120a6e
                       bool inksOnly) {
Shinya Kitaoka 120a6e
  //  se aff := TAffine(sx, 0, tx, 0, sy, ty) e' degenere la controimmagine
Shinya Kitaoka 120a6e
  //  di up e' un segmento (o un punto)
Shinya Kitaoka 120a6e
  if ((sx == 0) || (sy == 0)) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  contatore bit di shift
Shinya Kitaoka 120a6e
  const int PADN = 16;
Shinya Kitaoka 120a6e
  assert(std::max(up->getLx(), up->getLy()) <
Shinya Kitaoka 120a6e
         (1 << (8 * sizeof(int) - PADN - 1)));
Shinya Kitaoka 120a6e
  //  max dimensioni di up gestibili (limite imposto dal numero di bit
Shinya Kitaoka 120a6e
  // disponibili per la parte intera di xL, yL)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TAffine aff(sx, 0, tx, 0, sy, ty);
Shinya Kitaoka 120a6e
  TRectD boundingBoxD =
Shinya Kitaoka 120a6e
      TRectD(convert(dn->getBounds())) *
Shinya Kitaoka 120a6e
      (aff * TRectD(-0.5, -0.5, up->getLx() - 0.5, up->getLy() - 0.5));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping
Shinya Kitaoka 120a6e
  if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1)
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping y su dn
Shinya Kitaoka 120a6e
  int yMin = std::max(tfloor(boundingBoxD.y0), 0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping y su dn
Shinya Kitaoka 120a6e
  int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping x su dn
Shinya Kitaoka 120a6e
  int xMin = std::max(tfloor(boundingBoxD.x0), 0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping x su dn
Shinya Kitaoka 120a6e
  int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TAffine invAff = inv(aff);  //  inversa di aff
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  nello scorrere le scanline di boundingBoxD, il passaggio alla scanline
Shinya Kitaoka 120a6e
  //  successiva comporta l'incremento (0, deltaYD) delle coordinate dei
Shinya Kitaoka 120a6e
  //  pixels corrispondenti di up
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  nel disegnare la y-esima scanline di dn, il passaggio al pixel
Shinya Kitaoka 120a6e
  //  successivo comporta l'incremento (deltaXD, 0) delle coordinate del
Shinya Kitaoka 120a6e
  //  pixel corrispondente di up
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double deltaXD = invAff.a11;
Shinya Kitaoka 120a6e
  double deltaYD = invAff.a22;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  deltaXD "TLonghizzato" (round)
Shinya Kitaoka 120a6e
  int deltaXL = tround(deltaXD * (1 << PADN));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  deltaYD "TLonghizzato" (round)
Shinya Kitaoka 120a6e
  int deltaYL = tround(deltaYD * (1 << PADN));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  se aff "TLonghizzata" (round) e' degenere la controimmagine di up e' un
Shinya Kitaoka 120a6e
  //  segmento (o un punto)
Shinya Kitaoka 120a6e
  if ((deltaXL == 0) || (deltaYL == 0)) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //	(1)  equazione (kX, kY)-parametrica di boundingBoxD:
Shinya Kitaoka 120a6e
  //	       (xMin, yMin) + kX*(1, 0) + kY*(0, 1),
Shinya Kitaoka 120a6e
  //	         kX = 0, ..., (xMax - xMin),
Shinya Kitaoka 120a6e
  //             kY = 0, ..., (yMax - yMin)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //	(2)  equazione (kX, kY)-parametrica dell'immagine
Shinya Kitaoka 120a6e
  //         mediante invAff di (1):
Shinya Kitaoka 120a6e
  //	       invAff*(xMin, yMin) + kX*(deltaXD, 0) + kY*(0, deltaYD),
Shinya Kitaoka 120a6e
  //	         kX = kMinX, ..., kMaxX
Shinya Kitaoka 120a6e
  //             con 0 <= kMinX <= kMaxX <= (xMax - xMin)
Shinya Kitaoka 120a6e
  //
Shinya Kitaoka 120a6e
  //             kY = kMinY, ..., kMaxY
Shinya Kitaoka 120a6e
  //             con 0 <= kMinY <= kMaxY <= (yMax - yMin)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  calcola kMinX, kMaxX, kMinY, kMaxY intersecando la (2) con i lati di up
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  il segmento [a, b] di up e' la controimmagine mediante aff della
Shinya Kitaoka 120a6e
  // porzione di scanline  [ (xMin, yMin), (xMax, yMin) ] di dn
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  TPointD b = invAff*TPointD(xMax, yMin);
Shinya Kitaoka 120a6e
  TPointD a = invAff * TPointD(xMin, yMin);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  (xL0, yL0) sono le coordinate di a (inizializzate per il round)
Shinya Kitaoka 120a6e
  // in versione "TLonghizzata"
Shinya Kitaoka 120a6e
  //	0 <= xL0 + kX*deltaXL
Shinya Kitaoka 120a6e
  //      < up->getLx()*(1<<PADN),
Shinya Kitaoka 120a6e
  //
Shinya Kitaoka 120a6e
  //    0 <= kMinX
Shinya Kitaoka 120a6e
  //      <= kX
Shinya Kitaoka 120a6e
  //      <= kMaxX
Shinya Kitaoka 120a6e
  //      <= (xMax - xMin)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //	0 <= yL0 + kY*deltaYL
Shinya Kitaoka 120a6e
  //      < up->getLy()*(1<<PADN),
Shinya Kitaoka 120a6e
  //
Shinya Kitaoka 120a6e
  //    0 <= kMinY
Shinya Kitaoka 120a6e
  //      <= kY
Shinya Kitaoka 120a6e
  //      <= kMaxY
Shinya Kitaoka 120a6e
  //      <= (yMax - yMin)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  xL0 inizializzato per il round
Shinya Kitaoka 120a6e
  int xL0 = tround((a.x + 0.5) * (1 << PADN));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  yL0 inizializzato per il round
Shinya Kitaoka 120a6e
  int yL0 = tround((a.y + 0.5) * (1 << PADN));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  calcola kMinY, kMaxY, kMinX, kMaxX intersecando la (2) con i lati di up
Shinya Kitaoka 120a6e
  int kMinX = 0, kMaxX = xMax - xMin;  //  clipping su dn
Shinya Kitaoka 120a6e
  int kMinY = 0, kMaxY = yMax - yMin;  //  clipping su dn
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  TINT32 predecessore di up->getLx()
Shinya Kitaoka 120a6e
  int lxPred = up->getLx() * (1 << PADN) - 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  TINT32 predecessore di up->getLy()
Shinya Kitaoka 120a6e
  int lyPred = up->getLy() * (1 << PADN) - 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  0 <= xL0 + k*deltaXL < up->getLx()*(1<<PADN)
Shinya Kitaoka 120a6e
  //            <=>
Shinya Kitaoka 120a6e
  //  0 <= xL0 + k*deltaXL <= lxPred
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  0 <= yL0 + k*deltaYL < up->getLy()*(1<<PADN)
Shinya Kitaoka 120a6e
  //            <=>
Shinya Kitaoka 120a6e
  //  0 <= yL0 + k*deltaYL <= lyPred
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  calcola kMinY, kMaxY intersecando la (2) con i lati
Shinya Kitaoka 120a6e
  //  (y = yMin) e (y = yMax) di up
Shinya Kitaoka 120a6e
  if (deltaYL > 0)  //  (deltaYL != 0)
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    //  [a, b] interno ad up+(bordo destro/basso)
Shinya Kitaoka 120a6e
    assert(yL0 <= lyPred);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    kMaxY = (lyPred - yL0) / deltaYL;  //  floor
Shinya Kitaoka 120a6e
    if (yL0 < 0) {
Shinya Kitaoka 120a6e
      kMinY = ((-yL0) + deltaYL - 1) / deltaYL;  //  ceil
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else  //  (deltaYL < 0)
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    //  [a, b] interno ad up+(bordo destro/basso)
Shinya Kitaoka 120a6e
    assert(0 <= yL0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    kMaxY = yL0 / (-deltaYL);  //  floor
Shinya Kitaoka 120a6e
    if (lyPred < yL0) {
Shinya Kitaoka 120a6e
      kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL);  //  ceil
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  //  calcola kMinY, kMaxY effettuando anche il clippind su dn
Shinya Kitaoka 120a6e
  kMinY = std::max(kMinY, (int)0);
Shinya Kitaoka 120a6e
  kMaxY = std::min(kMaxY, yMax - yMin);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  calcola kMinX, kMaxX intersecando la (2) con i lati
Shinya Kitaoka 120a6e
  //  (x = xMin) e (x = xMax) di up
Shinya Kitaoka 120a6e
  if (deltaXL > 0)  //  (deltaXL != 0)
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    //  [a, b] interno ad up+(bordo destro/basso)
Shinya Kitaoka 120a6e
    assert(xL0 <= lxPred);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    kMaxX = (lxPred - xL0) / deltaXL;  //  floor
Shinya Kitaoka 120a6e
    if (xL0 < 0) {
Shinya Kitaoka 120a6e
      kMinX = ((-xL0) + deltaXL - 1) / deltaXL;  //  ceil
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else  //  (deltaXL < 0)
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    //  [a, b] interno ad up+(bordo destro/basso)
Shinya Kitaoka 120a6e
    assert(0 <= xL0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    kMaxX = xL0 / (-deltaXL);  //  floor
Shinya Kitaoka 120a6e
    if (lxPred < xL0) {
Shinya Kitaoka 120a6e
      kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL);  //  ceil
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  //  calcola kMinX, kMaxX effettuando anche il clippind su dn
Shinya Kitaoka 120a6e
  kMinX = std::max(kMinX, (int)0);
Shinya Kitaoka 120a6e
  kMaxX = std::min(kMaxX, xMax - xMin);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int dnWrap = dn->getWrap();
Shinya Kitaoka 120a6e
  int upWrap = up->getWrap();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int count = std::max({palette->getStyleCount(), TPixelCM32::getMaxInk(),
Shinya Kitaoka 120a6e
                        TPixelCM32::getMaxPaint()});
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::vector<TPixel32> paints(count, TPixel32::Red);
Shinya Kitaoka 120a6e
  std::vector<TPixel32> inks(count, TPixel32::Red);
Shinya Kitaoka 120a6e
  if (globalColorScale != TPixel::Black)
shun-iwasawa 84ffc5
    for (int i = 0; i < palette->getStyleCount(); i++)
Shinya Kitaoka 120a6e
      paints[i] = inks[i] = applyColorScaleCMapped(
Shinya Kitaoka 120a6e
          palette->getStyle(i)->getAverageColor(), globalColorScale);
Shinya Kitaoka 120a6e
  else
shun-iwasawa 84ffc5
    for (int i = 0; i < palette->getStyleCount(); i++)
Shinya Kitaoka 120a6e
      paints[i] = inks[i] =
Shinya Kitaoka 120a6e
          ::premultiply(palette->getStyle(i)->getAverageColor());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  dn->lock();
Shinya Kitaoka 120a6e
  up->lock();
Shinya Kitaoka 120a6e
  TPixelCM32 *upBasePix = up->pixels();
Shinya Kitaoka 120a6e
  TPixel32 *dnRow       = dn->pixels(yMin + kMinY);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  (xL, yL) sono le coordinate (inizializzate per il round)
Shinya Kitaoka 120a6e
  //  in versione "TLonghizzata" del pixel corrente di up
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  inizializza yL
Shinya Kitaoka 120a6e
  int yL = yL0 + (kMinY - 1) * deltaYL;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  scorre le scanline di boundingBoxD
Shinya Kitaoka 120a6e
  for (int kY = kMinY; kY <= kMaxY; kY++, dnRow += dnWrap) {
Shinya Kitaoka 120a6e
    //  inizializza xL
Shinya Kitaoka 120a6e
    int xL = xL0 + (kMinX - 1) * deltaXL;
Shinya Kitaoka 120a6e
    yL += deltaYL;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  il punto di up TPointD(xL/(1<
Shinya Kitaoka 120a6e
    //  con (xI, yI)
Shinya Kitaoka 120a6e
    int yI = yL >> PADN;  //  round
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TPixel32 *dnPix    = dnRow + xMin + kMinX;
Shinya Kitaoka 120a6e
    TPixel32 *dnEndPix = dnRow + xMin + kMaxX + 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  scorre i pixel sulla (yMin + kY)-esima scanline di dn
Shinya Kitaoka 120a6e
    for (; dnPix < dnEndPix; ++dnPix) {
Shinya Kitaoka 120a6e
      xL += deltaXL;
Shinya Kitaoka 120a6e
      //  il punto di up TPointD(xL/(1<
Shinya Kitaoka 120a6e
      //  approssimato con (xI, yI)
Shinya Kitaoka 120a6e
      int xI = xL >> PADN;  //	round
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      assert((0 <= xI) && (xI <= up->getLx() - 1) && (0 <= yI) &&
Shinya Kitaoka 120a6e
             (yI <= up->getLy() - 1));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      TPixelCM32 *upPix = upBasePix + (yI * upWrap + xI);
Shinya Kitaoka 120a6e
      int t             = upPix->getTone();
Shinya Kitaoka 120a6e
      int p             = upPix->getPaint();
Shinya Kitaoka 120a6e
      assert(0 <= t && t < 256);
Shinya Kitaoka 120a6e
      assert(0 <= p && p < (int)paints.size());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (t == 0xff && p == 0)
Shinya Kitaoka 120a6e
        continue;
Shinya Kitaoka 120a6e
      else {
Shinya Kitaoka 120a6e
        int i = upPix->getInk();
Shinya Kitaoka 120a6e
        assert(0 <= i && i < (int)inks.size());
Shinya Kitaoka 120a6e
        TPixel32 colorUp;
Shinya Kitaoka 120a6e
        if (inksOnly) switch (t) {
Shinya Kitaoka 120a6e
          case 0:
Shinya Kitaoka 120a6e
            colorUp = inks[i];
Shinya Kitaoka 120a6e
            break;
Shinya Kitaoka 120a6e
          case 255:
Shinya Kitaoka 120a6e
            colorUp = TPixel::Transparent;
Shinya Kitaoka 120a6e
            break;
Shinya Kitaoka 120a6e
          default:
Shinya Kitaoka 120a6e
            colorUp = antialias(inks[i], 255 - t);
Shinya Kitaoka 120a6e
            break;
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
        else
Shinya Kitaoka 120a6e
          switch (t) {
Shinya Kitaoka 120a6e
          case 0:
Shinya Kitaoka 120a6e
            colorUp = inks[i];
Shinya Kitaoka 120a6e
            break;
Shinya Kitaoka 120a6e
          case 255:
Shinya Kitaoka 120a6e
            colorUp = paints[p];
Shinya Kitaoka 120a6e
            break;
Shinya Kitaoka 120a6e
          default:
Shinya Kitaoka 120a6e
            colorUp = blend(inks[i], paints[p], t, TPixelCM32::getMaxTone());
Shinya Kitaoka 120a6e
            break;
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        if (colorUp.m == 255)
Shinya Kitaoka 120a6e
          *dnPix = colorUp;
Shinya Kitaoka 120a6e
        else if (colorUp.m != 0)
Shinya Kitaoka 120a6e
          *dnPix = quickOverPix(*dnPix, colorUp);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  dn->unlock();
Shinya Kitaoka 120a6e
  up->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void doQuickResampleColorFilter(const TRaster32P &dn, const TRasterCM32P &up,
Shinya Kitaoka 120a6e
                                const TPaletteP &plt, const TAffine &aff,
Shinya Kitaoka 120a6e
                                UCHAR colorMask) {
Shinya Kitaoka 120a6e
  if ((aff.a11 * aff.a22 - aff.a12 * aff.a21) == 0) return;
Shinya Kitaoka 120a6e
  const int PADN = 16;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::vector<TPixel32> paints(plt->getStyleCount());
Shinya Kitaoka 120a6e
  std::vector<TPixel32> inks(plt->getStyleCount());
Shinya Kitaoka 120a6e
shun-iwasawa 84ffc5
  for (int i = 0; i < plt->getStyleCount(); i++)
Shinya Kitaoka 120a6e
    paints[i] = inks[i] = ::premultiply(plt->getStyle(i)->getAverageColor());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  assert(std::max(up->getLx(), up->getLy()) <
Shinya Kitaoka 120a6e
         (1 << (8 * sizeof(int) - PADN - 1)));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRectD boundingBoxD =
Shinya Kitaoka 120a6e
      TRectD(convert(dn->getBounds())) *
Shinya Kitaoka 120a6e
      (aff * TRectD(-0.5, -0.5, up->getLx() - 0.5, up->getLy() - 0.5));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1)
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int yMin = std::max(tfloor(boundingBoxD.y0), 0);  //  clipping y su dn
Shinya Kitaoka 120a6e
  int yMax =
Shinya Kitaoka 120a6e
      std::min(tceil(boundingBoxD.y1), dn->getLy() - 1);  //  clipping y su dn
Shinya Kitaoka 120a6e
  int xMin = std::max(tfloor(boundingBoxD.x0), 0);        //  clipping x su dn
Shinya Kitaoka 120a6e
  int xMax =
Shinya Kitaoka 120a6e
      std::min(tceil(boundingBoxD.x1), dn->getLx() - 1);  //  clipping x su dn
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TAffine invAff = inv(aff);  //  inversa di aff
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double deltaXD = invAff.a11;
Shinya Kitaoka 120a6e
  double deltaYD = invAff.a21;
Shinya Kitaoka 120a6e
  int deltaXL =
Shinya Kitaoka 120a6e
      tround(deltaXD * (1 << PADN));  //  deltaXD "TLonghizzato" (round)
Shinya Kitaoka 120a6e
  int deltaYL =
Shinya Kitaoka 120a6e
      tround(deltaYD * (1 << PADN));  //  deltaYD "TLonghizzato" (round)
Shinya Kitaoka 120a6e
  if ((deltaXL == 0) && (deltaYL == 0)) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int lxPred =
Shinya Kitaoka 120a6e
      up->getLx() * (1 << PADN) - 1;  //  TINT32 predecessore di up->getLx()
Shinya Kitaoka 120a6e
  int lyPred =
Shinya Kitaoka 120a6e
      up->getLy() * (1 << PADN) - 1;  //  TINT32 predecessore di up->getLy()
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int dnWrap = dn->getWrap();
Shinya Kitaoka 120a6e
  int upWrap = up->getWrap();
Shinya Kitaoka 120a6e
  dn->lock();
Shinya Kitaoka 120a6e
  up->lock();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TPixel32 *dnRow       = dn->pixels(yMin);
Shinya Kitaoka 120a6e
  TPixelCM32 *upBasePix = up->pixels();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (int y = yMin; y <= yMax; y++, dnRow += dnWrap) {
Shinya Kitaoka 120a6e
    TPointD a = invAff * TPointD(xMin, y);
Shinya Kitaoka 120a6e
    int xL0   = tround((a.x + 0.5) * (1 << PADN));
Shinya Kitaoka 120a6e
    int yL0   = tround((a.y + 0.5) * (1 << PADN));
Shinya Kitaoka 120a6e
    int kMinX = 0, kMaxX = xMax - xMin;  //  clipping su dn
Shinya Kitaoka 120a6e
    int kMinY = 0, kMaxY = xMax - xMin;  //  clipping su dn
Shinya Kitaoka 120a6e
    if (deltaXL == 0) {
Shinya Kitaoka 120a6e
      if ((xL0 < 0) || (lxPred < xL0)) continue;
Shinya Kitaoka 120a6e
    } else if (deltaXL > 0) {
Shinya Kitaoka 120a6e
      if (lxPred < xL0) continue;
Shinya Kitaoka 120a6e
shun-iwasawa 84ffc5
      kMaxX = (lxPred - xL0) / deltaXL;                       //  floor
Shinya Kitaoka 120a6e
      if (xL0 < 0) kMinX = ((-xL0) + deltaXL - 1) / deltaXL;  //  ceil
Shinya Kitaoka 120a6e
    } else                                                    //  (deltaXL < 0)
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      if (xL0 < 0) continue;
Shinya Kitaoka 120a6e
      kMaxX = xL0 / (-deltaXL);  //  floor
Shinya Kitaoka 120a6e
      if (lxPred < xL0)
Shinya Kitaoka 120a6e
        kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL);  //  ceil
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    if (deltaYL == 0) {
Shinya Kitaoka 120a6e
      if ((yL0 < 0) || (lyPred < yL0)) continue;
Shinya Kitaoka 120a6e
    } else if (deltaYL > 0) {
Shinya Kitaoka 120a6e
      if (lyPred < yL0) continue;
Shinya Kitaoka 120a6e
shun-iwasawa 84ffc5
      kMaxY = (lyPred - yL0) / deltaYL;                       //  floor
Shinya Kitaoka 120a6e
      if (yL0 < 0) kMinY = ((-yL0) + deltaYL - 1) / deltaYL;  //  ceil
Shinya Kitaoka 120a6e
    } else                                                    //  (deltaYL < 0)
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      if (yL0 < 0) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      kMaxY = yL0 / (-deltaYL);  //  floor
Shinya Kitaoka 120a6e
      if (lyPred < yL0)
Shinya Kitaoka 120a6e
        kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL);  //  ceil
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    int kMin           = std::max({kMinX, kMinY, (int)0});
Shinya Kitaoka 120a6e
    int kMax           = std::min({kMaxX, kMaxY, xMax - xMin});
Shinya Kitaoka 120a6e
    TPixel32 *dnPix    = dnRow + xMin + kMin;
Shinya Kitaoka 120a6e
    TPixel32 *dnEndPix = dnRow + xMin + kMax + 1;
Shinya Kitaoka 120a6e
    int xL             = xL0 + (kMin - 1) * deltaXL;  //  inizializza xL
Shinya Kitaoka 120a6e
    int yL             = yL0 + (kMin - 1) * deltaYL;  //  inizializza yL
Shinya Kitaoka 120a6e
    for (; dnPix < dnEndPix; ++dnPix) {
Shinya Kitaoka 120a6e
      xL += deltaXL;
Shinya Kitaoka 120a6e
      yL += deltaYL;
Shinya Kitaoka 120a6e
      int xI = xL >> PADN;  //  round
Shinya Kitaoka 120a6e
      int yI = yL >> PADN;  //  round
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      assert((0 <= xI) && (xI <= up->getLx() - 1) && (0 <= yI) &&
Shinya Kitaoka 120a6e
             (yI <= up->getLy() - 1));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      TPixelCM32 *upPix = upBasePix + (yI * upWrap + xI);
Shinya Kitaoka 120a6e
      int t             = upPix->getTone();
Shinya Kitaoka 120a6e
      int p             = upPix->getPaint();
Shinya Kitaoka 120a6e
      int i             = upPix->getInk();
Shinya Kitaoka 120a6e
      TPixel32 colorUp;
Shinya Kitaoka 120a6e
      switch (t) {
Shinya Kitaoka 120a6e
      case 0:
Shinya Kitaoka 120a6e
        colorUp = inks[i];
Shinya Kitaoka 120a6e
        break;
Shinya Kitaoka 120a6e
      case 255:
Shinya Kitaoka 120a6e
        colorUp = paints[p];
Shinya Kitaoka 120a6e
        break;
Shinya Kitaoka 120a6e
      default:
Shinya Kitaoka 120a6e
        colorUp = blend(inks[i], paints[p], t, TPixelCM32::getMaxTone());
Shinya Kitaoka 120a6e
        break;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (colorMask == TRop::MChan)
Shinya Kitaoka 120a6e
        dnPix->r = dnPix->g = dnPix->b = colorUp.m;
Shinya Kitaoka 120a6e
      else {
Shinya Kitaoka 120a6e
        dnPix->r = ((colorMask & TRop::RChan) ? colorUp.r : 0);
Shinya Kitaoka 120a6e
        dnPix->g = ((colorMask & TRop::GChan) ? colorUp.g : 0);
Shinya Kitaoka 120a6e
        dnPix->b = ((colorMask & TRop::BChan) ? colorUp.b : 0);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      dnPix->m = 255;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  dn->unlock();
Shinya Kitaoka 120a6e
  up->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==========================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
#endif  // TNZCORE_LIGHT
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef OPTIMIZE_FOR_LP64
Shinya Kitaoka 120a6e
void doQuickResampleFilter_optimized(const TRaster32P &dn, const TRaster32P &up,
Shinya Kitaoka 120a6e
                                     const TAffine &aff) {
Shinya Kitaoka 120a6e
  //  se aff e' degenere la controimmagine di up e' un segmento (o un punto)
Shinya Kitaoka 120a6e
  if ((aff.a11 * aff.a22 - aff.a12 * aff.a21) == 0) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //  contatore bit di shift
Shinya Kitaoka 120a6e
  const int PADN = 16;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //  maschera del filtro bilineare
Shinya Kitaoka 120a6e
  const int MASKN = (1 << PADN) - 1;
Shinya Kitaoka 120a6e
  assert(std::max(up->getLx(), up->getLy()) <
Shinya Kitaoka 120a6e
         (1 << (8 * sizeof(int) - PADN - 1)));
Shinya Kitaoka 120a6e
  //  max dimensioni di up gestibili (limite imposto dal numero di bit
Shinya Kitaoka 120a6e
  //  disponibili per la parte intera di xL, yL)
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TRectD boundingBoxD = TRectD(convert(dn->getSize())) *
Shinya Kitaoka 120a6e
                        (aff * TRectD(0, 0, up->getLx() - 2, up->getLy() - 2));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //  clipping
Shinya Kitaoka 120a6e
  if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1)
Shinya Kitaoka 120a6e
    return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //  clipping y su dn
Shinya Kitaoka 120a6e
  int yMin = std::max(tfloor(boundingBoxD.y0), 0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping y su dn
Shinya Kitaoka 120a6e
  int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping x su dn
Shinya Kitaoka 120a6e
  int xMin = std::max(tfloor(boundingBoxD.x0), 0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping x su dn
Shinya Kitaoka 120a6e
  int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TAffine invAff = inv(aff);  //  inversa di aff
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  nel disegnare la y-esima scanline di dn, il passaggio al pixel
Shinya Kitaoka 120a6e
  //  successivo comporta l'incremento (deltaXD, deltaYD) delle coordinate
Shinya Kitaoka 120a6e
  //  del pixel corrispondente di up
Shinya Kitaoka 120a6e
  double deltaXD = invAff.a11;
Shinya Kitaoka 120a6e
  double deltaYD = invAff.a21;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  deltaXD "TLonghizzato" (round)
Shinya Kitaoka 120a6e
  int deltaXL = tround(deltaXD * (1 << PADN));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  deltaYD "TLonghizzato" (round)
Shinya Kitaoka 120a6e
  int deltaYL = tround(deltaYD * (1 << PADN));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  se aff "TLonghizzata" (round) e' degenere la controimmagine di up e' un
Shinya Kitaoka 120a6e
  //  segmento (o un punto)
Shinya Kitaoka 120a6e
  if ((deltaXL == 0) && (deltaYL == 0)) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // naturale predecessore di up->getLx() - 1
Shinya Kitaoka 120a6e
  int lxPred = (up->getLx() - 2) * (1 << PADN);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  naturale predecessore di up->getLy() - 1
Shinya Kitaoka 120a6e
  int lyPred = (up->getLy() - 2) * (1 << PADN);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int dnWrap = dn->getWrap();
Shinya Kitaoka 120a6e
  int upWrap = up->getWrap();
Shinya Kitaoka 120a6e
  dn->lock();
Shinya Kitaoka 120a6e
  up->lock();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TPixel32 *dnRow     = dn->pixels(yMin);
Shinya Kitaoka 120a6e
  TPixel32 *upBasePix = up->pixels();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  long c1;
Shinya Kitaoka 120a6e
  long c2;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  long c3;
Shinya Kitaoka 120a6e
  long c4;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  long c5;
Shinya Kitaoka 120a6e
  long c6;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  long s_rg;
Shinya Kitaoka 120a6e
  long s_br;
Shinya Kitaoka 120a6e
  long s_gb;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  UINT32 rColDownTmp;
Shinya Kitaoka 120a6e
  UINT32 gColDownTmp;
Shinya Kitaoka 120a6e
  UINT32 bColDownTmp;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  UINT32 rColUpTmp;
Shinya Kitaoka 120a6e
  UINT32 gColUpTmp;
Shinya Kitaoka 120a6e
  UINT32 bColUpTmp;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  unsigned char rCol;
Shinya Kitaoka 120a6e
  unsigned char gCol;
Shinya Kitaoka 120a6e
  unsigned char bCol;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int xI;
Shinya Kitaoka 120a6e
  int yI;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int xWeight1;
Shinya Kitaoka 120a6e
  int xWeight0;
Shinya Kitaoka 120a6e
  int yWeight1;
Shinya Kitaoka 120a6e
  int yWeight0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TPixel32 *upPix00;
Shinya Kitaoka 120a6e
  TPixel32 *upPix10;
Shinya Kitaoka 120a6e
  TPixel32 *upPix01;
Shinya Kitaoka 120a6e
  TPixel32 *upPix11;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TPointD a;
Shinya Kitaoka 120a6e
  int xL0;
Shinya Kitaoka 120a6e
  int yL0;
Shinya Kitaoka 120a6e
  int kMinX;
Shinya Kitaoka 120a6e
  int kMaxX;
Shinya Kitaoka 120a6e
  int kMinY;
Shinya Kitaoka 120a6e
  int kMaxY;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int kMin;
Shinya Kitaoka 120a6e
  int kMax;
Shinya Kitaoka 120a6e
  TPixel32 *dnPix;
Shinya Kitaoka 120a6e
  TPixel32 *dnEndPix;
Shinya Kitaoka 120a6e
  int xL;
Shinya Kitaoka 120a6e
  int yL;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int y = yMin;
Shinya Kitaoka 120a6e
  ++yMax;
Shinya Kitaoka 120a6e
  //  scorre le scanline di boundingBoxD
Shinya Kitaoka 120a6e
  for (; y < yMax - 32; ++y, dnRow += dnWrap) {
Shinya Kitaoka 120a6e
    EXTERNAL_LOOP_THE_FIRST_X_32
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  for (; y < yMax - 16; ++y, dnRow += dnWrap) {
Shinya Kitaoka 120a6e
    EXTERNAL_LOOP_THE_FIRST_X_16
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  for (; y < yMax - 8; ++y, dnRow += dnWrap) {
Shinya Kitaoka 120a6e
    EXTERNAL_LOOP_THE_FIRST_X_8
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  for (; y < yMax - 4; ++y, dnRow += dnWrap) {
Shinya Kitaoka 120a6e
    EXTERNAL_LOOP_THE_FIRST_X_4
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  for (; y < yMax - 2; ++y, dnRow += dnWrap) {
Shinya Kitaoka 120a6e
    EXTERNAL_LOOP_THE_FIRST_X_2
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  for (; y < yMax; ++y, dnRow += dnWrap) {
Shinya Kitaoka 120a6e
    EXTERNAL_LOOP_THE_FIRST
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  dn->unlock();
Shinya Kitaoka 120a6e
  up->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef OPTIMIZE_FOR_LP64
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void doQuickResampleFilter_optimized(const TRaster32P &dn, const TRaster32P &up,
Shinya Kitaoka 120a6e
                                     double sx, double sy, double tx,
Shinya Kitaoka 120a6e
                                     double ty) {
Shinya Kitaoka 120a6e
  //  se aff := TAffine(sx, 0, tx, 0, sy, ty) e' degenere la controimmagine
Shinya Kitaoka 120a6e
  //  di up e' un segmento (o un punto)
Shinya Kitaoka 120a6e
  if ((sx == 0) || (sy == 0)) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //  contatore bit di shift
Shinya Kitaoka 120a6e
  const int PADN = 16;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //  maschera del filtro bilineare
Shinya Kitaoka 120a6e
  const int MASKN = (1 << PADN) - 1;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //  max dimensioni di up gestibili (limite imposto dal numero di bit
Shinya Kitaoka 120a6e
  // disponibili per la parte intera di xL, yL)
Shinya Kitaoka 120a6e
  assert(std::max(up->getLx(), up->getLy()) <
Shinya Kitaoka 120a6e
         (1 << (8 * sizeof(int) - PADN - 1)));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TAffine aff(sx, 0, tx, 0, sy, ty);
Shinya Kitaoka 120a6e
  TRectD boundingBoxD = TRectD(convert(dn->getSize())) *
Shinya Kitaoka 120a6e
                        (aff * TRectD(0, 0, up->getLx() - 2, up->getLy() - 2));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping
Shinya Kitaoka 120a6e
  if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1)
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping y su dn
Shinya Kitaoka 120a6e
  int yMin = std::max(tfloor(boundingBoxD.y0), 0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping y su dn
Shinya Kitaoka 120a6e
  int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping x su dn
Shinya Kitaoka 120a6e
  int xMin = std::max(tfloor(boundingBoxD.x0), 0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  clipping x su dn
Shinya Kitaoka 120a6e
  int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  inversa di aff
Shinya Kitaoka 120a6e
  TAffine invAff = inv(aff);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  nello scorrere le scanline di boundingBoxD, il passaggio alla scanline
Shinya Kitaoka 120a6e
  //  successiva comporta l'incremento (0, deltaYD) delle coordinate dei
Shinya Kitaoka 120a6e
  //  pixels corrispondenti di up
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  nel disegnare la y-esima scanline di dn, il passaggio al pixel
Shinya Kitaoka 120a6e
  //  successivo comporta l'incremento (deltaXD, 0) delle coordinate del
Shinya Kitaoka 120a6e
  //  pixel corrispondente di up
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double deltaXD = invAff.a11;
Shinya Kitaoka 120a6e
  double deltaYD = invAff.a22;
Shinya Kitaoka 120a6e
  int deltaXL =
Shinya Kitaoka 120a6e
      tround(deltaXD * (1 << PADN));  //  deltaXD "TLonghizzato" (round)
Shinya Kitaoka 120a6e
  int deltaYL =
Shinya Kitaoka 120a6e
      tround(deltaYD * (1 << PADN));  //  deltaYD "TLonghizzato" (round)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  se aff "TLonghizzata" (round) e' degenere la controimmagine di up e'
Shinya Kitaoka 120a6e
  //  un segmento (o un punto)
Shinya Kitaoka 120a6e
  if ((deltaXL == 0) || (deltaYL == 0)) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  (1)  equazione (kX, kY)-parametrica di boundingBoxD:
Shinya Kitaoka 120a6e
  //         (xMin, yMin) + kX*(1, 0) + kY*(0, 1),
Shinya Kitaoka 120a6e
  //           kX = 0, ..., (xMax - xMin),
Shinya Kitaoka 120a6e
  //           kY = 0, ..., (yMax - yMin)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  (2)  equazione (kX, kY)-parametrica dell'immagine mediante invAff di (1):
Shinya Kitaoka 120a6e
  //         invAff*(xMin, yMin) + kX*(deltaXD, 0) + kY*(0, deltaYD),
Shinya Kitaoka 120a6e
  //           kX = kMinX, ..., kMaxX
Shinya Kitaoka 120a6e
  //             con 0 <= kMinX <= kMaxX <= (xMax - xMin)
Shinya Kitaoka 120a6e
  //
Shinya Kitaoka 120a6e
  //           kY = kMinY, ..., kMaxY
Shinya Kitaoka 120a6e
  //             con 0 <= kMinY <= kMaxY <= (yMax - yMin)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  calcola kMinX, kMaxX, kMinY, kMaxY intersecando la (2) con i lati di up
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  il segmento [a, b] di up (con gli estremi eventualmente invertiti) e'
Shinya Kitaoka 120a6e
  //  la controimmagine mediante aff della porzione di scanline
Shinya Kitaoka 120a6e
  //  [ (xMin, yMin), (xMax, yMin) ] di dn
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  TPointD b = invAff*TPointD(xMax, yMin);
Shinya Kitaoka 120a6e
  TPointD a = invAff * TPointD(xMin, yMin);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  (xL0, yL0) sono le coordinate di a (inizializzate per il round)
Shinya Kitaoka 120a6e
  //  in versione "TLonghizzata"
Shinya Kitaoka 120a6e
  //  0 <= xL0 + kX*deltaXL <= (up->getLx() - 2)*(1<<PADN),
Shinya Kitaoka 120a6e
  //  0 <= kMinX <= kX <= kMaxX <= (xMax - xMin)
Shinya Kitaoka 120a6e
  //  0 <= yL0 + kY*deltaYL <= (up->getLy() - 2)*(1<<PADN),
Shinya Kitaoka 120a6e
  //  0 <= kMinY <= kY <= kMaxY <= (yMax - yMin)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int xL0 = tround(a.x * (1 << PADN));  //  xL0 inizializzato
Shinya Kitaoka 120a6e
  int yL0 = tround(a.y * (1 << PADN));  //  yL0 inizializzato
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  calcola kMinY, kMaxY, kMinX, kMaxX intersecando la (2) con i lati di up
Shinya Kitaoka 120a6e
  int kMinX = 0, kMaxX = xMax - xMin;  //  clipping su dn
Shinya Kitaoka 120a6e
  int kMinY = 0, kMaxY = yMax - yMin;  //  clipping su dn
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  TINT32 predecessore di (up->getLx() - 1)
Shinya Kitaoka 120a6e
  int lxPred = (up->getLx() - 2) * (1 << PADN);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  TINT32 predecessore di (up->getLy() - 1)
Shinya Kitaoka 120a6e
  int lyPred = (up->getLy() - 2) * (1 << PADN);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  0 <= xL0 + k*deltaXL <= (up->getLx() - 2)*(1<<PADN)
Shinya Kitaoka 120a6e
  //               <=>
Shinya Kitaoka 120a6e
  //  0 <= xL0 + k*deltaXL <= lxPred
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  0 <= yL0 + k*deltaYL <= (up->getLy() - 2)*(1<<PADN)
Shinya Kitaoka 120a6e
  //               <=>
Shinya Kitaoka 120a6e
  //  0 <= yL0 + k*deltaYL <= lyPred
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  calcola kMinY, kMaxY intersecando la (2) con i lati
Shinya Kitaoka 120a6e
  //  (y = yMin) e (y = yMax) di up
Shinya Kitaoka 120a6e
  if (deltaYL > 0)  //  (deltaYL != 0)
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    //  [a, b] interno ad up contratto
Shinya Kitaoka 120a6e
    assert(yL0 <= lyPred);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    kMaxY = (lyPred - yL0) / deltaYL;  //  floor
Shinya Kitaoka 120a6e
    if (yL0 < 0) {
Shinya Kitaoka 120a6e
      kMinY = ((-yL0) + deltaYL - 1) / deltaYL;  //  ceil
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else  //  (deltaYL < 0)
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    //  [a, b] interno ad up contratto
Shinya Kitaoka 120a6e
    assert(0 <= yL0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    kMaxY = yL0 / (-deltaYL);  //  floor
Shinya Kitaoka 120a6e
    if (lyPred < yL0) {
Shinya Kitaoka 120a6e
      kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL);  //  ceil
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  //  calcola kMinY, kMaxY effettuando anche il clippind su dn
Shinya Kitaoka 120a6e
  kMinY = std::max(kMinY, (int)0);
Shinya Kitaoka 120a6e
  kMaxY = std::min(kMaxY, yMax - yMin);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  calcola kMinX, kMaxX intersecando la (2) con i lati
Shinya Kitaoka 120a6e
  //  (x = xMin) e (x = xMax) di up
Shinya Kitaoka 120a6e
  if (deltaXL > 0)  //  (deltaXL != 0)
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    //  [a, b] interno ad up contratto
Shinya Kitaoka 120a6e
    assert(xL0 <= lxPred);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    kMaxX = (lxPred - xL0) / deltaXL;  //  floor
Shinya Kitaoka 120a6e
    if (xL0 < 0) {
Shinya Kitaoka 120a6e
      kMinX = ((-xL0) + deltaXL - 1) / deltaXL;  //  ceil
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else  //  (deltaXL < 0)
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    //  [a, b] interno ad up contratto
Shinya Kitaoka 120a6e
    assert(0 <= xL0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    kMaxX = xL0 / (-deltaXL);  //  floor
Shinya Kitaoka 120a6e
    if (lxPred < xL0) {
Shinya Kitaoka 120a6e
      kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL);  //  ceil
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  //  calcola kMinX, kMaxX effettuando anche il clippind su dn
Shinya Kitaoka 120a6e
  kMinX = std::max(kMinX, (int)0);
Shinya Kitaoka 120a6e
  kMaxX = std::min(kMaxX, xMax - xMin);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int dnWrap = dn->getWrap();
Shinya Kitaoka 120a6e
  int upWrap = up->getWrap();
Shinya Kitaoka 120a6e
  dn->lock();
Shinya Kitaoka 120a6e
  up->lock();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TPixel32 *upBasePix = up->pixels();
Shinya Kitaoka 120a6e
  TPixel32 *dnRow     = dn->pixels(yMin + kMinY);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  (xL, yL) sono le coordinate (inizializzate per il round)
Shinya Kitaoka 120a6e
  //  in versione "TLonghizzata"
Shinya Kitaoka 120a6e
  //  del pixel corrente di up
Shinya Kitaoka 120a6e
  int yL = yL0 + (kMinY - 1) * deltaYL;  //  inizializza yL
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  long c1;
Shinya Kitaoka 120a6e
  long c2;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  long c3;
Shinya Kitaoka 120a6e
  long c4;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  long c5;
Shinya Kitaoka 120a6e
  long c6;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  long s_rg;
Shinya Kitaoka 120a6e
  long s_br;
Shinya Kitaoka 120a6e
  long s_gb;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  UINT32 rColDownTmp;
Shinya Kitaoka 120a6e
  UINT32 gColDownTmp;
Shinya Kitaoka 120a6e
  UINT32 bColDownTmp;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  UINT32 rColUpTmp;
Shinya Kitaoka 120a6e
  UINT32 gColUpTmp;
Shinya Kitaoka 120a6e
  UINT32 bColUpTmp;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int xI;
Shinya Kitaoka 120a6e
  TPixel32 *upPix00;
Shinya Kitaoka 120a6e
  TPixel32 *upPix10;
Shinya Kitaoka 120a6e
  TPixel32 *upPix01;
Shinya Kitaoka 120a6e
  TPixel32 *upPix11;
Shinya Kitaoka 120a6e
  int xWeight1;
Shinya Kitaoka 120a6e
  int xWeight0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  unsigned char rCol;
Shinya Kitaoka 120a6e
  unsigned char gCol;
Shinya Kitaoka 120a6e
  unsigned char bCol;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int xL;
Shinya Kitaoka 120a6e
  int yI;
Shinya Kitaoka 120a6e
  int yWeight1;
Shinya Kitaoka 120a6e
  int yWeight0;
Shinya Kitaoka 120a6e
  TPixel32 *dnPix;
Shinya Kitaoka 120a6e
  TPixel32 *dnEndPix;
Shinya Kitaoka 120a6e
  int kY = kMinY;
Shinya Kitaoka 120a6e
  ++kMaxY;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  scorre le scanline di boundingBoxD
Shinya Kitaoka 120a6e
  for (; kY < kMaxY - 32; kY++, dnRow += dnWrap) {
Shinya Kitaoka 120a6e
    EXTERNAL_LOOP_THE_SECOND_X_32
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  for (; kY < kMaxY - 16; kY++, dnRow += dnWrap) {
Shinya Kitaoka 120a6e
    EXTERNAL_LOOP_THE_SECOND_X_16
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  for (; kY < kMaxY - 8; kY++, dnRow += dnWrap) {
Shinya Kitaoka 120a6e
    EXTERNAL_LOOP_THE_SECOND_X_8
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  for (; kY < kMaxY - 4; kY++, dnRow += dnWrap) {
Shinya Kitaoka 120a6e
    EXTERNAL_LOOP_THE_SECOND_X_4
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  for (; kY < kMaxY - 2; kY++, dnRow += dnWrap) {
Shinya Kitaoka 120a6e
    EXTERNAL_LOOP_THE_SECOND_X_2
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  for (; kY < kMaxY; kY++, dnRow += dnWrap) {
Shinya Kitaoka 120a6e
    EXTERNAL_LOOP_THE_SECOND
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  dn->unlock();
Shinya Kitaoka 120a6e
  up->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// namespace
shun-iwasawa 84ffc5
};  // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifndef TNZCORE_LIGHT
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
// quickPut (paletted)
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TRop::quickPut(const TRasterP &dn, const TRasterCM32P &upCM32,
Shinya Kitaoka 120a6e
                    const TPaletteP &plt, const TAffine &aff,
Shinya Kitaoka 120a6e
                    const TPixel32 &globalColorScale, bool inksOnly) {
Shinya Kitaoka 120a6e
  TRaster32P dn32 = dn;
Shinya Kitaoka 120a6e
  if (dn32 && upCM32)
Shinya Kitaoka 120a6e
    if (areAlmostEqual(aff.a12, 0) && areAlmostEqual(aff.a21, 0))
Shinya Kitaoka 120a6e
      doQuickPutCmapped(dn32, upCM32, plt, aff.a11, aff.a22, aff.a13, aff.a23,
Shinya Kitaoka 120a6e
                        globalColorScale, inksOnly);
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      doQuickPutCmapped(dn32, upCM32, plt, aff, globalColorScale, inksOnly);
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    throw TRopException("raster type mismatch");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
// quickPut (paletted + transparency check + ink check + paint check)
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 38fd86
void TRop::quickPut(const TRasterP &dn, const TRasterCM32P &upCM32,
Shinya Kitaoka 38fd86
                    const TPaletteP &plt, const TAffine &aff,
Shinya Kitaoka 38fd86
                    const CmappedQuickputSettings &settings)  // const TPixel32&
Shinya Kitaoka 38fd86
// globalColorScale, bool
Shinya Kitaoka 38fd86
// inksOnly, bool
Shinya Kitaoka 38fd86
// transparencyCheck, bool
Shinya Kitaoka 38fd86
// blackBgCheck, int inkIndex, int
Shinya Kitaoka 38fd86
// paintIndex)
Toshihiro Shimizu 890ddd
{
Shinya Kitaoka 120a6e
  TRaster32P dn32 = dn;
Shinya Kitaoka 120a6e
  if (dn32 && upCM32)
Shinya Kitaoka 120a6e
    doQuickPutCmapped(dn32, upCM32, plt, aff,
Shinya Kitaoka 120a6e
                      settings);  // globalColorScale, inksOnly,
Shinya Kitaoka 120a6e
                                  // transparencyCheck, blackBgCheck, inkIndex,
Shinya Kitaoka 120a6e
                                  // paintIndex);
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    throw TRopException("raster type mismatch");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TRop::quickResampleColorFilter(const TRasterP &dn, const TRasterP &up,
Shinya Kitaoka 120a6e
                                    const TAffine &aff, const TPaletteP &plt,
Shinya Kitaoka 120a6e
                                    UCHAR colorMask) {
Shinya Kitaoka 120a6e
  TRaster32P dn32     = dn;
Shinya Kitaoka 120a6e
  TRaster32P up32     = up;
Shinya Kitaoka 120a6e
  TRaster64P up64     = up;
Shinya Kitaoka 120a6e
  TRasterCM32P upCM32 = up;
Shinya Kitaoka 120a6e
  if (dn32 && up32)
Shinya Kitaoka 120a6e
    doQuickResampleColorFilter(dn32, up32, aff, colorMask);
Shinya Kitaoka 120a6e
  else if (dn32 && upCM32)
Shinya Kitaoka 120a6e
    doQuickResampleColorFilter(dn32, upCM32, plt, aff, colorMask);
Shinya Kitaoka 120a6e
  else if (dn32 && up64)
Shinya Kitaoka 120a6e
    doQuickResampleColorFilter(dn32, up64, aff, colorMask);
Shinya Kitaoka 120a6e
  // else if (dn32 && upCM32)
Shinya Kitaoka 120a6e
  //  doQuickResampleColorFilter(dn32, upCM32, aff, plt, colorMask);
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    throw TRopException("raster type mismatch");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
#endif  // TNZCORE_LIGHT
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
// quickPut (Bilinear/Closest)
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void quickPut(const TRasterP &dn, const TRasterP &up, const TAffine &aff,
Shinya Kitaoka 120a6e
              TRop::ResampleFilterType filterType, const TPixel32 &colorScale,
Shinya Kitaoka 120a6e
              bool doPremultiply, bool whiteTransp, bool firstColumn,
Shinya Kitaoka 120a6e
              bool doRasterDarkenBlendedView) {
Shinya Kitaoka 120a6e
  assert(filterType == TRop::Bilinear || filterType == TRop::ClosestPixel);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  bool bilinear = filterType == TRop::Bilinear;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRaster32P dn32 = dn;
Shinya Kitaoka 120a6e
  TRaster32P up32 = up;
Shinya Kitaoka 120a6e
  TRasterGR8P dn8 = dn;
Shinya Kitaoka 120a6e
  TRasterGR8P up8 = up;
shun-iwasawa 215a5b
  TRaster64P dn64 = dn;
Shinya Kitaoka 120a6e
  TRaster64P up64 = up;
shun-iwasawa 481b59
  TRasterFP upF   = up;
shun-iwasawa 481b59
  TRasterFP dnF   = dn;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (up8 && dn32) {
Shinya Kitaoka 120a6e
    assert(filterType == TRop::ClosestPixel);
Shinya Kitaoka 120a6e
    if (areAlmostEqual(aff.a12, 0) && areAlmostEqual(aff.a21, 0))
Shinya Kitaoka 120a6e
      doQuickPutNoFilter(dn32, up8, aff.a11, aff.a22, aff.a13, aff.a23,
Shinya Kitaoka 120a6e
                         colorScale);
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      doQuickPutNoFilter(dn32, up8, aff, colorScale);
Shinya Kitaoka 120a6e
  } else if (dn32 && up32) {
shun-iwasawa 27b0cf
    if (areAlmostEqual(aff.a12, 0) && areAlmostEqual(aff.a21, 0)) {
Shinya Kitaoka 120a6e
      if (bilinear)
Shinya Kitaoka 120a6e
        doQuickPutFilter(dn32, up32, aff.a11, aff.a22, aff.a13, aff.a23);
shun_iwasawa 21a6b6
      else {
Shinya Kitaoka 120a6e
        doQuickPutNoFilter(dn32, up32, aff.a11, aff.a22, aff.a13, aff.a23,
shun-iwasawa 27b0cf
                           colorScale, doPremultiply, whiteTransp, firstColumn,
shun-iwasawa 27b0cf
                           doRasterDarkenBlendedView);
shun_iwasawa 21a6b6
      }
shun-iwasawa 27b0cf
    } else if (bilinear)
Shinya Kitaoka 120a6e
      doQuickPutFilter(dn32, up32, aff);
shun_iwasawa 21a6b6
    else {
Shinya Kitaoka 120a6e
      doQuickPutNoFilter(dn32, up32, aff, colorScale, doPremultiply,
shun-iwasawa 27b0cf
                         whiteTransp, firstColumn, doRasterDarkenBlendedView);
shun_iwasawa 21a6b6
    }
Shinya Kitaoka 120a6e
  } else if (dn32 && up64)
Shinya Kitaoka 120a6e
    doQuickPutNoFilter(dn32, up64, aff, doPremultiply, firstColumn);
shun-iwasawa 215a5b
  else if (dn64 && up64)
shun-iwasawa 215a5b
    doQuickPutNoFilter(dn64, up64, aff, doPremultiply, firstColumn);
shun-iwasawa 215a5b
  else if (dn64 && up32)
shun-iwasawa 215a5b
    doQuickPutNoFilter(dn64, up32, aff, doPremultiply, firstColumn);
shun-iwasawa 481b59
  else if (dn64 && upF)
shun-iwasawa 481b59
    doQuickPutNoFilter(dn64, upF, aff, doPremultiply, firstColumn);
shun-iwasawa 481b59
  else if (dnF && upF)
shun-iwasawa 481b59
    doQuickPutNoFilter(dnF, upF, aff, doPremultiply, firstColumn);
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    throw TRopException("raster type mismatch");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
template <typename PIX>
Shinya Kitaoka 120a6e
void doQuickResampleNoFilter(const TRasterPT<PIX> &dn, const TRasterPT<PIX> &up,
Shinya Kitaoka 120a6e
                             const TAffine &aff) {
Shinya Kitaoka 120a6e
  //  se aff := TAffine(sx, 0, tx, 0, sy, ty) e' degenere la controimmagine
Shinya Kitaoka 120a6e
  //  di up e' un segmento (o un punto)
Shinya Kitaoka 120a6e
  if ((aff.a11 * aff.a22 - aff.a12 * aff.a21) == 0) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  contatore bit di shift
Shinya Kitaoka 120a6e
  const int PADN = 16;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  max dimensioni di up gestibili (limite imposto dal numero di bit
Shinya Kitaoka 120a6e
  //  disponibili per la parte intera di xL, yL)
Shinya Kitaoka 120a6e
  assert(std::max(up->getLx(), up->getLy()) <
Shinya Kitaoka 120a6e
         (1 << (8 * sizeof(int) - PADN - 1)));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRectD boundingBoxD =
Shinya Kitaoka 120a6e
      TRectD(convert(dn->getBounds())) *
Shinya Kitaoka 120a6e
      (aff * TRectD(-0.5, -0.5, up->getLx() - 0.5, up->getLy() - 0.5));
Shinya Kitaoka 120a6e
  //  clipping
Shinya Kitaoka 120a6e
  if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1)
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int yMin = std::max(tfloor(boundingBoxD.y0), 0);  //  clipping y su dn
Shinya Kitaoka 120a6e
  int yMax =
Shinya Kitaoka 120a6e
      std::min(tceil(boundingBoxD.y1), dn->getLy() - 1);  //  clipping y su dn
Shinya Kitaoka 120a6e
  int xMin = std::max(tfloor(boundingBoxD.x0), 0);        //  clipping x su dn
Shinya Kitaoka 120a6e
  int xMax =
Shinya Kitaoka 120a6e
      std::min(tceil(boundingBoxD.x1), dn->getLx() - 1);  //  clipping x su dn
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TAffine invAff = inv(aff);  //  inversa di aff
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  nel disegnare la y-esima scanline di dn, il passaggio al pixel
Shinya Kitaoka 120a6e
  //  successivo comporta l'incremento (deltaXD, deltaYD) delle coordinate
Shinya Kitaoka 120a6e
  //  del pixel corrispondente di up
Shinya Kitaoka 120a6e
  double deltaXD = invAff.a11;
Shinya Kitaoka 120a6e
  double deltaYD = invAff.a21;
Shinya Kitaoka 120a6e
  int deltaXL =
Shinya Kitaoka 120a6e
      tround(deltaXD * (1 << PADN));  //  deltaXD "TLonghizzato" (round)
Shinya Kitaoka 120a6e
  int deltaYL =
Shinya Kitaoka 120a6e
      tround(deltaYD * (1 << PADN));  //  deltaYD "TLonghizzato" (round)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  se aff "TLonghizzata" (round) e' degenere la controimmagine di up e'
Shinya Kitaoka 120a6e
  //  un segmento (o un punto)
Shinya Kitaoka 120a6e
  if ((deltaXL == 0) && (deltaYL == 0)) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int lxPred =
Shinya Kitaoka 120a6e
      up->getLx() * (1 << PADN) - 1;  //  TINT32 predecessore di up->getLx()
Shinya Kitaoka 120a6e
  int lyPred =
Shinya Kitaoka 120a6e
      up->getLy() * (1 << PADN) - 1;  //  TINT32 predecessore di up->getLy()
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int dnWrap = dn->getWrap();
Shinya Kitaoka 120a6e
  int upWrap = up->getWrap();
Shinya Kitaoka 120a6e
  dn->lock();
Shinya Kitaoka 120a6e
  up->lock();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  PIX *dnRow     = dn->pixels(yMin);
Shinya Kitaoka 120a6e
  PIX *upBasePix = up->pixels();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  scorre le scanline di boundingBoxD
Shinya Kitaoka 120a6e
  for (int y = yMin; y <= yMax; y++, dnRow += dnWrap) {
Shinya Kitaoka 120a6e
    //  (1)  equazione k-parametrica della y-esima scanline di boundingBoxD:
Shinya Kitaoka 120a6e
    //         (xMin, y) + k*(1, 0),
Shinya Kitaoka 120a6e
    //           k = 0, ..., (xMax - xMin)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  (2)  equazione k-parametrica dell'immagine mediante invAff di (1):
Shinya Kitaoka 120a6e
    //         invAff*(xMin, y) + k*(deltaXD, deltaYD),
Shinya Kitaoka 120a6e
    //           k = kMin, ..., kMax
Shinya Kitaoka 120a6e
    //           con 0 <= kMin <= kMax <= (xMax - xMin)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  calcola kMin, kMax per la scanline corrente intersecando
Shinya Kitaoka 120a6e
    //  la (2) con i lati di up
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  il segmento [a, b] di up e' la controimmagine mediante aff della
Shinya Kitaoka 120a6e
    //  porzione di scanline  [ (xMin, y), (xMax, y) ] di dn
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  TPointD b = invAff*TPointD(xMax, y);
Shinya Kitaoka 120a6e
    TPointD a = invAff * TPointD(xMin, y);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  (xL0, yL0) sono le coordinate di a (inizializzate per il round)
Shinya Kitaoka 120a6e
    //  in versione "TLonghizzata"
Shinya Kitaoka 120a6e
    //  0 <= xL0 + k*deltaXL < up->getLx()*(1<<PADN),
Shinya Kitaoka 120a6e
    //  0 <= kMinX <= kMin <= k <= kMax <= kMaxX <= (xMax - xMin)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  0 <= yL0 + k*deltaYL < up->getLy()*(1<<PADN),
Shinya Kitaoka 120a6e
    //  0 <= kMinY <= kMin <= k <= kMax <= kMaxY <= (xMax - xMin)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  xL0 inizializzato per il round
Shinya Kitaoka 120a6e
    int xL0 = tround((a.x + 0.5) * (1 << PADN));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  yL0 inizializzato per il round
Shinya Kitaoka 120a6e
    int yL0 = tround((a.y + 0.5) * (1 << PADN));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  calcola kMinX, kMaxX, kMinY, kMaxY
Shinya Kitaoka 120a6e
    int kMinX = 0, kMaxX = xMax - xMin;  //  clipping su dn
Shinya Kitaoka 120a6e
    int kMinY = 0, kMaxY = xMax - xMin;  //  clipping su dn
Shinya Kitaoka 120a6e
    //  0 <= xL0 + k*deltaXL < up->getLx()*(1<<PADN)
Shinya Kitaoka 120a6e
    //               <=>
Shinya Kitaoka 120a6e
    //  0 <= xL0 + k*eltaXL <= lxPred
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  0 <= yL0 + k*deltaYL < up->getLy()*(1<<PADN)
Shinya Kitaoka 120a6e
    //               <=>
Shinya Kitaoka 120a6e
    //  0 <= yL0 + k*deltaYL <= lyPred
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  calcola kMinX, kMaxX
Shinya Kitaoka 120a6e
    if (deltaXL == 0) {
Shinya Kitaoka 120a6e
      //  [a, b] verticale esterno ad up+(bordo destro/basso)
Shinya Kitaoka 120a6e
      if ((xL0 < 0) || (lxPred < xL0)) continue;
Shinya Kitaoka 120a6e
      //  altrimenti usa solo
Shinya Kitaoka 120a6e
      //  kMinY, kMaxY ((deltaXL != 0) || (deltaYL != 0))
Shinya Kitaoka 120a6e
    } else if (deltaXL > 0) {
Shinya Kitaoka 120a6e
      //  [a, b] esterno ad up+(bordo destro/basso)
Shinya Kitaoka 120a6e
      if (lxPred < xL0) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      kMaxX = (lxPred - xL0) / deltaXL;  //  floor
Shinya Kitaoka 120a6e
      if (xL0 < 0) {
Shinya Kitaoka 120a6e
        kMinX = ((-xL0) + deltaXL - 1) / deltaXL;  //  ceil
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else  //  (deltaXL < 0)
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      // [a, b] esterno ad up+(bordo destro/basso)
Shinya Kitaoka 120a6e
      if (xL0 < 0) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      kMaxX = xL0 / (-deltaXL);  //  floor
Shinya Kitaoka 120a6e
      if (lxPred < xL0) {
Shinya Kitaoka 120a6e
        kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL);  //  ceil
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  calcola kMinY, kMaxY
Shinya Kitaoka 120a6e
    if (deltaYL == 0) {
Shinya Kitaoka 120a6e
      //  [a, b] orizzontale esterno ad up+(bordo destro/basso)
Shinya Kitaoka 120a6e
      if ((yL0 < 0) || (lyPred < yL0)) continue;
Shinya Kitaoka 120a6e
      //  altrimenti usa solo
Shinya Kitaoka 120a6e
      //  kMinX, kMaxX ((deltaXL != 0) || (deltaYL != 0))
Shinya Kitaoka 120a6e
    } else if (deltaYL > 0) {
Shinya Kitaoka 120a6e
      //  [a, b] esterno ad up+(bordo destro/basso)
Shinya Kitaoka 120a6e
      if (lyPred < yL0) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      kMaxY = (lyPred - yL0) / deltaYL;  //  floor
Shinya Kitaoka 120a6e
      if (yL0 < 0) {
Shinya Kitaoka 120a6e
        kMinY = ((-yL0) + deltaYL - 1) / deltaYL;  //  ceil
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else  //  (deltaYL < 0)
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      //  [a, b] esterno ad up+(bordo destro/basso)
Shinya Kitaoka 120a6e
      if (yL0 < 0) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      kMaxY = yL0 / (-deltaYL);  //  floor
Shinya Kitaoka 120a6e
      if (lyPred < yL0) {
Shinya Kitaoka 120a6e
        kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL);  //  ceil
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  calcola kMin, kMax effettuando anche il clippind su dn
Shinya Kitaoka 120a6e
    int kMin = std::max({kMinX, kMinY, (int)0});
Shinya Kitaoka 120a6e
    int kMax = std::min({kMaxX, kMaxY, xMax - xMin});
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    PIX *dnPix    = dnRow + xMin + kMin;
Shinya Kitaoka 120a6e
    PIX *dnEndPix = dnRow + xMin + kMax + 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  (xL, yL) sono le coordinate (inizializzate per il round)
Shinya Kitaoka 120a6e
    //  in versione "TLonghizzata" del pixel corrente di up
Shinya Kitaoka 120a6e
    int xL = xL0 + (kMin - 1) * deltaXL;  //  inizializza xL
Shinya Kitaoka 120a6e
    int yL = yL0 + (kMin - 1) * deltaYL;  //  inizializza yL
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //  scorre i pixel sulla y-esima scanline di boundingBoxD
Shinya Kitaoka 120a6e
    for (; dnPix < dnEndPix; ++dnPix) {
Shinya Kitaoka 120a6e
      xL += deltaXL;
Shinya Kitaoka 120a6e
      yL += deltaYL;
Shinya Kitaoka 120a6e
      //  il punto di up TPointD(xL/(1<
Shinya Kitaoka 120a6e
      //  approssimato con (xI, yI)
Shinya Kitaoka 120a6e
      int xI = xL >> PADN;  //  round
Shinya Kitaoka 120a6e
      int yI = yL >> PADN;  //  round
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      assert((0 <= xI) && (xI <= up->getLx() - 1) && (0 <= yI) &&
Shinya Kitaoka 120a6e
             (yI <= up->getLy() - 1));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      *dnPix = *(upBasePix + (yI * upWrap + xI));
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  dn->unlock();
Shinya Kitaoka 120a6e
  up->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef OPTIMIZE_FOR_LP64
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void quickResample_optimized(const TRasterP &dn, const TRasterP &up,
Shinya Kitaoka 120a6e
                             const TAffine &aff,
Shinya Kitaoka 120a6e
                             TRop::ResampleFilterType filterType) {
Shinya Kitaoka 120a6e
  assert(filterType == TRop::Bilinear || filterType == TRop::ClosestPixel);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  bool bilinear = filterType == TRop::Bilinear;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRaster32P dn32 = dn;
Shinya Kitaoka 120a6e
  TRaster32P up32 = up;
Shinya Kitaoka 120a6e
  TRasterGR8P dn8 = dn;
Shinya Kitaoka 120a6e
  TRasterGR8P up8 = up;
Shinya Kitaoka 120a6e
  if (dn32 && up32)
Shinya Kitaoka 120a6e
    if (areAlmostEqual(aff.a12, 0) && areAlmostEqual(aff.a21, 0))
Shinya Kitaoka 120a6e
      if (bilinear)
Shinya Kitaoka 120a6e
        doQuickResampleFilter_optimized(dn32, up32, aff.a11, aff.a22, aff.a13,
Shinya Kitaoka 120a6e
                                        aff.a23);
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        doQuickResampleNoFilter(dn32, up32, aff.a11, aff.a22, aff.a13, aff.a23);
Shinya Kitaoka 120a6e
    else if (bilinear)
Shinya Kitaoka 120a6e
      doQuickResampleFilter_optimized(dn32, up32, aff);
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      doQuickResampleNoFilter(dn32, up32, aff);
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    throw TRopException("raster type mismatch");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void quickResample(const TRasterP &dn, const TRasterP &up, const TAffine &aff,
Shinya Kitaoka 120a6e
                   TRop::ResampleFilterType filterType) {
Toshihiro Shimizu 890ddd
#ifdef OPTIMIZE_FOR_LP64
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  quickResample_optimized(dn, up, aff, filterType);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  assert(filterType == TRop::Bilinear || filterType == TRop::ClosestPixel);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  bool bilinear = filterType == TRop::Bilinear;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRaster32P dn32     = dn;
Shinya Kitaoka 120a6e
  TRaster32P up32     = up;
Shinya Kitaoka 120a6e
  TRasterCM32P dnCM32 = dn;
Shinya Kitaoka 120a6e
  TRasterCM32P upCM32 = up;
Shinya Kitaoka 120a6e
  TRasterGR8P dn8     = dn;
Shinya Kitaoka 120a6e
  TRasterGR8P up8     = up;
Shinya Kitaoka 120a6e
  dn->clear();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (bilinear) {
Shinya Kitaoka 120a6e
    if (dn32 && up32) {
Shinya Kitaoka 120a6e
      if (areAlmostEqual(aff.a12, 0) && areAlmostEqual(aff.a21, 0))
Shinya Kitaoka 120a6e
        doQuickResampleFilter(dn32, up32, aff.a11, aff.a22, aff.a13, aff.a23);
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        doQuickResampleFilter(dn32, up32, aff);
Shinya Kitaoka 120a6e
    } else if (dn32 && up8) {
Shinya Kitaoka 120a6e
      if (areAlmostEqual(aff.a12, 0) && areAlmostEqual(aff.a21, 0))
Shinya Kitaoka 120a6e
        doQuickResampleFilter(dn32, up8, aff.a11, aff.a22, aff.a13, aff.a23);
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        doQuickResampleFilter(dn32, up8, aff);
Shinya Kitaoka 120a6e
    } else
Shinya Kitaoka 120a6e
      throw TRopException("raster type mismatch");
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    if (dn32 && up32) {
Shinya Kitaoka 120a6e
      if (areAlmostEqual(aff.a12, 0) && areAlmostEqual(aff.a21, 0))
Shinya Kitaoka 120a6e
        doQuickResampleNoFilter(dn32, up32, aff.a11, aff.a22, aff.a13, aff.a23);
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        doQuickResampleNoFilter(dn32, up32, aff);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    } else if (dnCM32 && upCM32) {
Shinya Kitaoka 120a6e
      if (areAlmostEqual(aff.a12, 0) && areAlmostEqual(aff.a21, 0))
Shinya Kitaoka 120a6e
        doQuickResampleNoFilter(dnCM32, upCM32, aff.a11, aff.a22, aff.a13,
Shinya Kitaoka 120a6e
                                aff.a23);
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        doQuickResampleNoFilter(dnCM32, upCM32, aff);
Shinya Kitaoka 120a6e
    } else if (dn8 && up8) {
Shinya Kitaoka 120a6e
      if (areAlmostEqual(aff.a12, 0) && areAlmostEqual(aff.a21, 0))
Shinya Kitaoka 120a6e
        doQuickResampleNoFilter(dn8, up8, aff.a11, aff.a22, aff.a13, aff.a23);
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        doQuickResampleNoFilter(dn8, up8, aff);
Shinya Kitaoka 120a6e
    } else
Shinya Kitaoka 120a6e
      throw TRopException("raster type mismatch");
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void quickPut(const TRasterP &out, const TRasterCM32P &up, const TAffine &aff,
Shinya Kitaoka 120a6e
              const TPixel32 &inkCol, const TPixel32 &paintCol);