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