37    void imageColors( QHash<QRgb, int> &colors, 
const QImage &image )
 
   40      const int width = image.width();
 
   41      const int height = image.height();
 
   43      const QRgb *currentScanLine = 
nullptr;
 
   44      QHash<QRgb, int>::iterator colorIt;
 
   45      for ( 
int i = 0; i < height; ++i )
 
   47        currentScanLine = ( 
const QRgb * )( image.scanLine( i ) );
 
   48        for ( 
int j = 0; j < width; ++j )
 
   50          colorIt = colors.find( currentScanLine[j] );
 
   51          if ( colorIt == colors.end() )
 
   53            colors.insert( currentScanLine[j], 1 );
 
   63    bool minMaxRange( 
const QgsColorBox &colorBox, 
int &redRange, 
int &greenRange, 
int &blueRange, 
int &alphaRange )
 
   65      if ( colorBox.size() < 1 )
 
   70      int rMin = std::numeric_limits<int>::max();
 
   71      int gMin = std::numeric_limits<int>::max();
 
   72      int bMin = std::numeric_limits<int>::max();
 
   73      int aMin = std::numeric_limits<int>::max();
 
   74      int rMax = std::numeric_limits<int>::min();
 
   75      int gMax = std::numeric_limits<int>::min();
 
   76      int bMax = std::numeric_limits<int>::min();
 
   77      int aMax = std::numeric_limits<int>::min();
 
   84      for ( 
auto colorBoxIt = colorBox.constBegin() ; colorBoxIt != colorBox.constEnd(); ++colorBoxIt )
 
   86        currentRed = qRed( colorBoxIt->first );
 
   87        if ( currentRed > rMax )
 
   91        if ( currentRed < rMin )
 
   96        currentGreen = qGreen( colorBoxIt->first );
 
   97        if ( currentGreen > gMax )
 
  101        if ( currentGreen < gMin )
 
  106        currentBlue = qBlue( colorBoxIt->first );
 
  107        if ( currentBlue > bMax )
 
  111        if ( currentBlue < bMin )
 
  116        currentAlpha = qAlpha( colorBoxIt->first );
 
  117        if ( currentAlpha > aMax )
 
  121        if ( currentAlpha < aMin )
 
  127      redRange = rMax - rMin;
 
  128      greenRange = gMax - gMin;
 
  129      blueRange = bMax - bMin;
 
  130      alphaRange = aMax - aMin;
 
  134    bool redCompare( QPair<QRgb, int> c1, QPair<QRgb, int> c2 )
 
  136      return qRed( c1.first ) < qRed( c2.first );
 
  139    bool greenCompare( QPair<QRgb, int> c1, QPair<QRgb, int> c2 )
 
  141      return qGreen( c1.first ) < qGreen( c2.first );
 
  144    bool blueCompare( QPair<QRgb, int> c1, QPair<QRgb, int> c2 )
 
  146      return qBlue( c1.first ) < qBlue( c2.first );
 
  149    bool alphaCompare( QPair<QRgb, int> c1, QPair<QRgb, int> c2 )
 
  151      return qAlpha( c1.first ) < qAlpha( c2.first );
 
  154    QRgb boxColor( 
const QgsColorBox &box, 
int boxPixels )
 
  165      for ( 
auto colorBoxIt = box.constBegin(); colorBoxIt != box.constEnd(); ++colorBoxIt )
 
  167        currentColor = colorBoxIt->first;
 
  168        currentPixel = colorBoxIt->second;
 
  169        weight = 
