📄 image.cc
字号:
// Image.cc for Blackbox - an X11 Window manager// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)//// Permission is hereby granted, free of charge, to any person obtaining a// copy of this software and associated documentation files (the "Software"),// to deal in the Software without restriction, including without limitation// the rights to use, copy, modify, merge, publish, distribute, sublicense,// and/or sell copies of the Software, and to permit persons to whom the// Software is furnished to do so, subject to the following conditions://// The above copyright notice and this permission notice shall be included in// all copies or substantial portions of the Software.//// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER// DEALINGS IN THE SOFTWARE.// stupid macros needed to access some functions in version 2 of the GNU C// library#ifndef _GNU_SOURCE#define _GNU_SOURCE#endif // _GNU_SOURCE#ifdef HAVE_CONFIG_H# include "config.h"#endif // HAVE_CONFIG_H#include "BaseDisplay.hh"#include "Image.hh"#ifdef HAVE_SYS_TYPES_H# include <sys/types.h>#endif // HAVE_SYS_TYPES_H#ifndef u_int32_t# ifdef uint_32_ttypedef uint32_t u_int32_t;# else# ifdef __uint32_ttypedef __uint32_t u_int32_t;# elsetypedef unsigned int u_int32_t;# endif# endif#endif#ifdef STDC_HEADERS# include <stdlib.h># include <string.h>#endif // STDC_HEADERS#ifdef HAVE_STDIO_H# include <stdio.h>#endif // HAVE_STDIO_H#ifdef HAVE_CTYPE_H# include <ctype.h>#endif // HAVE_CTYPE_Hstatic unsigned long bsqrt(unsigned long x){ if (x <= 0) return 0; if (x == 1) return 1; unsigned long r = x >> 1; unsigned long q; while (1) { q = x / r; if (q >= r) return r; r = (r + q) >> 1; }}BImage::BImage(BImageControl *c, unsigned int w, unsigned int h){ control = c; width = ((signed) w > 0) ? w : 1; height = ((signed) h > 0) ? h : 1; red = new unsigned char[width * height]; green = new unsigned char[width * height]; blue = new unsigned char[width * height]; xtable = ytable = (unsigned int *) 0; cpc = control->getColorsPerChannel(); cpccpc = cpc * cpc; control->getColorTables(&red_table, &green_table, &blue_table, &red_offset, &green_offset, &blue_offset, &red_bits, &green_bits, &blue_bits); if (control->getVisual()->c_class != TrueColor) control->getXColorTable(&colors, &ncolors);}BImage::~BImage(void){ if (red) delete [] red; if (green) delete [] green; if (blue) delete [] blue;}Pixmap BImage::render(BTexture *texture){ if (texture->getTexture() & BImage_ParentRelative) return ParentRelative; else if (texture->getTexture() & BImage_Solid) return render_solid(texture); else if (texture->getTexture() & BImage_Gradient) return render_gradient(texture); return None;}Pixmap BImage::render_solid(BTexture *texture){ Pixmap pixmap = XCreatePixmap(control->getBaseDisplay()->getXDisplay(), control->getDrawable(), width, height, control->getDepth()); if (pixmap == None) { fprintf(stderr, "BImage::render_solid: error creating pixmap\n"); return None; } XGCValues gcv; GC gc, hgc, lgc; gcv.foreground = texture->getColor()->getPixel(); gcv.fill_style = FillSolid; gc = XCreateGC(control->getBaseDisplay()->getXDisplay(), pixmap, GCForeground | GCFillStyle, &gcv); gcv.foreground = texture->getHiColor()->getPixel(); hgc = XCreateGC(control->getBaseDisplay()->getXDisplay(), pixmap, GCForeground, &gcv); gcv.foreground = texture->getLoColor()->getPixel(); lgc = XCreateGC(control->getBaseDisplay()->getXDisplay(), pixmap, GCForeground, &gcv); XFillRectangle(control->getBaseDisplay()->getXDisplay(), pixmap, gc, 0, 0, width, height);#ifdef INTERLACE if (texture->getTexture() & BImage_Interlaced) { gcv.foreground = texture->getColorTo()->getPixel(); GC igc = XCreateGC(control->getBaseDisplay()->getXDisplay(), pixmap, GCForeground, &gcv); register unsigned int i = 0; for (; i < height; i += 2) XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, igc, 0, i, width, i); XFreeGC(control->getBaseDisplay()->getXDisplay(), igc); }#endif // INTERLACE if (texture->getTexture() & BImage_Bevel1) { if (texture->getTexture() & BImage_Raised) { XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, lgc, 0, height - 1, width - 1, height - 1); XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, lgc, width - 1, height - 1, width - 1, 0); XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, hgc, 0, 0, width - 1, 0); XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, hgc, 0, height - 1, 0, 0); } else if (texture->getTexture() & BImage_Sunken) { XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, hgc, 0, height - 1, width - 1, height - 1); XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, hgc, width - 1, height - 1, width - 1, 0); XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, lgc, 0, 0, width - 1, 0); XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, lgc, 0, height - 1, 0, 0); } } else if (texture->getTexture() & BImage_Bevel2) { if (texture->getTexture() & BImage_Raised) { XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, lgc, 1, height - 3, width - 3, height - 3); XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, lgc, width - 3, height - 3, width - 3, 1); XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, hgc, 1, 1, width - 3, 1); XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, hgc, 1, height - 3, 1, 1); } else if (texture->getTexture() & BImage_Sunken) { XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, hgc, 1, height - 3, width - 3, height - 3); XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, hgc, width - 3, height - 3, width - 3, 1); XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, lgc, 1, 1, width - 3, 1); XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, lgc, 1, height - 3, 1, 1); } } XFreeGC(control->getBaseDisplay()->getXDisplay(), gc); XFreeGC(control->getBaseDisplay()->getXDisplay(), hgc); XFreeGC(control->getBaseDisplay()->getXDisplay(), lgc); return pixmap;}Pixmap BImage::render_gradient(BTexture *texture){ int inverted = 0;#ifdef INTERLACE interlaced = texture->getTexture() & BImage_Interlaced;#endif // INTERLACE if (texture->getTexture() & BImage_Sunken) { from = texture->getColorTo(); to = texture->getColor(); if (! (texture->getTexture() & BImage_Invert)) inverted = 1; } else { from = texture->getColor(); to = texture->getColorTo(); if (texture->getTexture() & BImage_Invert) inverted = 1; } control->getGradientBuffers(width, height, &xtable, &ytable); if (texture->getTexture() & BImage_Diagonal) dgradient(); else if (texture->getTexture() & BImage_Elliptic) egradient(); else if (texture->getTexture() & BImage_Horizontal) hgradient(); else if (texture->getTexture() & BImage_Pyramid) pgradient(); else if (texture->getTexture() & BImage_Rectangle) rgradient(); else if (texture->getTexture() & BImage_Vertical) vgradient(); else if (texture->getTexture() & BImage_CrossDiagonal) cdgradient(); else if (texture->getTexture() & BImage_PipeCross) pcgradient(); if (texture->getTexture() & BImage_Bevel1) bevel1(); else if (texture->getTexture() & BImage_Bevel2) bevel2(); if (inverted) invert(); Pixmap pixmap = renderPixmap(); return pixmap;}XImage *BImage::renderXImage(void){ XImage *image = XCreateImage(control->getBaseDisplay()->getXDisplay(), control->getVisual(), control->getDepth(), ZPixmap, 0, 0, width, height, 32, 0); if (! image) { fprintf(stderr, "BImage::renderXImage: error creating XImage\n"); return (XImage *) 0; } // insurance policy image->data = (char *) 0; unsigned char *d = new unsigned char[image->bytes_per_line * (height + 1)]; register unsigned int x, y, dithx, dithy, r, g, b, o, er, eg, eb, offset; unsigned char *pixel_data = d, *ppixel_data = d; unsigned long pixel; o = image->bits_per_pixel + ((image->byte_order == MSBFirst) ? 1 : 0); if (control->doDither() && width > 1 && height > 1) { unsigned char dither4[4][4] = { {0, 4, 1, 5}, {6, 2, 7, 3}, {1, 5, 0, 4}, {7, 3, 6, 2} };#ifdef ORDEREDPSEUDO unsigned char dither8[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 } };#endif // ORDEREDPSEUDO switch (control->getVisual()->c_class) { case TrueColor: // algorithm: ordered dithering... many many thanks to rasterman // (raster@rasterman.com) for telling me about this... portions of this // code is based off of his code in Imlib for (y = 0, offset = 0; y < height; y++) { dithy = y & 0x3; for (x = 0; x < width; x++, offset++) { dithx = x & 0x3; r = red[offset]; g = green[offset]; b = blue[offset]; er = r & (red_bits - 1); eg = g & (green_bits - 1); eb = b & (blue_bits - 1); r = red_table[r]; g = green_table[g]; b = blue_table[b]; if ((dither4[dithy][dithx] < er) && (r < red_table[255])) r++; if ((dither4[dithy][dithx] < eg) && (g < green_table[255])) g++; if ((dither4[dithy][dithx] < eb) && (b < blue_table[255])) b++; pixel = (r << red_offset) | (g << green_offset) | (b << blue_offset); switch (o) { case 16: // 16bpp LSB *pixel_data++ = pixel; *pixel_data++ = pixel >> 8; break; case 17: // 16bpp MSB *pixel_data++ = pixel >> 8; *pixel_data++ = pixel; break; case 24: // 24bpp LSB *pixel_data++ = pixel; *pixel_data++ = pixel >> 8; *pixel_data++ = pixel >> 16; break; case 25: // 24bpp MSB *pixel_data++ = pixel >> 16; *pixel_data++ = pixel >> 8; *pixel_data++ = pixel; break; case 32: // 32bpp LSB *pixel_data++ = pixel; *pixel_data++ = pixel >> 8; *pixel_data++ = pixel >> 16; *pixel_data++ = pixel >> 24; break; case 33: // 32bpp MSB *pixel_data++ = pixel >> 24; *pixel_data++ = pixel >> 16; *pixel_data++ = pixel >> 8; *pixel_data++ = pixel; break; } } pixel_data = (ppixel_data += image->bytes_per_line); } break; case StaticColor: case PseudoColor: {#ifndef ORDEREDPSEUDO short *terr, *rerr = new short[width + 2], *gerr = new short[width + 2], *berr = new short[width + 2], *nrerr = new short[width + 2], *ngerr = new short[width + 2], *nberr = new short[width + 2]; int rr, gg, bb, rer, ger, ber; int dd = 255 / control->getColorsPerChannel(); for (x = 0; x < width; x++) { *(rerr + x) = *(red + x); *(gerr + x) = *(green + x); *(berr + x) = *(blue + x); } *(rerr + x) = *(gerr + x) = *(berr + x) = 0;#endif // ORDEREDPSEUDO for (y = 0, offset = 0; y < height; y++) {#ifdef ORDEREDPSEUDO dithy = y & 7; for (x = 0; x < width; x++, offset++) { dithx = x & 7; r = red[offset]; g = green[offset]; b = blue[offset]; er = r & (red_bits - 1); eg = g & (green_bits - 1); eb = b & (blue_bits - 1); r = red_table[r]; g = green_table[g]; b = blue_table[b]; if ((dither8[dithy][dithx] < er) && (r < red_table[255])) r++; if ((dither8[dithy][dithx] < eg) && (g < green_table[255])) g++; if ((dither8[dithy][dithx] < eb) && (b < blue_table[255])) b++; pixel = (r * cpccpc) + (g * cpc) + b; *(pixel_data++) = colors[pixel].pixel; } pixel_data = (ppixel_data += image->bytes_per_line); }#else // !ORDEREDPSEUDO if (y < (height - 1)) { int i = offset + width; for (x = 0; x < width; x++, i++) { *(nrerr + x) = *(red + i); *(ngerr + x) = *(green + i); *(nberr + x) = *(blue + i); } *(nrerr + x) = *(red + (--i)); *(ngerr + x) = *(green + i); *(nberr + x) = *(blue + i); } for (x = 0; x < width; x++) { rr = rerr[x]; gg = gerr[x]; bb = berr[x]; if (rr > 255) rr = 255; else if (rr < 0) rr = 0; if (gg > 255) gg = 255; else if (gg < 0) gg = 0; if (bb > 255) bb = 255; else if (bb < 0) bb = 0; r = red_table[rr]; g = green_table[gg]; b = blue_table[bb]; rer = rerr[x] - r*dd; ger = gerr[x] - g*dd; ber = berr[x] - b*dd; pixel = (r * cpccpc) + (g * cpc) + b; *pixel_data++ = colors[pixel].pixel; r = rer >> 1; g = ger >> 1; b = ber >> 1; rerr[x+1] += r; gerr[x+1] += g; berr[x+1] += b; nrerr[x] += r; ngerr[x] += g; nberr[x] += b; } offset += width; pixel_data = (ppixel_data += image->bytes_per_line); terr = rerr; rerr = nrerr; nrerr = terr; terr = gerr; gerr = ngerr; ngerr = terr; terr = berr; berr = nberr; nberr = terr; } delete [] rerr;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -