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"
37 #include "basedisplay.hh"
43 BImage::BImage(BImageControl
*c
, int w
, int h
) {
46 width
= (w
> 0) ? w
: 1;
47 height
= (h
> 0) ? h
: 1;
49 red
= new unsigned char[width
* height
];
50 green
= new unsigned char[width
* height
];
51 blue
= new unsigned char[width
* height
];
53 xtable
= ytable
= (unsigned int *) 0;
55 cpc
= control
->getColorsPerChannel();
58 control
->getColorTables(&red_table
, &green_table
, &blue_table
,
59 &red_offset
, &green_offset
, &blue_offset
,
60 &red_bits
, &green_bits
, &blue_bits
);
62 if (control
->getVisual()->c_class
!= TrueColor
)
63 control
->getXColorTable(&colors
, &ncolors
);
67 BImage::~BImage(void) {
74 Pixmap
BImage::render(const BTexture
&texture
) {
75 if (texture
.texture() & BTexture::Parent_Relative
)
76 return ParentRelative
;
77 else if (texture
.texture() & BTexture::Solid
)
78 return render_solid(texture
);
79 else if (texture
.texture() & BTexture::Gradient
)
80 return render_gradient(texture
);
85 Pixmap
BImage::render_solid(const BTexture
&texture
) {
86 Pixmap pixmap
= XCreatePixmap(control
->getBaseDisplay()->getXDisplay(),
87 control
->getDrawable(), width
,
88 height
, control
->getDepth());
90 fprintf(stderr
, i18n(ImageSet
, ImageErrorCreatingSolidPixmap
,
91 "BImage::render_solid: error creating pixmap\n"));
95 Display
*display
= control
->getBaseDisplay()->getXDisplay();
97 BPen
pen(texture
.color());
98 BPen
penlight(texture
.lightColor());
99 BPen
penshadow(texture
.shadowColor());
101 XFillRectangle(display
, pixmap
, pen
.gc(), 0, 0, width
, height
);
103 if (texture
.texture() & BTexture::Interlaced
) {
104 BPen
peninterlace(texture
.colorTo());
105 for (unsigned int i
= 0; i
< height
; i
+= 2)
106 XDrawLine(display
, pixmap
, peninterlace
.gc(), 0, i
, width
, i
);
109 int left
= 0, top
= 0, right
= width
- 1, bottom
= height
- 1;
111 if (texture
.texture() & BTexture::Border
) {
112 BPen
penborder(texture
.borderColor());
113 XDrawRectangle(display
, pixmap
, penborder
.gc(),
114 left
, top
, right
, bottom
);
117 if (texture
.texture() & BTexture::Bevel1
) {
118 if (texture
.texture() & BTexture::Raised
) {
119 XDrawLine(display
, pixmap
, penshadow
.gc(),
120 left
, bottom
, right
, bottom
);
121 XDrawLine(display
, pixmap
, penshadow
.gc(),
122 right
, bottom
, right
, top
);
124 XDrawLine(display
, pixmap
, penlight
.gc(),
125 left
, top
, right
, top
);
126 XDrawLine(display
, pixmap
, penlight
.gc(),
127 left
, bottom
, left
, top
);
128 } else if (texture
.texture() & BTexture::Sunken
) {
129 XDrawLine(display
, pixmap
, penlight
.gc(),
130 left
, bottom
, right
, bottom
);
131 XDrawLine(display
, pixmap
, penlight
.gc(),
132 right
, bottom
, right
, top
);
134 XDrawLine(display
, pixmap
, penshadow
.gc(),
135 left
, top
, right
, top
);
136 XDrawLine(display
, pixmap
, penshadow
.gc(),
137 left
, bottom
, left
, top
);
139 } else if (texture
.texture() & BTexture::Bevel2
) {
140 if (texture
.texture() & BTexture::Raised
) {
141 XDrawLine(display
, pixmap
, penshadow
.gc(),
142 left
+ 1, bottom
- 2, right
- 2, bottom
- 2);
143 XDrawLine(display
, pixmap
, penshadow
.gc(),
144 right
- 2, bottom
- 2, right
- 2, top
+ 1);
146 XDrawLine(display
, pixmap
, penlight
.gc(),
147 left
+ 1, top
+ 1, right
- 2, top
+ 1);
148 XDrawLine(display
, pixmap
, penlight
.gc(),
149 left
+ 1, bottom
- 2, left
+ 1, top
+ 1);
150 } else if (texture
.texture() & BTexture::Sunken
) {
151 XDrawLine(display
, pixmap
, penlight
.gc(),
152 left
+ 1, bottom
- 2, right
- 2, bottom
- 2);
153 XDrawLine(display
, pixmap
, penlight
.gc(),
154 right
- 2, bottom
- 2, right
- 2, top
+ 1);
156 XDrawLine(display
, pixmap
, penshadow
.gc(),
157 left
+ 1, top
+ 1, right
- 2, top
+ 1);
158 XDrawLine(display
, pixmap
, penshadow
.gc(),
159 left
+ 1, bottom
- 2, left
+ 1, top
+ 1);
167 Pixmap
BImage::render_gradient(const BTexture
&texture
) {
168 bool inverted
= False
;
170 interlaced
= texture
.texture() & BTexture::Interlaced
;
172 if (texture
.texture() & BTexture::Sunken
) {
173 from
= texture
.colorTo();
174 to
= texture
.color();
176 if (! (texture
.texture() & BTexture::Invert
)) inverted
= True
;
178 from
= texture
.color();
179 to
= texture
.colorTo();
181 if (texture
.texture() & BTexture::Invert
) inverted
= True
;
184 control
->getGradientBuffers(width
, height
, &xtable
, &ytable
);
186 if (texture
.texture() & BTexture::Diagonal
) dgradient();
187 else if (texture
.texture() & BTexture::Elliptic
) egradient();
188 else if (texture
.texture() & BTexture::Horizontal
) hgradient();
189 else if (texture
.texture() & BTexture::Pyramid
) pgradient();
190 else if (texture
.texture() & BTexture::Rectangle
) rgradient();
191 else if (texture
.texture() & BTexture::Vertical
) vgradient();
192 else if (texture
.texture() & BTexture::CrossDiagonal
) cdgradient();
193 else if (texture
.texture() & BTexture::PipeCross
) pcgradient();
195 if (texture
.texture() & BTexture::Bevel1
) bevel1();
196 else if (texture
.texture() & BTexture::Bevel2
) bevel2();
198 if (texture
.texture() & BTexture::Border
) border(texture
);
200 if (inverted
) invert();
202 return renderPixmap();
207 static const unsigned char dither4
[4][4] = {
216 * Helper function for TrueColorDither and renderXImage
218 * This handles the proper setting of the image data based on the image depth
219 * and the machine's byte ordering
222 void assignPixelData(unsigned int bit_depth
, unsigned char **data
,
223 unsigned long pixel
) {
224 unsigned char *pixel_data
= *data
;
227 *pixel_data
++ = pixel
;
230 case 16: // 16bpp LSB
231 *pixel_data
++ = pixel
;
232 *pixel_data
++ = pixel
>> 8;
235 case 17: // 16bpp MSB
236 *pixel_data
++ = pixel
>> 8;
237 *pixel_data
++ = pixel
;
240 case 24: // 24bpp LSB
241 *pixel_data
++ = pixel
;
242 *pixel_data
++ = pixel
>> 8;
243 *pixel_data
++ = pixel
>> 16;
246 case 25: // 24bpp MSB
247 *pixel_data
++ = pixel
>> 16;
248 *pixel_data
++ = pixel
>> 8;
249 *pixel_data
++ = pixel
;
252 case 32: // 32bpp LSB
253 *pixel_data
++ = pixel
;
254 *pixel_data
++ = pixel
>> 8;
255 *pixel_data
++ = pixel
>> 16;
256 *pixel_data
++ = pixel
>> 24;
259 case 33: // 32bpp MSB
260 *pixel_data
++ = pixel
>> 24;
261 *pixel_data
++ = pixel
>> 16;
262 *pixel_data
++ = pixel
>> 8;
263 *pixel_data
++ = pixel
;
266 *data
= pixel_data
; // assign back so we don't lose our place
270 // algorithm: ordered dithering... many many thanks to rasterman
271 // (raster@rasterman.com) for telling me about this... portions of this
272 // code is based off of his code in Imlib
273 void BImage::TrueColorDither(unsigned int bit_depth
, int bytes_per_line
,
274 unsigned char *pixel_data
) {
275 unsigned int x
, y
, dithx
, dithy
, r
, g
, b
, er
, eg
, eb
, offset
;
276 unsigned char *ppixel_data
= pixel_data
;
279 for (y
= 0, offset
= 0; y
< height
; y
++) {
282 for (x
= 0; x
< width
; x
++, offset
++) {
288 er
= r
& (red_bits
- 1);
289 eg
= g
& (green_bits
- 1);
290 eb
= b
& (blue_bits
- 1);
296 if ((dither4
[dithy
][dithx
] < er
) && (r
< red_table
[255])) r
++;
297 if ((dither4
[dithy
][dithx
] < eg
) && (g
< green_table
[255])) g
++;
298 if ((dither4
[dithy
][dithx
] < eb
) && (b
< blue_table
[255])) b
++;
300 pixel
= (r
<< red_offset
) | (g
<< green_offset
) | (b
<< blue_offset
);
301 assignPixelData(bit_depth
, &pixel_data
, pixel
);
304 pixel_data
= (ppixel_data
+= bytes_per_line
);
309 const static unsigned char dither8
[8][8] = {
310 { 0, 32, 8, 40, 2, 34, 10, 42},
311 { 48, 16, 56, 24, 50, 18, 58, 26},
312 { 12, 44, 4, 36, 14, 46, 6, 38},
313 { 60, 28, 52, 20, 62, 30, 54, 22},
314 { 3, 35, 11, 43, 1, 33, 9, 41},
315 { 51, 19, 59, 27, 49, 17, 57, 25},
316 { 15, 47, 7, 39, 13, 45, 5, 37},
317 { 63, 31, 55, 23, 61, 29, 53, 21}
320 void BImage::OrderedPseudoColorDither(int bytes_per_line
,
321 unsigned char *pixel_data
) {
322 unsigned int x
, y
, dithx
, dithy
, r
, g
, b
, er
, eg
, eb
, offset
;
324 unsigned char *ppixel_data
= pixel_data
;
326 for (y
= 0, offset
= 0; y
< height
; y
++) {
329 for (x
= 0; x
< width
; x
++, offset
++) {
336 er
= r
& (red_bits
- 1);
337 eg
= g
& (green_bits
- 1);
338 eb
= b
& (blue_bits
- 1);
344 if ((dither8
[dithy
][dithx
] < er
) && (r
< red_table
[255])) r
++;
345 if ((dither8
[dithy
][dithx
] < eg
) && (g
< green_table
[255])) g
++;
346 if ((dither8
[dithy
][dithx
] < eb
) && (b
< blue_table
[255])) b
++;
348 pixel
= (r
* cpccpc
) + (g
* cpc
) + b
;
349 *(pixel_data
++) = colors
[pixel
].pixel
;
352 pixel_data
= (ppixel_data
+= bytes_per_line
);
357 void BImage::PseudoColorDither(int bytes_per_line
, unsigned char *pixel_data
) {
359 *rerr
= new short[width
+ 2],
360 *gerr
= new short[width
+ 2],
361 *berr
= new short[width
+ 2],
362 *nrerr
= new short[width
+ 2],
363 *ngerr
= new short[width
+ 2],
364 *nberr
= new short[width
+ 2];
366 int rr
, gg
, bb
, rer
, ger
, ber
;
367 int dd
= 255 / control
->getColorsPerChannel();
368 unsigned int x
, y
, r
, g
, b
, offset
;
370 unsigned char *ppixel_data
= pixel_data
;
372 for (x
= 0; x
< width
; x
++) {
373 *(rerr
+ x
) = *(red
+ x
);
374 *(gerr
+ x
) = *(green
+ x
);
375 *(berr
+ x
) = *(blue
+ x
);
378 *(rerr
+ x
) = *(gerr
+ x
) = *(berr
+ x
) = 0;
380 for (y
= 0, offset
= 0; y
< height
; y
++) {
381 if (y
< (height
- 1)) {
382 int i
= offset
+ width
;
383 for (x
= 0; x
< width
; x
++, i
++) {
384 *(nrerr
+ x
) = *(red
+ i
);
385 *(ngerr
+ x
) = *(green
+ i
);
386 *(nberr
+ x
) = *(blue
+ i
);
389 *(nrerr
+ x
) = *(red
+ (--i
));
390 *(ngerr
+ x
) = *(green
+ i
);
391 *(nberr
+ x
) = *(blue
+ i
);
394 for (x
= 0; x
< width
; x
++) {
399 if (rr
> 255) rr
= 255; else if (rr
< 0) rr
= 0;
400 if (gg
> 255) gg
= 255; else if (gg
< 0) gg
= 0;
401 if (bb
> 255) bb
= 255; else if (bb
< 0) bb
= 0;
407 rer
= rerr
[x
] - r
*dd
;
408 ger
= gerr
[x
] - g
*dd
;
409 ber
= berr
[x
] - b
*dd
;
411 pixel
= (r
* cpccpc
) + (g
* cpc
) + b
;
412 *pixel_data
++ = colors
[pixel
].pixel
;
427 pixel_data
= (ppixel_data
+= bytes_per_line
);
450 XImage
*BImage::renderXImage(void) {
452 XCreateImage(control
->getBaseDisplay()->getXDisplay(),
453 control
->getVisual(), control
->getDepth(), ZPixmap
, 0, 0,
454 width
, height
, 32, 0);
457 fprintf(stderr
, i18n(ImageSet
, ImageErrorCreatingXImage
,
458 "BImage::renderXImage: error creating XImage\n"));
463 image
->data
= (char *) 0;
465 unsigned char *d
= new unsigned char[image
->bytes_per_line
* (height
+ 1)];
467 unsigned int o
= image
->bits_per_pixel
+
468 ((image
->byte_order
== MSBFirst
) ? 1 : 0);
470 bool unsupported
= False
;
472 if (control
->doDither() && width
> 1 && height
> 1) {
473 switch (control
->getVisual()->c_class
) {
475 TrueColorDither(o
, image
->bytes_per_line
, d
);
481 OrderedPseudoColorDither(image
->bytes_per_line
, d
);
483 PseudoColorDither(image
->bytes_per_line
, d
);
492 unsigned int x
, y
, r
, g
, b
, offset
;
493 unsigned char *pixel_data
= d
, *ppixel_data
= d
;
496 switch (control
->getVisual()->c_class
) {
499 for (y
= 0, offset
= 0; y
< height
; ++y
) {
500 for (x
= 0; x
< width
; ++x
, ++offset
) {
501 r
= red_table
[red
[offset
]];
502 g
= green_table
[green
[offset
]];
503 b
= blue_table
[blue
[offset
]];
505 pixel
= (r
* cpccpc
) + (g
* cpc
) + b
;
506 *pixel_data
++ = colors
[pixel
].pixel
;
509 pixel_data
= (ppixel_data
+= image
->bytes_per_line
);
515 for (y
= 0, offset
= 0; y
< height
; y
++) {
516 for (x
= 0; x
< width
; x
++, offset
++) {
517 r
= red_table
[red
[offset
]];
518 g
= green_table
[green
[offset
]];
519 b
= blue_table
[blue
[offset
]];
521 pixel
= (r
<< red_offset
) | (g
<< green_offset
) | (b
<< blue_offset
);
522 assignPixelData(o
, &pixel_data
, pixel
);
525 pixel_data
= (ppixel_data
+= image
->bytes_per_line
);
532 for (y
= 0, offset
= 0; y
< height
; y
++) {
533 for (x
= 0; x
< width
; x
++, offset
++) {
534 r
= *(red_table
+ *(red
+ offset
));
535 g
= *(green_table
+ *(green
+ offset
));
536 b
= *(blue_table
+ *(blue
+ offset
));
538 g
= ((r
* 30) + (g
* 59) + (b
* 11)) / 100;
539 *pixel_data
++ = colors
[g
].pixel
;
542 pixel_data
= (ppixel_data
+= image
->bytes_per_line
);
553 fprintf(stderr
, i18n(ImageSet
, ImageUnsupVisual
,
554 "BImage::renderXImage: unsupported visual\n"));
556 XDestroyImage(image
);
560 image
->data
= (char *) d
;
566 Pixmap
BImage::renderPixmap(void) {
568 XCreatePixmap(control
->getBaseDisplay()->getXDisplay(),
569 control
->getDrawable(), width
, height
, control
->getDepth());
571 if (pixmap
== None
) {
572 fprintf(stderr
, i18n(ImageSet
, ImageErrorCreatingPixmap
,
573 "BImage::renderPixmap: error creating pixmap\n"));
577 XImage
*image
= renderXImage();
580 XFreePixmap(control
->getBaseDisplay()->getXDisplay(), pixmap
);
585 XDestroyImage(image
);
586 XFreePixmap(control
->getBaseDisplay()->getXDisplay(), pixmap
);
590 XPutImage(control
->getBaseDisplay()->getXDisplay(), pixmap
,
591 DefaultGC(control
->getBaseDisplay()->getXDisplay(),
592 control
->getScreenInfo()->getScreenNumber()),
593 image
, 0, 0, 0, 0, width
, height
);
596 delete [] image
->data
;
600 XDestroyImage(image
);
606 void BImage::bevel1(void) {
607 if (width
> 2 && height
> 2) {
608 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
610 register unsigned char r
, g
, b
, rr
,gg
,bb
;
611 register unsigned int w
= width
, h
= height
- 1, wh
= w
* h
;
629 rr
= (r
>> 2) + (r
>> 1);
632 gg
= (g
>> 2) + (g
>> 1);
635 bb
= (b
>> 2) + (b
>> 1);
658 rr
= (r
>> 2) + (r
>> 1);
661 gg
= (g
>> 2) + (g
>> 1);
664 bb
= (b
>> 2) + (b
>> 1);
695 rr
= (r
>> 2) + (r
>> 1);
698 gg
= (g
>> 2) + (g
>> 1);
701 bb
= (b
>> 2) + (b
>> 1);
728 rr
= (r
>> 2) + (r
>> 1);
731 gg
= (g
>> 2) + (g
>> 1);
734 bb
= (b
>> 2) + (b
>> 1);
744 void BImage::bevel2(void) {
745 if (width
> 4 && height
> 4) {
746 unsigned char r
, g
, b
, rr
,gg
,bb
, *pr
= red
+ width
+ 1,
747 *pg
= green
+ width
+ 1, *pb
= blue
+ width
+ 1;
748 unsigned int w
= width
- 2, h
= height
- 1, wh
= width
* (height
- 3);
766 rr
= (r
>> 2) + (r
>> 1);
769 gg
= (g
>> 2) + (g
>> 1);
772 bb
= (b
>> 2) + (b
>> 1);
804 rr
= (r
>> 2) + (r
>> 1);
807 gg
= (g
>> 2) + (g
>> 1);
810 bb
= (b
>> 2) + (b
>> 1);
823 void BImage::border(const BTexture
&texture
) {
824 if (width
< 2 || height
< 2) return;
826 register unsigned int i
;
827 int r
= texture
.borderColor().red(),
828 g
= texture
.borderColor().green(),
829 b
= texture
.borderColor().blue();
831 unsigned char *pr
, *pg
, *pb
;
837 for (i
= 0; i
< width
; ++i
) {
844 // left and right lines (pr,pg,pb are already lined up)
845 for (i
= 1; i
< height
- 1; ++i
) {
858 // bottom line (pr,pg,pb are already lined up)
859 for (i
= 0; i
< width
; ++i
) {
867 void BImage::invert(void) {
868 register unsigned int i
, j
, wh
= (width
* height
) - 1;
871 for (i
= 0, j
= wh
; j
> i
; j
--, i
++) {
873 *(red
+ j
) = *(red
+ i
);
877 *(green
+ j
) = *(green
+ i
);
881 *(blue
+ j
) = *(blue
+ i
);
887 void BImage::dgradient(void) {
888 // diagonal gradient code was written by Mike Cole <mike@mydot.com>
889 // modified for interlacing by Brad Hughes
891 float drx
, dgx
, dbx
, dry
, dgy
, dby
, yr
= 0.0, yg
= 0.0, yb
= 0.0,
892 xr
= (float) from
.red(),
893 xg
= (float) from
.green(),
894 xb
= (float) from
.blue();
895 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
896 unsigned int w
= width
* 2, h
= height
* 2, *xt
= xtable
, *yt
= ytable
;
898 register unsigned int x
, y
;
900 dry
= drx
= (float) (to
.red() - from
.red());
901 dgy
= dgx
= (float) (to
.green() - from
.green());
902 dby
= dbx
= (float) (to
.blue() - from
.blue());
909 for (x
= 0; x
< width
; x
++) {
910 *(xt
++) = (unsigned char) (xr
);
911 *(xt
++) = (unsigned char) (xg
);
912 *(xt
++) = (unsigned char) (xb
);
924 for (y
= 0; y
< height
; y
++) {
925 *(yt
++) = ((unsigned char) yr
);
926 *(yt
++) = ((unsigned char) yg
);
927 *(yt
++) = ((unsigned char) yb
);
934 // Combine tables to create gradient
938 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
939 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
940 *(pr
++) = *(xt
++) + *(yt
);
941 *(pg
++) = *(xt
++) + *(yt
+ 1);
942 *(pb
++) = *(xt
++) + *(yt
+ 2);
946 // faked interlacing effect
947 unsigned char channel
, channel2
;
949 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
950 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
952 channel
= *(xt
++) + *(yt
);
953 channel2
= (channel
>> 1) + (channel
>> 2);
954 if (channel2
> channel
) channel2
= 0;
957 channel
= *(xt
++) + *(yt
+ 1);
958 channel2
= (channel
>> 1) + (channel
>> 2);
959 if (channel2
> channel
) channel2
= 0;
962 channel
= *(xt
++) + *(yt
+ 2);
963 channel2
= (channel
>> 1) + (channel
>> 2);
964 if (channel2
> channel
) channel2
= 0;
967 channel
= *(xt
++) + *(yt
);
968 channel2
= channel
+ (channel
>> 3);
969 if (channel2
< channel
) channel2
= ~0;
972 channel
= *(xt
++) + *(yt
+ 1);
973 channel2
= channel
+ (channel
>> 3);
974 if (channel2
< channel
) channel2
= ~0;
977 channel
= *(xt
++) + *(yt
+ 2);
978 channel2
= channel
+ (channel
>> 3);
979 if (channel2
< channel
) channel2
= ~0;
988 void BImage::hgradient(void) {
990 xr
= (float) from
.red(),
991 xg
= (float) from
.green(),
992 xb
= (float) from
.blue();
993 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
995 register unsigned int x
, y
;
997 drx
= (float) (to
.red() - from
.red());
998 dgx
= (float) (to
.green() - from
.green());
999 dbx
= (float) (to
.blue() - from
.blue());
1005 if (interlaced
&& height
> 2) {
1006 // faked interlacing effect
1007 unsigned char channel
, channel2
;
1009 for (x
= 0; x
< width
; x
++, pr
++, pg
++, pb
++) {
1010 channel
= (unsigned char) xr
;
1011 channel2
= (channel
>> 1) + (channel
>> 2);
1012 if (channel2
> channel
) channel2
= 0;
1015 channel
= (unsigned char) xg
;
1016 channel2
= (channel
>> 1) + (channel
>> 2);
1017 if (channel2
> channel
) channel2
= 0;
1020 channel
= (unsigned char) xb
;
1021 channel2
= (channel
>> 1) + (channel
>> 2);
1022 if (channel2
> channel
) channel2
= 0;
1026 channel
= (unsigned char) xr
;
1027 channel2
= channel
+ (channel
>> 3);
1028 if (channel2
< channel
) channel2
= ~0;
1029 *(pr
+ width
) = channel2
;
1031 channel
= (unsigned char) xg
;
1032 channel2
= channel
+ (channel
>> 3);
1033 if (channel2
< channel
) channel2
= ~0;
1034 *(pg
+ width
) = channel2
;
1036 channel
= (unsigned char) xb
;
1037 channel2
= channel
+ (channel
>> 3);
1038 if (channel2
< channel
) channel2
= ~0;
1039 *(pb
+ width
) = channel2
;
1052 for (y
= 2; y
< height
; y
++, pr
+= width
, pg
+= width
, pb
+= width
) {
1053 if (y
& 1) offset
= width
; else offset
= 0;
1055 memcpy(pr
, (red
+ offset
), width
);
1056 memcpy(pg
, (green
+ offset
), width
);
1057 memcpy(pb
, (blue
+ offset
), width
);
1061 for (x
= 0; x
< width
; x
++) {
1062 *(pr
++) = (unsigned char) (xr
);
1063 *(pg
++) = (unsigned char) (xg
);
1064 *(pb
++) = (unsigned char) (xb
);
1071 for (y
= 1; y
< height
; y
++, pr
+= width
, pg
+= width
, pb
+= width
) {
1072 memcpy(pr
, red
, width
);
1073 memcpy(pg
, green
, width
);
1074 memcpy(pb
, blue
, width
);
1080 void BImage::vgradient(void) {
1081 float dry
, dgy
, dby
,
1082 yr
= (float) from
.red(),
1083 yg
= (float) from
.green(),
1084 yb
= (float) from
.blue();
1085 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1087 register unsigned int y
;
1089 dry
= (float) (to
.red() - from
.red());
1090 dgy
= (float) (to
.green() - from
.green());
1091 dby
= (float) (to
.blue() - from
.blue());
1098 // faked interlacing effect
1099 unsigned char channel
, channel2
;
1101 for (y
= 0; y
< height
; y
++, pr
+= width
, pg
+= width
, pb
+= width
) {
1103 channel
= (unsigned char) yr
;
1104 channel2
= (channel
>> 1) + (channel
>> 2);
1105 if (channel2
> channel
) channel2
= 0;
1106 memset(pr
, channel2
, width
);
1108 channel
= (unsigned char) yg
;
1109 channel2
= (channel
>> 1) + (channel
>> 2);
1110 if (channel2
> channel
) channel2
= 0;
1111 memset(pg
, channel2
, width
);
1113 channel
= (unsigned char) yb
;
1114 channel2
= (channel
>> 1) + (channel
>> 2);
1115 if (channel2
> channel
) channel2
= 0;
1116 memset(pb
, channel2
, width
);
1118 channel
= (unsigned char) yr
;
1119 channel2
= channel
+ (channel
>> 3);
1120 if (channel2
< channel
) channel2
= ~0;
1121 memset(pr
, channel2
, width
);
1123 channel
= (unsigned char) yg
;
1124 channel2
= channel
+ (channel
>> 3);
1125 if (channel2
< channel
) channel2
= ~0;
1126 memset(pg
, channel2
, width
);
1128 channel
= (unsigned char) yb
;
1129 channel2
= channel
+ (channel
>> 3);
1130 if (channel2
< channel
) channel2
= ~0;
1131 memset(pb
, channel2
, width
);
1140 for (y
= 0; y
< height
; y
++, pr
+= width
, pg
+= width
, pb
+= width
) {
1141 memset(pr
, (unsigned char) yr
, width
);
1142 memset(pg
, (unsigned char) yg
, width
);
1143 memset(pb
, (unsigned char) yb
, width
);
1153 void BImage::pgradient(void) {
1154 // pyramid gradient - based on original dgradient, written by
1155 // Mosfet (mosfet@kde.org)
1156 // adapted from kde sources for Blackbox by Brad Hughes
1158 float yr
, yg
, yb
, drx
, dgx
, dbx
, dry
, dgy
, dby
,
1160 int rsign
, gsign
, bsign
;
1161 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1162 unsigned int tr
= to
.red(), tg
= to
.green(), tb
= to
.blue(),
1163 *xt
= xtable
, *yt
= ytable
;
1165 register unsigned int x
, y
;
1167 dry
= drx
= (float) (to
.red() - from
.red());
1168 dgy
= dgx
= (float) (to
.green() - from
.green());
1169 dby
= dbx
= (float) (to
.blue() - from
.blue());
1171 rsign
= (drx
< 0) ? -1 : 1;
1172 gsign
= (dgx
< 0) ? -1 : 1;
1173 bsign
= (dbx
< 0) ? -1 : 1;
1175 xr
= yr
= (drx
/ 2);
1176 xg
= yg
= (dgx
/ 2);
1177 xb
= yb
= (dbx
/ 2);
1184 for (x
= 0; x
< width
; x
++) {
1185 *(xt
++) = (unsigned char) ((xr
< 0) ? -xr
: xr
);
1186 *(xt
++) = (unsigned char) ((xg
< 0) ? -xg
: xg
);
1187 *(xt
++) = (unsigned char) ((xb
< 0) ? -xb
: xb
);
1199 for (y
= 0; y
< height
; y
++) {
1200 *(yt
++) = ((unsigned char) ((yr
< 0) ? -yr
: yr
));
1201 *(yt
++) = ((unsigned char) ((yg
< 0) ? -yg
: yg
));
1202 *(yt
++) = ((unsigned char) ((yb
< 0) ? -yb
: yb
));
1209 // Combine tables to create gradient
1213 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1214 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1215 *(pr
++) = (unsigned char) (tr
- (rsign
* (*(xt
++) + *(yt
))));
1216 *(pg
++) = (unsigned char) (tg
- (gsign
* (*(xt
++) + *(yt
+ 1))));
1217 *(pb
++) = (unsigned char) (tb
- (bsign
* (*(xt
++) + *(yt
+ 2))));
1221 // faked interlacing effect
1222 unsigned char channel
, channel2
;
1224 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1225 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1227 channel
= (unsigned char) (tr
- (rsign
* (*(xt
++) + *(yt
))));
1228 channel2
= (channel
>> 1) + (channel
>> 2);
1229 if (channel2
> channel
) channel2
= 0;
1232 channel
= (unsigned char) (tg
- (gsign
* (*(xt
++) + *(yt
+ 1))));
1233 channel2
= (channel
>> 1) + (channel
>> 2);
1234 if (channel2
> channel
) channel2
= 0;
1237 channel
= (unsigned char) (tb
- (bsign
* (*(xt
++) + *(yt
+ 2))));
1238 channel2
= (channel
>> 1) + (channel
>> 2);
1239 if (channel2
> channel
) channel2
= 0;
1242 channel
= (unsigned char) (tr
- (rsign
* (*(xt
++) + *(yt
))));
1243 channel2
= channel
+ (channel
>> 3);
1244 if (channel2
< channel
) channel2
= ~0;
1247 channel
= (unsigned char) (tg
- (gsign
* (*(xt
++) + *(yt
+ 1))));
1248 channel2
= channel
+ (channel
>> 3);
1249 if (channel2
< channel
) channel2
= ~0;
1252 channel
= (unsigned char) (tb
- (bsign
* (*(xt
++) + *(yt
+ 2))));
1253 channel2
= channel
+ (channel
>> 3);
1254 if (channel2
< channel
) channel2
= ~0;
1263 void BImage::rgradient(void) {
1264 // rectangle gradient - based on original dgradient, written by
1265 // Mosfet (mosfet@kde.org)
1266 // adapted from kde sources for Blackbox by Brad Hughes
1268 float drx
, dgx
, dbx
, dry
, dgy
, dby
, xr
, xg
, xb
, yr
, yg
, yb
;
1269 int rsign
, gsign
, bsign
;
1270 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1271 unsigned int tr
= to
.red(), tg
= to
.green(), tb
= to
.blue(),
1272 *xt
= xtable
, *yt
= ytable
;
1274 register unsigned int x
, y
;
1276 dry
= drx
= (float) (to
.red() - from
.red());
1277 dgy
= dgx
= (float) (to
.green() - from
.green());
1278 dby
= dbx
= (float) (to
.blue() - from
.blue());
1280 rsign
= (drx
< 0) ? -2 : 2;
1281 gsign
= (dgx
< 0) ? -2 : 2;
1282 bsign
= (dbx
< 0) ? -2 : 2;
1284 xr
= yr
= (drx
/ 2);
1285 xg
= yg
= (dgx
/ 2);
1286 xb
= yb
= (dbx
/ 2);
1293 for (x
= 0; x
< width
; x
++) {
1294 *(xt
++) = (unsigned char) ((xr
< 0) ? -xr
: xr
);
1295 *(xt
++) = (unsigned char) ((xg
< 0) ? -xg
: xg
);
1296 *(xt
++) = (unsigned char) ((xb
< 0) ? -xb
: xb
);
1308 for (y
= 0; y
< height
; y
++) {
1309 *(yt
++) = ((unsigned char) ((yr
< 0) ? -yr
: yr
));
1310 *(yt
++) = ((unsigned char) ((yg
< 0) ? -yg
: yg
));
1311 *(yt
++) = ((unsigned char) ((yb
< 0) ? -yb
: yb
));
1318 // Combine tables to create gradient
1322 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1323 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1324 *(pr
++) = (unsigned char) (tr
- (rsign
* max(*(xt
++), *(yt
))));
1325 *(pg
++) = (unsigned char) (tg
- (gsign
* max(*(xt
++), *(yt
+ 1))));
1326 *(pb
++) = (unsigned char) (tb
- (bsign
* max(*(xt
++), *(yt
+ 2))));
1330 // faked interlacing effect
1331 unsigned char channel
, channel2
;
1333 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1334 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1336 channel
= (unsigned char) (tr
- (rsign
* max(*(xt
++), *(yt
))));
1337 channel2
= (channel
>> 1) + (channel
>> 2);
1338 if (channel2
> channel
) channel2
= 0;
1341 channel
= (unsigned char) (tg
- (gsign
* max(*(xt
++), *(yt
+ 1))));
1342 channel2
= (channel
>> 1) + (channel
>> 2);
1343 if (channel2
> channel
) channel2
= 0;
1346 channel
= (unsigned char) (tb
- (bsign
* max(*(xt
++), *(yt
+ 2))));
1347 channel2
= (channel
>> 1) + (channel
>> 2);
1348 if (channel2
> channel
) channel2
= 0;
1351 channel
= (unsigned char) (tr
- (rsign
* max(*(xt
++), *(yt
))));
1352 channel2
= channel
+ (channel
>> 3);
1353 if (channel2
< channel
) channel2
= ~0;
1356 channel
= (unsigned char) (tg
- (gsign
* max(*(xt
++), *(yt
+ 1))));
1357 channel2
= channel
+ (channel
>> 3);
1358 if (channel2
< channel
) channel2
= ~0;
1361 channel
= (unsigned char) (tb
- (bsign
* max(*(xt
++), *(yt
+ 2))));
1362 channel2
= channel
+ (channel
>> 3);
1363 if (channel2
< channel
) channel2
= ~0;
1372 void BImage::egradient(void) {
1373 // elliptic gradient - based on original dgradient, written by
1374 // Mosfet (mosfet@kde.org)
1375 // adapted from kde sources for Blackbox by Brad Hughes
1377 float drx
, dgx
, dbx
, dry
, dgy
, dby
, yr
, yg
, yb
, xr
, xg
, xb
;
1378 int rsign
, gsign
, bsign
;
1379 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1380 unsigned int *xt
= xtable
, *yt
= ytable
,
1381 tr
= (unsigned long) to
.red(),
1382 tg
= (unsigned long) to
.green(),
1383 tb
= (unsigned long) to
.blue();
1385 register unsigned int x
, y
;
1387 dry
= drx
= (float) (to
.red() - from
.red());
1388 dgy
= dgx
= (float) (to
.green() - from
.green());
1389 dby
= dbx
= (float) (to
.blue() - from
.blue());
1391 rsign
= (drx
< 0) ? -1 : 1;
1392 gsign
= (dgx
< 0) ? -1 : 1;
1393 bsign
= (dbx
< 0) ? -1 : 1;
1395 xr
= yr
= (drx
/ 2);
1396 xg
= yg
= (dgx
/ 2);
1397 xb
= yb
= (dbx
/ 2);
1404 for (x
= 0; x
< width
; x
++) {
1405 *(xt
++) = (unsigned long) (xr
* xr
);
1406 *(xt
++) = (unsigned long) (xg
* xg
);
1407 *(xt
++) = (unsigned long) (xb
* xb
);
1419 for (y
= 0; y
< height
; y
++) {
1420 *(yt
++) = (unsigned long) (yr
* yr
);
1421 *(yt
++) = (unsigned long) (yg
* yg
);
1422 *(yt
++) = (unsigned long) (yb
* yb
);
1429 // Combine tables to create gradient
1433 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1434 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1435 *(pr
++) = (unsigned char)
1436 (tr
- (rsign
* control
->getSqrt(*(xt
++) + *(yt
))));
1437 *(pg
++) = (unsigned char)
1438 (tg
- (gsign
* control
->getSqrt(*(xt
++) + *(yt
+ 1))));
1439 *(pb
++) = (unsigned char)
1440 (tb
- (bsign
* control
->getSqrt(*(xt
++) + *(yt
+ 2))));
1444 // faked interlacing effect
1445 unsigned char channel
, channel2
;
1447 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1448 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1450 channel
= (unsigned char)
1451 (tr
- (rsign
* control
->getSqrt(*(xt
++) + *(yt
))));
1452 channel2
= (channel
>> 1) + (channel
>> 2);
1453 if (channel2
> channel
) channel2
= 0;
1456 channel
= (unsigned char)
1457 (tg
- (gsign
* control
->getSqrt(*(xt
++) + *(yt
+ 1))));
1458 channel2
= (channel
>> 1) + (channel
>> 2);
1459 if (channel2
> channel
) channel2
= 0;
1462 channel
= (unsigned char)
1463 (tb
- (bsign
* control
->getSqrt(*(xt
++) + *(yt
+ 2))));
1464 channel2
= (channel
>> 1) + (channel
>> 2);
1465 if (channel2
> channel
) channel2
= 0;
1468 channel
= (unsigned char)
1469 (tr
- (rsign
* control
->getSqrt(*(xt
++) + *(yt
))));
1470 channel2
= channel
+ (channel
>> 3);
1471 if (channel2
< channel
) channel2
= ~0;
1474 channel
= (unsigned char)
1475 (tg
- (gsign
* control
->getSqrt(*(xt
++) + *(yt
+ 1))));
1476 channel2
= channel
+ (channel
>> 3);
1477 if (channel2
< channel
) channel2
= ~0;
1480 channel
= (unsigned char)
1481 (tb
- (bsign
* control
->getSqrt(*(xt
++) + *(yt
+ 2))));
1482 channel2
= channel
+ (channel
>> 3);
1483 if (channel2
< channel
) channel2
= ~0;
1492 void BImage::pcgradient(void) {
1493 // pipe cross gradient - based on original dgradient, written by
1494 // Mosfet (mosfet@kde.org)
1495 // adapted from kde sources for Blackbox by Brad Hughes
1497 float drx
, dgx
, dbx
, dry
, dgy
, dby
, xr
, xg
, xb
, yr
, yg
, yb
;
1498 int rsign
, gsign
, bsign
;
1499 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1500 unsigned int *xt
= xtable
, *yt
= ytable
,
1505 register unsigned int x
, y
;
1507 dry
= drx
= (float) (to
.red() - from
.red());
1508 dgy
= dgx
= (float) (to
.green() - from
.green());
1509 dby
= dbx
= (float) (to
.blue() - from
.blue());
1511 rsign
= (drx
< 0) ? -2 : 2;
1512 gsign
= (dgx
< 0) ? -2 : 2;
1513 bsign
= (dbx
< 0) ? -2 : 2;
1515 xr
= yr
= (drx
/ 2);
1516 xg
= yg
= (dgx
/ 2);
1517 xb
= yb
= (dbx
/ 2);
1524 for (x
= 0; x
< width
; x
++) {
1525 *(xt
++) = (unsigned char) ((xr
< 0) ? -xr
: xr
);
1526 *(xt
++) = (unsigned char) ((xg
< 0) ? -xg
: xg
);
1527 *(xt
++) = (unsigned char) ((xb
< 0) ? -xb
: xb
);
1539 for (y
= 0; y
< height
; y
++) {
1540 *(yt
++) = ((unsigned char) ((yr
< 0) ? -yr
: yr
));
1541 *(yt
++) = ((unsigned char) ((yg
< 0) ? -yg
: yg
));
1542 *(yt
++) = ((unsigned char) ((yb
< 0) ? -yb
: yb
));
1549 // Combine tables to create gradient
1552 // normal pcgradient
1553 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1554 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1555 *(pr
++) = (unsigned char) (tr
- (rsign
* min(*(xt
++), *(yt
))));
1556 *(pg
++) = (unsigned char) (tg
- (gsign
* min(*(xt
++), *(yt
+ 1))));
1557 *(pb
++) = (unsigned char) (tb
- (bsign
* min(*(xt
++), *(yt
+ 2))));
1561 // faked interlacing effect
1562 unsigned char channel
, channel2
;
1564 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1565 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1567 channel
= (unsigned char) (tr
- (rsign
* min(*(xt
++), *(yt
))));
1568 channel2
= (channel
>> 1) + (channel
>> 2);
1569 if (channel2
> channel
) channel2
= 0;
1572 channel
= (unsigned char) (tg
- (bsign
* min(*(xt
++), *(yt
+ 1))));
1573 channel2
= (channel
>> 1) + (channel
>> 2);
1574 if (channel2
> channel
) channel2
= 0;
1577 channel
= (unsigned char) (tb
- (gsign
* min(*(xt
++), *(yt
+ 2))));
1578 channel2
= (channel
>> 1) + (channel
>> 2);
1579 if (channel2
> channel
) channel2
= 0;
1582 channel
= (unsigned char) (tr
- (rsign
* min(*(xt
++), *(yt
))));
1583 channel2
= channel
+ (channel
>> 3);
1584 if (channel2
< channel
) channel2
= ~0;
1587 channel
= (unsigned char) (tg
- (gsign
* min(*(xt
++), *(yt
+ 1))));
1588 channel2
= channel
+ (channel
>> 3);
1589 if (channel2
< channel
) channel2
= ~0;
1592 channel
= (unsigned char) (tb
- (bsign
* min(*(xt
++), *(yt
+ 2))));
1593 channel2
= channel
+ (channel
>> 3);
1594 if (channel2
< channel
) channel2
= ~0;
1603 void BImage::cdgradient(void) {
1604 // cross diagonal gradient - based on original dgradient, written by
1605 // Mosfet (mosfet@kde.org)
1606 // adapted from kde sources for Blackbox by Brad Hughes
1608 float drx
, dgx
, dbx
, dry
, dgy
, dby
, yr
= 0.0, yg
= 0.0, yb
= 0.0,
1609 xr
= (float) from
.red(),
1610 xg
= (float) from
.green(),
1611 xb
= (float) from
.blue();
1612 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1613 unsigned int w
= width
* 2, h
= height
* 2, *xt
, *yt
;
1615 register unsigned int x
, y
;
1617 dry
= drx
= (float) (to
.red() - from
.red());
1618 dgy
= dgx
= (float) (to
.green() - from
.green());
1619 dby
= dbx
= (float) (to
.blue() - from
.blue());
1626 for (xt
= (xtable
+ (width
* 3) - 1), x
= 0; x
< width
; x
++) {
1627 *(xt
--) = (unsigned char) xb
;
1628 *(xt
--) = (unsigned char) xg
;
1629 *(xt
--) = (unsigned char) xr
;
1641 for (yt
= ytable
, y
= 0; y
< height
; y
++) {
1642 *(yt
++) = (unsigned char) yr
;
1643 *(yt
++) = (unsigned char) yg
;
1644 *(yt
++) = (unsigned char) yb
;
1651 // Combine tables to create gradient
1654 // normal cdgradient
1655 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1656 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1657 *(pr
++) = *(xt
++) + *(yt
);
1658 *(pg
++) = *(xt
++) + *(yt
+ 1);
1659 *(pb
++) = *(xt
++) + *(yt
+ 2);
1663 // faked interlacing effect
1664 unsigned char channel
, channel2
;
1666 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1667 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1669 channel
= *(xt
++) + *(yt
);
1670 channel2
= (channel
>> 1) + (channel
>> 2);
1671 if (channel2
> channel
) channel2
= 0;
1674 channel
= *(xt
++) + *(yt
+ 1);
1675 channel2
= (channel
>> 1) + (channel
>> 2);
1676 if (channel2
> channel
) channel2
= 0;
1679 channel
= *(xt
++) + *(yt
+ 2);
1680 channel2
= (channel
>> 1) + (channel
>> 2);
1681 if (channel2
> channel
) channel2
= 0;
1684 channel
= *(xt
++) + *(yt
);
1685 channel2
= channel
+ (channel
>> 3);
1686 if (channel2
< channel
) channel2
= ~0;
1689 channel
= *(xt
++) + *(yt
+ 1);
1690 channel2
= channel
+ (channel
>> 3);
1691 if (channel2
< channel
) channel2
= ~0;
1694 channel
= *(xt
++) + *(yt
+ 2);
1695 channel2
= channel
+ (channel
>> 3);
1696 if (channel2
< channel
) channel2
= ~0;