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