00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "kis_pattern.h"
00023
00024 #include <sys/types.h>
00025 #include <netinet/in.h>
00026
00027 #include <limits.h>
00028 #include <stdlib.h>
00029
00030 #include <qpoint.h>
00031 #include <qsize.h>
00032 #include <qimage.h>
00033 #include <qvaluevector.h>
00034 #include <qmap.h>
00035 #include <qfile.h>
00036
00037 #include <kdebug.h>
00038 #include <klocale.h>
00039
00040 #include "kis_color.h"
00041 #include "kis_layer.h"
00042 #include "kis_paint_device.h"
00043
00044 namespace {
00045 struct GimpPatternHeader {
00046 Q_UINT32 header_size;
00047 Q_UINT32 version;
00048 Q_UINT32 width;
00049 Q_UINT32 height;
00050 Q_UINT32 bytes;
00051 Q_UINT32 magic_number;
00052 };
00053
00054
00055 Q_UINT32 const GimpPatternMagic = (('G' << 24) + ('P' << 16) + ('A' << 8) + ('T' << 0));
00056 }
00057
00058 KisPattern::KisPattern(const QString& file) : super(file), m_hasFile(true)
00059 {
00060 }
00061
00062 KisPattern::KisPattern(KisPaintDevice* image, int x, int y, int w, int h)
00063 : super(""), m_hasFile(false)
00064 {
00065
00066
00067 setImage(image->convertToQImage(0, x, y, w, h));
00068 setName(image->name());
00069 }
00070
00071 KisPattern::~KisPattern()
00072 {
00073 }
00074
00075 bool KisPattern::load()
00076 {
00077 if (!m_hasFile)
00078 return true;
00079
00080 QFile file(filename());
00081 file.open(IO_ReadOnly);
00082 QByteArray data = file.readAll();
00083 if (!data.isEmpty()) {
00084 Q_INT32 startPos = m_data.size();
00085
00086 m_data.resize(m_data.size() + data.count());
00087 memcpy(&m_data[startPos], data.data(), data.count());
00088 }
00089 file.close();
00090 return init();
00091 }
00092
00093 bool KisPattern::save()
00094 {
00095 QFile file(filename());
00096 file.open(IO_WriteOnly | IO_Truncate);
00097
00098 QTextStream stream(&file);
00099
00100
00101
00102
00103
00104
00105
00106
00107 GimpPatternHeader ph;
00108 QCString utf8Name = name().utf8();
00109 char const* name = utf8Name.data();
00110 int nameLength = qstrlen(name);
00111
00112 ph.header_size = htonl(sizeof(GimpPatternHeader) + nameLength + 1);
00113 ph.version = htonl(1);
00114 ph.width = htonl(width());
00115 ph.height = htonl(height());
00116 ph.bytes = htonl(4);
00117 ph.magic_number = htonl(GimpPatternMagic);
00118
00119 QByteArray bytes;
00120 bytes.setRawData(reinterpret_cast<char*>(&ph), sizeof(GimpPatternHeader));
00121 int wrote = file.writeBlock(bytes);
00122 bytes.resetRawData(reinterpret_cast<char*>(&ph), sizeof(GimpPatternHeader));
00123
00124 if (wrote == -1)
00125 return false;
00126
00127 wrote = file.writeBlock(name, nameLength + 1);
00128 if (wrote == -1)
00129 return false;
00130
00131 int k = 0;
00132 bytes.resize(width() * height() * 4);
00133 for (Q_INT32 y = 0; y < height(); y++) {
00134 for (Q_INT32 x = 0; x < width(); x++) {
00135
00136 QRgb pixel = m_img.pixel(x,y);
00137 bytes[k++] = static_cast<char>(qRed(pixel));
00138 bytes[k++] = static_cast<char>(qGreen(pixel));
00139 bytes[k++] = static_cast<char>(qBlue(pixel));
00140 bytes[k++] = static_cast<char>(qAlpha(pixel));
00141 }
00142 }
00143
00144 wrote = file.writeBlock(bytes);
00145 if (wrote == -1)
00146 return false;
00147
00148 file.close();
00149
00150 return true;
00151 }
00152
00153 QImage KisPattern::img()
00154 {
00155 return m_img;
00156 }
00157
00158 bool KisPattern::init()
00159 {
00160
00161 GimpPatternHeader bh;
00162 Q_INT32 k;
00163 QValueVector<char> name;
00164
00165 if (sizeof(GimpPatternHeader) > m_data.size()) {
00166 return false;
00167 }
00168
00169 memcpy(&bh, &m_data[0], sizeof(GimpPatternHeader));
00170 bh.header_size = ntohl(bh.header_size);
00171 bh.version = ntohl(bh.version);
00172 bh.width = ntohl(bh.width);
00173 bh.height = ntohl(bh.height);
00174 bh.bytes = ntohl(bh.bytes);
00175 bh.magic_number = ntohl(bh.magic_number);
00176
00177 if (bh.header_size > m_data.size() || bh.header_size == 0) {
00178 return false;
00179 }
00180
00181 name.resize(bh.header_size - sizeof(GimpPatternHeader));
00182 memcpy(&name[0], &m_data[sizeof(GimpPatternHeader)], name.size());
00183
00184 if (name[name.size() - 1]) {
00185 return false;
00186 }
00187
00188 setName(i18n(&name[0]));
00189
00190 if (bh.width == 0 || bh.height == 0 || !m_img.create(bh.width, bh.height, 32)) {
00191 return false;
00192 }
00193
00194 k = bh.header_size;
00195
00196 if (bh.bytes == 1) {
00197
00198 Q_INT32 val;
00199
00200 for (Q_UINT32 y = 0; y < bh.height; y++) {
00201 for (Q_UINT32 x = 0; x < bh.width; x++, k++) {
00202 if (static_cast<Q_UINT32>(k) > m_data.size()) {
00203 kdDebug(DBG_AREA_FILE) << "failed in gray\n";
00204 return false;
00205 }
00206
00207 val = m_data[k];
00208 m_img.setPixel(x, y, qRgb(val, val, val));
00209 m_img.setAlphaBuffer(false);
00210 }
00211 }
00212 } else if (bh.bytes == 2) {
00213
00214 Q_INT32 val;
00215 Q_INT32 alpha;
00216 for (Q_UINT32 y = 0; y < bh.height; y++) {
00217 for (Q_UINT32 x = 0; x < bh.width; x++, k++) {
00218 if (static_cast<Q_UINT32>(k + 2) > m_data.size()) {
00219 kdDebug(DBG_AREA_FILE) << "failed in grayA\n";
00220 return false;
00221 }
00222
00223 val = m_data[k];
00224 alpha = m_data[k++];
00225 m_img.setPixel(x, y, qRgba(val, val, val, alpha));
00226 m_img.setAlphaBuffer(true);
00227 }
00228 }
00229 } else if (bh.bytes == 3) {
00230
00231 for (Q_UINT32 y = 0; y < bh.height; y++) {
00232 for (Q_UINT32 x = 0; x < bh.width; x++) {
00233 if (static_cast<Q_UINT32>(k + 3) > m_data.size()) {
00234 kdDebug(DBG_AREA_FILE) << "failed in RGB\n";
00235 return false;
00236 }
00237
00238 m_img.setPixel(x, y, qRgb(m_data[k],
00239 m_data[k + 1],
00240 m_data[k + 2]));
00241 k += 3;
00242 m_img.setAlphaBuffer(false);
00243 }
00244 }
00245 } else if (bh.bytes == 4) {
00246
00247 for (Q_UINT32 y = 0; y < bh.height; y++) {
00248 for (Q_UINT32 x = 0; x < bh.width; x++) {
00249 if (static_cast<Q_UINT32>(k + 4) > m_data.size()) {
00250 kdDebug(DBG_AREA_FILE) << "failed in RGBA\n";
00251 return false;
00252 }
00253
00254 m_img.setPixel(x, y, qRgba(m_data[k],
00255 m_data[k + 1],
00256 m_data[k + 2],
00257 m_data[k + 3]));
00258 k += 4;
00259 m_img.setAlphaBuffer(true);
00260 }
00261 }
00262 } else {
00263 return false;
00264 }
00265
00266 if (m_img.isNull()) {
00267 return false;
00268 }
00269
00270 setWidth(m_img.width());
00271 setHeight(m_img.height());
00272
00273 setValid(true);
00274
00275 return true;
00276 }
00277
00278 KisPaintDeviceSP KisPattern::image(KisColorSpace * colorSpace) {
00279
00280 QMap<QString, KisPaintDeviceSP>::const_iterator it = m_colorspaces.find(colorSpace->id().id());
00281 if (it != m_colorspaces.end())
00282 return (*it);
00283
00284
00285 KisPaintDeviceSP layer = new KisPaintDevice(colorSpace, "pattern");
00286
00287 Q_CHECK_PTR(layer);
00288
00289 layer->convertFromQImage(m_img,"");
00290
00291 m_colorspaces[colorSpace->id().id()] = layer;
00292 return layer;
00293 }
00294
00295 Q_INT32 KisPattern::width() const
00296 {
00297 return m_width;
00298 }
00299
00300 void KisPattern::setWidth(Q_INT32 w)
00301 {
00302 m_width = w;
00303 }
00304
00305 Q_INT32 KisPattern::height() const
00306 {
00307 return m_height;
00308 }
00309
00310 void KisPattern::setHeight(Q_INT32 h)
00311 {
00312 m_height = h;
00313 }
00314
00315 void KisPattern::setImage(const QImage& img)
00316 {
00317 m_hasFile = false;
00318 m_img = img;
00319 m_img.detach();
00320
00321 setWidth(img.width());
00322 setHeight(img.height());
00323
00324 setValid(true);
00325 }
00326
00327 KisPattern* KisPattern::clone() const
00328 {
00329 KisPattern* pattern = new KisPattern("");
00330 pattern->setImage(m_img);
00331 pattern->setName(name());
00332 return pattern;
00333 }
00334
00335 #include "kis_pattern.moc"