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