Skip to content

Commit 024b661

Browse files
mhugentMarco Hugentobler
authored andcommittedOct 2, 2012
More color quantisation
1 parent 3a27411 commit 024b661

File tree

2 files changed

+175
-4
lines changed

2 files changed

+175
-4
lines changed
 

‎src/mapserver/qgshttprequesthandler.cpp

Lines changed: 170 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -488,10 +488,11 @@ void QgsHttpRequestHandler::medianCut( QVector<QRgb>& colorTable, int nColors, c
488488
}
489489

490490
QgsColorBoxMap colorBoxMap; //QMultiMap< int, ColorBox >
491-
QMap<int, QgsColorBox>::iterator colorBoxMapIt;
492-
491+
colorBoxMap.insert( firstBoxPixelSum, firstBox );
492+
QMap<int, QgsColorBox>::iterator colorBoxMapIt = colorBoxMap.end();
493493

494494
//split boxes until number of boxes == nColors or all the boxes have color count 1
495+
bool allColorsMapped = false;
495496
while ( colorBoxMap.size() < nColors )
496497
{
497498
//start at the end of colorBoxMap and pick the first entry with number of colors < 1
@@ -502,15 +503,27 @@ void QgsHttpRequestHandler::medianCut( QVector<QRgb>& colorTable, int nColors, c
502503
if ( colorBoxMapIt.value().size() > 1 )
503504
{
504505
splitColorBox( colorBoxMapIt.value(), colorBoxMap, colorBoxMapIt );
505-
continue;
506+
break;
506507
}
507508
if ( colorBoxMapIt == colorBoxMap.begin() )
508509
{
510+
allColorsMapped = true;
509511
break;
510512
}
511513
}
514+
515+
if ( allColorsMapped )
516+
{
517+
break;
518+
}
519+
else
520+
{
521+
continue;
522+
}
512523
}
513524

525+
bool debug = true; //only for breakpoint
526+
514527
//todo: evaluate the colors of the final boxes
515528
}
516529

