5
* the stone rendering part has been coded by Marin Ferecatu - thanks, good job!
9
#include "imagehandler.h"
23
#include ALT_GHOST_BLACK
24
#include ALT_GHOST_WHITE
28
#define M_PI 3.141592653
29
double drand48() { return rand()*1.0/RAND_MAX; }
34
* Static class variables
36
QPixmap* ImageHandler::woodPixmap1 = NULL;
37
QPixmap* ImageHandler::woodPixmap2 = NULL;
38
QPixmap* ImageHandler::woodPixmap3 = NULL;
39
QPixmap* ImageHandler::woodPixmap4 = NULL;
40
QPixmap* ImageHandler::woodPixmap5 = NULL;
41
QPixmap* ImageHandler::tablePixmap = NULL;
42
QCanvasPixmapArray* ImageHandler::altGhostPixmaps = NULL;
43
int ImageHandler::classCounter = 0;
44
int ImageHandler::antialiasingColor = 0;
45
int ImageHandler::ac1 = 0;
46
int ImageHandler::ac2 = 0;
47
int ImageHandler::ac3 = 0;
48
int ImageHandler::ac4 = 0;
49
int ImageHandler::ac5 = 0;
52
* Stone rendering code
53
* Heavily inspired from Jago and CGoban code
54
* http://www.igoweb.org/~wms/comp/cgoban
55
* /http://www.rene-grothmann.de/jago/
58
void ImageHandler::icopy(int *im, QImage &qim, int w, int h) {
60
for (int y = 0; y < h; y++) {
61
uint *p = (uint *)qim.scanLine(y);
62
for(int x = 0; x < w; x++) {
69
void ImageHandler::decideAppearance(WhiteDesc *desc, int size) {
70
double minStripeW, maxStripeW, theta;
72
minStripeW = (double)size / 20.0;
75
maxStripeW = (double)size / 5.0;
79
theta = drand48() * 2.0 * M_PI;
80
desc->cosTheta = cos(theta);
81
desc->sinTheta = sin(theta);
82
desc->stripeWidth = 1.5*minStripeW +
83
(drand48() * (maxStripeW - minStripeW));
85
desc->xAdd = 3*desc->stripeWidth +
88
desc->stripeMul = 3.0;
89
desc->zMul = drand48() * 650.0 + 70.0;
93
double ImageHandler::getStripe(WhiteDesc &white, double bright, double z, int x, int y) {
96
bright = bright/256.0;
98
double wStripeLoc = x*white.cosTheta - y*white.sinTheta + white.xAdd;
99
double wStripeColor = fmod(wStripeLoc + (z * z * z * white.zMul) *
101
white.stripeWidth) / white.stripeWidth;
102
wStripeColor = wStripeColor * white.stripeMul - 0.5;
103
if (wStripeColor < 0.0)
104
wStripeColor = -2.0 * wStripeColor;
105
if (wStripeColor > 1.0)
107
wStripeColor = wStripeColor * 0.15 + 0.85;
109
wBright = bright*wStripeColor;
119
void ImageHandler::paintBlackStone (QImage &bi, int d) {
121
const double pixel=0.8,shadow=0.99;
123
int col = antialiasingColor; //0xecb164;
124
int blue=col&0x0000FF,green=(col&0x00FF00)>>8,red=(col&0xFF0000)>>16;
128
// these are the images
129
int *pb=new int[d*d];
131
double di, dj, d2=(double)d/2.0-5e-1, r=d2-2e-1, f=sqrt(3);
132
double x, y, z, xr, xg, hh;
136
bool smallerstones = false;
137
if (smallerstones) r-=1;
140
for (j=0; j<d; j++) {
142
hh=r-sqrt(di*di+dj*dj);
145
if (z>0) z=sqrt(z)*f;
148
xr=sqrt(6*(x*x+y*y+z*z));
150
if (xr>0.9) xg=(xr-0.9)*10;
152
if (hh>pixel || !Alias) {
153
g=(int)(10+10*xr+xg*140);
154
pb[k]=(255<<24)|(g<<16)|(g<<8)|g;
158
g=(int)(10+10*xr+xg*140);
160
if (di-dj<r/3) shade=1;
163
|(((int)((1-hh)*g+hh*shade*red))<<16)
164
|(((int)((1-hh)*g+hh*shade*green))<<8)
165
|((int)((1-hh)*g+hh*shade*blue)));
173
// now copy the result in QImages
180
// non shaded white stones
181
void ImageHandler::paintWhiteStone1 (QImage &wi, int d, bool stripes) {
184
decideAppearance(&desc, d);
186
const double pixel=0.8,shadow=0.99;
188
int col = antialiasingColor; //0xecb164;
189
int blue=col&0x0000FF,green=(col&0x00FF00)>>8,red=(col&0xFF0000)>>16;
193
// these are the images
194
int *pw=new int[d*d];
196
double di, dj, d2=(double)d/2.0-5e-1, r=d2-2e-1, f=sqrt(3);
197
double x, y, z, xr, xg, hh;
201
bool smallerstones = false;
202
if (smallerstones) r-=1;
205
for (j=0; j<d; j++) {
207
hh=r-sqrt(di*di+dj*dj);
210
if (z>0) z=sqrt(z)*f;
213
xr=sqrt(6*(x*x+y*y+z*z));
215
if (xr>0.9) xg=(xr-0.9)*10;
217
if (hh>pixel || !Alias) {
218
g=(int)(200+10*xr+xg*45);
220
g = (int)getStripe(desc, g, xr/7.0, i, j);
221
pw[k]=(255<<24)|(g<<16)|((g)<<8)|(g);
225
//g=(int)(10+10*xr+xg*140);
227
if (di-dj<r/3) shade=1;
229
g=(int)(200+10*xr+xg*45);
231
g = (int)getStripe(desc, g, xr/7.0, i, j);
233
|(((int)((1-hh)*g+hh*shade*red))<<16)
234
|(((int)((1-hh)*g+hh*shade*green))<<8)
235
|((int)((1-hh)*g+hh*shade*blue)));
243
// now copy the result in QImages
250
// shaded white stones
251
void ImageHandler::paintWhiteStone2 (QImage &wi, int d, bool stripes) {
254
decideAppearance(&desc, d);
256
// the angle from which the shadow starts (measured to the light direction = pi/4)
257
// alpha should be in (0, pi)
258
const double ALPHA = M_PI/4;
259
// how big the shadow is (should be < d/2)
260
const double STRIPE = d/5.0;
263
const double pixel=0.8, shadow=0.99;
265
int col = antialiasingColor; //0xecb164;
266
int blue=col&0x0000FF,green=(col&0x00FF00)>>8,red=(col&0xFF0000)>>16;
270
// these are the images
271
int *pw=new int[d*d];
273
double di, dj, d2=(double)d/2.0-5e-1, r=d2-2e-1, f=sqrt(3);
274
double x, y, z, xr, xg, hh;
278
bool smallerstones = false;
279
if (smallerstones) r-=1;
282
for (j=0; j<d; j++) {
284
hh=r-sqrt(di*di+dj*dj);
287
if (z>0) z=sqrt(z)*f;
290
xr=sqrt(6*(x*x+y*y+z*z));
292
if (xr>0.9) xg=(xr-0.9)*10;
295
theta = atan2(double(j-d/2), double(i-d/2)) + M_PI - M_PI/4 + M_PI/2;
296
bool stripeband = theta > ALPHA && theta < 2*M_PI-ALPHA;
299
theta = (2*M_PI-theta);
301
double stripe = STRIPE*sin((M_PI/2)*(theta-ALPHA)/(M_PI-ALPHA));
302
if (stripe < 1) stripe = 1;
304
double gmin=(int)(0+10*xr+xg*45);
305
double gmax=(int)(200+10*xr+xg*45);
306
gmin = gmax - (gmax-gmin)*(1-exp(-1*(theta-ALPHA)/(M_PI-ALPHA)));
308
if (hh < STRIPE && hh > pixel && stripeband) {
310
if (hh > stripe) g = (int)gmax;
311
else g = int(gmin + (gmax-gmin)*(hh/stripe));
314
g = (int)getStripe(desc, g, xr/7.0, i, j);
315
pw[k]=(255<<24)|(g<<16)|((g)<<8)|(g);
317
else if (hh>pixel || !Alias) {
318
g=(int)(200+10*xr+xg*45);
320
g = (int)getStripe(desc, g, xr/7.0, i, j);
321
pw[k]=(255<<24)|(g<<16)|((g)<<8)|(g);
325
//g=(int)(10+10*xr+xg*140);
327
if (di-dj<r/3) shade=1;
329
if(stripeband) g=(int)gmin;
330
else g=(int)(200+10*xr+xg*45);
332
g = (int)getStripe(desc, g, xr/7.0, i, j);
334
|(((int)((1-hh)*g+hh*shade*red))<<16)
335
|(((int)((1-hh)*g+hh*shade*green))<<8)
336
|((int)((1-hh)*g+hh*shade*blue)));
343
// now copy the result in QImages
351
void ImageHandler::paintWhiteStone (QImage &wi, int d, bool noShadow, bool stripes)
354
paintWhiteStone1 (wi, d, stripes);
356
paintWhiteStone2 (wi, d, stripes);
360
// This function generates a realistic wood like board image.
361
// It is not really used in the code but included only for
364
void createwood (QImage &im, int w, int h, int color, bool shadows, int ox, int oy, int d) {
366
if (w==0 || h==0) return;
371
if (shadows) ps=new int[w*h];
376
int blue=col&0x0000FF,green=(col&0x00FF00)>>8,red=(col&0xFF0000)>>16;
383
for (j=0; j<w; j++) {
385
f=((sin(18*(double)j/w)+1)/2
386
+(sin(3*(double)j/w)+1)/10
387
+0.2*cos(5*(double)i/h)+
388
+0.1*sin(11*(double)i/h))
391
f=((sin(14*(double)j/w)+1)/2
392
+0.2*cos(3*(double)i/h)+
393
+0.1*sin(11*(double)i/h))
397
else if (f<4e-1) f=1-(4e-1-f)/2;
399
if (i==w-1 || (i==w-2 && j<w-2) || j==0
400
|| (j==1 && i>1)) f=f/2;
401
if (i==0 || (i==1 && j>1) || j>=w-1
402
|| (j==w-2 && i<h-1)) {
403
r=128+red*f/2; g=128+green*f/2; b=128+blue*f/2;
406
r=red*f; g=green*f; b=blue*f;
408
p[w*i+j]=(255<<24)|((int)(r)<<16)|((int)(g)<<8)|(int)(b);
411
y=abs((i-(ox+d/2+(i-ox)/d*(double)d)));
412
x=abs((j-(oy+d/2+(j-oy)/d*(double)d)));
413
dist=sqrt(x*x+y*y)/d*2;
414
if (dist<1.0) f=0.9*dist;
415
ps[w*i+j]=(255<<24)|((int)(r*f)<<16)|((int)(g*f)<<8)|(int)(b*f);
426
* end stone rendering code
432
ImageHandler::ImageHandler()
436
if (tablePixmap == NULL)
437
tablePixmap = new QPixmap(const_cast<const char**>(table_xpm));
438
if (woodPixmap1 == NULL)
439
woodPixmap1 = new QPixmap(const_cast<const char**>(wood_xpm));
440
if (woodPixmap2 == NULL)
441
woodPixmap2 = new QPixmap(const_cast<const char**>(wood2_xpm));
442
if (woodPixmap3 == NULL)
443
woodPixmap3 = new QPixmap(const_cast<const char**>(wood3_xpm));
444
if (woodPixmap4 == NULL)
445
woodPixmap4 = new QPixmap(const_cast<const char**>(wood4_xpm));
446
if (woodPixmap5 == NULL)
447
woodPixmap5 = new QPixmap(const_cast<const char**>(wood5_xpm));
449
if (tablePixmap == NULL)
450
tablePixmap = new QPixmap(TABLE_PIC);
451
if (woodPixmap1 == NULL)
452
// img_wood = QImage(WOOD_PIC);
453
woodPixmap1 = new QPixmap(WOOD_PIC);
454
if (woodPixmap2 == NULL)
455
woodPixmap2 = new QPixmap(WOOD2_PIC);
456
if (woodPixmap3 == NULL)
457
woodPixmap3 = new QPixmap(WOOD3_PIC);
458
if (woodPixmap4 == NULL)
459
woodPixmap4 = new QPixmap(WOOD4_PIC);
460
if (woodPixmap5 == NULL)
461
woodPixmap5 = new QPixmap(WOOD5_PIC);
464
if (tablePixmap == NULL || tablePixmap->isNull())
465
qFatal("Could not load pixmaps.");
467
// get medium color of table pixmap used for antialiasing
468
CHECK_PTR(woodPixmap1);
469
QImage img_ = woodPixmap1->convertToImage();
470
if (img_.valid(0, 0))
471
ac1 = img_.pixel(0, 0);
472
CHECK_PTR(woodPixmap2);
473
img_ = woodPixmap2->convertToImage();
474
if (img_.valid(0, 0))
475
ac2 = img_.pixel(0, 0);
476
CHECK_PTR(woodPixmap3);
477
img_ = woodPixmap3->convertToImage();
478
if (img_.valid(0, 0))
479
ac3 = img_.pixel(0, 0);
480
CHECK_PTR(woodPixmap4);
481
img_ = woodPixmap4->convertToImage();
482
if (img_.valid(0, 0))
483
ac4 = img_.pixel(0, 0);
484
CHECK_PTR(woodPixmap5);
485
img_ = woodPixmap5->convertToImage();
486
if (img_.valid(0, 0))
487
ac5 = img_.pixel(0, 0);
492
// Init the alternate ghost pixmaps
493
if (altGhostPixmaps == NULL)
496
QPixmap alt1(const_cast<const char**>(alt_ghost_black_xpm));
497
QPixmap alt2(const_cast<const char**>(alt_ghost_white_xpm));
499
QPixmap alt1(ALT_GHOST_BLACK);
500
QPixmap alt2(ALT_GHOST_WHITE);
502
if (alt1.isNull() || alt2.isNull())
503
qFatal("Could not load alt_ghost pixmaps.");
507
QList<QPoint> hotspots;
508
hotspots.append(new QPoint(alt1.width()/2, alt1.height()/2));
509
hotspots.append(new QPoint(alt2.width()/2, alt2.height()/2));
510
altGhostPixmaps = new QCanvasPixmapArray(list, hotspots);
512
CHECK_PTR(altGhostPixmaps);
517
ImageHandler::~ImageHandler()
520
if (classCounter == 0)
534
delete altGhostPixmaps;
535
altGhostPixmaps = NULL;
542
QPixmap* ImageHandler::getBoardPixmap(skinType s)
561
void ImageHandler::init(int size)
564
size = size * 9 / 10;
567
bool noShadow = !setting->readBoolEntry("STONES_SHADOW");
568
bool stripes = setting->readBoolEntry("STONES_SHELLS");
569
QImage ib = QImage(size, size, 32);
570
ib.setAlphaBuffer(TRUE);
571
paintBlackStone(ib, size);
573
QImage iw1 = QImage(size, size, 32);
574
iw1.setAlphaBuffer(TRUE);
575
paintWhiteStone(iw1, size, noShadow, stripes);
577
QImage iw2, iw3, iw4, iw5, iw6, iw7, iw8;
581
iw2 = QImage(size, size, 32);
582
iw2.setAlphaBuffer(TRUE);
583
paintWhiteStone(iw2, size, noShadow, stripes);
585
iw3 = QImage(size, size, 32);
586
iw3.setAlphaBuffer(TRUE);
587
paintWhiteStone(iw3, size, noShadow, stripes);
589
iw4 = QImage(size, size, 32);
590
iw4.setAlphaBuffer(TRUE);
591
paintWhiteStone(iw4, size, noShadow, stripes);
593
iw5 = QImage(size, size, 32);
594
iw5.setAlphaBuffer(TRUE);
595
paintWhiteStone(iw5, size, noShadow, stripes);
597
iw6 = QImage(size, size, 32);
598
iw6.setAlphaBuffer(TRUE);
599
paintWhiteStone(iw6, size, noShadow, stripes);
601
iw7 = QImage(size, size, 32);
602
iw7.setAlphaBuffer(TRUE);
603
paintWhiteStone(iw7, size, noShadow, stripes);
605
iw8 = QImage(size, size, 32);
606
iw8.setAlphaBuffer(TRUE);
607
paintWhiteStone(iw8, size, noShadow, stripes);
623
// Convert images to pixmaps
625
QPixmap *ibp = new QPixmap();
626
ibp->convertFromImage(ib,
627
QPixmap::PreferDither |
628
QPixmap::DiffuseAlphaDither |
629
QPixmap::DiffuseDither);
632
QPixmap *iw1p = new QPixmap();
633
iw1p->convertFromImage(iw1,
634
QPixmap::PreferDither |
635
QPixmap::DiffuseAlphaDither |
636
QPixmap::DiffuseDither);
639
QPixmap *iw2p, *iw3p, *iw4p, *iw5p, *iw6p, *iw7p, *iw8p;
643
iw2p = new QPixmap();
644
iw2p->convertFromImage(iw2,
645
QPixmap::PreferDither |
646
QPixmap::DiffuseAlphaDither |
647
QPixmap::DiffuseDither);
650
iw3p = new QPixmap();
651
iw3p->convertFromImage(iw3,
652
QPixmap::PreferDither |
653
QPixmap::DiffuseAlphaDither |
654
QPixmap::DiffuseDither);
657
iw4p = new QPixmap();
658
iw4p->convertFromImage(iw4,
659
QPixmap::PreferDither |
660
QPixmap::DiffuseAlphaDither |
661
QPixmap::DiffuseDither);
664
iw5p = new QPixmap();
665
iw5p->convertFromImage(iw5,
666
QPixmap::PreferDither |
667
QPixmap::DiffuseAlphaDither |
668
QPixmap::DiffuseDither);
671
iw6p = new QPixmap();
672
iw6p->convertFromImage(iw6,
673
QPixmap::PreferDither |
674
QPixmap::DiffuseAlphaDither |
675
QPixmap::DiffuseDither);
678
iw7p = new QPixmap();
679
iw7p->convertFromImage(iw7,
680
QPixmap::PreferDither |
681
QPixmap::DiffuseAlphaDither |
682
QPixmap::DiffuseDither);
685
iw8p = new QPixmap();
686
iw8p->convertFromImage(iw8,
687
QPixmap::PreferDither |
688
QPixmap::DiffuseAlphaDither |
689
QPixmap::DiffuseDither);
703
// Create the hotspots as middle of the image
704
QList<QPoint> hotspots;
705
QPoint point(size/2, size/2);
706
hotspots.append(&point);
707
hotspots.append(&point);
708
hotspots.append(&point);
709
hotspots.append(&point);
710
hotspots.append(&point);
711
hotspots.append(&point);
712
hotspots.append(&point);
713
hotspots.append(&point);
714
hotspots.append(&point);
716
// Assemble the data in the QCanvasPixmapArray
717
stonePixmaps = new QCanvasPixmapArray(list, hotspots);
719
// Do the same for the ghosts
739
list.append(new QCanvasPixmap(gb));
740
list.append(new QCanvasPixmap(gw1));
741
list.append(new QCanvasPixmap(gw2));
742
list.append(new QCanvasPixmap(gw3));
743
list.append(new QCanvasPixmap(gw4));
744
list.append(new QCanvasPixmap(gw5));
745
list.append(new QCanvasPixmap(gw6));
746
list.append(new QCanvasPixmap(gw7));
747
list.append(new QCanvasPixmap(gw8));
748
ghostPixmaps = new QCanvasPixmapArray(list, hotspots);
751
void ImageHandler::rescale(int size, bool smallerStones)
753
CHECK_PTR(stonePixmaps);
754
CHECK_PTR(ghostPixmaps);
758
// get antialiasing color
759
switch (setting->readIntEntry("SKIN"))
762
antialiasingColor = ac1;
765
antialiasingColor = ac2;
768
antialiasingColor = ac3;
771
antialiasingColor = ac4;
774
antialiasingColor = ac5;
782
bool noShadow = !setting->readBoolEntry("STONES_SHADOW");
783
bool stripes = setting->readBoolEntry("STONES_SHELLS");
784
QImage ib = QImage(size, size, 32);
785
ib.setAlphaBuffer(TRUE);
786
paintBlackStone(ib, size);
788
QImage iw1 = QImage(size, size, 32);
789
iw1.setAlphaBuffer(TRUE);
790
paintWhiteStone(iw1, size, noShadow, stripes);
792
QImage iw2, iw3, iw4, iw5, iw6, iw7, iw8;
796
iw2 = QImage(size, size, 32);
797
iw2.setAlphaBuffer(TRUE);
798
paintWhiteStone(iw2, size, noShadow, stripes);
800
iw3 = QImage(size, size, 32);
801
iw3.setAlphaBuffer(TRUE);
802
paintWhiteStone(iw3, size, noShadow, stripes);
804
iw4 = QImage(size, size, 32);
805
iw4.setAlphaBuffer(TRUE);
806
paintWhiteStone(iw4, size, noShadow, stripes);
808
iw5 = QImage(size, size, 32);
809
iw5.setAlphaBuffer(TRUE);
810
paintWhiteStone(iw5, size, noShadow, stripes);
812
iw6 = QImage(size, size, 32);
813
iw6.setAlphaBuffer(TRUE);
814
paintWhiteStone(iw6, size, noShadow, stripes);
816
iw7 = QImage(size, size, 32);
817
iw7.setAlphaBuffer(TRUE);
818
paintWhiteStone(iw7, size, noShadow, stripes);
820
iw8 = QImage(size, size, 32);
821
iw8.setAlphaBuffer(TRUE);
822
paintWhiteStone(iw8, size, noShadow, stripes);
835
// Replace the images in the array
837
stonePixmaps->setImage(0, new QCanvasPixmap(ib));
838
stonePixmaps->image(0)->setOffset(size/2, size/2);
839
stonePixmaps->setImage(1, new QCanvasPixmap(iw1));
840
stonePixmaps->image(1)->setOffset(size/2, size/2);
841
stonePixmaps->setImage(2, new QCanvasPixmap(iw2));
842
stonePixmaps->image(2)->setOffset(size/2, size/2);
843
stonePixmaps->setImage(3, new QCanvasPixmap(iw3));
844
stonePixmaps->image(3)->setOffset(size/2, size/2);
845
stonePixmaps->setImage(4, new QCanvasPixmap(iw4));
846
stonePixmaps->image(4)->setOffset(size/2, size/2);
847
stonePixmaps->setImage(5, new QCanvasPixmap(iw5));
848
stonePixmaps->image(5)->setOffset(size/2, size/2);
849
stonePixmaps->setImage(6, new QCanvasPixmap(iw6));
850
stonePixmaps->image(6)->setOffset(size/2, size/2);
851
stonePixmaps->setImage(7, new QCanvasPixmap(iw7));
852
stonePixmaps->image(7)->setOffset(size/2, size/2);
853
stonePixmaps->setImage(8, new QCanvasPixmap(iw8));
854
stonePixmaps->image(8)->setOffset(size/2, size/2);
856
// Do the same for the ghosts
875
ghostPixmaps->setImage(0, new QCanvasPixmap(gb));
876
ghostPixmaps->image(0)->setOffset(size/2, size/2);
877
ghostPixmaps->setImage(1, new QCanvasPixmap(gw1));
878
ghostPixmaps->image(1)->setOffset(size/2, size/2);
879
ghostPixmaps->setImage(2, new QCanvasPixmap(gw2));
880
ghostPixmaps->image(2)->setOffset(size/2, size/2);
881
ghostPixmaps->setImage(3, new QCanvasPixmap(gw3));
882
ghostPixmaps->image(3)->setOffset(size/2, size/2);
883
ghostPixmaps->setImage(4, new QCanvasPixmap(gw4));
884
ghostPixmaps->image(4)->setOffset(size/2, size/2);
885
ghostPixmaps->setImage(5, new QCanvasPixmap(gw5));
886
ghostPixmaps->image(5)->setOffset(size/2, size/2);
887
ghostPixmaps->setImage(6, new QCanvasPixmap(gw6));
888
ghostPixmaps->image(6)->setOffset(size/2, size/2);
889
ghostPixmaps->setImage(7, new QCanvasPixmap(gw7));
890
ghostPixmaps->image(7)->setOffset(size/2, size/2);
891
ghostPixmaps->setImage(8, new QCanvasPixmap(gw8));
892
ghostPixmaps->image(8)->setOffset(size/2, size/2);
895
void ImageHandler::ghostImage(QImage *img)
897
img->setAlphaBuffer(true);
898
img->convertDepth(32);
900
int w = img->width(),
906
uint *line = (uint*)img->scanLine(y);
909
if ((x%2 && !(y%2)) || (!(x%2) && y%2))
911
line[x] = qRgba(qRed(line[x]), qGreen(line[x]), qBlue(line[x]), 0);