/*
* colors.c
*
* Copyright (C) 1997,98 Rasca, Berlin
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include "colors.h"
#ifndef max
#define max(a,b) (a>b? a:b)
#endif
#ifndef min
#define min(a,b) (a<b? a:b)
#endif
/*
* ..
*/
int
xvc_get_colors(Display * dpy, XWindowAttributes * winfo, XColor ** colors)
{
# define lowbit(x) ((x) & (~(x) + 1))
int ncolors, i;
Visual *visual;
visual = winfo->visual;
ncolors = visual->map_entries;
if (*colors)
free(*colors);
*colors = (XColor *) malloc(sizeof(XColor) * ncolors);
if (!*colors) {
perror("GetColors()");
return (0);
}
if ((visual->class == DirectColor) || (visual->class == TrueColor)) {
Pixel red, green, blue, red0, green0, blue0;
#ifdef DEBUG
printf("GetColors() Direct- or TrueColor (%d)\n", ncolors);
#endif
red = green = blue = 0;
red0 = lowbit(visual->red_mask);
green0 = lowbit(visual->green_mask);
blue0 = lowbit(visual->blue_mask);
for (i = 0; i < ncolors; i++) {
(*colors)[i].pixel = red | green | blue;
(*colors)[i].pad = 0;
red += red0;
if (red > visual->red_mask)
red = 0;
green += green0;
if (green > visual->green_mask)
green = 0;
blue += blue0;
if (blue > visual->blue_mask)
blue = 0;
}
} else {
for (i = 0; i < ncolors; i++) {
(*colors)[i].pixel = i;
(*colors)[i].pad = 0;
}
}
XQueryColors(dpy, winfo->colormap, *colors, ncolors);
#ifdef DEBUG2
for (i = 0; i < ncolors; i++) {
printf("color[%d] pixel:%ld red:%d green:%d blue:%d\n", i,
(*colors)[i].pixel,
(*colors)[i].red, (*colors)[i].green, (*colors)[i].blue);
}
#endif
return (ncolors);
}
/*
* fill the 'ci' structure with some usefull information
* we need to process the color values in the ximage->data
* field
*/
void
xvc_get_color_info(XImage * image, ColorInfo * ci /* return struct */ )
{
unsigned long red_mask, green_mask, blue_mask, alpha_mask;
// the shifts are unsigned longs as well
if (!ci)
return;
// setting shifts and bit_depths to zero
ci->red_shift = ci->green_shift = ci->blue_shift = ci->alpha_shift = 0;
ci->red_bit_depth = ci->green_bit_depth = ci->blue_bit_depth =
ci->alpha_bit_depth = 0;
red_mask = image->red_mask;
if (red_mask > 0) {
// shift red_mask to the right till all empty bits have been
// shifted out and count how many they were
while ((red_mask & 0x01) == 0) {
red_mask >>= 1;
ci->red_shift++;
}
// count how many bits are set in the mask = depth
while ((red_mask & 0x01) == 1) {
red_mask >>= 1;
ci->red_bit_depth++;
}
}
// why don't I just set this above when 0 bits are shifted out of the
// mask??????
ci->red_max_val = (1 << ci->red_bit_depth) - 1;
green_mask = image->green_mask;
if (green_mask > 0) {
while ((green_mask & 0x01) == 0) {
green_mask >>= 1;
ci->green_shift++;
}
while ((green_mask & 0x01) == 1) {
green_mask >>= 1;
ci->green_bit_depth++;
}
}
ci->green_max_val = (1 << ci->green_bit_depth) - 1;
blue_mask = image->blue_mask;
if (blue_mask > 0) {
while ((blue_mask & 0x01) == 0) {
blue_mask >>= 1;
ci->blue_shift++;
}
while ((blue_mask & 0x01) == 1) {
blue_mask >>= 1;
ci->blue_bit_depth++;
}
}
ci->blue_max_val = (1 << ci->blue_bit_depth) - 1;
/*
* over all max values
*/
// whatever they are good for
ci->max_val = max(ci->red_max_val, ci->green_max_val);
ci->max_val = max(ci->blue_max_val, ci->max_val);
ci->bit_depth = max(ci->red_bit_depth, ci->green_bit_depth);
ci->bit_depth = max(ci->blue_bit_depth, ci->bit_depth);
if (image->bits_per_pixel > image->depth) {
/*
* alpha?
*/
// this seems to not reflect X's ignorance of alpha in its
// masks
ci->alpha_mask = ~
(image->red_mask | image->blue_mask | image->green_mask);
alpha_mask = ci->alpha_mask;
if (alpha_mask > 0) {
while ((alpha_mask & 0x01) == 0) {
alpha_mask >>= 1;
ci->alpha_shift++;
}
while ((alpha_mask & 0x01) == 1) {
alpha_mask >>= 1;
ci->alpha_bit_depth++;
}
}
ci->alpha_max_val = (1 << ci->alpha_bit_depth) - 1;
}
#ifdef DEBUG2
printf("rgb mask %08x bit_depth %lu max_val %lu\n",
(uint) (image->red_mask | image->green_mask | image->blue_mask),
ci->bit_depth, ci->max_val);
printf("red mask %08x bit_depth %lu shift %lu max_val %lu\n",
(uint) (image->red_mask), ci->red_bit_depth, ci->red_shift,
ci->red_max_val);
printf("green mask %08x bit_depth %lu shift %lu max_val %lu\n",
(uint) (image->green_mask), ci->green_bit_depth,
ci->green_shift, ci->green_max_val);
printf("blue mask %08x bit_depth %lu shift %lu max_val %lu\n",
(uint) (image->blue_mask), ci->blue_bit_depth, ci->blue_shift,
ci->blue_max_val);
printf("alpha mask %08x bit_depth %lu shift %lu max_val %lu\n",
ci->alpha_mask, ci->alpha_bit_depth, ci->alpha_shift,
ci->alpha_max_val);
#endif
}
syntax highlighted by Code2HTML, v. 0.9.1