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 if (texture
.texture() & BTexture::FlatBorder
) {
111 BPen
penborder(texture
.colorTo());
112 XDrawRectangle(display
, pixmap
, penborder
.gc(), 0, 0, width
-1, height
-1);
115 if (texture
.texture() & BTexture::Bevel1
) {
116 if (texture
.texture() & BTexture::Raised
) {
117 XDrawLine(display
, pixmap
, penshadow
.gc(),
118 0, height
- 1, width
- 1, height
- 1);
119 XDrawLine(display
, pixmap
, penshadow
.gc(),
120 width
- 1, height
- 1, width
- 1, 0);
122 XDrawLine(display
, pixmap
, penlight
.gc(),
124 XDrawLine(display
, pixmap
, penlight
.gc(),
125 0, height
- 1, 0, 0);
126 } else if (texture
.texture() & BTexture::Sunken
) {
127 XDrawLine(display
, pixmap
, penlight
.gc(),
128 0, height
- 1, width
- 1, height
- 1);
129 XDrawLine(display
, pixmap
, penlight
.gc(),
130 width
- 1, height
- 1, width
- 1, 0);
132 XDrawLine(display
, pixmap
, penshadow
.gc(),
134 XDrawLine(display
, pixmap
, penshadow
.gc(),
135 0, height
- 1, 0, 0);
137 } else if (texture
.texture() & BTexture::Bevel2
) {
138 if (texture
.texture() & BTexture::Raised
) {
139 XDrawLine(display
, pixmap
, penshadow
.gc(),
140 1, height
- 3, width
- 3, height
- 3);
141 XDrawLine(display
, pixmap
, penshadow
.gc(),
142 width
- 3, height
- 3, width
- 3, 1);
144 XDrawLine(display
, pixmap
, penlight
.gc(),
146 XDrawLine(display
, pixmap
, penlight
.gc(),
147 1, height
- 3, 1, 1);
148 } else if (texture
.texture() & BTexture::Sunken
) {
149 XDrawLine(display
, pixmap
, penlight
.gc(),
150 1, height
- 3, width
- 3, height
- 3);
151 XDrawLine(display
, pixmap
, penlight
.gc(),
152 width
- 3, height
- 3, width
- 3, 1);
154 XDrawLine(display
, pixmap
, penshadow
.gc(),
156 XDrawLine(display
, pixmap
, penshadow
.gc(),
157 1, height
- 3, 1, 1);
165 Pixmap
BImage::render_gradient(const BTexture
&texture
) {
166 bool inverted
= False
;
168 interlaced
= texture
.texture() & BTexture::Interlaced
;
170 if (texture
.texture() & BTexture::Sunken
) {
171 from
= texture
.colorTo();
172 to
= texture
.color();
174 if (! (texture
.texture() & BTexture::Invert
)) inverted
= True
;
176 from
= texture
.color();
177 to
= texture
.colorTo();
179 if (texture
.texture() & BTexture::Invert
) inverted
= True
;
182 control
->getGradientBuffers(width
, height
, &xtable
, &ytable
);
184 if (texture
.texture() & BTexture::Diagonal
) dgradient();
185 else if (texture
.texture() & BTexture::Elliptic
) egradient();
186 else if (texture
.texture() & BTexture::Horizontal
) hgradient();
187 else if (texture
.texture() & BTexture::Pyramid
) pgradient();
188 else if (texture
.texture() & BTexture::Rectangle
) rgradient();
189 else if (texture
.texture() & BTexture::Vertical
) vgradient();
190 else if (texture
.texture() & BTexture::CrossDiagonal
) cdgradient();
191 else if (texture
.texture() & BTexture::PipeCross
) pcgradient();
193 if (texture
.texture() & BTexture::Bevel1
) bevel1();
194 else if (texture
.texture() & BTexture::Bevel2
) bevel2();
196 if (inverted
) invert();
198 return renderPixmap();
203 static const unsigned char dither4
[4][4] = {
212 * Helper function for TrueColorDither and renderXImage
214 * This handles the proper setting of the image data based on the image depth
215 * and the machine's byte ordering
218 void assignPixelData(unsigned int bit_depth
, unsigned char **data
,
219 unsigned long pixel
) {
220 unsigned char *pixel_data
= *data
;
223 *pixel_data
++ = pixel
;
226 case 16: // 16bpp LSB
227 *pixel_data
++ = pixel
;
228 *pixel_data
++ = pixel
>> 8;
231 case 17: // 16bpp MSB
232 *pixel_data
++ = pixel
>> 8;
233 *pixel_data
++ = pixel
;
236 case 24: // 24bpp LSB
237 *pixel_data
++ = pixel
;
238 *pixel_data
++ = pixel
>> 8;
239 *pixel_data
++ = pixel
>> 16;
242 case 25: // 24bpp MSB
243 *pixel_data
++ = pixel
>> 16;
244 *pixel_data
++ = pixel
>> 8;
245 *pixel_data
++ = pixel
;
248 case 32: // 32bpp LSB
249 *pixel_data
++ = pixel
;
250 *pixel_data
++ = pixel
>> 8;
251 *pixel_data
++ = pixel
>> 16;
252 *pixel_data
++ = pixel
>> 24;
255 case 33: // 32bpp MSB
256 *pixel_data
++ = pixel
>> 24;
257 *pixel_data
++ = pixel
>> 16;
258 *pixel_data
++ = pixel
>> 8;
259 *pixel_data
++ = pixel
;
262 *data
= pixel_data
; // assign back so we don't lose our place
266 // algorithm: ordered dithering... many many thanks to rasterman
267 // (raster@rasterman.com) for telling me about this... portions of this
268 // code is based off of his code in Imlib
269 void BImage::TrueColorDither(unsigned int bit_depth
, int bytes_per_line
,
270 unsigned char *pixel_data
) {
271 unsigned int x
, y
, dithx
, dithy
, r
, g
, b
, er
, eg
, eb
, offset
;
272 unsigned char *ppixel_data
= pixel_data
;
275 for (y
= 0, offset
= 0; y
< height
; y
++) {
278 for (x
= 0; x
< width
; x
++, offset
++) {
284 er
= r
& (red_bits
- 1);
285 eg
= g
& (green_bits
- 1);
286 eb
= b
& (blue_bits
- 1);
292 if ((dither4
[dithy
][dithx
] < er
) && (r
< red_table
[255])) r
++;
293 if ((dither4
[dithy
][dithx
] < eg
) && (g
< green_table
[255])) g
++;
294 if ((dither4
[dithy
][dithx
] < eb
) && (b
< blue_table
[255])) b
++;
296 pixel
= (r
<< red_offset
) | (g
<< green_offset
) | (b
<< blue_offset
);
297 assignPixelData(bit_depth
, &pixel_data
, pixel
);
300 pixel_data
= (ppixel_data
+= bytes_per_line
);
305 const static unsigned char dither8
[8][8] = {
306 { 0, 32, 8, 40, 2, 34, 10, 42},
307 { 48, 16, 56, 24, 50, 18, 58, 26},
308 { 12, 44, 4, 36, 14, 46, 6, 38},
309 { 60, 28, 52, 20, 62, 30, 54, 22},
310 { 3, 35, 11, 43, 1, 33, 9, 41},
311 { 51, 19, 59, 27, 49, 17, 57, 25},
312 { 15, 47, 7, 39, 13, 45, 5, 37},
313 { 63, 31, 55, 23, 61, 29, 53, 21}
316 void BImage::OrderedPseudoColorDither(int bytes_per_line
,
317 unsigned char *pixel_data
) {
318 unsigned int x
, y
, dithx
, dithy
, r
, g
, b
, er
, eg
, eb
, offset
;
320 unsigned char *ppixel_data
= pixel_data
;
322 for (y
= 0, offset
= 0; y
< height
; y
++) {
325 for (x
= 0; x
< width
; x
++, offset
++) {
332 er
= r
& (red_bits
- 1);
333 eg
= g
& (green_bits
- 1);
334 eb
= b
& (blue_bits
- 1);
340 if ((dither8
[dithy
][dithx
] < er
) && (r
< red_table
[255])) r
++;
341 if ((dither8
[dithy
][dithx
] < eg
) && (g
< green_table
[255])) g
++;
342 if ((dither8
[dithy
][dithx
] < eb
) && (b
< blue_table
[255])) b
++;
344 pixel
= (r
* cpccpc
) + (g
* cpc
) + b
;
345 *(pixel_data
++) = colors
[pixel
].pixel
;
348 pixel_data
= (ppixel_data
+= bytes_per_line
);
353 void BImage::PseudoColorDither(int bytes_per_line
, unsigned char *pixel_data
) {
355 *rerr
= new short[width
+ 2],
356 *gerr
= new short[width
+ 2],
357 *berr
= new short[width
+ 2],
358 *nrerr
= new short[width
+ 2],
359 *ngerr
= new short[width
+ 2],
360 *nberr
= new short[width
+ 2];
362 int rr
, gg
, bb
, rer
, ger
, ber
;
363 int dd
= 255 / control
->getColorsPerChannel();
364 unsigned int x
, y
, r
, g
, b
, offset
;
366 unsigned char *ppixel_data
= pixel_data
;
368 for (x
= 0; x
< width
; x
++) {
369 *(rerr
+ x
) = *(red
+ x
);
370 *(gerr
+ x
) = *(green
+ x
);
371 *(berr
+ x
) = *(blue
+ x
);
374 *(rerr
+ x
) = *(gerr
+ x
) = *(berr
+ x
) = 0;
376 for (y
= 0, offset
= 0; y
< height
; y
++) {
377 if (y
< (height
- 1)) {
378 int i
= offset
+ width
;
379 for (x
= 0; x
< width
; x
++, i
++) {
380 *(nrerr
+ x
) = *(red
+ i
);
381 *(ngerr
+ x
) = *(green
+ i
);
382 *(nberr
+ x
) = *(blue
+ i
);
385 *(nrerr
+ x
) = *(red
+ (--i
));
386 *(ngerr
+ x
) = *(green
+ i
);
387 *(nberr
+ x
) = *(blue
+ i
);
390 for (x
= 0; x
< width
; x
++) {
395 if (rr
> 255) rr
= 255; else if (rr
< 0) rr
= 0;
396 if (gg
> 255) gg
= 255; else if (gg
< 0) gg
= 0;
397 if (bb
> 255) bb
= 255; else if (bb
< 0) bb
= 0;
403 rer
= rerr
[x
] - r
*dd
;
404 ger
= gerr
[x
] - g
*dd
;
405 ber
= berr
[x
] - b
*dd
;
407 pixel
= (r
* cpccpc
) + (g
* cpc
) + b
;
408 *pixel_data
++ = colors
[pixel
].pixel
;
423 pixel_data
= (ppixel_data
+= bytes_per_line
);
446 XImage
*BImage::renderXImage(void) {
448 XCreateImage(control
->getBaseDisplay()->getXDisplay(),
449 control
->getVisual(), control
->getDepth(), ZPixmap
, 0, 0,
450 width
, height
, 32, 0);
453 fprintf(stderr
, i18n(ImageSet
, ImageErrorCreatingXImage
,
454 "BImage::renderXImage: error creating XImage\n"));
459 image
->data
= (char *) 0;
461 unsigned char *d
= new unsigned char[image
->bytes_per_line
* (height
+ 1)];
463 unsigned int o
= image
->bits_per_pixel
+
464 ((image
->byte_order
== MSBFirst
) ? 1 : 0);
466 bool unsupported
= False
;
468 if (control
->doDither() && width
> 1 && height
> 1) {
469 switch (control
->getVisual()->c_class
) {
471 TrueColorDither(o
, image
->bytes_per_line
, d
);
477 OrderedPseudoColorDither(image
->bytes_per_line
, d
);
479 PseudoColorDither(image
->bytes_per_line
, d
);
488 unsigned int x
, y
, r
, g
, b
, offset
;
489 unsigned char *pixel_data
= d
, *ppixel_data
= d
;
492 switch (control
->getVisual()->c_class
) {
495 for (y
= 0, offset
= 0; y
< height
; ++y
) {
496 for (x
= 0; x
< width
; ++x
, ++offset
) {
497 r
= red_table
[red
[offset
]];
498 g
= green_table
[green
[offset
]];
499 b
= blue_table
[blue
[offset
]];
501 pixel
= (r
* cpccpc
) + (g
* cpc
) + b
;
502 *pixel_data
++ = colors
[pixel
].pixel
;
505 pixel_data
= (ppixel_data
+= image
->bytes_per_line
);
511 for (y
= 0, offset
= 0; y
< height
; y
++) {
512 for (x
= 0; x
< width
; x
++, offset
++) {
513 r
= red_table
[red
[offset
]];
514 g
= green_table
[green
[offset
]];
515 b
= blue_table
[blue
[offset
]];
517 pixel
= (r
<< red_offset
) | (g
<< green_offset
) | (b
<< blue_offset
);
518 assignPixelData(o
, &pixel_data
, pixel
);
521 pixel_data
= (ppixel_data
+= image
->bytes_per_line
);
528 for (y
= 0, offset
= 0; y
< height
; y
++) {
529 for (x
= 0; x
< width
; x
++, offset
++) {
530 r
= *(red_table
+ *(red
+ offset
));
531 g
= *(green_table
+ *(green
+ offset
));
532 b
= *(blue_table
+ *(blue
+ offset
));
534 g
= ((r
* 30) + (g
* 59) + (b
* 11)) / 100;
535 *pixel_data
++ = colors
[g
].pixel
;
538 pixel_data
= (ppixel_data
+= image
->bytes_per_line
);
549 fprintf(stderr
, i18n(ImageSet
, ImageUnsupVisual
,
550 "BImage::renderXImage: unsupported visual\n"));
552 XDestroyImage(image
);
556 image
->data
= (char *) d
;
562 Pixmap
BImage::renderPixmap(void) {
564 XCreatePixmap(control
->getBaseDisplay()->getXDisplay(),
565 control
->getDrawable(), width
, height
, control
->getDepth());
567 if (pixmap
== None
) {
568 fprintf(stderr
, i18n(ImageSet
, ImageErrorCreatingPixmap
,
569 "BImage::renderPixmap: error creating pixmap\n"));
573 XImage
*image
= renderXImage();
576 XFreePixmap(control
->getBaseDisplay()->getXDisplay(), pixmap
);
581 XDestroyImage(image
);
582 XFreePixmap(control
->getBaseDisplay()->getXDisplay(), pixmap
);
586 XPutImage(control
->getBaseDisplay()->getXDisplay(), pixmap
,
587 DefaultGC(control
->getBaseDisplay()->getXDisplay(),
588 control
->getScreenInfo()->getScreenNumber()),
589 image
, 0, 0, 0, 0, width
, height
);
592 delete [] image
->data
;
596 XDestroyImage(image
);
602 void BImage::bevel1(void) {
603 if (width
> 2 && height
> 2) {
604 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
606 register unsigned char r
, g
, b
, rr
,gg
,bb
;
607 register unsigned int w
= width
, h
= height
- 1, wh
= w
* h
;
625 rr
= (r
>> 2) + (r
>> 1);
628 gg
= (g
>> 2) + (g
>> 1);
631 bb
= (b
>> 2) + (b
>> 1);
654 rr
= (r
>> 2) + (r
>> 1);
657 gg
= (g
>> 2) + (g
>> 1);
660 bb
= (b
>> 2) + (b
>> 1);
691 rr
= (r
>> 2) + (r
>> 1);
694 gg
= (g
>> 2) + (g
>> 1);
697 bb
= (b
>> 2) + (b
>> 1);
724 rr
= (r
>> 2) + (r
>> 1);
727 gg
= (g
>> 2) + (g
>> 1);
730 bb
= (b
>> 2) + (b
>> 1);
740 void BImage::bevel2(void) {
741 if (width
> 4 && height
> 4) {
742 unsigned char r
, g
, b
, rr
,gg
,bb
, *pr
= red
+ width
+ 1,
743 *pg
= green
+ width
+ 1, *pb
= blue
+ width
+ 1;
744 unsigned int w
= width
- 2, h
= height
- 1, wh
= width
* (height
- 3);
762 rr
= (r
>> 2) + (r
>> 1);
765 gg
= (g
>> 2) + (g
>> 1);
768 bb
= (b
>> 2) + (b
>> 1);
800 rr
= (r
>> 2) + (r
>> 1);
803 gg
= (g
>> 2) + (g
>> 1);
806 bb
= (b
>> 2) + (b
>> 1);
819 void BImage::invert(void) {
820 register unsigned int i
, j
, wh
= (width
* height
) - 1;
823 for (i
= 0, j
= wh
; j
> i
; j
--, i
++) {
825 *(red
+ j
) = *(red
+ i
);
829 *(green
+ j
) = *(green
+ i
);
833 *(blue
+ j
) = *(blue
+ i
);
839 void BImage::dgradient(void) {
840 // diagonal gradient code was written by Mike Cole <mike@mydot.com>
841 // modified for interlacing by Brad Hughes
843 float drx
, dgx
, dbx
, dry
, dgy
, dby
, yr
= 0.0, yg
= 0.0, yb
= 0.0,
844 xr
= (float) from
.red(),
845 xg
= (float) from
.green(),
846 xb
= (float) from
.blue();
847 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
848 unsigned int w
= width
* 2, h
= height
* 2, *xt
= xtable
, *yt
= ytable
;
850 register unsigned int x
, y
;
852 dry
= drx
= (float) (to
.red() - from
.red());
853 dgy
= dgx
= (float) (to
.green() - from
.green());
854 dby
= dbx
= (float) (to
.blue() - from
.blue());
861 for (x
= 0; x
< width
; x
++) {
862 *(xt
++) = (unsigned char) (xr
);
863 *(xt
++) = (unsigned char) (xg
);
864 *(xt
++) = (unsigned char) (xb
);
876 for (y
= 0; y
< height
; y
++) {
877 *(yt
++) = ((unsigned char) yr
);
878 *(yt
++) = ((unsigned char) yg
);
879 *(yt
++) = ((unsigned char) yb
);
886 // Combine tables to create gradient
890 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
891 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
892 *(pr
++) = *(xt
++) + *(yt
);
893 *(pg
++) = *(xt
++) + *(yt
+ 1);
894 *(pb
++) = *(xt
++) + *(yt
+ 2);
898 // faked interlacing effect
899 unsigned char channel
, channel2
;
901 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
902 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
904 channel
= *(xt
++) + *(yt
);
905 channel2
= (channel
>> 1) + (channel
>> 2);
906 if (channel2
> channel
) channel2
= 0;
909 channel
= *(xt
++) + *(yt
+ 1);
910 channel2
= (channel
>> 1) + (channel
>> 2);
911 if (channel2
> channel
) channel2
= 0;
914 channel
= *(xt
++) + *(yt
+ 2);
915 channel2
= (channel
>> 1) + (channel
>> 2);
916 if (channel2
> channel
) channel2
= 0;
919 channel
= *(xt
++) + *(yt
);
920 channel2
= channel
+ (channel
>> 3);
921 if (channel2
< channel
) channel2
= ~0;
924 channel
= *(xt
++) + *(yt
+ 1);
925 channel2
= channel
+ (channel
>> 3);
926 if (channel2
< channel
) channel2
= ~0;
929 channel
= *(xt
++) + *(yt
+ 2);
930 channel2
= channel
+ (channel
>> 3);
931 if (channel2
< channel
) channel2
= ~0;
940 void BImage::hgradient(void) {
942 xr
= (float) from
.red(),
943 xg
= (float) from
.green(),
944 xb
= (float) from
.blue();
945 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
947 register unsigned int x
, y
;
949 drx
= (float) (to
.red() - from
.red());
950 dgx
= (float) (to
.green() - from
.green());
951 dbx
= (float) (to
.blue() - from
.blue());
957 if (interlaced
&& height
> 2) {
958 // faked interlacing effect
959 unsigned char channel
, channel2
;
961 for (x
= 0; x
< width
; x
++, pr
++, pg
++, pb
++) {
962 channel
= (unsigned char) xr
;
963 channel2
= (channel
>> 1) + (channel
>> 2);
964 if (channel2
> channel
) channel2
= 0;
967 channel
= (unsigned char) xg
;
968 channel2
= (channel
>> 1) + (channel
>> 2);
969 if (channel2
> channel
) channel2
= 0;
972 channel
= (unsigned char) xb
;
973 channel2
= (channel
>> 1) + (channel
>> 2);
974 if (channel2
> channel
) channel2
= 0;
978 channel
= (unsigned char) xr
;
979 channel2
= channel
+ (channel
>> 3);
980 if (channel2
< channel
) channel2
= ~0;
981 *(pr
+ width
) = channel2
;
983 channel
= (unsigned char) xg
;
984 channel2
= channel
+ (channel
>> 3);
985 if (channel2
< channel
) channel2
= ~0;
986 *(pg
+ width
) = channel2
;
988 channel
= (unsigned char) xb
;
989 channel2
= channel
+ (channel
>> 3);
990 if (channel2
< channel
) channel2
= ~0;
991 *(pb
+ width
) = channel2
;
1004 for (y
= 2; y
< height
; y
++, pr
+= width
, pg
+= width
, pb
+= width
) {
1005 if (y
& 1) offset
= width
; else offset
= 0;
1007 memcpy(pr
, (red
+ offset
), width
);
1008 memcpy(pg
, (green
+ offset
), width
);
1009 memcpy(pb
, (blue
+ offset
), width
);
1013 for (x
= 0; x
< width
; x
++) {
1014 *(pr
++) = (unsigned char) (xr
);
1015 *(pg
++) = (unsigned char) (xg
);
1016 *(pb
++) = (unsigned char) (xb
);
1023 for (y
= 1; y
< height
; y
++, pr
+= width
, pg
+= width
, pb
+= width
) {
1024 memcpy(pr
, red
, width
);
1025 memcpy(pg
, green
, width
);
1026 memcpy(pb
, blue
, width
);
1032 void BImage::vgradient(void) {
1033 float dry
, dgy
, dby
,
1034 yr
= (float) from
.red(),
1035 yg
= (float) from
.green(),
1036 yb
= (float) from
.blue();
1037 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1039 register unsigned int y
;
1041 dry
= (float) (to
.red() - from
.red());
1042 dgy
= (float) (to
.green() - from
.green());
1043 dby
= (float) (to
.blue() - from
.blue());
1050 // faked interlacing effect
1051 unsigned char channel
, channel2
;
1053 for (y
= 0; y
< height
; y
++, pr
+= width
, pg
+= width
, pb
+= width
) {
1055 channel
= (unsigned char) yr
;
1056 channel2
= (channel
>> 1) + (channel
>> 2);
1057 if (channel2
> channel
) channel2
= 0;
1058 memset(pr
, channel2
, width
);
1060 channel
= (unsigned char) yg
;
1061 channel2
= (channel
>> 1) + (channel
>> 2);
1062 if (channel2
> channel
) channel2
= 0;
1063 memset(pg
, channel2
, width
);
1065 channel
= (unsigned char) yb
;
1066 channel2
= (channel
>> 1) + (channel
>> 2);
1067 if (channel2
> channel
) channel2
= 0;
1068 memset(pb
, channel2
, width
);
1070 channel
= (unsigned char) yr
;
1071 channel2
= channel
+ (channel
>> 3);
1072 if (channel2
< channel
) channel2
= ~0;
1073 memset(pr
, channel2
, width
);
1075 channel
= (unsigned char) yg
;
1076 channel2
= channel
+ (channel
>> 3);
1077 if (channel2
< channel
) channel2
= ~0;
1078 memset(pg
, channel2
, width
);
1080 channel
= (unsigned char) yb
;
1081 channel2
= channel
+ (channel
>> 3);
1082 if (channel2
< channel
) channel2
= ~0;
1083 memset(pb
, channel2
, width
);
1092 for (y
= 0; y
< height
; y
++, pr
+= width
, pg
+= width
, pb
+= width
) {
1093 memset(pr
, (unsigned char) yr
, width
);
1094 memset(pg
, (unsigned char) yg
, width
);
1095 memset(pb
, (unsigned char) yb
, width
);
1105 void BImage::pgradient(void) {
1106 // pyramid gradient - based on original dgradient, written by
1107 // Mosfet (mosfet@kde.org)
1108 // adapted from kde sources for Blackbox by Brad Hughes
1110 float yr
, yg
, yb
, drx
, dgx
, dbx
, dry
, dgy
, dby
,
1112 int rsign
, gsign
, bsign
;
1113 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1114 unsigned int tr
= to
.red(), tg
= to
.green(), tb
= to
.blue(),
1115 *xt
= xtable
, *yt
= ytable
;
1117 register unsigned int x
, y
;
1119 dry
= drx
= (float) (to
.red() - from
.red());
1120 dgy
= dgx
= (float) (to
.green() - from
.green());
1121 dby
= dbx
= (float) (to
.blue() - from
.blue());
1123 rsign
= (drx
< 0) ? -1 : 1;
1124 gsign
= (dgx
< 0) ? -1 : 1;
1125 bsign
= (dbx
< 0) ? -1 : 1;
1127 xr
= yr
= (drx
/ 2);
1128 xg
= yg
= (dgx
/ 2);
1129 xb
= yb
= (dbx
/ 2);
1136 for (x
= 0; x
< width
; x
++) {
1137 *(xt
++) = (unsigned char) ((xr
< 0) ? -xr
: xr
);
1138 *(xt
++) = (unsigned char) ((xg
< 0) ? -xg
: xg
);
1139 *(xt
++) = (unsigned char) ((xb
< 0) ? -xb
: xb
);
1151 for (y
= 0; y
< height
; y
++) {
1152 *(yt
++) = ((unsigned char) ((yr
< 0) ? -yr
: yr
));
1153 *(yt
++) = ((unsigned char) ((yg
< 0) ? -yg
: yg
));
1154 *(yt
++) = ((unsigned char) ((yb
< 0) ? -yb
: yb
));
1161 // Combine tables to create gradient
1165 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1166 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1167 *(pr
++) = (unsigned char) (tr
- (rsign
* (*(xt
++) + *(yt
))));
1168 *(pg
++) = (unsigned char) (tg
- (gsign
* (*(xt
++) + *(yt
+ 1))));
1169 *(pb
++) = (unsigned char) (tb
- (bsign
* (*(xt
++) + *(yt
+ 2))));
1173 // faked interlacing effect
1174 unsigned char channel
, channel2
;
1176 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1177 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1179 channel
= (unsigned char) (tr
- (rsign
* (*(xt
++) + *(yt
))));
1180 channel2
= (channel
>> 1) + (channel
>> 2);
1181 if (channel2
> channel
) channel2
= 0;
1184 channel
= (unsigned char) (tg
- (gsign
* (*(xt
++) + *(yt
+ 1))));
1185 channel2
= (channel
>> 1) + (channel
>> 2);
1186 if (channel2
> channel
) channel2
= 0;
1189 channel
= (unsigned char) (tb
- (bsign
* (*(xt
++) + *(yt
+ 2))));
1190 channel2
= (channel
>> 1) + (channel
>> 2);
1191 if (channel2
> channel
) channel2
= 0;
1194 channel
= (unsigned char) (tr
- (rsign
* (*(xt
++) + *(yt
))));
1195 channel2
= channel
+ (channel
>> 3);
1196 if (channel2
< channel
) channel2
= ~0;
1199 channel
= (unsigned char) (tg
- (gsign
* (*(xt
++) + *(yt
+ 1))));
1200 channel2
= channel
+ (channel
>> 3);
1201 if (channel2
< channel
) channel2
= ~0;
1204 channel
= (unsigned char) (tb
- (bsign
* (*(xt
++) + *(yt
+ 2))));
1205 channel2
= channel
+ (channel
>> 3);
1206 if (channel2
< channel
) channel2
= ~0;
1215 void BImage::rgradient(void) {
1216 // rectangle gradient - based on original dgradient, written by
1217 // Mosfet (mosfet@kde.org)
1218 // adapted from kde sources for Blackbox by Brad Hughes
1220 float drx
, dgx
, dbx
, dry
, dgy
, dby
, xr
, xg
, xb
, yr
, yg
, yb
;
1221 int rsign
, gsign
, bsign
;
1222 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1223 unsigned int tr
= to
.red(), tg
= to
.green(), tb
= to
.blue(),
1224 *xt
= xtable
, *yt
= ytable
;
1226 register unsigned int x
, y
;
1228 dry
= drx
= (float) (to
.red() - from
.red());
1229 dgy
= dgx
= (float) (to
.green() - from
.green());
1230 dby
= dbx
= (float) (to
.blue() - from
.blue());
1232 rsign
= (drx
< 0) ? -2 : 2;
1233 gsign
= (dgx
< 0) ? -2 : 2;
1234 bsign
= (dbx
< 0) ? -2 : 2;
1236 xr
= yr
= (drx
/ 2);
1237 xg
= yg
= (dgx
/ 2);
1238 xb
= yb
= (dbx
/ 2);
1245 for (x
= 0; x
< width
; x
++) {
1246 *(xt
++) = (unsigned char) ((xr
< 0) ? -xr
: xr
);
1247 *(xt
++) = (unsigned char) ((xg
< 0) ? -xg
: xg
);
1248 *(xt
++) = (unsigned char) ((xb
< 0) ? -xb
: xb
);
1260 for (y
= 0; y
< height
; y
++) {
1261 *(yt
++) = ((unsigned char) ((yr
< 0) ? -yr
: yr
));
1262 *(yt
++) = ((unsigned char) ((yg
< 0) ? -yg
: yg
));
1263 *(yt
++) = ((unsigned char) ((yb
< 0) ? -yb
: yb
));
1270 // Combine tables to create gradient
1274 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1275 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1276 *(pr
++) = (unsigned char) (tr
- (rsign
* max(*(xt
++), *(yt
))));
1277 *(pg
++) = (unsigned char) (tg
- (gsign
* max(*(xt
++), *(yt
+ 1))));
1278 *(pb
++) = (unsigned char) (tb
- (bsign
* max(*(xt
++), *(yt
+ 2))));
1282 // faked interlacing effect
1283 unsigned char channel
, channel2
;
1285 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1286 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1288 channel
= (unsigned char) (tr
- (rsign
* max(*(xt
++), *(yt
))));
1289 channel2
= (channel
>> 1) + (channel
>> 2);
1290 if (channel2
> channel
) channel2
= 0;
1293 channel
= (unsigned char) (tg
- (gsign
* max(*(xt
++), *(yt
+ 1))));
1294 channel2
= (channel
>> 1) + (channel
>> 2);
1295 if (channel2
> channel
) channel2
= 0;
1298 channel
= (unsigned char) (tb
- (bsign
* max(*(xt
++), *(yt
+ 2))));
1299 channel2
= (channel
>> 1) + (channel
>> 2);
1300 if (channel2
> channel
) channel2
= 0;
1303 channel
= (unsigned char) (tr
- (rsign
* max(*(xt
++), *(yt
))));
1304 channel2
= channel
+ (channel
>> 3);
1305 if (channel2
< channel
) channel2
= ~0;
1308 channel
= (unsigned char) (tg
- (gsign
* max(*(xt
++), *(yt
+ 1))));
1309 channel2
= channel
+ (channel
>> 3);
1310 if (channel2
< channel
) channel2
= ~0;
1313 channel
= (unsigned char) (tb
- (bsign
* max(*(xt
++), *(yt
+ 2))));
1314 channel2
= channel
+ (channel
>> 3);
1315 if (channel2
< channel
) channel2
= ~0;
1324 void BImage::egradient(void) {
1325 // elliptic gradient - based on original dgradient, written by
1326 // Mosfet (mosfet@kde.org)
1327 // adapted from kde sources for Blackbox by Brad Hughes
1329 float drx
, dgx
, dbx
, dry
, dgy
, dby
, yr
, yg
, yb
, xr
, xg
, xb
;
1330 int rsign
, gsign
, bsign
;
1331 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1332 unsigned int *xt
= xtable
, *yt
= ytable
,
1333 tr
= (unsigned long) to
.red(),
1334 tg
= (unsigned long) to
.green(),
1335 tb
= (unsigned long) to
.blue();
1337 register unsigned int x
, y
;
1339 dry
= drx
= (float) (to
.red() - from
.red());
1340 dgy
= dgx
= (float) (to
.green() - from
.green());
1341 dby
= dbx
= (float) (to
.blue() - from
.blue());
1343 rsign
= (drx
< 0) ? -1 : 1;
1344 gsign
= (dgx
< 0) ? -1 : 1;
1345 bsign
= (dbx
< 0) ? -1 : 1;
1347 xr
= yr
= (drx
/ 2);
1348 xg
= yg
= (dgx
/ 2);
1349 xb
= yb
= (dbx
/ 2);
1356 for (x
= 0; x
< width
; x
++) {
1357 *(xt
++) = (unsigned long) (xr
* xr
);
1358 *(xt
++) = (unsigned long) (xg
* xg
);
1359 *(xt
++) = (unsigned long) (xb
* xb
);
1371 for (y
= 0; y
< height
; y
++) {
1372 *(yt
++) = (unsigned long) (yr
* yr
);
1373 *(yt
++) = (unsigned long) (yg
* yg
);
1374 *(yt
++) = (unsigned long) (yb
* yb
);
1381 // Combine tables to create gradient
1385 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1386 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1387 *(pr
++) = (unsigned char)
1388 (tr
- (rsign
* control
->getSqrt(*(xt
++) + *(yt
))));
1389 *(pg
++) = (unsigned char)
1390 (tg
- (gsign
* control
->getSqrt(*(xt
++) + *(yt
+ 1))));
1391 *(pb
++) = (unsigned char)
1392 (tb
- (bsign
* control
->getSqrt(*(xt
++) + *(yt
+ 2))));
1396 // faked interlacing effect
1397 unsigned char channel
, channel2
;
1399 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1400 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1402 channel
= (unsigned char)
1403 (tr
- (rsign
* control
->getSqrt(*(xt
++) + *(yt
))));
1404 channel2
= (channel
>> 1) + (channel
>> 2);
1405 if (channel2
> channel
) channel2
= 0;
1408 channel
= (unsigned char)
1409 (tg
- (gsign
* control
->getSqrt(*(xt
++) + *(yt
+ 1))));
1410 channel2
= (channel
>> 1) + (channel
>> 2);
1411 if (channel2
> channel
) channel2
= 0;
1414 channel
= (unsigned char)
1415 (tb
- (bsign
* control
->getSqrt(*(xt
++) + *(yt
+ 2))));
1416 channel2
= (channel
>> 1) + (channel
>> 2);
1417 if (channel2
> channel
) channel2
= 0;
1420 channel
= (unsigned char)
1421 (tr
- (rsign
* control
->getSqrt(*(xt
++) + *(yt
))));
1422 channel2
= channel
+ (channel
>> 3);
1423 if (channel2
< channel
) channel2
= ~0;
1426 channel
= (unsigned char)
1427 (tg
- (gsign
* control
->getSqrt(*(xt
++) + *(yt
+ 1))));
1428 channel2
= channel
+ (channel
>> 3);
1429 if (channel2
< channel
) channel2
= ~0;
1432 channel
= (unsigned char)
1433 (tb
- (bsign
* control
->getSqrt(*(xt
++) + *(yt
+ 2))));
1434 channel2
= channel
+ (channel
>> 3);
1435 if (channel2
< channel
) channel2
= ~0;
1444 void BImage::pcgradient(void) {
1445 // pipe cross gradient - based on original dgradient, written by
1446 // Mosfet (mosfet@kde.org)
1447 // adapted from kde sources for Blackbox by Brad Hughes
1449 float drx
, dgx
, dbx
, dry
, dgy
, dby
, xr
, xg
, xb
, yr
, yg
, yb
;
1450 int rsign
, gsign
, bsign
;
1451 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1452 unsigned int *xt
= xtable
, *yt
= ytable
,
1457 register unsigned int x
, y
;
1459 dry
= drx
= (float) (to
.red() - from
.red());
1460 dgy
= dgx
= (float) (to
.green() - from
.green());
1461 dby
= dbx
= (float) (to
.blue() - from
.blue());
1463 rsign
= (drx
< 0) ? -2 : 2;
1464 gsign
= (dgx
< 0) ? -2 : 2;
1465 bsign
= (dbx
< 0) ? -2 : 2;
1467 xr
= yr
= (drx
/ 2);
1468 xg
= yg
= (dgx
/ 2);
1469 xb
= yb
= (dbx
/ 2);
1476 for (x
= 0; x
< width
; x
++) {
1477 *(xt
++) = (unsigned char) ((xr
< 0) ? -xr
: xr
);
1478 *(xt
++) = (unsigned char) ((xg
< 0) ? -xg
: xg
);
1479 *(xt
++) = (unsigned char) ((xb
< 0) ? -xb
: xb
);
1491 for (y
= 0; y
< height
; y
++) {
1492 *(yt
++) = ((unsigned char) ((yr
< 0) ? -yr
: yr
));
1493 *(yt
++) = ((unsigned char) ((yg
< 0) ? -yg
: yg
));
1494 *(yt
++) = ((unsigned char) ((yb
< 0) ? -yb
: yb
));
1501 // Combine tables to create gradient
1504 // normal pcgradient
1505 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1506 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1507 *(pr
++) = (unsigned char) (tr
- (rsign
* min(*(xt
++), *(yt
))));
1508 *(pg
++) = (unsigned char) (tg
- (gsign
* min(*(xt
++), *(yt
+ 1))));
1509 *(pb
++) = (unsigned char) (tb
- (bsign
* min(*(xt
++), *(yt
+ 2))));
1513 // faked interlacing effect
1514 unsigned char channel
, channel2
;
1516 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1517 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1519 channel
= (unsigned char) (tr
- (rsign
* min(*(xt
++), *(yt
))));
1520 channel2
= (channel
>> 1) + (channel
>> 2);
1521 if (channel2
> channel
) channel2
= 0;
1524 channel
= (unsigned char) (tg
- (bsign
* min(*(xt
++), *(yt
+ 1))));
1525 channel2
= (channel
>> 1) + (channel
>> 2);
1526 if (channel2
> channel
) channel2
= 0;
1529 channel
= (unsigned char) (tb
- (gsign
* min(*(xt
++), *(yt
+ 2))));
1530 channel2
= (channel
>> 1) + (channel
>> 2);
1531 if (channel2
> channel
) channel2
= 0;
1534 channel
= (unsigned char) (tr
- (rsign
* min(*(xt
++), *(yt
))));
1535 channel2
= channel
+ (channel
>> 3);
1536 if (channel2
< channel
) channel2
= ~0;
1539 channel
= (unsigned char) (tg
- (gsign
* min(*(xt
++), *(yt
+ 1))));
1540 channel2
= channel
+ (channel
>> 3);
1541 if (channel2
< channel
) channel2
= ~0;
1544 channel
= (unsigned char) (tb
- (bsign
* min(*(xt
++), *(yt
+ 2))));
1545 channel2
= channel
+ (channel
>> 3);
1546 if (channel2
< channel
) channel2
= ~0;
1555 void BImage::cdgradient(void) {
1556 // cross diagonal gradient - based on original dgradient, written by
1557 // Mosfet (mosfet@kde.org)
1558 // adapted from kde sources for Blackbox by Brad Hughes
1560 float drx
, dgx
, dbx
, dry
, dgy
, dby
, yr
= 0.0, yg
= 0.0, yb
= 0.0,
1561 xr
= (float) from
.red(),
1562 xg
= (float) from
.green(),
1563 xb
= (float) from
.blue();
1564 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1565 unsigned int w
= width
* 2, h
= height
* 2, *xt
, *yt
;
1567 register unsigned int x
, y
;
1569 dry
= drx
= (float) (to
.red() - from
.red());
1570 dgy
= dgx
= (float) (to
.green() - from
.green());
1571 dby
= dbx
= (float) (to
.blue() - from
.blue());
1578 for (xt
= (xtable
+ (width
* 3) - 1), x
= 0; x
< width
; x
++) {
1579 *(xt
--) = (unsigned char) xb
;
1580 *(xt
--) = (unsigned char) xg
;
1581 *(xt
--) = (unsigned char) xr
;
1593 for (yt
= ytable
, y
= 0; y
< height
; y
++) {
1594 *(yt
++) = (unsigned char) yr
;
1595 *(yt
++) = (unsigned char) yg
;
1596 *(yt
++) = (unsigned char) yb
;
1603 // Combine tables to create gradient
1606 // normal cdgradient
1607 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1608 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1609 *(pr
++) = *(xt
++) + *(yt
);
1610 *(pg
++) = *(xt
++) + *(yt
+ 1);
1611 *(pb
++) = *(xt
++) + *(yt
+ 2);
1615 // faked interlacing effect
1616 unsigned char channel
, channel2
;
1618 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1619 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1621 channel
= *(xt
++) + *(yt
);
1622 channel2
= (channel
>> 1) + (channel
>> 2);
1623 if (channel2
> channel
) channel2
= 0;
1626 channel
= *(xt
++) + *(yt
+ 1);
1627 channel2
= (channel
>> 1) + (channel
>> 2);
1628 if (channel2
> channel
) channel2
= 0;
1631 channel
= *(xt
++) + *(yt
+ 2);
1632 channel2
= (channel
>> 1) + (channel
>> 2);
1633 if (channel2
> channel
) channel2
= 0;
1636 channel
= *(xt
++) + *(yt
);
1637 channel2
= channel
+ (channel
>> 3);
1638 if (channel2
< channel
) channel2
= ~0;
1641 channel
= *(xt
++) + *(yt
+ 1);
1642 channel2
= channel
+ (channel
>> 3);
1643 if (channel2
< channel
) channel2
= ~0;
1646 channel
= *(xt
++) + *(yt
+ 2);
1647 channel2
= channel
+ (channel
>> 3);
1648 if (channel2
< channel
) channel2
= ~0;