📄 gdkcc.c
字号:
*nallocated = 0; /* First allocate all pixels */ for (i = 0; i < ncolors; i++) { /* used[i] is only -1 if the pixel at that location hasn't * been allocated yet. This is a sanity check required for proper * color allocation by the progressive image loader. * When colors[i] == 0 it indicates the slot is available for * allocation. */ if (used[i] != FALSE) { if (colors[i] == 0) { defs[i].red = reds[i]; defs[i].green = greens[i]; defs[i].blue = blues[i]; colors[i] = gdk_color_context_get_pixel (cc, reds[i], greens[i], blues[i], &bad_alloc); /* successfully allocated, store it */ if (!bad_alloc) { defs[i].pixel = colors[i]; allocated[ncols++] = colors[i]; } else failed[nopen++] = i; }#ifdef DEBUG else GDK_NOTE (COLOR_CONTEXT, g_message ("gdk_color_context_get_pixels_incremental: " "pixel at slot %i already allocated, skipping\n", i));#endif } } *nallocated = ncols; if ((ncols == ncolors) || (nopen == 0)) { GDK_NOTE (COLOR_CONTEXT, g_message ("gdk_color_context_get_pixels_incremental: got all %i colors " "(%i colors allocated so far)\n", ncolors, cc->num_allocated)); return; } cmapsize = MIN (cc->num_colors, MAX_IMAGE_COLORS); if (cmapsize < 0) { g_warning ("gdk_color_context_get_pixels_incremental: oops! " "No colors available images will look *really* ugly."); return; } #ifdef G_ENABLE_DEBUG exact_col = ncols;#endif /* initialize pixels */ for (i = 0; i < cmapsize; i++) { cmap[i].pixel = i; cmap[i].red = cmap[i].green = cmap[i].blue = 0; } /* read */ my_x_query_colors (cc->colormap, cmap, cmapsize); /* now match any unallocated colors */ counter = nopen; nopen = 0; idx = 0; do { gint d, j, mdist, close, ri, gi, bi; gint rd, gd, bd; i = failed[idx]; mdist = 0x1000000; close = -1; /* store */ ri = reds[i]; gi = greens[i]; bi = blues[i]; for (j = 0; (j < cmapsize) && (mdist != 0); j++) { /* Don't replace these by shifts; the sign may get clobbered */ rd = (ri - cmap[j].red) / 256; gd = (gi - cmap[j].green) / 256; bd = (bi - cmap[j].blue) / 256; d = rd * rd + gd * gd + bd * bd; if (d < mdist) { close = j; mdist = d; } } if (close != -1) { rd = cmap[close].red; gd = cmap[close].green; bd = cmap[close].blue; /* allocate */ colors[i] = gdk_color_context_get_pixel (cc, rd, gd, bd, &bad_alloc); /* store */ if (!bad_alloc) { defs[i] = cmap[close]; defs[i].pixel = colors[i]; allocated[ncols++] = colors[i];#ifdef G_ENABLE_DEBUG close_col++;#endif } else failed[nopen++] = i; } else failed[nopen++] = i; /* deal with in next stage if allocation failed */ } while (++idx < counter); *nallocated = ncols; if ((ncols == ncolors) || (nopen == 0)) { GDK_NOTE (COLOR_CONTEXT, g_message ("gdk_color_context_get_pixels_incremental: " "got %i colors, %i exact and %i close " "(%i colors allocated so far)\n", ncolors, exact_col, close_col, cc->num_allocated)); return; } /* map remaining unallocated pixels into colors we did get */ idx = 0; do { gint d, mdist, close, ri, gi, bi; gint j, rd, gd, bd; i = failed[idx]; mdist = 0x1000000; close = -1; ri = reds[i]; gi = greens[i]; bi = blues[i]; /* search allocated colors */ for (j = 0; (j < ncols) && (mdist != 0); j++) { k = allocated[j]; /* downscale */ /* Don't replace these by shifts; the sign may get clobbered */ rd = (ri - defs[k].red) / 256; gd = (gi - defs[k].green) / 256; bd = (bi - defs[k].blue) / 256; d = rd * rd + gd * gd + bd * bd; if (d < mdist) { close = k; mdist = d; } } if (close < 0) { /* too bad, map to black */ defs[i].pixel = cc->black_pixel; defs[i].red = defs[i].green = defs[i].blue = 0;#ifdef G_ENABLE_DEBUG black_col++;#endif } else { defs[i] = defs[close];#ifdef G_ENABLE_DEBUG subst_col++;#endif } colors[i] = defs[i].pixel; } while (++idx < nopen); GDK_NOTE (COLOR_CONTEXT, g_message ("gdk_color_context_get_pixels_incremental: " "got %i colors, %i exact, %i close, %i substituted, %i to black " "(%i colors allocated so far)\n", ncolors, exact_col, close_col, subst_col, black_col, cc->num_allocated));}gintgdk_color_context_query_color (GdkColorContext *cc, GdkColor *color){ return gdk_color_context_query_colors (cc, color, 1);}gintgdk_color_context_query_colors (GdkColorContext *cc, GdkColor *colors, gint num_colors){ gint i; GdkColor *tc; g_assert (cc != NULL); g_assert (colors != NULL); switch (cc->mode) { case GDK_CC_MODE_BW: for (i = 0, tc = colors; i < num_colors; i++, tc++) { if (tc->pixel == cc->white_pixel) tc->red = tc->green = tc->blue = 65535; else tc->red = tc->green = tc->blue = 0; } break; case GDK_CC_MODE_TRUE: if (cc->clut == NULL) for (i = 0, tc = colors; i < num_colors; i++, tc++) { tc->red = ((tc->pixel & cc->masks.red) >> cc->shifts.red) << (16 - cc->bits.red); tc->green = ((tc->pixel & cc->masks.green) >> cc->shifts.green) << (16 - cc->bits.green); tc->blue = ((tc->pixel & cc->masks.blue) >> cc->shifts.blue) << (16 - cc->bits.blue); } else { my_x_query_colors (cc->colormap, colors, num_colors); return 1; } break; case GDK_CC_MODE_STD_CMAP: default: if (cc->cmap == NULL) { my_x_query_colors (cc->colormap, colors, num_colors); return 1; } else { gint first, last, half; gulong half_pixel; for (i = 0, tc = colors; i < num_colors; i++) { first = 0; last = cc->num_colors - 1; while (first <= last) { half = (first + last) / 2; half_pixel = cc->cmap[half].pixel; if (tc->pixel == half_pixel) { tc->red = cc->cmap[half].red; tc->green = cc->cmap[half].green; tc->blue = cc->cmap[half].blue; first = last + 1; /* false break */ } else { if (tc->pixel > half_pixel) first = half + 1; else last = half - 1; } } } return 1; } break; } return 1;}gintgdk_color_context_add_palette (GdkColorContext *cc, GdkColor *palette, gint num_palette){ gint i, j, erg; gushort r, g, b; gulong pixel[1]; g_assert (cc != NULL); /* initialize this palette (will also erase previous palette as well) */ init_palette (cc); /* restore previous mode if we aren't adding a new palette */ if (num_palette == 0) return 0; /* copy incoming palette */ cc->palette = g_new0(GdkColor, num_palette); j = 0; for (i = 0; i < num_palette; i++) { erg = 0; pixel[0] = 0; /* try to allocate this color */ r = palette[i].red; g = palette[i].green; b = palette[i].blue; gdk_color_context_get_pixels (cc, &r, &g, &b, 1, pixel, &erg); /* only store if we succeed */ if (erg) { /* store in palette */ cc->palette[j].red = r; cc->palette[j].green = g; cc->palette[j].blue = b; cc->palette[j].pixel = pixel[0]; /* move to next slot */ j++; } } /* resize to fit */ if (j != num_palette) cc->palette = g_realloc (cc->palette, j * sizeof (GdkColor)); /* clear the hash table, we don't use it when dithering */ if (cc->color_hash) { g_hash_table_foreach (cc->color_hash, free_hash_entry, NULL); g_hash_table_destroy (cc->color_hash); cc->color_hash = NULL; } /* store real palette size */ cc->num_palette = j; /* switch to palette mode */ cc->mode = GDK_CC_MODE_PALETTE; /* sort palette */ qsort (cc->palette, cc->num_palette, sizeof (GdkColor), pixel_sort); cc->fast_dither = NULL; return j;}voidgdk_color_context_init_dither (GdkColorContext *cc){ gint rr, gg, bb, err, erg, erb; gint success = FALSE; g_assert (cc != NULL); /* now we can initialize the fast dither matrix */ if (cc->fast_dither == NULL) cc->fast_dither = g_new (GdkColorContextDither, 1); /* Fill it. We ignore unsuccessful allocations, they are just mapped * to black instead */ for (rr = 0; rr < 32; rr++) for (gg = 0; gg < 32; gg++) for (bb = 0; bb < 32; bb++) { err = (rr << 3) | (rr >> 2); erg = (gg << 3) | (gg >> 2); erb = (bb << 3) | (bb >> 2); cc->fast_dither->fast_rgb[rr][gg][bb] = gdk_color_context_get_index_from_palette (cc, &err, &erg, &erb, &success); cc->fast_dither->fast_err[rr][gg][bb] = err; cc->fast_dither->fast_erg[rr][gg][bb] = erg; cc->fast_dither->fast_erb[rr][gg][bb] = erb; }}voidgdk_color_context_free_dither (GdkColorContext *cc){ g_assert (cc != NULL); if (cc->fast_dither) g_free (cc->fast_dither); cc->fast_dither = NULL;}gulonggdk_color_context_get_pixel_from_palette (GdkColorContext *cc, gushort *red, gushort *green, gushort *blue, gint *failed){ gulong pixel = 0; gint dif, dr, dg, db, j = -1; gint mindif = 0x7fffffff; gint err = 0, erg = 0, erb = 0; gint i; g_assert (cc != NULL); g_assert (red != NULL); g_assert (green != NULL); g_assert (blue != NULL); g_assert (failed != NULL); *failed = FALSE; for (i = 0; i < cc->num_palette; i++) { dr = *red - cc->palette[i].red; dg = *green - cc->palette[i].green; db = *blue - cc->palette[i].blue; dif = dr * dr + dg * dg + db * db; if (dif < mindif) { mindif = dif; j = i; pixel = cc->palette[i].pixel; err = dr; erg = dg; erb = db; if (mindif == 0) break; } } /* we failed to map onto a color */ if (j == -1) *failed = TRUE; else { *red = ABS (err); *green = ABS (erg); *blue = ABS (erb); } return pixel;}guchargdk_color_context_get_index_from_palette (GdkColorContext *cc, gint *red, gint *green, gint *blue, gint *failed){ gint dif, dr, dg, db, j = -1; gint mindif = 0x7fffffff; gint err = 0, erg = 0, erb = 0; gint i; g_assert (cc != NULL); g_assert (red != NULL); g_assert (green != NULL); g_assert (blue != NULL); g_assert (failed != NULL); *failed = FALSE; for (i = 0; i < cc->num_palette; i++) { dr = *red - cc->palette[i].red; dg = *green - cc->palette[i].green; db = *blue - cc->palette[i].blue; dif = dr * dr + dg * dg + db * db; if (dif < mindif) { mindif = dif; j = i; err = dr; erg = dg; erb = db; if (mindif == 0) break; } } /* we failed to map onto a color */ if (j == -1) { *failed = TRUE; j = 0; } else { /* return error fractions */ *red = err; *green = erg; *blue = erb; } return j;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -