📄 dl1quant.cpp
字号:
}
LOCAL void closest_color(int index, int level)
{
int i;
if (rgb_table[level][index].children) {
for (i = 7; i >= 0; i--) {
if (rgb_table[level][index].children & (1 << i)) {
closest_color((index << 3) + i, level + 1);
}
}
}
if (rgb_table[level][index].pixel_count) {
slong dist, r_dist, g_dist, b_dist;
uchar pal_num = rgb_table[level][index].palette_index;
/* Determine if this color is "closest". */
r_dist = palette[0][pal_num] - c_info.red;
g_dist = palette[1][pal_num] - c_info.green;
b_dist = palette[2][pal_num] - c_info.blue;
dist = squares[r_dist] + squares[g_dist] + squares[b_dist];
if (dist < (slong)c_info.distance) {
c_info.distance = dist;
c_info.palette_index = pal_num;
}
}
}
/* returns 1 on success, 0 on failure */
LOCAL int quantize_image(uchar *in, uchar *out, int width, int height, int dither)
{
if (!dither) {
ulong i=0;
ulong pixels = width * height;
ushort level=0;
ushort index=0;
uchar tmp_r=0;
uchar tmp_g=0;
uchar tmp_b=0;
uchar cube=0;
uchar *lookup=NULL;
lookup = (BYTE*)malloc(sizeof(char) * 32768);
if (lookup == NULL)
return 0;
for (i = 0; i < 32768; i++)
if (rgb_table[5][i].pixel_count) {
tmp_r = (BYTE)((i & 0x4000) >> 7 | (i & 0x0800) >> 5 |
(i & 0x0100) >> 3 | (i & 0x0020) >> 1 |
(i & 0x0004) << 1);
tmp_g = (BYTE)((i & 0x2000) >> 6 | (i & 0x0400) >> 4 |
(i & 0x0080) >> 2 | (i & 0x0010) >> 0 |
(i & 0x0002) << 2);
tmp_b = (BYTE)((i & 0x1000) >> 5 | (i & 0x0200) >> 3 |
(i & 0x0040) >> 1 | (i & 0x0008) << 1 |
(i & 0x0001) << 3);
#ifdef QUAL2
lookup[i] = bestcolor(tmp_r, tmp_g, tmp_b);
#else
c_info.red = tmp_r + 4;
c_info.green = tmp_g + 4;
c_info.blue = tmp_b + 4;
level = 0;
index = 0;
for (;;) {
cube = (tmp_r&128) >> 5 | (tmp_g&128) >> 6 | (tmp_b&128) >> 7;
if ((rgb_table[level][index].children & (1 << cube)) == 0) {
c_info.distance = (ULONG)~0L;
closest_color(index, level);
lookup[i] = c_info.palette_index;
break;
}
level++;
index = (index << 3) + cube;
tmp_r <<= 1;
tmp_g <<= 1;
tmp_b <<= 1;
}
#endif
}
for (i = 0; i < pixels; i++) {
#ifdef FAST
out[i] = lookup[dl_image[i]];
#else
out[i] = lookup[r_offset[in[0]] + g_offset[in[1]] + b_offset[in[2]]];
in += 3;
#endif
}
free(lookup);
} else { // dither
#if defined(DITHER2) || defined(DITHER4)
slong i=0;
slong j=0;
slong r_pix=0;
slong g_pix=0;
slong b_pix=0;
slong offset=0;
slong dir=0;
slong two_val=0;
slong odd_scanline = 0;
slong err_len = (width + 2) * 3;
uchar *range_tbl = NULL;
uchar *range = NULL;
sshort *lookup = NULL;
sshort *erowerr = NULL;
sshort *orowerr = NULL;
sshort *thisrowerr = NULL;
sshort *nextrowerr = NULL;
schar *dith_max_tbl = NULL;
schar *dith_max = NULL;
lookup = (sshort *)malloc(sizeof(short) * 32768);
erowerr = (sshort *)malloc(sizeof(short) * err_len);
orowerr = (sshort *)malloc(sizeof(short) * err_len);
range_tbl = (BYTE*)malloc(3 * 256);
range = range_tbl + 256;
dith_max_tbl= (schar *)malloc(512);
dith_max = dith_max_tbl + 256;
if (range_tbl == NULL || lookup == NULL ||
erowerr == NULL || orowerr == NULL || dith_max_tbl == NULL) {
if (range_tbl != NULL) {
free(range_tbl);
range_tbl=NULL;
}
if (lookup != NULL) {
free(lookup);
lookup=NULL;
}
if (erowerr != NULL) {
free(erowerr);
erowerr=NULL;
}
if (orowerr != NULL) {
free(orowerr);
orowerr=NULL;
}
if (dith_max_tbl != NULL) {
free(dith_max_tbl);
dith_max_tbl=NULL;
}
return 0;
}
for (i = 0; i < err_len; i++)
erowerr[i] = 0;
for (i = 0; i < 32768; i++)
lookup[i] = -1;
for (i = 0; i < 256; i++) {
range_tbl[i] = 0;
range_tbl[i + 256] = (uchar) i;
range_tbl[i + 512] = 255;
}
for (i = 0; i < 256; i++) {
dith_max_tbl[i] = -DITHER_MAX;
dith_max_tbl[i + 256] = DITHER_MAX;
}
for (i = -DITHER_MAX; i <= DITHER_MAX; i++)
dith_max_tbl[i + 256] = (schar)i;
for (i = 0 ; i < height; i++) {
if (odd_scanline) {
dir = -1;
in += (width - 1) * 3;
out += (width - 1);
thisrowerr = orowerr + 3;
nextrowerr = erowerr + width * 3;
} else {
dir = 1;
thisrowerr = erowerr + 3;
nextrowerr = orowerr + width * 3;
}
nextrowerr[0] = nextrowerr[1] = nextrowerr[2] = 0;
for (j = 0; j < width; j++) {
#ifdef DITHER2
r_pix = range[(thisrowerr[0] >> 1) + in[0]];
g_pix = range[(thisrowerr[1] >> 1) + in[1]];
b_pix = range[(thisrowerr[2] >> 1) + in[2]];
#else
r_pix = range[((thisrowerr[0] + 8) >> 4) + in[0]];
g_pix = range[((thisrowerr[1] + 8) >> 4) + in[1]];
b_pix = range[((thisrowerr[2] + 8) >> 4) + in[2]];
#endif
offset = (r_pix&248) << 7 | (g_pix&248) << 2 | b_pix >> 3;
if (lookup[offset] < 0)
lookup[offset] = bestcolor(r_pix, g_pix, b_pix);
*out = (BYTE)lookup[offset];
r_pix = dith_max[r_pix - palette[0][lookup[offset]]];
g_pix = dith_max[g_pix - palette[1][lookup[offset]]];
b_pix = dith_max[b_pix - palette[2][lookup[offset]]];
#ifdef DITHER2
nextrowerr[0 ] = (short)r_pix;
thisrowerr[0+3] += (short)r_pix;
nextrowerr[1 ] = (short)g_pix;
thisrowerr[1+3] += (short)g_pix;
nextrowerr[2 ] = (short)b_pix;
thisrowerr[2+3] += (short)b_pix;
#else
two_val = r_pix * 2;
nextrowerr[0-3] = r_pix;
r_pix += two_val;
nextrowerr[0+3] += r_pix;
r_pix += two_val;
nextrowerr[0 ] += r_pix;
r_pix += two_val;
thisrowerr[0+3] += r_pix;
two_val = g_pix * 2;
nextrowerr[1-3] = g_pix;
g_pix += two_val;
nextrowerr[1+3] += g_pix;
g_pix += two_val;
nextrowerr[1 ] += g_pix;
g_pix += two_val;
thisrowerr[1+3] += g_pix;
two_val = b_pix * 2;
nextrowerr[2-3] = b_pix;
b_pix += two_val;
nextrowerr[2+3] += b_pix;
b_pix += two_val;
nextrowerr[2 ] += b_pix;
b_pix += two_val;
thisrowerr[2+3] += b_pix;
#endif
thisrowerr += 3;
nextrowerr -= 3;
in += dir * 3;
out += dir;
}
if ((i % 2) == 1) {
in += (width + 1) * 3;
out += (width + 1);
}
odd_scanline = !odd_scanline;
}
free(range_tbl);
free(lookup);
free(erowerr);
free(orowerr);
free(dith_max_tbl);
#else
slong i =0;
slong j=0;
slong r_pix=0;
slong g_pix=0;
slong b_pix=0;
slong r_err=0;
slong g_err=0;
slong b_err=0;
slong offset=0;
uchar *range_tbl = (BYTE*)malloc(3 * 256), *range = range_tbl + 256;
sshort *lookup = (sshort *)malloc(sizeof(short) * 32768);
if (range_tbl == NULL || lookup == NULL) {
if (range_tbl != NULL)
free(range_tbl);
if (lookup != NULL)
free(lookup);
return 0;
}
for (i = 0; i < 32768; i++)
lookup[i] = -1;
for (i = 0; i < 256; i++) {
range_tbl[i] = 0;
range_tbl[i + 256] = (uchar) i;
range_tbl[i + 512] = 255;
}
for (i = 0; i < height; i++) {
r_err = g_err = b_err = 0;
for (j = width - 1; j >= 0; j--) {
r_pix = range[(r_err >> 1) + in[0]];
g_pix = range[(g_err >> 1) + in[1]];
b_pix = range[(b_err >> 1) + in[2]];
offset = (r_pix&248) << 7 | (g_pix&248) << 2 | b_pix >> 3;
if (lookup[offset] < 0)
lookup[offset] = bestcolor(r_pix, g_pix, b_pix);
*out++ = (BYTE)lookup[offset];
r_err = r_pix - palette[0][lookup[offset]];
g_err = g_pix - palette[1][lookup[offset]];
b_err = b_pix - palette[2][lookup[offset]];
in += 3;
}
}
free(range_tbl);
free(lookup);
#endif
}
return 1;
}
LOCAL int bestcolor(int r, int g, int b)
{
ulong i=0;
ulong bestcolor=0;
ulong curdist=0;
ulong mindist=0;
slong rdist=0;
slong gdist=0;
slong bdist=0;
r = (r & 248) + 4;
g = (g & 248) + 4;
b = (b & 248) + 4;
mindist = 200000;
for (i = 0; i < (ulong)tot_colors; i++) {
rdist = palette[0][i] - r;
gdist = palette[1][i] - g;
bdist = palette[2][i] - b;
curdist = squares[rdist] + squares[gdist] + squares[bdist];
if (curdist < mindist) {
mindist = curdist;
bestcolor = i;
}
}
return bestcolor;
}
#ifdef __cplusplus
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -