//------------------------------------------------------------------------- //<PQueue<T>, Dictionary<int, int>, float> private static void __Iter <T>(EICPQueue <T> lh, int[] histo, float target) { var ncolors = 1; var niters = 0; T vbox; while (niters < maxIterations) { vbox = lh.pop(); if ((vbox as EICBox).count() == 0) { /* just put it back */ lh.push(vbox); niters++; continue; } var vboxes = __MedianCutApply(histo, vbox as EICBox); T vbox1 = (T)vboxes[0]; T vbox2 = (T)vboxes[1]; if (vbox1 == null) { //无法切分 ("vbox1 not defined; shouldn't happen!"); return; } lh.push(vbox1); if (vbox2 != null) { /* vbox2 can be null */ lh.push(vbox2); ncolors++; } //找到最集中的点的数量,已经大于我们需要的,就不要在继续切分 if (ncolors >= target) { return; } //循环的次数如果太多,也不要继续循环。 if (niters++ > maxIterations) { // ("infinite loop; perhaps too few pixels!"); return; } } }
//------------------------------------------------------------------------- /// <summary> /// 开始计算 /// </summary> /// <param name="pixels"></param> /// <param name="maxcolors"></param> /// <returns></returns> private static EICCMap __Quantize(List <Color> pixels, int maxcolors) { if (pixels.Count == 0 || maxcolors < 2 || maxcolors > 256) { return(null); } //得到颜色空间 里面每种颜色的数量集合 var histo = __GetHisto(pixels); //color总数 var nColors = 0; //代表总共有多少种颜色,通过采样出来的 foreach (var v in histo) { if (v > 0) { nColors++; } } //如果颜色还少于需要计算的颜色,应该不现实? if (nColors <= maxcolors) { // XXX: generate the new colors from the histo and return } //得到颜色的三维空间中 三个向量的最大值 最小值 var vbox = __VboxFromPixels(pixels, histo); var pq = new EICPQueue <EICBox>((a, b) => { return(NaturalOrder(a.count(), b.count())); }); pq.push(vbox); //按照像素点进行切分 __Iter(pq, histo, fractByPopulations * maxcolors); //切分完毕的数据,按照重量进行排序 var pq2 = new EICPQueue <EICBox>( (a, b) => { return(NaturalOrder(a.count() * a.volume(), b.count() * b.volume())); }); //把切分完毕的,装在进去 while (pq.size() > 0) { pq2.push(pq.pop()); } //?继续切分吗? __Iter(pq2, histo, maxcolors - pq2.size()); // calculate the actual colors var cmap = new EICCMap(); while (pq2.size() > 0) { cmap.push(pq2.pop()); } return(cmap); }