]> Dogcows Code - chaz/openbox/blob - src/image.cc
add comment for later
[chaz/openbox] / src / image.cc
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)
5 //
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:
12 //
13 // The above copyright notice and this permission notice shall be included in
14 // all copies or substantial portions of the Software.
15 //
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.
23
24 #ifdef HAVE_CONFIG_H
25 # include "../config.h"
26 #endif // HAVE_CONFIG_H
27
28 #ifdef HAVE_STDIO_H
29 # include <stdio.h>
30 #endif // HAVE_STDIO_H
31
32 #include <algorithm>
33 using std::max;
34 using std::min;
35
36 #include "blackbox.hh"
37 #include "basedisplay.hh"
38 #include "gccache.hh"
39 #include "image.hh"
40 #include "texture.hh"
41
42
43 BImage::BImage(BImageControl *c, int w, int h) {
44 control = c;
45
46 width = (w > 0) ? w : 1;
47 height = (h > 0) ? h : 1;
48
49 red = new unsigned char[width * height];
50 green = new unsigned char[width * height];
51 blue = new unsigned char[width * height];
52
53 xtable = ytable = (unsigned int *) 0;
54
55 cpc = control->getColorsPerChannel();
56 cpccpc = cpc * cpc;
57
58 control->getColorTables(&red_table, &green_table, &blue_table,
59 &red_offset, &green_offset, &blue_offset,
60 &red_bits, &green_bits, &blue_bits);
61
62 if (control->getVisual()->c_class != TrueColor)
63 control->getXColorTable(&colors, &ncolors);
64 }
65
66
67 BImage::~BImage(void) {
68 delete [] red;
69 delete [] green;
70 delete [] blue;
71 }
72
73
74 Pixmap BImage::render(const BTexture &texture) {
75 if (texture.texture() & BTexture::Parent_Relative)
76 return ParentRelative;
77 else if (texture.texture() & BTexture::Solid)
78 return render_solid(texture);
79 else if (texture.texture() & BTexture::Gradient)
80 return render_gradient(texture);
81 return None;
82 }
83
84
85 Pixmap BImage::render_solid(const BTexture &texture) {
86 Pixmap pixmap = XCreatePixmap(control->getBaseDisplay()->getXDisplay(),
87 control->getDrawable(), width,
88 height, control->getDepth());
89 if (pixmap == None) {
90 fprintf(stderr, "BImage::render_solid: error creating pixmap\n");
91 return None;
92 }
93
94 Display *display = control->getBaseDisplay()->getXDisplay();
95
96 BPen pen(texture.color());
97 BPen penlight(texture.lightColor());
98 BPen penshadow(texture.shadowColor());
99
100 XFillRectangle(display, pixmap, pen.gc(), 0, 0, width, height);
101
102 if (texture.texture() & BTexture::Interlaced) {
103 BPen peninterlace(texture.colorTo());
104 for (unsigned int i = 0; i < height; i += 2)
105 XDrawLine(display, pixmap, peninterlace.gc(), 0, i, width, i);
106 }
107
108 int left = 0, top = 0, right = width - 1, bottom = height - 1;
109
110 if (texture.texture() & BTexture::Border) {
111 BPen penborder(texture.borderColor());
112 XDrawRectangle(display, pixmap, penborder.gc(),
113 left, top, right, bottom);
114 }
115
116 if (texture.texture() & BTexture::Bevel1) {
117 if (texture.texture() & BTexture::Raised) {
118 XDrawLine(display, pixmap, penshadow.gc(),
119 left, bottom, right, bottom);
120 XDrawLine(display, pixmap, penshadow.gc(),
121 right, bottom, right, top);
122
123 XDrawLine(display, pixmap, penlight.gc(),
124 left, top, right, top);
125 XDrawLine(display, pixmap, penlight.gc(),
126 left, bottom, left, top);
127 } else if (texture.texture() & BTexture::Sunken) {
128 XDrawLine(display, pixmap, penlight.gc(),
129 left, bottom, right, bottom);
130 XDrawLine(display, pixmap, penlight.gc(),
131 right, bottom, right, top);
132
133 XDrawLine(display, pixmap, penshadow.gc(),
134 left, top, right, top);
135 XDrawLine(display, pixmap, penshadow.gc(),
136 left, bottom, left, top);
137 }
138 } else if (texture.texture() & BTexture::Bevel2) {
139 if (texture.texture() & BTexture::Raised) {
140 XDrawLine(display, pixmap, penshadow.gc(),
141 left + 1, bottom - 2, right - 2, bottom - 2);
142 XDrawLine(display, pixmap, penshadow.gc(),
143 right - 2, bottom - 2, right - 2, top + 1);
144
145 XDrawLine(display, pixmap, penlight.gc(),
146 left + 1, top + 1, right - 2, top + 1);
147 XDrawLine(display, pixmap, penlight.gc(),
148 left + 1, bottom - 2, left + 1, top + 1);
149 } else if (texture.texture() & BTexture::Sunken) {
150 XDrawLine(display, pixmap, penlight.gc(),
151 left + 1, bottom - 2, right - 2, bottom - 2);
152 XDrawLine(display, pixmap, penlight.gc(),
153 right - 2, bottom - 2, right - 2, top + 1);
154
155 XDrawLine(display, pixmap, penshadow.gc(),
156 left + 1, top + 1, right - 2, top + 1);
157 XDrawLine(display, pixmap, penshadow.gc(),
158 left + 1, bottom - 2, left + 1, top + 1);
159 }
160 }
161
162 return pixmap;
163 }
164
165
166 Pixmap BImage::render_gradient(const BTexture &texture) {
167 bool inverted = False;
168
169 interlaced = texture.texture() & BTexture::Interlaced;
170
171 if (texture.texture() & BTexture::Sunken) {
172 from = texture.colorTo();
173 to = texture.color();
174
175 if (! (texture.texture() & BTexture::Invert)) inverted = True;
176 } else {
177 from = texture.color();
178 to = texture.colorTo();
179
180 if (texture.texture() & BTexture::Invert) inverted = True;
181 }
182
183 control->getGradientBuffers(width, height, &xtable, &ytable);
184
185 if (texture.texture() & BTexture::Diagonal) dgradient();
186 else if (texture.texture() & BTexture::Elliptic) egradient();
187 else if (texture.texture() & BTexture::Horizontal) hgradient();
188 else if (texture.texture() & BTexture::Pyramid) pgradient();
189 else if (texture.texture() & BTexture::Rectangle) rgradient();
190 else if (texture.texture() & BTexture::Vertical) vgradient();
191 else if (texture.texture() & BTexture::CrossDiagonal) cdgradient();
192 else if (texture.texture() & BTexture::PipeCross) pcgradient();
193
194 if (texture.texture() & BTexture::Bevel1) bevel1();
195 else if (texture.texture() & BTexture::Bevel2) bevel2();
196
197 if (texture.texture() & BTexture::Border) border(texture);
198
199 if (inverted) invert();
200
201 return renderPixmap();
202
203 }
204
205
206 static const unsigned char dither4[4][4] = {
207 {0, 4, 1, 5},
208 {6, 2, 7, 3},
209 {1, 5, 0, 4},
210 {7, 3, 6, 2}
211 };
212
213
214 /*
215 * Helper function for TrueColorDither and renderXImage
216 *
217 * This handles the proper setting of the image data based on the image depth
218 * and the machine's byte ordering
219 */
220 static inline
221 void assignPixelData(unsigned int bit_depth, unsigned char **data,
222 unsigned long pixel) {
223 unsigned char *pixel_data = *data;
224 switch (bit_depth) {
225 case 8: // 8bpp
226 *pixel_data++ = pixel;
227 break;
228
229 case 16: // 16bpp LSB
230 *pixel_data++ = pixel;
231 *pixel_data++ = pixel >> 8;
232 break;
233
234 case 17: // 16bpp MSB
235 *pixel_data++ = pixel >> 8;
236 *pixel_data++ = pixel;
237 break;
238
239 case 24: // 24bpp LSB
240 *pixel_data++ = pixel;
241 *pixel_data++ = pixel >> 8;
242 *pixel_data++ = pixel >> 16;
243 break;
244
245 case 25: // 24bpp MSB
246 *pixel_data++ = pixel >> 16;
247 *pixel_data++ = pixel >> 8;
248 *pixel_data++ = pixel;
249 break;
250
251 case 32: // 32bpp LSB
252 *pixel_data++ = pixel;
253 *pixel_data++ = pixel >> 8;
254 *pixel_data++ = pixel >> 16;
255 *pixel_data++ = pixel >> 24;
256 break;
257
258 case 33: // 32bpp MSB
259 *pixel_data++ = pixel >> 24;
260 *pixel_data++ = pixel >> 16;
261 *pixel_data++ = pixel >> 8;
262 *pixel_data++ = pixel;
263 break;
264 }
265 *data = pixel_data; // assign back so we don't lose our place
266 }
267
268
269 // algorithm: ordered dithering... many many thanks to rasterman
270 // (raster@rasterman.com) for telling me about this... portions of this
271 // code is based off of his code in Imlib
272 void BImage::TrueColorDither(unsigned int bit_depth, int bytes_per_line,
273 unsigned char *pixel_data) {
274 unsigned int x, y, dithx, dithy, r, g, b, er, eg, eb, offset;
275 unsigned char *ppixel_data = pixel_data;
276 unsigned long pixel;
277
278 for (y = 0, offset = 0; y < height; y++) {
279 dithy = y & 0x3;
280
281 for (x = 0; x < width; x++, offset++) {
282 dithx = x & 0x3;
283 r = red[offset];
284 g = green[offset];
285 b = blue[offset];
286
287 er = r & (red_bits - 1);
288 eg = g & (green_bits - 1);
289 eb = b & (blue_bits - 1);
290
291 r = red_table[r];
292 g = green_table[g];
293 b = blue_table[b];
294
295 if ((dither4[dithy][dithx] < er) && (r < red_table[255])) r++;
296 if ((dither4[dithy][dithx] < eg) && (g < green_table[255])) g++;
297 if ((dither4[dithy][dithx] < eb) && (b < blue_table[255])) b++;
298
299 pixel = (r << red_offset) | (g << green_offset) | (b << blue_offset);
300 assignPixelData(bit_depth, &pixel_data, pixel);
301 }
302
303 pixel_data = (ppixel_data += bytes_per_line);
304 }
305 }
306
307 #ifdef ORDEREDPSEUDO
308 const static unsigned char dither8[8][8] = {
309 { 0, 32, 8, 40, 2, 34, 10, 42},
310 { 48, 16, 56, 24, 50, 18, 58, 26},
311 { 12, 44, 4, 36, 14, 46, 6, 38},
312 { 60, 28, 52, 20, 62, 30, 54, 22},
313 { 3, 35, 11, 43, 1, 33, 9, 41},
314 { 51, 19, 59, 27, 49, 17, 57, 25},
315 { 15, 47, 7, 39, 13, 45, 5, 37},
316 { 63, 31, 55, 23, 61, 29, 53, 21}
317 };
318
319 void BImage::OrderedPseudoColorDither(int bytes_per_line,
320 unsigned char *pixel_data) {
321 unsigned int x, y, dithx, dithy, r, g, b, er, eg, eb, offset;
322 unsigned long pixel;
323 unsigned char *ppixel_data = pixel_data;
324
325 for (y = 0, offset = 0; y < height; y++) {
326 dithy = y & 7;
327
328 for (x = 0; x < width; x++, offset++) {
329 dithx = x & 7;
330
331 r = red[offset];
332 g = green[offset];
333 b = blue[offset];
334
335 er = r & (red_bits - 1);
336 eg = g & (green_bits - 1);
337 eb = b & (blue_bits - 1);
338
339 r = red_table[r];
340 g = green_table[g];
341 b = blue_table[b];
342
343 if ((dither8[dithy][dithx] < er) && (r < red_table[255])) r++;
344 if ((dither8[dithy][dithx] < eg) && (g < green_table[255])) g++;
345 if ((dither8[dithy][dithx] < eb) && (b < blue_table[255])) b++;
346
347 pixel = (r * cpccpc) + (g * cpc) + b;
348 *(pixel_data++) = colors[pixel].pixel;
349 }
350
351 pixel_data = (ppixel_data += bytes_per_line);
352 }
353 }
354 #endif
355
356 void BImage::PseudoColorDither(int bytes_per_line, unsigned char *pixel_data) {
357 short *terr,
358 *rerr = new short[width + 2],
359 *gerr = new short[width + 2],
360 *berr = new short[width + 2],
361 *nrerr = new short[width + 2],
362 *ngerr = new short[width + 2],
363 *nberr = new short[width + 2];
364
365 int rr, gg, bb, rer, ger, ber;
366 int dd = 255 / control->getColorsPerChannel();
367 unsigned int x, y, r, g, b, offset;
368 unsigned long pixel;
369 unsigned char *ppixel_data = pixel_data;
370
371 for (x = 0; x < width; x++) {
372 *(rerr + x) = *(red + x);
373 *(gerr + x) = *(green + x);
374 *(berr + x) = *(blue + x);
375 }
376
377 *(rerr + x) = *(gerr + x) = *(berr + x) = 0;
378
379 for (y = 0, offset = 0; y < height; y++) {
380 if (y < (height - 1)) {
381 int i = offset + width;
382 for (x = 0; x < width; x++, i++) {
383 *(nrerr + x) = *(red + i);
384 *(ngerr + x) = *(green + i);
385 *(nberr + x) = *(blue + i);
386 }
387
388 *(nrerr + x) = *(red + (--i));
389 *(ngerr + x) = *(green + i);
390 *(nberr + x) = *(blue + i);
391 }
392
393 for (x = 0; x < width; x++) {
394 rr = rerr[x];
395 gg = gerr[x];
396 bb = berr[x];
397
398 if (rr > 255) rr = 255; else if (rr < 0) rr = 0;
399 if (gg > 255) gg = 255; else if (gg < 0) gg = 0;
400 if (bb > 255) bb = 255; else if (bb < 0) bb = 0;
401
402 r = red_table[rr];
403 g = green_table[gg];
404 b = blue_table[bb];
405
406 rer = rerr[x] - r*dd;
407 ger = gerr[x] - g*dd;
408 ber = berr[x] - b*dd;
409
410 pixel = (r * cpccpc) + (g * cpc) + b;
411 *pixel_data++ = colors[pixel].pixel;
412
413 r = rer >> 1;
414 g = ger >> 1;
415 b = ber >> 1;
416 rerr[x+1] += r;
417 gerr[x+1] += g;
418 berr[x+1] += b;
419 nrerr[x] += r;
420 ngerr[x] += g;
421 nberr[x] += b;
422 }
423
424 offset += width;
425
426 pixel_data = (ppixel_data += bytes_per_line);
427
428 terr = rerr;
429 rerr = nrerr;
430 nrerr = terr;
431
432 terr = gerr;
433 gerr = ngerr;
434 ngerr = terr;
435
436 terr = berr;
437 berr = nberr;
438 nberr = terr;
439 }
440
441 delete [] rerr;
442 delete [] gerr;
443 delete [] berr;
444 delete [] nrerr;
445 delete [] ngerr;
446 delete [] nberr;
447 }
448
449 XImage *BImage::renderXImage(void) {
450 XImage *image =
451 XCreateImage(control->getBaseDisplay()->getXDisplay(),
452 control->getVisual(), control->getDepth(), ZPixmap, 0, 0,
453 width, height, 32, 0);
454
455 if (! image) {
456 fprintf(stderr, "BImage::renderXImage: error creating XImage\n");
457 return (XImage *) 0;
458 }
459
460 // insurance policy
461 image->data = (char *) 0;
462
463 unsigned char *d = new unsigned char[image->bytes_per_line * (height + 1)];
464
465 unsigned int o = image->bits_per_pixel +
466 ((image->byte_order == MSBFirst) ? 1 : 0);
467
468 bool unsupported = False;
469
470 if (control->doDither() && width > 1 && height > 1) {
471 switch (control->getVisual()->c_class) {
472 case TrueColor:
473 TrueColorDither(o, image->bytes_per_line, d);
474 break;
475
476 case StaticColor:
477 case PseudoColor: {
478 #ifdef ORDEREDPSEUDO
479 OrderedPseudoColorDither(image->bytes_per_line, d);
480 #else
481 PseudoColorDither(image->bytes_per_line, d);
482 #endif
483 break;
484 }
485
486 default:
487 unsupported = True;
488 }
489 } else {
490 unsigned int x, y, r, g, b, offset;
491 unsigned char *pixel_data = d, *ppixel_data = d;
492 unsigned long pixel;
493
494 switch (control->getVisual()->c_class) {
495 case StaticColor:
496 case PseudoColor:
497 for (y = 0, offset = 0; y < height; ++y) {
498 for (x = 0; x < width; ++x, ++offset) {
499 r = red_table[red[offset]];
500 g = green_table[green[offset]];
501 b = blue_table[blue[offset]];
502
503 pixel = (r * cpccpc) + (g * cpc) + b;
504 *pixel_data++ = colors[pixel].pixel;
505 }
506
507 pixel_data = (ppixel_data += image->bytes_per_line);
508 }
509
510 break;
511
512 case TrueColor:
513 for (y = 0, offset = 0; y < height; y++) {
514 for (x = 0; x < width; x++, offset++) {
515 r = red_table[red[offset]];
516 g = green_table[green[offset]];
517 b = blue_table[blue[offset]];
518
519 pixel = (r << red_offset) | (g << green_offset) | (b << blue_offset);
520 assignPixelData(o, &pixel_data, pixel);
521 }
522
523 pixel_data = (ppixel_data += image->bytes_per_line);
524 }
525
526 break;
527
528 case StaticGray:
529 case GrayScale:
530 for (y = 0, offset = 0; y < height; y++) {
531 for (x = 0; x < width; x++, offset++) {
532 r = *(red_table + *(red + offset));
533 g = *(green_table + *(green + offset));
534 b = *(blue_table + *(blue + offset));
535
536 g = ((r * 30) + (g * 59) + (b * 11)) / 100;
537 *pixel_data++ = colors[g].pixel;
538 }
539
540 pixel_data = (ppixel_data += image->bytes_per_line);
541 }
542
543 break;
544
545 default:
546 unsupported = True;
547 }
548 }
549
550 if (unsupported) {
551 fprintf(stderr, "BImage::renderXImage: unsupported visual\n");
552 delete [] d;
553 XDestroyImage(image);
554 return (XImage *) 0;
555 }
556
557 image->data = (char *) d;
558
559 return image;
560 }
561
562
563 Pixmap BImage::renderPixmap(void) {
564 Pixmap pixmap =
565 XCreatePixmap(control->getBaseDisplay()->getXDisplay(),
566 control->getDrawable(), width, height, control->getDepth());
567
568 if (pixmap == None) {
569 fprintf(stderr, "BImage::renderPixmap: error creating pixmap\n");
570 return None;
571 }
572
573 XImage *image = renderXImage();
574
575 if (! image) {
576 XFreePixmap(control->getBaseDisplay()->getXDisplay(), pixmap);
577 return None;
578 }
579
580 if (! image->data) {
581 XDestroyImage(image);
582 XFreePixmap(control->getBaseDisplay()->getXDisplay(), pixmap);
583 return None;
584 }
585
586 XPutImage(control->getBaseDisplay()->getXDisplay(), pixmap,
587 DefaultGC(control->getBaseDisplay()->getXDisplay(),
588 control->getScreenInfo()->getScreenNumber()),
589 image, 0, 0, 0, 0, width, height);
590
591 if (image->data) {
592 delete [] image->data;
593 image->data = NULL;
594 }
595
596 XDestroyImage(image);
597
598 return pixmap;
599 }
600
601
602 void BImage::bevel1(void) {
603 if (width > 2 && height > 2) {
604 unsigned char *pr = red, *pg = green, *pb = blue;
605
606 register unsigned char r, g, b, rr ,gg ,bb;
607 register unsigned int w = width, h = height - 1, wh = w * h;
608
609 while (--w) {
610 r = *pr;
611 rr = r + (r >> 1);
612 if (rr < r) rr = ~0;
613 g = *pg;
614 gg = g + (g >> 1);
615 if (gg < g) gg = ~0;
616 b = *pb;
617 bb = b + (b >> 1);
618 if (bb < b) bb = ~0;
619
620 *pr = rr;
621 *pg = gg;
622 *pb = bb;
623
624 r = *(pr + wh);
625 rr = (r >> 2) + (r >> 1);
626 if (rr > r) rr = 0;
627 g = *(pg + wh);
628 gg = (g >> 2) + (g >> 1);
629 if (gg > g) gg = 0;
630 b = *(pb + wh);
631 bb = (b >> 2) + (b >> 1);
632 if (bb > b) bb = 0;
633
634 *((pr++) + wh) = rr;
635 *((pg++) + wh) = gg;
636 *((pb++) + wh) = bb;
637 }
638
639 r = *pr;
640 rr = r + (r >> 1);
641 if (rr < r) rr = ~0;
642 g = *pg;
643 gg = g + (g >> 1);
644 if (gg < g) gg = ~0;
645 b = *pb;
646 bb = b + (b >> 1);
647 if (bb < b) bb = ~0;
648
649 *pr = rr;
650 *pg = gg;
651 *pb = bb;
652
653 r = *(pr + wh);
654 rr = (r >> 2) + (r >> 1);
655 if (rr > r) rr = 0;
656 g = *(pg + wh);
657 gg = (g >> 2) + (g >> 1);
658 if (gg > g) gg = 0;
659 b = *(pb + wh);
660 bb = (b >> 2) + (b >> 1);
661 if (bb > b) bb = 0;
662
663 *(pr + wh) = rr;
664 *(pg + wh) = gg;
665 *(pb + wh) = bb;
666
667 pr = red + width;
668 pg = green + width;
669 pb = blue + width;
670
671 while (--h) {
672 r = *pr;
673 rr = r + (r >> 1);
674 if (rr < r) rr = ~0;
675 g = *pg;
676 gg = g + (g >> 1);
677 if (gg < g) gg = ~0;
678 b = *pb;
679 bb = b + (b >> 1);
680 if (bb < b) bb = ~0;
681
682 *pr = rr;
683 *pg = gg;
684 *pb = bb;
685
686 pr += width - 1;
687 pg += width - 1;
688 pb += width - 1;
689
690 r = *pr;
691 rr = (r >> 2) + (r >> 1);
692 if (rr > r) rr = 0;
693 g = *pg;
694 gg = (g >> 2) + (g >> 1);
695 if (gg > g) gg = 0;
696 b = *pb;
697 bb = (b >> 2) + (b >> 1);
698 if (bb > b) bb = 0;
699
700 *(pr++) = rr;
701 *(pg++) = gg;
702 *(pb++) = bb;
703 }
704
705 r = *pr;
706 rr = r + (r >> 1);
707 if (rr < r) rr = ~0;
708 g = *pg;
709 gg = g + (g >> 1);
710 if (gg < g) gg = ~0;
711 b = *pb;
712 bb = b + (b >> 1);
713 if (bb < b) bb = ~0;
714
715 *pr = rr;
716 *pg = gg;
717 *pb = bb;
718
719 pr += width - 1;
720 pg += width - 1;
721 pb += width - 1;
722
723 r = *pr;
724 rr = (r >> 2) + (r >> 1);
725 if (rr > r) rr = 0;
726 g = *pg;
727 gg = (g >> 2) + (g >> 1);
728 if (gg > g) gg = 0;
729 b = *pb;
730 bb = (b >> 2) + (b >> 1);
731 if (bb > b) bb = 0;
732
733 *pr = rr;
734 *pg = gg;
735 *pb = bb;
736 }
737 }
738
739
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);
745
746 while (--w) {
747 r = *pr;
748 rr = r + (r >> 1);
749 if (rr < r) rr = ~0;
750 g = *pg;
751 gg = g + (g >> 1);
752 if (gg < g) gg = ~0;
753 b = *pb;
754 bb = b + (b >> 1);
755 if (bb < b) bb = ~0;
756
757 *pr = rr;
758 *pg = gg;
759 *pb = bb;
760
761 r = *(pr + wh);
762 rr = (r >> 2) + (r >> 1);
763 if (rr > r) rr = 0;
764 g = *(pg + wh);
765 gg = (g >> 2) + (g >> 1);
766 if (gg > g) gg = 0;
767 b = *(pb + wh);
768 bb = (b >> 2) + (b >> 1);
769 if (bb > b) bb = 0;
770
771 *((pr++) + wh) = rr;
772 *((pg++) + wh) = gg;
773 *((pb++) + wh) = bb;
774 }
775
776 pr = red + width;
777 pg = green + width;
778 pb = blue + width;
779
780 while (--h) {
781 r = *pr;
782 rr = r + (r >> 1);
783 if (rr < r) rr = ~0;
784 g = *pg;
785 gg = g + (g >> 1);
786 if (gg < g) gg = ~0;
787 b = *pb;
788 bb = b + (b >> 1);
789 if (bb < b) bb = ~0;
790
791 *(++pr) = rr;
792 *(++pg) = gg;
793 *(++pb) = bb;
794
795 pr += width - 3;
796 pg += width - 3;
797 pb += width - 3;
798
799 r = *pr;
800 rr = (r >> 2) + (r >> 1);
801 if (rr > r) rr = 0;
802 g = *pg;
803 gg = (g >> 2) + (g >> 1);
804 if (gg > g) gg = 0;
805 b = *pb;
806 bb = (b >> 2) + (b >> 1);
807 if (bb > b) bb = 0;
808
809 *(pr++) = rr;
810 *(pg++) = gg;
811 *(pb++) = bb;
812
813 pr++; pg++; pb++;
814 }
815 }
816 }
817
818
819 void BImage::border(const BTexture &texture) {
820 if (width < 2 || height < 2) return;
821
822 register unsigned int i;
823 int r = texture.borderColor().red(),
824 g = texture.borderColor().green(),
825 b = texture.borderColor().blue();
826
827 unsigned char *pr, *pg, *pb;
828
829 // top line
830 pr = red;
831 pg = green;
832 pb = blue;
833 for (i = 0; i < width; ++i) {
834 *pr++ = r;
835 *pg++ = g;
836 *pb++ = b;
837 }
838
839 if (height > 2) {
840 // left and right lines (pr,pg,pb are already lined up)
841 for (i = 1; i < height - 1; ++i) {
842 *pr = r;
843 *pg = g;
844 *pb = b;
845 pr += width - 1;
846 pg += width - 1;
847 pb += width - 1;
848 *pr++ = r;
849 *pg++ = g;
850 *pb++ = b;
851 }
852 }
853
854 // bottom line (pr,pg,pb are already lined up)
855 for (i = 0; i < width; ++i) {
856 *pr++ = r;
857 *pg++ = g;
858 *pb++ = b;
859 }
860 }
861
862
863 void BImage::invert(void) {
864 register unsigned int i, j, wh = (width * height) - 1;
865 unsigned char tmp;
866
867 for (i = 0, j = wh; j > i; j--, i++) {
868 tmp = *(red + j);
869 *(red + j) = *(red + i);
870 *(red + i) = tmp;
871
872 tmp = *(green + j);
873 *(green + j) = *(green + i);
874 *(green + i) = tmp;
875
876 tmp = *(blue + j);
877 *(blue + j) = *(blue + i);
878 *(blue + i) = tmp;
879 }
880 }
881
882
883 void BImage::dgradient(void) {
884 // diagonal gradient code was written by Mike Cole <mike@mydot.com>
885 // modified for interlacing by Brad Hughes
886
887 float drx, dgx, dbx, dry, dgy, dby, yr = 0.0, yg = 0.0, yb = 0.0,
888 xr = (float) from.red(),
889 xg = (float) from.green(),
890 xb = (float) from.blue();
891 unsigned char *pr = red, *pg = green, *pb = blue;
892 unsigned int w = width * 2, h = height * 2, *xt = xtable, *yt = ytable;
893
894 register unsigned int x, y;
895
896 dry = drx = (float) (to.red() - from.red());
897 dgy = dgx = (float) (to.green() - from.green());
898 dby = dbx = (float) (to.blue() - from.blue());
899
900 // Create X table
901 drx /= w;
902 dgx /= w;
903 dbx /= w;
904
905 for (x = 0; x < width; x++) {
906 *(xt++) = (unsigned char) (xr);
907 *(xt++) = (unsigned char) (xg);
908 *(xt++) = (unsigned char) (xb);
909
910 xr += drx;
911 xg += dgx;
912 xb += dbx;
913 }
914
915 // Create Y table
916 dry /= h;
917 dgy /= h;
918 dby /= h;
919
920 for (y = 0; y < height; y++) {
921 *(yt++) = ((unsigned char) yr);
922 *(yt++) = ((unsigned char) yg);
923 *(yt++) = ((unsigned char) yb);
924
925 yr += dry;
926 yg += dgy;
927 yb += dby;
928 }
929
930 // Combine tables to create gradient
931
932 if (! interlaced) {
933 // normal dgradient
934 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
935 for (xt = xtable, x = 0; x < width; x++) {
936 *(pr++) = *(xt++) + *(yt);
937 *(pg++) = *(xt++) + *(yt + 1);
938 *(pb++) = *(xt++) + *(yt + 2);
939 }
940 }
941 } else {
942 // faked interlacing effect
943 unsigned char channel, channel2;
944
945 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
946 for (xt = xtable, x = 0; x < width; x++) {
947 if (y & 1) {
948 channel = *(xt++) + *(yt);
949 channel2 = (channel >> 1) + (channel >> 2);
950 if (channel2 > channel) channel2 = 0;
951 *(pr++) = channel2;
952
953 channel = *(xt++) + *(yt + 1);
954 channel2 = (channel >> 1) + (channel >> 2);
955 if (channel2 > channel) channel2 = 0;
956 *(pg++) = channel2;
957
958 channel = *(xt++) + *(yt + 2);
959 channel2 = (channel >> 1) + (channel >> 2);
960 if (channel2 > channel) channel2 = 0;
961 *(pb++) = channel2;
962 } else {
963 channel = *(xt++) + *(yt);
964 channel2 = channel + (channel >> 3);
965 if (channel2 < channel) channel2 = ~0;
966 *(pr++) = channel2;
967
968 channel = *(xt++) + *(yt + 1);
969 channel2 = channel + (channel >> 3);
970 if (channel2 < channel) channel2 = ~0;
971 *(pg++) = channel2;
972
973 channel = *(xt++) + *(yt + 2);
974 channel2 = channel + (channel >> 3);
975 if (channel2 < channel) channel2 = ~0;
976 *(pb++) = channel2;
977 }
978 }
979 }
980 }
981 }
982
983
984 void BImage::hgradient(void) {
985 float drx, dgx, dbx,
986 xr = (float) from.red(),
987 xg = (float) from.green(),
988 xb = (float) from.blue();
989 unsigned char *pr = red, *pg = green, *pb = blue;
990
991 register unsigned int x, y;
992
993 drx = (float) (to.red() - from.red());
994 dgx = (float) (to.green() - from.green());
995 dbx = (float) (to.blue() - from.blue());
996
997 drx /= width;
998 dgx /= width;
999 dbx /= width;
1000
1001 if (interlaced && height > 2) {
1002 // faked interlacing effect
1003 unsigned char channel, channel2;
1004
1005 for (x = 0; x < width; x++, pr++, pg++, pb++) {
1006 channel = (unsigned char) xr;
1007 channel2 = (channel >> 1) + (channel >> 2);
1008 if (channel2 > channel) channel2 = 0;
1009 *pr = channel2;
1010
1011 channel = (unsigned char) xg;
1012 channel2 = (channel >> 1) + (channel >> 2);
1013 if (channel2 > channel) channel2 = 0;
1014 *pg = channel2;
1015
1016 channel = (unsigned char) xb;
1017 channel2 = (channel >> 1) + (channel >> 2);
1018 if (channel2 > channel) channel2 = 0;
1019 *pb = channel2;
1020
1021
1022 channel = (unsigned char) xr;
1023 channel2 = channel + (channel >> 3);
1024 if (channel2 < channel) channel2 = ~0;
1025 *(pr + width) = channel2;
1026
1027 channel = (unsigned char) xg;
1028 channel2 = channel + (channel >> 3);
1029 if (channel2 < channel) channel2 = ~0;
1030 *(pg + width) = channel2;
1031
1032 channel = (unsigned char) xb;
1033 channel2 = channel + (channel >> 3);
1034 if (channel2 < channel) channel2 = ~0;
1035 *(pb + width) = channel2;
1036
1037 xr += drx;
1038 xg += dgx;
1039 xb += dbx;
1040 }
1041
1042 pr += width;
1043 pg += width;
1044 pb += width;
1045
1046 int offset;
1047
1048 for (y = 2; y < height; y++, pr += width, pg += width, pb += width) {
1049 if (y & 1) offset = width; else offset = 0;
1050
1051 memcpy(pr, (red + offset), width);
1052 memcpy(pg, (green + offset), width);
1053 memcpy(pb, (blue + offset), width);
1054 }
1055 } else {
1056 // normal hgradient
1057 for (x = 0; x < width; x++) {
1058 *(pr++) = (unsigned char) (xr);
1059 *(pg++) = (unsigned char) (xg);
1060 *(pb++) = (unsigned char) (xb);
1061
1062 xr += drx;
1063 xg += dgx;
1064 xb += dbx;
1065 }
1066
1067 for (y = 1; y < height; y++, pr += width, pg += width, pb += width) {
1068 memcpy(pr, red, width);
1069 memcpy(pg, green, width);
1070 memcpy(pb, blue, width);
1071 }
1072 }
1073 }
1074
1075
1076 void BImage::vgradient(void) {
1077 float dry, dgy, dby,
1078 yr = (float) from.red(),
1079 yg = (float) from.green(),
1080 yb = (float) from.blue();
1081 unsigned char *pr = red, *pg = green, *pb = blue;
1082
1083 register unsigned int y;
1084
1085 dry = (float) (to.red() - from.red());
1086 dgy = (float) (to.green() - from.green());
1087 dby = (float) (to.blue() - from.blue());
1088
1089 dry /= height;
1090 dgy /= height;
1091 dby /= height;
1092
1093 if (interlaced) {
1094 // faked interlacing effect
1095 unsigned char channel, channel2;
1096
1097 for (y = 0; y < height; y++, pr += width, pg += width, pb += width) {
1098 if (y & 1) {
1099 channel = (unsigned char) yr;
1100 channel2 = (channel >> 1) + (channel >> 2);
1101 if (channel2 > channel) channel2 = 0;
1102 memset(pr, channel2, width);
1103
1104 channel = (unsigned char) yg;
1105 channel2 = (channel >> 1) + (channel >> 2);
1106 if (channel2 > channel) channel2 = 0;
1107 memset(pg, channel2, width);
1108
1109 channel = (unsigned char) yb;
1110 channel2 = (channel >> 1) + (channel >> 2);
1111 if (channel2 > channel) channel2 = 0;
1112 memset(pb, channel2, width);
1113 } else {
1114 channel = (unsigned char) yr;
1115 channel2 = channel + (channel >> 3);
1116 if (channel2 < channel) channel2 = ~0;
1117 memset(pr, channel2, width);
1118
1119 channel = (unsigned char) yg;
1120 channel2 = channel + (channel >> 3);
1121 if (channel2 < channel) channel2 = ~0;
1122 memset(pg, channel2, width);
1123
1124 channel = (unsigned char) yb;
1125 channel2 = channel + (channel >> 3);
1126 if (channel2 < channel) channel2 = ~0;
1127 memset(pb, channel2, width);
1128 }
1129
1130 yr += dry;
1131 yg += dgy;
1132 yb += dby;
1133 }
1134 } else {
1135 // normal vgradient
1136 for (y = 0; y < height; y++, pr += width, pg += width, pb += width) {
1137 memset(pr, (unsigned char) yr, width);
1138 memset(pg, (unsigned char) yg, width);
1139 memset(pb, (unsigned char) yb, width);
1140
1141 yr += dry;
1142 yg += dgy;
1143 yb += dby;
1144 }
1145 }
1146 }
1147
1148
1149 void BImage::pgradient(void) {
1150 // pyramid gradient - based on original dgradient, written by
1151 // Mosfet (mosfet@kde.org)
1152 // adapted from kde sources for Blackbox by Brad Hughes
1153
1154 float yr, yg, yb, drx, dgx, dbx, dry, dgy, dby,
1155 xr, xg, xb;
1156 int rsign, gsign, bsign;
1157 unsigned char *pr = red, *pg = green, *pb = blue;
1158 unsigned int tr = to.red(), tg = to.green(), tb = to.blue(),
1159 *xt = xtable, *yt = ytable;
1160
1161 register unsigned int x, y;
1162
1163 dry = drx = (float) (to.red() - from.red());
1164 dgy = dgx = (float) (to.green() - from.green());
1165 dby = dbx = (float) (to.blue() - from.blue());
1166
1167 rsign = (drx < 0) ? -1 : 1;
1168 gsign = (dgx < 0) ? -1 : 1;
1169 bsign = (dbx < 0) ? -1 : 1;
1170
1171 xr = yr = (drx / 2);
1172 xg = yg = (dgx / 2);
1173 xb = yb = (dbx / 2);
1174
1175 // Create X table
1176 drx /= width;
1177 dgx /= width;
1178 dbx /= width;
1179
1180 for (x = 0; x < width; x++) {
1181 *(xt++) = (unsigned char) ((xr < 0) ? -xr : xr);
1182 *(xt++) = (unsigned char) ((xg < 0) ? -xg : xg);
1183 *(xt++) = (unsigned char) ((xb < 0) ? -xb : xb);
1184
1185 xr -= drx;
1186 xg -= dgx;
1187 xb -= dbx;
1188 }
1189
1190 // Create Y table
1191 dry /= height;
1192 dgy /= height;
1193 dby /= height;
1194
1195 for (y = 0; y < height; y++) {
1196 *(yt++) = ((unsigned char) ((yr < 0) ? -yr : yr));
1197 *(yt++) = ((unsigned char) ((yg < 0) ? -yg : yg));
1198 *(yt++) = ((unsigned char) ((yb < 0) ? -yb : yb));
1199
1200 yr -= dry;
1201 yg -= dgy;
1202 yb -= dby;
1203 }
1204
1205 // Combine tables to create gradient
1206
1207 if (! interlaced) {
1208 // normal pgradient
1209 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1210 for (xt = xtable, x = 0; x < width; x++) {
1211 *(pr++) = (unsigned char) (tr - (rsign * (*(xt++) + *(yt))));
1212 *(pg++) = (unsigned char) (tg - (gsign * (*(xt++) + *(yt + 1))));
1213 *(pb++) = (unsigned char) (tb - (bsign * (*(xt++) + *(yt + 2))));
1214 }
1215 }
1216 } else {
1217 // faked interlacing effect
1218 unsigned char channel, channel2;
1219
1220 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1221 for (xt = xtable, x = 0; x < width; x++) {
1222 if (y & 1) {
1223 channel = (unsigned char) (tr - (rsign * (*(xt++) + *(yt))));
1224 channel2 = (channel >> 1) + (channel >> 2);
1225 if (channel2 > channel) channel2 = 0;
1226 *(pr++) = channel2;
1227
1228 channel = (unsigned char) (tg - (gsign * (*(xt++) + *(yt + 1))));
1229 channel2 = (channel >> 1) + (channel >> 2);
1230 if (channel2 > channel) channel2 = 0;
1231 *(pg++) = channel2;
1232
1233 channel = (unsigned char) (tb - (bsign * (*(xt++) + *(yt + 2))));
1234 channel2 = (channel >> 1) + (channel >> 2);
1235 if (channel2 > channel) channel2 = 0;
1236 *(pb++) = channel2;
1237 } else {
1238 channel = (unsigned char) (tr - (rsign * (*(xt++) + *(yt))));
1239 channel2 = channel + (channel >> 3);
1240 if (channel2 < channel) channel2 = ~0;
1241 *(pr++) = channel2;
1242
1243 channel = (unsigned char) (tg - (gsign * (*(xt++) + *(yt + 1))));
1244 channel2 = channel + (channel >> 3);
1245 if (channel2 < channel) channel2 = ~0;
1246 *(pg++) = channel2;
1247
1248 channel = (unsigned char) (tb - (bsign * (*(xt++) + *(yt + 2))));
1249 channel2 = channel + (channel >> 3);
1250 if (channel2 < channel) channel2 = ~0;
1251 *(pb++) = channel2;
1252 }
1253 }
1254 }
1255 }
1256 }
1257
1258
1259 void BImage::rgradient(void) {
1260 // rectangle gradient - based on original dgradient, written by
1261 // Mosfet (mosfet@kde.org)
1262 // adapted from kde sources for Blackbox by Brad Hughes
1263
1264 float drx, dgx, dbx, dry, dgy, dby, xr, xg, xb, yr, yg, yb;
1265 int rsign, gsign, bsign;
1266 unsigned char *pr = red, *pg = green, *pb = blue;
1267 unsigned int tr = to.red(), tg = to.green(), tb = to.blue(),
1268 *xt = xtable, *yt = ytable;
1269
1270 register unsigned int x, y;
1271
1272 dry = drx = (float) (to.red() - from.red());
1273 dgy = dgx = (float) (to.green() - from.green());
1274 dby = dbx = (float) (to.blue() - from.blue());
1275
1276 rsign = (drx < 0) ? -2 : 2;
1277 gsign = (dgx < 0) ? -2 : 2;
1278 bsign = (dbx < 0) ? -2 : 2;
1279
1280 xr = yr = (drx / 2);
1281 xg = yg = (dgx / 2);
1282 xb = yb = (dbx / 2);
1283
1284 // Create X table
1285 drx /= width;
1286 dgx /= width;
1287 dbx /= width;
1288
1289 for (x = 0; x < width; x++) {
1290 *(xt++) = (unsigned char) ((xr < 0) ? -xr : xr);
1291 *(xt++) = (unsigned char) ((xg < 0) ? -xg : xg);
1292 *(xt++) = (unsigned char) ((xb < 0) ? -xb : xb);
1293
1294 xr -= drx;
1295 xg -= dgx;
1296 xb -= dbx;
1297 }
1298
1299 // Create Y table
1300 dry /= height;
1301 dgy /= height;
1302 dby /= height;
1303
1304 for (y = 0; y < height; y++) {
1305 *(yt++) = ((unsigned char) ((yr < 0) ? -yr : yr));
1306 *(yt++) = ((unsigned char) ((yg < 0) ? -yg : yg));
1307 *(yt++) = ((unsigned char) ((yb < 0) ? -yb : yb));
1308
1309 yr -= dry;
1310 yg -= dgy;
1311 yb -= dby;
1312 }
1313
1314 // Combine tables to create gradient
1315
1316 if (! interlaced) {
1317 // normal rgradient
1318 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1319 for (xt = xtable, x = 0; x < width; x++) {
1320 *(pr++) = (unsigned char) (tr - (rsign * max(*(xt++), *(yt))));
1321 *(pg++) = (unsigned char) (tg - (gsign * max(*(xt++), *(yt + 1))));
1322 *(pb++) = (unsigned char) (tb - (bsign * max(*(xt++), *(yt + 2))));
1323 }
1324 }
1325 } else {
1326 // faked interlacing effect
1327 unsigned char channel, channel2;
1328
1329 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1330 for (xt = xtable, x = 0; x < width; x++) {
1331 if (y & 1) {
1332 channel = (unsigned char) (tr - (rsign * max(*(xt++), *(yt))));
1333 channel2 = (channel >> 1) + (channel >> 2);
1334 if (channel2 > channel) channel2 = 0;
1335 *(pr++) = channel2;
1336
1337 channel = (unsigned char) (tg - (gsign * max(*(xt++), *(yt + 1))));
1338 channel2 = (channel >> 1) + (channel >> 2);
1339 if (channel2 > channel) channel2 = 0;
1340 *(pg++) = channel2;
1341
1342 channel = (unsigned char) (tb - (bsign * max(*(xt++), *(yt + 2))));
1343 channel2 = (channel >> 1) + (channel >> 2);
1344 if (channel2 > channel) channel2 = 0;
1345 *(pb++) = channel2;
1346 } else {
1347 channel = (unsigned char) (tr - (rsign * max(*(xt++), *(yt))));
1348 channel2 = channel + (channel >> 3);
1349 if (channel2 < channel) channel2 = ~0;
1350 *(pr++) = channel2;
1351
1352 channel = (unsigned char) (tg - (gsign * max(*(xt++), *(yt + 1))));
1353 channel2 = channel + (channel >> 3);
1354 if (channel2 < channel) channel2 = ~0;
1355 *(pg++) = channel2;
1356
1357 channel = (unsigned char) (tb - (bsign * max(*(xt++), *(yt + 2))));
1358 channel2 = channel + (channel >> 3);
1359 if (channel2 < channel) channel2 = ~0;
1360 *(pb++) = channel2;
1361 }
1362 }
1363 }
1364 }
1365 }
1366
1367
1368 void BImage::egradient(void) {
1369 // elliptic gradient - based on original dgradient, written by
1370 // Mosfet (mosfet@kde.org)
1371 // adapted from kde sources for Blackbox by Brad Hughes
1372
1373 float drx, dgx, dbx, dry, dgy, dby, yr, yg, yb, xr, xg, xb;
1374 int rsign, gsign, bsign;
1375 unsigned char *pr = red, *pg = green, *pb = blue;
1376 unsigned int *xt = xtable, *yt = ytable,
1377 tr = (unsigned long) to.red(),
1378 tg = (unsigned long) to.green(),
1379 tb = (unsigned long) to.blue();
1380
1381 register unsigned int x, y;
1382
1383 dry = drx = (float) (to.red() - from.red());
1384 dgy = dgx = (float) (to.green() - from.green());
1385 dby = dbx = (float) (to.blue() - from.blue());
1386
1387 rsign = (drx < 0) ? -1 : 1;
1388 gsign = (dgx < 0) ? -1 : 1;
1389 bsign = (dbx < 0) ? -1 : 1;
1390
1391 xr = yr = (drx / 2);
1392 xg = yg = (dgx / 2);
1393 xb = yb = (dbx / 2);
1394
1395 // Create X table
1396 drx /= width;
1397 dgx /= width;
1398 dbx /= width;
1399
1400 for (x = 0; x < width; x++) {
1401 *(xt++) = (unsigned long) (xr * xr);
1402 *(xt++) = (unsigned long) (xg * xg);
1403 *(xt++) = (unsigned long) (xb * xb);
1404
1405 xr -= drx;
1406 xg -= dgx;
1407 xb -= dbx;
1408 }
1409
1410 // Create Y table
1411 dry /= height;
1412 dgy /= height;
1413 dby /= height;
1414
1415 for (y = 0; y < height; y++) {
1416 *(yt++) = (unsigned long) (yr * yr);
1417 *(yt++) = (unsigned long) (yg * yg);
1418 *(yt++) = (unsigned long) (yb * yb);
1419
1420 yr -= dry;
1421 yg -= dgy;
1422 yb -= dby;
1423 }
1424
1425 // Combine tables to create gradient
1426
1427 if (! interlaced) {
1428 // normal egradient
1429 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1430 for (xt = xtable, x = 0; x < width; x++) {
1431 *(pr++) = (unsigned char)
1432 (tr - (rsign * control->getSqrt(*(xt++) + *(yt))));
1433 *(pg++) = (unsigned char)
1434 (tg - (gsign * control->getSqrt(*(xt++) + *(yt + 1))));
1435 *(pb++) = (unsigned char)
1436 (tb - (bsign * control->getSqrt(*(xt++) + *(yt + 2))));
1437 }
1438 }
1439 } else {
1440 // faked interlacing effect
1441 unsigned char channel, channel2;
1442
1443 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1444 for (xt = xtable, x = 0; x < width; x++) {
1445 if (y & 1) {
1446 channel = (unsigned char)
1447 (tr - (rsign * control->getSqrt(*(xt++) + *(yt))));
1448 channel2 = (channel >> 1) + (channel >> 2);
1449 if (channel2 > channel) channel2 = 0;
1450 *(pr++) = channel2;
1451
1452 channel = (unsigned char)
1453 (tg - (gsign * control->getSqrt(*(xt++) + *(yt + 1))));
1454 channel2 = (channel >> 1) + (channel >> 2);
1455 if (channel2 > channel) channel2 = 0;
1456 *(pg++) = channel2;
1457
1458 channel = (unsigned char)
1459 (tb - (bsign * control->getSqrt(*(xt++) + *(yt + 2))));
1460 channel2 = (channel >> 1) + (channel >> 2);
1461 if (channel2 > channel) channel2 = 0;
1462 *(pb++) = channel2;
1463 } else {
1464 channel = (unsigned char)
1465 (tr - (rsign * control->getSqrt(*(xt++) + *(yt))));
1466 channel2 = channel + (channel >> 3);
1467 if (channel2 < channel) channel2 = ~0;
1468 *(pr++) = channel2;
1469
1470 channel = (unsigned char)
1471 (tg - (gsign * control->getSqrt(*(xt++) + *(yt + 1))));
1472 channel2 = channel + (channel >> 3);
1473 if (channel2 < channel) channel2 = ~0;
1474 *(pg++) = channel2;
1475
1476 channel = (unsigned char)
1477 (tb - (bsign * control->getSqrt(*(xt++) + *(yt + 2))));
1478 channel2 = channel + (channel >> 3);
1479 if (channel2 < channel) channel2 = ~0;
1480 *(pb++) = channel2;
1481 }
1482 }
1483 }
1484 }
1485 }
1486
1487
1488 void BImage::pcgradient(void) {
1489 // pipe cross gradient - based on original dgradient, written by
1490 // Mosfet (mosfet@kde.org)
1491 // adapted from kde sources for Blackbox by Brad Hughes
1492
1493 float drx, dgx, dbx, dry, dgy, dby, xr, xg, xb, yr, yg, yb;
1494 int rsign, gsign, bsign;
1495 unsigned char *pr = red, *pg = green, *pb = blue;
1496 unsigned int *xt = xtable, *yt = ytable,
1497 tr = to.red(),
1498 tg = to.green(),
1499 tb = to.blue();
1500
1501 register unsigned int x, y;
1502
1503 dry = drx = (float) (to.red() - from.red());
1504 dgy = dgx = (float) (to.green() - from.green());
1505 dby = dbx = (float) (to.blue() - from.blue());
1506
1507 rsign = (drx < 0) ? -2 : 2;
1508 gsign = (dgx < 0) ? -2 : 2;
1509 bsign = (dbx < 0) ? -2 : 2;
1510
1511 xr = yr = (drx / 2);
1512 xg = yg = (dgx / 2);
1513 xb = yb = (dbx / 2);
1514
1515 // Create X table
1516 drx /= width;
1517 dgx /= width;
1518 dbx /= width;
1519
1520 for (x = 0; x < width; x++) {
1521 *(xt++) = (unsigned char) ((xr < 0) ? -xr : xr);
1522 *(xt++) = (unsigned char) ((xg < 0) ? -xg : xg);
1523 *(xt++) = (unsigned char) ((xb < 0) ? -xb : xb);
1524
1525 xr -= drx;
1526 xg -= dgx;
1527 xb -= dbx;
1528 }
1529
1530 // Create Y table
1531 dry /= height;
1532 dgy /= height;
1533 dby /= height;
1534
1535 for (y = 0; y < height; y++) {
1536 *(yt++) = ((unsigned char) ((yr < 0) ? -yr : yr));
1537 *(yt++) = ((unsigned char) ((yg < 0) ? -yg : yg));
1538 *(yt++) = ((unsigned char) ((yb < 0) ? -yb : yb));
1539
1540 yr -= dry;
1541 yg -= dgy;
1542 yb -= dby;
1543 }
1544
1545 // Combine tables to create gradient
1546
1547 if (! interlaced) {
1548 // normal pcgradient
1549 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1550 for (xt = xtable, x = 0; x < width; x++) {
1551 *(pr++) = (unsigned char) (tr - (rsign * min(*(xt++), *(yt))));
1552 *(pg++) = (unsigned char) (tg - (gsign * min(*(xt++), *(yt + 1))));
1553 *(pb++) = (unsigned char) (tb - (bsign * min(*(xt++), *(yt + 2))));
1554 }
1555 }
1556 } else {
1557 // faked interlacing effect
1558 unsigned char channel, channel2;
1559
1560 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1561 for (xt = xtable, x = 0; x < width; x++) {
1562 if (y & 1) {
1563 channel = (unsigned char) (tr - (rsign * min(*(xt++), *(yt))));
1564 channel2 = (channel >> 1) + (channel >> 2);
1565 if (channel2 > channel) channel2 = 0;
1566 *(pr++) = channel2;
1567
1568 channel = (unsigned char) (tg - (bsign * min(*(xt++), *(yt + 1))));
1569 channel2 = (channel >> 1) + (channel >> 2);
1570 if (channel2 > channel) channel2 = 0;
1571 *(pg++) = channel2;
1572
1573 channel = (unsigned char) (tb - (gsign * min(*(xt++), *(yt + 2))));
1574 channel2 = (channel >> 1) + (channel >> 2);
1575 if (channel2 > channel) channel2 = 0;
1576 *(pb++) = channel2;
1577 } else {
1578 channel = (unsigned char) (tr - (rsign * min(*(xt++), *(yt))));
1579 channel2 = channel + (channel >> 3);
1580 if (channel2 < channel) channel2 = ~0;
1581 *(pr++) = channel2;
1582
1583 channel = (unsigned char) (tg - (gsign * min(*(xt++), *(yt + 1))));
1584 channel2 = channel + (channel >> 3);
1585 if (channel2 < channel) channel2 = ~0;
1586 *(pg++) = channel2;
1587
1588 channel = (unsigned char) (tb - (bsign * min(*(xt++), *(yt + 2))));
1589 channel2 = channel + (channel >> 3);
1590 if (channel2 < channel) channel2 = ~0;
1591 *(pb++) = channel2;
1592 }
1593 }
1594 }
1595 }
1596 }
1597
1598
1599 void BImage::cdgradient(void) {
1600 // cross diagonal gradient - based on original dgradient, written by
1601 // Mosfet (mosfet@kde.org)
1602 // adapted from kde sources for Blackbox by Brad Hughes
1603
1604 float drx, dgx, dbx, dry, dgy, dby, yr = 0.0, yg = 0.0, yb = 0.0,
1605 xr = (float) from.red(),
1606 xg = (float) from.green(),
1607 xb = (float) from.blue();
1608 unsigned char *pr = red, *pg = green, *pb = blue;
1609 unsigned int w = width * 2, h = height * 2, *xt, *yt;
1610
1611 register unsigned int x, y;
1612
1613 dry = drx = (float) (to.red() - from.red());
1614 dgy = dgx = (float) (to.green() - from.green());
1615 dby = dbx = (float) (to.blue() - from.blue());
1616
1617 // Create X table
1618 drx /= w;
1619 dgx /= w;
1620 dbx /= w;
1621
1622 for (xt = (xtable + (width * 3) - 1), x = 0; x < width; x++) {
1623 *(xt--) = (unsigned char) xb;
1624 *(xt--) = (unsigned char) xg;
1625 *(xt--) = (unsigned char) xr;
1626
1627 xr += drx;
1628 xg += dgx;
1629 xb += dbx;
1630 }
1631
1632 // Create Y table
1633 dry /= h;
1634 dgy /= h;
1635 dby /= h;
1636
1637 for (yt = ytable, y = 0; y < height; y++) {
1638 *(yt++) = (unsigned char) yr;
1639 *(yt++) = (unsigned char) yg;
1640 *(yt++) = (unsigned char) yb;
1641
1642 yr += dry;
1643 yg += dgy;
1644 yb += dby;
1645 }
1646
1647 // Combine tables to create gradient
1648
1649 if (! interlaced) {
1650 // normal cdgradient
1651 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1652 for (xt = xtable, x = 0; x < width; x++) {
1653 *(pr++) = *(xt++) + *(yt);
1654 *(pg++) = *(xt++) + *(yt + 1);
1655 *(pb++) = *(xt++) + *(yt + 2);
1656 }
1657 }
1658 } else {
1659 // faked interlacing effect
1660 unsigned char channel, channel2;
1661
1662 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1663 for (xt = xtable, x = 0; x < width; x++) {
1664 if (y & 1) {
1665 channel = *(xt++) + *(yt);
1666 channel2 = (channel >> 1) + (channel >> 2);
1667 if (channel2 > channel) channel2 = 0;
1668 *(pr++) = channel2;
1669
1670 channel = *(xt++) + *(yt + 1);
1671 channel2 = (channel >> 1) + (channel >> 2);
1672 if (channel2 > channel) channel2 = 0;
1673 *(pg++) = channel2;
1674
1675 channel = *(xt++) + *(yt + 2);
1676 channel2 = (channel >> 1) + (channel >> 2);
1677 if (channel2 > channel) channel2 = 0;
1678 *(pb++) = channel2;
1679 } else {
1680 channel = *(xt++) + *(yt);
1681 channel2 = channel + (channel >> 3);
1682 if (channel2 < channel) channel2 = ~0;
1683 *(pr++) = channel2;
1684
1685 channel = *(xt++) + *(yt + 1);
1686 channel2 = channel + (channel >> 3);
1687 if (channel2 < channel) channel2 = ~0;
1688 *(pg++) = channel2;
1689
1690 channel = *(xt++) + *(yt + 2);
1691 channel2 = channel + (channel >> 3);
1692 if (channel2 < channel) channel2 = ~0;
1693 *(pb++) = channel2;
1694 }
1695 }
1696 }
1697 }
1698 }
This page took 0.118938 seconds and 4 git commands to generate.