Color quantization: Difference between revisions

Updated second D entry
(+ second D entry)
(Updated second D entry)
Line 288:
import std.exception: enforce;
import std.array: empty;
import std.compiler: version_minor;
 
enum ON_INHEAP = 1;
Line 323 ⟶ 324:
} while (line.length && line[0] == '#');
 
static if (version_minor < 66) { //*
const size = line.split.to!(uint[]);
enforce( const size.length == 2line.split.to!(uint[]);
//immutable enforce(size.length == line.split.to!(uint[2]);
} else {
const immutable size = line.split.to!(uint[2]);
}
auto img = imageNew(size[0], size[1]);
enforce(fIn.readln.strip == "255");
Line 373 ⟶ 377:
}
 
void downHeap(NodeHeap* h, OctreeNode* p) pure nothrow @nogc {
in {
assert(h != null);
assert(p != null);
} body {
auto n = p.heapIdx;
 
Line 395 ⟶ 403:
}
 
void upHeap(NodeHeap* h, OctreeNode* p) pure nothrow @nogc {
in {
assert(h != null);
assert(p != null);
} body {
auto n = p.heapIdx;
 
Line 412 ⟶ 424:
}
 
void heapAdd(NodeHeap* h, OctreeNode* p) nothrow @nogc {
in {
assert(h != null);
assert(p != null);
} body {
if ((p.flags & ON_INHEAP)) {
downHeap(h, p);
Line 434 ⟶ 450:
}
 
OctreeNode* popHeap(NodeHeap* h) pure nothrow @nogc {
in {
assert(h != null);
} out(result) {
assert(result != null);
} body {
if (h.n <= 1)
return null;
Line 450 ⟶ 471:
 
OctreeNode* nodeNew(in ubyte idx, in ubyte depth, OctreeNode* p,
ref OctreeNode*[] pool) nothrow @nogc {
out(result) {
assert(result != null);
} body {
__gshared static uint len = 0;
 
Line 456 ⟶ 480:
OctreeNode* p2 = cast(OctreeNode*)calloc(OctreeNode.sizeof, 2048);
assert(p2 != null);
p2.parent = pool.ptr;
pool = p2[0 .. 2048];
len = 2047;
}
 
OctreeNode* x = pool.ptr + len--;
x.kidIdx = idx;
x.depth = depth;
Line 470 ⟶ 494:
}
 
void nodeFree(ref OctreeNode*[] poolpoolArr) nothrow @nogc {
out {
assert(poolArr.length == 0);
} body {
auto pool = poolArr.ptr;
 
while (pool) {
auto p = pool.parent;
Line 476 ⟶ 505:
pool = p;
}
 
poolArr = null;
}
 
OctreeNode* nodeInsert(OctreeNode* root, in ubyte* pix, ref OctreeNode*[] pool)
nothrow @nogc {
in {
assert(root != null);
assert(pix != null);
assert(pool.length != 0);
} out(result) {
assert(result != null);
} body {
ubyte depth = 0;
 
Line 499 ⟶ 537:
}
 
OctreeNode* nodeFold(OctreeNode* p) nothrow @nogc {
in {
assert(p != null);
} out(result) {
assert(result != null);
} body {
if (p.nKids)
abort();
Line 513 ⟶ 556:
}
 
void colorReplace(OctreeNode* root, ubyte* pix) pure nothrow @nogc {
in {
assert(root != null);
assert(pix != null);
} body {
for (ubyte bit = (1 << 7); bit; bit >>= 1) {
immutable i = !!(pix[1] & bit) * 4 +
Line 528 ⟶ 575:
}
 
void errorDiffuse(Image* im, NodeHeap* h) nothrow @nogc {
in {
OctreeNode* nearestColor(in int* v) nothrow @nogc {
assert(im != null);
assert(h != null);
} body {
OctreeNode* nearestColor(in int* v) nothrow @nogc {
in {
assert(v != null);
} out(result) {
assert(result != null);
} body {
auto max = long.max;
typeof(return) on = null;
Line 624 ⟶ 680:
}
 
void colorQuant(Image* im, in uint nColors, in bool dither) nothrow @nogc {
in {
assert(im != null);
assert(nColors > 1);
} body {
auto pix = im.pix.ptr;
NodeHeap heap = { 0, 0, null };
OctreeNode*[] pool = null;
 
auto root = nodeNew(0, 0, null, pool);