24#include <klocalizedstring.h>
41 QImage img(width, height, QImage::Format_RGB32);
44 for (
int y = 0; y < height; y++) {
45 QRgb *pixel =
reinterpret_cast<QRgb *
>(img.scanLine(y));
46 for (
int x = 0; x < width; x++, pos++) {
47 value = 255 - buffer[pos];
56static qint32
rle_decode(QDataStream & abr,
char *buffer, qint32 height)
66 cscanline_len =
new short[ height ];
67 for (i = 0; i < height; i++) {
69 abr >> cscanline_len[i];
73 for (i = 0; i < height; i++) {
74 for (j = 0; j < cscanline_len[i];) {
76 if (!abr.device()->getChar(&ptmp)) {
89 if (!abr.device()->getChar(&ch)) {
94 for (c = 0; c < n; c++, data++) {
100 for (c = 0; c < n + 1; c++, j++, data++) {
102 if (!abr.device()->getChar(data)) {
109 delete [] cscanline_len;
116 QString result = filename;
117 int pos = filename.lastIndexOf(
'.');
118 result.remove(pos, 4);
119 QTextStream(&result) <<
"_" << id;
142 qint32 section_size = 0;
146 while (!abr.atEnd()) {
147 r = abr.readRawData(tag, 4);
150 warnKrita <<
"Error: Cannot read 8BIM tag ";
154 if (strncmp(tag,
"8BIM", 4)) {
155 warnKrita <<
"Error: Start tag not 8BIM but " << (int)tag[0] << (
int)tag[1] << (int)tag[2] << (
int)tag[3] <<
" at position " << abr.device()->pos();
159 r = abr.readRawData(tagname, 4);
162 warnKrita <<
"Error: Cannot read 8BIM tag name";
167 QString
s1 = QString::fromLatin1(tagname, 4);
169 if (!
s1.compare(name)) {
175 abr.device()->seek(abr.device()->pos() + section_size);
183 qint32 sample_section_size;
184 qint32 sample_section_end;
194 origin = abr.device()->pos();
198 abr.device()->seek(origin);
203 abr >> sample_section_size;
204 sample_section_end = sample_section_size + abr.device()->pos();
206 if(sample_section_end < 0 || sample_section_end > abr.device()->size())
209 data_start = abr.device()->pos();
211 while ((!abr.atEnd()) && (abr.device()->pos() < sample_section_end)) {
214 brush_end = brush_size;
216 while (brush_end % 4 != 0) brush_end++;
218 qint64 newPos = abr.device()->pos() + brush_end;
219 if(newPos > 0 && newPos < abr.device()->size()) {
220 abr.device()->seek(newPos);
229 abr.device()->seek(data_start);
247 abr >> abr_hdr->
count;
276 if (name_size == 0) {
281 buf_size = name_size;
286 ushort * name_ucs2 =
new ushort[buf_size];
287 for (i = 0; i < buf_size ; i++) {
294 QString name_utf8 = QString::fromUtf16(name_ucs2, buf_size);
304 qint32 brush_size = 0;
305 qint32 brush_end = 0;
306 qint32 next_brush = 0;
308 qint32 top, left, bottom, right;
309 top = left = bottom = right = 0;
317 qint32 layer_ID = -1;
322 brush_end = brush_size;
324 while (brush_end % 4 != 0) {
328 next_brush = abr.device()->pos() + brush_end;
331 abr.device()->seek(abr.device()->pos() + 37);
334 abr.device()->seek(abr.device()->pos() + 10);
337 abr.device()->seek(abr.device()->pos() + 264);
347 abr.device()->getChar(&compression);
349 width = right - left;
350 height = bottom - top;
351 size = width * (depth >> 3) * height;
356 buffer = (
char*)malloc(size);
362 abr.readRawData(buffer, size);
378 buf.open(QFile::ReadWrite);
379 brushTipImage.save(&buf,
"PNG");
383 abrBrush->setBrushTipImage(brushTipImage);
385 abrBrush->setValid(
true);
386 abrBrush->setName(name);
392 abr.device()->seek(next_brush);
406 qint32 top, left, bottom, right;
411 qint32 width, height;
414 qint32 layer_ID = -1;
421 next_brush = abr.device()->pos() + brush_size;
423 if (brush_type == 1) {
426 warnKrita <<
"WARNING: computed brush unsupported, skipping.";
427 abr.device()->seek(abr.device()->pos() + next_brush);
430 else if (brush_type == 2) {
433 abr.device()->seek(abr.device()->pos() + 6);
442 abr.device()->seek(abr.device()->pos() + 9);
452 abr.device()->getChar(&compression);
454 width = right - left;
455 height = bottom - top;
456 size = width * (depth >> 3) * height;
459 if (height > 16384) {
460 warnKrita <<
"WARNING: wide brushes not supported";
461 abr.device()->seek(next_brush);
464 buffer = (
char*)malloc(size);
468 abr.readRawData(buffer, size);
481 buf.open(QFile::ReadWrite);
482 brushTipImage.save(&buf,
"PNG");
486 abrBrush->setBrushTipImage(brushTipImage);
488 abrBrush->setValid(
true);
489 abrBrush->setName(name);
495 warnKrita <<
"Unknown ABR brush type, skipping.";
496 abr.device()->seek(next_brush);
505 qint32 layer_ID = -1;
525 , m_filename(filename)
531 : m_isLoaded(rhs.m_isLoaded)
532 , m_lastModified(rhs.m_lastModified)
547 QFileInfo info(file);
550 if (!file.open(QIODevice::ReadOnly)) {
569 QByteArray ba = dev->readAll();
571 buf.open(QIODevice::ReadOnly);
572 QDataStream abr(&buf);
585 if (abr_hdr.
count == 0) {
592 for (i = 0; i < abr_hdr.
count; i++) {
594 if (layer_ID == -1) {
635 return QString(
".abr");
float value(const T *src, size_t ch)
QString defaultFileExtension() const
bool saveToDevice(QIODevice *dev) const
quint32 abr_brush_load_v6(QDataStream &abr, AbrInfo *abr_hdr, const QString filename, qint32 image_ID, qint32 id)
qint32 abr_brush_load_v12(QDataStream &abr, AbrInfo *abr_hdr, const QString filename, qint32 image_ID, qint32 id)
bool loadFromDevice(QIODevice *dev)
KisAbrBrushCollection(const QString &filename)
Construct brush to load filename later as brush.
QSharedPointer< QMap< QString, KisAbrBrushSP > > m_abrBrushes
qint32 abr_brush_load(QDataStream &abr, AbrInfo *abr_hdr, const QString filename, qint32 image_ID, qint32 id)
void toXML(QDomDocument &d, QDomElement &e) const
static QString generateHash(const QString &filename)
generateHash reads the given file and generates a hex-encoded md5sum for the file.
QSharedPointer< KisAbrBrush > KisAbrBrushSP
static bool abr_reach_8BIM_section(QDataStream &abr, const QString name)
static QString abr_v1_brush_name(const QString filename, qint32 id)
static qint32 find_sample_count_v6(QDataStream &abr, AbrInfo *abr_info)
static bool abr_read_content(QDataStream &abr, AbrInfo *abr_hdr)
static bool abr_supported_content(AbrInfo *abr_hdr)
static QString abr_read_ucs2_text(QDataStream &abr)
static QImage convertToQImage(char *buffer, qint32 width, qint32 height)
save the QImages as png files to directory image_tests
static qint32 rle_decode(QDataStream &abr, char *buffer, qint32 height)
const quint16 quint16_MAX