*/
/* For more information on GdkRgb, see http://www.levien.com/gdkrgb/
-
+
Raph Levien <raph@acm.org>
-*/
+ */
#include <math.h>
#include <stdio.h>
{
GdkVisual *visual;
GdkColormap *cmap;
-
+
gulong *color_pixels;
gulong *gray_pixels;
gulong *reserved_pixels;
-
+
guint nred_shades;
guint ngreen_shades;
guint nblue_shades;
guint ngray_shades;
guint nreserved;
-
+
guint bpp;
gint cmap_alloced;
gdouble gamma;
-
+
/* Generally, the stage buffer is used to convert 32bit RGB, gray,
and indexed images into 24 bit packed RGB. */
guchar *stage_buf;
-
+
GdkRgbCmap *gray_cmap;
-
+
gboolean dith_default;
-
+
/* Convert functions */
GdkRgbConvFunc conv;
GdkRgbConvFunc conv_d;
-
+
GdkRgbConvFunc conv_32;
GdkRgbConvFunc conv_32_d;
-
+
GdkRgbConvFunc conv_gray;
GdkRgbConvFunc conv_gray_d;
-
+
GdkRgbConvFunc conv_indexed;
GdkRgbConvFunc conv_indexed_d;
};
gulong free_pixels[256];
gint n_free;
gint i;
-
+
#ifdef VERBOSE
- g_message ("%s", msg);
+ g_print ("%s", msg);
#endif
n_free = 0;
for (i = 0; i < 256; i++)
{
guchar rt[16], gt[16], bt[16];
gint i;
-
+
colorcube = g_new (guchar, 4096);
for (i = 0; i < 16; i++)
{
gt[i] = nb * ((i * 17 * (ng - 1) + 128) >> 8);
bt[i] = ((i * 17 * (nb - 1) + 128) >> 8);
}
-
+
for (i = 0; i < 4096; i++)
{
colorcube[i] = pixels[rt[i >> 8] + gt[(i >> 4) & 0x0f] + bt[i & 0x0f]];
#ifdef VERBOSE
- g_message ("%03x %02x %x %x %x", i, colorcube[i], rt[i >> 8], gt[(i >> 4) & 0x0f], bt[i & 0x0f]);
+ g_print ("%03x %02x %x %x %x\n", i, colorcube[i], rt[i >> 8], gt[(i >> 4) & 0x0f], bt[i & 0x0f]);
#endif
}
}
{
gint r, g, b;
gint i;
-
+
colorcube_d = g_new (guchar, 512);
for (i = 0; i < 512; i++)
{
gint colors_needed;
gint idx;
gint best[256];
-
+
if (nr * ng * nb < gdk_rgb_min_colors)
return FALSE;
-
+
if (image_info->cmap_alloced)
cmap = image_info->cmap;
else
cmap = gdk_colormap_get_system ();
-
+
colors_needed = nr * ng * nb;
for (i = 0; i < 256; i++)
{
best[i] = 192;
pixels[i] = 256;
}
-
+
#ifndef GAMMA
if (!gdk_rgb_install_cmap)
- /* find color cube colors that are already present */
- for (i = 0; i < MIN (256, cmap->size); i++)
- {
- r = cmap->colors[i].red >> 8;
- g = cmap->colors[i].green >> 8;
- b = cmap->colors[i].blue >> 8;
- ri = (r * (nr - 1) + 128) >> 8;
- gi = (g * (ng - 1) + 128) >> 8;
- bi = (b * (nb - 1) + 128) >> 8;
- r0 = ri * 255 / (nr - 1);
- g0 = gi * 255 / (ng - 1);
- b0 = bi * 255 / (nb - 1);
- idx = ((ri * nr) + gi) * nb + bi;
- d2 = (r - r0) * (r - r0) + (g - g0) * (g - g0) + (b - b0) * (b - b0);
- if (d2 < best[idx]) {
- if (pixels[idx] < 256)
- gdk_colors_free (cmap, pixels + idx, 1, 0);
- else
- colors_needed--;
- color = cmap->colors[i];
- if (!gdk_color_alloc (cmap, &color))
- return gdk_rgb_cmap_fail ("error allocating system color",
- cmap, pixels);
- pixels[idx] = color.pixel; /* which is almost certainly i */
- best[idx] = d2;
- }
+ /* find color cube colors that are already present */
+ for (i = 0; i < MIN (256, cmap->size); i++)
+ {
+ r = cmap->colors[i].red >> 8;
+ g = cmap->colors[i].green >> 8;
+ b = cmap->colors[i].blue >> 8;
+ ri = (r * (nr - 1) + 128) >> 8;
+ gi = (g * (ng - 1) + 128) >> 8;
+ bi = (b * (nb - 1) + 128) >> 8;
+ r0 = ri * 255 / (nr - 1);
+ g0 = gi * 255 / (ng - 1);
+ b0 = bi * 255 / (nb - 1);
+ idx = ((ri * nr) + gi) * nb + bi;
+ d2 = (r - r0) * (r - r0) + (g - g0) * (g - g0) + (b - b0) * (b - b0);
+ if (d2 < best[idx]) {
+ if (pixels[idx] < 256)
+ gdk_colors_free (cmap, pixels + idx, 1, 0);
+ else
+ colors_needed--;
+ color = cmap->colors[i];
+ if (!gdk_color_alloc (cmap, &color))
+ return gdk_rgb_cmap_fail ("error allocating system color\n",
+ cmap, pixels);
+ pixels[idx] = color.pixel; /* which is almost certainly i */
+ best[idx] = d2;
}
+ }
#endif
-
+
if (colors_needed)
{
if (!gdk_colors_alloc (cmap, 0, NULL, 0, junk, colors_needed))
char tmp_str[80];
sprintf (tmp_str,
- "%d %d %d colormap failed (in gdk_colors_alloc)",
+ "%d %d %d colormap failed (in gdk_colors_alloc)\n",
nr, ng, nb);
return gdk_rgb_cmap_fail (tmp_str, cmap, pixels);
}
-
+
gdk_colors_free (cmap, junk, colors_needed, 0);
}
-
+
for (r = 0, i = 0; r < nr; r++)
for (g = 0; g < ng; g++)
for (b = 0; b < nb; b++, i++)
color.red = r * 65535 / (nr - 1);
color.green = g * 65535 / (ng - 1);
color.blue = b * 65535 / (nb - 1);
-
+
#ifdef GAMMA
color.red = 65535 * pow (color.red / 65535.0, 0.5);
color.green = 65535 * pow (color.green / 65535.0, 0.5);
color.blue = 65535 * pow (color.blue / 65535.0, 0.5);
#endif
-
+
+ /* This should be a raw XAllocColor call */
if (!gdk_color_alloc (cmap, &color))
{
char tmp_str[80];
-
- sprintf (tmp_str, "%d %d %d colormap failed",
+
+ sprintf (tmp_str, "%d %d %d colormap failed\n",
nr, ng, nb);
return gdk_rgb_cmap_fail (tmp_str,
cmap, pixels);
pixels[i] = color.pixel;
}
#ifdef VERBOSE
- g_message ("%d: %lx", i, pixels[i]);
+ g_print ("%d: %lx\n", i, pixels[i]);
#endif
}
-
+
image_info->nred_shades = nr;
image_info->ngreen_shades = ng;
image_info->nblue_shades = nb;
gdk_rgb_do_colormaps (void)
{
const gint sizes[][3] = {
- /* { 6, 7, 6 }, */
+ /* { 6, 7, 6 }, */
{ 6, 6, 6 },
{ 6, 6, 5 },
{ 6, 6, 4 },
};
const gint n_sizes = sizeof(sizes) / (3 * sizeof(gint));
gint i;
-
+
for (i = 0; i < n_sizes; i++)
if (gdk_rgb_try_colormap (sizes[i][0], sizes[i][1], sizes[i][2]))
return TRUE;
return FALSE;
}
+/* Make a 2 x 2 x 2 colorcube */
+static void
+gdk_rgb_colorcube_222 (void)
+{
+ int i;
+ GdkColor color;
+ GdkColormap *cmap;
+
+ if (image_info->cmap_alloced)
+ cmap = image_info->cmap;
+ else
+ cmap = gdk_colormap_get_system ();
+
+ colorcube_d = g_new (guchar, 512);
+
+ for (i = 0; i < 8; i++)
+ {
+ color.red = ((i & 4) >> 2) * 65535;
+ color.green = ((i & 2) >> 1) * 65535;
+ color.blue = (i & 1) * 65535;
+ gdk_color_alloc (cmap, &color);
+ colorcube_d[((i & 4) << 4) | ((i & 2) << 2) | (i & 1)] = color.pixel;
+ }
+}
+
void
gdk_rgb_set_verbose (gboolean verbose)
{
}
/* Return a "score" based on the following criteria (in hex):
-
+
x000 is the quality - 1 is 1bpp, 2 is 4bpp,
- 4 is 8bpp,
- 7 is 15bpp truecolor, 8 is 16bpp truecolor,
- 9 is 24bpp truecolor.
+ 4 is 8bpp,
+ 7 is 15bpp truecolor, 8 is 16bpp truecolor,
+ 9 is 24bpp truecolor.
0x00 is the speed - 1 is the normal case,
- 2 means faster than normal
+ 2 means faster than normal
00x0 gets a point for being the system visual
000x gets a point for being pseudocolor
-
+
A caveat: in the 8bpp modes, being the system visual seems to be
quite important. Thus, all of the 8bpp modes should be ranked at
the same speed.
"true color",
"direct color",
};
-
-
+
+
quality = 0;
speed = 1;
sys = 0;
else if (visual->depth == 8)
quality = 4;
}
- else if (visual->type == GDK_VISUAL_PSEUDO_COLOR)
+ else if (visual->type == GDK_VISUAL_PSEUDO_COLOR ||
+ visual->type == GDK_VISUAL_STATIC_COLOR)
{
if (visual->depth == 8)
quality = 4;
+ else if (visual->depth == 4)
+ quality = 2;
+ else if (visual->depth == 1)
+ quality = 1;
}
else if (visual->type == GDK_VISUAL_STATIC_GRAY
#ifdef ENABLE_GRAYSCALE
else if (visual->depth == 1)
quality = 1;
}
-
+
if (quality == 0)
return 0;
-
+
sys = (visual == gdk_visual_get_system ());
-
+
pseudo = (visual->type == GDK_VISUAL_PSEUDO_COLOR);
-
+
if (gdk_rgb_verbose)
- g_message ("Visual 0x%x, type = %s, depth = %d, %x:%x:%x%s; score=%x",
- (gint)(((GdkVisualPrivate *)visual)->xvisual->visualid),
- visual_names[visual->type],
- visual->depth,
- visual->red_mask,
- visual->green_mask,
- visual->blue_mask,
- sys ? " (system)" : "",
- (quality << 12) | (speed << 8) | (sys << 4) | pseudo);
-
+ g_print ("Visual 0x%x, type = %s, depth = %d, %x:%x:%x%s; score=%x\n",
+ (gint)(((GdkVisualPrivate *)visual)->xvisual->visualid),
+ visual_names[visual->type],
+ visual->depth,
+ visual->red_mask,
+ visual->green_mask,
+ visual->blue_mask,
+ sys ? " (system)" : "",
+ (quality << 12) | (speed << 8) | (sys << 4) | pseudo);
+
return (quality << 12) | (speed << 8) | (sys << 4) | pseudo;
}
GList *visuals;
guint32 score, best_score;
GdkVisual *visual, *best_visual;
-
+
visuals = gdk_list_visuals ();
-
+
best_visual = visuals->data;
best_score = gdk_rgb_score_visual (best_visual);
visuals = visuals->next;
}
visuals = visuals->next;
}
-
+
image_info->visual = best_visual;
}
gint status;
gulong pixels[256];
gint r, g, b, gray;
-
+
for (i = 0; i < 256; i++)
{
color.pixel = i;
status = gdk_color_alloc (cmap, &color);
pixels[i] = color.pixel;
#ifdef VERBOSE
- g_message ("allocating pixel %d, %x %x %x, result %d",
- color.pixel, color.red, color.green, color.blue, status);
+ g_print ("allocating pixel %d, %x %x %x, result %d\n",
+ color.pixel, color.red, color.green, color.blue, status);
#endif
}
-
+
/* Now, we make fake colorcubes - we ultimately just use the pseudocolor
methods. */
-
+
colorcube = g_new (guchar, 4096);
-
+
for (i = 0; i < 4096; i++)
{
r = (i >> 4) & 0xf0;
{
gint i;
gint byte_order[1] = { 1 };
-
+
/* check endian sanity */
#ifdef WORDS_BIGENDIAN
if (((char *)byte_order)[0] == 1)
if (((char *)byte_order)[0] != 1)
g_error ("gdk_rgb_init: WORDS_BIGENDIAN is not defined, but this is a little endian machine.\n\n");
#endif
-
+
if (image_info == NULL)
{
image_info = g_new0 (GdkRgbInfo, 1);
-
+
image_info->visual = NULL;
image_info->cmap = NULL;
-
+
image_info->color_pixels = NULL;
image_info->gray_pixels = NULL;
image_info->reserved_pixels = NULL;
-
+
image_info->nred_shades = 6;
image_info->ngreen_shades = 6;
image_info->nblue_shades = 4;
image_info->ngray_shades = 24;
image_info->nreserved = 0;
-
+
image_info->bpp = 0;
image_info->cmap_alloced = FALSE;
image_info->gamma = 1.0;
-
+
image_info->stage_buf = NULL;
-
+
gdk_rgb_choose_visual ();
-
- if (image_info->visual->type == GDK_VISUAL_PSEUDO_COLOR)
+
+ if (image_info->visual->depth == 4)
+ {
+ gdk_rgb_colorcube_222 ();
+ }
+ else if (image_info->visual->type == GDK_VISUAL_PSEUDO_COLOR)
{
if (gdk_rgb_install_cmap ||
image_info->visual != gdk_visual_get_system ())
gdk_rgb_do_colormaps ();
}
if (gdk_rgb_verbose)
- g_message ("color cube: %d x %d x %d",
- image_info->nred_shades,
- image_info->ngreen_shades,
- image_info->nblue_shades);
-
+ g_print ("color cube: %d x %d x %d\n",
+ image_info->nred_shades,
+ image_info->ngreen_shades,
+ image_info->nblue_shades);
+
if (!image_info->cmap_alloced)
- image_info->cmap = gdk_colormap_get_system ();
+ image_info->cmap = gdk_colormap_get_system ();
}
#ifdef ENABLE_GRAYSCALE
else if (image_info->visual->type == GDK_VISUAL_GRAYSCALE)
image_info->cmap = gdk_colormap_new (image_info->visual, FALSE);
gdk_rgb_set_gray_cmap (image_info->cmap);
image_info->cmap_alloced = TRUE;
- }
+ }
#endif
else
{
image_info->cmap_alloced = TRUE;
}
}
-
+
for (i = 0; i < N_IMAGES; i++)
static_image[i] = gdk_image_new (GDK_IMAGE_FASTEST,
image_info->visual,
IMAGE_WIDTH, IMAGE_HEIGHT);
-
+
image_info->bpp = static_image[0]->bpp;
-
+
gdk_rgb_select_conv (static_image[0]);
-
+
}
}
gdk_rgb_xpixel_from_rgb (guint32 rgb)
{
gulong pixel;
-
+
if (image_info->visual->type == GDK_VISUAL_PSEUDO_COLOR)
pixel = colorcube[((rgb & 0xf00000) >> 12) |
((rgb & 0xf000) >> 8) |
((rgb & 0xf0) >> 4)];
+ else if (image_info->visual->depth == 4 &&
+ image_info->visual->type == GDK_VISUAL_STATIC_COLOR)
+ {
+ pixel = colorcube_d[((rgb & 0x800000) >> 17) |
+ ((rgb & 0x8000) >> 12) |
+ ((rgb & 0x80) >> 7)];
+ }
else
{
#ifdef VERBOSE
- g_message ("shift, prec: r %d %d g %d %d b %d %d",
- image_info->visual->red_shift,
- image_info->visual->red_prec,
- image_info->visual->green_shift,
- image_info->visual->green_prec,
- image_info->visual->blue_shift,
- image_info->visual->blue_prec);
+ g_print ("shift, prec: r %d %d g %d %d b %d %d\n",
+ image_info->visual->red_shift,
+ image_info->visual->red_prec,
+ image_info->visual->green_shift,
+ image_info->visual->green_prec,
+ image_info->visual->blue_shift,
+ image_info->visual->blue_prec);
#endif
-
+
pixel = (((((rgb & 0xff0000) >> 16) >>
(8 - image_info->visual->red_prec)) <<
image_info->visual->red_shift) +
- ((((rgb & 0xff00) >> 8) >>
+ ((((rgb & 0xff00) >> 8) >>
(8 - image_info->visual->green_prec)) <<
image_info->visual->green_shift) +
(((rgb & 0xff) >>
(8 - image_info->visual->blue_prec)) <<
image_info->visual->blue_shift));
-
- ;
}
-
+
return pixel;
}
gdk_rgb_gc_set_foreground (GdkGC *gc, guint32 rgb)
{
GdkColor color;
-
+
color.pixel = gdk_rgb_xpixel_from_rgb (rgb);
gdk_gc_set_foreground (gc, &color);
}
gdk_rgb_gc_set_background (GdkGC *gc, guint32 rgb)
{
GdkColor color;
-
+
color.pixel = gdk_rgb_xpixel_from_rgb (rgb);
gdk_gc_set_background (gc, &color);
}
guchar *obuf, *obptr;
guchar *bptr, *bp2;
gint r, g, b;
-
+
bptr = buf;
bpl = image->bpl;
obuf = ((guchar *)image->mem) + y0 * bpl + x0;
{
bp2 = bptr;
obptr = obuf;
- if (width < 8 || (((unsigned long)obuf | (unsigned long) bp2) & 3))
+ if (((unsigned long)obuf | (unsigned long) bp2) & 3)
{
for (x = 0; x < width; x++)
{
guint32 r1b0g0r0;
guint32 g2r2b1g1;
guint32 b3g3r3b2;
-
+
r1b0g0r0 = ((guint32 *)bp2)[0];
g2r2b1g1 = ((guint32 *)bp2)[1];
b3g3r3b2 = ((guint32 *)bp2)[2];
guchar *obuf, *obptr;
guchar *bptr, *bp2;
gint r, g, b;
-
+
bptr = buf;
bpl = image->bpl;
obuf = ((guchar *)image->mem) + y0 * bpl + x0;
{ 46, 2, 56, 11, 41, 1, 49, 6, 27, 47, 2, 48, 5, 32, 37, 3, 13, 19, 32, 1, 55, 28, 60, 17, 43, 59, 32, 20, 49, 16, 55, 23, 14, 46, 2, 36, 6, 30, 20, 49, 12, 47, 35, 14, 21, 60, 29, 14, 35, 24, 46, 1, 56, 29, 53, 8, 33, 23, 56, 1, 35, 46, 20, 39, 26, 4, 53, 28, 17, 38, 60, 34, 48, 9, 55, 15, 46, 7, 41, 31, 60, 24, 16, 36, 1, 59, 19, 52, 35, 6, 55, 11, 59, 33, 7, 57, 4, 29, 48, 1, 19, 26, 37, 30, 18, 63, 37, 6, 59, 1, 40, 24, 56, 33, 46, 22, 35, 7, 24, 53, 39, 5, 26, 45, 55, 18, 62, 7 },
{ 20, 60, 29, 34, 20, 62, 33, 52, 10, 36, 13, 60, 41, 21, 50, 27, 56, 49, 8, 51, 21, 45, 11, 48, 8, 23, 53, 3, 29, 44, 5, 52, 9, 32, 50, 17, 43, 56, 3, 38, 24, 10, 62, 25, 51, 9, 33, 49, 61, 7, 30, 62, 22, 19, 2, 42, 63, 5, 49, 18, 60, 15, 52, 7, 43, 56, 23, 50, 5, 50, 2, 20, 41, 30, 1, 52, 22, 61, 14, 26, 3, 43, 53, 7, 47, 28, 11, 14, 23, 58, 33, 25, 47, 13, 50, 17, 40, 54, 34, 60, 41, 6, 59, 14, 50, 7, 25, 55, 20, 42, 51, 8, 27, 4, 16, 60, 28, 50, 44, 3, 22, 49, 63, 12, 33, 1, 43, 31 },
{ 36, 5, 46, 8, 44, 24, 13, 39, 25, 57, 31, 18, 8, 52, 10, 45, 6, 30, 36, 24, 63, 4, 33, 26, 57, 40, 15, 56, 37, 12, 40, 25, 37, 58, 11, 63, 21, 45, 16, 60, 31, 53, 18, 33, 3, 45, 23, 0, 20, 54, 40, 15, 50, 38, 60, 16, 25, 42, 29, 38, 7, 41, 25, 62, 18, 33, 8, 35, 42, 16, 32, 56, 12, 39, 59, 19, 34, 9, 49, 38, 57, 12, 21, 50, 14, 40, 61, 44, 50, 9, 49, 19, 3, 29, 35, 62, 12, 24, 7, 18, 52, 32, 10, 46, 21, 41, 32, 11, 36, 29, 14, 34, 60, 38, 54, 11, 41, 14, 19, 57, 32, 16, 7, 41, 51, 25, 14, 57 },
- { 53, 18, 26, 50, 15, 58, 4, 63, 17, 43, 7, 40, 61, 35, 15, 41, 23, 60, 16, 38, 14, 42, 19, 50, 0, 31, 10, 46, 27, 63, 18, 60, 0, 20, 29, 39, 8, 26, 37, 5, 42, 0, 44, 39, 57, 17, 58, 41, 28, 37, 4, 32, 9, 44, 12, 31, 54, 10, 59, 14, 27, 53, 12, 36, 0, 47, 13, 64, 21, 58, 10, 24, 50, 27, 4, 26, 44, 53, 31, 0, 18, 42, 29, 33, 57, 4, 32, 26, 0, 38, 16, 61, 41, 53, 20, 0, 42, 44, 49, 27, 10, 56, 39, 0, 57, 15, 53, 49, 3, 61, 22, 47, 17, 5, 49, 26, 2, 63, 39, 10, 47, 27, 37, 23, 4, 59, 38, 10 },
+ { 53, 18, 26, 50, 15, 58, 4, 63, 17, 43, 7, 40, 61, 35, 15, 41, 23, 60, 16, 38, 14, 42, 19, 50, 0, 31, 10, 46, 27, 63, 18, 60, 0, 20, 29, 39, 8, 26, 37, 5, 42, 0, 44, 39, 57, 17, 58, 41, 28, 37, 4, 32, 9, 44, 12, 31, 54, 10, 59, 14, 27, 53, 12, 36, 0, 47, 13, 63, 21, 58, 10, 24, 50, 27, 4, 26, 44, 53, 31, 0, 18, 42, 29, 33, 57, 4, 32, 26, 0, 38, 16, 61, 41, 53, 20, 0, 42, 44, 49, 27, 10, 56, 39, 0, 57, 15, 53, 49, 3, 61, 22, 47, 17, 5, 49, 26, 2, 63, 39, 10, 47, 27, 37, 23, 4, 59, 38, 10 },
{ 23, 39, 61, 3, 37, 28, 48, 31, 0, 34, 51, 23, 2, 26, 58, 0, 53, 11, 46, 1, 57, 29, 52, 14, 37, 61, 21, 35, 2, 49, 7, 34, 47, 55, 4, 33, 54, 13, 58, 52, 19, 50, 22, 7, 13, 29, 36, 11, 51, 17, 60, 25, 55, 4, 34, 51, 0, 35, 20, 48, 32, 3, 51, 30, 59, 28, 40, 3, 46, 29, 54, 43, 7, 62, 47, 11, 39, 4, 23, 46, 55, 8, 63, 5, 25, 37, 18, 46, 21, 56, 31, 5, 36, 8, 45, 58, 26, 15, 2, 36, 47, 21, 29, 44, 25, 34, 3, 27, 43, 10, 52, 0, 45, 30, 24, 36, 43, 18, 34, 59, 0, 52, 61, 15, 44, 19, 30, 49 },
{ 0, 27, 12, 43, 54, 9, 22, 53, 21, 46, 15, 55, 29, 47, 20, 33, 39, 28, 59, 35, 9, 44, 5, 24, 47, 7, 52, 17, 56, 22, 30, 42, 14, 26, 45, 18, 49, 1, 24, 34, 11, 27, 55, 32, 61, 47, 2, 56, 6, 44, 13, 47, 36, 27, 58, 22, 16, 47, 40, 4, 57, 38, 21, 45, 16, 9, 56, 26, 11, 38, 0, 22, 36, 17, 33, 57, 16, 30, 62, 15, 35, 40, 20, 45, 59, 10, 54, 8, 63, 13, 52, 27, 22, 57, 28, 12, 32, 51, 55, 22, 63, 4, 16, 54, 12, 62, 45, 19, 58, 13, 32, 40, 20, 56, 7, 57, 9, 54, 6, 29, 42, 21, 8, 55, 35, 47, 6, 41 },
{ 56, 33, 58, 32, 19, 35, 42, 6, 59, 11, 38, 5, 49, 12, 62, 7, 52, 17, 5, 25, 54, 20, 61, 31, 54, 27, 41, 11, 44, 5, 59, 12, 36, 51, 10, 61, 28, 41, 48, 9, 43, 63, 5, 40, 20, 8, 49, 26, 34, 21, 58, 1, 18, 45, 7, 39, 61, 26, 8, 50, 23, 10, 63, 5, 55, 37, 19, 49, 52, 15, 59, 47, 13, 54, 1, 25, 42, 58, 10, 48, 3, 27, 50, 1, 17, 48, 34, 41, 16, 40, 2, 45, 10, 39, 17, 61, 5, 38, 19, 9, 41, 31, 60, 38, 5, 23, 36, 8, 30, 55, 24, 63, 12, 48, 14, 51, 31, 20, 45, 25, 12, 50, 32, 2, 28, 11, 62, 14 },
#define DM_HEIGHT 8
static guchar DM[8][8] =
{
- { 0, 32, 8, 40, 2, 34, 10, 42 },
+ { 0, 32, 8, 40, 2, 34, 10, 42 },
{ 48, 16, 56, 24, 50, 18, 58, 26 },
- { 12, 44, 4, 36, 14, 46, 6, 38 },
+ { 12, 44, 4, 36, 14, 46, 6, 38 },
{ 60, 28, 52, 20, 62, 30, 54, 22 },
- { 3, 35, 11, 43, 1, 33, 9, 41 },
+ { 3, 35, 11, 43, 1, 33, 9, 41 },
{ 51, 19, 59, 27, 49, 17, 57, 25 },
- { 15, 47, 7, 39, 13, 45, 5, 37 },
+ { 15, 47, 7, 39, 13, 45, 5, 37 },
{ 63, 31, 55, 23, 61, 29, 53, 21 }
};
#endif
{
int i;
guint32 dith;
-
+
if (DM_565 == NULL)
{
DM_565 = g_new (guint32, DM_WIDTH * DM_HEIGHT);
dith = DM[0][i] >> 3;
DM_565[i] = (dith << 20) | dith | (((7 - dith) >> 1) << 10);
#ifdef VERBOSE
- g_message ("%i %x %x", i, dith, DM_565[i]);
+ g_print ("%i %x %x\n", i, dith, DM_565[i]);
#endif
}
}
gint r, g, b;
guchar *dmp;
gint dith;
-
+
bptr = buf;
bpl = image->bpl;
obuf = ((guchar *)image->mem) + y0 * bpl + x0;
guchar *dmp;
gint dith;
gint rs, gs, bs;
-
+
bptr = buf;
bpl = image->bpl;
rs = image_info->nred_shades - 1;
guchar *bptr, *bp2;
guchar c;
guchar *lut;
-
+
lut = cmap->lut;
bptr = buf;
bpl = image->bpl;
guchar *obuf, *obptr;
guchar *bptr, *bp2;
gint r, g, b;
-
+
bptr = buf;
bpl = image->bpl;
obuf = ((guchar *)image->mem) + y0 * bpl + x0;
gint bpl;
guchar *obuf;
guchar *bptr;
-
+
bptr = buf;
bpl = image->bpl;
obuf = ((guchar *)image->mem) + y0 * bpl + x0;
This assumes native byte ordering - what should really be done is to
check whether static_image->byte_order is consistent with the _ENDIAN
config flag, and if not, use a different function.
-
+
This one is even faster than the one below - its inner loop loads 3
words (i.e. 4 24-bit pixels), does a lot of shifting and masking,
then writes 2 words. */
gint bpl;
guchar *bptr, *bp2;
guchar r, g, b;
-
+
bptr = buf;
bpl = image->bpl;
obuf = ((guchar *)image->mem) + y0 * bpl + x0 * 2;
{
bp2 = bptr;
obptr = obuf;
- if (width < 8 || (((unsigned long)obuf | (unsigned long) bp2) & 3))
+ if (((unsigned long)obuf | (unsigned long) bp2) & 3)
{
for (x = 0; x < width; x++)
{
guint32 r1b0g0r0;
guint32 g2r2b1g1;
guint32 b3g3r3b2;
-
+
r1b0g0r0 = ((guint32 *)bp2)[0];
g2r2b1g1 = ((guint32 *)bp2)[1];
b3g3r3b2 = ((guint32 *)bp2)[2];
This assumes native byte ordering - what should really be done is to
check whether static_image->byte_order is consistent with the _ENDIAN
config flag, and if not, use a different function.
-
+
This routine is faster than the one included with Gtk 1.0 for a number
of reasons:
-
+
1. Shifting instead of lookup tables (less memory traffic).
-
+
2. Much less register pressure, especially because shifts are
in the code.
-
+
3. A memcpy is avoided (i.e. the transfer function).
-
+
4. On big-endian architectures, byte swapping is avoided.
-
+
That said, it wouldn't be hard to make it even faster - just make an
inner loop that reads 3 words (i.e. 4 24-bit pixels), does a lot of
shifting and masking, then writes 2 words.
gint bpl;
guchar *bptr, *bp2;
guchar r, g, b;
-
+
bptr = buf;
bpl = image->bpl;
obuf = ((guchar *)image->mem) + y0 * bpl + x0 * 2;
gint bpl;
guchar *bptr, *bp2;
guchar g;
-
+
bptr = buf;
bpl = image->bpl;
obuf = ((guchar *)image->mem) + y0 * bpl + x0 * 2;
{
bp2 = bptr;
obptr = obuf;
- if (width < 8 || (((unsigned long)obuf | (unsigned long) bp2) & 3))
+ if (((unsigned long)obuf | (unsigned long) bp2) & 3)
{
for (x = 0; x < width; x++)
{
for (x = 0; x < width - 3; x += 4)
{
guint32 g3g2g1g0;
-
+
g3g2g1g0 = ((guint32 *)bp2)[0];
((guint32 *)obptr)[0] =
((g3g2g1g0 & 0xf8) << 8) |
gint bpl;
guchar *bptr, *bp2;
guchar g;
-
+
bptr = buf;
bpl = image->bpl;
obuf = ((guchar *)image->mem) + y0 * bpl + x0 * 2;
gint bpl;
guchar *bptr, *bp2;
guchar r, g, b;
-
+
bptr = buf;
bpl = image->bpl;
obuf = ((guchar *)image->mem) + y0 * bpl + x0 * 2;
b = *bp2++;
/* final word is:
g4 g3 g2 b7 b6 b5 b4 b3 r7 r6 r5 r4 r3 g7 g6 g5
- */
+ */
((unsigned short *)obuf)[x] = (r & 0xf8) |
((g & 0xe0) >> 5) |
((g & 0x1c) << 11) |
#ifdef HAIRY_CONVERT_565
static void
gdk_rgb_convert_565_d (GdkImage *image,
- gint x0, gint y0, gint width, gint height,
- guchar *buf, int rowstride,
- gint x_align, gint y_align, GdkRgbCmap *cmap)
+ gint x0, gint y0, gint width, gint height,
+ guchar *buf, int rowstride,
+ gint x_align, gint y_align, GdkRgbCmap *cmap)
{
/* Now this is what I'd call some highly tuned code! */
int x, y;
guchar *obuf, *obptr;
gint bpl;
guchar *bptr, *bp2;
-
+
width += x_align;
height += y_align;
guint32 *dmp = DM_565 + ((y & (DM_HEIGHT - 1)) << DM_WIDTH_SHIFT);
bp2 = bptr;
obptr = obuf;
- if (width < 8 || (((unsigned long)obuf | (unsigned long) bp2) & 3))
+ if (((unsigned long)obuf | (unsigned long) bp2) & 3)
{
for (x = x_align; x < width; x++)
{
rgb += 0x10040100
- ((rgb & 0x1e0001e0) >> 5)
- ((rgb & 0x00070000) >> 6);
-
- ((unsigned short *)obuf)[0] =
+
+ ((unsigned short *)obptr)[0] =
((rgb & 0x0f800000) >> 12) |
((rgb & 0x0003f000) >> 7) |
((rgb & 0x000000f8) >> 3);
guint32 g2r2b1g1;
guint32 b3g3r3b2;
guint32 rgb02, rgb13;
-
+
r1b0g0r0 = ((guint32 *)bp2)[0];
g2r2b1g1 = ((guint32 *)bp2)[1];
b3g3r3b2 = ((guint32 *)bp2)[2];
rgb += 0x10040100
- ((rgb & 0x1e0001e0) >> 5)
- ((rgb & 0x00070000) >> 6);
-
- ((unsigned short *)obuf)[0] =
+
+ ((unsigned short *)obptr)[0] =
((rgb & 0x0f800000) >> 12) |
((rgb & 0x0003f000) >> 7) |
((rgb & 0x000000f8) >> 3);
#else
static void
gdk_rgb_convert_565_d (GdkImage *image,
- gint x0, gint y0, gint width, gint height,
- guchar *buf, int rowstride,
- gint x_align, gint y_align, GdkRgbCmap *cmap)
+ gint x0, gint y0, gint width, gint height,
+ guchar *buf, int rowstride,
+ gint x_align, gint y_align, GdkRgbCmap *cmap)
{
int x, y;
guchar *obuf;
gint bpl;
guchar *bptr;
-
+
width += x_align;
height += y_align;
bptr = buf;
bpl = image->bpl;
obuf = ((guchar *)image->mem) + y0 * bpl + (x0 - x_align) * 2;
-
+
for (y = y_align; y < height; y++)
{
guint32 *dmp = DM_565 + ((y & (DM_HEIGHT - 1)) << DM_WIDTH_SHIFT);
guchar *bp2 = bptr;
-
+
for (x = x_align; x < width; x++)
- {
- gint32 rgb = *bp2++ << 20;
- rgb += *bp2++ << 10;
- rgb += *bp2++;
+ {
+ gint32 rgb = *bp2++ << 20;
+ rgb += *bp2++ << 10;
+ rgb += *bp2++;
rgb += dmp[x & (DM_WIDTH - 1)];
- rgb += 0x10040100
- - ((rgb & 0x1e0001e0) >> 5)
- - ((rgb & 0x00070000) >> 6);
-
- ((unsigned short *)obuf)[x] =
- ((rgb & 0x0f800000) >> 12) |
- ((rgb & 0x0003f000) >> 7) |
- ((rgb & 0x000000f8) >> 3);
- }
-
+ rgb += 0x10040100
+ - ((rgb & 0x1e0001e0) >> 5)
+ - ((rgb & 0x00070000) >> 6);
+
+ ((unsigned short *)obuf)[x] =
+ ((rgb & 0x0f800000) >> 12) |
+ ((rgb & 0x0003f000) >> 7) |
+ ((rgb & 0x000000f8) >> 3);
+ }
+
bptr += rowstride;
obuf += bpl;
}
gint bpl;
guchar *bptr, *bp2;
guchar r, g, b;
-
+
bptr = buf;
bpl = image->bpl;
obuf = ((guchar *)image->mem) + y0 * bpl + x0 * 2;
gint bpl;
guchar *bptr, *bp2;
guchar r, g, b;
-
+
bptr = buf;
bpl = image->bpl;
obuf = ((guchar *)image->mem) + y0 * bpl + x0 * 2;
b = *bp2++;
/* final word is:
g5 g4 g3 b7 b6 b5 b4 b3 0 r7 r6 r5 r4 r3 g7 g6
- */
+ */
((unsigned short *)obuf)[x] = ((r & 0xf8) >> 1) |
((g & 0xc0) >> 6) |
((g & 0x18) << 10) |
guchar *obuf;
gint bpl;
guchar *bptr;
-
+
bptr = buf;
bpl = image->bpl;
obuf = ((guchar *)image->mem) + y0 * bpl + x0 * 3;
gint bpl;
guchar *bptr, *bp2;
int r, g, b;
-
+
bptr = buf;
bpl = image->bpl;
obuf = ((guchar *)image->mem) + y0 * bpl + x0 * 3;
{
bp2 = bptr;
obptr = obuf;
- if (width < 8 || (((unsigned long)obuf | (unsigned long) bp2) & 3))
+ if (((unsigned long)obuf | (unsigned long) bp2) & 3)
{
for (x = 0; x < width; x++)
{
guint32 r1b0g0r0;
guint32 g2r2b1g1;
guint32 b3g3r3b2;
-
+
r1b0g0r0 = ((guint32 *)bp2)[0];
g2r2b1g1 = ((guint32 *)bp2)[1];
b3g3r3b2 = ((guint32 *)bp2)[2];
gint bpl;
guchar *bptr, *bp2;
int r, g, b;
-
+
bptr = buf;
bpl = image->bpl;
obuf = ((guchar *)image->mem) + y0 * bpl + x0 * 3;
gint bpl;
guchar *bptr, *bp2;
int r, g, b;
-
+
bptr = buf;
bpl = image->bpl;
obuf = ((guchar *)image->mem) + y0 * bpl + x0 * 4;
gint bpl;
guchar *bptr, *bp2;
int r, g, b;
-
+
bptr = buf;
bpl = image->bpl;
obuf = ((guchar *)image->mem) + y0 * bpl + x0 * 4;
gint bpp;
guint32 pixel;
gint i;
-
+
r_right = 8 - image_info->visual->red_prec;
r_left = image_info->visual->red_shift;
g_right = 8 - image_info->visual->green_prec;
gint dith;
gint r1, g1, b1;
guchar *dmp;
-
+
r_right = 8 - image_info->visual->red_prec;
r_left = image_info->visual->red_shift;
r_prec = image_info->visual->red_prec;
gint bpp;
guint32 pixel;
gint shift, shift_init;
-
+
r_right = 8 - image_info->visual->red_prec;
r_left = image_info->visual->red_shift;
g_right = 8 - image_info->visual->green_prec;
gint dith;
gint r1, g1, b1;
guchar *dmp;
-
+
r_right = 8 - image_info->visual->red_prec;
r_left = image_info->visual->red_shift;
r_prec = image_info->visual->red_prec;
}
}
+#define IMAGE_8BPP
+static void
+gdk_rgb_convert_4 (GdkImage *image,
+ gint x0, gint y0, gint width, gint height,
+ guchar *buf, int rowstride,
+ gint x_align, gint y_align,
+ GdkRgbCmap *cmap)
+{
+ int x, y;
+ gint bpl;
+ guchar *obuf, *obptr;
+ guchar *bptr, *bp2;
+ gint r, g, b;
+ guchar *dmp;
+ gint dith;
+ guchar pix0, pix1;
+
+ bptr = buf;
+ bpl = image->bpl;
+ obuf = ((guchar *)image->mem) + y0 * bpl + x0;
+ for (y = 0; y < height; y++)
+ {
+ dmp = DM[(y_align + y) & (DM_HEIGHT - 1)];
+ bp2 = bptr;
+ obptr = obuf;
+#ifdef IMAGE_8BPP
+ for (x = 0; x < width; x += 1)
+ {
+ r = *bp2++;
+ g = *bp2++;
+ b = *bp2++;
+ dith = (dmp[(x_align + x) & (DM_WIDTH - 1)] << 2) | 3;
+ obptr[0] = colorcube_d[(((r + dith) & 0x100) >> 2) |
+ (((g + 258 - dith) & 0x100) >> 5) |
+ (((b + dith) & 0x100) >> 8)];
+ obptr++;
+ }
+#else
+ for (x = 0; x < width; x += 2)
+ {
+ r = *bp2++;
+ g = *bp2++;
+ b = *bp2++;
+ dith = (dmp[(x_align + x) & (DM_WIDTH - 1)] << 2) | 3;
+ pix0 = colorcube_d[(((r + dith) & 0x100) >> 2) |
+ (((g + dith) & 0x100) >> 5) |
+ (((b + dith) & 0x100) >> 8)];
+ r = *bp2++;
+ g = *bp2++;
+ b = *bp2++;
+ dith = (dmp[(x_align + x + 1) & (DM_WIDTH - 1)] << 2) | 3;
+ pix1 = colorcube_d[(((r + dith) & 0x100) >> 2) |
+ (((g + dith) & 0x100) >> 5) |
+ (((b + dith) & 0x100) >> 8)];
+ obptr[0] = (pix0 << 4) | pix1;
+ obptr++;
+ }
+#endif
+ bptr += rowstride;
+ obuf += bpl;
+ }
+}
+
+
/* Returns a pointer to the stage buffer. */
static guchar *
gdk_rgb_ensure_stage (void)
gint x, y;
guchar *pi_start, *po_start;
guchar *pi, *po;
-
+
pi_start = buf;
po_start = gdk_rgb_ensure_stage ();
for (y = 0; y < height; y++)
gint x_align, gint y_align, GdkRgbCmap *cmap)
{
gdk_rgb_32_to_stage (buf, rowstride, width, height);
-
+
(*image_info->conv) (image, x0, y0, width, height,
image_info->stage_buf, STAGE_ROWSTRIDE,
x_align, y_align, cmap);
gint x_align, gint y_align, GdkRgbCmap *cmap)
{
gdk_rgb_32_to_stage (buf, rowstride, width, height);
-
+
(*image_info->conv_d) (image, x0, y0, width, height,
image_info->stage_buf, STAGE_ROWSTRIDE,
x_align, y_align, cmap);
guchar *pi_start, *po_start;
guchar *pi, *po;
guchar gray;
-
+
pi_start = buf;
po_start = gdk_rgb_ensure_stage ();
for (y = 0; y < height; y++)
gint x_align, gint y_align, GdkRgbCmap *cmap)
{
gdk_rgb_gray_to_stage (buf, rowstride, width, height);
-
+
(*image_info->conv) (image, x0, y0, width, height,
image_info->stage_buf, STAGE_ROWSTRIDE,
x_align, y_align, cmap);
gint x_align, gint y_align, GdkRgbCmap *cmap)
{
gdk_rgb_gray_to_stage (buf, rowstride, width, height);
-
+
(*image_info->conv_d) (image, x0, y0, width, height,
image_info->stage_buf, STAGE_ROWSTRIDE,
x_align, y_align, cmap);
#if 0
static void
gdk_rgb_convert_gray_cmap_d (GdkImage *image,
- gint x0, gint y0, gint width, gint height,
- guchar *buf, gint rowstride,
- gint x_align, gint y_align, GdkRgbCmap *cmap)
+ gint x0, gint y0, gint width, gint height,
+ guchar *buf, gint rowstride,
+ gint x_align, gint y_align, GdkRgbCmap *cmap)
{
(*image_info->conv_indexed_d) (image, x0, y0, width, height,
buf, rowstride,
guchar *pi_start, *po_start;
guchar *pi, *po;
gint rgb;
-
+
pi_start = buf;
po_start = gdk_rgb_ensure_stage ();
for (y = 0; y < height; y++)
gint x_align, gint y_align, GdkRgbCmap *cmap)
{
gdk_rgb_indexed_to_stage (buf, rowstride, width, height, cmap);
-
+
(*image_info->conv) (image, x0, y0, width, height,
image_info->stage_buf, STAGE_ROWSTRIDE,
x_align, y_align, cmap);
GdkRgbCmap *cmap)
{
gdk_rgb_indexed_to_stage (buf, rowstride, width, height, cmap);
-
+
(*image_info->conv_d) (image, x0, y0, width, height,
image_info->stage_buf, STAGE_ROWSTRIDE,
x_align, y_align, cmap);
GdkRgbConvFunc conv_32, conv_32_d;
GdkRgbConvFunc conv_gray, conv_gray_d;
GdkRgbConvFunc conv_indexed, conv_indexed_d;
-
+
depth = image_info->visual->depth;
bpp = image->bpp;
-
+
byte_order = image->byte_order;
-
+
#ifdef WORDS_BIGENDIAN
byterev = (byte_order == GDK_LSB_FIRST);
#else
byterev = (byte_order == GDK_MSB_FIRST);
#endif
-
+
vtype = image_info->visual->type;
if (vtype == GDK_VISUAL_DIRECT_COLOR)
vtype = GDK_VISUAL_TRUE_COLOR;
-
+
red_mask = image_info->visual->red_mask;
green_mask = image_info->visual->green_mask;
blue_mask = image_info->visual->blue_mask;
-
+
conv = NULL;
conv_d = NULL;
-
+
conv_32 = gdk_rgb_convert_32_generic;
conv_32_d = gdk_rgb_convert_32_generic_d;
-
+
conv_gray = gdk_rgb_convert_gray_generic;
conv_gray_d = gdk_rgb_convert_gray_generic_d;
-
+
conv_indexed = gdk_rgb_convert_indexed_generic;
conv_indexed_d = gdk_rgb_convert_indexed_generic_d;
-
+
image_info->dith_default = FALSE;
-
+
if (bpp == 2 && depth == 16 && !byterev &&
red_mask == 0xf800 && green_mask == 0x7e0 && blue_mask == 0x1f)
{
}
else if (bpp == 2 && depth == 16 &&
vtype == GDK_VISUAL_TRUE_COLOR && byterev &&
- red_mask == 0xf800 && green_mask == 0x7e0 && blue_mask == 0x1f)
+ red_mask == 0xf800 && green_mask == 0x7e0 && blue_mask == 0x1f)
conv = gdk_rgb_convert_565_br;
-
+
else if (bpp == 2 && depth == 15 &&
vtype == GDK_VISUAL_TRUE_COLOR && !byterev &&
- red_mask == 0x7c00 && green_mask == 0x3e0 && blue_mask == 0x1f)
+ red_mask == 0x7c00 && green_mask == 0x3e0 && blue_mask == 0x1f)
conv = gdk_rgb_convert_555;
-
+
else if (bpp == 2 && depth == 15 &&
vtype == GDK_VISUAL_TRUE_COLOR && byterev &&
- red_mask == 0x7c00 && green_mask == 0x3e0 && blue_mask == 0x1f)
+ red_mask == 0x7c00 && green_mask == 0x3e0 && blue_mask == 0x1f)
conv = gdk_rgb_convert_555_br;
-
+
/* I'm not 100% sure about the 24bpp tests */
else if (bpp == 3 && depth == 24 &&
vtype == GDK_VISUAL_TRUE_COLOR && byte_order == GDK_LSB_FIRST &&
vtype == GDK_VISUAL_TRUE_COLOR && byterev &&
red_mask == 0xff0000 && green_mask == 0xff00 && blue_mask == 0xff)
conv = gdk_rgb_convert_0888_br;
-
+
else if (vtype == GDK_VISUAL_TRUE_COLOR && byte_order == GDK_LSB_FIRST)
{
conv = gdk_rgb_convert_truecolor_lsb;
conv = gdk_rgb_convert_gray8;
conv_gray = gdk_rgb_convert_gray8_gray;
}
-
+ else if (depth == 4)
+ {
+ conv = gdk_rgb_convert_4;
+ }
+
if (conv_d == NULL)
conv_d = conv;
-
+
image_info->conv = conv;
image_info->conv_d = conv_d;
-
+
image_info->conv_32 = conv_32;
image_info->conv_32_d = conv_32_d;
-
+
image_info->conv_gray = conv_gray;
image_info->conv_gray_d = conv_gray_d;
-
+
image_info->conv_indexed = conv_indexed;
image_info->conv_indexed_d = conv_indexed_d;
}
gdk_flush ();
#endif
#ifdef VERBOSE
- g_message ("flush, %d puts since last flush", sincelast);
+ g_print ("flush, %d puts since last flush\n", sincelast);
sincelast = 0;
#endif
static_image_idx = 0;
{
GdkImage *image;
gint idx;
-
-
+
+
if (width >= (IMAGE_WIDTH >> 1))
{
if (height >= (IMAGE_HEIGHT >> 1))
}
image = static_image[idx];
#ifdef VERBOSE
- g_message ("index %d, x %d, y %d (%d x %d)", idx, *x0, *y0, width, height);
+ g_print ("index %d, x %d, y %d (%d x %d)\n", idx, *x0, *y0, width, height);
sincelast++;
#endif
return image;
GdkImage *image;
gint width1, height1;
guchar *buf_ptr;
-
+
for (y0 = 0; y0 < height; y0 += IMAGE_HEIGHT)
{
height1 = MIN (height - y0, IMAGE_HEIGHT);
{
width1 = MIN (width - x0, IMAGE_WIDTH);
buf_ptr = buf + y0 * rowstride + x0 * pixstride;
-
+
image = gdk_rgb_alloc_scratch (width1, height1, &xs0, &ys0);
-
+
conv (image, xs0, ys0, width1, height1, buf_ptr, rowstride,
x + x0, y + y0, cmap);
-
+
#ifndef DONT_ACTUALLY_DRAW
gdk_draw_image (drawable, gc,
image, xs0, ys0, x + x0, y + y0, width1, height1);
{
guint32 rgb[256];
gint i;
-
+
for (i = 0; i < 256; i++)
- rgb[i] = (i << 16) | (i << 8) | i;
+ rgb[i] = (i << 16) | (i << 8) | i;
info->gray_cmap = gdk_rgb_cmap_new (rgb, 256);
}
GdkRgbCmap *cmap;
int i, j;
guint32 rgb;
-
+
g_return_val_if_fail (n_colors >= 0, NULL);
g_return_val_if_fail (n_colors <= 256, NULL);
cmap = g_new (GdkRgbCmap, 1);
{
rgb = colors[i];
j = ((rgb & 0xf00000) >> 12) |
- ((rgb & 0xf000) >> 8) |
- ((rgb & 0xf0) >> 4);
+ ((rgb & 0xf000) >> 8) |
+ ((rgb & 0xf0) >> 4);
#ifdef VERBOSE
- g_message ("%d %x %x %d", i, j, colorcube[j]);
+ g_print ("%d %x %x %d\n", i, j, colorcube[j]);
#endif
cmap->lut[i] = colorcube[j];
}
#include <sys/types.h>
#include <sys/param.h>
#include "gdk/gdkx.h"
+#include "gdk/gdkrgb.h"
#include "gtkpreview.h"
#include "gtksignal.h"
-#define IMAGE_SIZE 256
#define PREVIEW_CLASS(w) GTK_PREVIEW_CLASS (GTK_OBJECT (w)->klass)
-#define COLOR_COMPOSE(r,g,b) (lookup_red[r] | lookup_green[g] | lookup_blue[b])
-
-
-typedef struct _GtkPreviewProp GtkPreviewProp;
-typedef void (*GtkTransferFunc) (guchar *dest, guchar *src, gint count);
-
-struct _GtkPreviewProp
-{
- guint16 ref_count;
- guint16 nred_shades;
- guint16 ngreen_shades;
- guint16 nblue_shades;
- guint16 ngray_shades;
-};
static void gtk_preview_class_init (GtkPreviewClass *klass);
static gint gtk_preview_expose (GtkWidget *widget,
GdkEventExpose *event);
static void gtk_preview_make_buffer (GtkPreview *preview);
-static void gtk_preview_get_visuals (GtkPreviewClass *klass);
-static void gtk_preview_get_cmaps (GtkPreviewClass *klass);
-static void gtk_preview_dither_init (GtkPreviewClass *klass);
-static void gtk_fill_lookup_array (gulong *array,
- int depth,
- int shift,
- int prec);
-static void gtk_trim_cmap (GtkPreviewClass *klass);
-static void gtk_create_8_bit (GtkPreviewClass *klass);
-
-static void gtk_color_8 (guchar *src,
- guchar *data,
- gint x,
- gint y,
- gulong width);
-static void gtk_color_16 (guchar *src,
- guchar *data,
- gulong width);
-static void gtk_color_24 (guchar *src,
- guchar *data,
- gulong width);
-static void gtk_grayscale_8 (guchar *src,
- guchar *data,
- gint x,
- gint y,
- gulong width);
-static void gtk_grayscale_16 (guchar *src,
- guchar *data,
- gulong width);
-static void gtk_grayscale_24 (guchar *src,
- guchar *data,
- gulong width);
-
-static gint gtk_get_preview_prop (guint *nred,
- guint *nblue,
- guint *ngreen,
- guint *ngray);
-static void gtk_set_preview_prop (guint nred,
- guint ngreen,
- guint nblue,
- guint ngray);
-
-/* transfer functions:
- * destination byte order/source bpp/destination bpp
- */
-static void gtk_lsbmsb_1_1 (guchar *dest,
- guchar *src,
- gint count);
-static void gtk_lsb_2_2 (guchar *dest,
- guchar *src,
- gint count);
-static void gtk_msb_2_2 (guchar *dest,
- guchar *src,
- gint count);
-static void gtk_lsb_3_3 (guchar *dest,
- guchar *src,
- gint count);
-static void gtk_msb_3_3 (guchar *dest,
- guchar *src,
- gint count);
-static void gtk_lsb_3_4 (guchar *dest,
- guchar *src,
- gint count);
-static void gtk_msb_3_4 (guchar *dest,
- guchar *src,
- gint count);
-
+static void gtk_fill_lookup_array (guchar *array);
static GtkWidgetClass *parent_class = NULL;
static GtkPreviewClass *preview_class = NULL;
-static GtkPreviewInfo *preview_info = NULL;
static gint install_cmap = FALSE;
widget_class->realize = gtk_preview_realize;
widget_class->expose_event = gtk_preview_expose;
- if (preview_info)
- klass->info = *preview_info;
- else
- {
- klass->info.visual = NULL;
- klass->info.cmap = NULL;
-
- klass->info.color_pixels = NULL;
- klass->info.gray_pixels = NULL;
- klass->info.reserved_pixels = NULL;
-
- klass->info.lookup_red = NULL;
- klass->info.lookup_green = NULL;
- klass->info.lookup_blue = NULL;
-
- klass->info.dither_red = NULL;
- klass->info.dither_green = NULL;
- klass->info.dither_blue = NULL;
- klass->info.dither_gray = NULL;
- klass->info.dither_matrix = NULL;
-
- klass->info.nred_shades = 6;
- klass->info.ngreen_shades = 6;
- klass->info.nblue_shades = 4;
- klass->info.ngray_shades = 24;
- klass->info.nreserved = 0;
-
- klass->info.bpp = 0;
- klass->info.cmap_alloced = FALSE;
- klass->info.gamma = 1.0;
- }
+ klass->info.visual = NULL;
+ klass->info.cmap = NULL;
- klass->image = NULL;
+ klass->info.lookup = NULL;
- gtk_preview_get_visuals (klass);
- gtk_preview_get_cmaps (klass);
- gtk_preview_dither_init (klass);
+ klass->info.gamma = 1.0;
+
+ gdk_rgb_init ();
+ klass->info.cmap = gdk_rgb_get_cmap ();
+ klass->info.visual = gdk_rgb_get_visual ();
}
void
gtk_preview_reset (void)
{
- GtkPreviewInfo *info;
-
- if (!preview_class || !preview_info)
- return;
-
- info = &preview_class->info;
-
- gtk_preview_uninit();
-
- if (info->color_pixels)
- {
- gdk_colors_free (info->cmap,
- info->color_pixels,
- info->nred_shades *
- info->ngreen_shades *
- info->nblue_shades,
- 0);
-
- gdk_colors_free (info->cmap,
- info->gray_pixels,
- info->ngray_shades, 0);
-
- g_free (info->color_pixels);
- g_free (info->gray_pixels);
- }
-
- if (info->reserved_pixels)
- {
- gdk_colors_free (info->cmap,
- info->reserved_pixels,
- info->nreserved, 0);
- g_free (info->reserved_pixels);
- }
-
- if (info->cmap && info->cmap_alloced)
- gdk_colormap_unref (info->cmap);
-
- if (info->lookup_red)
- {
- g_free (info->lookup_red);
- g_free (info->lookup_green);
- g_free (info->lookup_blue);
- }
-
- if (info->dither_matrix)
- {
- int i, j;
-
- for (i= 0 ; i < 8 ; i++)
- {
- for (j = 0; j < 8 ; j++)
- g_free (info->dither_matrix[i][j]);
- g_free (info->dither_matrix[i]);
- }
- g_free (info->dither_matrix);
- g_free (info->dither_red);
- g_free (info->dither_green);
- g_free (info->dither_blue);
- }
-
- preview_class->info = *preview_info;
-
- gtk_preview_get_visuals (preview_class);
- gtk_preview_get_cmaps (preview_class);
- gtk_preview_dither_init (preview_class);
+ /* unimplemented */
}
static void
void
gtk_preview_uninit (void)
{
- GtkPreviewProp *prop;
- GdkAtom property;
-
- /* FIXME: need to grab the server here to prevent a race condition */
-
- if (preview_class && !install_cmap && preview_class->info.visual &&
- (preview_class->info.visual->type != GDK_VISUAL_TRUE_COLOR) &&
- (preview_class->info.visual->type != GDK_VISUAL_DIRECT_COLOR))
- {
- property = gdk_atom_intern ("GTK_PREVIEW_INFO", FALSE);
- if (gdk_property_get (NULL, property, property,
- 0, sizeof (GtkPreviewProp), FALSE,
- NULL, NULL, NULL, (guchar**) &prop))
- {
- prop->ref_count = prop->ref_count - 1;
- if (prop->ref_count == 0)
- {
- gdk_property_delete (NULL, property);
- }
- else
- {
- gdk_property_change (NULL, property, property, 16,
- GDK_PROP_MODE_REPLACE,
- (guchar*) prop, 5);
- }
- }
- }
+ /* unimplemented */
}
GtkWidget*
preview = gtk_type_new (gtk_preview_get_type ());
preview->type = type;
+ if (type == GTK_PREVIEW_COLOR)
+ preview->bpp = 3;
+ else
+ preview->bpp = 1;
+
+ preview->dither = GDK_RGB_DITHER_NORMAL;
+
return GTK_WIDGET (preview);
}
gint height)
{
GtkWidget *widget;
- GdkImage *image;
GdkRectangle r1, r2, r3;
- GtkTransferFunc transfer_func;
- guchar *image_mem;
- guchar *src, *dest;
- gint x, xe, x2;
- gint y, ye, y2;
- guint dest_rowstride;
- guint src_bpp;
- guint dest_bpp;
- gint i;
+ guchar *src;
+ guint bpp;
+ guint rowstride;
g_return_if_fail (preview != NULL);
g_return_if_fail (GTK_IS_PREVIEW (preview));
if (!gdk_rectangle_intersect (&r1, &r2, &r3))
return;
- x2 = r3.x + r3.width;
- y2 = r3.y + r3.height;
-
- if (!preview_class->image)
- preview_class->image = gdk_image_new (GDK_IMAGE_FASTEST,
- preview_class->info.visual,
- IMAGE_SIZE, IMAGE_SIZE);
- image = preview_class->image;
- src_bpp = preview_class->info.bpp;
-
- image_mem = image->mem;
- dest_bpp = image->bpp;
- dest_rowstride = image->bpl;
-
- transfer_func = NULL;
-
- switch (dest_bpp)
- {
- case 1:
- switch (src_bpp)
- {
- case 1:
- transfer_func = gtk_lsbmsb_1_1;
- break;
- }
- break;
- case 2:
- switch (src_bpp)
- {
- case 2:
- if (image->byte_order == GDK_MSB_FIRST)
- transfer_func = gtk_msb_2_2;
- else
- transfer_func = gtk_lsb_2_2;
- break;
- case 3:
- break;
- }
- break;
- case 3:
- switch (src_bpp)
- {
- case 3:
- if (image->byte_order == GDK_MSB_FIRST)
- transfer_func = gtk_msb_3_3;
- else
- transfer_func = gtk_lsb_3_3;
- break;
- }
- break;
- case 4:
- switch (src_bpp)
- {
- case 3:
- if (image->byte_order == GDK_MSB_FIRST)
- transfer_func = gtk_msb_3_4;
- else
- transfer_func = gtk_lsb_3_4;
- break;
- }
- break;
- }
-
- if (!transfer_func)
- {
- g_warning ("unsupported byte order/src bpp/dest bpp combination: %s:%d:%d",
- (image->byte_order == GDK_MSB_FIRST) ? "msb" : "lsb", src_bpp, dest_bpp);
- return;
- }
-
- for (y = r3.y; y < y2; y += IMAGE_SIZE)
- {
- for (x = r3.x; x < x2; x += IMAGE_SIZE)
- {
- xe = x + IMAGE_SIZE;
- if (xe > x2)
- xe = x2;
-
- ye = y + IMAGE_SIZE;
- if (ye > y2)
- ye = y2;
-
- for (i = y; i < ye; i++)
- {
- src = preview->buffer + (((gulong) (i - r1.y) * (gulong) preview->buffer_width) +
- (x - r1.x)) * (gulong) src_bpp;
- dest = image_mem + ((gulong) (i - y) * dest_rowstride);
-
- if (xe > x)
- (* transfer_func) (dest, src, xe - x);
- }
-
- gdk_draw_image (window, gc,
- image, 0, 0,
- destx + (r3.x - srcx) + (x - r3.x),
- desty + (r3.y - srcy) + (y - r3.y),
- xe - x, ye - y);
- gdk_flush ();
- }
- }
+ bpp = preview->bpp;
+ rowstride = preview->rowstride;
+
+ src = preview->buffer + r3.y * rowstride + r3.x * bpp;
+
+ if (preview->type == GTK_PREVIEW_COLOR)
+ gdk_draw_rgb_image (window,
+ gc,
+ destx + (r3.x - srcx),
+ desty + (r3.y - srcy),
+ r3.width,
+ r3.height,
+ preview->dither,
+ src,
+ rowstride);
+ else
+ gdk_draw_gray_image (window,
+ gc,
+ destx + (r3.x - srcx),
+ desty + (r3.y - srcy),
+ r3.width,
+ r3.height,
+ preview->dither,
+ src,
+ rowstride);
+
}
void
gint y,
gint w)
{
- g_return_if_fail (preview != NULL);
- g_return_if_fail (GTK_IS_PREVIEW (preview));
- g_return_if_fail (src != NULL);
- g_return_if_fail (dest != NULL);
-
- switch (preview->type)
- {
- case GTK_PREVIEW_COLOR:
- switch (preview_class->info.visual->depth)
- {
- case 8:
- gtk_color_8 (src, dest, x, y, w);
- break;
- case 15:
- case 16:
- gtk_color_16 (src, dest, w);
- break;
- case 24:
- case 32:
- gtk_color_24 (src, dest, w);
- break;
- }
- break;
- case GTK_PREVIEW_GRAYSCALE:
- switch (preview_class->info.visual->depth)
- {
- case 8:
- gtk_grayscale_8 (src, dest, x, y, w);
- break;
- case 15:
- case 16:
- gtk_grayscale_16 (src, dest, w);
- break;
- case 24:
- case 32:
- gtk_grayscale_24 (src, dest, w);
- break;
- }
- break;
- }
+ g_warning ("gtk_preview_put_row not implemented (deprecated)\n");
}
void
gint y,
gint w)
{
- guchar *dest;
+ guint bpp;
+ guint rowstride;
g_return_if_fail (preview != NULL);
g_return_if_fail (GTK_IS_PREVIEW (preview));
g_return_if_fail (data != NULL);
g_return_if_fail (preview_class->info.visual != NULL);
+ bpp = (preview->type == GTK_PREVIEW_COLOR ? 3 : 1);
+ rowstride = (preview->buffer_width * bpp + 3) & -4;
+
if ((w <= 0) || (y < 0))
return;
gtk_preview_make_buffer (preview);
- if (y >= preview->buffer_height)
+ if (x + w > preview->buffer_width)
+ return;
+
+ if (y + 1 > preview->buffer_height)
return;
- switch (preview->type)
+ if (preview_class->info.gamma == 1.0)
+ memcpy (preview->buffer + y * rowstride + x * bpp, data, w * bpp);
+ else
{
- case GTK_PREVIEW_COLOR:
- switch (preview_class->info.visual->depth)
- {
- case 8:
- dest = preview->buffer + ((gulong) y * (gulong) preview->buffer_width + (gulong) x);
- gtk_color_8 (data, dest, x, y, w);
- break;
- case 15:
- case 16:
- dest = preview->buffer + ((gulong) y * (gulong) preview->buffer_width + (gulong) x) * 2;
- gtk_color_16 (data, dest, w);
- break;
- case 24:
- case 32:
- dest = preview->buffer + ((gulong) y * (gulong) preview->buffer_width + (gulong) x) * 3;
- gtk_color_24 (data, dest, w);
- break;
- }
- break;
- case GTK_PREVIEW_GRAYSCALE:
- switch (preview_class->info.visual->depth)
+ guint i, size;
+ guchar *src, *dst;
+ guchar *lookup;
+
+ if (preview_class->info.lookup != NULL)
+ lookup = preview_class->info.lookup;
+ else
{
- case 8:
- dest = preview->buffer + ((gulong) y * (gulong) preview->buffer_width + (gulong) x);
- gtk_grayscale_8 (data, dest, x, y, w);
- break;
- case 15:
- case 16:
- dest = preview->buffer + ((gulong) y * (gulong) preview->buffer_width + (gulong) x) * 2;
- gtk_grayscale_16 (data, dest, w);
- break;
- case 24:
- case 32:
- dest = preview->buffer + ((gulong) y * (gulong) preview->buffer_width + (gulong) x) * 3;
- gtk_grayscale_24 (data, dest, w);
- break;
+ preview_class->info.lookup = g_new (guchar, 256);
+ gtk_fill_lookup_array (preview_class->info.lookup);
+ lookup = preview_class->info.lookup;
}
- break;
+ size = w * bpp;
+ src = data;
+ dst = preview->buffer + y * rowstride + x * bpp;
+ for (i = 0; i < size; i++)
+ *dst++ = lookup[*src++];
}
}
void
gtk_preview_set_gamma (double _gamma)
{
- if (!preview_info)
+ if (!preview_class)
+ preview_class = gtk_type_class (gtk_preview_get_type ());
+
+ if (preview_class->info.gamma != _gamma)
{
- preview_info = g_new0 (GtkPreviewInfo, 1);
- preview_info->nred_shades = 6;
- preview_info->ngreen_shades = 6;
- preview_info->nblue_shades = 4;
- preview_info->ngray_shades = 24;
+ preview_class->info.gamma = _gamma;
+ if (preview_class->info.lookup != NULL)
+ {
+ g_free (preview_class->info.lookup);
+ preview_class->info.lookup = NULL;
+ }
}
-
- preview_info->gamma = _gamma;
}
void
guint nblue_shades,
guint ngray_shades)
{
- if (!preview_info)
- {
- preview_info = g_new0 (GtkPreviewInfo, 1);
- preview_info->gamma = 1.0;
- }
-
- preview_info->nred_shades = nred_shades;
- preview_info->ngreen_shades = ngreen_shades;
- preview_info->nblue_shades = nblue_shades;
- preview_info->ngray_shades = ngray_shades;
+ /* unimplemented */
}
void
gtk_preview_set_install_cmap (gint _install_cmap)
{
+ /* effectively unimplemented */
install_cmap = _install_cmap;
}
void
gtk_preview_set_reserved (gint nreserved)
{
- if (!preview_info)
- preview_info = g_new0 (GtkPreviewInfo, 1);
- preview_info->nreserved = nreserved;
+ /* unimplemented */
+}
+
+void
+gtk_preview_set_dither (GtkPreview *preview,
+ GdkRgbDither dither)
+{
+ preview->dither = dither;
}
GdkVisual*
preview->buffer_width = width;
preview->buffer_height = height;
+ preview->rowstride = (preview->buffer_width * preview->bpp + 3) & -4;
preview->buffer = g_new0 (guchar,
- preview->buffer_width *
preview->buffer_height *
- preview_class->info.bpp);
- }
-}
-
-static void
-gtk_preview_get_visuals (GtkPreviewClass *klass)
-{
- static GdkVisualType types[] =
- {
- GDK_VISUAL_TRUE_COLOR,
- GDK_VISUAL_DIRECT_COLOR,
- GDK_VISUAL_TRUE_COLOR,
- GDK_VISUAL_DIRECT_COLOR,
- GDK_VISUAL_TRUE_COLOR,
- GDK_VISUAL_DIRECT_COLOR,
- GDK_VISUAL_TRUE_COLOR,
- GDK_VISUAL_DIRECT_COLOR,
- GDK_VISUAL_PSEUDO_COLOR,
- GDK_VISUAL_STATIC_COLOR,
- GDK_VISUAL_STATIC_GRAY
- };
- static gint depths[] = { 24, 24, 32, 32, 16, 16, 15, 15, 8, 4, 1 };
- static gint nvisual_types = sizeof (types) / sizeof (types[0]);
-
- int i;
-
- g_return_if_fail (klass != NULL);
-
- if (!klass->info.visual)
- for (i = 0; i < nvisual_types; i++)
- if ((klass->info.visual = gdk_visual_get_best_with_both (depths[i], types[i])))
- {
- if ((klass->info.visual->type == GDK_VISUAL_TRUE_COLOR) ||
- (klass->info.visual->type == GDK_VISUAL_DIRECT_COLOR))
- {
- klass->info.lookup_red = g_new (gulong, 256);
- klass->info.lookup_green = g_new (gulong, 256);
- klass->info.lookup_blue = g_new (gulong, 256);
-
- gtk_fill_lookup_array (klass->info.lookup_red,
- klass->info.visual->depth,
- klass->info.visual->red_shift,
- 8 - klass->info.visual->red_prec);
- gtk_fill_lookup_array (klass->info.lookup_green,
- klass->info.visual->depth,
- klass->info.visual->green_shift,
- 8 - klass->info.visual->green_prec);
- gtk_fill_lookup_array (klass->info.lookup_blue,
- klass->info.visual->depth,
- klass->info.visual->blue_shift,
- 8 - klass->info.visual->blue_prec);
- }
- break;
- }
-
- if (!klass->info.visual)
- {
- g_warning ("unable to find a suitable visual for color image display.\n");
- return;
- }
-
- /* If we are _not_ running with an installed cmap, we must run
- * with the system visual. Otherwise, we let GDK pick the visual,
- * and it makes some effort to pick a non-default visual, which
- * will hopefully provide minimum color flashing.
- */
- if ((klass->info.visual->depth == gdk_visual_get_system()->depth) &&
- (klass->info.visual->type == gdk_visual_get_system()->type) &&
- !install_cmap)
- {
- klass->info.visual = gdk_visual_get_system();
- }
-
- switch (klass->info.visual->depth)
- {
- case 1:
- case 4:
- case 8:
- klass->info.bpp = 1;
- break;
- case 15:
- case 16:
- klass->info.bpp = 2;
- break;
- case 24:
- case 32:
- klass->info.bpp = 3;
- break;
- }
-}
-
-static void
-gtk_preview_get_cmaps (GtkPreviewClass *klass)
-{
- g_return_if_fail (klass != NULL);
- g_return_if_fail (klass->info.visual != NULL);
-
- if ((klass->info.visual->type != GDK_VISUAL_TRUE_COLOR) &&
- (klass->info.visual->type != GDK_VISUAL_DIRECT_COLOR))
- {
- if (install_cmap)
- {
- klass->info.cmap = gdk_colormap_new (klass->info.visual, FALSE);
- klass->info.cmap_alloced = install_cmap;
-
- gtk_trim_cmap (klass);
- gtk_create_8_bit (klass);
- }
- else
- {
- guint nred;
- guint ngreen;
- guint nblue;
- guint ngray;
- gint set_prop;
-
- klass->info.cmap = gdk_colormap_get_system ();
-
- set_prop = TRUE;
- if (gtk_get_preview_prop (&nred, &ngreen, &nblue, &ngray))
- {
- set_prop = FALSE;
-
- klass->info.nred_shades = nred;
- klass->info.ngreen_shades = ngreen;
- klass->info.nblue_shades = nblue;
- klass->info.ngray_shades = ngray;
-
- if (klass->info.nreserved)
- {
- klass->info.reserved_pixels = g_new (gulong, klass->info.nreserved);
- if (!gdk_colors_alloc (klass->info.cmap, 0, NULL, 0,
- klass->info.reserved_pixels,
- klass->info.nreserved))
- {
- g_free (klass->info.reserved_pixels);
- klass->info.reserved_pixels = NULL;
- }
- }
- }
- else
- {
- gtk_trim_cmap (klass);
- }
-
- gtk_create_8_bit (klass);
-
- if (set_prop)
- gtk_set_preview_prop (klass->info.nred_shades,
- klass->info.ngreen_shades,
- klass->info.nblue_shades,
- klass->info.ngray_shades);
- }
- }
- else
- {
- if (klass->info.visual == gdk_visual_get_system ())
- klass->info.cmap = gdk_colormap_get_system ();
- else
- {
- klass->info.cmap = gdk_colormap_new (klass->info.visual, FALSE);
- klass->info.cmap_alloced = TRUE;
- }
-
- klass->info.nred_shades = 0;
- klass->info.ngreen_shades = 0;
- klass->info.nblue_shades = 0;
- klass->info.ngray_shades = 0;
- }
-}
-
-static void
-gtk_preview_dither_init (GtkPreviewClass *klass)
-{
- int i, j, k;
- unsigned char low_shade, high_shade;
- unsigned short index;
- long red_mult, green_mult;
- double red_matrix_width;
- double green_matrix_width;
- double blue_matrix_width;
- double gray_matrix_width;
- double red_colors_per_shade;
- double green_colors_per_shade;
- double blue_colors_per_shade;
- double gray_colors_per_shade;
- gulong *gray_pixels;
- gint shades_r, shades_g, shades_b, shades_gray;
- GtkDitherInfo *red_ordered_dither;
- GtkDitherInfo *green_ordered_dither;
- GtkDitherInfo *blue_ordered_dither;
- GtkDitherInfo *gray_ordered_dither;
- guchar ***dither_matrix;
- guchar DM[8][8] =
- {
- { 0, 32, 8, 40, 2, 34, 10, 42 },
- { 48, 16, 56, 24, 50, 18, 58, 26 },
- { 12, 44, 4, 36, 14, 46, 6, 38 },
- { 60, 28, 52, 20, 62, 30, 54, 22 },
- { 3, 35, 11, 43, 1, 33, 9, 41 },
- { 51, 19, 59, 27, 49, 17, 57, 25 },
- { 15, 47, 7, 39, 13, 45, 5, 37 },
- { 63, 31, 55, 23, 61, 29, 53, 21 }
- };
-
- if (!klass->info.visual || klass->info.visual->type != GDK_VISUAL_PSEUDO_COLOR)
- return;
-
- shades_r = klass->info.nred_shades;
- shades_g = klass->info.ngreen_shades;
- shades_b = klass->info.nblue_shades;
- shades_gray = klass->info.ngray_shades;
-
- red_mult = shades_g * shades_b;
- green_mult = shades_b;
-
- red_colors_per_shade = 255.0 / (shades_r - 1);
- red_matrix_width = red_colors_per_shade / 64;
-
- green_colors_per_shade = 255.0 / (shades_g - 1);
- green_matrix_width = green_colors_per_shade / 64;
-
- blue_colors_per_shade = 255.0 / (shades_b - 1);
- blue_matrix_width = blue_colors_per_shade / 64;
-
- gray_colors_per_shade = 255.0 / (shades_gray - 1);
- gray_matrix_width = gray_colors_per_shade / 64;
-
- /* alloc the ordered dither arrays for accelerated dithering */
-
- klass->info.dither_red = g_new (GtkDitherInfo, 256);
- klass->info.dither_green = g_new (GtkDitherInfo, 256);
- klass->info.dither_blue = g_new (GtkDitherInfo, 256);
- klass->info.dither_gray = g_new (GtkDitherInfo, 256);
-
- red_ordered_dither = klass->info.dither_red;
- green_ordered_dither = klass->info.dither_green;
- blue_ordered_dither = klass->info.dither_blue;
- gray_ordered_dither = klass->info.dither_gray;
-
- dither_matrix = g_new (guchar**, 8);
- for (i = 0; i < 8; i++)
- {
- dither_matrix[i] = g_new (guchar*, 8);
- for (j = 0; j < 8; j++)
- dither_matrix[i][j] = g_new (guchar, 65);
- }
-
- klass->info.dither_matrix = dither_matrix;
-
- /* setup the ordered_dither_matrices */
-
- for (i = 0; i < 8; i++)
- for (j = 0; j < 8; j++)
- for (k = 0; k <= 64; k++)
- dither_matrix[i][j][k] = (DM[i][j] < k) ? 1 : 0;
-
- /* setup arrays containing three bytes of information for red, green, & blue */
- /* the arrays contain :
- * 1st byte: low end shade value
- * 2nd byte: high end shade value
- * 3rd & 4th bytes: ordered dither matrix index
- */
-
- gray_pixels = klass->info.gray_pixels;
-
- for (i = 0; i < 256; i++)
- {
-
- /* setup the red information */
- {
- low_shade = (unsigned char) (i / red_colors_per_shade);
- if (low_shade == (shades_r - 1))
- low_shade--;
- high_shade = low_shade + 1;
-
- index = (unsigned short)
- (((double) i - low_shade * red_colors_per_shade) /
- red_matrix_width);
-
- low_shade *= red_mult;
- high_shade *= red_mult;
-
- red_ordered_dither[i].s[1] = index;
- red_ordered_dither[i].c[0] = low_shade;
- red_ordered_dither[i].c[1] = high_shade;
- }
-
-
- /* setup the green information */
- {
- low_shade = (unsigned char) (i / green_colors_per_shade);
- if (low_shade == (shades_g - 1))
- low_shade--;
- high_shade = low_shade + 1;
-
- index = (unsigned short)
- (((double) i - low_shade * green_colors_per_shade) /
- green_matrix_width);
-
- low_shade *= green_mult;
- high_shade *= green_mult;
-
- green_ordered_dither[i].s[1] = index;
- green_ordered_dither[i].c[0] = low_shade;
- green_ordered_dither[i].c[1] = high_shade;
- }
-
-
- /* setup the blue information */
- {
- low_shade = (unsigned char) (i / blue_colors_per_shade);
- if (low_shade == (shades_b - 1))
- low_shade--;
- high_shade = low_shade + 1;
-
- index = (unsigned short)
- (((double) i - low_shade * blue_colors_per_shade) /
- blue_matrix_width);
-
- blue_ordered_dither[i].s[1] = index;
- blue_ordered_dither[i].c[0] = low_shade;
- blue_ordered_dither[i].c[1] = high_shade;
- }
-
-
- /* setup the gray information */
- {
- low_shade = (unsigned char) (i / gray_colors_per_shade);
- if (low_shade == (shades_gray - 1))
- low_shade--;
- high_shade = low_shade + 1;
-
- index = (unsigned short)
- (((double) i - low_shade * gray_colors_per_shade) /
- gray_matrix_width);
-
- gray_ordered_dither[i].s[1] = index;
- gray_ordered_dither[i].c[0] = gray_pixels[low_shade];
- gray_ordered_dither[i].c[1] = gray_pixels[high_shade];
- }
+ preview->rowstride);
}
}
+/* This will be useful for implementing gamma. */
static void
-gtk_fill_lookup_array (gulong *array,
- int depth,
- int shift,
- int prec)
+gtk_fill_lookup_array (guchar *array)
{
double one_over_gamma;
double ind;
int val;
int i;
- if (preview_class->info.gamma != 0.0)
- one_over_gamma = 1.0 / preview_class->info.gamma;
- else
- one_over_gamma = 1.0;
+ one_over_gamma = 1.0 / preview_class->info.gamma;
for (i = 0; i < 256; i++)
{
- if (one_over_gamma == 1.0)
- array[i] = ((i >> prec) << shift);
- else
- {
- ind = (double) i / 255.0;
- val = (int) (255 * pow (ind, one_over_gamma));
- array[i] = ((val >> prec) << shift);
- }
- }
-}
-
-static void
-gtk_trim_cmap (GtkPreviewClass *klass)
-{
- gulong pixels[256];
- guint nred;
- guint ngreen;
- guint nblue;
- guint ngray;
- guint nreserved;
- guint total;
- guint tmp;
- gint success;
-
- nred = klass->info.nred_shades;
- ngreen = klass->info.ngreen_shades;
- nblue = klass->info.nblue_shades;
- ngray = klass->info.ngray_shades;
- nreserved = klass->info.nreserved;
-
- success = FALSE;
- while (!success)
- {
- total = nred * ngreen * nblue + ngray + nreserved;
-
- if (total <= 256)
- {
- if ((nred < 2) || (ngreen < 2) || (nblue < 2) || (ngray < 2))
- success = TRUE;
- else
- {
- success = gdk_colors_alloc (klass->info.cmap, 0, NULL, 0, pixels, total);
- if (success)
- {
- if (nreserved > 0)
- {
- klass->info.reserved_pixels = g_new (gulong, nreserved);
- memcpy (klass->info.reserved_pixels, pixels, sizeof (gulong) * nreserved);
- gdk_colors_free (klass->info.cmap, &pixels[nreserved],
- total - nreserved, 0);
- }
- else
- {
- gdk_colors_free (klass->info.cmap, pixels, total, 0);
- }
- }
- }
- }
-
- if (!success)
- {
- if ((nblue >= nred) && (nblue >= ngreen))
- nblue = nblue - 1;
- else if ((nred >= ngreen) && (nred >= nblue))
- nred = nred - 1;
- else
- {
- tmp = log ((gdouble)ngray) / log (2.0);
-
- if (ngreen >= tmp)
- ngreen = ngreen - 1;
- else
- ngray -= 1;
- }
- }
- }
-
- if ((nred < 2) || (ngreen < 2) || (nblue < 2) || (ngray < 2))
- {
- g_message ("Unable to allocate sufficient colormap entries.");
- g_message ("Try exiting other color intensive applications.");
- return;
- }
-
- /* If any of the shade values has changed, issue a warning */
- if ((nred != klass->info.nred_shades) ||
- (ngreen != klass->info.ngreen_shades) ||
- (nblue != klass->info.nblue_shades) ||
- (ngray != klass->info.ngray_shades))
- {
- g_message ("Not enough colors to satisfy requested color cube.");
- g_message ("Reduced color cube shades from");
- g_message ("[%d of Red, %d of Green, %d of Blue, %d of Gray] ==> [%d of Red, %d of Green, %d of Blue, %d of Gray]\n",
- klass->info.nred_shades, klass->info.ngreen_shades,
- klass->info.nblue_shades, klass->info.ngray_shades,
- nred, ngreen, nblue, ngray);
- }
-
- klass->info.nred_shades = nred;
- klass->info.ngreen_shades = ngreen;
- klass->info.nblue_shades = nblue;
- klass->info.ngray_shades = ngray;
-}
-
-static void
-gtk_create_8_bit (GtkPreviewClass *klass)
-{
- unsigned int r, g, b;
- unsigned int rv, gv, bv;
- unsigned int dr, dg, db, dgray;
- GdkColor color;
- gulong *pixels;
- double one_over_gamma;
- int i;
-
- if (!klass->info.color_pixels)
- klass->info.color_pixels = g_new (gulong, 256);
-
- if (!klass->info.gray_pixels)
- klass->info.gray_pixels = g_new (gulong, 256);
-
- if (klass->info.gamma != 0.0)
- one_over_gamma = 1.0 / klass->info.gamma;
- else
- one_over_gamma = 1.0;
-
- dr = klass->info.nred_shades - 1;
- dg = klass->info.ngreen_shades - 1;
- db = klass->info.nblue_shades - 1;
- dgray = klass->info.ngray_shades - 1;
-
- pixels = klass->info.color_pixels;
-
- for (r = 0, i = 0; r <= dr; r++)
- for (g = 0; g <= dg; g++)
- for (b = 0; b <= db; b++, i++)
- {
- rv = (unsigned int) ((r * klass->info.visual->colormap_size) / dr);
- gv = (unsigned int) ((g * klass->info.visual->colormap_size) / dg);
- bv = (unsigned int) ((b * klass->info.visual->colormap_size) / db);
- color.red = ((int) (255 * pow ((double) rv / 256.0, one_over_gamma))) * 257;
- color.green = ((int) (255 * pow ((double) gv / 256.0, one_over_gamma))) * 257;
- color.blue = ((int) (255 * pow ((double) bv / 256.0, one_over_gamma))) * 257;
-
- if (!gdk_color_alloc (klass->info.cmap, &color))
- {
- g_error ("could not initialize 8-bit combined colormap");
- return;
- }
-
- pixels[i] = color.pixel;
- }
-
-
- pixels = klass->info.gray_pixels;
-
- for (i = 0; i < (int) klass->info.ngray_shades; i++)
- {
- color.red = (i * klass->info.visual->colormap_size) / dgray;
- color.red = ((int) (255 * pow ((double) color.red / 256.0, one_over_gamma))) * 257;
- color.green = color.red;
- color.blue = color.red;
-
- if (!gdk_color_alloc (klass->info.cmap, &color))
- {
- g_error ("could not initialize 8-bit combined colormap");
- return;
- }
-
- pixels[i] = color.pixel;
- }
-}
-
-
-static void
-gtk_color_8 (guchar *src,
- guchar *dest,
- gint x,
- gint y,
- gulong width)
-{
- gulong *colors;
- GtkDitherInfo *dither_red;
- GtkDitherInfo *dither_green;
- GtkDitherInfo *dither_blue;
- GtkDitherInfo r, g, b;
- guchar **dither_matrix;
- guchar *matrix;
-
- colors = preview_class->info.color_pixels;
- dither_red = preview_class->info.dither_red;
- dither_green = preview_class->info.dither_green;
- dither_blue = preview_class->info.dither_blue;
- dither_matrix = preview_class->info.dither_matrix[y & 0x7];
-
- while (width--)
- {
- r = dither_red[src[0]];
- g = dither_green[src[1]];
- b = dither_blue[src[2]];
- src += 3;
-
- matrix = dither_matrix[x++ & 0x7];
- *dest++ = colors[(r.c[matrix[r.s[1]]] +
- g.c[matrix[g.s[1]]] +
- b.c[matrix[b.s[1]]])];
- }
-}
-
-static void
-gtk_color_16 (guchar *src,
- guchar *dest,
- gulong width)
-{
- gulong *lookup_red;
- gulong *lookup_green;
- gulong *lookup_blue;
- gulong val;
-
- lookup_red = preview_class->info.lookup_red;
- lookup_green = preview_class->info.lookup_green;
- lookup_blue = preview_class->info.lookup_blue;
-
- while (width--)
- {
- val = COLOR_COMPOSE (src[0], src[1], src[2]);
- dest[0] = val;
- dest[1] = val >> 8;
- dest += 2;
- src += 3;
- }
-}
-
-static void
-gtk_color_24 (guchar *src,
- guchar *dest,
- gulong width)
-{
- gulong *lookup_red;
- gulong *lookup_green;
- gulong *lookup_blue;
- gulong val;
-
- lookup_red = preview_class->info.lookup_red;
- lookup_green = preview_class->info.lookup_green;
- lookup_blue = preview_class->info.lookup_blue;
-
- while (width--)
- {
- val = COLOR_COMPOSE (src[0], src[1], src[2]);
- dest[0] = val;
- dest[1] = val >> 8;
- dest[2] = val >> 16;
- dest += 3;
- src += 3;
- }
-}
-
-static void
-gtk_grayscale_8 (guchar *src,
- guchar *dest,
- gint x,
- gint y,
- gulong width)
-{
- GtkDitherInfo *dither_gray;
- GtkDitherInfo gray;
- guchar **dither_matrix;
- guchar *matrix;
-
- dither_gray = preview_class->info.dither_gray;
- dither_matrix = preview_class->info.dither_matrix[y & 0x7];
-
- while (width--)
- {
- gray = dither_gray[*src++];
- matrix = dither_matrix[x++ & 0x7];
- *dest++ = gray.c[matrix[gray.s[1]]];
- }
-}
-
-static void
-gtk_grayscale_16 (guchar *src,
- guchar *dest,
- gulong width)
-{
- gulong *lookup_red;
- gulong *lookup_green;
- gulong *lookup_blue;
- gulong val;
-
- lookup_red = preview_class->info.lookup_red;
- lookup_green = preview_class->info.lookup_green;
- lookup_blue = preview_class->info.lookup_blue;
-
- while (width--)
- {
- val = COLOR_COMPOSE (*src, *src, *src);
- dest[0] = val;
- dest[1] = val >> 8;
- dest += 2;
- src += 1;
- }
-}
-
-static void
-gtk_grayscale_24 (guchar *src,
- guchar *dest,
- gulong width)
-{
- gulong *lookup_red;
- gulong *lookup_green;
- gulong *lookup_blue;
- gulong val;
-
- lookup_red = preview_class->info.lookup_red;
- lookup_green = preview_class->info.lookup_green;
- lookup_blue = preview_class->info.lookup_blue;
-
- while (width--)
- {
- val = COLOR_COMPOSE (*src, *src, *src);
- dest[0] = val;
- dest[1] = val >> 8;
- dest[2] = val >> 16;
- dest += 3;
- src += 1;
- }
-}
-
-
-static gint
-gtk_get_preview_prop (guint *nred,
- guint *ngreen,
- guint *nblue,
- guint *ngray)
-{
- GtkPreviewProp *prop;
- GdkAtom property;
-
- /* FIXME: need to grab the server here to prevent a race condition */
-
- property = gdk_atom_intern ("GTK_PREVIEW_INFO", FALSE);
-
- if (gdk_property_get (NULL, property, property,
- 0, sizeof (GtkPreviewProp), FALSE,
- NULL, NULL, NULL, (guchar**) &prop))
- {
- *nred = prop->nred_shades;
- *ngreen = prop->ngreen_shades;
- *nblue = prop->nblue_shades;
- *ngray = prop->ngray_shades;
-
- prop->ref_count = prop->ref_count + 1;
- gdk_property_change (NULL, property, property, 16,
- GDK_PROP_MODE_REPLACE,
- (guchar*) prop, 5);
-
- return TRUE;
- }
-
- return FALSE;
-}
-
-static void
-gtk_set_preview_prop (guint nred,
- guint ngreen,
- guint nblue,
- guint ngray)
-{
- GtkPreviewProp prop;
- GdkAtom property;
-
- property = gdk_atom_intern ("GTK_PREVIEW_INFO", FALSE);
-
- prop.ref_count = 1;
- prop.nred_shades = nred;
- prop.ngreen_shades = ngreen;
- prop.nblue_shades = nblue;
- prop.ngray_shades = ngray;
-
- gdk_property_change (NULL, property, property, 16,
- GDK_PROP_MODE_REPLACE,
- (guchar*) &prop, 5);
-}
-
-
-static void
-gtk_lsbmsb_1_1 (guchar *dest,
- guchar *src,
- gint count)
-{
- memcpy (dest, src, count);
-}
-
-static void
-gtk_lsb_2_2 (guchar *dest,
- guchar *src,
- gint count)
-{
- memcpy (dest, src, count * 2);
-}
-
-static void
-gtk_msb_2_2 (guchar *dest,
- guchar *src,
- gint count)
-{
- while (count--)
- {
- dest[0] = src[1];
- dest[1] = src[0];
- dest += 2;
- src += 2;
- }
-}
-
-static void
-gtk_lsb_3_3 (guchar *dest,
- guchar *src,
- gint count)
-{
- memcpy (dest, src, count * 3);
-}
-
-static void
-gtk_msb_3_3 (guchar *dest,
- guchar *src,
- gint count)
-{
- while (count--)
- {
- dest[0] = src[2];
- dest[1] = src[1];
- dest[2] = src[0];
- dest += 3;
- src += 3;
- }
-}
-
-static void
-gtk_lsb_3_4 (guchar *dest,
- guchar *src,
- gint count)
-{
- while (count--)
- {
- dest[0] = src[0];
- dest[1] = src[1];
- dest[2] = src[2];
- dest += 4;
- src += 3;
- }
-}
-
-static void
-gtk_msb_3_4 (guchar *dest,
- guchar *src,
- gint count)
-{
- while (count--)
- {
- dest[1] = src[2];
- dest[2] = src[1];
- dest[3] = src[0];
- dest += 4;
- src += 3;
+ ind = (double) i / 255.0;
+ val = (int) (255 * pow (ind, one_over_gamma));
+ array[i] = val;
}
}