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
, int w
, int h
) {
47 width
= (w
> 0) ? w
: 1;
48 height
= (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) {
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 for (unsigned int i
= 0; i
< height
; i
+= 2)
107 XDrawLine(display
, pixmap
, peninterlace
.gc(), 0, i
, width
, i
);
110 int left
= 0, top
= 0, right
= width
- 1, bottom
= height
- 1;
112 if (texture
.texture() & BTexture::Border
) {
113 BPen
penborder(texture
.borderColor());
114 XDrawRectangle(display
, pixmap
, penborder
.gc(),
115 left
, top
, right
, bottom
);
118 if (texture
.texture() & BTexture::Bevel1
) {
119 if (texture
.texture() & BTexture::Raised
) {
120 XDrawLine(display
, pixmap
, penshadow
.gc(),
121 left
, bottom
, right
, bottom
);
122 XDrawLine(display
, pixmap
, penshadow
.gc(),
123 right
, bottom
, right
, top
);
125 XDrawLine(display
, pixmap
, penlight
.gc(),
126 left
, top
, right
, top
);
127 XDrawLine(display
, pixmap
, penlight
.gc(),
128 left
, bottom
, left
, top
);
129 } else if (texture
.texture() & BTexture::Sunken
) {
130 XDrawLine(display
, pixmap
, penlight
.gc(),
131 left
, bottom
, right
, bottom
);
132 XDrawLine(display
, pixmap
, penlight
.gc(),
133 right
, bottom
, right
, top
);
135 XDrawLine(display
, pixmap
, penshadow
.gc(),
136 left
, top
, right
, top
);
137 XDrawLine(display
, pixmap
, penshadow
.gc(),
138 left
, bottom
, left
, top
);
140 } else if (texture
.texture() & BTexture::Bevel2
) {
141 if (texture
.texture() & BTexture::Raised
) {
142 XDrawLine(display
, pixmap
, penshadow
.gc(),
143 left
+ 1, bottom
- 2, right
- 2, bottom
- 2);
144 XDrawLine(display
, pixmap
, penshadow
.gc(),
145 right
- 2, bottom
- 2, right
- 2, top
+ 1);
147 XDrawLine(display
, pixmap
, penlight
.gc(),
148 left
+ 1, top
+ 1, right
- 2, top
+ 1);
149 XDrawLine(display
, pixmap
, penlight
.gc(),
150 left
+ 1, bottom
- 2, left
+ 1, top
+ 1);
151 } else if (texture
.texture() & BTexture::Sunken
) {
152 XDrawLine(display
, pixmap
, penlight
.gc(),
153 left
+ 1, bottom
- 2, right
- 2, bottom
- 2);
154 XDrawLine(display
, pixmap
, penlight
.gc(),
155 right
- 2, bottom
- 2, right
- 2, top
+ 1);
157 XDrawLine(display
, pixmap
, penshadow
.gc(),
158 left
+ 1, top
+ 1, right
- 2, top
+ 1);
159 XDrawLine(display
, pixmap
, penshadow
.gc(),
160 left
+ 1, bottom
- 2, left
+ 1, top
+ 1);
168 Pixmap
BImage::render_gradient(const BTexture
&texture
) {
169 bool inverted
= False
;
171 interlaced
= texture
.texture() & BTexture::Interlaced
;
173 if (texture
.texture() & BTexture::Sunken
) {
174 from
= texture
.colorTo();
175 to
= texture
.color();
177 if (! (texture
.texture() & BTexture::Invert
)) inverted
= True
;
179 from
= texture
.color();
180 to
= texture
.colorTo();
182 if (texture
.texture() & BTexture::Invert
) inverted
= True
;
185 control
->getGradientBuffers(width
, height
, &xtable
, &ytable
);
187 if (texture
.texture() & BTexture::Diagonal
) dgradient();
188 else if (texture
.texture() & BTexture::Elliptic
) egradient();
189 else if (texture
.texture() & BTexture::Horizontal
) hgradient();
190 else if (texture
.texture() & BTexture::Pyramid
) pgradient();
191 else if (texture
.texture() & BTexture::Rectangle
) rgradient();
192 else if (texture
.texture() & BTexture::Vertical
) vgradient();
193 else if (texture
.texture() & BTexture::CrossDiagonal
) cdgradient();
194 else if (texture
.texture() & BTexture::PipeCross
) pcgradient();
196 if (texture
.texture() & BTexture::Bevel1
) bevel1();
197 else if (texture
.texture() & BTexture::Bevel2
) bevel2();
199 if (texture
.texture() & BTexture::Border
) border(texture
);
201 if (inverted
) invert();
203 return renderPixmap();
208 static const unsigned char dither4
[4][4] = {
217 * Helper function for TrueColorDither and renderXImage
219 * This handles the proper setting of the image data based on the image depth
220 * and the machine's byte ordering
223 void assignPixelData(unsigned int bit_depth
, unsigned char **data
,
224 unsigned long pixel
) {
225 unsigned char *pixel_data
= *data
;
228 *pixel_data
++ = pixel
;
231 case 16: // 16bpp LSB
232 *pixel_data
++ = pixel
;
233 *pixel_data
++ = pixel
>> 8;
236 case 17: // 16bpp MSB
237 *pixel_data
++ = pixel
>> 8;
238 *pixel_data
++ = pixel
;
241 case 24: // 24bpp LSB
242 *pixel_data
++ = pixel
;
243 *pixel_data
++ = pixel
>> 8;
244 *pixel_data
++ = pixel
>> 16;
247 case 25: // 24bpp MSB
248 *pixel_data
++ = pixel
>> 16;
249 *pixel_data
++ = pixel
>> 8;
250 *pixel_data
++ = pixel
;
253 case 32: // 32bpp LSB
254 *pixel_data
++ = pixel
;
255 *pixel_data
++ = pixel
>> 8;
256 *pixel_data
++ = pixel
>> 16;
257 *pixel_data
++ = pixel
>> 24;
260 case 33: // 32bpp MSB
261 *pixel_data
++ = pixel
>> 24;
262 *pixel_data
++ = pixel
>> 16;
263 *pixel_data
++ = pixel
>> 8;
264 *pixel_data
++ = pixel
;
267 *data
= pixel_data
; // assign back so we don't lose our place
271 // algorithm: ordered dithering... many many thanks to rasterman
272 // (raster@rasterman.com) for telling me about this... portions of this
273 // code is based off of his code in Imlib
274 void BImage::TrueColorDither(unsigned int bit_depth
, int bytes_per_line
,
275 unsigned char *pixel_data
) {
276 unsigned int x
, y
, dithx
, dithy
, r
, g
, b
, er
, eg
, eb
, offset
;
277 unsigned char *ppixel_data
= pixel_data
;
280 for (y
= 0, offset
= 0; y
< height
; y
++) {
283 for (x
= 0; x
< width
; x
++, offset
++) {
289 er
= r
& (red_bits
- 1);
290 eg
= g
& (green_bits
- 1);
291 eb
= b
& (blue_bits
- 1);
297 if ((dither4
[dithy
][dithx
] < er
) && (r
< red_table
[255])) r
++;
298 if ((dither4
[dithy
][dithx
] < eg
) && (g
< green_table
[255])) g
++;
299 if ((dither4
[dithy
][dithx
] < eb
) && (b
< blue_table
[255])) b
++;
301 pixel
= (r
<< red_offset
) | (g
<< green_offset
) | (b
<< blue_offset
);
302 assignPixelData(bit_depth
, &pixel_data
, pixel
);
305 pixel_data
= (ppixel_data
+= bytes_per_line
);
310 const static unsigned char dither8
[8][8] = {
311 { 0, 32, 8, 40, 2, 34, 10, 42},
312 { 48, 16, 56, 24, 50, 18, 58, 26},
313 { 12, 44, 4, 36, 14, 46, 6, 38},
314 { 60, 28, 52, 20, 62, 30, 54, 22},
315 { 3, 35, 11, 43, 1, 33, 9, 41},
316 { 51, 19, 59, 27, 49, 17, 57, 25},
317 { 15, 47, 7, 39, 13, 45, 5, 37},
318 { 63, 31, 55, 23, 61, 29, 53, 21}
321 void BImage::OrderedPseudoColorDither(int bytes_per_line
,
322 unsigned char *pixel_data
) {
323 unsigned int x
, y
, dithx
, dithy
, r
, g
, b
, er
, eg
, eb
, offset
;
325 unsigned char *ppixel_data
= pixel_data
;
327 for (y
= 0, offset
= 0; y
< height
; y
++) {
330 for (x
= 0; x
< width
; x
++, offset
++) {
337 er
= r
& (red_bits
- 1);
338 eg
= g
& (green_bits
- 1);
339 eb
= b
& (blue_bits
- 1);
345 if ((dither8
[dithy
][dithx
] < er
) && (r
< red_table
[255])) r
++;
346 if ((dither8
[dithy
][dithx
] < eg
) && (g
< green_table
[255])) g
++;
347 if ((dither8
[dithy
][dithx
] < eb
) && (b
< blue_table
[255])) b
++;
349 pixel
= (r
* cpccpc
) + (g
* cpc
) + b
;
350 *(pixel_data
++) = colors
[pixel
].pixel
;
353 pixel_data
= (ppixel_data
+= bytes_per_line
);
358 void BImage::PseudoColorDither(int bytes_per_line
, unsigned char *pixel_data
) {
360 *rerr
= new short[width
+ 2],
361 *gerr
= new short[width
+ 2],
362 *berr
= new short[width
+ 2],
363 *nrerr
= new short[width
+ 2],
364 *ngerr
= new short[width
+ 2],
365 *nberr
= new short[width
+ 2];
367 int rr
, gg
, bb
, rer
, ger
, ber
;
368 int dd
= 255 / control
->getColorsPerChannel();
369 unsigned int x
, y
, r
, g
, b
, offset
;
371 unsigned char *ppixel_data
= pixel_data
;
373 for (x
= 0; x
< width
; x
++) {
374 *(rerr
+ x
) = *(red
+ x
);
375 *(gerr
+ x
) = *(green
+ x
);
376 *(berr
+ x
) = *(blue
+ x
);
379 *(rerr
+ x
) = *(gerr
+ x
) = *(berr
+ x
) = 0;
381 for (y
= 0, offset
= 0; y
< height
; y
++) {
382 if (y
< (height
- 1)) {
383 int i
= offset
+ width
;
384 for (x
= 0; x
< width
; x
++, i
++) {
385 *(nrerr
+ x
) = *(red
+ i
);
386 *(ngerr
+ x
) = *(green
+ i
);
387 *(nberr
+ x
) = *(blue
+ i
);
390 *(nrerr
+ x
) = *(red
+ (--i
));
391 *(ngerr
+ x
) = *(green
+ i
);
392 *(nberr
+ x
) = *(blue
+ i
);
395 for (x
= 0; x
< width
; x
++) {
400 if (rr
> 255) rr
= 255; else if (rr
< 0) rr
= 0;
401 if (gg
> 255) gg
= 255; else if (gg
< 0) gg
= 0;
402 if (bb
> 255) bb
= 255; else if (bb
< 0) bb
= 0;
408 rer
= rerr
[x
] - r
*dd
;
409 ger
= gerr
[x
] - g
*dd
;
410 ber
= berr
[x
] - b
*dd
;
412 pixel
= (r
* cpccpc
) + (g
* cpc
) + b
;
413 *pixel_data
++ = colors
[pixel
].pixel
;
428 pixel_data
= (ppixel_data
+= bytes_per_line
);
451 XImage
*BImage::renderXImage(void) {
453 XCreateImage(control
->getBaseDisplay()->getXDisplay(),
454 control
->getVisual(), control
->getDepth(), ZPixmap
, 0, 0,
455 width
, height
, 32, 0);
458 fprintf(stderr
, i18n(ImageSet
, ImageErrorCreatingXImage
,
459 "BImage::renderXImage: error creating XImage\n"));
464 image
->data
= (char *) 0;
466 unsigned char *d
= new unsigned char[image
->bytes_per_line
* (height
+ 1)];
468 unsigned int o
= image
->bits_per_pixel
+
469 ((image
->byte_order
== MSBFirst
) ? 1 : 0);
471 bool unsupported
= False
;
473 if (control
->doDither() && width
> 1 && height
> 1) {
474 switch (control
->getVisual()->c_class
) {
476 TrueColorDither(o
, image
->bytes_per_line
, d
);
482 OrderedPseudoColorDither(image
->bytes_per_line
, d
);
484 PseudoColorDither(image
->bytes_per_line
, d
);
493 unsigned int x
, y
, r
, g
, b
, offset
;
494 unsigned char *pixel_data
= d
, *ppixel_data
= d
;
497 switch (control
->getVisual()->c_class
) {
500 for (y
= 0, offset
= 0; y
< height
; ++y
) {
501 for (x
= 0; x
< width
; ++x
, ++offset
) {
502 r
= red_table
[red
[offset
]];
503 g
= green_table
[green
[offset
]];
504 b
= blue_table
[blue
[offset
]];
506 pixel
= (r
* cpccpc
) + (g
* cpc
) + b
;
507 *pixel_data
++ = colors
[pixel
].pixel
;
510 pixel_data
= (ppixel_data
+= image
->bytes_per_line
);
516 for (y
= 0, offset
= 0; y
< height
; y
++) {
517 for (x
= 0; x
< width
; x
++, offset
++) {
518 r
= red_table
[red
[offset
]];
519 g
= green_table
[green
[offset
]];
520 b
= blue_table
[blue
[offset
]];
522 pixel
= (r
<< red_offset
) | (g
<< green_offset
) | (b
<< blue_offset
);
523 assignPixelData(o
, &pixel_data
, pixel
);
526 pixel_data
= (ppixel_data
+= image
->bytes_per_line
);
533 for (y
= 0, offset
= 0; y
< height
; y
++) {
534 for (x
= 0; x
< width
; x
++, offset
++) {
535 r
= *(red_table
+ *(red
+ offset
));
536 g
= *(green_table
+ *(green
+ offset
));
537 b
= *(blue_table
+ *(blue
+ offset
));
539 g
= ((r
* 30) + (g
* 59) + (b
* 11)) / 100;
540 *pixel_data
++ = colors
[g
].pixel
;
543 pixel_data
= (ppixel_data
+= image
->bytes_per_line
);
554 fprintf(stderr
, i18n(ImageSet
, ImageUnsupVisual
,
555 "BImage::renderXImage: unsupported visual\n"));
557 XDestroyImage(image
);
561 image
->data
= (char *) d
;
567 Pixmap
BImage::renderPixmap(void) {
569 XCreatePixmap(control
->getBaseDisplay()->getXDisplay(),
570 control
->getDrawable(), width
, height
, control
->getDepth());
572 if (pixmap
== None
) {
573 fprintf(stderr
, i18n(ImageSet
, ImageErrorCreatingPixmap
,
574 "BImage::renderPixmap: error creating pixmap\n"));
578 XImage
*image
= renderXImage();
581 XFreePixmap(control
->getBaseDisplay()->getXDisplay(), pixmap
);
586 XDestroyImage(image
);
587 XFreePixmap(control
->getBaseDisplay()->getXDisplay(), pixmap
);
591 XPutImage(control
->getBaseDisplay()->getXDisplay(), pixmap
,
592 DefaultGC(control
->getBaseDisplay()->getXDisplay(),
593 control
->getScreenInfo()->getScreenNumber()),
594 image
, 0, 0, 0, 0, width
, height
);
597 delete [] image
->data
;
601 XDestroyImage(image
);
607 void BImage::bevel1(void) {
608 if (width
> 2 && height
> 2) {
609 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
611 register unsigned char r
, g
, b
, rr
,gg
,bb
;
612 register unsigned int w
= width
, h
= height
- 1, wh
= w
* h
;
630 rr
= (r
>> 2) + (r
>> 1);
633 gg
= (g
>> 2) + (g
>> 1);
636 bb
= (b
>> 2) + (b
>> 1);
659 rr
= (r
>> 2) + (r
>> 1);
662 gg
= (g
>> 2) + (g
>> 1);
665 bb
= (b
>> 2) + (b
>> 1);
696 rr
= (r
>> 2) + (r
>> 1);
699 gg
= (g
>> 2) + (g
>> 1);
702 bb
= (b
>> 2) + (b
>> 1);
729 rr
= (r
>> 2) + (r
>> 1);
732 gg
= (g
>> 2) + (g
>> 1);
735 bb
= (b
>> 2) + (b
>> 1);
745 void BImage::bevel2(void) {
746 if (width
> 4 && height
> 4) {
747 unsigned char r
, g
, b
, rr
,gg
,bb
, *pr
= red
+ width
+ 1,
748 *pg
= green
+ width
+ 1, *pb
= blue
+ width
+ 1;
749 unsigned int w
= width
- 2, h
= height
- 1, wh
= width
* (height
- 3);
767 rr
= (r
>> 2) + (r
>> 1);
770 gg
= (g
>> 2) + (g
>> 1);
773 bb
= (b
>> 2) + (b
>> 1);
805 rr
= (r
>> 2) + (r
>> 1);
808 gg
= (g
>> 2) + (g
>> 1);
811 bb
= (b
>> 2) + (b
>> 1);
824 void BImage::border(const BTexture
&texture
) {
825 register unsigned int i
;
826 int r
= texture
.borderColor().red(),
827 g
= texture
.borderColor().green(),
828 b
= texture
.borderColor().blue();
830 unsigned char *pr
, *pg
, *pb
;
836 for (i
= 0; i
< width
; ++i
) {
842 // left and right lines (pr,pg,pb are already lined up)
843 for (i
= 1; i
< height
- 1; ++i
) {
855 // bottom line (pr,pg,pb are already lined up)
856 for (i
= 0; i
< width
; ++i
) {
864 void BImage::invert(void) {
865 register unsigned int i
, j
, wh
= (width
* height
) - 1;
868 for (i
= 0, j
= wh
; j
> i
; j
--, i
++) {
870 *(red
+ j
) = *(red
+ i
);
874 *(green
+ j
) = *(green
+ i
);
878 *(blue
+ j
) = *(blue
+ i
);
884 void BImage::dgradient(void) {
885 // diagonal gradient code was written by Mike Cole <mike@mydot.com>
886 // modified for interlacing by Brad Hughes
888 float drx
, dgx
, dbx
, dry
, dgy
, dby
, yr
= 0.0, yg
= 0.0, yb
= 0.0,
889 xr
= (float) from
.red(),
890 xg
= (float) from
.green(),
891 xb
= (float) from
.blue();
892 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
893 unsigned int w
= width
* 2, h
= height
* 2, *xt
= xtable
, *yt
= ytable
;
895 register unsigned int x
, y
;
897 dry
= drx
= (float) (to
.red() - from
.red());
898 dgy
= dgx
= (float) (to
.green() - from
.green());
899 dby
= dbx
= (float) (to
.blue() - from
.blue());
906 for (x
= 0; x
< width
; x
++) {
907 *(xt
++) = (unsigned char) (xr
);
908 *(xt
++) = (unsigned char) (xg
);
909 *(xt
++) = (unsigned char) (xb
);
921 for (y
= 0; y
< height
; y
++) {
922 *(yt
++) = ((unsigned char) yr
);
923 *(yt
++) = ((unsigned char) yg
);
924 *(yt
++) = ((unsigned char) yb
);
931 // Combine tables to create gradient
935 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
936 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
937 *(pr
++) = *(xt
++) + *(yt
);
938 *(pg
++) = *(xt
++) + *(yt
+ 1);
939 *(pb
++) = *(xt
++) + *(yt
+ 2);
943 // faked interlacing effect
944 unsigned char channel
, channel2
;
946 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
947 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
949 channel
= *(xt
++) + *(yt
);
950 channel2
= (channel
>> 1) + (channel
>> 2);
951 if (channel2
> channel
) channel2
= 0;
954 channel
= *(xt
++) + *(yt
+ 1);
955 channel2
= (channel
>> 1) + (channel
>> 2);
956 if (channel2
> channel
) channel2
= 0;
959 channel
= *(xt
++) + *(yt
+ 2);
960 channel2
= (channel
>> 1) + (channel
>> 2);
961 if (channel2
> channel
) channel2
= 0;
964 channel
= *(xt
++) + *(yt
);
965 channel2
= channel
+ (channel
>> 3);
966 if (channel2
< channel
) channel2
= ~0;
969 channel
= *(xt
++) + *(yt
+ 1);
970 channel2
= channel
+ (channel
>> 3);
971 if (channel2
< channel
) channel2
= ~0;
974 channel
= *(xt
++) + *(yt
+ 2);
975 channel2
= channel
+ (channel
>> 3);
976 if (channel2
< channel
) channel2
= ~0;
985 void BImage::hgradient(void) {
987 xr
= (float) from
.red(),
988 xg
= (float) from
.green(),
989 xb
= (float) from
.blue();
990 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
992 register unsigned int x
, y
;
994 drx
= (float) (to
.red() - from
.red());
995 dgx
= (float) (to
.green() - from
.green());
996 dbx
= (float) (to
.blue() - from
.blue());
1002 if (interlaced
&& height
> 2) {
1003 // faked interlacing effect
1004 unsigned char channel
, channel2
;
1006 for (x
= 0; x
< width
; x
++, pr
++, pg
++, pb
++) {
1007 channel
= (unsigned char) xr
;
1008 channel2
= (channel
>> 1) + (channel
>> 2);
1009 if (channel2
> channel
) channel2
= 0;
1012 channel
= (unsigned char) xg
;
1013 channel2
= (channel
>> 1) + (channel
>> 2);
1014 if (channel2
> channel
) channel2
= 0;
1017 channel
= (unsigned char) xb
;
1018 channel2
= (channel
>> 1) + (channel
>> 2);
1019 if (channel2
> channel
) channel2
= 0;
1023 channel
= (unsigned char) xr
;
1024 channel2
= channel
+ (channel
>> 3);
1025 if (channel2
< channel
) channel2
= ~0;
1026 *(pr
+ width
) = channel2
;
1028 channel
= (unsigned char) xg
;
1029 channel2
= channel
+ (channel
>> 3);
1030 if (channel2
< channel
) channel2
= ~0;
1031 *(pg
+ width
) = channel2
;
1033 channel
= (unsigned char) xb
;
1034 channel2
= channel
+ (channel
>> 3);
1035 if (channel2
< channel
) channel2
= ~0;
1036 *(pb
+ width
) = channel2
;
1049 for (y
= 2; y
< height
; y
++, pr
+= width
, pg
+= width
, pb
+= width
) {
1050 if (y
& 1) offset
= width
; else offset
= 0;
1052 memcpy(pr
, (red
+ offset
), width
);
1053 memcpy(pg
, (green
+ offset
), width
);
1054 memcpy(pb
, (blue
+ offset
), width
);
1058 for (x
= 0; x
< width
; x
++) {
1059 *(pr
++) = (unsigned char) (xr
);
1060 *(pg
++) = (unsigned char) (xg
);
1061 *(pb
++) = (unsigned char) (xb
);
1068 for (y
= 1; y
< height
; y
++, pr
+= width
, pg
+= width
, pb
+= width
) {
1069 memcpy(pr
, red
, width
);
1070 memcpy(pg
, green
, width
);
1071 memcpy(pb
, blue
, width
);
1077 void BImage::vgradient(void) {
1078 float dry
, dgy
, dby
,
1079 yr
= (float) from
.red(),
1080 yg
= (float) from
.green(),
1081 yb
= (float) from
.blue();
1082 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1084 register unsigned int y
;
1086 dry
= (float) (to
.red() - from
.red());
1087 dgy
= (float) (to
.green() - from
.green());
1088 dby
= (float) (to
.blue() - from
.blue());
1095 // faked interlacing effect
1096 unsigned char channel
, channel2
;
1098 for (y
= 0; y
< height
; y
++, pr
+= width
, pg
+= width
, pb
+= width
) {
1100 channel
= (unsigned char) yr
;
1101 channel2
= (channel
>> 1) + (channel
>> 2);
1102 if (channel2
> channel
) channel2
= 0;
1103 memset(pr
, channel2
, width
);
1105 channel
= (unsigned char) yg
;
1106 channel2
= (channel
>> 1) + (channel
>> 2);
1107 if (channel2
> channel
) channel2
= 0;
1108 memset(pg
, channel2
, width
);
1110 channel
= (unsigned char) yb
;
1111 channel2
= (channel
>> 1) + (channel
>> 2);
1112 if (channel2
> channel
) channel2
= 0;
1113 memset(pb
, channel2
, width
);
1115 channel
= (unsigned char) yr
;
1116 channel2
= channel
+ (channel
>> 3);
1117 if (channel2
< channel
) channel2
= ~0;
1118 memset(pr
, channel2
, width
);
1120 channel
= (unsigned char) yg
;
1121 channel2
= channel
+ (channel
>> 3);
1122 if (channel2
< channel
) channel2
= ~0;
1123 memset(pg
, channel2
, width
);
1125 channel
= (unsigned char) yb
;
1126 channel2
= channel
+ (channel
>> 3);
1127 if (channel2
< channel
) channel2
= ~0;
1128 memset(pb
, channel2
, width
);
1137 for (y
= 0; y
< height
; y
++, pr
+= width
, pg
+= width
, pb
+= width
) {
1138 memset(pr
, (unsigned char) yr
, width
);
1139 memset(pg
, (unsigned char) yg
, width
);
1140 memset(pb
, (unsigned char) yb
, width
);
1150 void BImage::pgradient(void) {
1151 // pyramid gradient - based on original dgradient, written by
1152 // Mosfet (mosfet@kde.org)
1153 // adapted from kde sources for Blackbox by Brad Hughes
1155 float yr
, yg
, yb
, drx
, dgx
, dbx
, dry
, dgy
, dby
,
1157 int rsign
, gsign
, bsign
;
1158 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1159 unsigned int tr
= to
.red(), tg
= to
.green(), tb
= to
.blue(),
1160 *xt
= xtable
, *yt
= ytable
;
1162 register unsigned int x
, y
;
1164 dry
= drx
= (float) (to
.red() - from
.red());
1165 dgy
= dgx
= (float) (to
.green() - from
.green());
1166 dby
= dbx
= (float) (to
.blue() - from
.blue());
1168 rsign
= (drx
< 0) ? -1 : 1;
1169 gsign
= (dgx
< 0) ? -1 : 1;
1170 bsign
= (dbx
< 0) ? -1 : 1;
1172 xr
= yr
= (drx
/ 2);
1173 xg
= yg
= (dgx
/ 2);
1174 xb
= yb
= (dbx
/ 2);
1181 for (x
= 0; x
< width
; x
++) {
1182 *(xt
++) = (unsigned char) ((xr
< 0) ? -xr
: xr
);
1183 *(xt
++) = (unsigned char) ((xg
< 0) ? -xg
: xg
);
1184 *(xt
++) = (unsigned char) ((xb
< 0) ? -xb
: xb
);
1196 for (y
= 0; y
< height
; y
++) {
1197 *(yt
++) = ((unsigned char) ((yr
< 0) ? -yr
: yr
));
1198 *(yt
++) = ((unsigned char) ((yg
< 0) ? -yg
: yg
));
1199 *(yt
++) = ((unsigned char) ((yb
< 0) ? -yb
: yb
));
1206 // Combine tables to create gradient
1210 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1211 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1212 *(pr
++) = (unsigned char) (tr
- (rsign
* (*(xt
++) + *(yt
))));
1213 *(pg
++) = (unsigned char) (tg
- (gsign
* (*(xt
++) + *(yt
+ 1))));
1214 *(pb
++) = (unsigned char) (tb
- (bsign
* (*(xt
++) + *(yt
+ 2))));
1218 // faked interlacing effect
1219 unsigned char channel
, channel2
;
1221 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1222 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1224 channel
= (unsigned char) (tr
- (rsign
* (*(xt
++) + *(yt
))));
1225 channel2
= (channel
>> 1) + (channel
>> 2);
1226 if (channel2
> channel
) channel2
= 0;
1229 channel
= (unsigned char) (tg
- (gsign
* (*(xt
++) + *(yt
+ 1))));
1230 channel2
= (channel
>> 1) + (channel
>> 2);
1231 if (channel2
> channel
) channel2
= 0;
1234 channel
= (unsigned char) (tb
- (bsign
* (*(xt
++) + *(yt
+ 2))));
1235 channel2
= (channel
>> 1) + (channel
>> 2);
1236 if (channel2
> channel
) channel2
= 0;
1239 channel
= (unsigned char) (tr
- (rsign
* (*(xt
++) + *(yt
))));
1240 channel2
= channel
+ (channel
>> 3);
1241 if (channel2
< channel
) channel2
= ~0;
1244 channel
= (unsigned char) (tg
- (gsign
* (*(xt
++) + *(yt
+ 1))));
1245 channel2
= channel
+ (channel
>> 3);
1246 if (channel2
< channel
) channel2
= ~0;
1249 channel
= (unsigned char) (tb
- (bsign
* (*(xt
++) + *(yt
+ 2))));
1250 channel2
= channel
+ (channel
>> 3);
1251 if (channel2
< channel
) channel2
= ~0;
1260 void BImage::rgradient(void) {
1261 // rectangle gradient - based on original dgradient, written by
1262 // Mosfet (mosfet@kde.org)
1263 // adapted from kde sources for Blackbox by Brad Hughes
1265 float drx
, dgx
, dbx
, dry
, dgy
, dby
, xr
, xg
, xb
, yr
, yg
, yb
;
1266 int rsign
, gsign
, bsign
;
1267 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1268 unsigned int tr
= to
.red(), tg
= to
.green(), tb
= to
.blue(),
1269 *xt
= xtable
, *yt
= ytable
;
1271 register unsigned int x
, y
;
1273 dry
= drx
= (float) (to
.red() - from
.red());
1274 dgy
= dgx
= (float) (to
.green() - from
.green());
1275 dby
= dbx
= (float) (to
.blue() - from
.blue());
1277 rsign
= (drx
< 0) ? -2 : 2;
1278 gsign
= (dgx
< 0) ? -2 : 2;
1279 bsign
= (dbx
< 0) ? -2 : 2;
1281 xr
= yr
= (drx
/ 2);
1282 xg
= yg
= (dgx
/ 2);
1283 xb
= yb
= (dbx
/ 2);
1290 for (x
= 0; x
< width
; x
++) {
1291 *(xt
++) = (unsigned char) ((xr
< 0) ? -xr
: xr
);
1292 *(xt
++) = (unsigned char) ((xg
< 0) ? -xg
: xg
);
1293 *(xt
++) = (unsigned char) ((xb
< 0) ? -xb
: xb
);
1305 for (y
= 0; y
< height
; y
++) {
1306 *(yt
++) = ((unsigned char) ((yr
< 0) ? -yr
: yr
));
1307 *(yt
++) = ((unsigned char) ((yg
< 0) ? -yg
: yg
));
1308 *(yt
++) = ((unsigned char) ((yb
< 0) ? -yb
: yb
));
1315 // Combine tables to create gradient
1319 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1320 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1321 *(pr
++) = (unsigned char) (tr
- (rsign
* max(*(xt
++), *(yt
))));
1322 *(pg
++) = (unsigned char) (tg
- (gsign
* max(*(xt
++), *(yt
+ 1))));
1323 *(pb
++) = (unsigned char) (tb
- (bsign
* max(*(xt
++), *(yt
+ 2))));
1327 // faked interlacing effect
1328 unsigned char channel
, channel2
;
1330 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1331 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1333 channel
= (unsigned char) (tr
- (rsign
* max(*(xt
++), *(yt
))));
1334 channel2
= (channel
>> 1) + (channel
>> 2);
1335 if (channel2
> channel
) channel2
= 0;
1338 channel
= (unsigned char) (tg
- (gsign
* max(*(xt
++), *(yt
+ 1))));
1339 channel2
= (channel
>> 1) + (channel
>> 2);
1340 if (channel2
> channel
) channel2
= 0;
1343 channel
= (unsigned char) (tb
- (bsign
* max(*(xt
++), *(yt
+ 2))));
1344 channel2
= (channel
>> 1) + (channel
>> 2);
1345 if (channel2
> channel
) channel2
= 0;
1348 channel
= (unsigned char) (tr
- (rsign
* max(*(xt
++), *(yt
))));
1349 channel2
= channel
+ (channel
>> 3);
1350 if (channel2
< channel
) channel2
= ~0;
1353 channel
= (unsigned char) (tg
- (gsign
* max(*(xt
++), *(yt
+ 1))));
1354 channel2
= channel
+ (channel
>> 3);
1355 if (channel2
< channel
) channel2
= ~0;
1358 channel
= (unsigned char) (tb
- (bsign
* max(*(xt
++), *(yt
+ 2))));
1359 channel2
= channel
+ (channel
>> 3);
1360 if (channel2
< channel
) channel2
= ~0;
1369 void BImage::egradient(void) {
1370 // elliptic gradient - based on original dgradient, written by
1371 // Mosfet (mosfet@kde.org)
1372 // adapted from kde sources for Blackbox by Brad Hughes
1374 float drx
, dgx
, dbx
, dry
, dgy
, dby
, yr
, yg
, yb
, xr
, xg
, xb
;
1375 int rsign
, gsign
, bsign
;
1376 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1377 unsigned int *xt
= xtable
, *yt
= ytable
,
1378 tr
= (unsigned long) to
.red(),
1379 tg
= (unsigned long) to
.green(),
1380 tb
= (unsigned long) to
.blue();
1382 register unsigned int x
, y
;
1384 dry
= drx
= (float) (to
.red() - from
.red());
1385 dgy
= dgx
= (float) (to
.green() - from
.green());
1386 dby
= dbx
= (float) (to
.blue() - from
.blue());
1388 rsign
= (drx
< 0) ? -1 : 1;
1389 gsign
= (dgx
< 0) ? -1 : 1;
1390 bsign
= (dbx
< 0) ? -1 : 1;
1392 xr
= yr
= (drx
/ 2);
1393 xg
= yg
= (dgx
/ 2);
1394 xb
= yb
= (dbx
/ 2);
1401 for (x
= 0; x
< width
; x
++) {
1402 *(xt
++) = (unsigned long) (xr
* xr
);
1403 *(xt
++) = (unsigned long) (xg
* xg
);
1404 *(xt
++) = (unsigned long) (xb
* xb
);
1416 for (y
= 0; y
< height
; y
++) {
1417 *(yt
++) = (unsigned long) (yr
* yr
);
1418 *(yt
++) = (unsigned long) (yg
* yg
);
1419 *(yt
++) = (unsigned long) (yb
* yb
);
1426 // Combine tables to create gradient
1430 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1431 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1432 *(pr
++) = (unsigned char)
1433 (tr
- (rsign
* control
->getSqrt(*(xt
++) + *(yt
))));
1434 *(pg
++) = (unsigned char)
1435 (tg
- (gsign
* control
->getSqrt(*(xt
++) + *(yt
+ 1))));
1436 *(pb
++) = (unsigned char)
1437 (tb
- (bsign
* control
->getSqrt(*(xt
++) + *(yt
+ 2))));
1441 // faked interlacing effect
1442 unsigned char channel
, channel2
;
1444 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1445 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1447 channel
= (unsigned char)
1448 (tr
- (rsign
* control
->getSqrt(*(xt
++) + *(yt
))));
1449 channel2
= (channel
>> 1) + (channel
>> 2);
1450 if (channel2
> channel
) channel2
= 0;
1453 channel
= (unsigned char)
1454 (tg
- (gsign
* control
->getSqrt(*(xt
++) + *(yt
+ 1))));
1455 channel2
= (channel
>> 1) + (channel
>> 2);
1456 if (channel2
> channel
) channel2
= 0;
1459 channel
= (unsigned char)
1460 (tb
- (bsign
* control
->getSqrt(*(xt
++) + *(yt
+ 2))));
1461 channel2
= (channel
>> 1) + (channel
>> 2);
1462 if (channel2
> channel
) channel2
= 0;
1465 channel
= (unsigned char)
1466 (tr
- (rsign
* control
->getSqrt(*(xt
++) + *(yt
))));
1467 channel2
= channel
+ (channel
>> 3);
1468 if (channel2
< channel
) channel2
= ~0;
1471 channel
= (unsigned char)
1472 (tg
- (gsign
* control
->getSqrt(*(xt
++) + *(yt
+ 1))));
1473 channel2
= channel
+ (channel
>> 3);
1474 if (channel2
< channel
) channel2
= ~0;
1477 channel
= (unsigned char)
1478 (tb
- (bsign
* control
->getSqrt(*(xt
++) + *(yt
+ 2))));
1479 channel2
= channel
+ (channel
>> 3);
1480 if (channel2
< channel
) channel2
= ~0;
1489 void BImage::pcgradient(void) {
1490 // pipe cross gradient - based on original dgradient, written by
1491 // Mosfet (mosfet@kde.org)
1492 // adapted from kde sources for Blackbox by Brad Hughes
1494 float drx
, dgx
, dbx
, dry
, dgy
, dby
, xr
, xg
, xb
, yr
, yg
, yb
;
1495 int rsign
, gsign
, bsign
;
1496 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1497 unsigned int *xt
= xtable
, *yt
= ytable
,
1502 register unsigned int x
, y
;
1504 dry
= drx
= (float) (to
.red() - from
.red());
1505 dgy
= dgx
= (float) (to
.green() - from
.green());
1506 dby
= dbx
= (float) (to
.blue() - from
.blue());
1508 rsign
= (drx
< 0) ? -2 : 2;
1509 gsign
= (dgx
< 0) ? -2 : 2;
1510 bsign
= (dbx
< 0) ? -2 : 2;
1512 xr
= yr
= (drx
/ 2);
1513 xg
= yg
= (dgx
/ 2);
1514 xb
= yb
= (dbx
/ 2);
1521 for (x
= 0; x
< width
; x
++) {
1522 *(xt
++) = (unsigned char) ((xr
< 0) ? -xr
: xr
);
1523 *(xt
++) = (unsigned char) ((xg
< 0) ? -xg
: xg
);
1524 *(xt
++) = (unsigned char) ((xb
< 0) ? -xb
: xb
);
1536 for (y
= 0; y
< height
; y
++) {
1537 *(yt
++) = ((unsigned char) ((yr
< 0) ? -yr
: yr
));
1538 *(yt
++) = ((unsigned char) ((yg
< 0) ? -yg
: yg
));
1539 *(yt
++) = ((unsigned char) ((yb
< 0) ? -yb
: yb
));
1546 // Combine tables to create gradient
1549 // normal pcgradient
1550 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1551 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1552 *(pr
++) = (unsigned char) (tr
- (rsign
* min(*(xt
++), *(yt
))));
1553 *(pg
++) = (unsigned char) (tg
- (gsign
* min(*(xt
++), *(yt
+ 1))));
1554 *(pb
++) = (unsigned char) (tb
- (bsign
* min(*(xt
++), *(yt
+ 2))));
1558 // faked interlacing effect
1559 unsigned char channel
, channel2
;
1561 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1562 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1564 channel
= (unsigned char) (tr
- (rsign
* min(*(xt
++), *(yt
))));
1565 channel2
= (channel
>> 1) + (channel
>> 2);
1566 if (channel2
> channel
) channel2
= 0;
1569 channel
= (unsigned char) (tg
- (bsign
* min(*(xt
++), *(yt
+ 1))));
1570 channel2
= (channel
>> 1) + (channel
>> 2);
1571 if (channel2
> channel
) channel2
= 0;
1574 channel
= (unsigned char) (tb
- (gsign
* min(*(xt
++), *(yt
+ 2))));
1575 channel2
= (channel
>> 1) + (channel
>> 2);
1576 if (channel2
> channel
) channel2
= 0;
1579 channel
= (unsigned char) (tr
- (rsign
* min(*(xt
++), *(yt
))));
1580 channel2
= channel
+ (channel
>> 3);
1581 if (channel2
< channel
) channel2
= ~0;
1584 channel
= (unsigned char) (tg
- (gsign
* min(*(xt
++), *(yt
+ 1))));
1585 channel2
= channel
+ (channel
>> 3);
1586 if (channel2
< channel
) channel2
= ~0;
1589 channel
= (unsigned char) (tb
- (bsign
* min(*(xt
++), *(yt
+ 2))));
1590 channel2
= channel
+ (channel
>> 3);
1591 if (channel2
< channel
) channel2
= ~0;
1600 void BImage::cdgradient(void) {
1601 // cross diagonal gradient - based on original dgradient, written by
1602 // Mosfet (mosfet@kde.org)
1603 // adapted from kde sources for Blackbox by Brad Hughes
1605 float drx
, dgx
, dbx
, dry
, dgy
, dby
, yr
= 0.0, yg
= 0.0, yb
= 0.0,
1606 xr
= (float) from
.red(),
1607 xg
= (float) from
.green(),
1608 xb
= (float) from
.blue();
1609 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1610 unsigned int w
= width
* 2, h
= height
* 2, *xt
, *yt
;
1612 register unsigned int x
, y
;
1614 dry
= drx
= (float) (to
.red() - from
.red());
1615 dgy
= dgx
= (float) (to
.green() - from
.green());
1616 dby
= dbx
= (float) (to
.blue() - from
.blue());
1623 for (xt
= (xtable
+ (width
* 3) - 1), x
= 0; x
< width
; x
++) {
1624 *(xt
--) = (unsigned char) xb
;
1625 *(xt
--) = (unsigned char) xg
;
1626 *(xt
--) = (unsigned char) xr
;
1638 for (yt
= ytable
, y
= 0; y
< height
; y
++) {
1639 *(yt
++) = (unsigned char) yr
;
1640 *(yt
++) = (unsigned char) yg
;
1641 *(yt
++) = (unsigned char) yb
;
1648 // Combine tables to create gradient
1651 // normal cdgradient
1652 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1653 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1654 *(pr
++) = *(xt
++) + *(yt
);
1655 *(pg
++) = *(xt
++) + *(yt
+ 1);
1656 *(pb
++) = *(xt
++) + *(yt
+ 2);
1660 // faked interlacing effect
1661 unsigned char channel
, channel2
;
1663 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1664 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1666 channel
= *(xt
++) + *(yt
);
1667 channel2
= (channel
>> 1) + (channel
>> 2);
1668 if (channel2
> channel
) channel2
= 0;
1671 channel
= *(xt
++) + *(yt
+ 1);
1672 channel2
= (channel
>> 1) + (channel
>> 2);
1673 if (channel2
> channel
) channel2
= 0;
1676 channel
= *(xt
++) + *(yt
+ 2);
1677 channel2
= (channel
>> 1) + (channel
>> 2);
1678 if (channel2
> channel
) channel2
= 0;
1681 channel
= *(xt
++) + *(yt
);
1682 channel2
= channel
+ (channel
>> 3);
1683 if (channel2
< channel
) channel2
= ~0;
1686 channel
= *(xt
++) + *(yt
+ 1);
1687 channel2
= channel
+ (channel
>> 3);
1688 if (channel2
< channel
) channel2
= ~0;
1691 channel
= *(xt
++) + *(yt
+ 2);
1692 channel2
= channel
+ (channel
>> 3);
1693 if (channel2
< channel
) channel2
= ~0;