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