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