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