Ejemplo n.º 1
0
QPainterPath SmoothCurveCreator::createSmoothCurve(const QList<QPointF> &points) {
    QPainterPath path;
    int len = points.size();

    if (len < 2) {
        return path;
    }

    QList<QPointF> firstControlPoints;
    QList<QPointF> secondControlPoints;
    calculateControlPoints(points, &firstControlPoints, &secondControlPoints);

    path.moveTo(points[0].x(), points[0].y());

    // Using bezier curve to gelnerate a smooth curve.
    for (int i = 0; i < len - 1; ++i) {
        path.cubicTo(firstControlPoints[i], secondControlPoints[i], points[i+1]);
    }

    return path;
}
Ejemplo n.º 2
0
void QgsCubicRasterResampler::resample( const QImage& srcImage, QImage& dstImage )
{
  int nCols = srcImage.width();
  int nRows = srcImage.height();

  int pos = 0;
  QRgb px;
  int *redMatrix = new int[ nCols * nRows ];
  int *greenMatrix = new int[ nCols * nRows ];
  int *blueMatrix = new int[ nCols * nRows ];
  int *alphaMatrix = new int[ nCols * nRows ];

  for ( int heightIndex = 0; heightIndex < nRows; ++heightIndex )
  {
    QRgb* scanLine = ( QRgb* )srcImage.constScanLine( heightIndex );
    for ( int widthIndex = 0; widthIndex < nCols; ++widthIndex )
    {
      px = scanLine[widthIndex];
      int alpha = qAlpha( px );
      alphaMatrix[pos] = alpha;
      redMatrix[pos] = qRed( px );
      greenMatrix[pos] = qGreen( px );
      blueMatrix[pos] = qBlue( px );

      pos++;
    }
  }

  //derivative x
  double* xDerivativeMatrixRed = new double[ nCols * nRows ];
  xDerivativeMatrix( nCols, nRows, xDerivativeMatrixRed, redMatrix );
  double* xDerivativeMatrixGreen = new double[ nCols * nRows ];
  xDerivativeMatrix( nCols, nRows, xDerivativeMatrixGreen, greenMatrix );
  double* xDerivativeMatrixBlue = new double[ nCols * nRows ];
  xDerivativeMatrix( nCols, nRows, xDerivativeMatrixBlue, blueMatrix );
  double* xDerivativeMatrixAlpha = new double[ nCols * nRows ];
  xDerivativeMatrix( nCols, nRows, xDerivativeMatrixAlpha, alphaMatrix );

  //derivative y
  double* yDerivativeMatrixRed = new double[ nCols * nRows ];
  yDerivativeMatrix( nCols, nRows, yDerivativeMatrixRed, redMatrix );
  double* yDerivativeMatrixGreen = new double[ nCols * nRows ];
  yDerivativeMatrix( nCols, nRows, yDerivativeMatrixGreen, greenMatrix );
  double* yDerivativeMatrixBlue = new double[ nCols * nRows ];
  yDerivativeMatrix( nCols, nRows, yDerivativeMatrixBlue, blueMatrix );
  double* yDerivativeMatrixAlpha = new double[ nCols * nRows ];
  yDerivativeMatrix( nCols, nRows, yDerivativeMatrixAlpha, alphaMatrix );

  //compute output
  double nSrcPerDstX = ( double ) srcImage.width() / ( double ) dstImage.width();
  double nSrcPerDstY = ( double ) srcImage.height() / ( double ) dstImage.height();

  double currentSrcRow = nSrcPerDstY / 2.0 - 0.5;
  double currentSrcCol;
  int currentSrcColInt;
  int currentSrcRowInt;
  int lastSrcColInt = -100;
  int lastSrcRowInt = -100;

  //bernstein polynomials
  double bp0u, bp1u, bp2u, bp3u, bp0v, bp1v, bp2v, bp3v;
  double u, v;

  for ( int y = 0; y < dstImage.height(); ++y )
  {
    currentSrcRowInt = floor( currentSrcRow );
    v = currentSrcRow - currentSrcRowInt;

    currentSrcCol = nSrcPerDstX / 2.0 - 0.5;

    QRgb* scanLine = ( QRgb* )dstImage.scanLine( y );
    for ( int x = 0; x < dstImage.width(); ++x )
    {
      currentSrcColInt = floor( currentSrcCol );
      u = currentSrcCol - currentSrcColInt;

      //handle eight edge-cases
      if (( currentSrcRowInt < 0 || currentSrcRowInt >= ( srcImage.height() - 1 ) || currentSrcColInt < 0 || currentSrcColInt >= ( srcImage.width() - 1 ) ) )
      {
        QRgb px1, px2;
        //pixels at the border of the source image needs to be handled in a special way
        if ( currentSrcRowInt < 0 && currentSrcColInt < 0 )
        {
          scanLine[x] = srcImage.pixel( 0, 0 );
        }
        else if ( currentSrcRowInt < 0 && currentSrcColInt >= ( srcImage.width() - 1 ) )
        {
          scanLine[x] = srcImage.pixel( srcImage.width() - 1, 0 );
        }
        else if ( currentSrcRowInt >= ( srcImage.height() - 1 ) && currentSrcColInt >= ( srcImage.width() - 1 ) )
        {
          scanLine[x] = srcImage.pixel( srcImage.width() - 1, srcImage.height() - 1 );
        }
        else if ( currentSrcRowInt >= ( srcImage.height() - 1 ) && currentSrcColInt < 0 )
        {
          scanLine[x] = srcImage.pixel( 0, srcImage.height() - 1 );
        }
        else if ( currentSrcRowInt < 0 )
        {
          px1 = srcImage.pixel( currentSrcColInt, 0 );
          px2 = srcImage.pixel( currentSrcColInt + 1, 0 );
          scanLine[x] = curveInterpolation( px1, px2, u, xDerivativeMatrixRed[ currentSrcColInt ], xDerivativeMatrixGreen[ currentSrcColInt ],
                                            xDerivativeMatrixBlue[ currentSrcColInt ], xDerivativeMatrixAlpha[ currentSrcColInt ], xDerivativeMatrixRed[ currentSrcColInt + 1 ], xDerivativeMatrixGreen[ currentSrcColInt + 1 ],
                                            xDerivativeMatrixBlue[ currentSrcColInt + 1 ], xDerivativeMatrixAlpha[ currentSrcColInt + 1 ] );
        }
        else if ( currentSrcRowInt >= ( srcImage.height() - 1 ) )
        {
          int idx = ( srcImage.height() - 1 ) * srcImage.width() + currentSrcColInt;
          px1 = srcImage.pixel( currentSrcColInt, srcImage.height() - 1 );
          px2 = srcImage.pixel( currentSrcColInt + 1, srcImage.height() - 1 );
          scanLine[x] = curveInterpolation( px1, px2, u, xDerivativeMatrixRed[ idx ], xDerivativeMatrixGreen[ idx ], xDerivativeMatrixBlue[idx],
                                            xDerivativeMatrixAlpha[idx], xDerivativeMatrixRed[ idx + 1 ], xDerivativeMatrixGreen[ idx + 1 ], xDerivativeMatrixBlue[idx + 1],
                                            xDerivativeMatrixAlpha[idx + 1] );
        }
        else if ( currentSrcColInt < 0 )
        {
          int idx1 = currentSrcRowInt * srcImage.width();
          int idx2 = idx1 + srcImage.width();
          px1 = srcImage.pixel( 0, currentSrcRowInt );
          px2 = srcImage.pixel( 0, currentSrcRowInt + 1 );
          scanLine[x] = curveInterpolation( px1, px2, v, yDerivativeMatrixRed[ idx1 ], yDerivativeMatrixGreen[ idx1 ], yDerivativeMatrixBlue[ idx1],
                                            yDerivativeMatrixAlpha[ idx1], yDerivativeMatrixRed[ idx2 ], yDerivativeMatrixGreen[ idx2 ], yDerivativeMatrixBlue[ idx2],
                                            yDerivativeMatrixAlpha[ idx2] );
        }
        else if ( currentSrcColInt >= ( srcImage.width() - 1 ) )
        {
          int idx1 = currentSrcRowInt * srcImage.width() + srcImage.width() - 1;
          int idx2 = idx1 + srcImage.width();
          px1 = srcImage.pixel( srcImage.width() - 1, currentSrcRowInt );
          px2 = srcImage.pixel( srcImage.width() - 1, currentSrcRowInt + 1 );
          scanLine[x] = curveInterpolation( px1, px2, v, yDerivativeMatrixRed[ idx1 ], yDerivativeMatrixGreen[ idx1 ], yDerivativeMatrixBlue[ idx1],
                                            yDerivativeMatrixAlpha[ idx1], yDerivativeMatrixRed[ idx2 ], yDerivativeMatrixGreen[ idx2 ], yDerivativeMatrixBlue[ idx2],
                                            yDerivativeMatrixAlpha[ idx2] );
        }
        currentSrcCol += nSrcPerDstX;
        continue;
      }

      //first update the control points if necessary
      if ( currentSrcColInt != lastSrcColInt || currentSrcRowInt != lastSrcRowInt )
      {
        calculateControlPoints( nCols, nRows, currentSrcRowInt, currentSrcColInt, redMatrix, greenMatrix, blueMatrix, alphaMatrix,
                                xDerivativeMatrixRed, xDerivativeMatrixGreen, xDerivativeMatrixBlue, xDerivativeMatrixAlpha,
                                yDerivativeMatrixRed, yDerivativeMatrixGreen, yDerivativeMatrixBlue, yDerivativeMatrixAlpha );
      }

      //bernstein polynomials
      bp0u = calcBernsteinPolyN3( 0, u );
      bp1u = calcBernsteinPolyN3( 1, u );
      bp2u = calcBernsteinPolyN3( 2, u );
      bp3u = calcBernsteinPolyN3( 3, u );
      bp0v = calcBernsteinPolyN3( 0, v );
      bp1v = calcBernsteinPolyN3( 1, v );
      bp2v = calcBernsteinPolyN3( 2, v );
      bp3v = calcBernsteinPolyN3( 3, v );

      //then calculate value based on bernstein form of Bezier patch
      //todo: move into function
      int r = bp0u * bp0v * cRed00 +
              bp1u * bp0v * cRed10 +
              bp2u * bp0v * cRed20 +
              bp3u * bp0v * cRed30 +
              bp0u * bp1v * cRed01 +
              bp1u * bp1v * cRed11 +
              bp2u * bp1v * cRed21 +
              bp3u * bp1v * cRed31 +
              bp0u * bp2v * cRed02 +
              bp1u * bp2v * cRed12 +
              bp2u * bp2v * cRed22 +
              bp3u * bp2v * cRed32 +
              bp0u * bp3v * cRed03 +
              bp1u * bp3v * cRed13 +
              bp2u * bp3v * cRed23 +
              bp3u * bp3v * cRed33;

      int g = bp0u * bp0v * cGreen00 +
              bp1u * bp0v * cGreen10 +
              bp2u * bp0v * cGreen20 +
              bp3u * bp0v * cGreen30 +
              bp0u * bp1v * cGreen01 +
              bp1u * bp1v * cGreen11 +
              bp2u * bp1v * cGreen21 +
              bp3u * bp1v * cGreen31 +
              bp0u * bp2v * cGreen02 +
              bp1u * bp2v * cGreen12 +
              bp2u * bp2v * cGreen22 +
              bp3u * bp2v * cGreen32 +
              bp0u * bp3v * cGreen03 +
              bp1u * bp3v * cGreen13 +
              bp2u * bp3v * cGreen23 +
              bp3u * bp3v * cGreen33;

      int b = bp0u * bp0v * cBlue00 +
              bp1u * bp0v * cBlue10 +
              bp2u * bp0v * cBlue20 +
              bp3u * bp0v * cBlue30 +
              bp0u * bp1v * cBlue01 +
              bp1u * bp1v * cBlue11 +
              bp2u * bp1v * cBlue21 +
              bp3u * bp1v * cBlue31 +
              bp0u * bp2v * cBlue02 +
              bp1u * bp2v * cBlue12 +
              bp2u * bp2v * cBlue22 +
              bp3u * bp2v * cBlue32 +
              bp0u * bp3v * cBlue03 +
              bp1u * bp3v * cBlue13 +
              bp2u * bp3v * cBlue23 +
              bp3u * bp3v * cBlue33;

      int a = bp0u * bp0v * cAlpha00 +
              bp1u * bp0v * cAlpha10 +
              bp2u * bp0v * cAlpha20 +
              bp3u * bp0v * cAlpha30 +
              bp0u * bp1v * cAlpha01 +
              bp1u * bp1v * cAlpha11 +
              bp2u * bp1v * cAlpha21 +
              bp3u * bp1v * cAlpha31 +
              bp0u * bp2v * cAlpha02 +
              bp1u * bp2v * cAlpha12 +
              bp2u * bp2v * cAlpha22 +
              bp3u * bp2v * cAlpha32 +
              bp0u * bp3v * cAlpha03 +
              bp1u * bp3v * cAlpha13 +
              bp2u * bp3v * cAlpha23 +
              bp3u * bp3v * cAlpha33;

      scanLine[x] = createPremultipliedColor( r, g, b, a );

      lastSrcColInt = currentSrcColInt;
      currentSrcCol += nSrcPerDstX;
    }
    lastSrcRowInt = currentSrcRowInt;
    currentSrcRow += nSrcPerDstY;
  }


  //cleanup memory
  delete[] redMatrix;
  delete[] greenMatrix;
  delete[] blueMatrix;
  delete[] alphaMatrix;
  delete[] xDerivativeMatrixRed;
  delete[] xDerivativeMatrixGreen;
  delete[] xDerivativeMatrixBlue;
  delete[] xDerivativeMatrixAlpha;
  delete[] yDerivativeMatrixRed;
  delete[] yDerivativeMatrixGreen;
  delete[] yDerivativeMatrixBlue;
  delete[] yDerivativeMatrixAlpha;
}