53 #define HASH_SIZE 20023
54 #define ppm_hashpixel(p) (((int)(p)&0x7fffffff) % HASH_SIZE)
58 typedef struct colorhist_item *colorhist_vector;
59 struct colorhist_item {
64 typedef struct colorhist_list_item *colorhist_list;
65 struct colorhist_list_item {
66 struct colorhist_item ch;
90 for(i = 0; i <
HASH_SIZE; ++i) cht[i] = (colorhist_list)
nullptr;
98 colorhist_list chl, chlnext;
101 for(chl = cht[i]; chl != (colorhist_list)
nullptr; chl = chlnext) {
109 const int cols,
const int rows,
122 for(row = 0; row < rows; ++row)
123 for(col = 0, pP = pixels[row]; col < cols; ++col, ++pP) {
125 for(chl = cht[hash]; chl != (colorhist_list)
nullptr; chl = chl->next)
127 if(chl != (colorhist_list)
nullptr)
130 if(++(*colorsP) > maxcolors) {
134 chl = (colorhist_list)
Malloc(
sizeof(
struct colorhist_list_item));
137 chl->next = cht[hash];
151 chl = (colorhist_list)
Malloc(
sizeof(
struct colorhist_list_item));
153 chl->ch.color = *colorP;
154 chl->ch.value = value;
155 chl->next = cht[hash];
163 colorhist_vector chv;
168 chv = (colorhist_vector)
Malloc(maxcolors *
sizeof(
struct colorhist_item));
172 for(chl = cht[i]; chl != (colorhist_list)
nullptr; chl = chl->next) {
192 for(i = 0; i < colors; ++i) {
193 color = chv[i].color;
195 for(chl = cht[hash]; chl != (colorhist_list)
nullptr; chl = chl->next)
199 chl = (colorhist_list)
Malloc(
sizeof(
struct colorhist_list_item));
200 chl->ch.color = color;
202 chl->next = cht[hash];
210 const int cols,
const int rows,
215 colorhist_vector chv;
230 for(chl = cht[hash]; chl != (colorhist_list)
nullptr; chl = chl->next)
231 if(
PPM_EQUAL(chl->ch.color, *colorP))
return chl->ch.value;
248 else if(colors <= 16)
250 else if(colors <= 32)
252 else if(colors <= 64)
254 else if(colors <= 128)
256 else if(colors <= 256)
259 Msg::Error(
"GIF: can't happen: too many colors");
266 static int sqr(
int x) {
return x * x; }
270 int i, r, g, b, d, imin = 0, dmin;
308 #define REP_AVERAGE_PIXELS
319 return (
int)
PPM_GETR(((colorhist_vector)ch1)->color) -
320 (int)
PPM_GETR(((colorhist_vector)ch2)->color);
325 return (
int)
PPM_GETG(((colorhist_vector)ch1)->color) -
326 (int)
PPM_GETG(((colorhist_vector)ch2)->color);
331 return (
int)
PPM_GETB(((colorhist_vector)ch1)->color) -
332 (int)
PPM_GETB(((colorhist_vector)ch2)->color);
346 static colorhist_vector
mediancut(colorhist_vector chv,
int colors,
int sum,
347 pixval maxval,
int newcolors)
349 colorhist_vector colormap;
356 (colorhist_vector)malloc(
sizeof(
struct colorhist_item) * newcolors);
357 if(bv == (
box_vector)
nullptr || colormap == (colorhist_vector)
nullptr)
359 for(i = 0; i < newcolors; ++i)
PPM_ASSIGN(colormap[i].color, 0, 0, 0);
372 while(boxes < newcolors) {
375 int minr, maxr, ming, maxg, minb, maxb, v;
376 int halfsum, lowersum;
381 for(bi = 0; bi < boxes; ++bi)
382 if(bv[bi].colors >= 2)
break;
383 if(bi == boxes)
break;
392 minr = maxr =
PPM_GETR(chv[indx].color);
393 ming = maxg =
PPM_GETG(chv[indx].color);
394 minb = maxb =
PPM_GETB(chv[indx].color);
395 for(i = 1; i < clrs; ++i) {
397 if(v < minr) minr = v;
398 if(v > maxr) maxr = v;
400 if(v < ming) ming = v;
401 if(v > maxg) maxg = v;
403 if(v < minb) minb = v;
404 if(v > maxb) maxb = v;
416 if(maxr - minr >= maxg - ming && maxr - minr >= maxb - minb)
417 qsort((
char *)&(chv[indx]), clrs,
sizeof(
struct colorhist_item),
419 else if(maxg - ming >= maxb - minb)
420 qsort((
char *)&(chv[indx]), clrs,
sizeof(
struct colorhist_item),
423 qsort((
char *)&(chv[indx]), clrs,
sizeof(
struct colorhist_item),
438 if(rl >= gl && rl >= bl)
439 qsort((
char *)&(chv[indx]), clrs,
sizeof(
struct colorhist_item),
442 qsort((
char *)&(chv[indx]), clrs,
sizeof(
struct colorhist_item),
445 qsort((
char *)&(chv[indx]), clrs,
sizeof(
struct colorhist_item),
453 lowersum = chv[indx].value;
455 for(i = 1; i < clrs - 1; ++i) {
456 if(lowersum >= halfsum)
break;
457 lowersum += chv[indx + i].value;
464 bv[bi].
sum = lowersum;
465 bv[boxes].
ind = indx + i;
466 bv[boxes].
colors = clrs - i;
467 bv[boxes].
sum = sm - lowersum;
482 for(bi = 0; bi < boxes; ++bi) {
483 #ifdef REP_CENTER_BOX
484 int indx = bv[bi].
ind;
486 int minr, maxr, ming, maxg, minb, maxb, v;
488 minr = maxr =
PPM_GETR(chv[indx].color);
489 ming = maxg =
PPM_GETG(chv[indx].color);
490 minb = maxb =
PPM_GETB(chv[indx].color);
491 for(i = 1; i < clrs; ++i) {
502 PPM_ASSIGN(colormap[bi].color, (minr + maxr) / 2, (ming + maxg) / 2,
506 #ifdef REP_AVERAGE_COLORS
507 int indx = bv[bi].
ind;
509 long r = 0, g = 0, b = 0;
511 for(i = 0; i < clrs; ++i) {
522 #ifdef REP_AVERAGE_PIXELS
523 int indx = bv[bi].
ind;
525 long r = 0, g = 0, b = 0, sum = 0;
527 for(i = 0; i < clrs; ++i) {
528 r +=
PPM_GETR(chv[indx + i].color) * chv[indx + i].value;
529 g +=
PPM_GETG(chv[indx + i].color) * chv[indx + i].value;
530 b +=
PPM_GETB(chv[indx + i].color) * chv[indx + i].value;
531 sum += chv[indx + i].value;
534 if(r > (
long)maxval) r = maxval;
536 if(g > (
long)maxval) g = maxval;
538 if(b > (
long)maxval) b = maxval;
570 #define ARGVAL() (*++(*argv) || (--argc && *++argv))
578 #define MAXCODE(n_bits) (((code_int)1 << (n_bits)) - 1)
582 #define HashTabOf(i) htab[i]
583 #define CodeTabOf(i) codetab[i]
596 #define tab_prefixof(i) CodeTabOf(i)
597 #define tab_suffixof(i) ((char_type *)(htab))[i]
598 #define de_stack ((char_type *)&tab_suffixof((code_int)1 << BITS))
697 case 3:
cury += 2;
break;
739 static unsigned long masks[] = {0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F,
740 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF,
741 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF};
838 }
while((i -= 16) >= 0);
840 for(i += 16; i > 0; --i) *--htab_p = m1;
890 for(fcode = (
long)
hsize; fcode < 65536L; fcode *= 2L) ++hshift;
901 fcode = (long)(((
long)
c <<
maxbits) + ent);
910 disp = hsize_reg - i;
913 if((i -= disp) < 0) i += hsize_reg;
945 fputc((w / 256) & 0xff, fp);
948 static void GIFEncode(FILE *fp,
int GWidth,
int GHeight,
int GInterlace,
949 int Background,
int Transparent,
int BitsPerPixel,
967 ColorMapSize = 1 << BitsPerPixel;
969 RWidth =
Width = GWidth;
970 RHeight =
Height = GHeight;
971 LeftOfs = TopOfs = 0;
973 Resolution = BitsPerPixel;
988 if(BitsPerPixel <= 1)
991 InitCodeSize = BitsPerPixel;
1001 fwrite(Transparent < 0 ?
"GIF87a" :
"GIF89a", 1, 6, fp);
1017 B |= (Resolution - 1) << 5;
1022 B |= (BitsPerPixel - 1);
1032 fputc(Background, fp);
1042 for(i = 0; i < ColorMapSize; ++i) {
1044 fputc(Green[i], fp);
1051 if(Transparent >= 0) {
1058 fputc(Transparent, fp);
1087 fputc(InitCodeSize, fp);
1107 #define FS_SCALE 1024
1108 #define MAXCOL2 32767
1111 int interlace,
int transparency)
1113 int i, j, k, transparent, rows, cols;
1115 colorhist_vector chv, colormap;
1116 int BitsPerPixel, usehash;
1120 int col, row, limitcol, ind;
1121 int newcolors = 256;
1122 long *thisrerr =
nullptr, *nextrerr =
nullptr, *thisgerr =
nullptr, *nextgerr =
nullptr;
1123 long *thisberr =
nullptr, *nextberr =
nullptr, *temperr =
nullptr;
1124 long sr = 0, sg = 0, sb = 0, err = 0;
1125 int fs_direction = 0;
1132 Msg::Error(
"GIF only implemented for GL_RGB");
1137 for(i = 0; i < height; i++)
1140 unsigned char *pixels = (
unsigned char *)buffer->
getPixels();
1141 for(i = 0; i < height; i++)
1142 for(j = 0; j < width; j++)
1144 static_pixels[height - 1 - i][j], pixels[i * width * 3 + j * 3],
1145 pixels[i * width * 3 + j * 3 + 1], pixels[i * width * 3 + j * 3 + 2]);
1154 if(chv == (colorhist_vector)
nullptr) {
1164 if(chv != (colorhist_vector)
nullptr)
break;
1166 newmaxval = maxval / 2;
1167 Msg::Debug(
"GIF: scaling colors from maxval=%d to maxval=%d to improve "
1170 for(row = 0; row < rows; ++row)
1171 for(col = 0, pP =
static_pixels[row]; col < cols; ++col, ++pP)
1176 Msg::Debug(
"GIF: choosing %d colors...", newcolors);
1184 Msg::Debug(
"GIF: mapping image to new colors...");
1188 Msg::Debug(
"GIF: Floyd-Steinberg dithering is selected...");
1190 thisrerr = (
long *)
Malloc((cols + 2) *
sizeof(long));
1191 nextrerr = (
long *)
Malloc((cols + 2) *
sizeof(long));
1192 thisgerr = (
long *)
Malloc((cols + 2) *
sizeof(long));
1193 nextgerr = (
long *)
Malloc((cols + 2) *
sizeof(long));
1194 thisberr = (
long *)
Malloc((cols + 2) *
sizeof(long));
1195 nextberr = (
long *)
Malloc((cols + 2) *
sizeof(long));
1197 for(col = 0; col < cols + 2; ++col) {
1205 for(row = 0; row < rows; ++row) {
1207 for(col = 0; col < cols + 2; ++col)
1208 nextrerr[col] = nextgerr[col] = nextberr[col] = 0;
1210 if((!dither) || fs_direction) {
1229 else if(sr > (
long)maxval)
1233 else if(sg > (
long)maxval)
1237 else if(sb > (
long)maxval)
1245 int i, r1, g1,
b1, r2, g2, b2;
1251 for(i = 0; i < newcolors; ++i) {
1255 newdist = (r1 - r2) * (r1 - r2) + (g1 - g2) * (g1 - g2) +
1256 (
b1 - b2) * (
b1 - b2);
1257 if(newdist < dist) {
1264 Msg::Warning(
"GIF: Out of memory adding to hash table");
1274 thisrerr[col + 2] += (err * 7) / 16;
1275 nextrerr[col] += (err * 3) / 16;
1276 nextrerr[col + 1] += (err * 5) / 16;
1277 nextrerr[col + 2] += (err) / 16;
1279 thisgerr[col + 2] += (err * 7) / 16;
1280 nextgerr[col] += (err * 3) / 16;
1281 nextgerr[col + 1] += (err * 5) / 16;
1282 nextgerr[col + 2] += (err) / 16;
1284 thisberr[col + 2] += (err * 7) / 16;
1285 nextberr[col] += (err * 3) / 16;
1286 nextberr[col + 1] += (err * 5) / 16;
1287 nextberr[col + 2] += (err) / 16;
1291 thisrerr[col] += (err * 7) / 16;
1292 nextrerr[col + 2] += (err * 3) / 16;
1293 nextrerr[col + 1] += (err * 5) / 16;
1294 nextrerr[col] += (err) / 16;
1296 thisgerr[col] += (err * 7) / 16;
1297 nextgerr[col + 2] += (err * 3) / 16;
1298 nextgerr[col + 1] += (err * 5) / 16;
1299 nextgerr[col] += (err) / 16;
1301 thisberr[col] += (err * 7) / 16;
1302 nextberr[col + 2] += (err * 3) / 16;
1303 nextberr[col + 1] += (err * 5) / 16;
1304 nextberr[col] += (err) / 16;
1308 *pP = colormap[ind].color;
1310 if((!dither) || fs_direction) {
1318 }
while(col != limitcol);
1322 thisrerr = nextrerr;
1325 thisgerr = nextgerr;
1328 thisberr = nextberr;
1330 fs_direction = !fs_direction;
1392 if(transparent == -1)
1401 GIFEncode(outfile, width, height, interlace, 0, transparent, BitsPerPixel,