pikl 0.2.7 → 0.2.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ #ifndef _EXTRA_MEDIAN_
2
+ #define _EXTRA_MEDIAN_
3
+
4
+ void to_indexed(char*input,long ncolors,long dither,int width,int height,
5
+ unsigned char *Picture256, unsigned char *QuantizedPalette);
6
+
7
+ #endif
@@ -0,0 +1,563 @@
1
+ /* NeuQuant Neural-Net Quantization Algorithm
2
+ * ------------------------------------------
3
+ *
4
+ * Copyright (c) 1994 Anthony Dekker
5
+ *
6
+ * NEUQUANT Neural-Net quantization algorithm by Anthony Dekker, 1994.
7
+ * See "Kohonen neural networks for optimal colour quantization"
8
+ * in "Network: Computation in Neural Systems" Vol. 5 (1994) pp 351-367.
9
+ * for a discussion of the algorithm.
10
+ * See also http://members.ozemail.com.au/~dekker/NEUQUANT.HTML
11
+ *
12
+ * Any party obtaining a copy of these files from the author, directly or
13
+ * indirectly, is granted, free of charge, a full and unrestricted irrevocable,
14
+ * world-wide, paid up, royalty-free, nonexclusive right and license to deal
15
+ * in this software and documentation files (the "Software"), including without
16
+ * limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
17
+ * and/or sell copies of the Software, and to permit persons who receive
18
+ * copies from any such party to do so, with the only requirement being
19
+ * that this copyright notice remain intact.
20
+ */
21
+
22
+ /* ------------------------------------------
23
+ Code found on the Neuquant web page: http://acm.org/~dekker/NEUQUANT.HTML
24
+ */
25
+
26
+ //
27
+ // Benny's additional stuff: v5
28
+ // Weber fix: 9 Mar 00
29
+ //
30
+ // soezimaster additional
31
+ // 2008.8.15
32
+ //
33
+
34
+ int colorsreq = 256;
35
+
36
+ //-- soezimaster delete(function's call)
37
+ //void error(char *s);
38
+ //extern unsigned char *QuantizedPicture;
39
+ //extern unsigned char *QuantizedPalette;
40
+ //----------------------------------------
41
+
42
+ // number of colours used
43
+ #define NETSIZE 256
44
+
45
+ // 1 slower, 30 faster [1..30]
46
+ //#define SFACTOR 15 // 1 15 30
47
+
48
+ #include "neuquant.h"
49
+
50
+ int netsize = NETSIZE;
51
+
52
+ /* Network Definitions
53
+ ------------------- */
54
+
55
+ #define maxnetpos (netsize-1)
56
+ #define netbiasshift 4 /* bias for colour values */
57
+ #define ncycles 100 /* no. of learning cycles */
58
+
59
+ /* defs for freq and bias */
60
+ #define intbiasshift 16 /* bias for fractions */
61
+ #define intbias (((int) 1)<<intbiasshift)
62
+ #define gammashift 10 /* gamma = 1024 */
63
+ #define gamma (((int) 1)<<gammashift)
64
+ #define betashift 10
65
+ #define beta (intbias>>betashift) /* beta = 1/1024 */
66
+ #define betagamma (intbias<<(gammashift-betashift))
67
+
68
+ /* defs for decreasing radius factor */
69
+ #define INITRAD (NETSIZE>>3) /* for 256 cols, radius starts */
70
+ #define initrad (netsize>>3) /* for 256 cols, radius starts */
71
+ #define radiusbiasshift 6 /* at 32.0 biased by 6 bits */
72
+ #define radiusbias (((int) 1)<<radiusbiasshift)
73
+ #define initradius (initrad*radiusbias) /* and decreases by a */
74
+ #define radiusdec 30 /* factor of 1/30 each cycle */
75
+
76
+ /* defs for decreasing alpha factor */
77
+ #define alphabiasshift 10 /* alpha starts at 1.0 */
78
+ #define initalpha (((int) 1)<<alphabiasshift)
79
+ int alphadec; /* biased by 10 bits */
80
+
81
+ /* radbias and alpharadbias used for radpower calculation */
82
+ #define radbiasshift 8
83
+ #define radbias (((int) 1)<<radbiasshift)
84
+ #define alpharadbshift (alphabiasshift+radbiasshift)
85
+ #define alpharadbias (((int) 1)<<alpharadbshift)
86
+
87
+
88
+ /* Types and Global Variables
89
+ -------------------------- */
90
+
91
+ static unsigned char *thepicture; /* the input image itself */
92
+ static int lengthcount; /* lengthcount = H*W*3 */
93
+ static int samplefac; /* sampling factor 1..30 */
94
+
95
+ typedef int pixel[4]; /* BGRc */
96
+ static pixel network[NETSIZE]; /* the network itself */
97
+
98
+ static int netindex[256]; /* for network lookup - really 256 */
99
+
100
+ static int bias[NETSIZE]; /* bias and freq arrays for learning */
101
+ static int freq[NETSIZE];
102
+ static int radpower[INITRAD]; /* radpower for precomputation */
103
+
104
+
105
+ /* Initialise network in range (0,0,0) to (255,255,255) and set parameters
106
+ ----------------------------------------------------------------------- */
107
+
108
+ /*
109
+ void initnet(thepic,len,sample,output_size)
110
+ unsigned char *thepic;
111
+ int len;
112
+ int sample;
113
+ int output_size;
114
+ { */
115
+ //static void initnet(unsigned char *thepic, int len,int sample)
116
+ void initnet(unsigned char *thepic, int len,int sample)
117
+ {
118
+ int i, *p;
119
+
120
+ /*
121
+ netsize = output_size;
122
+
123
+ network = (pixel *)malloc(netsize*sizeof(pixel));
124
+ bias = (int *)malloc(netsize*sizeof(int));
125
+ freq = (int *)malloc(netsize*sizeof(int));
126
+ radpower = (int *)malloc(initrad*sizeof(int));
127
+
128
+ if(!network || !bias || !freq || !radpower)exit(1);
129
+ */
130
+
131
+ thepicture = thepic;
132
+ lengthcount = len;
133
+ samplefac = sample;
134
+
135
+ for (i = 0; i < netsize; i++) {
136
+ p = network[i];
137
+ p[0] = p[1] = p[2] = (i << (netbiasshift + 8)) / netsize;
138
+ freq[i] = intbias / netsize; /* 1/netsize */
139
+ bias[i] = 0;
140
+ }
141
+ }
142
+
143
+
144
+ /* Unbias network to give byte values 0..255 and record position i to prepare for sort
145
+ ----------------------------------------------------------------------------------- */
146
+
147
+ //static void unbiasnet()
148
+ void unbiasnet()
149
+ {
150
+ int i, j;
151
+
152
+ for (i = 0; i < netsize; i++) {
153
+ for (j = 0; j < 3; j++)
154
+ network[i][j] >>= netbiasshift;
155
+ network[i][3] = i; /* record colour no */
156
+ }
157
+ }
158
+
159
+
160
+ /* Output colour map
161
+ -----------------
162
+ static void writecolourmap(FILE *f)
163
+ {
164
+ int i, j;
165
+
166
+ for (i = 2; i >= 0; i--)
167
+ for (j = 0; j < netsize; j++)
168
+ putc(network[j][i], f);
169
+ }
170
+ */
171
+
172
+
173
+ /* Insertion sort of network and building of netindex[0..255]
174
+ (to do after unbias)
175
+ ----------------------------------------------------------
176
+ --------------------- */
177
+
178
+ //static void inxbuild()
179
+ void inxbuild()
180
+ {
181
+ int i, j, smallpos, smallval;
182
+ int *p, *q;
183
+ int previouscol, startpos;
184
+
185
+ previouscol = 0;
186
+ startpos = 0;
187
+ for (i = 0; i < netsize; i++) {
188
+ p = network[i];
189
+ smallpos = i;
190
+ smallval = p[1]; /* index on g */
191
+ /* find smallest in i..netsize-1 */
192
+ for (j = i + 1; j < netsize; j++) {
193
+ q = network[j];
194
+ if (q[1] < smallval) { /* index on g */
195
+ smallpos = j;
196
+ smallval = q[1]; /* index on g */
197
+ }
198
+ }
199
+ q = network[smallpos];
200
+ /* swap p (i) and q (smallpos) entries */
201
+ if (i != smallpos) {
202
+ j = q[0];
203
+ q[0] = p[0];
204
+ p[0] = j;
205
+ j = q[1];
206
+ q[1] = p[1];
207
+ p[1] = j;
208
+ j = q[2];
209
+ q[2] = p[2];
210
+ p[2] = j;
211
+ j = q[3];
212
+ q[3] = p[3];
213
+ p[3] = j;
214
+ }
215
+ /* smallval entry is now in position i */
216
+ if (smallval != previouscol) {
217
+ netindex[previouscol] = (startpos + i) >> 1;
218
+ for (j = previouscol + 1; j < smallval; j++)
219
+ netindex[j] = i;
220
+ previouscol = smallval;
221
+ startpos = i;
222
+ }
223
+ }
224
+ netindex[previouscol] = (startpos + maxnetpos) >> 1;
225
+ for (j = previouscol + 1; j < 256; j++)
226
+ netindex[j] = maxnetpos; /* really 256 */
227
+ }
228
+
229
+
230
+ /* Search for BGR values 0..255 (after net is unbiased) and
231
+ return colour index
232
+ --------------------------------------------------------
233
+ -------------------- */
234
+ //static int inxsearch(int b, int g, int r)
235
+ int inxsearch(int b, int g, int r)
236
+ {
237
+ int i, j, dist, a, bestd;
238
+ int *p;
239
+ int best;
240
+
241
+ bestd = 1000; /* biggest possible dist is 256*3 */
242
+ best = -1;
243
+ i = netindex[g]; /* index on g */
244
+ j = i - 1; /* start at netindex[g] and work outwards */
245
+
246
+ while ((i < netsize) || (j >= 0)) {
247
+ if (i < netsize) {
248
+ p = network[i];
249
+ dist = p[1] - g; /* inx key */
250
+ if (dist >= bestd)
251
+ i = netsize; /* stop iter */
252
+ else {
253
+ i++;
254
+ if (dist < 0)
255
+ dist = -dist;
256
+ a = p[0] - b;
257
+ if (a < 0)
258
+ a = -a;
259
+ dist += a;
260
+ if (dist < bestd) {
261
+ a = p[2] - r;
262
+ if (a < 0)
263
+ a = -a;
264
+ dist += a;
265
+ if (dist < bestd) {
266
+ bestd = dist;
267
+ best = p[3];
268
+ }
269
+ }
270
+ }
271
+ }
272
+ /* if (j >= 0) */ // not needed (Weber)
273
+ if (j >= 0){ //retreave(soezimaster)
274
+ p = network[j];
275
+ dist = g - p[1]; /* inx key - reverse dif */
276
+ if (dist >= bestd)
277
+ j = -1; /* stop iter */
278
+ else {
279
+ j--;
280
+ if (dist < 0)
281
+ dist = -dist;
282
+ a = p[0] - b;
283
+ if (a < 0)
284
+ a = -a;
285
+ dist += a;
286
+ if (dist < bestd) {
287
+ a = p[2] - r;
288
+ if (a < 0)
289
+ a = -a;
290
+ dist += a;
291
+ if (dist < bestd) {
292
+ bestd = dist;
293
+ best = p[3];
294
+ }
295
+ }
296
+ }
297
+ }
298
+ }
299
+ return (best);
300
+ }
301
+
302
+
303
+ /* Search for biased BGR values
304
+ ---------------------------- */
305
+
306
+ static int contest(b, g, r)
307
+ int b, g, r;
308
+ {
309
+ /* finds closest neuron (min dist) and updates freq */
310
+ /* finds best neuron (min dist-bias) and returns position */
311
+ /* for frequently chosen neurons, freq[i] is high and bias[i] is negative */
312
+ /* bias[i] = gamma*((1/netsize)-freq[i]) */
313
+
314
+ int i, dist, a, biasdist, betafreq;
315
+ int bestpos, bestbiaspos, bestd, bestbiasd;
316
+ int *p, *f, *n;
317
+
318
+ bestd = ~(((int) 1) << 31);
319
+ bestbiasd = bestd;
320
+ bestpos = -1;
321
+ bestbiaspos = bestpos;
322
+ p = bias;
323
+ f = freq;
324
+
325
+ for (i = 0; i < netsize; i++) {
326
+ n = network[i];
327
+ dist = n[0] - b;
328
+ if (dist < 0)
329
+ dist = -dist;
330
+ a = n[1] - g;
331
+ if (a < 0)
332
+ a = -a;
333
+ dist += a;
334
+ a = n[2] - r;
335
+ if (a < 0)
336
+ a = -a;
337
+ dist += a;
338
+ if (dist < bestd) {
339
+ bestd = dist;
340
+ bestpos = i;
341
+ }
342
+ biasdist = dist - ((*p) >> (intbiasshift - netbiasshift));
343
+ if (biasdist < bestbiasd) {
344
+ bestbiasd = biasdist;
345
+ bestbiaspos = i;
346
+ }
347
+ betafreq = (*f >> betashift);
348
+ *f++ -= betafreq;
349
+ *p++ += (betafreq << gammashift);
350
+ }
351
+ freq[bestpos] += beta;
352
+ bias[bestpos] -= betagamma;
353
+ return (bestbiaspos);
354
+ }
355
+
356
+
357
+ /* Move neuron i towards biased (b,g,r) by factor alpha
358
+ ---------------------------------------------------- */
359
+
360
+ static void altersingle(alpha, i, b, g, r)
361
+ int alpha, i, b, g, r;
362
+ {
363
+ int *n;
364
+
365
+ n = network[i]; /* alter hit neuron */
366
+ *n -= (alpha * (*n - b)) / initalpha;
367
+ n++;
368
+ *n -= (alpha * (*n - g)) / initalpha;
369
+ n++;
370
+ *n -= (alpha * (*n - r)) / initalpha;
371
+ }
372
+
373
+
374
+ /* Move adjacent neurons by precomputed alpha*(1-((i-j)^2/[r]^2))
375
+ in radpower[|i-j|]
376
+ --------------------------------------------------------------
377
+ ------------------- */
378
+
379
+ static void alterneigh(rad, i, b, g, r)
380
+ int rad, i;
381
+ int b, g, r;
382
+ {
383
+ int j, k, lo, hi, a;
384
+ int *p, *q;
385
+
386
+ lo = i - rad;
387
+ if (lo < -1)
388
+ lo = -1;
389
+ hi = i + rad;
390
+ if (hi > netsize)
391
+ hi = netsize;
392
+
393
+ j = i + 1;
394
+ k = i - 1;
395
+ q = radpower;
396
+ while ((j < hi) || (k > lo)) {
397
+ a = (*(++q));
398
+ if (j < hi) {
399
+ p = network[j];
400
+ *p -= (a * (*p - b)) / alpharadbias;
401
+ p++;
402
+ *p -= (a * (*p - g)) / alpharadbias;
403
+ p++;
404
+ *p -= (a * (*p - r)) / alpharadbias;
405
+ j++;
406
+ }
407
+ if (k > lo) {
408
+ p = network[k];
409
+ *p -= (a * (*p - b)) / alpharadbias;
410
+ p++;
411
+ *p -= (a * (*p - g)) / alpharadbias;
412
+ p++;
413
+ *p -= (a * (*p - r)) / alpharadbias;
414
+ k--;
415
+ }
416
+ }
417
+ }
418
+
419
+
420
+ /* Main Learning Loop
421
+ ------------------ */
422
+ //static void learn()
423
+ void learn()
424
+ {
425
+ int i, j, b, g, r;
426
+ int radius, rad, alpha, step, delta, samplepixels;
427
+ unsigned char *p;
428
+ unsigned char *lim;
429
+
430
+ alphadec = 30 + ((samplefac - 1) / 3);
431
+ p = thepicture;
432
+ lim = thepicture + lengthcount;
433
+ samplepixels = lengthcount / (3 * samplefac);
434
+ delta = samplepixels / ncycles;
435
+ alpha = initalpha;
436
+ radius = initradius;
437
+
438
+ rad = radius >> radiusbiasshift;
439
+ if (rad <= 1)
440
+ rad = 0;
441
+ for (i = 0; i < rad; i++)
442
+ radpower[i] = alpha * (((rad * rad - i * i) * radbias) / (rad * rad));
443
+
444
+ // printf("beginning 1D learning: initial radius=%d\n", rad);
445
+
446
+ if ((lengthcount % prime1) != 0)
447
+ step = 3 * prime1;
448
+ else {
449
+ if ((lengthcount % prime2) != 0)
450
+ step = 3 * prime2;
451
+ else {
452
+ if ((lengthcount % prime3) != 0)
453
+ step = 3 * prime3;
454
+ else
455
+ step = 3 * prime4;
456
+ }
457
+ }
458
+
459
+ i = 0;
460
+ while (i < samplepixels) {
461
+ b = p[0] << netbiasshift;
462
+ g = p[1] << netbiasshift;
463
+ r = p[2] << netbiasshift;
464
+ j = contest(b, g, r);
465
+
466
+ altersingle(alpha, j, b, g, r);
467
+ if (rad)
468
+ alterneigh(rad, j, b, g, r); /* alter neighbours */
469
+
470
+ p += step;
471
+ if (p >= lim)
472
+ p -= lengthcount;
473
+
474
+ i++;
475
+ if (i % delta == 0) {
476
+ alpha -= alpha / alphadec;
477
+ radius -= radius / radiusdec;
478
+ rad = radius >> radiusbiasshift;
479
+ if (rad <= 1)
480
+ rad = 0;
481
+ for (j = 0; j < rad; j++)
482
+ radpower[j] = alpha * (((rad * rad - j * j) * radbias) / (rad * rad));
483
+ }
484
+ }
485
+ // printf("finished 1D learning: final alpha=%f !\n",((float)alpha)/initalpha);
486
+ }
487
+
488
+
489
+
490
+ static void writemap(unsigned char *f)
491
+ {
492
+ int j, k = 0;
493
+
494
+ //// BGR
495
+ //for (j = 0; j < /*netsize*/ colorsreq; j++) {
496
+ // f[k] = network[j][2];
497
+ // k++;
498
+ // f[k] = network[j][1];
499
+ // k++;
500
+ // f[k] = network[j][0];
501
+ // k++;
502
+ //}
503
+ //--changed.(soezimaster)
504
+ //RGB
505
+ //for (j = 0; j < /*netsize*/ colorsreq; j++) {
506
+ for (j = 0; j <netsize; j++) {
507
+ f[k++] = network[j][0];
508
+ f[k++] = network[j][1];
509
+ f[k++] = network[j][2];
510
+ }
511
+ }
512
+
513
+
514
+
515
+ static void Quantize24Bit(unsigned char *pic_in,
516
+ unsigned char *pic_out, unsigned char *pal_out,
517
+ int length, int reduce_to, int sample_factor)
518
+ {
519
+ int i;
520
+
521
+ netsize = reduce_to;
522
+ initnet(pic_in, length, sample_factor);
523
+
524
+ learn();
525
+ unbiasnet();
526
+
527
+ writemap(pal_out);
528
+ inxbuild();
529
+
530
+ for (i = 0; i < length; i += 3)
531
+ pic_out[i / 3] = inxsearch(pic_in[i+0], pic_in[i+1], pic_in[i+2]);
532
+ }
533
+
534
+ //int neuReduce(unsigned char *RGBpic, int numcolors, long picsize, int sfactor)
535
+ int neuReduce(unsigned char *RGBpic, int numcolors, long picsize, int sfactor,
536
+ unsigned char *QuantizedPicture, unsigned char *QuantizedPalette)
537
+ {
538
+ colorsreq = numcolors;
539
+ Quantize24Bit(RGBpic,
540
+ QuantizedPicture,
541
+ QuantizedPalette,
542
+ picsize*3L,
543
+ numcolors,
544
+ sfactor);
545
+ return 0;
546
+ }
547
+
548
+ /* Program Skeleton
549
+ ----------------
550
+ [select samplefac in range 1..30]
551
+ [read image from input file]
552
+ pic_in = (unsigned char*) malloc(3*width*height);
553
+ initnet(pic_in,3*width*height,samplefac);
554
+ learn();
555
+ unbiasnet();
556
+ [write output image header, using writecolourmap(f)]
557
+ inxbuild();
558
+ write output image using inxsearch(b,g,r)
559
+ */
560
+ /* Output:
561
+ QuantizedPicture[picsize];
562
+ QuantizedPalette[numcolors*3];
563
+ */