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 if (width
< 2 || height
< 2) return;
827 register unsigned int i
;
828 int r
= texture
.borderColor().red(),
829 g
= texture
.borderColor().green(),
830 b
= texture
.borderColor().blue();
832 unsigned char *pr
, *pg
, *pb
;
838 for (i
= 0; i
< width
; ++i
) {
845 // left and right lines (pr,pg,pb are already lined up)
846 for (i
= 1; i
< height
- 1; ++i
) {
859 // bottom line (pr,pg,pb are already lined up)
860 for (i
= 0; i
< width
; ++i
) {
868 void BImage::invert(void) {
869 register unsigned int i
, j
, wh
= (width
* height
) - 1;
872 for (i
= 0, j
= wh
; j
> i
; j
--, i
++) {
874 *(red
+ j
) = *(red
+ i
);
878 *(green
+ j
) = *(green
+ i
);
882 *(blue
+ j
) = *(blue
+ i
);
888 void BImage::dgradient(void) {
889 // diagonal gradient code was written by Mike Cole <mike@mydot.com>
890 // modified for interlacing by Brad Hughes
892 float drx
, dgx
, dbx
, dry
, dgy
, dby
, yr
= 0.0, yg
= 0.0, yb
= 0.0,
893 xr
= (float) from
.red(),
894 xg
= (float) from
.green(),
895 xb
= (float) from
.blue();
896 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
897 unsigned int w
= width
* 2, h
= height
* 2, *xt
= xtable
, *yt
= ytable
;
899 register unsigned int x
, y
;
901 dry
= drx
= (float) (to
.red() - from
.red());
902 dgy
= dgx
= (float) (to
.green() - from
.green());
903 dby
= dbx
= (float) (to
.blue() - from
.blue());
910 for (x
= 0; x
< width
; x
++) {
911 *(xt
++) = (unsigned char) (xr
);
912 *(xt
++) = (unsigned char) (xg
);
913 *(xt
++) = (unsigned char) (xb
);
925 for (y
= 0; y
< height
; y
++) {
926 *(yt
++) = ((unsigned char) yr
);
927 *(yt
++) = ((unsigned char) yg
);
928 *(yt
++) = ((unsigned char) yb
);
935 // Combine tables to create gradient
939 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
940 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
941 *(pr
++) = *(xt
++) + *(yt
);
942 *(pg
++) = *(xt
++) + *(yt
+ 1);
943 *(pb
++) = *(xt
++) + *(yt
+ 2);
947 // faked interlacing effect
948 unsigned char channel
, channel2
;
950 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
951 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
953 channel
= *(xt
++) + *(yt
);
954 channel2
= (channel
>> 1) + (channel
>> 2);
955 if (channel2
> channel
) channel2
= 0;
958 channel
= *(xt
++) + *(yt
+ 1);
959 channel2
= (channel
>> 1) + (channel
>> 2);
960 if (channel2
> channel
) channel2
= 0;
963 channel
= *(xt
++) + *(yt
+ 2);
964 channel2
= (channel
>> 1) + (channel
>> 2);
965 if (channel2
> channel
) channel2
= 0;
968 channel
= *(xt
++) + *(yt
);
969 channel2
= channel
+ (channel
>> 3);
970 if (channel2
< channel
) channel2
= ~0;
973 channel
= *(xt
++) + *(yt
+ 1);
974 channel2
= channel
+ (channel
>> 3);
975 if (channel2
< channel
) channel2
= ~0;
978 channel
= *(xt
++) + *(yt
+ 2);
979 channel2
= channel
+ (channel
>> 3);
980 if (channel2
< channel
) channel2
= ~0;
989 void BImage::hgradient(void) {
991 xr
= (float) from
.red(),
992 xg
= (float) from
.green(),
993 xb
= (float) from
.blue();
994 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
996 register unsigned int x
, y
;
998 drx
= (float) (to
.red() - from
.red());
999 dgx
= (float) (to
.green() - from
.green());
1000 dbx
= (float) (to
.blue() - from
.blue());
1006 if (interlaced
&& height
> 2) {
1007 // faked interlacing effect
1008 unsigned char channel
, channel2
;
1010 for (x
= 0; x
< width
; x
++, pr
++, pg
++, pb
++) {
1011 channel
= (unsigned char) xr
;
1012 channel2
= (channel
>> 1) + (channel
>> 2);
1013 if (channel2
> channel
) channel2
= 0;
1016 channel
= (unsigned char) xg
;
1017 channel2
= (channel
>> 1) + (channel
>> 2);
1018 if (channel2
> channel
) channel2
= 0;
1021 channel
= (unsigned char) xb
;
1022 channel2
= (channel
>> 1) + (channel
>> 2);
1023 if (channel2
> channel
) channel2
= 0;
1027 channel
= (unsigned char) xr
;
1028 channel2
= channel
+ (channel
>> 3);
1029 if (channel2
< channel
) channel2
= ~0;
1030 *(pr
+ width
) = channel2
;
1032 channel
= (unsigned char) xg
;
1033 channel2
= channel
+ (channel
>> 3);
1034 if (channel2
< channel
) channel2
= ~0;
1035 *(pg
+ width
) = channel2
;
1037 channel
= (unsigned char) xb
;
1038 channel2
= channel
+ (channel
>> 3);
1039 if (channel2
< channel
) channel2
= ~0;
1040 *(pb
+ width
) = channel2
;
1053 for (y
= 2; y
< height
; y
++, pr
+= width
, pg
+= width
, pb
+= width
) {
1054 if (y
& 1) offset
= width
; else offset
= 0;
1056 memcpy(pr
, (red
+ offset
), width
);
1057 memcpy(pg
, (green
+ offset
), width
);
1058 memcpy(pb
, (blue
+ offset
), width
);
1062 for (x
= 0; x
< width
; x
++) {
1063 *(pr
++) = (unsigned char) (xr
);
1064 *(pg
++) = (unsigned char) (xg
);
1065 *(pb
++) = (unsigned char) (xb
);
1072 for (y
= 1; y
< height
; y
++, pr
+= width
, pg
+= width
, pb
+= width
) {
1073 memcpy(pr
, red
, width
);
1074 memcpy(pg
, green
, width
);
1075 memcpy(pb
, blue
, width
);
1081 void BImage::vgradient(void) {
1082 float dry
, dgy
, dby
,
1083 yr
= (float) from
.red(),
1084 yg
= (float) from
.green(),
1085 yb
= (float) from
.blue();
1086 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1088 register unsigned int y
;
1090 dry
= (float) (to
.red() - from
.red());
1091 dgy
= (float) (to
.green() - from
.green());
1092 dby
= (float) (to
.blue() - from
.blue());
1099 // faked interlacing effect
1100 unsigned char channel
, channel2
;
1102 for (y
= 0; y
< height
; y
++, pr
+= width
, pg
+= width
, pb
+= width
) {
1104 channel
= (unsigned char) yr
;
1105 channel2
= (channel
>> 1) + (channel
>> 2);
1106 if (channel2
> channel
) channel2
= 0;
1107 memset(pr
, channel2
, width
);
1109 channel
= (unsigned char) yg
;
1110 channel2
= (channel
>> 1) + (channel
>> 2);
1111 if (channel2
> channel
) channel2
= 0;
1112 memset(pg
, channel2
, width
);
1114 channel
= (unsigned char) yb
;
1115 channel2
= (channel
>> 1) + (channel
>> 2);
1116 if (channel2
> channel
) channel2
= 0;
1117 memset(pb
, channel2
, width
);
1119 channel
= (unsigned char) yr
;
1120 channel2
= channel
+ (channel
>> 3);
1121 if (channel2
< channel
) channel2
= ~0;
1122 memset(pr
, channel2
, width
);
1124 channel
= (unsigned char) yg
;
1125 channel2
= channel
+ (channel
>> 3);
1126 if (channel2
< channel
) channel2
= ~0;
1127 memset(pg
, channel2
, width
);
1129 channel
= (unsigned char) yb
;
1130 channel2
= channel
+ (channel
>> 3);
1131 if (channel2
< channel
) channel2
= ~0;
1132 memset(pb
, channel2
, width
);
1141 for (y
= 0; y
< height
; y
++, pr
+= width
, pg
+= width
, pb
+= width
) {
1142 memset(pr
, (unsigned char) yr
, width
);
1143 memset(pg
, (unsigned char) yg
, width
);
1144 memset(pb
, (unsigned char) yb
, width
);
1154 void BImage::pgradient(void) {
1155 // pyramid gradient - based on original dgradient, written by
1156 // Mosfet (mosfet@kde.org)
1157 // adapted from kde sources for Blackbox by Brad Hughes
1159 float yr
, yg
, yb
, drx
, dgx
, dbx
, dry
, dgy
, dby
,
1161 int rsign
, gsign
, bsign
;
1162 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1163 unsigned int tr
= to
.red(), tg
= to
.green(), tb
= to
.blue(),
1164 *xt
= xtable
, *yt
= ytable
;
1166 register unsigned int x
, y
;
1168 dry
= drx
= (float) (to
.red() - from
.red());
1169 dgy
= dgx
= (float) (to
.green() - from
.green());
1170 dby
= dbx
= (float) (to
.blue() - from
.blue());
1172 rsign
= (drx
< 0) ? -1 : 1;
1173 gsign
= (dgx
< 0) ? -1 : 1;
1174 bsign
= (dbx
< 0) ? -1 : 1;
1176 xr
= yr
= (drx
/ 2);
1177 xg
= yg
= (dgx
/ 2);
1178 xb
= yb
= (dbx
/ 2);
1185 for (x
= 0; x
< width
; x
++) {
1186 *(xt
++) = (unsigned char) ((xr
< 0) ? -xr
: xr
);
1187 *(xt
++) = (unsigned char) ((xg
< 0) ? -xg
: xg
);
1188 *(xt
++) = (unsigned char) ((xb
< 0) ? -xb
: xb
);
1200 for (y
= 0; y
< height
; y
++) {
1201 *(yt
++) = ((unsigned char) ((yr
< 0) ? -yr
: yr
));
1202 *(yt
++) = ((unsigned char) ((yg
< 0) ? -yg
: yg
));
1203 *(yt
++) = ((unsigned char) ((yb
< 0) ? -yb
: yb
));
1210 // Combine tables to create gradient
1214 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1215 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1216 *(pr
++) = (unsigned char) (tr
- (rsign
* (*(xt
++) + *(yt
))));
1217 *(pg
++) = (unsigned char) (tg
- (gsign
* (*(xt
++) + *(yt
+ 1))));
1218 *(pb
++) = (unsigned char) (tb
- (bsign
* (*(xt
++) + *(yt
+ 2))));
1222 // faked interlacing effect
1223 unsigned char channel
, channel2
;
1225 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1226 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1228 channel
= (unsigned char) (tr
- (rsign
* (*(xt
++) + *(yt
))));
1229 channel2
= (channel
>> 1) + (channel
>> 2);
1230 if (channel2
> channel
) channel2
= 0;
1233 channel
= (unsigned char) (tg
- (gsign
* (*(xt
++) + *(yt
+ 1))));
1234 channel2
= (channel
>> 1) + (channel
>> 2);
1235 if (channel2
> channel
) channel2
= 0;
1238 channel
= (unsigned char) (tb
- (bsign
* (*(xt
++) + *(yt
+ 2))));
1239 channel2
= (channel
>> 1) + (channel
>> 2);
1240 if (channel2
> channel
) channel2
= 0;
1243 channel
= (unsigned char) (tr
- (rsign
* (*(xt
++) + *(yt
))));
1244 channel2
= channel
+ (channel
>> 3);
1245 if (channel2
< channel
) channel2
= ~0;
1248 channel
= (unsigned char) (tg
- (gsign
* (*(xt
++) + *(yt
+ 1))));
1249 channel2
= channel
+ (channel
>> 3);
1250 if (channel2
< channel
) channel2
= ~0;
1253 channel
= (unsigned char) (tb
- (bsign
* (*(xt
++) + *(yt
+ 2))));
1254 channel2
= channel
+ (channel
>> 3);
1255 if (channel2
< channel
) channel2
= ~0;
1264 void BImage::rgradient(void) {
1265 // rectangle gradient - based on original dgradient, written by
1266 // Mosfet (mosfet@kde.org)
1267 // adapted from kde sources for Blackbox by Brad Hughes
1269 float drx
, dgx
, dbx
, dry
, dgy
, dby
, xr
, xg
, xb
, yr
, yg
, yb
;
1270 int rsign
, gsign
, bsign
;
1271 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1272 unsigned int tr
= to
.red(), tg
= to
.green(), tb
= to
.blue(),
1273 *xt
= xtable
, *yt
= ytable
;
1275 register unsigned int x
, y
;
1277 dry
= drx
= (float) (to
.red() - from
.red());
1278 dgy
= dgx
= (float) (to
.green() - from
.green());
1279 dby
= dbx
= (float) (to
.blue() - from
.blue());
1281 rsign
= (drx
< 0) ? -2 : 2;
1282 gsign
= (dgx
< 0) ? -2 : 2;
1283 bsign
= (dbx
< 0) ? -2 : 2;
1285 xr
= yr
= (drx
/ 2);
1286 xg
= yg
= (dgx
/ 2);
1287 xb
= yb
= (dbx
/ 2);
1294 for (x
= 0; x
< width
; x
++) {
1295 *(xt
++) = (unsigned char) ((xr
< 0) ? -xr
: xr
);
1296 *(xt
++) = (unsigned char) ((xg
< 0) ? -xg
: xg
);
1297 *(xt
++) = (unsigned char) ((xb
< 0) ? -xb
: xb
);
1309 for (y
= 0; y
< height
; y
++) {
1310 *(yt
++) = ((unsigned char) ((yr
< 0) ? -yr
: yr
));
1311 *(yt
++) = ((unsigned char) ((yg
< 0) ? -yg
: yg
));
1312 *(yt
++) = ((unsigned char) ((yb
< 0) ? -yb
: yb
));
1319 // Combine tables to create gradient
1323 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1324 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1325 *(pr
++) = (unsigned char) (tr
- (rsign
* max(*(xt
++), *(yt
))));
1326 *(pg
++) = (unsigned char) (tg
- (gsign
* max(*(xt
++), *(yt
+ 1))));
1327 *(pb
++) = (unsigned char) (tb
- (bsign
* max(*(xt
++), *(yt
+ 2))));
1331 // faked interlacing effect
1332 unsigned char channel
, channel2
;
1334 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1335 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1337 channel
= (unsigned char) (tr
- (rsign
* max(*(xt
++), *(yt
))));
1338 channel2
= (channel
>> 1) + (channel
>> 2);
1339 if (channel2
> channel
) channel2
= 0;
1342 channel
= (unsigned char) (tg
- (gsign
* max(*(xt
++), *(yt
+ 1))));
1343 channel2
= (channel
>> 1) + (channel
>> 2);
1344 if (channel2
> channel
) channel2
= 0;
1347 channel
= (unsigned char) (tb
- (bsign
* max(*(xt
++), *(yt
+ 2))));
1348 channel2
= (channel
>> 1) + (channel
>> 2);
1349 if (channel2
> channel
) channel2
= 0;
1352 channel
= (unsigned char) (tr
- (rsign
* max(*(xt
++), *(yt
))));
1353 channel2
= channel
+ (channel
>> 3);
1354 if (channel2
< channel
) channel2
= ~0;
1357 channel
= (unsigned char) (tg
- (gsign
* max(*(xt
++), *(yt
+ 1))));
1358 channel2
= channel
+ (channel
>> 3);
1359 if (channel2
< channel
) channel2
= ~0;
1362 channel
= (unsigned char) (tb
- (bsign
* max(*(xt
++), *(yt
+ 2))));
1363 channel2
= channel
+ (channel
>> 3);
1364 if (channel2
< channel
) channel2
= ~0;
1373 void BImage::egradient(void) {
1374 // elliptic gradient - based on original dgradient, written by
1375 // Mosfet (mosfet@kde.org)
1376 // adapted from kde sources for Blackbox by Brad Hughes
1378 float drx
, dgx
, dbx
, dry
, dgy
, dby
, yr
, yg
, yb
, xr
, xg
, xb
;
1379 int rsign
, gsign
, bsign
;
1380 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1381 unsigned int *xt
= xtable
, *yt
= ytable
,
1382 tr
= (unsigned long) to
.red(),
1383 tg
= (unsigned long) to
.green(),
1384 tb
= (unsigned long) to
.blue();
1386 register unsigned int x
, y
;
1388 dry
= drx
= (float) (to
.red() - from
.red());
1389 dgy
= dgx
= (float) (to
.green() - from
.green());
1390 dby
= dbx
= (float) (to
.blue() - from
.blue());
1392 rsign
= (drx
< 0) ? -1 : 1;
1393 gsign
= (dgx
< 0) ? -1 : 1;
1394 bsign
= (dbx
< 0) ? -1 : 1;
1396 xr
= yr
= (drx
/ 2);
1397 xg
= yg
= (dgx
/ 2);
1398 xb
= yb
= (dbx
/ 2);
1405 for (x
= 0; x
< width
; x
++) {
1406 *(xt
++) = (unsigned long) (xr
* xr
);
1407 *(xt
++) = (unsigned long) (xg
* xg
);
1408 *(xt
++) = (unsigned long) (xb
* xb
);
1420 for (y
= 0; y
< height
; y
++) {
1421 *(yt
++) = (unsigned long) (yr
* yr
);
1422 *(yt
++) = (unsigned long) (yg
* yg
);
1423 *(yt
++) = (unsigned long) (yb
* yb
);
1430 // Combine tables to create gradient
1434 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1435 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1436 *(pr
++) = (unsigned char)
1437 (tr
- (rsign
* control
->getSqrt(*(xt
++) + *(yt
))));
1438 *(pg
++) = (unsigned char)
1439 (tg
- (gsign
* control
->getSqrt(*(xt
++) + *(yt
+ 1))));
1440 *(pb
++) = (unsigned char)
1441 (tb
- (bsign
* control
->getSqrt(*(xt
++) + *(yt
+ 2))));
1445 // faked interlacing effect
1446 unsigned char channel
, channel2
;
1448 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1449 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1451 channel
= (unsigned char)
1452 (tr
- (rsign
* control
->getSqrt(*(xt
++) + *(yt
))));
1453 channel2
= (channel
>> 1) + (channel
>> 2);
1454 if (channel2
> channel
) channel2
= 0;
1457 channel
= (unsigned char)
1458 (tg
- (gsign
* control
->getSqrt(*(xt
++) + *(yt
+ 1))));
1459 channel2
= (channel
>> 1) + (channel
>> 2);
1460 if (channel2
> channel
) channel2
= 0;
1463 channel
= (unsigned char)
1464 (tb
- (bsign
* control
->getSqrt(*(xt
++) + *(yt
+ 2))));
1465 channel2
= (channel
>> 1) + (channel
>> 2);
1466 if (channel2
> channel
) channel2
= 0;
1469 channel
= (unsigned char)
1470 (tr
- (rsign
* control
->getSqrt(*(xt
++) + *(yt
))));
1471 channel2
= channel
+ (channel
>> 3);
1472 if (channel2
< channel
) channel2
= ~0;
1475 channel
= (unsigned char)
1476 (tg
- (gsign
* control
->getSqrt(*(xt
++) + *(yt
+ 1))));
1477 channel2
= channel
+ (channel
>> 3);
1478 if (channel2
< channel
) channel2
= ~0;
1481 channel
= (unsigned char)
1482 (tb
- (bsign
* control
->getSqrt(*(xt
++) + *(yt
+ 2))));
1483 channel2
= channel
+ (channel
>> 3);
1484 if (channel2
< channel
) channel2
= ~0;
1493 void BImage::pcgradient(void) {
1494 // pipe cross gradient - based on original dgradient, written by
1495 // Mosfet (mosfet@kde.org)
1496 // adapted from kde sources for Blackbox by Brad Hughes
1498 float drx
, dgx
, dbx
, dry
, dgy
, dby
, xr
, xg
, xb
, yr
, yg
, yb
;
1499 int rsign
, gsign
, bsign
;
1500 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1501 unsigned int *xt
= xtable
, *yt
= ytable
,
1506 register unsigned int x
, y
;
1508 dry
= drx
= (float) (to
.red() - from
.red());
1509 dgy
= dgx
= (float) (to
.green() - from
.green());
1510 dby
= dbx
= (float) (to
.blue() - from
.blue());
1512 rsign
= (drx
< 0) ? -2 : 2;
1513 gsign
= (dgx
< 0) ? -2 : 2;
1514 bsign
= (dbx
< 0) ? -2 : 2;
1516 xr
= yr
= (drx
/ 2);
1517 xg
= yg
= (dgx
/ 2);
1518 xb
= yb
= (dbx
/ 2);
1525 for (x
= 0; x
< width
; x
++) {
1526 *(xt
++) = (unsigned char) ((xr
< 0) ? -xr
: xr
);
1527 *(xt
++) = (unsigned char) ((xg
< 0) ? -xg
: xg
);
1528 *(xt
++) = (unsigned char) ((xb
< 0) ? -xb
: xb
);
1540 for (y
= 0; y
< height
; y
++) {
1541 *(yt
++) = ((unsigned char) ((yr
< 0) ? -yr
: yr
));
1542 *(yt
++) = ((unsigned char) ((yg
< 0) ? -yg
: yg
));
1543 *(yt
++) = ((unsigned char) ((yb
< 0) ? -yb
: yb
));
1550 // Combine tables to create gradient
1553 // normal pcgradient
1554 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1555 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1556 *(pr
++) = (unsigned char) (tr
- (rsign
* min(*(xt
++), *(yt
))));
1557 *(pg
++) = (unsigned char) (tg
- (gsign
* min(*(xt
++), *(yt
+ 1))));
1558 *(pb
++) = (unsigned char) (tb
- (bsign
* min(*(xt
++), *(yt
+ 2))));
1562 // faked interlacing effect
1563 unsigned char channel
, channel2
;
1565 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1566 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1568 channel
= (unsigned char) (tr
- (rsign
* min(*(xt
++), *(yt
))));
1569 channel2
= (channel
>> 1) + (channel
>> 2);
1570 if (channel2
> channel
) channel2
= 0;
1573 channel
= (unsigned char) (tg
- (bsign
* min(*(xt
++), *(yt
+ 1))));
1574 channel2
= (channel
>> 1) + (channel
>> 2);
1575 if (channel2
> channel
) channel2
= 0;
1578 channel
= (unsigned char) (tb
- (gsign
* min(*(xt
++), *(yt
+ 2))));
1579 channel2
= (channel
>> 1) + (channel
>> 2);
1580 if (channel2
> channel
) channel2
= 0;
1583 channel
= (unsigned char) (tr
- (rsign
* min(*(xt
++), *(yt
))));
1584 channel2
= channel
+ (channel
>> 3);
1585 if (channel2
< channel
) channel2
= ~0;
1588 channel
= (unsigned char) (tg
- (gsign
* min(*(xt
++), *(yt
+ 1))));
1589 channel2
= channel
+ (channel
>> 3);
1590 if (channel2
< channel
) channel2
= ~0;
1593 channel
= (unsigned char) (tb
- (bsign
* min(*(xt
++), *(yt
+ 2))));
1594 channel2
= channel
+ (channel
>> 3);
1595 if (channel2
< channel
) channel2
= ~0;
1604 void BImage::cdgradient(void) {
1605 // cross diagonal gradient - based on original dgradient, written by
1606 // Mosfet (mosfet@kde.org)
1607 // adapted from kde sources for Blackbox by Brad Hughes
1609 float drx
, dgx
, dbx
, dry
, dgy
, dby
, yr
= 0.0, yg
= 0.0, yb
= 0.0,
1610 xr
= (float) from
.red(),
1611 xg
= (float) from
.green(),
1612 xb
= (float) from
.blue();
1613 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1614 unsigned int w
= width
* 2, h
= height
* 2, *xt
, *yt
;
1616 register unsigned int x
, y
;
1618 dry
= drx
= (float) (to
.red() - from
.red());
1619 dgy
= dgx
= (float) (to
.green() - from
.green());
1620 dby
= dbx
= (float) (to
.blue() - from
.blue());
1627 for (xt
= (xtable
+ (width
* 3) - 1), x
= 0; x
< width
; x
++) {
1628 *(xt
--) = (unsigned char) xb
;
1629 *(xt
--) = (unsigned char) xg
;
1630 *(xt
--) = (unsigned char) xr
;
1642 for (yt
= ytable
, y
= 0; y
< height
; y
++) {
1643 *(yt
++) = (unsigned char) yr
;
1644 *(yt
++) = (unsigned char) yg
;
1645 *(yt
++) = (unsigned char) yb
;
1652 // Combine tables to create gradient
1655 // normal cdgradient
1656 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1657 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1658 *(pr
++) = *(xt
++) + *(yt
);
1659 *(pg
++) = *(xt
++) + *(yt
+ 1);
1660 *(pb
++) = *(xt
++) + *(yt
+ 2);
1664 // faked interlacing effect
1665 unsigned char channel
, channel2
;
1667 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1668 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1670 channel
= *(xt
++) + *(yt
);
1671 channel2
= (channel
>> 1) + (channel
>> 2);
1672 if (channel2
> channel
) channel2
= 0;
1675 channel
= *(xt
++) + *(yt
+ 1);
1676 channel2
= (channel
>> 1) + (channel
>> 2);
1677 if (channel2
> channel
) channel2
= 0;
1680 channel
= *(xt
++) + *(yt
+ 2);
1681 channel2
= (channel
>> 1) + (channel
>> 2);
1682 if (channel2
> channel
) channel2
= 0;
1685 channel
= *(xt
++) + *(yt
);
1686 channel2
= channel
+ (channel
>> 3);
1687 if (channel2
< channel
) channel2
= ~0;
1690 channel
= *(xt
++) + *(yt
+ 1);
1691 channel2
= channel
+ (channel
>> 3);
1692 if (channel2
< channel
) channel2
= ~0;
1695 channel
= *(xt
++) + *(yt
+ 2);
1696 channel2
= channel
+ (channel
>> 3);
1697 if (channel2
< channel
) channel2
= ~0;