From: Derek Foreman Date: Sun, 6 Apr 2003 04:03:05 +0000 (+0000) Subject: added superb pseudo-color (8bpp) support X-Git-Url: https://git.dogcows.com/gitweb?a=commitdiff_plain;h=214fa8714ea0d2182c155eeb4b32ec32d7df337f;p=chaz%2Fopenbox added superb pseudo-color (8bpp) support --- diff --git a/render/color.c b/render/color.c index 0d3f8132..d5821c87 100644 --- a/render/color.c +++ b/render/color.c @@ -3,6 +3,10 @@ #include "render.h" #include "color.h" #include "../kernel/openbox.h" + +XColor *pseudo_colors; +int pseudo_bpc; + void color_allocate_gc(color_rgb *in) { XGCValues gcv; @@ -65,7 +69,8 @@ void reduce_depth(pixel32 *data, XImage *im) array*/ int r, g, b; int x,y; - pixel16 *p = (pixel16*) data; + pixel16 *p16 = (pixel16*) data; + unsigned char *p8 = (unsigned char *)data; switch (im->bits_per_pixel) { case 32: if ((render_red_offset != default_red_shift) || @@ -92,15 +97,35 @@ void reduce_depth(pixel32 *data, XImage *im) g = g >> render_green_shift; b = (data[x] >> default_blue_shift) & 0xFF; b = b >> render_blue_shift; - p[x] = (r << render_red_offset) + p16[x] = (r << render_red_offset) + (g << render_green_offset) + (b << render_blue_offset); } data += im->width; - p += im->bytes_per_line/2; + p16 += im->bytes_per_line/2; } - break; + break; + case 8: + g_assert(render_visual->class != TrueColor); + for (y = 0; y < im->height; y++) { + for (x = 0; x < im->width; x++) { + p8[x] = pickColor(data[x] >> default_red_shift, + data[x] >> default_green_shift, + data[x] >> default_blue_shift)->pixel; + } + data += im->width; + p8 += im->bytes_per_line; + } + + break; default: g_message("your bit depth is currently unhandled\n"); } } +XColor *pickColor(int r, int g, int b) +{ + r = (r & 0xff) >> (8-pseudo_bpc); + g = (g & 0xff) >> (8-pseudo_bpc); + b = (b & 0xff) >> (8-pseudo_bpc); + return &pseudo_colors[(r << (2*pseudo_bpc)) + (g << (1*pseudo_bpc)) + b]; +} diff --git a/render/color.h b/render/color.h index 202817d3..3114f4c7 100644 --- a/render/color.h +++ b/render/color.h @@ -43,6 +43,7 @@ typedef struct color_rgb { } color_rgb; void color_allocate_gc(color_rgb *in); +XColor *pickColor(int r, int g, int b); color_rgb *color_parse(char *colorname); color_rgb *color_new(int r, int g, int b); void color_free(color_rgb *in); @@ -56,4 +57,6 @@ extern int render_red_shift; extern int render_green_shift; extern int render_blue_shift; +extern int pseudo_bpc; +extern XColor *pseudo_colors; #endif /* __color_h */ diff --git a/render/render.c b/render/render.c index babfa522..71bf7fa3 100644 --- a/render/render.c +++ b/render/render.c @@ -56,7 +56,21 @@ void render_startup(void) } XFree(vinfo_return); } - truecolor_startup(); + switch (render_visual->class) { + case TrueColor: + truecolor_startup(); + break; + case PseudoColor: + case StaticColor: + case GrayScale: + case StaticGray: + pseudocolor_startup(); + break; + default: + g_critical("unsupported visual class.\n"); + exit(EXIT_FAILURE); + + } } void truecolor_startup(void) @@ -87,6 +101,89 @@ void truecolor_startup(void) XFree(timage); } +void pseudocolor_startup(void) +{ + XColor icolors[256]; + int tr, tg, tb, n, r, g, b, i, incolors, ii; + unsigned long dev; + int cpc, _ncolors; + g_message("Initializing PseudoColor RenderControl\n"); + + /* determine the number of colors and the bits-per-color */ + pseudo_bpc = 2; /* XXX THIS SHOULD BE A USER OPTION */ + g_assert(pseudo_bpc >= 1); + _ncolors = 1 << (pseudo_bpc * 3); + + if (_ncolors > 1 << render_depth) { + g_warning("PseudoRenderControl: Invalid colormap size. Resizing.\n"); + pseudo_bpc = 1 << (render_depth/3) >> 3; + _ncolors = 1 << (pseudo_bpc * 3); + } + + /* build a color cube */ + pseudo_colors = malloc(_ncolors * sizeof(XColor)); + cpc = 1 << pseudo_bpc; /* colors per channel */ + + for (n = 0, r = 0; r < cpc; r++) + for (g = 0; g < cpc; g++) + for (b = 0; b < cpc; b++, n++) { + tr = (int)(((float)(r)/(float)(cpc-1)) * 0xFF); + tg = (int)(((float)(g)/(float)(cpc-1)) * 0xFF); + tb = (int)(((float)(b)/(float)(cpc-1)) * 0xFF); + pseudo_colors[n].red = tr | tr << 8; + pseudo_colors[n].green = tg | tg << 8; + pseudo_colors[n].blue = tb | tb << 8; + pseudo_colors[n].flags = DoRed|DoGreen|DoBlue; /* used to track + allocation */ + } + + /* allocate the colors */ + for (i = 0; i < _ncolors; i++) + if (!XAllocColor(ob_display, render_colormap, &pseudo_colors[i])) + pseudo_colors[i].flags = 0; /* mark it as unallocated */ + + /* try allocate any colors that failed allocation above */ + + /* get the allocated values from the X server (only the first 256 XXX why!?) + */ + incolors = (((1 << render_depth) > 256) ? 256 : (1 << render_depth)); + for (i = 0; i < incolors; i++) + icolors[i].pixel = i; + XQueryColors(ob_display, render_colormap, icolors, incolors); + + /* try match unallocated ones */ + for (i = 0; i < _ncolors; i++) { + if (!pseudo_colors[i].flags) { /* if it wasn't allocated... */ + unsigned long closest = 0xffffffff, close = 0; + for (ii = 0; ii < incolors; ii++) { + /* find deviations */ + r = (pseudo_colors[i].red - icolors[ii].red) & 0xff; + g = (pseudo_colors[i].green - icolors[ii].green) & 0xff; + b = (pseudo_colors[i].blue - icolors[ii].blue) & 0xff; + /* find a weighted absolute deviation */ + dev = (r * r) + (g * g) + (b * b); + + if (dev < closest) { + closest = dev; + close = ii; + } + } + + pseudo_colors[i].red = icolors[close].red; + pseudo_colors[i].green = icolors[close].green; + pseudo_colors[i].blue = icolors[close].blue; + pseudo_colors[i].pixel = icolors[close].pixel; + + /* try alloc this closest color, it had better succeed! */ + if (XAllocColor(ob_display, render_colormap, &pseudo_colors[i])) + pseudo_colors[i].flags = DoRed|DoGreen|DoBlue; /* mark as alloced */ + else + g_assert(FALSE); /* wtf has gone wrong, its already alloced for + chissake! */ + } + } +} + void x_paint(Window win, Appearance *l) { int i, transferred = 0, sw; diff --git a/render/render.h b/render/render.h index c614d871..e282740e 100644 --- a/render/render.h +++ b/render/render.h @@ -153,6 +153,7 @@ Appearance *appearance_new(SurfaceType type, int numtex); Appearance *appearance_copy(Appearance *a); void appearance_free(Appearance *a); void truecolor_startup(void); +void pseudocolor_startup(void); void pixel32_to_pixmap(pixel32 *in, Pixmap out, int x, int y, int w, int h); #endif /*__render_h*/