@@ -543,8 +556,161 @@ void QgsHttpRequestHandler::imageColors( QHash<QRgb, int>& colors, const QImage&
543556
void QgsHttpRequestHandler::splitColorBox( QgsColorBox& colorBox, QgsColorBoxMap& colorBoxMap,
544557
QMap<int, QgsColorBox>::iterator colorBoxMapIt )
545558
{
546-
//todo: a,r,g,b ranges
559+
560+
if ( colorBox.size() < 2 )
561+
{
562+
return; //need at least two colors for a split
563+
}
564+
565+
//a,r,g,b ranges
566+
int redRange = 0;
567+
int greenRange = 0;
568+
int blueRange = 0;
569+
int alphaRange = 0;
570+
571+
if ( !minMaxRange( colorBox, redRange, greenRange, blueRange, alphaRange ) )
572+
{
573+
return;
574+
}
575+
547576
//sort color box for a/r/g/b
577+
if ( redRange >= greenRange && redRange >= blueRange && redRange >= alphaRange )
578+
{
579+
qSort( colorBox.begin(), colorBox.end(), redCompare );
580+
}
581+
else if ( greenRange >= redRange && greenRange >= blueRange && greenRange >= alphaRange )
582+
{
583+
qSort( colorBox.begin(), colorBox.end(), greenCompare );
584+
}
585+
else if ( blueRange >= redRange && blueRange >= greenRange && blueRange >= alphaRange )
586+
{
587+
qSort( colorBox.begin(), colorBox.end(), blueCompare );
588+
}
589+
else
590+
{
591+
qSort( colorBox.begin(), colorBox.end(), alphaCompare );
592+
}
593+
548594
//get median
595+
double halfSum = colorBoxMapIt.key() / 2.0;
596+
int currentSum = 0;
597+
int currentListIndex = 0;
598+
599+
QgsColorBox::iterator colorBoxIt = colorBox.begin();
600+
for ( ; colorBoxIt != colorBox.end(); ++colorBoxIt )
601+
{
602+
currentSum += colorBoxIt->second;
603+
if ( currentSum >= halfSum )
604+
{
605+
break;
606+
}
607+
++currentListIndex;
608+
}
609+
610+
if ( currentListIndex > ( colorBox.size() - 2 ) ) //if the median is contained in the last color, split one item before that
611+
{
612+
--currentListIndex;
613+
}
614+
else
615+
{
616+
++colorBoxIt; //the iterator needs to point behind the last item to remove
617+
}
618+
549619
//do split: replace old color box, insert new one
620+
QgsColorBox newColorBox1 = colorBox.mid( 0, currentListIndex + 1 );
621+
colorBoxMap.insert( currentSum, newColorBox1 );
622+
623+
colorBox.erase( colorBox.begin(), colorBoxIt );
624+
QgsColorBox newColorBox2 = colorBox;
625+
colorBoxMap.erase( colorBoxMapIt );
626+
colorBoxMap.insert( halfSum * 2.0 - currentSum, newColorBox2 );
627+
}
628+
629+
bool QgsHttpRequestHandler::minMaxRange( const QgsColorBox& colorBox, int& redRange, int& greenRange, int& blueRange, int& alphaRange )
630+
{
631+
if ( colorBox.size() < 1 )
632+
{
633+
return false;
634+
}
635+
636+
int rMin = INT_MAX;
637+
int gMin = INT_MAX;
638+
int bMin = INT_MAX;
639+
int aMin = INT_MAX;
640+
int rMax = INT_MIN;
641+
int gMax = INT_MIN;
642+
int bMax = INT_MIN;
643+
int aMax = INT_MIN;
644+
645+
int currentRed = 0; int currentGreen = 0; int currentBlue = 0; int currentAlpha = 0;
646+
647+
QgsColorBox::const_iterator colorBoxIt = colorBox.constBegin();
648+
for ( ; colorBoxIt != colorBox.constEnd(); ++colorBoxIt )
649+
{
650+
currentRed = qRed( colorBoxIt->first );
651+
if ( currentRed > rMax )
652+
{
653+
rMax = currentRed;
654+
}
655+
if ( currentRed < rMin )
656+
{
657+
rMin = currentRed;
658+
}
659+
660+
currentGreen = qGreen( colorBoxIt->first );
661+
if ( currentGreen > gMax )
662+
{
663+
gMax = currentGreen;
664+
}
665+
if ( currentGreen < gMin )
666+
{
667+
gMin = currentGreen;
668+
}
669+
670+
currentBlue = qBlue( colorBoxIt->first );
671+
if ( currentBlue > bMax )
672+
{
673+
bMax = currentBlue;
674+
}
675+
if ( currentBlue < bMin )
676+
{
677+
bMin = currentBlue;
678+
}
679+
680+
currentAlpha = qAlpha( colorBoxIt->first );
681+
if ( currentAlpha > aMax )
682+
{
683+
aMax = currentAlpha;
684+
}
685+
if ( currentAlpha < aMin )
686+
{
687+
aMin = currentAlpha;
688+
}
689+
}
690+
691+
redRange = rMax - rMin;
692+
greenRange = gMax - gMin;
693+
blueRange = bMax - bMin;
694+
alphaRange = aMax - aMin;
695+
return true;
696+
}
697+
698+
bool QgsHttpRequestHandler::redCompare( const QPair<QRgb, int>& c1, const QPair<QRgb, int>& c2 )
699+
{
700+
return qRed( c1.first ) < qRed( c2.first );
701+
}
702+
703+
bool QgsHttpRequestHandler::greenCompare( const QPair<QRgb, int>& c1, const QPair<QRgb, int>& c2 )
704+
{
705+
return qGreen( c1.first ) < qGreen( c2.first );
706+
}
707+
708+
bool QgsHttpRequestHandler::blueCompare( const QPair<QRgb, int>& c1, const QPair<QRgb, int>& c2 )
709+
{
710+
return qBlue( c1.first ) < qBlue( c2.first );
711+
}
712+
713+
bool QgsHttpRequestHandler::alphaCompare( const QPair<QRgb, int>& c1, const QPair<QRgb, int>& c2 )
714+
{
715+
return qAlpha( c1.first ) < qAlpha( c2.first );
550716
}

‎src/mapserver/qgshttprequesthandler.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ class QgsHttpRequestHandler: public QgsRequestHandler
5858
static void imageColors( QHash<QRgb, int>& colors, const QImage& image );
5959
static void splitColorBox( QgsColorBox& colorBox, QgsColorBoxMap& colorBoxMap,
6060
QMap<int, QgsColorBox>::iterator colorBoxMapIt );
61+
static bool minMaxRange( const QgsColorBox& colorBox, int& redRange, int& greenRange, int& blueRange, int& alphaRange );
62+
static bool redCompare( const QPair<QRgb, int>& c1, const QPair<QRgb, int>& c2 );
63+
static bool greenCompare( const QPair<QRgb, int>& c1, const QPair<QRgb, int>& c2 );
64+
static bool blueCompare( const QPair<QRgb, int>& c1, const QPair<QRgb, int>& c2 );
65+
static bool alphaCompare( const QPair<QRgb, int>& c1, const QPair<QRgb, int>& c2 );
6166
};
6267

6368
#endif

0 commit comments

Comments
 (0)
Please sign in to comment.