1 // -*- mode: C++; indent-tabs-mode: nil; -*-
2 // Image.cc for Blackbox - an X11 Window manager
3 // Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh@debian.org>
4 // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
6 // Permission is hereby granted, free of charge, to any person obtaining a
7 // copy of this software and associated documentation files (the "Software"),
8 // to deal in the Software without restriction, including without limitation
9 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 // and/or sell copies of the Software, and to permit persons to whom the
11 // Software is furnished to do so, subject to the following conditions:
13 // The above copyright notice and this permission notice shall be included in
14 // all copies or substantial portions of the Software.
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 // DEALINGS IN THE SOFTWARE.
25 # include "../config.h"
26 #endif // HAVE_CONFIG_H
30 #endif // HAVE_STDIO_H
36 #include "blackbox.hh"
38 #include "BaseDisplay.hh"
44 BImage::BImage(BImageControl
*c
, unsigned int w
, unsigned int h
) {
47 width
= ((signed) w
> 0) ? w
: 1;
48 height
= ((signed) h
> 0) ? h
: 1;
50 red
= new unsigned char[width
* height
];
51 green
= new unsigned char[width
* height
];
52 blue
= new unsigned char[width
* height
];
54 xtable
= ytable
= (unsigned int *) 0;
56 cpc
= control
->getColorsPerChannel();
59 control
->getColorTables(&red_table
, &green_table
, &blue_table
,
60 &red_offset
, &green_offset
, &blue_offset
,
61 &red_bits
, &green_bits
, &blue_bits
);
63 if (control
->getVisual()->c_class
!= TrueColor
)
64 control
->getXColorTable(&colors
, &ncolors
);
68 BImage::~BImage(void) {
69 if (red
) delete [] red
;
70 if (green
) delete [] green
;
71 if (blue
) delete [] blue
;
75 Pixmap
BImage::render(const BTexture
&texture
) {
76 if ((texture
.texture() & BTexture::Parent_Relative
))
77 return ParentRelative
;
78 else if ((texture
.texture() & BTexture::Solid
))
79 return render_solid(texture
);
80 else if ((texture
.texture() & BTexture::Gradient
))
81 return render_gradient(texture
);
86 Pixmap
BImage::render_solid(const BTexture
&texture
) {
87 Pixmap pixmap
= XCreatePixmap(control
->getBaseDisplay()->getXDisplay(),
88 control
->getDrawable(), width
,
89 height
, control
->getDepth());
91 fprintf(stderr
, i18n(ImageSet
, ImageErrorCreatingSolidPixmap
,
92 "BImage::render_solid: error creating pixmap\n"));
96 Display
*display
= control
->getBaseDisplay()->getXDisplay();
98 BPen
pen(texture
.color());
99 BPen
penlight(texture
.lightColor());
100 BPen
penshadow(texture
.shadowColor());
102 XFillRectangle(display
, pixmap
, pen
.gc(), 0, 0, width
, height
);
104 if (texture
.texture() & BTexture::Interlaced
) {
105 BPen
peninterlace(texture
.colorTo());
106 register unsigned int i
= 0;
107 for (; i
< height
; i
+= 2)
108 XDrawLine(display
, pixmap
, peninterlace
.gc(), 0, i
, width
, i
);
111 if (texture
.texture() & BTexture::Bevel1
) {
112 if (texture
.texture() & BTexture::Raised
) {
113 XDrawLine(display
, pixmap
, penshadow
.gc(),
114 0, height
- 1, width
- 1, height
- 1);
115 XDrawLine(display
, pixmap
, penshadow
.gc(),
116 width
- 1, height
- 1, width
- 1, 0);
118 XDrawLine(display
, pixmap
, penlight
.gc(),
120 XDrawLine(display
, pixmap
, penlight
.gc(),
121 0, height
- 1, 0, 0);
122 } else if (texture
.texture() & BTexture::Sunken
) {
123 XDrawLine(display
, pixmap
, penlight
.gc(),
124 0, height
- 1, width
- 1, height
- 1);
125 XDrawLine(display
, pixmap
, penlight
.gc(),
126 width
- 1, height
- 1, width
- 1, 0);
128 XDrawLine(display
, pixmap
, penshadow
.gc(),
130 XDrawLine(display
, pixmap
, penshadow
.gc(),
131 0, height
- 1, 0, 0);
133 } else if (texture
.texture() & BTexture::Bevel2
) {
134 if (texture
.texture() & BTexture::Raised
) {
135 XDrawLine(display
, pixmap
, penshadow
.gc(),
136 1, height
- 3, width
- 3, height
- 3);
137 XDrawLine(display
, pixmap
, penshadow
.gc(),
138 width
- 3, height
- 3, width
- 3, 1);
140 XDrawLine(display
, pixmap
, penlight
.gc(),
142 XDrawLine(display
, pixmap
, penlight
.gc(),
143 1, height
- 3, 1, 1);
144 } else if (texture
.texture() & BTexture::Sunken
) {
145 XDrawLine(display
, pixmap
, penlight
.gc(),
146 1, height
- 3, width
- 3, height
- 3);
147 XDrawLine(display
, pixmap
, penlight
.gc(),
148 width
- 3, height
- 3, width
- 3, 1);
150 XDrawLine(display
, pixmap
, penshadow
.gc(),
152 XDrawLine(display
, pixmap
, penshadow
.gc(),
153 1, height
- 3, 1, 1);
161 Pixmap
BImage::render_gradient(const BTexture
&texture
) {
164 interlaced
= texture
.texture() & BTexture::Interlaced
;
166 if (texture
.texture() & BTexture::Sunken
) {
167 from
= texture
.colorTo();
168 to
= texture
.color();
170 if (! (texture
.texture() & BTexture::Invert
)) inverted
= 1;
172 from
= texture
.color();
173 to
= texture
.colorTo();
175 if (texture
.texture() & BTexture::Invert
) inverted
= 1;
178 control
->getGradientBuffers(width
, height
, &xtable
, &ytable
);
180 if (texture
.texture() & BTexture::Diagonal
) dgradient();
181 else if (texture
.texture() & BTexture::Elliptic
) egradient();
182 else if (texture
.texture() & BTexture::Horizontal
) hgradient();
183 else if (texture
.texture() & BTexture::Pyramid
) pgradient();
184 else if (texture
.texture() & BTexture::Rectangle
) rgradient();
185 else if (texture
.texture() & BTexture::Vertical
) vgradient();
186 else if (texture
.texture() & BTexture::CrossDiagonal
) cdgradient();
187 else if (texture
.texture() & BTexture::PipeCross
) pcgradient();
189 if (texture
.texture() & BTexture::Bevel1
) bevel1();
190 else if (texture
.texture() & BTexture::Bevel2
) bevel2();
192 if (inverted
) invert();
194 Pixmap pixmap
= renderPixmap();
201 static const unsigned char dither4
[4][4] = {
210 * Helper function for TrueColorDither and renderXImage
212 * This handles the proper setting of the image data based on the image depth
213 * and the machine's byte ordering
216 void assignPixelData(unsigned int bit_depth
, unsigned char **data
,
217 unsigned long pixel
) {
218 unsigned char *pixel_data
= *data
;
221 *pixel_data
++ = pixel
;
224 case 16: // 16bpp LSB
225 *pixel_data
++ = pixel
;
226 *pixel_data
++ = pixel
>> 8;
229 case 17: // 16bpp MSB
230 *pixel_data
++ = pixel
>> 8;
231 *pixel_data
++ = pixel
;
234 case 24: // 24bpp LSB
235 *pixel_data
++ = pixel
;
236 *pixel_data
++ = pixel
>> 8;
237 *pixel_data
++ = pixel
>> 16;
240 case 25: // 24bpp MSB
241 *pixel_data
++ = pixel
>> 16;
242 *pixel_data
++ = pixel
>> 8;
243 *pixel_data
++ = pixel
;
246 case 32: // 32bpp LSB
247 *pixel_data
++ = pixel
;
248 *pixel_data
++ = pixel
>> 8;
249 *pixel_data
++ = pixel
>> 16;
250 *pixel_data
++ = pixel
>> 24;
253 case 33: // 32bpp MSB
254 *pixel_data
++ = pixel
>> 24;
255 *pixel_data
++ = pixel
>> 16;
256 *pixel_data
++ = pixel
>> 8;
257 *pixel_data
++ = pixel
;
260 *data
= pixel_data
; // assign back so we don't lose our place
264 // algorithm: ordered dithering... many many thanks to rasterman
265 // (raster@rasterman.com) for telling me about this... portions of this
266 // code is based off of his code in Imlib
267 void BImage::TrueColorDither(unsigned int bit_depth
, int bytes_per_line
,
268 unsigned char *pixel_data
) {
269 unsigned int x
, y
, dithx
, dithy
, r
, g
, b
, er
, eg
, eb
, offset
;
270 unsigned char *ppixel_data
= pixel_data
;
273 for (y
= 0, offset
= 0; y
< height
; y
++) {
276 for (x
= 0; x
< width
; x
++, offset
++) {
282 er
= r
& (red_bits
- 1);
283 eg
= g
& (green_bits
- 1);
284 eb
= b
& (blue_bits
- 1);
290 if ((dither4
[dithy
][dithx
] < er
) && (r
< red_table
[255])) r
++;
291 if ((dither4
[dithy
][dithx
] < eg
) && (g
< green_table
[255])) g
++;
292 if ((dither4
[dithy
][dithx
] < eb
) && (b
< blue_table
[255])) b
++;
294 pixel
= (r
<< red_offset
) | (g
<< green_offset
) | (b
<< blue_offset
);
295 assignPixelData(bit_depth
, &pixel_data
, pixel
);
298 pixel_data
= (ppixel_data
+= bytes_per_line
);
303 const static unsigned char dither8
[8][8] = {
304 { 0, 32, 8, 40, 2, 34, 10, 42},
305 { 48, 16, 56, 24, 50, 18, 58, 26},
306 { 12, 44, 4, 36, 14, 46, 6, 38},
307 { 60, 28, 52, 20, 62, 30, 54, 22},
308 { 3, 35, 11, 43, 1, 33, 9, 41},
309 { 51, 19, 59, 27, 49, 17, 57, 25},
310 { 15, 47, 7, 39, 13, 45, 5, 37},
311 { 63, 31, 55, 23, 61, 29, 53, 21}
314 void BImage::OrderedPseudoColorDither(int bytes_per_line
,
315 unsigned char *pixel_data
) {
316 unsigned int x
, y
, dithx
, dithy
, r
, g
, b
, er
, eg
, eb
, offset
;
318 unsigned char *ppixel_data
= pixel_data
;
320 for (y
= 0, offset
= 0; y
< height
; y
++) {
323 for (x
= 0; x
< width
; x
++, offset
++) {
330 er
= r
& (red_bits
- 1);
331 eg
= g
& (green_bits
- 1);
332 eb
= b
& (blue_bits
- 1);
338 if ((dither8
[dithy
][dithx
] < er
) && (r
< red_table
[255])) r
++;
339 if ((dither8
[dithy
][dithx
] < eg
) && (g
< green_table
[255])) g
++;
340 if ((dither8
[dithy
][dithx
] < eb
) && (b
< blue_table
[255])) b
++;
342 pixel
= (r
* cpccpc
) + (g
* cpc
) + b
;
343 *(pixel_data
++) = colors
[pixel
].pixel
;
346 pixel_data
= (ppixel_data
+= bytes_per_line
);
351 void BImage::PseudoColorDither(int bytes_per_line
, unsigned char *pixel_data
) {
353 *rerr
= new short[width
+ 2],
354 *gerr
= new short[width
+ 2],
355 *berr
= new short[width
+ 2],
356 *nrerr
= new short[width
+ 2],
357 *ngerr
= new short[width
+ 2],
358 *nberr
= new short[width
+ 2];
360 int rr
, gg
, bb
, rer
, ger
, ber
;
361 int dd
= 255 / control
->getColorsPerChannel();
362 unsigned int x
, y
, r
, g
, b
, offset
;
364 unsigned char *ppixel_data
= pixel_data
;
366 for (x
= 0; x
< width
; x
++) {
367 *(rerr
+ x
) = *(red
+ x
);
368 *(gerr
+ x
) = *(green
+ x
);
369 *(berr
+ x
) = *(blue
+ x
);
372 *(rerr
+ x
) = *(gerr
+ x
) = *(berr
+ x
) = 0;
374 for (y
= 0, offset
= 0; y
< height
; y
++) {
375 if (y
< (height
- 1)) {
376 int i
= offset
+ width
;
377 for (x
= 0; x
< width
; x
++, i
++) {
378 *(nrerr
+ x
) = *(red
+ i
);
379 *(ngerr
+ x
) = *(green
+ i
);
380 *(nberr
+ x
) = *(blue
+ i
);
383 *(nrerr
+ x
) = *(red
+ (--i
));
384 *(ngerr
+ x
) = *(green
+ i
);
385 *(nberr
+ x
) = *(blue
+ i
);
388 for (x
= 0; x
< width
; x
++) {
393 if (rr
> 255) rr
= 255; else if (rr
< 0) rr
= 0;
394 if (gg
> 255) gg
= 255; else if (gg
< 0) gg
= 0;
395 if (bb
> 255) bb
= 255; else if (bb
< 0) bb
= 0;
401 rer
= rerr
[x
] - r
*dd
;
402 ger
= gerr
[x
] - g
*dd
;
403 ber
= berr
[x
] - b
*dd
;
405 pixel
= (r
* cpccpc
) + (g
* cpc
) + b
;
406 *pixel_data
++ = colors
[pixel
].pixel
;
421 pixel_data
= (ppixel_data
+= bytes_per_line
);
444 XImage
*BImage::renderXImage(void) {
446 XCreateImage(control
->getBaseDisplay()->getXDisplay(),
447 control
->getVisual(), control
->getDepth(), ZPixmap
, 0, 0,
448 width
, height
, 32, 0);
451 fprintf(stderr
, i18n(ImageSet
, ImageErrorCreatingXImage
,
452 "BImage::renderXImage: error creating XImage\n"));
457 image
->data
= (char *) 0;
459 unsigned char *d
= new unsigned char[image
->bytes_per_line
* (height
+ 1)];
461 unsigned int o
= image
->bits_per_pixel
+
462 ((image
->byte_order
== MSBFirst
) ? 1 : 0);
464 if (control
->doDither() && width
> 1 && height
> 1) {
465 switch (control
->getVisual()->c_class
) {
467 TrueColorDither(o
, image
->bytes_per_line
, d
);
473 OrderedPseudoColorDither(image
->bytes_per_line
, d
);
475 PseudoColorDither(image
->bytes_per_line
, d
);
481 fprintf(stderr
, i18n(ImageSet
, ImageUnsupVisual
,
482 "BImage::renderXImage: unsupported visual\n"));
484 XDestroyImage(image
);
488 register unsigned int x
, y
, r
, g
, b
, offset
;
490 unsigned char *pixel_data
= d
, *ppixel_data
= d
;
493 switch (control
->getVisual()->c_class
) {
496 for (y
= 0, offset
= 0; y
< height
; y
++) {
497 for (x
= 0; x
< width
; x
++, offset
++) {
498 r
= red_table
[red
[offset
]];
499 g
= green_table
[green
[offset
]];
500 b
= blue_table
[blue
[offset
]];
502 pixel
= (r
* cpccpc
) + (g
* cpc
) + b
;
503 *pixel_data
++ = colors
[pixel
].pixel
;
506 pixel_data
= (ppixel_data
+= image
->bytes_per_line
);
512 for (y
= 0, offset
= 0; y
< height
; y
++) {
513 for (x
= 0; x
< width
; x
++, offset
++) {
514 r
= red_table
[red
[offset
]];
515 g
= green_table
[green
[offset
]];
516 b
= blue_table
[blue
[offset
]];
518 pixel
= (r
<< red_offset
) | (g
<< green_offset
) | (b
<< blue_offset
);
519 assignPixelData(o
, &pixel_data
, pixel
);
522 pixel_data
= (ppixel_data
+= image
->bytes_per_line
);
529 for (y
= 0, offset
= 0; y
< height
; y
++) {
530 for (x
= 0; x
< width
; x
++, offset
++) {
531 r
= *(red_table
+ *(red
+ offset
));
532 g
= *(green_table
+ *(green
+ offset
));
533 b
= *(blue_table
+ *(blue
+ offset
));
535 g
= ((r
* 30) + (g
* 59) + (b
* 11)) / 100;
536 *pixel_data
++ = colors
[g
].pixel
;
539 pixel_data
= (ppixel_data
+= image
->bytes_per_line
);
545 fprintf(stderr
, i18n(ImageSet
, ImageUnsupVisual
,
546 "BImage::renderXImage: unsupported visual\n"));
548 XDestroyImage(image
);
553 image
->data
= (char *) d
;
558 Pixmap
BImage::renderPixmap(void) {
560 XCreatePixmap(control
->getBaseDisplay()->getXDisplay(),
561 control
->getDrawable(), width
, height
, control
->getDepth());
563 if (pixmap
== None
) {
564 fprintf(stderr
, i18n(ImageSet
, ImageErrorCreatingPixmap
,
565 "BImage::renderPixmap: error creating pixmap\n"));
569 XImage
*image
= renderXImage();
572 XFreePixmap(control
->getBaseDisplay()->getXDisplay(), pixmap
);
574 } else if (! image
->data
) {
575 XDestroyImage(image
);
576 XFreePixmap(control
->getBaseDisplay()->getXDisplay(), pixmap
);
580 XPutImage(control
->getBaseDisplay()->getXDisplay(), pixmap
,
581 DefaultGC(control
->getBaseDisplay()->getXDisplay(),
582 control
->getScreenInfo()->getScreenNumber()),
583 image
, 0, 0, 0, 0, width
, height
);
586 delete [] image
->data
;
590 XDestroyImage(image
);
596 void BImage::bevel1(void) {
597 if (width
> 2 && height
> 2) {
598 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
600 register unsigned char r
, g
, b
, rr
,gg
,bb
;
601 register unsigned int w
= width
, h
= height
- 1, wh
= w
* h
;
619 rr
= (r
>> 2) + (r
>> 1);
622 gg
= (g
>> 2) + (g
>> 1);
625 bb
= (b
>> 2) + (b
>> 1);
648 rr
= (r
>> 2) + (r
>> 1);
651 gg
= (g
>> 2) + (g
>> 1);
654 bb
= (b
>> 2) + (b
>> 1);
685 rr
= (r
>> 2) + (r
>> 1);
688 gg
= (g
>> 2) + (g
>> 1);
691 bb
= (b
>> 2) + (b
>> 1);
718 rr
= (r
>> 2) + (r
>> 1);
721 gg
= (g
>> 2) + (g
>> 1);
724 bb
= (b
>> 2) + (b
>> 1);
734 void BImage::bevel2(void) {
735 if (width
> 4 && height
> 4) {
736 unsigned char r
, g
, b
, rr
,gg
,bb
, *pr
= red
+ width
+ 1,
737 *pg
= green
+ width
+ 1, *pb
= blue
+ width
+ 1;
738 unsigned int w
= width
- 2, h
= height
- 1, wh
= width
* (height
- 3);
756 rr
= (r
>> 2) + (r
>> 1);
759 gg
= (g
>> 2) + (g
>> 1);
762 bb
= (b
>> 2) + (b
>> 1);
794 rr
= (r
>> 2) + (r
>> 1);
797 gg
= (g
>> 2) + (g
>> 1);
800 bb
= (b
>> 2) + (b
>> 1);
813 void BImage::invert(void) {
814 register unsigned int i
, j
, wh
= (width
* height
) - 1;
817 for (i
= 0, j
= wh
; j
> i
; j
--, i
++) {
819 *(red
+ j
) = *(red
+ i
);
823 *(green
+ j
) = *(green
+ i
);
827 *(blue
+ j
) = *(blue
+ i
);
833 void BImage::dgradient(void) {
834 // diagonal gradient code was written by Mike Cole <mike@mydot.com>
835 // modified for interlacing by Brad Hughes
837 float drx
, dgx
, dbx
, dry
, dgy
, dby
, yr
= 0.0, yg
= 0.0, yb
= 0.0,
838 xr
= (float) from
.red(),
839 xg
= (float) from
.green(),
840 xb
= (float) from
.blue();
841 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
842 unsigned int w
= width
* 2, h
= height
* 2, *xt
= xtable
, *yt
= ytable
;
844 register unsigned int x
, y
;
846 dry
= drx
= (float) (to
.red() - from
.red());
847 dgy
= dgx
= (float) (to
.green() - from
.green());
848 dby
= dbx
= (float) (to
.blue() - from
.blue());
855 for (x
= 0; x
< width
; x
++) {
856 *(xt
++) = (unsigned char) (xr
);
857 *(xt
++) = (unsigned char) (xg
);
858 *(xt
++) = (unsigned char) (xb
);
870 for (y
= 0; y
< height
; y
++) {
871 *(yt
++) = ((unsigned char) yr
);
872 *(yt
++) = ((unsigned char) yg
);
873 *(yt
++) = ((unsigned char) yb
);
880 // Combine tables to create gradient
884 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
885 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
886 *(pr
++) = *(xt
++) + *(yt
);
887 *(pg
++) = *(xt
++) + *(yt
+ 1);
888 *(pb
++) = *(xt
++) + *(yt
+ 2);
892 // faked interlacing effect
893 unsigned char channel
, channel2
;
895 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
896 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
898 channel
= *(xt
++) + *(yt
);
899 channel2
= (channel
>> 1) + (channel
>> 2);
900 if (channel2
> channel
) channel2
= 0;
903 channel
= *(xt
++) + *(yt
+ 1);
904 channel2
= (channel
>> 1) + (channel
>> 2);
905 if (channel2
> channel
) channel2
= 0;
908 channel
= *(xt
++) + *(yt
+ 2);
909 channel2
= (channel
>> 1) + (channel
>> 2);
910 if (channel2
> channel
) channel2
= 0;
913 channel
= *(xt
++) + *(yt
);
914 channel2
= channel
+ (channel
>> 3);
915 if (channel2
< channel
) channel2
= ~0;
918 channel
= *(xt
++) + *(yt
+ 1);
919 channel2
= channel
+ (channel
>> 3);
920 if (channel2
< channel
) channel2
= ~0;
923 channel
= *(xt
++) + *(yt
+ 2);
924 channel2
= channel
+ (channel
>> 3);
925 if (channel2
< channel
) channel2
= ~0;
934 void BImage::hgradient(void) {
936 xr
= (float) from
.red(),
937 xg
= (float) from
.green(),
938 xb
= (float) from
.blue();
939 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
941 register unsigned int x
, y
;
943 drx
= (float) (to
.red() - from
.red());
944 dgx
= (float) (to
.green() - from
.green());
945 dbx
= (float) (to
.blue() - from
.blue());
951 if (interlaced
&& height
> 2) {
952 // faked interlacing effect
953 unsigned char channel
, channel2
;
955 for (x
= 0; x
< width
; x
++, pr
++, pg
++, pb
++) {
956 channel
= (unsigned char) xr
;
957 channel2
= (channel
>> 1) + (channel
>> 2);
958 if (channel2
> channel
) channel2
= 0;
961 channel
= (unsigned char) xg
;
962 channel2
= (channel
>> 1) + (channel
>> 2);
963 if (channel2
> channel
) channel2
= 0;
966 channel
= (unsigned char) xb
;
967 channel2
= (channel
>> 1) + (channel
>> 2);
968 if (channel2
> channel
) channel2
= 0;
972 channel
= (unsigned char) xr
;
973 channel2
= channel
+ (channel
>> 3);
974 if (channel2
< channel
) channel2
= ~0;
975 *(pr
+ width
) = channel2
;
977 channel
= (unsigned char) xg
;
978 channel2
= channel
+ (channel
>> 3);
979 if (channel2
< channel
) channel2
= ~0;
980 *(pg
+ width
) = channel2
;
982 channel
= (unsigned char) xb
;
983 channel2
= channel
+ (channel
>> 3);
984 if (channel2
< channel
) channel2
= ~0;
985 *(pb
+ width
) = channel2
;
998 for (y
= 2; y
< height
; y
++, pr
+= width
, pg
+= width
, pb
+= width
) {
999 if (y
& 1) offset
= width
; else offset
= 0;
1001 memcpy(pr
, (red
+ offset
), width
);
1002 memcpy(pg
, (green
+ offset
), width
);
1003 memcpy(pb
, (blue
+ offset
), width
);
1007 for (x
= 0; x
< width
; x
++) {
1008 *(pr
++) = (unsigned char) (xr
);
1009 *(pg
++) = (unsigned char) (xg
);
1010 *(pb
++) = (unsigned char) (xb
);
1017 for (y
= 1; y
< height
; y
++, pr
+= width
, pg
+= width
, pb
+= width
) {
1018 memcpy(pr
, red
, width
);
1019 memcpy(pg
, green
, width
);
1020 memcpy(pb
, blue
, width
);
1026 void BImage::vgradient(void) {
1027 float dry
, dgy
, dby
,
1028 yr
= (float) from
.red(),
1029 yg
= (float) from
.green(),
1030 yb
= (float) from
.blue();
1031 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1033 register unsigned int y
;
1035 dry
= (float) (to
.red() - from
.red());
1036 dgy
= (float) (to
.green() - from
.green());
1037 dby
= (float) (to
.blue() - from
.blue());
1044 // faked interlacing effect
1045 unsigned char channel
, channel2
;
1047 for (y
= 0; y
< height
; y
++, pr
+= width
, pg
+= width
, pb
+= width
) {
1049 channel
= (unsigned char) yr
;
1050 channel2
= (channel
>> 1) + (channel
>> 2);
1051 if (channel2
> channel
) channel2
= 0;
1052 memset(pr
, channel2
, width
);
1054 channel
= (unsigned char) yg
;
1055 channel2
= (channel
>> 1) + (channel
>> 2);
1056 if (channel2
> channel
) channel2
= 0;
1057 memset(pg
, channel2
, width
);
1059 channel
= (unsigned char) yb
;
1060 channel2
= (channel
>> 1) + (channel
>> 2);
1061 if (channel2
> channel
) channel2
= 0;
1062 memset(pb
, channel2
, width
);
1064 channel
= (unsigned char) yr
;
1065 channel2
= channel
+ (channel
>> 3);
1066 if (channel2
< channel
) channel2
= ~0;
1067 memset(pr
, channel2
, width
);
1069 channel
= (unsigned char) yg
;
1070 channel2
= channel
+ (channel
>> 3);
1071 if (channel2
< channel
) channel2
= ~0;
1072 memset(pg
, channel2
, width
);
1074 channel
= (unsigned char) yb
;
1075 channel2
= channel
+ (channel
>> 3);
1076 if (channel2
< channel
) channel2
= ~0;
1077 memset(pb
, channel2
, width
);
1086 for (y
= 0; y
< height
; y
++, pr
+= width
, pg
+= width
, pb
+= width
) {
1087 memset(pr
, (unsigned char) yr
, width
);
1088 memset(pg
, (unsigned char) yg
, width
);
1089 memset(pb
, (unsigned char) yb
, width
);
1099 void BImage::pgradient(void) {
1100 // pyramid gradient - based on original dgradient, written by
1101 // Mosfet (mosfet@kde.org)
1102 // adapted from kde sources for Blackbox by Brad Hughes
1104 float yr
, yg
, yb
, drx
, dgx
, dbx
, dry
, dgy
, dby
,
1106 int rsign
, gsign
, bsign
;
1107 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1108 unsigned int tr
= to
.red(), tg
= to
.green(), tb
= to
.blue(),
1109 *xt
= xtable
, *yt
= ytable
;
1111 register unsigned int x
, y
;
1113 dry
= drx
= (float) (to
.red() - from
.red());
1114 dgy
= dgx
= (float) (to
.green() - from
.green());
1115 dby
= dbx
= (float) (to
.blue() - from
.blue());
1117 rsign
= (drx
< 0) ? -1 : 1;
1118 gsign
= (dgx
< 0) ? -1 : 1;
1119 bsign
= (dbx
< 0) ? -1 : 1;
1121 xr
= yr
= (drx
/ 2);
1122 xg
= yg
= (dgx
/ 2);
1123 xb
= yb
= (dbx
/ 2);
1130 for (x
= 0; x
< width
; x
++) {
1131 *(xt
++) = (unsigned char) ((xr
< 0) ? -xr
: xr
);
1132 *(xt
++) = (unsigned char) ((xg
< 0) ? -xg
: xg
);
1133 *(xt
++) = (unsigned char) ((xb
< 0) ? -xb
: xb
);
1145 for (y
= 0; y
< height
; y
++) {
1146 *(yt
++) = ((unsigned char) ((yr
< 0) ? -yr
: yr
));
1147 *(yt
++) = ((unsigned char) ((yg
< 0) ? -yg
: yg
));
1148 *(yt
++) = ((unsigned char) ((yb
< 0) ? -yb
: yb
));
1155 // Combine tables to create gradient
1159 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1160 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1161 *(pr
++) = (unsigned char) (tr
- (rsign
* (*(xt
++) + *(yt
))));
1162 *(pg
++) = (unsigned char) (tg
- (gsign
* (*(xt
++) + *(yt
+ 1))));
1163 *(pb
++) = (unsigned char) (tb
- (bsign
* (*(xt
++) + *(yt
+ 2))));
1167 // faked interlacing effect
1168 unsigned char channel
, channel2
;
1170 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1171 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1173 channel
= (unsigned char) (tr
- (rsign
* (*(xt
++) + *(yt
))));
1174 channel2
= (channel
>> 1) + (channel
>> 2);
1175 if (channel2
> channel
) channel2
= 0;
1178 channel
= (unsigned char) (tg
- (gsign
* (*(xt
++) + *(yt
+ 1))));
1179 channel2
= (channel
>> 1) + (channel
>> 2);
1180 if (channel2
> channel
) channel2
= 0;
1183 channel
= (unsigned char) (tb
- (bsign
* (*(xt
++) + *(yt
+ 2))));
1184 channel2
= (channel
>> 1) + (channel
>> 2);
1185 if (channel2
> channel
) channel2
= 0;
1188 channel
= (unsigned char) (tr
- (rsign
* (*(xt
++) + *(yt
))));
1189 channel2
= channel
+ (channel
>> 3);
1190 if (channel2
< channel
) channel2
= ~0;
1193 channel
= (unsigned char) (tg
- (gsign
* (*(xt
++) + *(yt
+ 1))));
1194 channel2
= channel
+ (channel
>> 3);
1195 if (channel2
< channel
) channel2
= ~0;
1198 channel
= (unsigned char) (tb
- (bsign
* (*(xt
++) + *(yt
+ 2))));
1199 channel2
= channel
+ (channel
>> 3);
1200 if (channel2
< channel
) channel2
= ~0;
1209 void BImage::rgradient(void) {
1210 // rectangle gradient - based on original dgradient, written by
1211 // Mosfet (mosfet@kde.org)
1212 // adapted from kde sources for Blackbox by Brad Hughes
1214 float drx
, dgx
, dbx
, dry
, dgy
, dby
, xr
, xg
, xb
, yr
, yg
, yb
;
1215 int rsign
, gsign
, bsign
;
1216 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1217 unsigned int tr
= to
.red(), tg
= to
.green(), tb
= to
.blue(),
1218 *xt
= xtable
, *yt
= ytable
;
1220 register unsigned int x
, y
;
1222 dry
= drx
= (float) (to
.red() - from
.red());
1223 dgy
= dgx
= (float) (to
.green() - from
.green());
1224 dby
= dbx
= (float) (to
.blue() - from
.blue());
1226 rsign
= (drx
< 0) ? -2 : 2;
1227 gsign
= (dgx
< 0) ? -2 : 2;
1228 bsign
= (dbx
< 0) ? -2 : 2;
1230 xr
= yr
= (drx
/ 2);
1231 xg
= yg
= (dgx
/ 2);
1232 xb
= yb
= (dbx
/ 2);
1239 for (x
= 0; x
< width
; x
++) {
1240 *(xt
++) = (unsigned char) ((xr
< 0) ? -xr
: xr
);
1241 *(xt
++) = (unsigned char) ((xg
< 0) ? -xg
: xg
);
1242 *(xt
++) = (unsigned char) ((xb
< 0) ? -xb
: xb
);
1254 for (y
= 0; y
< height
; y
++) {
1255 *(yt
++) = ((unsigned char) ((yr
< 0) ? -yr
: yr
));
1256 *(yt
++) = ((unsigned char) ((yg
< 0) ? -yg
: yg
));
1257 *(yt
++) = ((unsigned char) ((yb
< 0) ? -yb
: yb
));
1264 // Combine tables to create gradient
1268 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1269 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1270 *(pr
++) = (unsigned char) (tr
- (rsign
* max(*(xt
++), *(yt
))));
1271 *(pg
++) = (unsigned char) (tg
- (gsign
* max(*(xt
++), *(yt
+ 1))));
1272 *(pb
++) = (unsigned char) (tb
- (bsign
* max(*(xt
++), *(yt
+ 2))));
1276 // faked interlacing effect
1277 unsigned char channel
, channel2
;
1279 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1280 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1282 channel
= (unsigned char) (tr
- (rsign
* max(*(xt
++), *(yt
))));
1283 channel2
= (channel
>> 1) + (channel
>> 2);
1284 if (channel2
> channel
) channel2
= 0;
1287 channel
= (unsigned char) (tg
- (gsign
* max(*(xt
++), *(yt
+ 1))));
1288 channel2
= (channel
>> 1) + (channel
>> 2);
1289 if (channel2
> channel
) channel2
= 0;
1292 channel
= (unsigned char) (tb
- (bsign
* max(*(xt
++), *(yt
+ 2))));
1293 channel2
= (channel
>> 1) + (channel
>> 2);
1294 if (channel2
> channel
) channel2
= 0;
1297 channel
= (unsigned char) (tr
- (rsign
* max(*(xt
++), *(yt
))));
1298 channel2
= channel
+ (channel
>> 3);
1299 if (channel2
< channel
) channel2
= ~0;
1302 channel
= (unsigned char) (tg
- (gsign
* max(*(xt
++), *(yt
+ 1))));
1303 channel2
= channel
+ (channel
>> 3);
1304 if (channel2
< channel
) channel2
= ~0;
1307 channel
= (unsigned char) (tb
- (bsign
* max(*(xt
++), *(yt
+ 2))));
1308 channel2
= channel
+ (channel
>> 3);
1309 if (channel2
< channel
) channel2
= ~0;
1318 void BImage::egradient(void) {
1319 // elliptic gradient - based on original dgradient, written by
1320 // Mosfet (mosfet@kde.org)
1321 // adapted from kde sources for Blackbox by Brad Hughes
1323 float drx
, dgx
, dbx
, dry
, dgy
, dby
, yr
, yg
, yb
, xr
, xg
, xb
;
1324 int rsign
, gsign
, bsign
;
1325 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1326 unsigned int *xt
= xtable
, *yt
= ytable
,
1327 tr
= (unsigned long) to
.red(),
1328 tg
= (unsigned long) to
.green(),
1329 tb
= (unsigned long) to
.blue();
1331 register unsigned int x
, y
;
1333 dry
= drx
= (float) (to
.red() - from
.red());
1334 dgy
= dgx
= (float) (to
.green() - from
.green());
1335 dby
= dbx
= (float) (to
.blue() - from
.blue());
1337 rsign
= (drx
< 0) ? -1 : 1;
1338 gsign
= (dgx
< 0) ? -1 : 1;
1339 bsign
= (dbx
< 0) ? -1 : 1;
1341 xr
= yr
= (drx
/ 2);
1342 xg
= yg
= (dgx
/ 2);
1343 xb
= yb
= (dbx
/ 2);
1350 for (x
= 0; x
< width
; x
++) {
1351 *(xt
++) = (unsigned long) (xr
* xr
);
1352 *(xt
++) = (unsigned long) (xg
* xg
);
1353 *(xt
++) = (unsigned long) (xb
* xb
);
1365 for (y
= 0; y
< height
; y
++) {
1366 *(yt
++) = (unsigned long) (yr
* yr
);
1367 *(yt
++) = (unsigned long) (yg
* yg
);
1368 *(yt
++) = (unsigned long) (yb
* yb
);
1375 // Combine tables to create gradient
1379 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1380 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1381 *(pr
++) = (unsigned char)
1382 (tr
- (rsign
* control
->getSqrt(*(xt
++) + *(yt
))));
1383 *(pg
++) = (unsigned char)
1384 (tg
- (gsign
* control
->getSqrt(*(xt
++) + *(yt
+ 1))));
1385 *(pb
++) = (unsigned char)
1386 (tb
- (bsign
* control
->getSqrt(*(xt
++) + *(yt
+ 2))));
1390 // faked interlacing effect
1391 unsigned char channel
, channel2
;
1393 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1394 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1396 channel
= (unsigned char)
1397 (tr
- (rsign
* control
->getSqrt(*(xt
++) + *(yt
))));
1398 channel2
= (channel
>> 1) + (channel
>> 2);
1399 if (channel2
> channel
) channel2
= 0;
1402 channel
= (unsigned char)
1403 (tg
- (gsign
* control
->getSqrt(*(xt
++) + *(yt
+ 1))));
1404 channel2
= (channel
>> 1) + (channel
>> 2);
1405 if (channel2
> channel
) channel2
= 0;
1408 channel
= (unsigned char)
1409 (tb
- (bsign
* control
->getSqrt(*(xt
++) + *(yt
+ 2))));
1410 channel2
= (channel
>> 1) + (channel
>> 2);
1411 if (channel2
> channel
) channel2
= 0;
1414 channel
= (unsigned char)
1415 (tr
- (rsign
* control
->getSqrt(*(xt
++) + *(yt
))));
1416 channel2
= channel
+ (channel
>> 3);
1417 if (channel2
< channel
) channel2
= ~0;
1420 channel
= (unsigned char)
1421 (tg
- (gsign
* control
->getSqrt(*(xt
++) + *(yt
+ 1))));
1422 channel2
= channel
+ (channel
>> 3);
1423 if (channel2
< channel
) channel2
= ~0;
1426 channel
= (unsigned char)
1427 (tb
- (bsign
* control
->getSqrt(*(xt
++) + *(yt
+ 2))));
1428 channel2
= channel
+ (channel
>> 3);
1429 if (channel2
< channel
) channel2
= ~0;
1438 void BImage::pcgradient(void) {
1439 // pipe cross gradient - based on original dgradient, written by
1440 // Mosfet (mosfet@kde.org)
1441 // adapted from kde sources for Blackbox by Brad Hughes
1443 float drx
, dgx
, dbx
, dry
, dgy
, dby
, xr
, xg
, xb
, yr
, yg
, yb
;
1444 int rsign
, gsign
, bsign
;
1445 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1446 unsigned int *xt
= xtable
, *yt
= ytable
,
1451 register unsigned int x
, y
;
1453 dry
= drx
= (float) (to
.red() - from
.red());
1454 dgy
= dgx
= (float) (to
.green() - from
.green());
1455 dby
= dbx
= (float) (to
.blue() - from
.blue());
1457 rsign
= (drx
< 0) ? -2 : 2;
1458 gsign
= (dgx
< 0) ? -2 : 2;
1459 bsign
= (dbx
< 0) ? -2 : 2;
1461 xr
= yr
= (drx
/ 2);
1462 xg
= yg
= (dgx
/ 2);
1463 xb
= yb
= (dbx
/ 2);
1470 for (x
= 0; x
< width
; x
++) {
1471 *(xt
++) = (unsigned char) ((xr
< 0) ? -xr
: xr
);
1472 *(xt
++) = (unsigned char) ((xg
< 0) ? -xg
: xg
);
1473 *(xt
++) = (unsigned char) ((xb
< 0) ? -xb
: xb
);
1485 for (y
= 0; y
< height
; y
++) {
1486 *(yt
++) = ((unsigned char) ((yr
< 0) ? -yr
: yr
));
1487 *(yt
++) = ((unsigned char) ((yg
< 0) ? -yg
: yg
));
1488 *(yt
++) = ((unsigned char) ((yb
< 0) ? -yb
: yb
));
1495 // Combine tables to create gradient
1498 // normal pcgradient
1499 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1500 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1501 *(pr
++) = (unsigned char) (tr
- (rsign
* min(*(xt
++), *(yt
))));
1502 *(pg
++) = (unsigned char) (tg
- (gsign
* min(*(xt
++), *(yt
+ 1))));
1503 *(pb
++) = (unsigned char) (tb
- (bsign
* min(*(xt
++), *(yt
+ 2))));
1507 // faked interlacing effect
1508 unsigned char channel
, channel2
;
1510 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1511 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1513 channel
= (unsigned char) (tr
- (rsign
* min(*(xt
++), *(yt
))));
1514 channel2
= (channel
>> 1) + (channel
>> 2);
1515 if (channel2
> channel
) channel2
= 0;
1518 channel
= (unsigned char) (tg
- (bsign
* min(*(xt
++), *(yt
+ 1))));
1519 channel2
= (channel
>> 1) + (channel
>> 2);
1520 if (channel2
> channel
) channel2
= 0;
1523 channel
= (unsigned char) (tb
- (gsign
* min(*(xt
++), *(yt
+ 2))));
1524 channel2
= (channel
>> 1) + (channel
>> 2);
1525 if (channel2
> channel
) channel2
= 0;
1528 channel
= (unsigned char) (tr
- (rsign
* min(*(xt
++), *(yt
))));
1529 channel2
= channel
+ (channel
>> 3);
1530 if (channel2
< channel
) channel2
= ~0;
1533 channel
= (unsigned char) (tg
- (gsign
* min(*(xt
++), *(yt
+ 1))));
1534 channel2
= channel
+ (channel
>> 3);
1535 if (channel2
< channel
) channel2
= ~0;
1538 channel
= (unsigned char) (tb
- (bsign
* min(*(xt
++), *(yt
+ 2))));
1539 channel2
= channel
+ (channel
>> 3);
1540 if (channel2
< channel
) channel2
= ~0;
1549 void BImage::cdgradient(void) {
1550 // cross diagonal gradient - based on original dgradient, written by
1551 // Mosfet (mosfet@kde.org)
1552 // adapted from kde sources for Blackbox by Brad Hughes
1554 float drx
, dgx
, dbx
, dry
, dgy
, dby
, yr
= 0.0, yg
= 0.0, yb
= 0.0,
1555 xr
= (float) from
.red(),
1556 xg
= (float) from
.green(),
1557 xb
= (float) from
.blue();
1558 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1559 unsigned int w
= width
* 2, h
= height
* 2, *xt
, *yt
;
1561 register unsigned int x
, y
;
1563 dry
= drx
= (float) (to
.red() - from
.red());
1564 dgy
= dgx
= (float) (to
.green() - from
.green());
1565 dby
= dbx
= (float) (to
.blue() - from
.blue());
1572 for (xt
= (xtable
+ (width
* 3) - 1), x
= 0; x
< width
; x
++) {
1573 *(xt
--) = (unsigned char) xb
;
1574 *(xt
--) = (unsigned char) xg
;
1575 *(xt
--) = (unsigned char) xr
;
1587 for (yt
= ytable
, y
= 0; y
< height
; y
++) {
1588 *(yt
++) = (unsigned char) yr
;
1589 *(yt
++) = (unsigned char) yg
;
1590 *(yt
++) = (unsigned char) yb
;
1597 // Combine tables to create gradient
1600 // normal cdgradient
1601 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1602 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1603 *(pr
++) = *(xt
++) + *(yt
);
1604 *(pg
++) = *(xt
++) + *(yt
+ 1);
1605 *(pb
++) = *(xt
++) + *(yt
+ 2);
1609 // faked interlacing effect
1610 unsigned char channel
, channel2
;
1612 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1613 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1615 channel
= *(xt
++) + *(yt
);
1616 channel2
= (channel
>> 1) + (channel
>> 2);
1617 if (channel2
> channel
) channel2
= 0;
1620 channel
= *(xt
++) + *(yt
+ 1);
1621 channel2
= (channel
>> 1) + (channel
>> 2);
1622 if (channel2
> channel
) channel2
= 0;
1625 channel
= *(xt
++) + *(yt
+ 2);
1626 channel2
= (channel
>> 1) + (channel
>> 2);
1627 if (channel2
> channel
) channel2
= 0;
1630 channel
= *(xt
++) + *(yt
);
1631 channel2
= channel
+ (channel
>> 3);
1632 if (channel2
< channel
) channel2
= ~0;
1635 channel
= *(xt
++) + *(yt
+ 1);
1636 channel2
= channel
+ (channel
>> 3);
1637 if (channel2
< channel
) channel2
= ~0;
1640 channel
= *(xt
++) + *(yt
+ 2);
1641 channel2
= channel
+ (channel
>> 3);
1642 if (channel2
< channel
) channel2
= ~0;