209 lines
6.5 KiB
C++
209 lines
6.5 KiB
C++
/***************************************************************************
|
|
* Copyright (C) 2012 Stefan Bühler <stbuehler@web.de> *
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
* This program is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
* GNU General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU General Public License *
|
|
* along with this program; if not, write to the *
|
|
* Free Software Foundation, Inc., *
|
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
|
***************************************************************************/
|
|
#include "nonogramimage.h"
|
|
|
|
#include <QDataStream>
|
|
|
|
namespace libqnono {
|
|
static const quint64 NonogramImage_DataStream_MAGIC = Q_UINT64_C(0xe47028650d925b33);
|
|
|
|
class NonogramImageViewRowColumn : public NonogramImageView {
|
|
public:
|
|
NonogramImageViewRowColumn(NonogramImage & img) : m_img(img) { }
|
|
|
|
virtual bool pixel(int row, int col) const {
|
|
return m_img.pixel(col, row);
|
|
}
|
|
virtual bool & pixel(int row, int col) {
|
|
return m_img.pixel(col, row);
|
|
}
|
|
private:
|
|
NonogramImage &m_img;
|
|
};
|
|
|
|
class NonogramImageViewColumnRow : public NonogramImageView {
|
|
public:
|
|
NonogramImageViewColumnRow(NonogramImage & img) : m_img(img) { }
|
|
|
|
virtual bool pixel(int col, int row) const {
|
|
return m_img.pixel(col, row);
|
|
}
|
|
virtual bool & pixel(int col, int row) {
|
|
return m_img.pixel(col, row);
|
|
}
|
|
private:
|
|
NonogramImage &m_img;
|
|
};
|
|
|
|
NonogramImage::NonogramImage() : m_size(0,0), m_data(0), m_blackPixels(0) {
|
|
}
|
|
|
|
NonogramImage::NonogramImage(QSize size)
|
|
: m_size(size), m_blackPixels(0) {
|
|
int n = m_size.width() * m_size.height();
|
|
m_data = new bool[n];
|
|
for (int i = 0; i < n; ++i) m_data[i] = 0;
|
|
}
|
|
|
|
NonogramImage::NonogramImage(const NonogramImage& other)
|
|
: m_size(other.size()), m_data(0), m_blackPixels(other.m_blackPixels) {
|
|
int n = m_size.width() * m_size.height();
|
|
m_data = new bool[n];
|
|
for (int i = 0; i < n; ++i) m_data[i] = other.m_data[i];
|
|
}
|
|
|
|
NonogramImage::NonogramImage(const QImage & image)
|
|
: m_size(image.size()), m_data(0), m_blackPixels(0) {
|
|
int rows = image.height(), cols = image.width();
|
|
m_data = new bool[rows*cols];
|
|
for (int i = 0, y = 0; y < rows; ++y) {
|
|
for (int x = 0; x < cols; ++x, ++i) {
|
|
m_data[i] = (0 == (image.pixel(x, y) & 0x00FFFFFF));
|
|
if (m_data[i]) ++m_blackPixels;
|
|
}
|
|
}
|
|
}
|
|
|
|
NonogramImage::~NonogramImage() {
|
|
delete [] m_data; m_data = 0;
|
|
}
|
|
|
|
NonogramImage& NonogramImage::operator=(const NonogramImage& other) {
|
|
delete [] m_data; m_data = 0;
|
|
|
|
m_size = other.m_size;
|
|
m_blackPixels = other.m_blackPixels;
|
|
int n = m_size.width() * m_size.height();
|
|
m_data = new bool[n];
|
|
for (int i = 0; i < n; ++i) m_data[i] = other.m_data[i];
|
|
|
|
return *this;
|
|
}
|
|
|
|
bool NonogramImage::operator==(const NonogramImage& other) const {
|
|
if (m_size != other.m_size || m_blackPixels != other.m_blackPixels) return false;
|
|
int n = m_size.width() * m_size.height();
|
|
for (int i = 0; i < n; ++i) if (m_data[i] != other.m_data[i]) return false;
|
|
return true;
|
|
}
|
|
|
|
void NonogramImage::fill(bool value) {
|
|
int n = m_size.width() * m_size.height();
|
|
for (int i = 0; i < n; ++i) m_data[i] = value;
|
|
m_blackPixels = value ? n : 0;
|
|
}
|
|
|
|
void NonogramImage::resize(QSize size) {
|
|
int n = size.width() * size.height();
|
|
bool *data = new bool[n];
|
|
int oldwidth = m_size.width(), newwidth = size.width(), w = qMin(oldwidth, newwidth), h = qMin(size.height(), m_size.height());
|
|
int y, x;
|
|
m_blackPixels = 0;
|
|
for (y = 0; y < h; ++y) {
|
|
for (x = 0; x < w; ++x) {
|
|
data[y*newwidth+x] = m_data[y*oldwidth+x];
|
|
if (data[y*newwidth+x]) ++m_blackPixels;
|
|
}
|
|
for (; x < newwidth; ++x) {
|
|
data[y*newwidth+x] = 0;
|
|
}
|
|
}
|
|
for (int i = y*newwidth; i < n; ++i) {
|
|
data[i] = 0;
|
|
}
|
|
|
|
delete [] m_data;
|
|
m_data = data;
|
|
m_size = size;
|
|
}
|
|
|
|
NonogramImageView* NonogramImage::viewRowColumn() {
|
|
return new NonogramImageViewRowColumn(*this);
|
|
}
|
|
|
|
NonogramImageView* NonogramImage::viewColumnRow() {
|
|
return new NonogramImageViewColumnRow(*this);
|
|
}
|
|
|
|
bool NonogramImage::readFromStream(QDataStream & stream) {
|
|
quint64 magic;
|
|
stream >> magic;
|
|
if (NonogramImage_DataStream_MAGIC != magic || QDataStream::Ok != stream.status()) {
|
|
if (QDataStream::ReadPastEnd != stream.status()) stream.setStatus(QDataStream::ReadCorruptData);
|
|
return false;
|
|
}
|
|
|
|
QSize size;
|
|
stream >> size;
|
|
if (QDataStream::Ok != stream.status()) return false;
|
|
|
|
int n = size.width() * size.height();
|
|
|
|
int bitcount = (n+7)/8;
|
|
char *bits = new char[bitcount];
|
|
if (bitcount != stream.readRawData(bits, bitcount) || QDataStream::Ok != stream.status()) {
|
|
delete[] bits;
|
|
if (QDataStream::ReadCorruptData != stream.status()) stream.setStatus(QDataStream::ReadPastEnd);
|
|
return false;
|
|
}
|
|
|
|
int blackPixels = 0;
|
|
delete[] m_data;
|
|
m_data = new bool[n];
|
|
for (int i = 0, k = 0; k < bitcount; ++k) {
|
|
unsigned char byte = bits[k];
|
|
for (int l = 0 ; l < 8 && i < n; ++l, ++i, byte >>= 1) {
|
|
m_data[i] = (byte & 0x1);
|
|
if (m_data[i]) ++blackPixels;
|
|
}
|
|
}
|
|
delete[] bits;
|
|
|
|
m_size = size;
|
|
m_blackPixels = blackPixels;
|
|
|
|
return true;
|
|
}
|
|
|
|
void NonogramImage::writeToStream(QDataStream & stream) const {
|
|
stream << NonogramImage_DataStream_MAGIC << m_size;
|
|
int n = m_size.width() * m_size.height();
|
|
int bitcount = (n+7)/8;
|
|
char *bits = new char[bitcount];
|
|
for (int i = 0, k = 0; k < bitcount; ++k) {
|
|
unsigned char byte = 0, mask = 1;
|
|
for (int l = 0 ; l < 8 && i < n; ++l, ++i, mask <<= 1) {
|
|
if (m_data[i]) byte |= mask;
|
|
}
|
|
bits[k] = byte;
|
|
}
|
|
stream.writeRawData(bits, bitcount);
|
|
}
|
|
|
|
QDataStream & operator<<(QDataStream & stream, const NonogramImage & image) {
|
|
image.writeToStream(stream);
|
|
return stream;
|
|
}
|
|
|
|
QDataStream & operator>>(QDataStream & stream, NonogramImage & image) {
|
|
image.readFromStream(stream);
|
|
return stream;
|
|
}
|
|
}
|