mirror of
https://frontier.innolan.net/github/AmigaExamples.git
synced 2026-09-12 23:12:56 +00:00
Got build working on newer OSX, included missing ADFs
This commit is contained in:
+56
-56
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
/*
|
||||
*
|
||||
* Originally from: https://rosettacode.org/wiki/Color_quantization/C
|
||||
* License information http://www.gnu.org/licenses/fdl-1.2.html
|
||||
* License information http://www.gnu.org/licenses/fdl-1.2.html
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -13,10 +13,10 @@
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
#include "quant.h"
|
||||
#include "quant.h"
|
||||
|
||||
|
||||
quant_image_t*
|
||||
|
||||
quant_image_t*
|
||||
quant_newImage(int w, int h)
|
||||
{
|
||||
quant_image_t* im = malloc(sizeof(quant_image_t) + h * w * 3);
|
||||
@@ -24,9 +24,9 @@ quant_newImage(int w, int h)
|
||||
im->pix = (unsigned char *)(im + 1);
|
||||
return im;
|
||||
}
|
||||
|
||||
|
||||
#define ON_INHEAP 1
|
||||
|
||||
|
||||
typedef struct oct_node_t oct_node_t, *oct_node;
|
||||
struct oct_node_t{
|
||||
int64_t r, g, b; /* sum of all child node colors */
|
||||
@@ -34,22 +34,22 @@ struct oct_node_t{
|
||||
unsigned char n_kids, kid_idx, flags, depth;
|
||||
oct_node kids[8], parent;
|
||||
};
|
||||
|
||||
|
||||
typedef struct {
|
||||
int alloc, n;
|
||||
oct_node* buf;
|
||||
} node_heap;
|
||||
|
||||
|
||||
inline int cmp_node(oct_node a, oct_node b)
|
||||
{
|
||||
if (a->n_kids < b->n_kids) return -1;
|
||||
if (a->n_kids > b->n_kids) return 1;
|
||||
|
||||
|
||||
int ac = a->count >> a->depth;
|
||||
int bc = b->count >> b->depth;
|
||||
return ac < bc ? -1 : ac > bc;
|
||||
}
|
||||
|
||||
|
||||
void down_heap(node_heap *h, oct_node p)
|
||||
{
|
||||
int n = p->heap_idx, m;
|
||||
@@ -57,9 +57,9 @@ void down_heap(node_heap *h, oct_node p)
|
||||
m = n * 2;
|
||||
if (m >= h->n) break;
|
||||
if (m + 1 < h->n && cmp_node(h->buf[m], h->buf[m + 1]) > 0) m++;
|
||||
|
||||
|
||||
if (cmp_node(p, h->buf[m]) <= 0) break;
|
||||
|
||||
|
||||
h->buf[n] = h->buf[m];
|
||||
h->buf[n]->heap_idx = n;
|
||||
n = m;
|
||||
@@ -67,16 +67,16 @@ void down_heap(node_heap *h, oct_node p)
|
||||
h->buf[n] = p;
|
||||
p->heap_idx = n;
|
||||
}
|
||||
|
||||
|
||||
void up_heap(node_heap *h, oct_node p)
|
||||
{
|
||||
int n = p->heap_idx;
|
||||
oct_node prev;
|
||||
|
||||
|
||||
while (n > 1) {
|
||||
prev = h->buf[n / 2];
|
||||
if (cmp_node(p, prev) >= 0) break;
|
||||
|
||||
|
||||
h->buf[n] = prev;
|
||||
prev->heap_idx = n;
|
||||
n /= 2;
|
||||
@@ -84,7 +84,7 @@ void up_heap(node_heap *h, oct_node p)
|
||||
h->buf[n] = p;
|
||||
p->heap_idx = n;
|
||||
}
|
||||
|
||||
|
||||
void heap_add(node_heap *h, oct_node p)
|
||||
{
|
||||
if ((p->flags & ON_INHEAP)) {
|
||||
@@ -92,34 +92,34 @@ void heap_add(node_heap *h, oct_node p)
|
||||
up_heap(h, p);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
p->flags |= ON_INHEAP;
|
||||
if (!h->n) h->n = 1;
|
||||
if (h->n >= h->alloc) {
|
||||
while (h->n >= h->alloc) h->alloc += 1024;
|
||||
h->buf = realloc(h->buf, sizeof(oct_node) * h->alloc);
|
||||
}
|
||||
|
||||
|
||||
p->heap_idx = h->n;
|
||||
h->buf[h->n++] = p;
|
||||
up_heap(h, p);
|
||||
}
|
||||
|
||||
|
||||
oct_node pop_heap(node_heap *h)
|
||||
{
|
||||
if (h->n <= 1) return 0;
|
||||
|
||||
|
||||
oct_node ret = h->buf[1];
|
||||
h->buf[1] = h->buf[--h->n];
|
||||
|
||||
|
||||
h->buf[h->n] = 0;
|
||||
|
||||
|
||||
h->buf[1]->heap_idx = 1;
|
||||
down_heap(h, h->buf[1]);
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static oct_node pool = 0;
|
||||
oct_node node_new(unsigned char idx, unsigned char depth, oct_node p)
|
||||
{
|
||||
@@ -130,7 +130,7 @@ oct_node node_new(unsigned char idx, unsigned char depth, oct_node p)
|
||||
pool = p_;
|
||||
len = 2047;
|
||||
}
|
||||
|
||||
|
||||
oct_node x = pool + len--;
|
||||
x->kid_idx = idx;
|
||||
x->depth = depth;
|
||||
@@ -138,7 +138,7 @@ oct_node node_new(unsigned char idx, unsigned char depth, oct_node p)
|
||||
if (p) p->n_kids++;
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
void node_free()
|
||||
{
|
||||
oct_node p;
|
||||
@@ -148,32 +148,32 @@ void node_free()
|
||||
pool = p;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
oct_node node_insert(oct_node root, unsigned char *pix)
|
||||
{
|
||||
unsigned char i, bit, depth = 0;
|
||||
|
||||
|
||||
for (bit = 1 << 7; ++depth < 8; bit >>= 1) {
|
||||
i = !!(pix[1] & bit) * 4 + !!(pix[0] & bit) * 2 + !!(pix[2] & bit);
|
||||
if (!root->kids[i])
|
||||
root->kids[i] = node_new(i, depth, root);
|
||||
|
||||
|
||||
root = root->kids[i];
|
||||
}
|
||||
|
||||
|
||||
root->r += pix[0];
|
||||
root->g += pix[1];
|
||||
root->b += pix[2];
|
||||
root->count++;
|
||||
return root;
|
||||
}
|
||||
|
||||
|
||||
oct_node node_fold(oct_node p)
|
||||
{
|
||||
if (p->n_kids) abort();
|
||||
oct_node q = p->parent;
|
||||
q->count += p->count;
|
||||
|
||||
|
||||
q->r += p->r;
|
||||
q->g += p->g;
|
||||
q->b += p->b;
|
||||
@@ -181,31 +181,31 @@ oct_node node_fold(oct_node p)
|
||||
q->kids[p->kid_idx] = 0;
|
||||
return q;
|
||||
}
|
||||
|
||||
|
||||
void color_replace(oct_node root, unsigned char *pix)
|
||||
{
|
||||
unsigned char i, bit;
|
||||
|
||||
|
||||
for (bit = 1 << 7; bit; bit >>= 1) {
|
||||
i = !!(pix[1] & bit) * 4 + !!(pix[0] & bit) * 2 + !!(pix[2] & bit);
|
||||
if (!root->kids[i]) break;
|
||||
root = root->kids[i];
|
||||
}
|
||||
|
||||
|
||||
pix[0] = root->r;
|
||||
pix[1] = root->g;
|
||||
pix[2] = root->b;
|
||||
}
|
||||
|
||||
static oct_node
|
||||
static oct_node
|
||||
nearest_color(int *v, node_heap *h) {
|
||||
int i;
|
||||
int diff, max = 100000000;
|
||||
oct_node o = 0;
|
||||
for (i = 1; i < h->n; i++) {
|
||||
diff = 3 * abs(h->buf[i]->r - v[0])
|
||||
+ 5 * abs(h->buf[i]->g - v[1])
|
||||
+ 2 * abs(h->buf[i]->b - v[2]);
|
||||
diff = 3 * abs((int)(h->buf[i]->r - v[0]))
|
||||
+ 5 * abs((int)(h->buf[i]->g - v[1]))
|
||||
+ 2 * abs((int)(h->buf[i]->b - v[2]));
|
||||
if (diff < max) {
|
||||
max = diff;
|
||||
o = h->buf[i];
|
||||
@@ -213,23 +213,23 @@ nearest_color(int *v, node_heap *h) {
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
|
||||
void error_diffuse(quant_image_t* im, node_heap *h)
|
||||
{
|
||||
|
||||
|
||||
#define POS(i, j) (3 * ((i) * im->w + (j)))
|
||||
int i, j;
|
||||
int *npx = calloc(sizeof(int), im->h * im->w * 3), *px;
|
||||
int v[3];
|
||||
unsigned char *pix = im->pix;
|
||||
oct_node nd;
|
||||
|
||||
|
||||
#define C10 7
|
||||
#define C01 5
|
||||
#define C11 2
|
||||
#define C00 1
|
||||
#define C00 1
|
||||
#define CTOTAL (C00 + C11 + C10 + C01)
|
||||
|
||||
|
||||
for (px = npx, i = 0; i < im->h; i++) {
|
||||
for (j = 0; j < im->w; j++, pix += 3, px += 3) {
|
||||
px[0] = (int)pix[0] * CTOTAL;
|
||||
@@ -245,13 +245,13 @@ void error_diffuse(quant_image_t* im, node_heap *h)
|
||||
px[1] /= CTOTAL;
|
||||
px[2] /= CTOTAL;
|
||||
clamp(px, 0); clamp(px, 1); clamp(px, 2);
|
||||
|
||||
|
||||
nd = nearest_color(px, h);
|
||||
|
||||
|
||||
v[0] = px[0] - nd->r;
|
||||
v[1] = px[1] - nd->g;
|
||||
v[2] = px[2] - nd->b;
|
||||
|
||||
|
||||
pix[0] = nd->r; pix[1] = nd->g; pix[2] = nd->b;
|
||||
if (j < im->w - 1) {
|
||||
npx[POS(i, j+1) + 0] += v[0] * C10;
|
||||
@@ -259,11 +259,11 @@ void error_diffuse(quant_image_t* im, node_heap *h)
|
||||
npx[POS(i, j+1) + 2] += v[2] * C10;
|
||||
}
|
||||
if (i >= im->h - 1) continue;
|
||||
|
||||
|
||||
npx[POS(i+1, j) + 0] += v[0] * C01;
|
||||
npx[POS(i+1, j) + 1] += v[1] * C01;
|
||||
npx[POS(i+1, j) + 2] += v[2] * C01;
|
||||
|
||||
|
||||
if (j < im->w - 1) {
|
||||
npx[POS(i+1, j+1) + 0] += v[0] * C11;
|
||||
npx[POS(i+1, j+1) + 1] += v[1] * C11;
|
||||
@@ -278,8 +278,8 @@ void error_diffuse(quant_image_t* im, node_heap *h)
|
||||
}
|
||||
free(npx);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
void
|
||||
quant_quantize(quant_image_t* im, int n_colors, int dither)
|
||||
{
|
||||
int i;
|
||||
@@ -291,12 +291,12 @@ quant_quantize(quant_image_t* im, int n_colors, int dither)
|
||||
for (i = 0; i < im->w * im->h; i++, pix += 3)
|
||||
heap_add(&heap, node_insert(root, pix));
|
||||
|
||||
|
||||
|
||||
while (heap.n > n_colors + 1)
|
||||
heap_add(&heap, node_fold(pop_heap(&heap)));
|
||||
|
||||
|
||||
|
||||
|
||||
double c;
|
||||
for (i = 1; i < heap.n; i++) {
|
||||
got = heap.buf[i];
|
||||
@@ -305,12 +305,12 @@ quant_quantize(quant_image_t* im, int n_colors, int dither)
|
||||
got->g = got->g / c + .5;
|
||||
got->b = got->b / c + .5;
|
||||
}
|
||||
|
||||
|
||||
if (dither) error_diffuse(im, &heap);
|
||||
else
|
||||
for (i = 0, pix = im->pix; i < im->w * im->h; i++, pix += 3)
|
||||
color_replace(root, pix);
|
||||
|
||||
|
||||
node_free();
|
||||
free(heap.buf);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user