Exemple #1
0
    static void qualityToMinColorError(TColorErrorParameter* out_errorParameter,float& colorQuality,bool isMustFitColorTable){
        if (colorQuality>100) colorQuality=100;
        else if (colorQuality<0) colorQuality=0;

        const TInt32 kDiffuseCoeff0=(1<<kColorErrorDiffuseCoefficientIntFloatBit)*87/100;
        const TInt32 kDiffuseCoeff100=(1<<kColorErrorDiffuseCoefficientIntFloatBit)*97/100;
        out_errorParameter->errorDiffuse_coefficient=(TInt32)(0.5f+kDiffuseCoeff0+(kDiffuseCoeff100-kDiffuseCoeff0)*colorQuality/100);

        const TInt32 kMaxDiffuseValue0=(1<<kColorErrorDiffuseCoefficientIntFloatBit)*(1<<5);
        const TInt32 kMaxDiffuseValue100=(1<<kColorErrorDiffuseCoefficientIntFloatBit)*(1<<2);
        out_errorParameter->maxErrorDiffuseValue=(TInt32)(0.5f+kMaxDiffuseValue0+(kMaxDiffuseValue100-kMaxDiffuseValue0)*colorQuality/100);

        out_errorParameter->isMustFitColorTable=isMustFitColorTable;//colorQuality<=80;

        static TInt32 kSingleColorError0=getColorDistance(Color24(150,150,150),Color24(0,0,0));
        static TInt32 kSingleColorError60=getColorDistance(Color24((1<<5)-1,(1<<5)-1,(1<<6)-1),Color24(0,0,0));
        static TInt32 kSingleColorError80=getColorDistance(Color24((1<<3)-1,(1<<3)-1,(1<<3)-1),Color24(0,0,0));
        static TInt32 kSingleColorError100=0;

        static TInt32 kTableSize0=2;
        static TInt32 kTableSize60=12;
        static TInt32 kTableSize80=16;

        if ((80<=colorQuality)&&(colorQuality<=100)){
            out_errorParameter->minColorError=(TInt32)(0.5f+(colorQuality-80)*(kSingleColorError100-kSingleColorError80)/(100-80)+kSingleColorError80);
            out_errorParameter->minColorError_optimize=(out_errorParameter->minColorError)>>1;
            out_errorParameter->maxTableSize=16;
            return;
        }else if ((60<=colorQuality)&&(colorQuality<80)){
Exemple #2
0
//--------------------------------------------------------------
void testApp::draw(){
    ofLog(OF_LOG_NOTICE, "draw"+ofToString(ofGetFrameNum()));
    if (!saveToFile) {
        if (counter <= image1.getWidth()*image1.getHeight()) {
            // 左の画像を右の画像に入れ替える
            ofPoint referencePoint;
            if (enableRandomExchange) {
                //ランダムで交換
                referencePoint = ofPoint(exchangeOrderVector[counter]%(int)image1.getWidth(), exchangeOrderVector[counter]/(int)image1.getWidth());
                
            }else{
                //上から順に交換
                referencePoint = ofPoint(counter%(int)image1.getWidth(), counter/(int)image1.getWidth());
            }
            ofColor referenceColor = image1.getColor(referencePoint.x, referencePoint.y);
            double minimumDistance = image1.getWidth()+image2.getHeight();
            ofPoint minimumDistancePoint;
            unsigned char * checkImagePixels = image2.getPixels();
            // 最小の距離の色を調べる
            for (int i=0; i<image1.getHeight(); i++) {
                for (int j=0; j<image1.getWidth(); j++) {
                    if (!enableDuplicate) {
                        // 重複を許さない
                        if (!usedOrNotVector[i*(int)image2.getWidth()+j]) {
                            ofColor checkColor = ofColor(checkImagePixels[(i*(int)image2.getWidth()+j)*3],
                                                         checkImagePixels[(i*(int)image2.getWidth()+j)*3+1],
                                                         checkImagePixels[(i*(int)image2.getWidth()+j)*3+2]);
                            double checkDistance = getColorDistance(referenceColor, checkColor);
                            if (checkDistance < minimumDistance) {
                                if (!usedOrNotVector[i*(int)image2.getWidth()+j]) {
                                    minimumDistance = checkDistance;
                                    minimumDistancePoint = ofPoint(j, i);
                                }
                                // 同じ色の重複を許す
                                minimumDistance = checkDistance;
                                minimumDistancePoint = ofPoint(j, i);
                            }
                        }
                    } else{
                        ofColor checkColor = ofColor(checkImagePixels[(i*(int)image2.getWidth()+j)*3],
                                                     checkImagePixels[(i*(int)image2.getWidth()+j)*3+1],
                                                     checkImagePixels[(i*(int)image2.getWidth()+j)*3+2]);
                        double checkDistance = getColorDistance(referenceColor, checkColor);
                        if (checkDistance < minimumDistance) {
                            if (!usedOrNotVector[i*(int)image2.getWidth()+j]) {
                                minimumDistance = checkDistance;
                                minimumDistancePoint = ofPoint(j, i);
                            }
                            // 同じ色の重複を許す
                            minimumDistance = checkDistance;
                            minimumDistancePoint = ofPoint(j, i);
                        }
                    }
                }
            }
            //最も近い距離の色の組み合わせをベクターに保存
            pointPair tempPointPair;
            tempPointPair.point1 = referencePoint;
            tempPointPair.point2 = minimumDistancePoint;
            
            // 重複を許さない
            if (!enableDuplicate) {
                //再利用しないために、使用したPointを保存
                usedOrNotVector[minimumDistancePoint.y*(int)image2.getWidth()+minimumDistancePoint.x] = true;
            }
            pointPairVector.push_back(tempPointPair);
            //    ofLog(OF_LOG_NOTICE, "X:"+ofToString(pointPairVector.back().point2.x)+" Y:"+ofToString(pointPairVector.back().point2.y));
            
            // 左の画像の色を入れ替える
            image1.setColor(pointPairVector.back().point1.x, pointPairVector.back().point1.y, image2.getColor(pointPairVector.back().point2.x, pointPairVector.back().point2.y));
            image1.update();
            
            // 右の画像の色を入れ替える
            if (enableExchange) {
                image2.setColor(pointPairVector.back().point2.x, pointPairVector.back().point2.y, originalImage1.getColor(pointPairVector.back().point1.x, pointPairVector.back().point1.y));
                image2.update();
            }
        }
        
        // draw image
        image1.draw(ofPoint(ofGetWidth()/4.-image1.getWidth()/2.+100, (ofGetHeight()-image1.getHeight())/2.), image1.getWidth(), image1.getHeight());
        image2.draw(ofPoint(ofGetWidth()/4.*3-image2.getWidth()/2.-100 , (ofGetHeight()-image2.getHeight())/2.), image2.getWidth(), image2.getHeight());
        
        //hightLihgting
        if (counter <= image1.getWidth()*image1.getHeight()) {
            ofPushStyle();
            ofSetColor(ofColor::white);
            ofSetLineWidth(1);
            ofLine(pointPairVector.back().point1.x+(ofGetWidth()/4.-image1.getWidth()/2.+100), pointPairVector.back().point1.y+((ofGetHeight()-image1.getHeight())/2.),
                   pointPairVector.back().point2.x+(ofGetWidth()/4.*3-image2.getWidth()/2.-100), pointPairVector.back().point2.y+((ofGetHeight()-image2.getHeight())/2.));
            ofPopStyle();
        }
        
        //		ofPushStyle();
        //				ofSetColor(255, 255, 0, 127);
        //				ofCircle(300, 100, 150);
        //				ofSetColor(0, 255, 255, 127);
        //				ofCircle(100, 100, 150);
        //
        //		ofPopStyle();
        
    }
}
Exemple #3
0
//--------------------------------------------------------------
void testApp::keyReleased(int key){
    switch (key) {
        case 'f':
            ofToggleFullscreen();
            break;
        case '0':
            ofEnableBlendMode(OF_BLENDMODE_DISABLED);
            break;
        case '1':
            ofEnableBlendMode(OF_BLENDMODE_ALPHA);
            break;
        case '2':
            ofEnableBlendMode(OF_BLENDMODE_ADD);
            break;
        case '3':
            ofEnableBlendMode(OF_BLENDMODE_SUBTRACT);
            break;
        case '4':
            ofEnableBlendMode(OF_BLENDMODE_MULTIPLY);
            break;
        case '5':
            ofEnableBlendMode(OF_BLENDMODE_SCREEN);
            break;
        case 'a':
            ofEnableAntiAliasing();
            break;
        case 'b':
            ofBackground(0, 0, 0, 255);
            break;
        case 'd':
            ofDisableAlphaBlending();
            break;
        case 'e':
            ofEnableAlphaBlending();
            break;
        case 'r':
            //read file
            importFileForStruct();
            break;
        case 's':
            ofDisableAntiAliasing();
            break;
        case 'w':
            ofBackground(255, 255, 255, 255);
            break;
        case ' ':
        {
            saveToFile = true;
            ofLog(OF_LOG_NOTICE, "calculating...");
            //ペアのデータを作成 -->
            vector<pointPair> pointPairVectorForWriting;
            for (int k=0; k<image1.getWidth()*image1.getHeight(); k++) {
                if (k <= image1.getWidth()*image1.getHeight()) {
                    // 左の画像を右の画像に入れ替える
                    ofPoint referencePoint;
                    if (enableRandomExchange) {
                        //ランダムで交換
                        referencePoint = ofPoint(exchangeOrderVector[k]%(int)image1.getWidth(), exchangeOrderVector[k]/(int)image1.getWidth());
                        
                    }else{
                        //上から順に交換
                        referencePoint = ofPoint(k%(int)image1.getWidth(), k/(int)image1.getWidth());
                    }
                    ofColor referenceColor = image1.getColor(referencePoint.x, referencePoint.y);
                    double minimumDistance = image1.getWidth()+image2.getHeight();
                    ofPoint minimumDistancePoint;
                    unsigned char * checkImagePixels = image2.getPixels();
                    // 最小の距離の色を調べる
                    for (int i=0; i<image1.getHeight(); i++) {
                        for (int j=0; j<image1.getWidth(); j++) {
                            if (!enableDuplicate) {
                                // 重複を許さない
                                if (!usedOrNotVector[i*(int)image2.getWidth()+j]) {
                                    ofColor checkColor = ofColor(checkImagePixels[(i*(int)image2.getWidth()+j)*3],
                                                                 checkImagePixels[(i*(int)image2.getWidth()+j)*3+1],
                                                                 checkImagePixels[(i*(int)image2.getWidth()+j)*3+2]);
                                    double checkDistance = getColorDistance(referenceColor, checkColor);
                                    if (checkDistance < minimumDistance) {
                                        if (!usedOrNotVector[i*(int)image2.getWidth()+j]) {
                                            minimumDistance = checkDistance;
                                            minimumDistancePoint = ofPoint(j, i);
                                        }
                                        // 同じ色の重複を許す
                                        minimumDistance = checkDistance;
                                        minimumDistancePoint = ofPoint(j, i);
                                    }
                                }
                            } else{
                                ofColor checkColor = ofColor(checkImagePixels[(i*(int)image2.getWidth()+j)*3],
                                                             checkImagePixels[(i*(int)image2.getWidth()+j)*3+1],
                                                             checkImagePixels[(i*(int)image2.getWidth()+j)*3+2]);
                                double checkDistance = getColorDistance(referenceColor, checkColor);
                                if (checkDistance < minimumDistance) {
                                    if (!usedOrNotVector[i*(int)image2.getWidth()+j]) {
                                        minimumDistance = checkDistance;
                                        minimumDistancePoint = ofPoint(j, i);
                                    }
                                    // 同じ色の重複を許す
                                    minimumDistance = checkDistance;
                                    minimumDistancePoint = ofPoint(j, i);
                                }
                            }
                        }
                    }
                    //最も近い距離の色の組み合わせをベクターに保存
                    pointPair tempPointPair;
                    tempPointPair.point1 = referencePoint;
                    tempPointPair.point2 = minimumDistancePoint;
                    
                    // 重複を許さない
                    if (!enableDuplicate) {
                        //再利用しないために、使用したPointを保存
                        usedOrNotVector[minimumDistancePoint.y*(int)image2.getWidth()+minimumDistancePoint.x] = true;
                    }
                    pointPairVectorForWriting.push_back(tempPointPair);
                }
            }
            ofLog(OF_LOG_NOTICE, "pointPairVectorForWriting done!");
            //<-- ペアのデータを作成
            ofLog(OF_LOG_NOTICE, "X1:"+ofToString(pointPairVectorForWriting[0].point1.x)+" Y1:"+ofToString(pointPairVectorForWriting[0].point1.y));
            ofLog(OF_LOG_NOTICE, "X2:"+ofToString(pointPairVectorForWriting[0].point2.x)+" Y2:"+ofToString(pointPairVectorForWriting[0].point2.y));
            exportFileForStruct(pointPairVectorForWriting);
            ofLog(OF_LOG_NOTICE, ofToString("writing file..."));
            saveToFile = false;
            ofLog(OF_LOG_NOTICE, "done");
        }
            break;
        default:
            break;
    }
}
void DKHFastScanning(LPIMGDATA imgData){
	int i, j, clusterCount, maxSize;
	CLUSIMG clusImg;
	//ALLOCDATA delLists;
	float threshold, dist;
	Cluster *clusterList, *Ci, *lastClus;
	char strThreshold[16];
	
	clusterCount = 1;
	threshold = 45.0f;
	clusImg.width = imgData->width;
	clusImg.height = imgData->height;
	clusImg.pixClus = (void**)HeapAlloc(GetProcessHeap(),0,clusImg.width*clusImg.height*sizeof(void*));
	writeConsole("\nThreshold distance: ");
	readConsoleString(strThreshold);
	threshold = atof(strThreshold);
	if(threshold < 1.0f)
		threshold = 50.0f;
	writeConsoleFmt("We'll be using threshold %.2f\n",threshold);
	
	LPCOLOR thisPx = (LPCOLOR)imgData->bitmap;
	Ci = new Cluster(0,0,*thisPx,&clusImg);
	lastClus = clusterList = Ci;
	thisPx++;
	for(j = 1; j < clusImg.width; j++){
		Ci = getPixelCluster(clusterList,&clusImg,j-1,0);
		dist = getColorDistance(Ci->getTone(),*thisPx);
		if(dist < threshold)
			Ci->mergePoint(j,0,*thisPx);
		else{
			Ci = new Cluster(j,0,*thisPx,&clusImg);
			lastClus->setNext(Ci);
			Ci->setBefore(lastClus);
			lastClus = Ci;
			clusterCount++;
		}
		thisPx++;
	}
	
	for(i = 1; i < clusImg.height; i++){
		Ci = getPixelCluster(clusterList,&clusImg,0,i-1);
		
		dist = getColorDistance(Ci->getTone(),*thisPx);
		if(dist < threshold)
			Ci->mergePoint(0,i,*thisPx);
		else{
			Ci = new Cluster(0,i,*thisPx,&clusImg);
			lastClus->setNext(Ci);
			Ci->setBefore(lastClus);
			lastClus = Ci;
			clusterCount++;
		}
		thisPx++;
		
		for(j = 1; j < clusImg.width; j++){
			Cluster* Cu = getPixelCluster(clusterList,&clusImg,j,i-1);
			Cluster* Cl = getPixelCluster(clusterList,&clusImg,j-1,i);
			dist = getColorDistance(Cu->getTone(),*thisPx);
			if(dist < threshold){
				Cu->mergePoint(j,i,*thisPx);
				dist = getColorDistance(Cl->getTone(),*thisPx);
				if(dist < threshold){
					if(Cu != Cl){
						clusterCount--;
						if(Cl != clusterList){
							if(Cl == lastClus)
								lastClus = lastClus->getBefore();
							Cu->mergeCluster(Cl,clusterList);
						}else{
							if(Cu == lastClus)
								lastClus = lastClus->getBefore();
							Cl->mergeCluster(Cu,clusterList);
						}
				    }
				}
			}else{
				dist = getColorDistance(Cl->getTone(),*thisPx);
				if(dist < threshold)
					Cl->mergePoint(j,i,*thisPx);
				else{
					Ci = new Cluster(j,i,*thisPx,&clusImg);
					lastClus->setNext(Ci);
					Ci->setBefore(lastClus);
					lastClus = Ci;
					clusterCount++;
				}
			}
			thisPx++;
		}
		writeConsoleFmt("Line %d done. Cluster count %d.\n",i,clusterCount);
		//dbgShow(clusterList,&clusImg);
	}
	
	j = 0;
	//Remove small clusters (less than 1%)
	writeConsoleFmt("Wich it's the minimum cluster size(size threshold in percent)?");
	readConsoleString(strThreshold);
	threshold = atof(strThreshold)/100.0f;
	if(threshold > 0.1f){
		writeConsole("Too big. You should had inserted values lower than 10.0\n");
		threshold = 0.01f;
	}else if(threshold < 0.0001f){
		writeConsole("Too small. You should had inserted values greater than 0.01\n");
		threshold = 0.01f;
	}
	writeConsoleFmt("Minimal cluster size to image ratio: %.4f%%\n",threshold*100.0f);
	maxSize = (int)((clusImg.width*clusImg.height)*threshold);
	maxSize = (clusImg.width*clusImg.height)/400; //Get how much is 1%
	Ci = clusterList->getNext();
	i = 0;
	while(Ci != (Cluster*)NULL){
		if(Ci->getCount() < maxSize){
			Cluster* delClus = Ci;
			j++;
			writeConsoleFmt("Merging cluster %08x because of low pixel count: %d. Clusters deleted: %d\n",Ci,Ci->getCount(),j);
			Ci = Ci->getNext();
			clusterCount--;
			delClus->mergeClosest(clusterList);
			continue;
		}else if(Ci->getCount() > i){
			i = Ci->getCount();
		}
		Ci = Ci->getNext();
	}
	//HeapDestroy(delLists.hHeap);
	convertClustersBitmap(clusterList, &clusImg, imgData);
	
	writeConsoleFmt("%d clusters found.\n",clusterCount);
	
	//seekDiamonds(&clusImg,clusterList);
	
	lastClus = clusterList;
	//writeConsole("   ID         RGB        Count   Position,Box\n");
	while(clusterList != (Cluster*)NULL){
		clusterList = clusterList->getNext();
		//writeConsoleFmt("%08x (%3d,%3d,%3d) %9d %dx%d,%dx%d",lastClus,lastClus->getTone().red,lastClus->getTone().green,lastClus->getTone().blue,
		//lastClus->getCount(),lastClus->getLeft(),lastClus->getTop(),lastClus->getRight()-lastClus->getLeft(),lastClus->getBottom()-lastClus->getTop());
		lastClus->detectShape();
		delete lastClus;
		lastClus = clusterList;
	}
	
}
/* Seek highest color.
 * Create list of clusters whose color is greater than or equal.
 * Order them by X position order, then by Y order.
 * Save average X and Z position.
 * Detect distance between them.
 *	If the distance varies on both X and Y directions, the cluster might not belong to thrust.
 * 
 * 
 */
void seekDiamonds(LPCLUSIMG clusImg, Cluster* head){
	Cluster* thisClus = head;
	ColorValue maxColor, thisColor;
	PCLUSLIST clusList, thisItem, lastItem;
	int count = 0;
	float minDist, thisDist;
	minDist = 500.0f;
	while(thisClus != NULL){
		thisDist = getColorDistance(COLOR_WHITE,thisClus->getTone());
		if(thisDist < minDist){
			count = 1;
			minDist = thisDist;
			maxColor.color = thisClus->getTone();
		}
		thisClus = thisClus->getNext();
	}
	//create CLUSLIST items.
	writeConsoleFmt("Highest color: %3d,%3d,%3d\n",maxColor.color.red,maxColor.color.green,maxColor.color.blue);
	
	int xmin, xmax, ymin, ymax;
	clusList = lastItem = (PCLUSLIST)NULL;
	thisClus = head;
	while(thisClus != NULL){
		thisColor.color = thisClus->getTone();
		if(thisColor.value == maxColor.value){
			thisItem = (PCLUSLIST)malloc(sizeof(CLUSLIST));
			thisItem->cluster = thisClus;
			thisItem->next = NULL;
			thisItem->left = thisClus->getLeft();
			thisItem->top = thisClus->getTop();
			thisItem->width = thisClus->getRight()-thisClus->getLeft();
			thisItem->height = thisClus->getBottom()-thisClus->getTop();
			thisItem->count = thisClus->getCount();
			
			if(clusList == NULL){
				clusList = thisItem;
				xmin = thisItem->left;
				xmax = thisItem->left;
				ymin = thisItem->top;
				ymax = thisItem->top;
			}else{
				lastItem->next = thisItem;
				if(thisItem->left < xmin)
					xmin = thisItem->left;
				if(thisItem->left > xmax)
					xmax = thisItem->left;
				if(thisItem->top < ymin)
					ymin = thisItem->top;
				if(thisItem->top > ymax)
					ymax = thisItem->top;
			}
			lastItem = thisItem;
		}
		thisClus = thisClus->getNext();
	}
		
	lastItem = clusList;
	while(lastItem != NULL){
		writeConsoleFmt("Cluster: %08x. Left: %d\n",lastItem->cluster,lastItem->left);
		lastItem = lastItem->next;
	}
	writeConsoleFmt("Variation: x:%d(%d-%d); y:%d(%d-%d);\n",xmax-xmin,xmax,xmin,ymax-ymin,ymax,ymin);
	
	clusList = lastItem = bubbleSortList(clusList,lastItem);
	while(lastItem != NULL){
		writeConsoleFmt("Cluster: %08x. Left: %d. DistNxt: %d\n",lastItem->cluster,lastItem->left,
		(lastItem->next!=NULL?lastItem->next->left-(lastItem->left+lastItem->width):0));
		clusList = lastItem;
		lastItem = lastItem->next;
		free(clusList);
	}
}
//void Cluster::mergeClosest(Cluster* head, HANDLE hHeap){
void Cluster::mergeClosest(Cluster* head){
	int i, j, n, sizex, sizey, step, currCnt, maxCnt, maxWeight, maxDist;
	Cluster **thisPx, *Ci;
	LPPIXCNT pixCnt;
	thisPx = (Cluster**)clustImage->pixClus;
	thisPx += (top*clustImage->width+left);
	sizex = right-left;
	sizey = bottom-top;
	step = clustImage->width-sizex;
	maxCnt = 128;
	maxDist = 0;
	currCnt = 0;
	
	//pixCnt = (LPPIXCNT)HeapAlloc(hHeap,HEAP_ZERO_MEMORY,maxCnt*sizeof(PIXCNT));
	pixCnt = (LPPIXCNT)malloc(maxCnt*sizeof(PIXCNT));
	i = top;
	while(i < bottom){
		j = left;
		while(j < right){
			if(*thisPx == this){
				Cluster* neighbour;
				for(int c = 0; c < 4; c++){
					switch(c){
						case 0: //Top
							if(i == 0)
								continue;
							neighbour = *(thisPx-clustImage->width);
							break; 
						case 1: //Left
							if(j == 0)
								continue;
							neighbour = *(thisPx-1);
							break;
						case 2: //Botton							
							if(i+1 == clustImage->height)
								continue;
							neighbour = *(thisPx+clustImage->width);
							break;
						case 3: //Right
							if(j+1 == clustImage->width)
								continue;
							neighbour = *(thisPx+1);
							break;
					}
					bool found = false;
					if(neighbour == this)
						continue;
					
					for(n = 0; n < currCnt; n++)
						if(pixCnt[n].cluster == neighbour){
							pixCnt[n].count++;
							found = true;
							break;
					}
					
					if(!found){
						if(currCnt+1 >= maxCnt){
							maxCnt += 128;
							//pixCnt = (LPPIXCNT)HeapReAlloc(hHeap,HEAP_ZERO_MEMORY,pixCnt,maxCnt*sizeof(PIXCNT));
							pixCnt = (LPPIXCNT)realloc(pixCnt,maxCnt*sizeof(PIXCNT));
							//writeConsoleFmt("List reallocation. %d current items. %d max items.",currCnt,maxCnt);
						}
						pixCnt[currCnt].cluster = neighbour;
						pixCnt[currCnt].count = 1;
						pixCnt[currCnt].distance = (int)trunc(getColorDistance(avgTone,neighbour->avgTone));
						pixCnt[currCnt].distance = abs(pixCnt[currCnt].distance);
						if(pixCnt[currCnt].distance > maxDist)
							maxDist = pixCnt[currCnt].distance;
						currCnt++;
					}
					
				}
			}
			thisPx++;
			j++;
		}
		thisPx += step;
		i++;
	}
	
	i = 0xFFFFFFFF;
	maxWeight = 0;
		
	for(n = 0; n < currCnt; n++){
		int thisWeight = pixCnt[n].count*(maxDist-pixCnt[n].distance);
		if(thisWeight > maxWeight || pixCnt[n].distance-maxDist < 1.01){
			i = n;
			maxWeight = thisWeight;
		}
		//writeConsoleFmt("%08x: %d, %d.\n",pixCnt[n].cluster,pixCnt[n].count,pixCnt[n].distance);
	}
	if(i != 0xFFFFFFFF)
		Ci = pixCnt[i].cluster;
	else{
		Ci = (Cluster*)NULL;
		writeConsoleFmt("FAILED TO FIND CLOSEST CLUSTER FOR %08X.\n",this);
	}
	writeConsoleFmt("Merge %08x (%d,%d,%d) with %08x (%d,%d,%d)\n",Ci,Ci->avgTone.red,Ci->avgTone.green,Ci->avgTone.blue,this,avgTone.red,avgTone.green,avgTone.blue);
	//HeapFree(hHeap,0,pixCnt);
	free(pixCnt);
	
	if(Ci != (Cluster*)NULL)
		Ci->mergeCluster(this,head);
}