/* * cmrender.c -- image w/ colormap renderer for enfle * (C)Copyright 1998, 98 by Hiroshi Takekawa * This file is part of Enfle. * * Last Modified: Sat Feb 19 18:24:04 2000. * $Id: cmrender.c,v 1.6 2000/02/19 09:30:08 sian Exp $ * * Enfle 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. * * Enfle 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #include "enfle.h" #include "cmrender.h" const char *cmrender_err[] = { "Rendering success", "Can't allocate enough color cells", "Unsupported pixel", "Can't store color", "Can't alloc color" }; int render_image_colormap(Info *info, Image *p, void *dist, int bits_per_pixel, int bytes_per_line) { Display *disp = info->disp; Window win = info->win; Visual *visual = info->visual; Colormap cm = DefaultColormap(disp, 0); XColor xc; unsigned long mask, pixel[256]; int i, j, k = 0; if (visual->class == GrayScale || visual->class == PseudoColor || visual->class == DirectColor) { /* GrayScale or PserdoColor or DirectColor */ if (XAllocColorCells(disp, cm, False, &mask, 0, pixel, p->ncolors) == False) { /* Create my own colormap and retry... */ cm = XCreateColormap(disp, RootWindow(disp, 0), visual, AllocNone); if (XAllocColorCells(disp, cm, False, &mask, 0, pixel, p->ncolors) == False) return CANTALLOCCELLS; XSetWindowColormap(disp, win, cm); XInstallColormap(disp, cm); } for (i = 0; i < p->ncolors; i++) { xc.red = p->colormap[i][0] << 8; xc.green = p->colormap[i][1] << 8; xc.blue = p->colormap[i][2] << 8; xc.pixel = pixel[i]; xc.flags = DoRed | DoGreen | DoBlue; if (XStoreColor(disp, cm, &xc) == False) return CANTSTORECOLOR; } } else { /* StaticColor or StaticGray or TrueColor */ for (i = 0; i < p->ncolors; i++) { xc.red = p->colormap[i][0] << 8; xc.green = p->colormap[i][1] << 8; xc.blue = p->colormap[i][2] << 8; if (XAllocColor(disp, cm, &xc) == False) return CANTALLOCCOLOR; pixel[i] = xc.pixel; } } switch (bits_per_pixel) { case 8: { unsigned char *data; data = (unsigned char *)dist; data += p->top * info->xwidth + p->left; if (p->transparent_disposal == _DONOTHING) { for (i = 0; i < p->height; i++) { for (j = 0; j < p->width; j++) data[j] = (unsigned char)pixel[(int)p->image[k++]]; data += bytes_per_line; } } else { /* Transparent */ int pix; for (i = 0; i < p->height; i++) { for (j = 0; j < p->width; j++) if ((pix = (int)p->image[k++]) != p->transparent.index) data[j] = (unsigned char)pixel[pix]; data += bytes_per_line; } } } break; case 16: { unsigned short *data; data = (unsigned short *)dist; data += p->top * info->xwidth + p->left; if (p->transparent_disposal == _DONOTHING) { for (i = 0; i < p->height; i++) { for (j = 0; j < p->width; j++) data[j] = (unsigned short)pixel[(int)p->image[k++]]; data += bytes_per_line >> 1; } } else { /* Transparent */ int pix; for (i = 0; i < p->height; i++) { for (j = 0; j < p->width; j++) if ((pix = (int)p->image[k++]) != p->transparent.index) data[j] = (unsigned short)pixel[pix]; data += bytes_per_line >> 1; } } } break; case 24: { unsigned char *data; int pix; data = (unsigned char *)dist; data += (p->top * info->xwidth + p->left) * 3; if (p->transparent_disposal == _DONOTHING) { for (i = 0; i < p->height; i++) { for (j = 0; j < p->width; j++) { pix = (int)p->image[k++]; #ifndef WORDS_BIGENDIAN data[j * 3 + 0] = (unsigned char)pixel[pix]; data[j * 3 + 1] = (unsigned char)(pixel[pix] >> 8); data[j * 3 + 2] = (unsigned char)(pixel[pix] >> 16); #else data[j * 3 + 2] = (unsigned char)pixel[pix]; data[j * 3 + 1] = (unsigned char)(pixel[pix] >> 8); data[j * 3 + 0] = (unsigned char)(pixel[pix] >> 16); #endif } data += bytes_per_line; } } else { for (i = 0; i < p->height; i++) { for (j = 0; j < p->width; j++) if ((pix = (int)p->image[k++]) != p->transparent.index) { #ifndef WORDS_BIGENDIAN data[j * 3 + 0] = (unsigned char)pixel[pix]; data[j * 3 + 1] = (unsigned char)(pixel[pix] >> 8); data[j * 3 + 2] = (unsigned char)(pixel[pix] >> 16); #else data[j * 3 + 0] = (unsigned char)(pixel[pix] >> 16); data[j * 3 + 1] = (unsigned char)(pixel[pix] >> 8); data[j * 3 + 2] = (unsigned char)pixel[pix]; #endif } data += bytes_per_line; } } } break; case 32: { unsigned char *data; int pix; data = (unsigned char *)dist; data += (p->top * info->xwidth + p->left) * 4; if (p->transparent_disposal == _DONOTHING) { #ifdef DEBUG fprintf(stderr, "%d %d %d %d %d\n", info->xdata_size, info->xwidth, info->xheight, p->width, p->height); #endif for (i = 0; i < p->height; i++) { for (j = 0; j < p->width; j++) { pix = (int)p->image[k++]; #ifndef WORDS_BIGENDIAN data[j * 4 + 0] = (unsigned char)pixel[pix]; data[j * 4 + 1] = (unsigned char)(pixel[pix] >> 8); data[j * 4 + 2] = (unsigned char)(pixel[pix] >> 16); data[j * 4 + 3] = (unsigned char)0; #else data[j * 4 + 3] = (unsigned char)pixel[pix]; data[j * 4 + 2] = (unsigned char)(pixel[pix] >> 8); data[j * 4 + 1] = (unsigned char)(pixel[pix] >> 16); data[j * 4 + 0] = (unsigned char)0; #endif } data += bytes_per_line; } } else { for (i = 0; i < p->height; i++) { for (j = 0; j < p->width; j++) if ((pix = (int)p->image[k++]) != p->transparent.index) { #ifndef WORDS_BIGENDIAN data[j * 4 + 0] = (unsigned char)pixel[pix]; data[j * 4 + 1] = (unsigned char)(pixel[pix] >> 8); data[j * 4 + 2] = (unsigned char)(pixel[pix] >> 16); data[j * 4 + 3] = (unsigned char)0; #else data[j * 4 + 3] = (unsigned char)pixel[pix]; data[j * 4 + 2] = (unsigned char)(pixel[pix] >> 8); data[j * 4 + 1] = (unsigned char)(pixel[pix] >> 16); data[j * 4 + 0] = (unsigned char)0; #endif } data += bytes_per_line; } } } break; default: fprintf(stderr, "Invalid bits_per_pixel: %d\n", bits_per_pixel); return UNSUPPORTEDPIXEL; } return RENDERSUCCESS; }