#ifdef _plan9_ #include #include #include #else #include #include #include #include #include #include #include #ifndef NO_MALLOC_H #include #endif #include #endif #include #include #include #include #define nprecells (context->type & (LARGEITER|SMALLITER|TRUECOLOR|TRUECOLOR16|TRUECOLOR24)?0:(context)->ncells) #define PREALLOCATED(palette) ((palette)->type & (LARGEITER|SMALLITER|TRUECOLOR|TRUECOLOR16|TRUECOLOR24)?0:(palette)->npreallocated) /*emulate allocation routines using setpalette */ unsigned col_diff[3][512]; static struct palette *context; static int maxentries; static int needupdate; static void genertruecolorinfo(struct truec *t, unsigned int r, unsigned int g, unsigned int b) { int n; for (n = 0; !((r >> n) & 1); n++); t->rshift = n; for (; ((r >> n) & 1); n++); t->rprec = 8 - (n - t->rshift); t->rmask = r; for (n = 0; !((g >> n) & 1); n++); t->gshift = n; for (; ((g >> n) & 1); n++); t->gprec = 8 - (n - t->gshift); t->gmask = g; for (n = 0; !((b >> n) & 1); n++); t->bshift = n; for (; ((b >> n) & 1); n++); t->bprec = 8 - (n - t->bshift); t->bmask = b; t->allmask = r | g | b; if ((r & b) || (r & g) || (b & g)) { x_fatalerror("Internal error:Invalid color masks 1 %x %x %x!\n", r, g, b); } if ((r < g && g < b) || (b < g && g < r)) { t->mask1 = r | b; t->mask2 = g; } else if ((g < r && r < b) || (b < r && r < g)) { t->mask1 = g | b; t->mask2 = r; } else if ((g < b && b < r) || (r < b && b < g)) { t->mask1 = g | r; t->mask2 = b; } t->byteexact = 0; t->missingbyte = -1; if (!(t->rshift % 8) && !(t->gshift % 8) && !(t->bshift % 8) && !t->rprec && !t->gprec && !t->bprec) { t->byteexact = 1; { unsigned char ch[4]; *(unsigned int *) ch = t->allmask; if (!ch[0]) t->missingbyte = 0; if (!ch[1]) t->missingbyte = 1; if (!ch[2]) t->missingbyte = 2; if (!ch[3]) t->missingbyte = 3; } } #ifdef DEBUG printf("Image:\n"); printf("rshift:%i gshift:%i bshift:%i\n", t->rshift, t->gshift, t->bshift); printf("rprec:%i gprec:%i bprec:%i\n", t->rprec, t->gprec, t->bprec); printf("rmask:%x gmask:%x bmask:%x\n", t->rmask, t->gmask, t->bmask); printf("mask1:%x mask2:%x allmask:%x\n", t->mask1, t->mask2, t->allmask); printf("byteexact:%x missingbyte:%i\n", t->byteexact, t->missingbyte); #endif } void bestfit_init(void) { int i; for (i = 1; i < 256; i++) { int k = i * i; col_diff[0][i] = col_diff[0][512 - i] = k * (59 * 59) / 256; col_diff[1][i] = col_diff[1][512 - i] = k * (30 * 30) / 256; col_diff[2][i] = col_diff[2][512 - i] = k * (11 * 11) / 256; } } static int allocgenerictruecolor(struct palette *palette, int init, int r, int g, int b) { unsigned int n; switch (palette->type) { case LARGEITER: case SMALLITER: #ifdef _UNDEFINED_ if (init) n = 0; else n = palette->size; #endif return 1; case TRUECOLOR: case TRUECOLOR16: case TRUECOLOR24: default: n = ((r >> palette->info.truec.rprec) << palette->info.truec. rshift) | ((g >> palette->info.truec.gprec) << palette->info. truec.gshift) | ((b >> palette->info.truec. bprec) << palette->info.truec. bshift); break; } if (init) palette->size = 0; else if (palette->size >= palette->maxentries) return -1; palette->pixels[palette->size] = n; palette->size++; return palette->size; } static int allocgeneric(struct palette *palette, int init, int r, int g, int b) { int start = palette->npreallocated + palette->start; if (init) palette->size = 0; else if (palette->size >= palette->end - start) return -1; palette->pixels[palette->size] = palette->size + start; palette->rgb[palette->size + start][0] = r; palette->rgb[palette->size + start][1] = g; palette->rgb[palette->size + start][2] = b; palette->size++; return (palette->size - 1); } int fixedalloccolor(struct palette *palette, int init, int r, int g, int b) { int i, coldif, lowest, bestfit; if (init) palette->size = 0; else if (palette->size >= palette->maxentries) return -1; lowest = INT_MAX; bestfit = 1; if (palette->type == FIXEDCOLOR || (palette->type & BITMAPS)) { for (i = palette->start; i < palette->end; i++) { coldif = col_diff[0][(g - palette->rgb[i][1]) & 0x1ff]; if (coldif < lowest) { coldif += col_diff[1][(r - palette->rgb[i][0]) & 0x1ff]; if (coldif < lowest) { coldif += col_diff[2][(b - palette->rgb[i][2]) & 0x1ff]; if (coldif < lowest) { bestfit = i; if (!coldif) break; lowest = coldif; } } } } } else { bestfit = (r * 30 + g * 59 + b * 11) * (palette->end - palette->start) / 256 / 100 + palette->start; } palette->pixels[palette->size] = bestfit; palette->size++; return (palette->size - 1); } static void setcolorgeneric(struct palette *palette, int start, int end, rgb_t * rgb) { } static void allocfinishedgeneric(struct palette *palette) { palette->setpalette(palette, palette->start, palette->size + palette->start + palette->npreallocated, palette->rgb + palette->start); } static void cycle_entries(struct palette *c, int direction) { int i; int i1, i2, i3; rgb_t *co; if (direction > 0) direction %= c->size - 1; else direction = -((-direction) % (c->size - 1)); if (!direction) return; co = (rgb_t *) malloc(c->end * sizeof(rgb_t)); memcpy(co, c->rgb, sizeof(*co) * c->end); i3 = (c->size - 1 + direction) % (c->size - 1) + 1; for (i = 1; i < c->size; i++) { i1 = c->pixels[i]; i2 = c->pixels[i3]; c->rgb[i1][0] = co[i2][0]; c->rgb[i1][1] = co[i2][1]; c->rgb[i1][2] = co[i2][2]; i3++; if (i3 >= c->size) i3 = 1; } free(co); } static void cyclecolorsgeneric(struct palette *pal, int direction) { cycle_entries(pal, direction); pal->setpalette(pal, pal->pixels[0], pal->size + pal->pixels[0], pal->rgb + pal->pixels[0]); } #define TRUECOLORPALETTE 65536 struct palette *createpalette(int start, int end, int type, int flags, int maxentries, int (*alloccolor) (struct palette * pal, int init, int r, int g, int b), void (*setcolor) (struct palette * pal, int start, int end, rgb_t * rgb), void (*allocfinished) (struct palette * pal), void (*cyclecolors) (struct palette * pal, int direction), union paletteinfo *info) { static int versioncount; struct palette *palette = (struct palette *) calloc(1, sizeof(struct palette)); if (col_diff[0][1] == 0) bestfit_init(); palette->ncells = 0; palette->index = NULL; palette->size = 0; palette->rgb = NULL; if (palette == NULL) return NULL; switch (type) { case LBITMAP: case MBITMAP: case LIBITMAP: case MIBITMAP: end = 2; start = 0; maxentries = 256; palette->rgb = (rgb_t *) calloc(end, sizeof(*palette->rgb)); if (palette->rgb == NULL) { free(palette); return NULL; } if (type & (LIBITMAP | MIBITMAP)) { palette->rgb[0][0] = 255; palette->rgb[0][1] = 255; palette->rgb[0][2] = 255; palette->rgb[1][0] = 0; palette->rgb[1][1] = 0; palette->rgb[1][2] = 0; } else { palette->rgb[0][0] = 0; palette->rgb[0][1] = 0; palette->rgb[0][2] = 0; palette->rgb[1][0] = 255; palette->rgb[1][1] = 255; palette->rgb[1][2] = 255; } palette->maxentries = maxentries; palette->alloccolor = fixedalloccolor; palette->setpalette = NULL; palette->allocfinished = NULL; palette->cyclecolors = NULL; break; case FIXEDCOLOR: if (!end) end = 256; if (!maxentries) maxentries = 256; palette->rgb = (rgb_t *) calloc(end, sizeof(*palette->rgb)); if (palette->rgb == NULL) { free(palette); return NULL; } palette->maxentries = maxentries; palette->alloccolor = fixedalloccolor; palette->setpalette = NULL; palette->allocfinished = NULL; palette->cyclecolors = NULL; break; case GRAYSCALE: if (!end) end = 256; if (!maxentries) maxentries = end - start; palette->maxentries = 65536; palette->alloccolor = fixedalloccolor; palette->setpalette = NULL; palette->allocfinished = NULL; palette->cyclecolors = NULL; palette->size = end - start; break; case C256: if (!end) end = 256; if (!maxentries) maxentries = end - start; if (cyclecolors == NULL && setcolor != NULL) cyclecolors = cyclecolorsgeneric; if (alloccolor == NULL) { alloccolor = allocgeneric, allocfinished = allocfinishedgeneric; if (setcolor == NULL && type == C256) /*non hardware palette */ setcolor = setcolorgeneric, cyclecolors = cyclecolorsgeneric; } palette->rgb = (rgb_t *) calloc(end, sizeof(*palette->rgb)); if (palette->rgb == NULL) { free(palette); return NULL; } palette->maxentries = maxentries; palette->alloccolor = alloccolor; palette->setpalette = setcolor; palette->allocfinished = allocfinished; palette->cyclecolors = cyclecolors; break; default: end = TRUECOLORPALETTE; start = 0; if (type == SMALLITER) end = 256; start = 0; palette->maxentries = end; palette->alloccolor = allocgenerictruecolor; palette->cyclecolors = NULL; palette->setpalette = NULL; palette->allocfinished = NULL; } { int ee = palette->maxentries; /*if(end>palette->maxentries) ee=end; */ if (ee < 256) palette->pixels = (unsigned int *) calloc(256, sizeof(*palette->pixels)); else palette->pixels = (unsigned int *) calloc(ee, sizeof(*palette->pixels)); } if (palette->pixels == NULL) { free(palette); return NULL; } if (type & (LARGEITER | SMALLITER)) { int i; palette->size = end; palette->flags |= DONOTCHANGE; for (i = 0; i < end; i++) palette->pixels[i] = i; } palette->start = start; palette->end = end; palette->type = type; palette->flags |= flags; palette->version = (versioncount += 65536); if (type == FIXEDCOLOR) { int i; if (setcolor != NULL) setcolor(palette, start, end, palette->rgb); for (i = 0; i < end - start; i++) palette->pixels[i] = i + start; } if (type == GRAYSCALE) { int i; for (i = palette->start; i < end - start; i++) palette->pixels[i] = i + start; } if (info != NULL && (type == TRUECOLOR || type == TRUECOLOR24 || type == TRUECOLOR16)) { genertruecolorinfo(&palette->info.truec, info->truec.rmask, info->truec.gmask, info->truec.bmask); } else { if (type == TRUECOLOR) genertruecolorinfo(&palette->info.truec, 255 << 16, 255 << 8, 255); if (type == TRUECOLOR24) genertruecolorinfo(&palette->info.truec, 255 << 16, 255 << 8, 255); if (type == TRUECOLOR16) genertruecolorinfo(&palette->info.truec, (255 >> 3) << 11, (255 >> 2) << 5, (255 >> 3)); } return (palette); } void destroypalette(struct palette *palette) { free(palette->pixels); if (palette->rgb != NULL) free(palette->rgb); if (palette->index != NULL) free(palette->index); free(palette); } #define MYMIN(x,y) ((x)<(y)?(x):(y)) struct palette *clonepalette(struct palette *palette) { struct palette *pal = createpalette(palette->start, palette->end, palette->type, palette->flags, palette->maxentries, /*palette->alloccolor, palette->setpalette, palette->allocfinished, palette->cyclecolors */ NULL, NULL, NULL, NULL, &palette->info); memcpy(pal->pixels, palette->pixels, sizeof(*pal->pixels) * MYMIN(palette->end, pal->end)); if (pal->rgb != NULL) { memcpy(pal->rgb, palette->rgb, sizeof(*pal->rgb) * MYMIN(palette->end, pal->end)); } pal->size = palette->size; return (pal); } void preallocpalette(struct palette *pal) { int i; int p; if (pal->index != NULL) free(pal->index), pal->index = NULL; pal->npreallocated = 0; if (!pal->ncells) return; pal->index = (unsigned int *) malloc(sizeof(int) * (pal->ncells + 1)); for (i = 0; i < pal->ncells; i++) { if (!i) p = pal->pixels[0]; else p = pal->pixels[pal->size]; pal->alloccolor(pal, i == 0, pal->prergb[i][0], pal->prergb[i][1], pal->prergb[i][2]); if (pal->size) { pal->index[i] = pal->pixels[pal->size - 1]; pal->pixels[pal->size - 1] = p; } } pal->npreallocated = pal->size; pal->size = 0; needupdate = 0; } void restorepalette(struct palette *dest, struct palette *src) { int i; preallocpalette(dest); for (i = 0; i < src->size; i++) { int r = 0, g = 0, b = 0; switch (src->type) { case SMALLITER: r = g = b = i; break; case LARGEITER: r = g = b = i / 256; break; case GRAYSCALE: r = g = b = src->pixels[i]; break; case C256: case FIXEDCOLOR: case MBITMAP: case LBITMAP: case MIBITMAP: case LIBITMAP: r = src->rgb[src->pixels[i]][0]; g = src->rgb[src->pixels[i]][1]; b = src->rgb[src->pixels[i]][2]; break; case TRUECOLOR: case TRUECOLOR16: case TRUECOLOR24: r = (((src->pixels[i] & src->info.truec.rmask) >> src-> info.truec.rshift)) << src->info.truec.rprec; g = (((src->pixels[i] & src->info.truec.gmask) >> src-> info.truec.gshift)) << src->info.truec.gprec; b = (((src->pixels[i] & src->info.truec.bmask) >> src-> info.truec.bshift)) << src->info.truec.bprec; break; } if (dest->size >= dest->maxentries - PREALLOCATED(dest)) break; if (dest-> alloccolor(dest, (i + dest->npreallocated) == 0, r, g, b) == -1) break; } if (!(dest->flags & FINISHLATER)) { if (dest->allocfinished != NULL) dest->allocfinished(dest); } else dest->flags |= UNFINISHED; dest->version++; } /*Generation code for various palettes */ #define DEFNSEGMENTS (255/8) #define MAXNSEGMENTS (4096) #define NSEGMENTS ((255/segmentsize)) static int segmentsize; static unsigned char colors[MAXNSEGMENTS][3]; static CONST unsigned char colors1[DEFNSEGMENTS][3] = { /*{8, 14, 32}, */ {0, 0, 0}, {120, 119, 238}, {24, 7, 25}, {197, 66, 28}, {29, 18, 11}, {135, 46, 71}, {24, 27, 13}, {241, 230, 128}, {17, 31, 24}, {240, 162, 139}, {11, 4, 30}, {106, 87, 189}, {29, 21, 14}, {12, 140, 118}, {10, 6, 29}, {50, 144, 77}, {22, 0, 24}, {148, 188, 243}, {4, 32, 7}, {231, 146, 14}, {10, 13, 20}, {184, 147, 68}, {13, 28, 3}, {169, 248, 152}, {4, 0, 34}, {62, 83, 48}, {7, 21, 22}, {152, 97, 184}, {8, 3, 12}, {247, 92, 235}, {31, 32, 16} }; REGISTERS(3) static int allocate(int r, int g, int b, int init) { unsigned int n; if (init) preallocpalette(context); n = context->pixels[(init ? 0 : context->size) /*+ context->start */ ]; if (!init && context->size == maxentries) return 0; if ((context->alloccolor(context, init && !context->npreallocated, (int) r, (int) g, (int) b)) == -1) { return 0; } if (context->pixels[context->size - 1 /*+ context->start */ ] != n) { needupdate = 1; } return (1); } static int mksmooth(int nsegments, int setsegments) { int i, y; float r, g, b, rs, gs, bs; int segmentsize1 = segmentsize; for (i = 0; i < setsegments; i++) { if (i == setsegments - 1 && !(context->flags & UNKNOWNENTRIES)) { segmentsize1 = maxentries - context->size - 2; } r = colors[i % nsegments][0]; g = colors[i % nsegments][1]; b = colors[i % nsegments][2]; rs = ((int) colors[(i + 1) % setsegments % nsegments][0] - r) / (unsigned int) segmentsize1; gs = ((int) colors[(i + 1) % setsegments % nsegments][1] - g) / (unsigned int) segmentsize1; bs = ((int) colors[(i + 1) % setsegments % nsegments][2] - b) / (unsigned int) segmentsize1; for (y = 0; y < segmentsize1; y++) { if (!allocate((int) r, (int) g, (int) b, i == 0 && y == 0)) { if (!i) context->size = 2; context->size = i * segmentsize; return 0; } r += rs; g += gs; b += bs; } } if (context->flags & UNKNOWNENTRIES) context->size = i * segmentsize; return 1; } static INLINE void hsv_to_rgb(int h, int s, int v, unsigned char *red, unsigned char *green, unsigned char *blue) { int hue; int f, p, q, t; h += 256; h %= 256; if (s == 0) { *red = v; *green = v; *blue = v; } else { h %= 256; if (h < 0) h += 256; hue = h * 6; f = hue & 255; p = v * (256 - s) / 256; q = v * (256 - (s * f) / 256) >> 8; t = v * (256 * 256 - (s * (256 - f))) >> 16; switch ((int) (hue / 256)) { case 0: *red = v; *green = t; *blue = p; break; case 1: *red = q; *green = v; *blue = p; break; case 2: *red = p; *green = v; *blue = t; break; case 3: *red = p; *green = q; *blue = v; break; case 4: *red = t; *green = p; *blue = v; break; case 5: *red = v; *green = p; *blue = q; break; } } } static void randomize_segments3(int whitemode, int nsegments) { int i = 0; int h, s, v; for (i = 0; i < nsegments; i++) { if (!(i % 3)) { if (i % 6) colors[i][0] = 255, colors[i][1] = 255, colors[i][2] = 255; else colors[i][0] = 0, colors[i][1] = 0, colors[i][2] = 0; } else { s = (int) XaoS_random() % 256; h = (int) XaoS_random() % (128 - 32); v = (int) XaoS_random() % 128; if (((i) % 6 > 3) ^ ((i) % 3 == 1)) /*if(((i)%3==1)) */ h += 42 + 16; else h += 42 + 128 + 16, v += 128 + 64; hsv_to_rgb(h, s, v, colors[i], colors[i] + 1, colors[i] + 2); } } colors[i - 1][0] = colors[0][0]; colors[i - 1][1] = colors[0][1]; colors[i - 1][2] = colors[0][2]; } static void randomize_segments2(int whitemode, int nsegments) { int i = 0; for (i = 0; i < nsegments; i++) { if (i % 3 == 2) colors[i][0] = whitemode * 255, colors[i][1] = whitemode * 255, colors[i][2] = whitemode * 255; else if (i % 3 == 0) colors[i][0] = (!whitemode) * 255, colors[i][1] = (!whitemode) * 255, colors[i][2] = (!whitemode) * 255; else colors[i][0] = (int) XaoS_random() % 256, colors[i][1] = (int) XaoS_random() % 256, colors[i][2] = (int) XaoS_random() % 256; } colors[i - 1][0] = colors[0][0]; colors[i - 1][1] = colors[0][1]; colors[i - 1][2] = colors[0][2]; } static void randomize_segments(int whitemode, int nsegments) { int i = 0; if (whitemode) { colors[0][0] = 255, colors[0][1] = 255, colors[0][2] = 255; for (i = 0; i < nsegments; i += 2) { if (i != 0) { colors[i][0] = (int) XaoS_random() % 256, colors[i][1] = (int) XaoS_random() % 256, colors[i][2] = (int) XaoS_random() % 256; } if (i + 1 < nsegments) colors[i + 1][0] = (int) XaoS_random() % 35, colors[i + 1][1] = (int) XaoS_random() % 35, colors[i + 1][2] = (int) XaoS_random() % 35; } } else { for (i = 0; i < nsegments; i += 2) { colors[i][0] = (int) XaoS_random() % 35, colors[i][1] = (int) XaoS_random() % 35, colors[i][2] = (int) XaoS_random() % 35; if (i + 1 < nsegments) colors[i + 1][0] = (int) XaoS_random() % 256, colors[i + 1][1] = (int) XaoS_random() % 256, colors[i + 1][2] = (int) XaoS_random() % 256; } } colors[i - 1][0] = colors[0][0]; colors[i - 1][1] = colors[0][1]; colors[i - 1][2] = colors[0][2]; } #define MYLONG_MAX 0xffffff #define rrandom(i) ((int)(((int)XaoS_random()/(double)MYLONG_MAX)*(i))) /*Do not use modulo type random since it should bring very different results *for slightly different sizes */ int mkpalette(struct palette *c, int seed, int algorithm) { int i, ncolors = c->size; int whitemode; int i1; context = c; needupdate = 0; if (c->flags & DONOTCHANGE) return 0; XaoS_srandom(seed); seed = (int) XaoS_random(); whitemode = (int) XaoS_random() % 2; if ((c->flags & UNKNOWNENTRIES) || !c->size) { maxentries = context->maxentries - nprecells; segmentsize = (rrandom(maxentries / 2)) & (~3); if (segmentsize < 1) segmentsize = 1; } else { if (maxentries > 8) { int qq = 255; maxentries = context->maxentries - nprecells; segmentsize = rrandom(qq / 3 + 4); segmentsize += rrandom(qq / 3 + 4); segmentsize += rrandom(qq / 3 + 4); segmentsize += rrandom(qq / 3 + 4); /*Make smaller segments with higher probability */ segmentsize = abs(segmentsize / 2 - qq / 3 + 3); if (segmentsize < 8) segmentsize = 8; if (segmentsize > maxentries / 3) segmentsize = maxentries / 3; } } if (c->flags & UNKNOWNENTRIES) i = rrandom(maxentries); else i = (maxentries + segmentsize - 5) / segmentsize; if (i < 0) i = 1; if (i > MAXNSEGMENTS) i1 = MAXNSEGMENTS; else i1 = i; XaoS_srandom(seed); switch (algorithm) { case 2: randomize_segments3(whitemode, i1); break; case 1: randomize_segments2(whitemode, i1); break; case 0: randomize_segments(whitemode, i1); } mksmooth(i1, i); if (!(c->flags & FINISHLATER)) { if (c->allocfinished != NULL) c->allocfinished(c); } else c->flags |= UNFINISHED; if (context->size != ncolors || needupdate) { context->version++; return 1; } return 0; } int mkstereogrampalette(struct palette *c) { int i, ncolors = c->size; context = c; needupdate = 0; for (i = 0; i < 16; i++) allocate(i * 4, i * 4, i * 16, i == 0); if (!(c->flags & FINISHLATER)) { if (c->allocfinished != NULL) c->allocfinished(c); } else c->flags |= UNFINISHED; if (context->size != ncolors || needupdate) { context->version++; return 1; } return 0; } int mkstarfieldpalette(struct palette *c) { int i, ncolors = c->size; context = c; needupdate = 0; for (i = 0; i < 16; i++) if (i % 2) allocate(i * 4, i * 4, i * 16, i == 0); else allocate(i * 16, i * 16, i * 16, i == 0); if (!(c->flags & FINISHLATER)) { if (c->allocfinished != NULL) c->allocfinished(c); } else c->flags |= UNFINISHED; if (context->size != ncolors || needupdate) { context->version++; return 1; } return 0; } int mkblurpalette(struct palette *c) { int i, ncolors = c->size; context = c; needupdate = 0; for (i = 0; i < 63; i++) allocate(i * 2, i * 2, i * 4, i == 0); allocate(i * 2, i * 2, i * 4 - 1, 0); if (!(c->flags & FINISHLATER)) { if (c->allocfinished != NULL) c->allocfinished(c); } else c->flags |= UNFINISHED; if (context->size != ncolors || needupdate) { context->version++; return 1; } return 0; } int mkgraypalette(struct palette *c) { int i, ncolors = c->size; context = c; needupdate = 0; for (i = 0; i < 64; i++) allocate(i * 4, i * 4, i * 4, i == 0); for (i = 0; i < 16; i++) allocate(255, 255 - i * 16, 255 - i * 16, 0); for (i = 0; i < 16; i++) allocate(255 - i * 16, 0, 0, 0); if (!(c->flags & FINISHLATER)) { if (c->allocfinished != NULL) c->allocfinished(c); } else c->flags |= UNFINISHED; if (context->size != ncolors || needupdate) { context->version++; return 1; } return 0; } int mkdefaultpalette(struct palette *c) { int i, ncolors = c->size; context = c; needupdate = 0; segmentsize = 8; if (c->flags & DONOTCHANGE) return 0; memcpy(colors, colors1, sizeof(colors1)); maxentries = context->maxentries - nprecells; if (c->flags & UNKNOWNENTRIES) i = 128 / 8; else i = (maxentries + 3) / 8; if (i < 0) i = 1; mksmooth(255 / 8, i); if (!(c->flags & FINISHLATER)) { if (c->allocfinished != NULL) c->allocfinished(c); } else c->flags |= UNFINISHED; if (context->size != ncolors || needupdate) { context->version++; return 1; } return 0; } int shiftpalette(struct palette *c, int shift) { if (!c->size) return 0; while (shift < 0) shift += c->size - 1; shift = shift % (c->size - 1); if (!shift) return 0; if (c->cyclecolors != NULL) { if (c->flags & UNFINISHED) { cycle_entries(c, shift); } else { c->cyclecolors(c, shift); } return 0; } if (c->type & (TRUECOLOR | TRUECOLOR24 | TRUECOLOR16)) { int i; int i3; int *co; if (shift > 0) shift %= c->size - 1; else shift = -((-shift) % (c->size - 1)); if (!shift) return 0; co = (int *) malloc(c->size * sizeof(*co)); memcpy(co, c->pixels, sizeof(*co) * c->size); i3 = (c->size - 1 + shift) % (c->size - 1) + 1; for (i = 1; i < c->size; i++) { c->pixels[i] = co[i3]; i3++; if (i3 >= c->size) i3 = 1; } c->version++; free(co); } return 1; } static int allocrgb(struct palette *c, int r1, int g1, int b1) { int r, g, b; int f = 1; for (g = 0; g < g1; g++) for (b = 0; b < b1; b++) { for (r = 0; r < r1; r++) { if (!allocate (r * 255 / (r1 - 1), g * 255 / (g1 - 1), b * 255 / (b1 - 1), f)) return 0; f = 0; } } return 1; } int mkrgb(struct palette *c) { int ncolors = c->size; int red = 8, green = 8, blue = 4; context = c; needupdate = 0; if (c->flags & UNKNOWNENTRIES) { while (blue > 0) { if (allocrgb(c, red, green, blue)) break; red--; if (allocrgb(c, red, green, blue)) break; green--; if (allocrgb(c, red, green, blue)) break; red--; if (allocrgb(c, red, green, blue)) break; green--; if (allocrgb(c, red, green, blue)) break; blue--; } } else { number_t n = pow((c->maxentries - nprecells) / (0.5 * 0.2 * 0.3), 1.0 / 3); green = (int) (n * 0.5); blue = (int) (n * 0.2); red = (int) (n * 0.3); while ((blue + 1) * red * green < (c->maxentries - nprecells)) blue++; while ((red + 1) * blue * green < (c->maxentries - nprecells)) red++; while ((green + 1) * blue * red < (c->maxentries - nprecells)) green++; allocrgb(c, red, green, blue); } if (!(c->flags & FINISHLATER)) { if (c->allocfinished != NULL) c->allocfinished(c); } else c->flags |= UNFINISHED; if (context->size != ncolors || needupdate) { context->version++; } return red * 256 * 256 + green * 256 + blue; }