pikl 0.2.7-x86-mswin32 → 0.2.8-x86-mswin32

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,62 @@
1
+ /* NeuQuant Neural-Net Quantization Algorithm Interface
2
+ * ----------------------------------------------------
3
+ */
4
+
5
+ #include <stdio.h>
6
+
7
+ /* For 256 colours, fixed arrays need 8kb, plus space for the image
8
+ ---------------------------------------------------------------- */
9
+
10
+ /* four primes near 500 - assume no image has a length so large */
11
+ /* that it is divisible by all four primes */
12
+ #define prime1 499
13
+ #define prime2 491
14
+ #define prime3 487
15
+ #define prime4 503
16
+
17
+ #define minpicturebytes (3*prime4) /* minimum size for input image */
18
+
19
+
20
+ /* Initialise network in range (0,0,0) to (255,255,255) and set parameters
21
+ ----------------------------------------------------------------------- */
22
+ void initnet(unsigned char *thepic, int len, int sample);
23
+
24
+ /* Unbias network to give byte values 0..255 and record position i to prepare for sort
25
+ ----------------------------------------------------------------------------------- */
26
+ void unbiasnet(); /* can edit this function to do output of colour map */
27
+
28
+ /* Output colour map
29
+ ----------------- */
30
+ void writecolourmap(FILE *f);
31
+
32
+ /* Insertion sort of network and building of netindex[0..255] (to do after unbias)
33
+ ------------------------------------------------------------------------------- */
34
+ void inxbuild();
35
+
36
+ /* Search for BGR values 0..255 (after net is unbiased) and return colour index
37
+ ---------------------------------------------------------------------------- */
38
+ int inxsearch(register int b, register int g, register int r);
39
+
40
+ /* Main Learning Loop
41
+ ------------------ */
42
+ void learn();
43
+
44
+
45
+
46
+
47
+ int neuReduce(unsigned char *RGBpic, int numcolors, long picsize, int sfactor,
48
+ unsigned char *QuantizedPicture, unsigned char *QuantizedPalette);
49
+
50
+
51
+
52
+ /* Program Skeleton
53
+ ----------------
54
+ [select samplefac in range 1..30]
55
+ [read image from input file]
56
+ pic = (unsigned char*) malloc(3*width*height);
57
+ initnet(pic,3*width*height,samplefac);
58
+ learn();
59
+ unbiasnet();
60
+ [write output image header, using writecolourmap(f)]
61
+ inxbuild();
62
+ write output image using inxsearch(b,g,r) */
@@ -0,0 +1,447 @@
1
+ /*
2
+ C Implementation of Wu's Color Quantizer (v2.0)
3
+ -- Xiaolin Wu.
4
+ From the Graphics Gems.
5
+
6
+ Memory hungry.
7
+
8
+ Some fixes and additional code by Benny.
9
+ */
10
+
11
+ #include<stdio.h>
12
+ #include<assert.h>
13
+ #include<malloc.h>
14
+
15
+ //#define NOINVERT // RGB or BGR
16
+
17
+ void error(char *s);
18
+
19
+ ///* Externs: */
20
+ //extern unsigned char *Picture256;
21
+ //extern unsigned char QuantizedPalette[768];
22
+
23
+ #define MAXCOLOR 256
24
+ #define RED 2
25
+ #define GREEN 1
26
+ #define BLUE 0
27
+
28
+ struct box {
29
+ int r0; /* min value, exclusive */
30
+ int r1; /* max value, inclusive */
31
+ int g0;
32
+ int g1;
33
+ int b0;
34
+ int b1;
35
+ int vol;
36
+ };
37
+
38
+ /* Histogram is in elements 1..HISTSIZE along each axis,
39
+ element 0 is for base or marginal value.
40
+ NB: these must start out 0! */
41
+ #define BOX 33
42
+ long wt[BOX][BOX][BOX],
43
+ mr[BOX][BOX][BOX],
44
+ mg[BOX][BOX][BOX],
45
+ mb[BOX][BOX][BOX];
46
+ float m2[BOX][BOX][BOX];
47
+
48
+ int ImageSize; /* image size */
49
+ int PalSize; /* color look-up table size */
50
+
51
+ unsigned short *Qadd; // *must* be unsigned?
52
+ unsigned char *TrueColorPic;
53
+
54
+ /* build 3-D color histogram of counts, r/g/b, c^2 */
55
+ static void Hist3d(long *vwt, long *vmr, long *vmg, long *vmb, float *m_2)
56
+ {
57
+ int ind,
58
+ r,
59
+ g,
60
+ b;
61
+ int inr,
62
+ ing,
63
+ inb,
64
+ table[256];
65
+ long i;
66
+
67
+ for (i = 0; i < 256; ++i)
68
+ table[i] = i * i;
69
+
70
+ for (i = 0; i < ImageSize; ++i) {
71
+ r = TrueColorPic[i*3 ];
72
+ g = TrueColorPic[i*3+1];
73
+ b = TrueColorPic[i*3+2];
74
+
75
+ inr = (r >> 3) + 1;
76
+ ing = (g >> 3) + 1;
77
+ inb = (b >> 3) + 1;
78
+ Qadd[i] = ind = (inr << 10) + (inr << 6) + inr + (ing << 5) + ing + inb;
79
+ /* [inr][ing][inb] */
80
+ ++vwt[ind];
81
+ vmr[ind] += r;
82
+ vmg[ind] += g;
83
+ vmb[ind] += b;
84
+ m_2[ind] += (float) (table[r] + table[g] + table[b]);
85
+ }
86
+ }
87
+
88
+ /* We now convert histogram into moments so that we can rapidly calculate
89
+ the sums of the above quantities over any desired box. */
90
+ static void Momt3d(long *vwt, long *vmr, long *vmg, long *vmb, float *m_2)
91
+ {
92
+ unsigned short ind1,
93
+ ind2;
94
+ unsigned char i,
95
+ r,
96
+ g,
97
+ b;
98
+ long line,
99
+ line_r,
100
+ line_g,
101
+ line_b,
102
+ area[BOX],
103
+ area_r[BOX],
104
+ area_g[BOX],
105
+ area_b[BOX];
106
+ float line2,
107
+ area2[BOX];
108
+
109
+ for (r = 1; r <= 32; ++r) {
110
+ for (i = 0; i <= 32; ++i)
111
+ area2[i] = area[i] = area_r[i] = area_g[i] = area_b[i] = 0;
112
+ for (g = 1; g <= 32; ++g) {
113
+ line2 = line = line_r = line_g = line_b = 0;
114
+ for (b = 1; b <= 32; ++b) {
115
+ ind1 = (r << 10) + (r << 6) + r + (g << 5) + g + b;
116
+ /* [r][g][b] */
117
+ line += vwt[ind1];
118
+ line_r += vmr[ind1];
119
+ line_g += vmg[ind1];
120
+ line_b += vmb[ind1];
121
+ line2 += m_2[ind1];
122
+ area[b] += line;
123
+ area_r[b] += line_r;
124
+ area_g[b] += line_g;
125
+ area_b[b] += line_b;
126
+ area2[b] += line2;
127
+ ind2 = ind1 - 1089; /* [r-1][g][b] */
128
+ vwt[ind1] = vwt[ind2] + area[b];
129
+ vmr[ind1] = vmr[ind2] + area_r[b];
130
+ vmg[ind1] = vmg[ind2] + area_g[b];
131
+ vmb[ind1] = vmb[ind2] + area_b[b];
132
+ m_2[ind1] = m_2[ind2] + area2[b];
133
+ }
134
+ }
135
+ }
136
+ }
137
+
138
+ static long Vol(struct box * cube, long mmt[BOX][BOX][BOX])
139
+ {
140
+ return (mmt[cube->r1][cube->g1][cube->b1]
141
+ - mmt[cube->r1][cube->g1][cube->b0]
142
+ - mmt[cube->r1][cube->g0][cube->b1]
143
+ + mmt[cube->r1][cube->g0][cube->b0]
144
+ - mmt[cube->r0][cube->g1][cube->b1]
145
+ + mmt[cube->r0][cube->g1][cube->b0]
146
+ + mmt[cube->r0][cube->g0][cube->b1]
147
+ - mmt[cube->r0][cube->g0][cube->b0]);
148
+ }
149
+
150
+ static long
151
+ Bottom(struct box * cube, unsigned char dir, long mmt[BOX][BOX][BOX])
152
+ {
153
+ switch (dir) {
154
+ case RED:
155
+ return (-mmt[cube->r0][cube->g1][cube->b1]
156
+ + mmt[cube->r0][cube->g1][cube->b0]
157
+ + mmt[cube->r0][cube->g0][cube->b1]
158
+ - mmt[cube->r0][cube->g0][cube->b0]);
159
+ case GREEN:
160
+ return (-mmt[cube->r1][cube->g0][cube->b1]
161
+ + mmt[cube->r1][cube->g0][cube->b0]
162
+ + mmt[cube->r0][cube->g0][cube->b1]
163
+ - mmt[cube->r0][cube->g0][cube->b0]);
164
+ case BLUE:
165
+ return (-mmt[cube->r1][cube->g1][cube->b0]
166
+ + mmt[cube->r1][cube->g0][cube->b0]
167
+ + mmt[cube->r0][cube->g1][cube->b0]
168
+ - mmt[cube->r0][cube->g0][cube->b0]);
169
+ }
170
+ error("error in Bottom()");
171
+ return 0;
172
+ }
173
+
174
+ static long
175
+ Top(struct box * cube, unsigned char dir, int pos, long mmt[BOX][BOX][BOX])
176
+ {
177
+ switch (dir) {
178
+ case RED:
179
+ return (mmt[pos][cube->g1][cube->b1]
180
+ - mmt[pos][cube->g1][cube->b0]
181
+ - mmt[pos][cube->g0][cube->b1]
182
+ + mmt[pos][cube->g0][cube->b0]);
183
+ case GREEN:
184
+ return (mmt[cube->r1][pos][cube->b1]
185
+ - mmt[cube->r1][pos][cube->b0]
186
+ - mmt[cube->r0][pos][cube->b1]
187
+ + mmt[cube->r0][pos][cube->b0]);
188
+ case BLUE:
189
+ return (mmt[cube->r1][cube->g1][pos]
190
+ - mmt[cube->r1][cube->g0][pos]
191
+ - mmt[cube->r0][cube->g1][pos]
192
+ + mmt[cube->r0][cube->g0][pos]);
193
+ }
194
+ error("error in Top()");
195
+ return 0;
196
+ }
197
+
198
+
199
+ static float Var(struct box * cube)
200
+ {
201
+ float dr,
202
+ dg,
203
+ db,
204
+ xx;
205
+
206
+ dr = Vol(cube, mr);
207
+ dg = Vol(cube, mg);
208
+ db = Vol(cube, mb);
209
+ xx = m2[cube->r1][cube->g1][cube->b1]
210
+ - m2[cube->r1][cube->g1][cube->b0]
211
+ - m2[cube->r1][cube->g0][cube->b1]
212
+ + m2[cube->r1][cube->g0][cube->b0]
213
+ - m2[cube->r0][cube->g1][cube->b1]
214
+ + m2[cube->r0][cube->g1][cube->b0]
215
+ + m2[cube->r0][cube->g0][cube->b1]
216
+ - m2[cube->r0][cube->g0][cube->b0];
217
+
218
+ return (xx - (dr * dr + dg * dg + db * db) / (float) Vol(cube, wt));
219
+ }
220
+
221
+ static float Maximize(cube, dir, first, last, cut,
222
+ whole_r, whole_g, whole_b, whole_w)
223
+ struct box *cube;
224
+ unsigned char dir;
225
+ int first,
226
+ last,
227
+ *cut;
228
+ long whole_r,
229
+ whole_g,
230
+ whole_b,
231
+ whole_w;
232
+ {
233
+ long half_r,
234
+ half_g,
235
+ half_b,
236
+ half_w;
237
+ long base_r,
238
+ base_g,
239
+ base_b,
240
+ base_w;
241
+ int i;
242
+ float temp, max;
243
+
244
+ base_r = Bottom(cube, dir, mr);
245
+ base_g = Bottom(cube, dir, mg);
246
+ base_b = Bottom(cube, dir, mb);
247
+ base_w = Bottom(cube, dir, wt);
248
+ max = 0.0;
249
+ *cut = -1;
250
+ for (i = first; i < last; ++i) {
251
+ half_r = base_r + Top(cube, dir, i, mr);
252
+ half_g = base_g + Top(cube, dir, i, mg);
253
+ half_b = base_b + Top(cube, dir, i, mb);
254
+ half_w = base_w + Top(cube, dir, i, wt);
255
+ /* now half_x is sum over lower half of box, if split at i */
256
+ if (half_w == 0) { /* subbox could be empty of pixels! */
257
+ continue; /* never split into an empty box */
258
+ } else
259
+ temp = ((float) half_r * half_r + (float) half_g * half_g +
260
+ (float) half_b * half_b) / half_w;
261
+
262
+ half_r = whole_r - half_r;
263
+ half_g = whole_g - half_g;
264
+ half_b = whole_b - half_b;
265
+ half_w = whole_w - half_w;
266
+ if (half_w == 0) { /* subbox could be empty of pixels! */
267
+ continue; /* never split into an empty box */
268
+ } else
269
+ temp += ((float) half_r * half_r + (float) half_g * half_g +
270
+ (float) half_b * half_b) / half_w;
271
+
272
+ if (temp > max) {
273
+ max = temp;
274
+ *cut = i;
275
+ }
276
+ }
277
+ return (max);
278
+ }
279
+
280
+ static int Cut(struct box * set1, struct box * set2)
281
+ {
282
+ unsigned char dir;
283
+ int cutr,
284
+ cutg,
285
+ cutb;
286
+ float maxr,
287
+ maxg,
288
+ maxb;
289
+ long whole_r,
290
+ whole_g,
291
+ whole_b,
292
+ whole_w;
293
+
294
+ whole_r = Vol(set1, mr);
295
+ whole_g = Vol(set1, mg);
296
+ whole_b = Vol(set1, mb);
297
+ whole_w = Vol(set1, wt);
298
+
299
+ maxr = Maximize(set1, RED, set1->r0 + 1, set1->r1, &cutr,
300
+ whole_r, whole_g, whole_b, whole_w);
301
+ maxg = Maximize(set1, GREEN, set1->g0 + 1, set1->g1, &cutg,
302
+ whole_r, whole_g, whole_b, whole_w);
303
+ maxb = Maximize(set1, BLUE, set1->b0 + 1, set1->b1, &cutb,
304
+ whole_r, whole_g, whole_b, whole_w);
305
+
306
+ if ((maxr >= maxg) && (maxr >= maxb)) {
307
+ dir = RED;
308
+ if (cutr < 0)
309
+ return 0; /* can't split the box */
310
+ } else if ((maxg >= maxr) && (maxg >= maxb))
311
+ dir = GREEN;
312
+ else
313
+ dir = BLUE;
314
+
315
+ set2->r1 = set1->r1;
316
+ set2->g1 = set1->g1;
317
+ set2->b1 = set1->b1;
318
+
319
+ switch (dir) {
320
+ case RED:
321
+ set2->r0 = set1->r1 = cutr;
322
+ set2->g0 = set1->g0;
323
+ set2->b0 = set1->b0;
324
+ break;
325
+ case GREEN:
326
+ set2->g0 = set1->g1 = cutg;
327
+ set2->r0 = set1->r0;
328
+ set2->b0 = set1->b0;
329
+ break;
330
+ case BLUE:
331
+ set2->b0 = set1->b1 = cutb;
332
+ set2->r0 = set1->r0;
333
+ set2->g0 = set1->g0;
334
+ break;
335
+ }
336
+ set1->vol = (set1->r1 - set1->r0) * (set1->g1 - set1->g0) * (set1->b1 - set1->b0);
337
+ set2->vol = (set2->r1 - set2->r0) * (set2->g1 - set2->g0) * (set2->b1 - set2->b0);
338
+ return 1;
339
+ }
340
+
341
+ static void Mark(struct box * cube, int label, unsigned char *tag)
342
+ {
343
+ int r, g, b;
344
+ for (r = cube->r0 + 1; r <= cube->r1; ++r)
345
+ for (g = cube->g0 + 1; g <= cube->g1; ++g)
346
+ for (b = cube->b0 + 1; b <= cube->b1; ++b)
347
+ tag[(r << 10) + (r << 6) + r + (g << 5) + g + b] = label;
348
+ }
349
+
350
+ #define WEIG //>>2
351
+ //int wuReduce(unsigned char *RGBpic, int numcolors, long picsize)
352
+ int wuReduce(unsigned char *RGBpic, int numcolors, long picsize,
353
+ unsigned char *Picture256, unsigned char *QuantizedPalette)
354
+ {
355
+ struct box cube[MAXCOLOR];
356
+ unsigned char *tag = 0;
357
+ float vv[MAXCOLOR],
358
+ temp = 0.;
359
+ long i = 0,
360
+ weight = 0;
361
+ int next = 0;
362
+ int j = 0,k = 0,l = 0;
363
+
364
+ /* input R,G,B components into TrueColorPic;
365
+ set ImageSize to width*height */
366
+ TrueColorPic = RGBpic;
367
+ ImageSize = picsize;
368
+ PalSize = numcolors;
369
+
370
+ for (j=0;j<BOX;j++)
371
+ for (k=0;k<BOX;k++)
372
+ for (l=0;l<BOX;l++) {
373
+ wt[j][k][l] = 0;
374
+ mr[j][k][l] = 0;
375
+ mg[j][k][l] = 0;
376
+ mb[j][k][l] = 0;
377
+ m2[j][k][l] = 0.;
378
+ }
379
+
380
+ Qadd = malloc(ImageSize * sizeof(short));
381
+ if (!Qadd) error("Not enough mem for *Qadd");
382
+
383
+ Hist3d((long *)&wt, (long *)&mr, (long *)&mg, (long *)&mb, (float *)&m2);
384
+ Momt3d((long *)&wt, (long *)&mr, (long *)&mg, (long *)&mb, (float *)&m2);
385
+
386
+ cube[0].r0 = cube[0].g0 = cube[0].b0 = 0;
387
+ cube[0].r1 = cube[0].g1 = cube[0].b1 = 32;
388
+ next = 0;
389
+ for (i = 1; i < PalSize; ++i) {
390
+ if (Cut(&cube[next], &cube[i])) {
391
+ vv[next] = (cube[next].vol > 1) ? Var(&cube[next]) : 0.0;
392
+ vv[i] = (cube[i].vol > 1) ? Var(&cube[i]) : 0.0;
393
+ } else {
394
+ vv[next] = 0.0;
395
+ i--;
396
+ }
397
+ next = 0;
398
+ temp = vv[0];
399
+ for (k = 1; k <= i; ++k)
400
+ if (vv[k] > temp) {
401
+ temp = vv[k];
402
+ next = k;
403
+ }
404
+ if (temp <= 0.0) {
405
+ PalSize = i + 1;
406
+ break;
407
+ }
408
+ }
409
+
410
+ tag = malloc(BOX * BOX * BOX);
411
+ if (!tag) error("Not enough mem for *tag");
412
+
413
+ for (k = 0; k < PalSize; ++k) {
414
+ Mark(&cube[k], k, tag);
415
+ weight = Vol(&cube[k], wt);
416
+ if (weight) {
417
+
418
+ #ifdef NOINVERT
419
+ QuantizedPalette[k*3+2] = (Vol(&cube[k], mr) / weight) WEIG;
420
+ QuantizedPalette[k*3+0] = (Vol(&cube[k], mb) / weight) WEIG;
421
+ #else
422
+ QuantizedPalette[k*3+0] = (Vol(&cube[k], mr) / weight) WEIG;
423
+ QuantizedPalette[k*3+2] = (Vol(&cube[k], mb) / weight) WEIG;
424
+ #endif
425
+ QuantizedPalette[k*3+1] = (Vol(&cube[k], mg) / weight) WEIG;
426
+ } else {
427
+ QuantizedPalette[k*3+0] =
428
+ QuantizedPalette[k*3+1] =
429
+ QuantizedPalette[k*3+2] = 0;
430
+ }
431
+ }
432
+
433
+ #ifdef VERBOSE
434
+ printf("ImageSize = %i\n", ImageSize);
435
+ #endif
436
+ for (i = 0; i < ImageSize; i++) {
437
+ Picture256[i] = tag[Qadd[i]];
438
+ }
439
+
440
+ free(tag);
441
+ free(Qadd);
442
+
443
+ return 0;
444
+ }
445
+ /* Output: QuantizedPalette[numcolors*3];
446
+ Picture256[picsize];
447
+ */