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