160 return rgb1.r == rgb2.r && rgb1.g == rgb2.g && rgb1.b == rgb2.b;
163int childIndex(RGB
rgb)
165 return ((
rgb.
r & 1) << 2) | ((
rgb.
g & 1) << 1) | (
rgb.
b & 1);
196 octreeDelete(pool, i);
198 ocnodeFree(pool,
node);
205void ocnodePrint(Ocnode *
node,
int indent)
208 printf(
"width:%d weight:%lu rgb:%6x nleaf:%d mi:%lu\n",
218 for (
int i = 0; i < 8; i++)
if (
node->child[i])
220 for (
int k = 0; k < indent; k++) printf(
" ");
221 printf(
"[%d:%p] ", i,
node->child[i]);
222 ocnodePrint(
node->child[i], indent+2);
226void octreePrint(Ocnode *
node)
228 printf(
"<<octree>>\n");
229 if (
node) printf(
"[r:%p] ",
node); ocnodePrint(
node, 2);
239 Ocnode *
node = ocnodeNew(pool);
256 if (!node1 && !node2)
return 0;
257 assert(node1 != node2);
267 int dwitdth = node1->width - node2->width;
268 if (dwitdth > 0 && node1->rgb == node2->rgb >> dwitdth) {
271 int i = childIndex(node2->rgb >> (dwitdth - 1));
272 node1->rs += node2->rs; node1->gs += node2->gs; node1->bs += node2->bs;
273 node1->weight += node2->weight;
275 if (node1->child[i]) node1->nleaf -= node1->child[i]->nleaf;
276 node1->nleaf += octreeMerge(pool, node1, &node1->child[i], node1->child[i], node2);
278 }
else if (dwitdth < 0 && node2->
rgb == node1->rgb >> (-dwitdth)) {
281 int i = childIndex(node1->rgb >> (-dwitdth - 1));
282 node2->rs += node1->rs; node2->gs += node1->gs; node2->bs += node1->bs;
283 node2->weight += node1->weight;
285 if (node2->child[i]) node2->nleaf -= node2->child[i]->nleaf;
286 node2->nleaf += octreeMerge(pool, node2, &node2->child[i], node2->child[i], node1);
291 newnode = ocnodeNew(pool);
292 newnode->rs = node1->rs + node2->rs;
293 newnode->gs = node1->gs + node2->gs;
294 newnode->bs = node1->bs + node2->bs;
295 newnode->weight = node1->weight + node2->weight;
296 *
ref = newnode; newnode->ref =
ref; newnode->parent =
parent;
297 if (dwitdth == 0 && node1->rgb == node2->rgb) {
299 newnode->width = node1->width;
300 newnode->rgb = node1->rgb;
303 if (node1->nchild == 0 && node2->nchild == 0) {
306 for (
int i = 0; i < 8; i++) {
307 if (node1->child[i] || node2->child[i]) {
308 newnode->nleaf += octreeMerge(pool, newnode, &newnode->child[i], node1->child[i], node2->child[i]);
312 ocnodeFree(pool, node1); ocnodeFree(pool, node2);
313 return newnode->nleaf;
316 int newwidth = std::max(node1->width, node2->width);
317 RGB rgb1 = node1->rgb >> (newwidth - node1->width);
318 RGB rgb2 = node2->rgb >> (newwidth - node2->width);
320 while (!(rgb1 == rgb2)) {
325 newnode->width = newwidth;
328 newnode->nleaf = node1->nleaf + node2->nleaf;
329 int i1 = childIndex(node1->rgb >> (newwidth - node1->width - 1));
330 int i2 = childIndex(node2->rgb >> (newwidth - node2->width - 1));
331 node1->parent = newnode;
332 node1->ref = &newnode->child[i1];
333 newnode->child[i1] = node1;
334 node2->parent = newnode;
335 node2->ref = &newnode->child[i2];
336 newnode->child[i2] = node2;
337 return newnode->nleaf;
345void ocnodeMi(Ocnode *
node)
355void ocnodeStrip(
Pool<Ocnode> &pool, Ocnode **
ref,
int &count,
unsigned long lvl)
360 if (
node->nchild == 0) {
362 if (
node->mi > lvl)
return;
363 ocnodeFree(pool,
node);
367 if (
node->mi &&
node->mi > lvl)
return;
371 Ocnode **lonelychild =
nullptr;
374 ocnodeStrip(pool, &i, count, lvl);
378 node->nleaf += i->nleaf;
379 if (!
node->mi ||
node->mi > i->mi) {
386 if (
node->nchild == 0) {
390 }
else if (
node->nchild == 1) {
391 if ((*lonelychild)->nchild == 0) {
396 ocnodeFree(pool, *lonelychild);
397 *lonelychild =
nullptr;
401 (*lonelychild)->ref =
ref;
402 ocnodeFree(pool,
node);
416 int n = (*ref)->nleaf - ncolor;
417 if (!*
ref || n <= 0)
return;
419 ocnodeStrip(pool,
ref, n, (*ref)->mi);
427void octreeBuildArea(
Pool<Ocnode> &pool, RgbMap
const &rgbmap, Ocnode **
ref,
int x1,
int y1,
int x2,
int y2,
int ncolor)
429 int dx = x2 - x1, dy = y2 - y1;
430 int xm = x1 + dx / 2, ym = y1 + dy / 2;
431 Ocnode *ref1 =
nullptr;
432 Ocnode *ref2 =
nullptr;
433 if (dx == 1 && dy == 1) {
434 ocnodeLeaf(pool,
ref, rgbmap.getPixel(x1, y1));
435 }
else if (dx > dy) {
436 octreeBuildArea(pool, rgbmap, &ref1, x1, y1, xm, y2, ncolor);
437 octreeBuildArea(pool, rgbmap, &ref2, xm, y1, x2, y2, ncolor);
438 octreeMerge(pool,
nullptr,
ref, ref1, ref2);
440 octreeBuildArea(pool, rgbmap, &ref1, x1, y1, x2, ym, ncolor);
441 octreeBuildArea(pool, rgbmap, &ref2, x1, ym, x2, y2, ncolor);
442 octreeMerge(pool,
nullptr,
ref, ref1, ref2);
453Ocnode *octreeBuild(
Pool<Ocnode> &pool, RgbMap
const &rgbmap,
int ncolor)
456 Ocnode *
node =
nullptr;
457 octreeBuildArea(pool,
459 0, 0, rgbmap.width, rgbmap.height, ncolor);
462 octreePrune(pool, &
node, ncolor);
470void octreeIndex(Ocnode *
node, RGB *rgbpal,
int &
index)
473 if (
node->nchild == 0) {
481 octreeIndex(i, rgbpal,
index);
490int distRGB(RGB rgb1, RGB rgb2)
492 return (rgb1.r - rgb2.r) * (rgb1.r - rgb2.r)
493 + (rgb1.g - rgb2.g) * (rgb1.g - rgb2.g)
494 + (rgb1.b - rgb2.b) * (rgb1.b - rgb2.b);
500int findRGB(RGB
const *rgbs,
int ncolor, RGB
rgb)
503 for (
int k = 0; k < ncolor; k++) {
504 int d = distRGB(rgbs[k],
rgb);
522 auto tree = octreeBuild(pool, rgbmap, ncolor);
524 auto rgbs = std::make_unique<RGB[]>(ncolor);
528 octreeDelete(pool,
tree);
531 std::sort(rgbs.get(), rgbs.get() + ncolor, [] (
auto &ra,
auto &rb) {
532 return (ra.r + ra.g + ra.b) < (rb.r + rb.g + rb.b);
537 for (
int i = 0; i <
index; i++) {
538 imap.clut[i] = rgbs[i];
540 imap.nrColors =
index;
543 for (
int y = 0; y < rgbmap.
height; y++) {
544 for (
int x = 0; x < rgbmap.
width; x++) {
546 int index = findRGB(rgbs.get(), ncolor,
rgb);
547 imap.setPixel(x, y,
index);
virtual Node * parent()=0
Get the parent of this node.
vector< vpsc::Rectangle * > rs
static char const *const parent
Inkscape::XML::Node * node
TODO: insert short description here.
std::istream & operator>>(std::istream &is, MTRand &mtrand)
double dist(const Point &a, const Point &b)
bool operator==(D2< T > const &a, D2< T > const &b)
IndexedMap rgbMapQuantize(RgbMap const &rgbmap, int ncolor)
quantize an RGB image to a reduced number of colors.
Helper class to stream background task notifications as a series of messages.
T getPixel(int x, int y) const