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::Bevel1
) {
111 if (texture
.texture() & BTexture::Raised
) {
112 XDrawLine(display
, pixmap
, penshadow
.gc(),
113 0, height
- 1, width
- 1, height
- 1);
114 XDrawLine(display
, pixmap
, penshadow
.gc(),
115 width
- 1, height
- 1, width
- 1, 0);
117 XDrawLine(display
, pixmap
, penlight
.gc(),
119 XDrawLine(display
, pixmap
, penlight
.gc(),
120 0, height
- 1, 0, 0);
121 } else if (texture
.texture() & BTexture::Sunken
) {
122 XDrawLine(display
, pixmap
, penlight
.gc(),
123 0, height
- 1, width
- 1, height
- 1);
124 XDrawLine(display
, pixmap
, penlight
.gc(),
125 width
- 1, height
- 1, width
- 1, 0);
127 XDrawLine(display
, pixmap
, penshadow
.gc(),
129 XDrawLine(display
, pixmap
, penshadow
.gc(),
130 0, height
- 1, 0, 0);
132 } else if (texture
.texture() & BTexture::Bevel2
) {
133 if (texture
.texture() & BTexture::Raised
) {
134 XDrawLine(display
, pixmap
, penshadow
.gc(),
135 1, height
- 3, width
- 3, height
- 3);
136 XDrawLine(display
, pixmap
, penshadow
.gc(),
137 width
- 3, height
- 3, width
- 3, 1);
139 XDrawLine(display
, pixmap
, penlight
.gc(),
141 XDrawLine(display
, pixmap
, penlight
.gc(),
142 1, height
- 3, 1, 1);
143 } else if (texture
.texture() & BTexture::Sunken
) {
144 XDrawLine(display
, pixmap
, penlight
.gc(),
145 1, height
- 3, width
- 3, height
- 3);
146 XDrawLine(display
, pixmap
, penlight
.gc(),
147 width
- 3, height
- 3, width
- 3, 1);
149 XDrawLine(display
, pixmap
, penshadow
.gc(),
151 XDrawLine(display
, pixmap
, penshadow
.gc(),
152 1, height
- 3, 1, 1);
160 Pixmap
BImage::render_gradient(const BTexture
&texture
) {
161 bool inverted
= False
;
163 interlaced
= texture
.texture() & BTexture::Interlaced
;
165 if (texture
.texture() & BTexture::Sunken
) {
166 from
= texture
.colorTo();
167 to
= texture
.color();
169 if (! (texture
.texture() & BTexture::Invert
)) inverted
= True
;
171 from
= texture
.color();
172 to
= texture
.colorTo();
174 if (texture
.texture() & BTexture::Invert
) inverted
= True
;
177 control
->getGradientBuffers(width
, height
, &xtable
, &ytable
);
179 if (texture
.texture() & BTexture::Diagonal
) dgradient();
180 else if (texture
.texture() & BTexture::Elliptic
) egradient();
181 else if (texture
.texture() & BTexture::Horizontal
) hgradient();
182 else if (texture
.texture() & BTexture::Pyramid
) pgradient();
183 else if (texture
.texture() & BTexture::Rectangle
) rgradient();
184 else if (texture
.texture() & BTexture::Vertical
) vgradient();
185 else if (texture
.texture() & BTexture::CrossDiagonal
) cdgradient();
186 else if (texture
.texture() & BTexture::PipeCross
) pcgradient();
188 if (texture
.texture() & BTexture::Bevel1
) bevel1();
189 else if (texture
.texture() & BTexture::Bevel2
) bevel2();
191 if (inverted
) invert();
193 return renderPixmap();
198 static const unsigned char dither4
[4][4] = {
207 * Helper function for TrueColorDither and renderXImage
209 * This handles the proper setting of the image data based on the image depth
210 * and the machine's byte ordering
213 void assignPixelData(unsigned int bit_depth
, unsigned char **data
,
214 unsigned long pixel
) {
215 unsigned char *pixel_data
= *data
;
218 *pixel_data
++ = pixel
;
221 case 16: // 16bpp LSB
222 *pixel_data
++ = pixel
;
223 *pixel_data
++ = pixel
>> 8;
226 case 17: // 16bpp MSB
227 *pixel_data
++ = pixel
>> 8;
228 *pixel_data
++ = pixel
;
231 case 24: // 24bpp LSB
232 *pixel_data
++ = pixel
;
233 *pixel_data
++ = pixel
>> 8;
234 *pixel_data
++ = pixel
>> 16;
237 case 25: // 24bpp MSB
238 *pixel_data
++ = pixel
>> 16;
239 *pixel_data
++ = pixel
>> 8;
240 *pixel_data
++ = pixel
;
243 case 32: // 32bpp LSB
244 *pixel_data
++ = pixel
;
245 *pixel_data
++ = pixel
>> 8;
246 *pixel_data
++ = pixel
>> 16;
247 *pixel_data
++ = pixel
>> 24;
250 case 33: // 32bpp MSB
251 *pixel_data
++ = pixel
>> 24;
252 *pixel_data
++ = pixel
>> 16;
253 *pixel_data
++ = pixel
>> 8;
254 *pixel_data
++ = pixel
;
257 *data
= pixel_data
; // assign back so we don't lose our place
261 // algorithm: ordered dithering... many many thanks to rasterman
262 // (raster@rasterman.com) for telling me about this... portions of this
263 // code is based off of his code in Imlib
264 void BImage::TrueColorDither(unsigned int bit_depth
, int bytes_per_line
,
265 unsigned char *pixel_data
) {
266 unsigned int x
, y
, dithx
, dithy
, r
, g
, b
, er
, eg
, eb
, offset
;
267 unsigned char *ppixel_data
= pixel_data
;
270 for (y
= 0, offset
= 0; y
< height
; y
++) {
273 for (x
= 0; x
< width
; x
++, offset
++) {
279 er
= r
& (red_bits
- 1);
280 eg
= g
& (green_bits
- 1);
281 eb
= b
& (blue_bits
- 1);
287 if ((dither4
[dithy
][dithx
] < er
) && (r
< red_table
[255])) r
++;
288 if ((dither4
[dithy
][dithx
] < eg
) && (g
< green_table
[255])) g
++;
289 if ((dither4
[dithy
][dithx
] < eb
) && (b
< blue_table
[255])) b
++;
291 pixel
= (r
<< red_offset
) | (g
<< green_offset
) | (b
<< blue_offset
);
292 assignPixelData(bit_depth
, &pixel_data
, pixel
);
295 pixel_data
= (ppixel_data
+= bytes_per_line
);
300 const static unsigned char dither8
[8][8] = {
301 { 0, 32, 8, 40, 2, 34, 10, 42},
302 { 48, 16, 56, 24, 50, 18, 58, 26},
303 { 12, 44, 4, 36, 14, 46, 6, 38},
304 { 60, 28, 52, 20, 62, 30, 54, 22},
305 { 3, 35, 11, 43, 1, 33, 9, 41},
306 { 51, 19, 59, 27, 49, 17, 57, 25},
307 { 15, 47, 7, 39, 13, 45, 5, 37},
308 { 63, 31, 55, 23, 61, 29, 53, 21}
311 void BImage::OrderedPseudoColorDither(int bytes_per_line
,
312 unsigned char *pixel_data
) {
313 unsigned int x
, y
, dithx
, dithy
, r
, g
, b
, er
, eg
, eb
, offset
;
315 unsigned char *ppixel_data
= pixel_data
;
317 for (y
= 0, offset
= 0; y
< height
; y
++) {
320 for (x
= 0; x
< width
; x
++, offset
++) {
327 er
= r
& (red_bits
- 1);
328 eg
= g
& (green_bits
- 1);
329 eb
= b
& (blue_bits
- 1);
335 if ((dither8
[dithy
][dithx
] < er
) && (r
< red_table
[255])) r
++;
336 if ((dither8
[dithy
][dithx
] < eg
) && (g
< green_table
[255])) g
++;
337 if ((dither8
[dithy
][dithx
] < eb
) && (b
< blue_table
[255])) b
++;
339 pixel
= (r
* cpccpc
) + (g
* cpc
) + b
;
340 *(pixel_data
++) = colors
[pixel
].pixel
;
343 pixel_data
= (ppixel_data
+= bytes_per_line
);
348 void BImage::PseudoColorDither(int bytes_per_line
, unsigned char *pixel_data
) {
350 *rerr
= new short[width
+ 2],
351 *gerr
= new short[width
+ 2],
352 *berr
= new short[width
+ 2],
353 *nrerr
= new short[width
+ 2],
354 *ngerr
= new short[width
+ 2],
355 *nberr
= new short[width
+ 2];
357 int rr
, gg
, bb
, rer
, ger
, ber
;
358 int dd
= 255 / control
->getColorsPerChannel();
359 unsigned int x
, y
, r
, g
, b
, offset
;
361 unsigned char *ppixel_data
= pixel_data
;
363 for (x
= 0; x
< width
; x
++) {
364 *(rerr
+ x
) = *(red
+ x
);
365 *(gerr
+ x
) = *(green
+ x
);
366 *(berr
+ x
) = *(blue
+ x
);
369 *(rerr
+ x
) = *(gerr
+ x
) = *(berr
+ x
) = 0;
371 for (y
= 0, offset
= 0; y
< height
; y
++) {
372 if (y
< (height
- 1)) {
373 int i
= offset
+ width
;
374 for (x
= 0; x
< width
; x
++, i
++) {
375 *(nrerr
+ x
) = *(red
+ i
);
376 *(ngerr
+ x
) = *(green
+ i
);
377 *(nberr
+ x
) = *(blue
+ i
);
380 *(nrerr
+ x
) = *(red
+ (--i
));
381 *(ngerr
+ x
) = *(green
+ i
);
382 *(nberr
+ x
) = *(blue
+ i
);
385 for (x
= 0; x
< width
; x
++) {
390 if (rr
> 255) rr
= 255; else if (rr
< 0) rr
= 0;
391 if (gg
> 255) gg
= 255; else if (gg
< 0) gg
= 0;
392 if (bb
> 255) bb
= 255; else if (bb
< 0) bb
= 0;
398 rer
= rerr
[x
] - r
*dd
;
399 ger
= gerr
[x
] - g
*dd
;
400 ber
= berr
[x
] - b
*dd
;
402 pixel
= (r
* cpccpc
) + (g
* cpc
) + b
;
403 *pixel_data
++ = colors
[pixel
].pixel
;
418 pixel_data
= (ppixel_data
+= bytes_per_line
);
441 XImage
*BImage::renderXImage(void) {
443 XCreateImage(control
->getBaseDisplay()->getXDisplay(),
444 control
->getVisual(), control
->getDepth(), ZPixmap
, 0, 0,
445 width
, height
, 32, 0);
448 fprintf(stderr
, i18n(ImageSet
, ImageErrorCreatingXImage
,
449 "BImage::renderXImage: error creating XImage\n"));
454 image
->data
= (char *) 0;
456 unsigned char *d
= new unsigned char[image
->bytes_per_line
* (height
+ 1)];
458 unsigned int o
= image
->bits_per_pixel
+
459 ((image
->byte_order
== MSBFirst
) ? 1 : 0);
461 bool unsupported
= False
;
463 if (control
->doDither() && width
> 1 && height
> 1) {
464 switch (control
->getVisual()->c_class
) {
466 TrueColorDither(o
, image
->bytes_per_line
, d
);
472 OrderedPseudoColorDither(image
->bytes_per_line
, d
);
474 PseudoColorDither(image
->bytes_per_line
, d
);
483 unsigned int x
, y
, r
, g
, b
, offset
;
484 unsigned char *pixel_data
= d
, *ppixel_data
= d
;
487 switch (control
->getVisual()->c_class
) {
490 for (y
= 0, offset
= 0; y
< height
; ++y
) {
491 for (x
= 0; x
< width
; ++x
, ++offset
) {
492 r
= red_table
[red
[offset
]];
493 g
= green_table
[green
[offset
]];
494 b
= blue_table
[blue
[offset
]];
496 pixel
= (r
* cpccpc
) + (g
* cpc
) + b
;
497 *pixel_data
++ = colors
[pixel
].pixel
;
500 pixel_data
= (ppixel_data
+= image
->bytes_per_line
);
506 for (y
= 0, offset
= 0; y
< height
; y
++) {
507 for (x
= 0; x
< width
; x
++, offset
++) {
508 r
= red_table
[red
[offset
]];
509 g
= green_table
[green
[offset
]];
510 b
= blue_table
[blue
[offset
]];
512 pixel
= (r
<< red_offset
) | (g
<< green_offset
) | (b
<< blue_offset
);
513 assignPixelData(o
, &pixel_data
, pixel
);
516 pixel_data
= (ppixel_data
+= image
->bytes_per_line
);
523 for (y
= 0, offset
= 0; y
< height
; y
++) {
524 for (x
= 0; x
< width
; x
++, offset
++) {
525 r
= *(red_table
+ *(red
+ offset
));
526 g
= *(green_table
+ *(green
+ offset
));
527 b
= *(blue_table
+ *(blue
+ offset
));
529 g
= ((r
* 30) + (g
* 59) + (b
* 11)) / 100;
530 *pixel_data
++ = colors
[g
].pixel
;
533 pixel_data
= (ppixel_data
+= image
->bytes_per_line
);
544 fprintf(stderr
, i18n(ImageSet
, ImageUnsupVisual
,
545 "BImage::renderXImage: unsupported visual\n"));
547 XDestroyImage(image
);
551 image
->data
= (char *) d
;
557 Pixmap
BImage::renderPixmap(void) {
559 XCreatePixmap(control
->getBaseDisplay()->getXDisplay(),
560 control
->getDrawable(), width
, height
, control
->getDepth());
562 if (pixmap
== None
) {
563 fprintf(stderr
, i18n(ImageSet
, ImageErrorCreatingPixmap
,
564 "BImage::renderPixmap: error creating pixmap\n"));
568 XImage
*image
= renderXImage();
571 XFreePixmap(control
->getBaseDisplay()->getXDisplay(), pixmap
);
576 XDestroyImage(image
);
577 XFreePixmap(control
->getBaseDisplay()->getXDisplay(), pixmap
);
581 XPutImage(control
->getBaseDisplay()->getXDisplay(), pixmap
,
582 DefaultGC(control
->getBaseDisplay()->getXDisplay(),
583 control
->getScreenInfo()->getScreenNumber()),
584 image
, 0, 0, 0, 0, width
, height
);
587 delete [] image
->data
;
591 XDestroyImage(image
);
597 void BImage::bevel1(void) {
598 if (width
> 2 && height
> 2) {
599 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
601 register unsigned char r
, g
, b
, rr
,gg
,bb
;
602 register unsigned int w
= width
, h
= height
- 1, wh
= w
* h
;
620 rr
= (r
>> 2) + (r
>> 1);
623 gg
= (g
>> 2) + (g
>> 1);
626 bb
= (b
>> 2) + (b
>> 1);
649 rr
= (r
>> 2) + (r
>> 1);
652 gg
= (g
>> 2) + (g
>> 1);
655 bb
= (b
>> 2) + (b
>> 1);
686 rr
= (r
>> 2) + (r
>> 1);
689 gg
= (g
>> 2) + (g
>> 1);
692 bb
= (b
>> 2) + (b
>> 1);
719 rr
= (r
>> 2) + (r
>> 1);
722 gg
= (g
>> 2) + (g
>> 1);
725 bb
= (b
>> 2) + (b
>> 1);
735 void BImage::bevel2(void) {
736 if (width
> 4 && height
> 4) {
737 unsigned char r
, g
, b
, rr
,gg
,bb
, *pr
= red
+ width
+ 1,
738 *pg
= green
+ width
+ 1, *pb
= blue
+ width
+ 1;
739 unsigned int w
= width
- 2, h
= height
- 1, wh
= width
* (height
- 3);
757 rr
= (r
>> 2) + (r
>> 1);
760 gg
= (g
>> 2) + (g
>> 1);
763 bb
= (b
>> 2) + (b
>> 1);
795 rr
= (r
>> 2) + (r
>> 1);
798 gg
= (g
>> 2) + (g
>> 1);
801 bb
= (b
>> 2) + (b
>> 1);
814 void BImage::invert(void) {
815 register unsigned int i
, j
, wh
= (width
* height
) - 1;
818 for (i
= 0, j
= wh
; j
> i
; j
--, i
++) {
820 *(red
+ j
) = *(red
+ i
);
824 *(green
+ j
) = *(green
+ i
);
828 *(blue
+ j
) = *(blue
+ i
);
834 void BImage::dgradient(void) {
835 // diagonal gradient code was written by Mike Cole <mike@mydot.com>
836 // modified for interlacing by Brad Hughes
838 float drx
, dgx
, dbx
, dry
, dgy
, dby
, yr
= 0.0, yg
= 0.0, yb
= 0.0,
839 xr
= (float) from
.red(),
840 xg
= (float) from
.green(),
841 xb
= (float) from
.blue();
842 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
843 unsigned int w
= width
* 2, h
= height
* 2, *xt
= xtable
, *yt
= ytable
;
845 register unsigned int x
, y
;
847 dry
= drx
= (float) (to
.red() - from
.red());
848 dgy
= dgx
= (float) (to
.green() - from
.green());
849 dby
= dbx
= (float) (to
.blue() - from
.blue());
856 for (x
= 0; x
< width
; x
++) {
857 *(xt
++) = (unsigned char) (xr
);
858 *(xt
++) = (unsigned char) (xg
);
859 *(xt
++) = (unsigned char) (xb
);
871 for (y
= 0; y
< height
; y
++) {
872 *(yt
++) = ((unsigned char) yr
);
873 *(yt
++) = ((unsigned char) yg
);
874 *(yt
++) = ((unsigned char) yb
);
881 // Combine tables to create gradient
885 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
886 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
887 *(pr
++) = *(xt
++) + *(yt
);
888 *(pg
++) = *(xt
++) + *(yt
+ 1);
889 *(pb
++) = *(xt
++) + *(yt
+ 2);
893 // faked interlacing effect
894 unsigned char channel
, channel2
;
896 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
897 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
899 channel
= *(xt
++) + *(yt
);
900 channel2
= (channel
>> 1) + (channel
>> 2);
901 if (channel2
> channel
) channel2
= 0;
904 channel
= *(xt
++) + *(yt
+ 1);
905 channel2
= (channel
>> 1) + (channel
>> 2);
906 if (channel2
> channel
) channel2
= 0;
909 channel
= *(xt
++) + *(yt
+ 2);
910 channel2
= (channel
>> 1) + (channel
>> 2);
911 if (channel2
> channel
) channel2
= 0;
914 channel
= *(xt
++) + *(yt
);
915 channel2
= channel
+ (channel
>> 3);
916 if (channel2
< channel
) channel2
= ~0;
919 channel
= *(xt
++) + *(yt
+ 1);
920 channel2
= channel
+ (channel
>> 3);
921 if (channel2
< channel
) channel2
= ~0;
924 channel
= *(xt
++) + *(yt
+ 2);
925 channel2
= channel
+ (channel
>> 3);
926 if (channel2
< channel
) channel2
= ~0;
935 void BImage::hgradient(void) {
937 xr
= (float) from
.red(),
938 xg
= (float) from
.green(),
939 xb
= (float) from
.blue();
940 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
942 register unsigned int x
, y
;
944 drx
= (float) (to
.red() - from
.red());
945 dgx
= (float) (to
.green() - from
.green());
946 dbx
= (float) (to
.blue() - from
.blue());
952 if (interlaced
&& height
> 2) {
953 // faked interlacing effect
954 unsigned char channel
, channel2
;
956 for (x
= 0; x
< width
; x
++, pr
++, pg
++, pb
++) {
957 channel
= (unsigned char) xr
;
958 channel2
= (channel
>> 1) + (channel
>> 2);
959 if (channel2
> channel
) channel2
= 0;
962 channel
= (unsigned char) xg
;
963 channel2
= (channel
>> 1) + (channel
>> 2);
964 if (channel2
> channel
) channel2
= 0;
967 channel
= (unsigned char) xb
;
968 channel2
= (channel
>> 1) + (channel
>> 2);
969 if (channel2
> channel
) channel2
= 0;
973 channel
= (unsigned char) xr
;
974 channel2
= channel
+ (channel
>> 3);
975 if (channel2
< channel
) channel2
= ~0;
976 *(pr
+ width
) = channel2
;
978 channel
= (unsigned char) xg
;
979 channel2
= channel
+ (channel
>> 3);
980 if (channel2
< channel
) channel2
= ~0;
981 *(pg
+ width
) = channel2
;
983 channel
= (unsigned char) xb
;
984 channel2
= channel
+ (channel
>> 3);
985 if (channel2
< channel
) channel2
= ~0;
986 *(pb
+ width
) = channel2
;
999 for (y
= 2; y
< height
; y
++, pr
+= width
, pg
+= width
, pb
+= width
) {
1000 if (y
& 1) offset
= width
; else offset
= 0;
1002 memcpy(pr
, (red
+ offset
), width
);
1003 memcpy(pg
, (green
+ offset
), width
);
1004 memcpy(pb
, (blue
+ offset
), width
);
1008 for (x
= 0; x
< width
; x
++) {
1009 *(pr
++) = (unsigned char) (xr
);
1010 *(pg
++) = (unsigned char) (xg
);
1011 *(pb
++) = (unsigned char) (xb
);
1018 for (y
= 1; y
< height
; y
++, pr
+= width
, pg
+= width
, pb
+= width
) {
1019 memcpy(pr
, red
, width
);
1020 memcpy(pg
, green
, width
);
1021 memcpy(pb
, blue
, width
);
1027 void BImage::vgradient(void) {
1028 float dry
, dgy
, dby
,
1029 yr
= (float) from
.red(),
1030 yg
= (float) from
.green(),
1031 yb
= (float) from
.blue();
1032 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1034 register unsigned int y
;
1036 dry
= (float) (to
.red() - from
.red());
1037 dgy
= (float) (to
.green() - from
.green());
1038 dby
= (float) (to
.blue() - from
.blue());
1045 // faked interlacing effect
1046 unsigned char channel
, channel2
;
1048 for (y
= 0; y
< height
; y
++, pr
+= width
, pg
+= width
, pb
+= width
) {
1050 channel
= (unsigned char) yr
;
1051 channel2
= (channel
>> 1) + (channel
>> 2);
1052 if (channel2
> channel
) channel2
= 0;
1053 memset(pr
, channel2
, width
);
1055 channel
= (unsigned char) yg
;
1056 channel2
= (channel
>> 1) + (channel
>> 2);
1057 if (channel2
> channel
) channel2
= 0;
1058 memset(pg
, channel2
, width
);
1060 channel
= (unsigned char) yb
;
1061 channel2
= (channel
>> 1) + (channel
>> 2);
1062 if (channel2
> channel
) channel2
= 0;
1063 memset(pb
, channel2
, width
);
1065 channel
= (unsigned char) yr
;
1066 channel2
= channel
+ (channel
>> 3);
1067 if (channel2
< channel
) channel2
= ~0;
1068 memset(pr
, channel2
, width
);
1070 channel
= (unsigned char) yg
;
1071 channel2
= channel
+ (channel
>> 3);
1072 if (channel2
< channel
) channel2
= ~0;
1073 memset(pg
, channel2
, width
);
1075 channel
= (unsigned char) yb
;
1076 channel2
= channel
+ (channel
>> 3);
1077 if (channel2
< channel
) channel2
= ~0;
1078 memset(pb
, channel2
, width
);
1087 for (y
= 0; y
< height
; y
++, pr
+= width
, pg
+= width
, pb
+= width
) {
1088 memset(pr
, (unsigned char) yr
, width
);
1089 memset(pg
, (unsigned char) yg
, width
);
1090 memset(pb
, (unsigned char) yb
, width
);
1100 void BImage::pgradient(void) {
1101 // pyramid gradient - based on original dgradient, written by
1102 // Mosfet (mosfet@kde.org)
1103 // adapted from kde sources for Blackbox by Brad Hughes
1105 float yr
, yg
, yb
, drx
, dgx
, dbx
, dry
, dgy
, dby
,
1107 int rsign
, gsign
, bsign
;
1108 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1109 unsigned int tr
= to
.red(), tg
= to
.green(), tb
= to
.blue(),
1110 *xt
= xtable
, *yt
= ytable
;
1112 register unsigned int x
, y
;
1114 dry
= drx
= (float) (to
.red() - from
.red());
1115 dgy
= dgx
= (float) (to
.green() - from
.green());
1116 dby
= dbx
= (float) (to
.blue() - from
.blue());
1118 rsign
= (drx
< 0) ? -1 : 1;
1119 gsign
= (dgx
< 0) ? -1 : 1;
1120 bsign
= (dbx
< 0) ? -1 : 1;
1122 xr
= yr
= (drx
/ 2);
1123 xg
= yg
= (dgx
/ 2);
1124 xb
= yb
= (dbx
/ 2);
1131 for (x
= 0; x
< width
; x
++) {
1132 *(xt
++) = (unsigned char) ((xr
< 0) ? -xr
: xr
);
1133 *(xt
++) = (unsigned char) ((xg
< 0) ? -xg
: xg
);
1134 *(xt
++) = (unsigned char) ((xb
< 0) ? -xb
: xb
);
1146 for (y
= 0; y
< height
; y
++) {
1147 *(yt
++) = ((unsigned char) ((yr
< 0) ? -yr
: yr
));
1148 *(yt
++) = ((unsigned char) ((yg
< 0) ? -yg
: yg
));
1149 *(yt
++) = ((unsigned char) ((yb
< 0) ? -yb
: yb
));
1156 // Combine tables to create gradient
1160 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1161 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1162 *(pr
++) = (unsigned char) (tr
- (rsign
* (*(xt
++) + *(yt
))));
1163 *(pg
++) = (unsigned char) (tg
- (gsign
* (*(xt
++) + *(yt
+ 1))));
1164 *(pb
++) = (unsigned char) (tb
- (bsign
* (*(xt
++) + *(yt
+ 2))));
1168 // faked interlacing effect
1169 unsigned char channel
, channel2
;
1171 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1172 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1174 channel
= (unsigned char) (tr
- (rsign
* (*(xt
++) + *(yt
))));
1175 channel2
= (channel
>> 1) + (channel
>> 2);
1176 if (channel2
> channel
) channel2
= 0;
1179 channel
= (unsigned char) (tg
- (gsign
* (*(xt
++) + *(yt
+ 1))));
1180 channel2
= (channel
>> 1) + (channel
>> 2);
1181 if (channel2
> channel
) channel2
= 0;
1184 channel
= (unsigned char) (tb
- (bsign
* (*(xt
++) + *(yt
+ 2))));
1185 channel2
= (channel
>> 1) + (channel
>> 2);
1186 if (channel2
> channel
) channel2
= 0;
1189 channel
= (unsigned char) (tr
- (rsign
* (*(xt
++) + *(yt
))));
1190 channel2
= channel
+ (channel
>> 3);
1191 if (channel2
< channel
) channel2
= ~0;
1194 channel
= (unsigned char) (tg
- (gsign
* (*(xt
++) + *(yt
+ 1))));
1195 channel2
= channel
+ (channel
>> 3);
1196 if (channel2
< channel
) channel2
= ~0;
1199 channel
= (unsigned char) (tb
- (bsign
* (*(xt
++) + *(yt
+ 2))));
1200 channel2
= channel
+ (channel
>> 3);
1201 if (channel2
< channel
) channel2
= ~0;
1210 void BImage::rgradient(void) {
1211 // rectangle gradient - based on original dgradient, written by
1212 // Mosfet (mosfet@kde.org)
1213 // adapted from kde sources for Blackbox by Brad Hughes
1215 float drx
, dgx
, dbx
, dry
, dgy
, dby
, xr
, xg
, xb
, yr
, yg
, yb
;
1216 int rsign
, gsign
, bsign
;
1217 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1218 unsigned int tr
= to
.red(), tg
= to
.green(), tb
= to
.blue(),
1219 *xt
= xtable
, *yt
= ytable
;
1221 register unsigned int x
, y
;
1223 dry
= drx
= (float) (to
.red() - from
.red());
1224 dgy
= dgx
= (float) (to
.green() - from
.green());
1225 dby
= dbx
= (float) (to
.blue() - from
.blue());
1227 rsign
= (drx
< 0) ? -2 : 2;
1228 gsign
= (dgx
< 0) ? -2 : 2;
1229 bsign
= (dbx
< 0) ? -2 : 2;
1231 xr
= yr
= (drx
/ 2);
1232 xg
= yg
= (dgx
/ 2);
1233 xb
= yb
= (dbx
/ 2);
1240 for (x
= 0; x
< width
; x
++) {
1241 *(xt
++) = (unsigned char) ((xr
< 0) ? -xr
: xr
);
1242 *(xt
++) = (unsigned char) ((xg
< 0) ? -xg
: xg
);
1243 *(xt
++) = (unsigned char) ((xb
< 0) ? -xb
: xb
);
1255 for (y
= 0; y
< height
; y
++) {
1256 *(yt
++) = ((unsigned char) ((yr
< 0) ? -yr
: yr
));
1257 *(yt
++) = ((unsigned char) ((yg
< 0) ? -yg
: yg
));
1258 *(yt
++) = ((unsigned char) ((yb
< 0) ? -yb
: yb
));
1265 // Combine tables to create gradient
1269 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1270 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1271 *(pr
++) = (unsigned char) (tr
- (rsign
* max(*(xt
++), *(yt
))));
1272 *(pg
++) = (unsigned char) (tg
- (gsign
* max(*(xt
++), *(yt
+ 1))));
1273 *(pb
++) = (unsigned char) (tb
- (bsign
* max(*(xt
++), *(yt
+ 2))));
1277 // faked interlacing effect
1278 unsigned char channel
, channel2
;
1280 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1281 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1283 channel
= (unsigned char) (tr
- (rsign
* max(*(xt
++), *(yt
))));
1284 channel2
= (channel
>> 1) + (channel
>> 2);
1285 if (channel2
> channel
) channel2
= 0;
1288 channel
= (unsigned char) (tg
- (gsign
* max(*(xt
++), *(yt
+ 1))));
1289 channel2
= (channel
>> 1) + (channel
>> 2);
1290 if (channel2
> channel
) channel2
= 0;
1293 channel
= (unsigned char) (tb
- (bsign
* max(*(xt
++), *(yt
+ 2))));
1294 channel2
= (channel
>> 1) + (channel
>> 2);
1295 if (channel2
> channel
) channel2
= 0;
1298 channel
= (unsigned char) (tr
- (rsign
* max(*(xt
++), *(yt
))));
1299 channel2
= channel
+ (channel
>> 3);
1300 if (channel2
< channel
) channel2
= ~0;
1303 channel
= (unsigned char) (tg
- (gsign
* max(*(xt
++), *(yt
+ 1))));
1304 channel2
= channel
+ (channel
>> 3);
1305 if (channel2
< channel
) channel2
= ~0;
1308 channel
= (unsigned char) (tb
- (bsign
* max(*(xt
++), *(yt
+ 2))));
1309 channel2
= channel
+ (channel
>> 3);
1310 if (channel2
< channel
) channel2
= ~0;
1319 void BImage::egradient(void) {
1320 // elliptic gradient - based on original dgradient, written by
1321 // Mosfet (mosfet@kde.org)
1322 // adapted from kde sources for Blackbox by Brad Hughes
1324 float drx
, dgx
, dbx
, dry
, dgy
, dby
, yr
, yg
, yb
, xr
, xg
, xb
;
1325 int rsign
, gsign
, bsign
;
1326 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1327 unsigned int *xt
= xtable
, *yt
= ytable
,
1328 tr
= (unsigned long) to
.red(),
1329 tg
= (unsigned long) to
.green(),
1330 tb
= (unsigned long) to
.blue();
1332 register unsigned int x
, y
;
1334 dry
= drx
= (float) (to
.red() - from
.red());
1335 dgy
= dgx
= (float) (to
.green() - from
.green());
1336 dby
= dbx
= (float) (to
.blue() - from
.blue());
1338 rsign
= (drx
< 0) ? -1 : 1;
1339 gsign
= (dgx
< 0) ? -1 : 1;
1340 bsign
= (dbx
< 0) ? -1 : 1;
1342 xr
= yr
= (drx
/ 2);
1343 xg
= yg
= (dgx
/ 2);
1344 xb
= yb
= (dbx
/ 2);
1351 for (x
= 0; x
< width
; x
++) {
1352 *(xt
++) = (unsigned long) (xr
* xr
);
1353 *(xt
++) = (unsigned long) (xg
* xg
);
1354 *(xt
++) = (unsigned long) (xb
* xb
);
1366 for (y
= 0; y
< height
; y
++) {
1367 *(yt
++) = (unsigned long) (yr
* yr
);
1368 *(yt
++) = (unsigned long) (yg
* yg
);
1369 *(yt
++) = (unsigned long) (yb
* yb
);
1376 // Combine tables to create gradient
1380 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1381 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1382 *(pr
++) = (unsigned char)
1383 (tr
- (rsign
* control
->getSqrt(*(xt
++) + *(yt
))));
1384 *(pg
++) = (unsigned char)
1385 (tg
- (gsign
* control
->getSqrt(*(xt
++) + *(yt
+ 1))));
1386 *(pb
++) = (unsigned char)
1387 (tb
- (bsign
* control
->getSqrt(*(xt
++) + *(yt
+ 2))));
1391 // faked interlacing effect
1392 unsigned char channel
, channel2
;
1394 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1395 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1397 channel
= (unsigned char)
1398 (tr
- (rsign
* control
->getSqrt(*(xt
++) + *(yt
))));
1399 channel2
= (channel
>> 1) + (channel
>> 2);
1400 if (channel2
> channel
) channel2
= 0;
1403 channel
= (unsigned char)
1404 (tg
- (gsign
* control
->getSqrt(*(xt
++) + *(yt
+ 1))));
1405 channel2
= (channel
>> 1) + (channel
>> 2);
1406 if (channel2
> channel
) channel2
= 0;
1409 channel
= (unsigned char)
1410 (tb
- (bsign
* control
->getSqrt(*(xt
++) + *(yt
+ 2))));
1411 channel2
= (channel
>> 1) + (channel
>> 2);
1412 if (channel2
> channel
) channel2
= 0;
1415 channel
= (unsigned char)
1416 (tr
- (rsign
* control
->getSqrt(*(xt
++) + *(yt
))));
1417 channel2
= channel
+ (channel
>> 3);
1418 if (channel2
< channel
) channel2
= ~0;
1421 channel
= (unsigned char)
1422 (tg
- (gsign
* control
->getSqrt(*(xt
++) + *(yt
+ 1))));
1423 channel2
= channel
+ (channel
>> 3);
1424 if (channel2
< channel
) channel2
= ~0;
1427 channel
= (unsigned char)
1428 (tb
- (bsign
* control
->getSqrt(*(xt
++) + *(yt
+ 2))));
1429 channel2
= channel
+ (channel
>> 3);
1430 if (channel2
< channel
) channel2
= ~0;
1439 void BImage::pcgradient(void) {
1440 // pipe cross gradient - based on original dgradient, written by
1441 // Mosfet (mosfet@kde.org)
1442 // adapted from kde sources for Blackbox by Brad Hughes
1444 float drx
, dgx
, dbx
, dry
, dgy
, dby
, xr
, xg
, xb
, yr
, yg
, yb
;
1445 int rsign
, gsign
, bsign
;
1446 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1447 unsigned int *xt
= xtable
, *yt
= ytable
,
1452 register unsigned int x
, y
;
1454 dry
= drx
= (float) (to
.red() - from
.red());
1455 dgy
= dgx
= (float) (to
.green() - from
.green());
1456 dby
= dbx
= (float) (to
.blue() - from
.blue());
1458 rsign
= (drx
< 0) ? -2 : 2;
1459 gsign
= (dgx
< 0) ? -2 : 2;
1460 bsign
= (dbx
< 0) ? -2 : 2;
1462 xr
= yr
= (drx
/ 2);
1463 xg
= yg
= (dgx
/ 2);
1464 xb
= yb
= (dbx
/ 2);
1471 for (x
= 0; x
< width
; x
++) {
1472 *(xt
++) = (unsigned char) ((xr
< 0) ? -xr
: xr
);
1473 *(xt
++) = (unsigned char) ((xg
< 0) ? -xg
: xg
);
1474 *(xt
++) = (unsigned char) ((xb
< 0) ? -xb
: xb
);
1486 for (y
= 0; y
< height
; y
++) {
1487 *(yt
++) = ((unsigned char) ((yr
< 0) ? -yr
: yr
));
1488 *(yt
++) = ((unsigned char) ((yg
< 0) ? -yg
: yg
));
1489 *(yt
++) = ((unsigned char) ((yb
< 0) ? -yb
: yb
));
1496 // Combine tables to create gradient
1499 // normal pcgradient
1500 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1501 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1502 *(pr
++) = (unsigned char) (tr
- (rsign
* min(*(xt
++), *(yt
))));
1503 *(pg
++) = (unsigned char) (tg
- (gsign
* min(*(xt
++), *(yt
+ 1))));
1504 *(pb
++) = (unsigned char) (tb
- (bsign
* min(*(xt
++), *(yt
+ 2))));
1508 // faked interlacing effect
1509 unsigned char channel
, channel2
;
1511 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1512 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1514 channel
= (unsigned char) (tr
- (rsign
* min(*(xt
++), *(yt
))));
1515 channel2
= (channel
>> 1) + (channel
>> 2);
1516 if (channel2
> channel
) channel2
= 0;
1519 channel
= (unsigned char) (tg
- (bsign
* min(*(xt
++), *(yt
+ 1))));
1520 channel2
= (channel
>> 1) + (channel
>> 2);
1521 if (channel2
> channel
) channel2
= 0;
1524 channel
= (unsigned char) (tb
- (gsign
* min(*(xt
++), *(yt
+ 2))));
1525 channel2
= (channel
>> 1) + (channel
>> 2);
1526 if (channel2
> channel
) channel2
= 0;
1529 channel
= (unsigned char) (tr
- (rsign
* min(*(xt
++), *(yt
))));
1530 channel2
= channel
+ (channel
>> 3);
1531 if (channel2
< channel
) channel2
= ~0;
1534 channel
= (unsigned char) (tg
- (gsign
* min(*(xt
++), *(yt
+ 1))));
1535 channel2
= channel
+ (channel
>> 3);
1536 if (channel2
< channel
) channel2
= ~0;
1539 channel
= (unsigned char) (tb
- (bsign
* min(*(xt
++), *(yt
+ 2))));
1540 channel2
= channel
+ (channel
>> 3);
1541 if (channel2
< channel
) channel2
= ~0;
1550 void BImage::cdgradient(void) {
1551 // cross diagonal gradient - based on original dgradient, written by
1552 // Mosfet (mosfet@kde.org)
1553 // adapted from kde sources for Blackbox by Brad Hughes
1555 float drx
, dgx
, dbx
, dry
, dgy
, dby
, yr
= 0.0, yg
= 0.0, yb
= 0.0,
1556 xr
= (float) from
.red(),
1557 xg
= (float) from
.green(),
1558 xb
= (float) from
.blue();
1559 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1560 unsigned int w
= width
* 2, h
= height
* 2, *xt
, *yt
;
1562 register unsigned int x
, y
;
1564 dry
= drx
= (float) (to
.red() - from
.red());
1565 dgy
= dgx
= (float) (to
.green() - from
.green());
1566 dby
= dbx
= (float) (to
.blue() - from
.blue());
1573 for (xt
= (xtable
+ (width
* 3) - 1), x
= 0; x
< width
; x
++) {
1574 *(xt
--) = (unsigned char) xb
;
1575 *(xt
--) = (unsigned char) xg
;
1576 *(xt
--) = (unsigned char) xr
;
1588 for (yt
= ytable
, y
= 0; y
< height
; y
++) {
1589 *(yt
++) = (unsigned char) yr
;
1590 *(yt
++) = (unsigned char) yg
;
1591 *(yt
++) = (unsigned char) yb
;
1598 // Combine tables to create gradient
1601 // normal cdgradient
1602 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1603 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1604 *(pr
++) = *(xt
++) + *(yt
);
1605 *(pg
++) = *(xt
++) + *(yt
+ 1);
1606 *(pb
++) = *(xt
++) + *(yt
+ 2);
1610 // faked interlacing effect
1611 unsigned char channel
, channel2
;
1613 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1614 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1616 channel
= *(xt
++) + *(yt
);
1617 channel2
= (channel
>> 1) + (channel
>> 2);
1618 if (channel2
> channel
) channel2
= 0;
1621 channel
= *(xt
++) + *(yt
+ 1);
1622 channel2
= (channel
>> 1) + (channel
>> 2);
1623 if (channel2
> channel
) channel2
= 0;
1626 channel
= *(xt
++) + *(yt
+ 2);
1627 channel2
= (channel
>> 1) + (channel
>> 2);
1628 if (channel2
> channel
) channel2
= 0;
1631 channel
= *(xt
++) + *(yt
);
1632 channel2
= channel
+ (channel
>> 3);
1633 if (channel2
< channel
) channel2
= ~0;
1636 channel
= *(xt
++) + *(yt
+ 1);
1637 channel2
= channel
+ (channel
>> 3);
1638 if (channel2
< channel
) channel2
= ~0;
1641 channel
= *(xt
++) + *(yt
+ 2);
1642 channel2
= channel
+ (channel
>> 3);
1643 if (channel2
< channel
) channel2
= ~0;