static_cast<double>( currentPixel ) / boxPixels;
 
  170        avRed   += ( qRed( currentColor ) * weight );
 
  171        avGreen += ( qGreen( currentColor ) * weight );
 
  172        avBlue  += ( qBlue( currentColor ) * weight );
 
  173        avAlpha += ( qAlpha( currentColor ) * weight );
 
  176      return qRgba( avRed, avGreen, avBlue, avAlpha );
 
  181                        QMultiMap<int, QgsColorBox>::iterator colorBoxMapIt )
 
  184      if ( colorBox.size() < 2 )
 
  195      if ( !minMaxRange( colorBox, redRange, greenRange, blueRange, alphaRange ) )
 
  201      if ( redRange >= greenRange && redRange >= blueRange && redRange >= alphaRange )
 
  203        std::sort( colorBox.begin(), colorBox.end(), redCompare );
 
  205      else if ( greenRange >= redRange && greenRange >= blueRange && greenRange >= alphaRange )
 
  207        std::sort( colorBox.begin(), colorBox.end(), greenCompare );
 
  209      else if ( blueRange >= redRange && blueRange >= greenRange && blueRange >= alphaRange )
 
  211        std::sort( colorBox.begin(), colorBox.end(), blueCompare );
 
  215        std::sort( colorBox.begin(), colorBox.end(), alphaCompare );
 
  219      const double halfSum = colorBoxMapIt.key() / 2.0;
 
  221      int currentListIndex = 0;
 
  223      auto colorBoxIt = colorBox.begin();
 
  224      for ( ; colorBoxIt != colorBox.end(); ++colorBoxIt )
 
  226        currentSum += colorBoxIt->second;
 
  227        if ( currentSum >= halfSum )
 
  234      if ( currentListIndex > ( colorBox.size() - 2 ) ) 
 
  237        currentSum -= colorBoxIt->second;
 
  245      const QgsColorBox newColorBox1 = colorBox.mid( 0, currentListIndex + 1 );
 
  246      colorBoxMap.insert( currentSum, newColorBox1 );
 
  248      colorBox.erase( colorBox.begin(), colorBoxIt );
 
  250      colorBoxMap.erase( colorBoxMapIt );
 
  251      colorBoxMap.insert( halfSum * 2.0 - currentSum, newColorBox2 );
 
  256  void medianCut( QVector<QRgb> &colorTable, 
int nColors, 
const QImage &inputImage )
 
  258    QHash<QRgb, int> inputColors;
 
  259    imageColors( inputColors, inputImage );
 
  261    if ( inputColors.size() <= nColors ) 
 
  263      colorTable.resize( inputColors.size() );
 
  265      for ( 
auto inputColorIt = inputColors.constBegin(); inputColorIt != inputColors.constEnd(); ++inputColorIt )
 
  267        colorTable[index] = inputColorIt.key();
 
  275    int firstBoxPixelSum = 0;
 
  276    for ( 
auto  inputColorIt = inputColors.constBegin(); inputColorIt != inputColors.constEnd(); ++inputColorIt )
 
  278      firstBox.push_back( qMakePair( inputColorIt.key(), inputColorIt.value() ) );
 
  279      firstBoxPixelSum += inputColorIt.value();
 
  283    colorBoxMap.insert( firstBoxPixelSum, firstBox );
 
  284    QMultiMap<int, QgsColorBox>::iterator colorBoxMapIt = colorBoxMap.end();
 
  287    bool allColorsMapped = 
false;
 
  288    while ( colorBoxMap.size() < nColors )
 
  291      colorBoxMapIt = colorBoxMap.end();
 
  295        if ( colorBoxMapIt.value().size() > 1 )
 
  297          splitColorBox( colorBoxMapIt.value(), colorBoxMap, colorBoxMapIt );
 
  300        if ( colorBoxMapIt == colorBoxMap.begin() )
 
  302          allColorsMapped = 
true;
 
  307      if ( allColorsMapped )
 
  315    colorTable.resize( colorBoxMap.size() );
 
  316    for ( 
auto colorBoxIt = colorBoxMap.constBegin(); colorBoxIt != colorBoxMap.constEnd(); ++colorBoxIt )
 
  318      colorTable[index] = boxColor( colorBoxIt.value(), colorBoxIt.key() );
 
Median cut implementation.
 
QList< QPair< QRgb, int > > QgsColorBox
 
void medianCut(QVector< QRgb > &colorTable, int nColors, const QImage &inputImage)
Median cut implementation used when reducing RGB colors to palletized colors.
 
QMultiMap< int, QgsColorBox > QgsColorBoxMap