File indexing completed on 2021-12-21 12:50:20

0001 /*
0002  *  ksokoban - a Sokoban game by KDE
0003  *  Copyright (C) 1998  Anders Widell  <awl@hem.passagen.se>
0004  *
0005  *  This program is free software; you can redistribute it and/or modify
0006  *  it under the terms of the GNU General Public License as published by
0007  *  the Free Software Foundation; either version 2 of the License, or
0008  *  (at your option) any later version.
0009  *
0010  *  This program is distributed in the hope that it will be useful,
0011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
0012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0013  *  GNU General Public License for more details.
0014  *
0015  *  You should have received a copy of the GNU General Public License
0016  *  along with this program; if not, write to the Free Software
0017  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
0018  */
0019 
0020 #include <assert.h>
0021 #include <QPainter>
0022 #include <QPixmap>
0023 #include <QImage>
0024 #include <QColor>
0025 
0026 #include "ImageData.h"
0027 
0028 ImageData::ImageData() : floor_(10,10), indexSize_(0), size_(0), halfSize_(0) {
0029   random.seed(QRandomGenerator::global()->generate());
0030   QPainter paint(&floor_);
0031   paint.fillRect(0,0,10,10, QColor(0x66,0x66,0x66, 255));
0032 }
0033 
0034 ImageData::~ImageData() {
0035 }
0036 
0037 void
0038 ImageData::expandIndex(int size) {
0039   size++;
0040   assert(size < 2500);
0041 
0042   upperLargeIndex_.resize(size);
0043   lowerLargeIndex_.resize(size);
0044   leftSmallIndex_.resize(size);
0045   rightSmallIndex_.resize(size);
0046 
0047   for (int i=indexSize_; i<size; i++) {
0048     upperLargeIndex_[i] = random.bounded(LARGE_STONES);
0049     lowerLargeIndex_[i] = random.bounded(LARGE_STONES);
0050     leftSmallIndex_[i] = random.bounded(SMALL_STONES);
0051     rightSmallIndex_[i] = random.bounded(SMALL_STONES);
0052   }
0053 
0054   indexSize_ = size;
0055 }
0056 
0057 const QPixmap &
0058 ImageData::upperLarge(int index) {
0059   assert(index >= 0);
0060   if (indexSize_ <= index) expandIndex(index);
0061   return largeStone_xpm_[(unsigned char)upperLargeIndex_[index]];
0062 }
0063 
0064 const QPixmap &
0065 ImageData::lowerLarge(int index) {
0066   assert(index >= 0);
0067   if (indexSize_ <= index) expandIndex(index);
0068   return largeStone_xpm_[(unsigned char)lowerLargeIndex_[index]];
0069 }
0070 
0071 const QPixmap &
0072 ImageData::leftSmall(int index) {
0073   assert(index >= 0);
0074   if (indexSize_ <= index) expandIndex(index);
0075   return smallStone_xpm_[(unsigned char)leftSmallIndex_[index]];
0076 }
0077 
0078 const QPixmap &
0079 ImageData::rightSmall(int index) {
0080   assert(index >= 0);
0081   if (indexSize_ <= index) expandIndex(index);
0082   return smallStone_xpm_[(unsigned char)rightSmallIndex_[index]];
0083 }
0084 
0085 int
0086 ImageData::resize(int size) {
0087   assert(size > 0);
0088   size &= ~1u;
0089   if (size == size_) return size;
0090 
0091   size_ = size;
0092   halfSize_ = size/2;
0093 
0094   for (int i=0; i<SMALL_STONES; i++) {
0095     image2pixmap(images_[i].scaled(halfSize_, halfSize_, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), smallStone_xpm_[i]);
0096 //     smallStone_xpm_[i].convertFromImage(images_[i].smoothScale(halfSize_, halfSize_), QPixmap::ColorOnly|QPixmap::DiffuseDither|QPixmap::DiffuseAlphaDither|QPixmap::AvoidDither);
0097   }
0098 
0099   for (int i=0; i<LARGE_STONES; i++) {
0100     image2pixmap(images_[SMALL_STONES+i].scaled(size_, halfSize_, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), largeStone_xpm_[i]);
0101 //     largeStone_xpm_[i].convertFromImage(images_[SMALL_STONES+i].smoothScale(size_, halfSize_) , QPixmap::ColorOnly|QPixmap::DiffuseDither|QPixmap::DiffuseAlphaDither|QPixmap::AvoidDither);
0102   }
0103 
0104   objectImg_ = images_[SMALL_STONES+LARGE_STONES].scaled(size_, size_, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
0105   
0106   // Use copy() because if the size is not changed, smoothScale is not
0107   // really a copy
0108   // Use {[Geometry] height=753 width=781} to test
0109 
0110   if (objectImg_.width() == size_) objectImg_ = objectImg_.copy();
0111 
0112   image2pixmap(objectImg_, otherPixmaps_[0], false);
0113   brighten(objectImg_);
0114   image2pixmap(objectImg_, brightObject_, false);
0115 
0116   QImage img = images_[SMALL_STONES+LARGE_STONES+1].scaled(size_, size_, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
0117   if (img.width() == size_) img = img.copy();
0118 
0119   image2pixmap(img, otherPixmaps_[1], false);
0120   brighten(img);
0121   image2pixmap(img, brightTreasure_, false);
0122 
0123   for (int i=2; i<OTHER_IMAGES; i++) {
0124     image2pixmap(images_[SMALL_STONES+LARGE_STONES+i].scaled(size_, size_, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), otherPixmaps_[i]);
0125 //     otherPixmaps_[i].convertFromImage(images_[SMALL_STONES+LARGE_STONES+i].smoothScale(size_, size_), QPixmap::ColorOnly|QPixmap::OrderedDither|QPixmap::OrderedAlphaDither|QPixmap::AvoidDither);
0126   }
0127   floor_ = floor_.scaled(size_, size_);
0128   return size_;
0129 }
0130 
0131 // Don't use DiffuseDither for the objects on the "floor" since
0132 // it gives spurious dots on the floor around them
0133 
0134 void
0135 ImageData::image2pixmap(const QImage &img, QPixmap& xpm, bool diffuse) {
0136   xpm = QPixmap::fromImage(img,
0137                (diffuse ?
0138             (Qt::DiffuseDither|Qt::DiffuseAlphaDither) :
0139             (Qt::OrderedDither|Qt::OrderedAlphaDither))|
0140                Qt::ColorOnly|Qt::AvoidDither);
0141 }
0142 
0143 void
0144 ImageData::brighten(QImage& img) {
0145   assert(img.depth() == 32);
0146 
0147   for (int y=0; y<img.height(); y++) {
0148     for (int x=0; x<img.width(); x++) {
0149       QRgb rgb = img.pixel(x, y);
0150       int r = qRed(rgb);
0151       int g = qGreen(rgb);
0152       int b = qBlue(rgb);
0153 
0154       if (r > g && r > b) {
0155        // only modify redish pixels
0156 
0157        QColor col(r, g, b);
0158        QColor lcol = col.lighter(130);
0159 
0160        img.setPixel(x, y, lcol.rgb());
0161       }
0162     }
0163   }
0164 }
0165 
0166 void
0167 ImageData::wall(QPainter &p, int x, int y, int index, bool left, bool right) {
0168   if (left) p.drawPixmap(x, y, upperLarge(index-1), halfSize_, 0, -1, -1);
0169   else p.drawPixmap(x, y, leftSmall(index));
0170 
0171   if (right) p.drawPixmap(x+halfSize_, y, upperLarge(index), 0, 0, halfSize_, -1);
0172   else p.drawPixmap(x+halfSize_, y, rightSmall(index));
0173 
0174   p.drawPixmap(x, y+halfSize_, lowerLarge(index));
0175 }
0176 
0177 void
0178 ImageData::floor(QPainter &p, int x, int y) {
0179   //p.eraseRect(x, y, size_, size_);
0180   p.drawPixmap(x, y, floor_);
0181 }
0182 
0183 void
0184 ImageData::goal(QPainter &p, int x, int y) {
0185   p.drawPixmap(x, y, otherPixmaps_[2]);
0186 }
0187 
0188 void
0189 ImageData::man(QPainter &p, int x, int y) {
0190   p.drawPixmap(x, y, otherPixmaps_[3]);
0191 }
0192 
0193 void
0194 ImageData::object(QPainter &p, int x, int y) {
0195   p.drawPixmap(x, y, otherPixmaps_[0]);
0196 }
0197 
0198 void
0199 ImageData::saveman(QPainter &p, int x, int y) {
0200   p.drawPixmap(x, y, otherPixmaps_[4]);
0201 }
0202 
0203 void
0204 ImageData::treasure(QPainter &p, int x, int y) {
0205   p.drawPixmap(x, y, otherPixmaps_[1]);
0206 }
0207 
0208 void
0209 ImageData::brightObject(QPainter &p, int x, int y) {
0210   p.drawPixmap(x, y, brightObject_);
0211 }
0212 
0213 void
0214 ImageData::brightTreasure(QPainter &p, int x, int y) {
0215   p.drawPixmap(x, y, brightTreasure_);
0216 }