[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-commits
Subject: [calligra/calligra/2.9] krita/plugins/formats/psd: Make reading of PSD pixel data shared between PSD
From: Dmitry Kazakov <dimula73 () gmail ! com>
Date: 2015-08-13 17:15:19
Message-ID: E1ZPw63-0001eb-JW () scm ! kde ! org
[Download RAW message or body]
Git commit b22044430069ccfa757ff2f461acfd614e8093d8 by Dmitry Kazakov.
Committed on 13/08/2015 at 15:46.
Pushed by dkazakov into branch 'calligra/2.9'.
Make reading of PSD pixel data shared between PSDLayerRecord and PSDImageData
M +28 -477 krita/plugins/formats/psd/psd_image_data.cpp
M +14 -99 krita/plugins/formats/psd/psd_layer_record.cpp
M +0 -3 krita/plugins/formats/psd/psd_layer_record.h
M +329 -0 krita/plugins/formats/psd/psd_pixel_utils.cpp
M +12 -235 krita/plugins/formats/psd/psd_pixel_utils.h
http://commits.kde.org/calligra/b22044430069ccfa757ff2f461acfd614e8093d8
diff --git a/krita/plugins/formats/psd/psd_image_data.cpp \
b/krita/plugins/formats/psd/psd_image_data.cpp index b904535..f609110 100644
--- a/krita/plugins/formats/psd/psd_image_data.cpp
+++ b/krita/plugins/formats/psd/psd_image_data.cpp
@@ -36,6 +36,11 @@
#include "kis_iterator_ng.h"
#include "kis_paint_device.h"
+#include <asl/kis_asl_reader_utils.h>
+
+#include "psd_pixel_utils.h"
+
+
PSDImageData::PSDImageData(PSDHeader *header)
{
m_header = header;
@@ -72,38 +77,10 @@ bool PSDImageData::read(QIODevice *io, KisPaintDeviceSP dev ) {
}
- switch (m_header->colormode) {
- case Bitmap:
- break;
- case Grayscale:
- readGrayscale(io,dev);
- break;
- case Indexed:
- break;
- case RGB:
- readRGB(io, dev);
- break;
- case CMYK:
- readCMYK(io, dev);
- break;
- case MultiChannel:
- break;
- case DuoTone:
- break;
- case Lab:
- readLAB(io, dev);
- break;
- case UNKNOWN:
- break;
- default:
- break;
- }
-
break;
case 1: // RLE
{
-
quint32 rlelength = 0;
// The start of the actual channel data is _after_ the RLE rowlengths block
@@ -136,88 +113,37 @@ bool PSDImageData::read(QIODevice *io, KisPaintDeviceSP dev ) {
m_channelInfoRecords.append(channelInfo);
}
- switch (m_header->colormode) {
- case Bitmap:
- break;
- case Grayscale:
- readGrayscale(io,dev);
- break;
- case Indexed:
- break;
- case RGB:
- readRGB(io, dev);
- break;
- case CMYK:
- readCMYK(io, dev);
- break;
- case MultiChannel:
- break;
- case DuoTone:
- break;
- case Lab:
- readLAB(io, dev);
- break;
- case UNKNOWN:
- break;
- default:
- break;
- }
-
break;
}
case 2: // ZIP without prediction
+ case 3: // ZIP with prediction
+ default:
+ break;
+ }
- switch (m_header->colormode) {
- case Bitmap:
- break;
- case Grayscale:
- break;
- case Indexed:
- break;
- case RGB:
- break;
- case CMYK:
- break;
- case MultiChannel:
- break;
- case DuoTone:
- break;
- case Lab:
- break;
- case UNKNOWN:
- break;
- default:
- break;
+ if (!m_channelInfoRecords.isEmpty()) {
+ QVector<ChannelInfo*> infoRecords;
+
+ QVector<ChannelInfo>::iterator it = m_channelInfoRecords.begin();
+ QVector<ChannelInfo>::iterator end = m_channelInfoRecords.end();
+
+ for (; it != end; ++it) {
+ infoRecords << &(*it);
}
- break;
- case 3: // ZIP with prediction
- switch (m_header->colormode) {
- case Bitmap:
- break;
- case Grayscale:
- break;
- case Indexed:
- break;
- case RGB:
- break;
- case CMYK:
- break;
- case MultiChannel:
- break;
- case DuoTone:
- break;
- case Lab:
- break;
- case UNKNOWN:
- break;
- default:
- break;
+ const QRect imageRect(0, 0, m_header->width, m_header->height);
+
+ try {
+ PsdPixelUtils::readChannels(io, dev,
+ m_header->colormode,
+ m_channelSize,
+ imageRect,
+ infoRecords);
+ } catch (KisAslReaderUtils::ASLParseException &e) {
+ dev->clear();
+ return true;
}
- break;
- default:
- break;
}
return true;
@@ -321,378 +247,3 @@ bool PSDImageData::write(QIODevice *io, KisPaintDeviceSP dev)
return true;
}
-
-bool PSDImageData::readRGB(QIODevice *io, KisPaintDeviceSP dev) {
-
- int channelid = 0;
-
- for (quint32 row = 0; row < m_header->height; row++) {
-
- KisHLineIteratorSP it = dev->createHLineIteratorNG(0, row, m_header->width);
- QVector<QByteArray> channelBytes;
-
- for (int channel = 0; channel < m_header->nChannels; channel++) {
-
- switch (m_compression) {
- case Compression::Uncompressed:
- {
- io->seek(m_channelInfoRecords[channel].channelDataStart + \
m_channelOffsets[0]);
- channelBytes.append(io->read(m_header->width*m_channelSize));
- }
- break;
- case Compression::RLE:
- {
- io->seek(m_channelInfoRecords[channel].channelDataStart + \
m_channelOffsets[channel]);
- int uncompressedLength = m_header->width * m_header->channelDepth / 8;
- QByteArray compressedBytes = \
io->read(m_channelInfoRecords[channel].rleRowLengths[row]);
- QByteArray uncompressedBytes = Compression::uncompress(uncompressedLength, \
compressedBytes, m_channelInfoRecords[channel].compressionType);
- channelBytes.append(uncompressedBytes);
- m_channelOffsets[channel] += \
m_channelInfoRecords[channel].rleRowLengths[row];
-
- }
- break;
- case Compression::ZIP:
- break;
- case Compression::ZIPWithPrediction:
- break;
-
- default:
- break;
- }
-
- }
-
- if (m_channelInfoRecords[channelid].compressionType == 0){
- m_channelOffsets[channelid] += (m_header->width * m_channelSize);
- }
-
- for (quint32 col = 0; col < m_header->width; col++) {
-
- if (m_channelSize == 1) {
-
- quint8 red = channelBytes[0].constData()[col];
- KoBgrU8Traits::setRed(it->rawData(), red);
-
- quint8 green = channelBytes[1].constData()[col];
- KoBgrU8Traits::setGreen(it->rawData(), green);
-
- quint8 blue = channelBytes[2].constData()[col];
- KoBgrU8Traits::setBlue(it->rawData(), blue);
-
- }
- else if (m_channelSize == 2) {
-
- quint16 red = ntohs(reinterpret_cast<const quint16 \
*>(channelBytes[0].constData())[col]);
- KoBgrU16Traits::setRed(it->rawData(), red);
-
- quint16 green = ntohs(reinterpret_cast<const quint16 \
*>(channelBytes[1].constData())[col]);
- KoBgrU16Traits::setGreen(it->rawData(), green);
-
- quint16 blue = ntohs(reinterpret_cast<const quint16 \
*>(channelBytes[2].constData())[col]);
- KoBgrU16Traits::setBlue(it->rawData(), blue);
-
- }
- else if (m_channelSize == 4) {
-
- quint32 red = ntohl(reinterpret_cast<const quint32 \
*>(channelBytes.constData())[col]);
- KoBgrTraits<quint32>::setRed(it->rawData(), red);
-
- quint32 green = ntohl(reinterpret_cast<const quint32 \
*>(channelBytes.constData())[col]);
- KoBgrTraits<quint32>::setGreen(it->rawData(), green);
-
- quint32 blue = ntohl(reinterpret_cast<const quint32 \
*>(channelBytes.constData())[col]);
- KoBgrTraits<quint32>::setBlue(it->rawData(), blue);
-
- }
-
- dev->colorSpace()->setOpacity(it->rawData(), OPACITY_OPAQUE_U8, 1);
- it->nextPixel();
- }
-
- }
-
- return true;
-}
-
-
-bool PSDImageData::readCMYK(QIODevice *io, KisPaintDeviceSP dev) {
-
- int channelid = 0;
-
- for (quint32 row = 0; row < m_header->height; row++) {
-
- KisHLineIteratorSP it = dev->createHLineIteratorNG(0, row, m_header->width);
- QVector<QByteArray> channelBytes;
-
- for (int channel = 0; channel < m_header->nChannels; channel++) {
-
-
- switch (m_compression) {
-
- case Compression::Uncompressed:
-
- {
- io->seek(m_channelInfoRecords[channel].channelDataStart + \
m_channelOffsets[0]);
- channelBytes.append(io->read(m_header->width*m_channelSize));
-
- }
- break;
-
- case Compression::RLE:
- {
- io->seek(m_channelInfoRecords[channel].channelDataStart + \
m_channelOffsets[channel]);
- int uncompressedLength = m_header->width * m_header->channelDepth / 8;
- QByteArray compressedBytes = \
io->read(m_channelInfoRecords[channel].rleRowLengths[row]);
- QByteArray uncompressedBytes = Compression::uncompress(uncompressedLength, \
compressedBytes, m_channelInfoRecords[channel].compressionType);
- channelBytes.append(uncompressedBytes);
- m_channelOffsets[channel] += \
m_channelInfoRecords[channel].rleRowLengths[row];
- }
- break;
-
- case Compression::ZIP:
- break;
-
- case Compression::ZIPWithPrediction:
- break;
-
- default:
- break;
- }
-
- }
-
- if (m_channelInfoRecords[channelid].compressionType == 0){
- m_channelOffsets[channelid] += (m_header->width * m_channelSize);
- }
-
- for (quint32 col = 0; col < m_header->width; col++) {
-
- if (m_channelSize == 1) {
-
- quint8 *pixel = new quint8[5];
- memset(pixel, 0, 5);
- dev->colorSpace()->setOpacity(pixel, OPACITY_OPAQUE_U8, 1);
-
- memset(pixel, 255 - channelBytes[0].constData()[col], 1);
- memset(pixel + 1, 255 - channelBytes[1].constData()[col], 1);
- memset(pixel + 2, 255 - channelBytes[2].constData()[col], 1);
- memset(pixel + 3, 255 - channelBytes[3].constData()[col], 1);
- dbgFile << "C" << pixel[0] << "M" << pixel[1] << "Y" << pixel[2] << "K" << \
pixel[3] << "A" << pixel[4];
- memcpy(it->rawData(), pixel, 5);
-
-
- }
- else if (m_channelSize == 2) {
-
- quint16 C = ntohs(reinterpret_cast<const quint16 \
*>(channelBytes[0].constData())[col]);
- KoCmykTraits<quint16>::setC(it->rawData(),C);
-
- quint16 M = ntohs(reinterpret_cast<const quint16 \
*>(channelBytes[1].constData())[col]);
- KoCmykTraits<quint16>::setM(it->rawData(),M);
-
- quint16 Y = ntohs(reinterpret_cast<const quint16 \
*>(channelBytes[2].constData())[col]);
- KoCmykTraits<quint16>::setY(it->rawData(),Y);
-
- quint16 K = ntohs(reinterpret_cast<const quint16 \
*>(channelBytes[3].constData())[col]);
- KoCmykTraits<quint16>::setK(it->rawData(),K);
-
- }
- else if (m_channelSize == 4) {
-
- quint32 C = ntohl(reinterpret_cast<const quint32 \
*>(channelBytes[0].constData())[col]);
- KoCmykTraits<quint32>::setC(it->rawData(),C);
-
- quint32 M = ntohl(reinterpret_cast<const quint32 \
*>(channelBytes[1].constData())[col]);
- KoCmykTraits<quint32>::setM(it->rawData(),M);
-
- quint32 Y = ntohl(reinterpret_cast<const quint32 \
*>(channelBytes[2].constData())[col]);
- KoCmykTraits<quint32>::setY(it->rawData(),Y);
-
- quint32 K = ntohl(reinterpret_cast<const quint32 \
*>(channelBytes[3].constData())[col]);
- KoCmykTraits<quint32>::setK(it->rawData(),K);
-
- }
-
- dev->colorSpace()->setOpacity(it->rawData(), OPACITY_OPAQUE_U8, 1);
- it->nextPixel();
- }
-
- }
-
- return true;
-
-}
-
-bool PSDImageData::readLAB(QIODevice *io, KisPaintDeviceSP dev) {
-
- int channelid = 0;
-
- for (quint32 row = 0; row < m_header->height; row++) {
-
- KisHLineIteratorSP it = dev->createHLineIteratorNG(0, row, m_header->width);
- QVector<QByteArray> channelBytes;
-
- for (int channel = 0; channel < m_header->nChannels; channel++) {
-
-
- switch (m_compression) {
-
- case Compression::Uncompressed:
-
- {
- io->seek(m_channelInfoRecords[channel].channelDataStart + \
m_channelOffsets[0]);
- channelBytes.append(io->read(m_header->width*m_channelSize));
- }
- break;
-
- case Compression::RLE:
- {
- io->seek(m_channelInfoRecords[channel].channelDataStart + \
m_channelOffsets[channel]);
- int uncompressedLength = m_header->width * m_header->channelDepth / 8;
- QByteArray compressedBytes = \
io->read(m_channelInfoRecords[channel].rleRowLengths[row]);
- QByteArray uncompressedBytes = Compression::uncompress(uncompressedLength, \
compressedBytes, m_channelInfoRecords[channel].compressionType);
- channelBytes.append(uncompressedBytes);
- m_channelOffsets[channel] += \
m_channelInfoRecords[channel].rleRowLengths[row];
-
- }
- break;
-
- case Compression::ZIP:
- break;
-
- case Compression::ZIPWithPrediction:
- break;
-
- default:
- break;
- }
-
- }
-
- if (m_channelInfoRecords[channelid].compressionType == 0){
- m_channelOffsets[channelid] += (m_header->width * m_channelSize);
- }
-
- for (quint32 col = 0; col < m_header->width; col++) {
-
- if (m_channelSize == 1) {
-
- quint8 L = channelBytes[0].constData()[col];
- KoLabTraits<quint8>::setL(it->rawData(), L);
-
- quint8 A = channelBytes[1].constData()[col];
- KoLabTraits<quint8>::setA(it->rawData(), A);
-
- quint8 B = channelBytes[2].constData()[col];
- KoLabTraits<quint8>::setB(it->rawData(), B);
- }
-
- else if (m_channelSize == 2) {
-
- quint16 L = ntohs(reinterpret_cast<const quint16 \
*>(channelBytes[0].constData())[col]);
- KoLabU16Traits::setL(it->rawData(),L);
-
- quint16 A = ntohs(reinterpret_cast<const quint16 \
*>(channelBytes[1].constData())[col]);
- KoLabU16Traits::setA(it->rawData(),A);
-
- quint16 B = ntohs(reinterpret_cast<const quint16 \
*>(channelBytes[2].constData())[col]);
- KoLabU16Traits::setB(it->rawData(),B);
-
- }
-
- else if (m_channelSize == 4) {
-
- quint32 L = ntohl(reinterpret_cast<const quint32 \
*>(channelBytes[0].constData())[col]);
- KoLabTraits<quint32>::setL(it->rawData(),L);
-
- quint32 A = ntohl(reinterpret_cast<const quint32 \
*>(channelBytes[1].constData())[col]);
- KoLabTraits<quint32>::setA(it->rawData(),A);
-
- quint32 B = ntohl(reinterpret_cast<const quint32 \
*>(channelBytes[2].constData())[col]);
- KoLabTraits<quint32>::setB(it->rawData(),B);
-
- }
-
- dev->colorSpace()->setOpacity(it->rawData(), OPACITY_OPAQUE_U8, 1);
- it->nextPixel();
- }
-
- }
-
- return true;
-}
-
-bool PSDImageData::readGrayscale(QIODevice *io, KisPaintDeviceSP dev) {
- int channelid = 0;
-
- for (quint32 row = 0; row < m_header->height; row++) {
-
- KisHLineIteratorSP it = dev->createHLineIteratorNG(0, row, m_header->width);
- QVector<QByteArray> channelBytes;
-
- for (int channel = 0; channel < m_header->nChannels; channel++) {
-
- switch (m_compression) {
- case Compression::Uncompressed:
- {
- io->seek(m_channelInfoRecords[channel].channelDataStart + \
m_channelOffsets[0]);
- channelBytes.append(io->read(m_header->width*m_channelSize));
- }
- break;
- case Compression::RLE:
- {
- io->seek(m_channelInfoRecords[channel].channelDataStart + \
m_channelOffsets[channel]);
- int uncompressedLength = m_header->width * m_header->channelDepth / 8;
- QByteArray compressedBytes = \
io->read(m_channelInfoRecords[channel].rleRowLengths[row]);
- QByteArray uncompressedBytes = Compression::uncompress(uncompressedLength, \
compressedBytes, m_channelInfoRecords[channel].compressionType);
- channelBytes.append(uncompressedBytes);
- m_channelOffsets[channel] += \
m_channelInfoRecords[channel].rleRowLengths[row];
-
- }
- break;
- case Compression::ZIP:
- break;
- case Compression::ZIPWithPrediction:
- break;
-
- default:
- break;
- }
-
- }
-
- if (m_channelInfoRecords[channelid].compressionType == 0) {
- m_channelOffsets[channelid] += (m_header->width * m_channelSize);
- }
-
- for (quint32 col = 0; col < m_header->width; col++) {
-
- if (m_channelSize == 1) {
-
- quint8 Gray = channelBytes[0].constData()[col];
- KoGrayU8Traits::setGray(it->rawData(), Gray);
-
- }
-
- else if (m_channelSize == 2) {
-
- quint16 Gray = ntohs(reinterpret_cast<const quint16 \
*>(channelBytes[0].constData())[col]);
- KoGrayU16Traits::setGray(it->rawData(), Gray);
-
- }
-
- else if (m_channelSize == 4) {
-
- quint32 Gray = ntohl(reinterpret_cast<const quint32 \
*>(channelBytes[0].constData())[col]);
- KoGrayTraits<quint32>::setGray(it->rawData(), Gray);
-
- }
-
- dev->colorSpace()->setOpacity(it->rawData(), OPACITY_OPAQUE_U8, 1);
- it->nextPixel();
- }
-
- }
-
- return true;
-}
diff --git a/krita/plugins/formats/psd/psd_layer_record.cpp \
b/krita/plugins/formats/psd/psd_layer_record.cpp index 16fc808..b7b391c 100644
--- a/krita/plugins/formats/psd/psd_layer_record.cpp
+++ b/krita/plugins/formats/psd/psd_layer_record.cpp
@@ -39,11 +39,11 @@
#include <asl/kis_offset_keeper.h>
#include <asl/kis_asl_writer_utils.h>
+#include <asl/kis_asl_reader_utils.h>
#include "psd_pixel_utils.h"
-
// Just for pretty debug messages
QString channelIdToChannelType(int channelId, psd_color_mode colormode)
{
@@ -747,33 +747,22 @@ bool PSDLayerRecord::valid()
bool PSDLayerRecord::readPixelData(QIODevice *io, KisPaintDeviceSP device)
{
dbgFile << "Reading pixel data for layer" << layerName << "pos" << io->pos();
- switch (m_header.colormode) {
- case Bitmap:
- error = "Unsupported color mode: bitmap";
- return false; // Not supported;
- case Indexed:
- error = "Unsupported color mode: indexed";
- return false; // Not supported;
- case MultiChannel:
- error = "Unsupported color mode: indexed";
- return false; // Not supported
- case DuoTone:
- error = "Unsupported color mode: Duotone";
- return false; // Not supported
- case Grayscale:
- return readCommon(device, io, &PsdPixelUtils::readGrayPixelCommon);
- case RGB:
- return readCommon(device, io, &PsdPixelUtils::readRgbPixelCommon);
- case CMYK:
- return readCommon(device, io, &PsdPixelUtils::readCmykPixelCommon);
- case Lab:
- return readCommon(device, io, &PsdPixelUtils::readLabPixelCommon);
- case UNKNOWN:
- default:
+
+ const int channelSize = m_header.channelDepth / 8;
+ const QRect layerRect = QRect(left,
+ top,
+ right - left,
+ bottom - top);
+
+ try {
+ PsdPixelUtils::readChannels(io, device, m_header.colormode, channelSize, layerRect, \
channelInfoRecords); + } catch (KisAslReaderUtils::ASLParseException &e) {
+ device->clear();
+ error = e.what();
return false;
}
- return false;
+ return true;
}
QRect PSDLayerRecord::channelRect(ChannelInfo *channel) const
@@ -858,80 +847,6 @@ bool PSDLayerRecord::readMask(QIODevice *io, KisPaintDeviceSP dev, \
ChannelInfo * return true;
}
-#include <asl/kis_asl_reader_utils.h>
-
-QMap<quint16, QByteArray> fetchChannelsBytes(QIODevice *io, QVector<ChannelInfo*> \
channelInfoRecords,
- int row, int width, int channelSize)
-{
- const int uncompressedLength = width * channelSize;
-
- QMap<quint16, QByteArray> channelBytes;
-
- foreach(ChannelInfo *channelInfo, channelInfoRecords) {
- // user supplied masks are ignored here
- if (channelInfo->channelId < -1) continue;
-
- io->seek(channelInfo->channelDataStart + channelInfo->channelOffset);
-
- if (channelInfo->compressionType == Compression::Uncompressed) {
- channelBytes[channelInfo->channelId] = io->read(uncompressedLength);
- channelInfo->channelOffset += uncompressedLength;
- }
- else if (channelInfo->compressionType == Compression::RLE) {
- int rleLength = channelInfo->rleRowLengths[row];
- QByteArray compressedBytes = io->read(rleLength);
- QByteArray uncompressedBytes = Compression::uncompress(uncompressedLength, \
compressedBytes, channelInfo->compressionType);
- channelBytes.insert(channelInfo->channelId, uncompressedBytes);
- channelInfo->channelOffset += rleLength;
- }
- else {
- QString error = QString("Unsupported Compression mode: \
%1").arg(channelInfo->compressionType);
- dbgFile << "ERROR: fetchChannelsBytes:" << error;
- throw KisAslReaderUtils::ASLParseException(error);
- }
- }
-
- return channelBytes;
-}
-
-bool PSDLayerRecord::readCommon(KisPaintDeviceSP dev, QIODevice *io, PixelFunc pixelFunc)
-{
- KisOffsetKeeper keeper(io);
-
- qint64 width = right - left;
-
- if (width <= 0) {
- dbgFile << "Empty layer";
- return true;
- }
-
- const int channelSize = m_header.channelDepth / 8;
-
- KisHLineIteratorSP it = dev->createHLineIteratorNG(left, top, width);
- for (int row = top ; row < bottom; row++)
- {
-
- QMap<quint16, QByteArray> channelBytes;
-
- try {
- channelBytes = fetchChannelsBytes(io, channelInfoRecords,
- row - top, width, channelSize);
- } catch (KisAslReaderUtils::ASLParseException &e) {
- dev->clear();
- error = e.what();
- return false;
- }
-
- for (qint64 col = 0; col < width; col++){
- pixelFunc(channelSize, channelBytes, col, it->rawData());
- it->nextPixel();
- }
- it->nextRow();
- }
-
- return true;
-}
-
QDebug operator<<(QDebug dbg, const PSDLayerRecord &layer)
{
#ifndef NODEBUG
diff --git a/krita/plugins/formats/psd/psd_layer_record.h \
b/krita/plugins/formats/psd/psd_layer_record.h index 655545b..a58a3e83 100644
--- a/krita/plugins/formats/psd/psd_layer_record.h
+++ b/krita/plugins/formats/psd/psd_layer_record.h
@@ -160,9 +160,6 @@ private:
private:
- typedef boost::function<void(int, const QMap<quint16, QByteArray>&, int, quint8*)> \
PixelFunc;
- bool readCommon(KisPaintDeviceSP dev, QIODevice *io, PixelFunc pixelFunc);
-
bool readRGB(KisPaintDeviceSP dev ,QIODevice *io);
bool readCMYK(KisPaintDeviceSP dev ,QIODevice *io);
bool readLAB(KisPaintDeviceSP dev ,QIODevice *io);
diff --git a/krita/plugins/formats/psd/psd_pixel_utils.cpp \
b/krita/plugins/formats/psd/psd_pixel_utils.cpp index bfe6303..50be4b9 100644
--- a/krita/plugins/formats/psd/psd_pixel_utils.cpp
+++ b/krita/plugins/formats/psd/psd_pixel_utils.cpp
@@ -18,6 +18,335 @@
#include "psd_pixel_utils.h"
+#include <QtGlobal>
+#include <QMap>
+#include <QIODevice>
+
+
+#include <KoColorSpace.h>
+#include <KoColorSpaceMaths.h>
+#include <KoColorSpaceTraits.h>
+#include <KoCmykColorSpaceTraits.h>
+
+#include <netinet/in.h> // htonl
+
+#include <asl/kis_asl_reader_utils.h>
+
+#include "psd_layer_record.h"
+#include <asl/kis_offset_keeper.h>
+#include "kis_iterator_ng.h"
+
+
namespace PsdPixelUtils {
+template <class Traits>
+typename Traits::channels_type convertByteOrder(typename Traits::channels_type value);
+// default implementation is undefined for every color space should be added manually
+
+template <>
+inline quint8 convertByteOrder<KoGrayU8Traits>(quint8 value) {
+ return value;
+}
+
+template <>
+inline quint16 convertByteOrder<KoGrayU16Traits>(quint16 value) {
+ return ntohs(value);
+}
+
+template <>
+inline quint32 convertByteOrder<KoGrayU32Traits>(quint32 value) {
+ return ntohs(value);
+}
+
+template <>
+inline quint8 convertByteOrder<KoBgrU8Traits>(quint8 value) {
+ return value;
+}
+
+template <>
+inline quint16 convertByteOrder<KoBgrU16Traits>(quint16 value) {
+ return ntohs(value);
+}
+
+template <>
+inline quint32 convertByteOrder<KoBgrU32Traits>(quint32 value) {
+ return ntohs(value);
+}
+
+template <>
+inline quint8 convertByteOrder<KoCmykU8Traits>(quint8 value) {
+ return value;
+}
+
+template <>
+inline quint16 convertByteOrder<KoCmykU16Traits>(quint16 value) {
+ return ntohs(value);
+}
+
+template <>
+inline float convertByteOrder<KoCmykF32Traits>(float value) {
+ return ntohs(value);
+}
+
+template <>
+inline quint8 convertByteOrder<KoLabU8Traits>(quint8 value) {
+ return value;
+}
+
+template <>
+inline quint16 convertByteOrder<KoLabU16Traits>(quint16 value) {
+ return ntohs(value);
+}
+
+template <>
+inline float convertByteOrder<KoLabF32Traits>(float value) {
+ return ntohs(value);
+}
+
+template <class Traits>
+void readGrayPixel(const QMap<quint16, QByteArray> &channelBytes,
+ int col, quint8 *dstPtr)
+{
+ typedef typename Traits::Pixel Pixel;
+ typedef typename Traits::channels_type channels_type;
+
+ const channels_type unitValue = KoColorSpaceMathsTraits<channels_type>::unitValue;
+ channels_type opacity = unitValue;
+ if (channelBytes.contains(-1)) {
+ opacity = channelBytes[-1].constData()[col];
+ }
+
+ Pixel *pixelPtr = reinterpret_cast<Pixel*>(dstPtr);
+
+ channels_type gray = convertByteOrder<Traits>(reinterpret_cast<const channels_type \
*>(channelBytes[0].constData())[col]); +
+ pixelPtr->gray = gray;
+ pixelPtr->alpha = opacity;
+}
+
+template <class Traits>
+void readRgbPixel(const QMap<quint16, QByteArray> &channelBytes,
+ int col, quint8 *dstPtr)
+{
+ typedef typename Traits::Pixel Pixel;
+ typedef typename Traits::channels_type channels_type;
+
+ const channels_type unitValue = KoColorSpaceMathsTraits<channels_type>::unitValue;
+ channels_type opacity = unitValue;
+ if (channelBytes.contains(-1)) {
+ opacity = channelBytes[-1].constData()[col];
+ }
+
+ Pixel *pixelPtr = reinterpret_cast<Pixel*>(dstPtr);
+
+ channels_type blue = convertByteOrder<Traits>(reinterpret_cast<const channels_type \
*>(channelBytes[2].constData())[col]); + channels_type green = \
convertByteOrder<Traits>(reinterpret_cast<const channels_type \
*>(channelBytes[1].constData())[col]); + channels_type red = \
convertByteOrder<Traits>(reinterpret_cast<const channels_type \
*>(channelBytes[0].constData())[col]); +
+ pixelPtr->blue = blue;
+ pixelPtr->green = green;
+ pixelPtr->red = red;
+ pixelPtr->alpha = opacity;
+}
+
+template <class Traits>
+void readCmykPixel(const QMap<quint16, QByteArray> &channelBytes,
+ int col, quint8 *dstPtr)
+{
+ typedef typename Traits::Pixel Pixel;
+ typedef typename Traits::channels_type channels_type;
+
+ const channels_type unitValue = KoColorSpaceMathsTraits<channels_type>::unitValue;
+ channels_type opacity = unitValue;
+ if (channelBytes.contains(-1)) {
+ opacity = channelBytes[-1].constData()[col];
+ }
+
+ Pixel *pixelPtr = reinterpret_cast<Pixel*>(dstPtr);
+
+ channels_type cyan = unitValue - convertByteOrder<Traits>(reinterpret_cast<const \
channels_type *>(channelBytes[0].constData())[col]); + channels_type magenta = unitValue - \
convertByteOrder<Traits>(reinterpret_cast<const channels_type \
*>(channelBytes[1].constData())[col]); + channels_type yellow = unitValue - \
convertByteOrder<Traits>(reinterpret_cast<const channels_type \
*>(channelBytes[2].constData())[col]); + channels_type black = unitValue - \
convertByteOrder<Traits>(reinterpret_cast<const channels_type \
*>(channelBytes[3].constData())[col]); +
+ pixelPtr->cyan = cyan;
+ pixelPtr->magenta = magenta;
+ pixelPtr->yellow = yellow;
+ pixelPtr->black = black;
+ pixelPtr->alpha = opacity;
+}
+
+template <class Traits>
+void readLabPixel(const QMap<quint16, QByteArray> &channelBytes,
+ int col, quint8 *dstPtr)
+{
+ typedef typename Traits::Pixel Pixel;
+ typedef typename Traits::channels_type channels_type;
+
+ const channels_type unitValue = KoColorSpaceMathsTraits<channels_type>::unitValue;
+ channels_type opacity = unitValue;
+ if (channelBytes.contains(-1)) {
+ opacity = channelBytes[-1].constData()[col];
+ }
+
+ Pixel *pixelPtr = reinterpret_cast<Pixel*>(dstPtr);
+
+ channels_type L = convertByteOrder<Traits>(reinterpret_cast<const channels_type \
*>(channelBytes[0].constData())[col]); + channels_type a = \
convertByteOrder<Traits>(reinterpret_cast<const channels_type \
*>(channelBytes[1].constData())[col]); + channels_type b = \
convertByteOrder<Traits>(reinterpret_cast<const channels_type \
*>(channelBytes[2].constData())[col]); +
+ pixelPtr->L = L;
+ pixelPtr->a = a;
+ pixelPtr->b = b;
+ pixelPtr->alpha = opacity;
+}
+
+void readRgbPixelCommon(int channelSize,
+ const QMap<quint16, QByteArray> &channelBytes,
+ int col, quint8 *dstPtr)
+{
+ if (channelSize == 1) {
+ readRgbPixel<KoBgrU8Traits>(channelBytes, col, dstPtr);
+ } else if (channelSize == 2) {
+ readRgbPixel<KoBgrU16Traits>(channelBytes, col, dstPtr);
+ } else if (channelSize == 4) {
+ readRgbPixel<KoBgrU16Traits>(channelBytes, col, dstPtr);
+ }
+}
+
+void readGrayPixelCommon(int channelSize,
+ const QMap<quint16, QByteArray> &channelBytes,
+ int col, quint8 *dstPtr)
+{
+ if (channelSize == 1) {
+ readGrayPixel<KoGrayU8Traits>(channelBytes, col, dstPtr);
+ } else if (channelSize == 2) {
+ readGrayPixel<KoGrayU16Traits>(channelBytes, col, dstPtr);
+ } else if (channelSize == 4) {
+ readGrayPixel<KoGrayU32Traits>(channelBytes, col, dstPtr);
+ }
+}
+
+void readCmykPixelCommon(int channelSize,
+ const QMap<quint16, QByteArray> &channelBytes,
+ int col, quint8 *dstPtr)
+{
+ if (channelSize == 1) {
+ readCmykPixel<KoCmykU8Traits>(channelBytes, col, dstPtr);
+ } else if (channelSize == 2) {
+ readCmykPixel<KoCmykU16Traits>(channelBytes, col, dstPtr);
+ } else if (channelSize == 4) {
+ readCmykPixel<KoCmykF32Traits>(channelBytes, col, dstPtr);
+ }
+}
+
+void readLabPixelCommon(int channelSize,
+ const QMap<quint16, QByteArray> &channelBytes,
+ int col, quint8 *dstPtr)
+{
+ if (channelSize == 1) {
+ readLabPixel<KoLabU8Traits>(channelBytes, col, dstPtr);
+ } else if (channelSize == 2) {
+ readLabPixel<KoLabU16Traits>(channelBytes, col, dstPtr);
+ } else if (channelSize == 4) {
+ readLabPixel<KoLabF32Traits>(channelBytes, col, dstPtr);
+ }
+}
+
+QMap<quint16, QByteArray> fetchChannelsBytes(QIODevice *io, QVector<ChannelInfo*> \
channelInfoRecords, + int row, int width, int \
channelSize) +{
+ const int uncompressedLength = width * channelSize;
+
+ QMap<quint16, QByteArray> channelBytes;
+
+ foreach(ChannelInfo *channelInfo, channelInfoRecords) {
+ // user supplied masks are ignored here
+ if (channelInfo->channelId < -1) continue;
+
+ io->seek(channelInfo->channelDataStart + channelInfo->channelOffset);
+
+ if (channelInfo->compressionType == Compression::Uncompressed) {
+ channelBytes[channelInfo->channelId] = io->read(uncompressedLength);
+ channelInfo->channelOffset += uncompressedLength;
+ }
+ else if (channelInfo->compressionType == Compression::RLE) {
+ int rleLength = channelInfo->rleRowLengths[row];
+ QByteArray compressedBytes = io->read(rleLength);
+ QByteArray uncompressedBytes = Compression::uncompress(uncompressedLength, \
compressedBytes, channelInfo->compressionType); + \
channelBytes.insert(channelInfo->channelId, uncompressedBytes); + \
channelInfo->channelOffset += rleLength; + }
+ else {
+ QString error = QString("Unsupported Compression mode: \
%1").arg(channelInfo->compressionType); + dbgFile << "ERROR: fetchChannelsBytes:" << \
error; + throw KisAslReaderUtils::ASLParseException(error);
+ }
+ }
+
+ return channelBytes;
+}
+
+typedef boost::function<void(int, const QMap<quint16, QByteArray>&, int, quint8*)> PixelFunc;
+
+void readCommon(KisPaintDeviceSP dev,
+ QIODevice *io,
+ const QRect &layerRect,
+ QVector<ChannelInfo*> infoRecords,
+ int channelSize,
+ PixelFunc pixelFunc)
+{
+ KisOffsetKeeper keeper(io);
+
+ if (layerRect.isEmpty()) {
+ dbgFile << "Empty layer!";
+ return;
+ }
+
+ KisHLineIteratorSP it = dev->createHLineIteratorNG(layerRect.left(), layerRect.top(), \
layerRect.width()); +
+ for (int i = 0 ; i < layerRect.height(); i++) {
+ QMap<quint16, QByteArray> channelBytes;
+
+ channelBytes = fetchChannelsBytes(io, infoRecords,
+ i, layerRect.width(), channelSize);
+
+ for (qint64 col = 0; col < layerRect.width(); col++){
+ pixelFunc(channelSize, channelBytes, col, it->rawData());
+ it->nextPixel();
+ }
+ it->nextRow();
+ }
+}
+
+void readChannels(QIODevice *io,
+ KisPaintDeviceSP device,
+ psd_color_mode colorMode,
+ int channelSize,
+ const QRect &layerRect,
+ QVector<ChannelInfo*> infoRecords)
+{
+ switch (colorMode) {
+ case Grayscale:
+ readCommon(device, io, layerRect, infoRecords, channelSize, &readGrayPixelCommon);
+ break;
+ case RGB:
+ readCommon(device, io, layerRect, infoRecords, channelSize, &readRgbPixelCommon);
+ break;
+ case CMYK:
+ readCommon(device, io, layerRect, infoRecords, channelSize, &readCmykPixelCommon);
+ break;
+ case Lab:
+ readCommon(device, io, layerRect, infoRecords, channelSize, &readLabPixelCommon);
+ break;
+ case Bitmap:
+ case Indexed:
+ case MultiChannel:
+ case DuoTone:
+ case UNKNOWN:
+ default:
+ QString error = QString("Unsupported color mode: %1").arg(colorMode);
+ throw KisAslReaderUtils::ASLParseException(error);
+ }
+}
}
diff --git a/krita/plugins/formats/psd/psd_pixel_utils.h \
b/krita/plugins/formats/psd/psd_pixel_utils.h index c987926..4af352f 100644
--- a/krita/plugins/formats/psd/psd_pixel_utils.h
+++ b/krita/plugins/formats/psd/psd_pixel_utils.h
@@ -19,247 +19,24 @@
#ifndef __PSD_PIXEL_UTILS_H
#define __PSD_PIXEL_UTILS_H
-#include <QtGlobal>
-#include <QMap>
+#include <QVector>
+#include <QRect>
-#include <KoColorSpace.h>
-#include <KoColorSpaceMaths.h>
-#include <KoColorSpaceTraits.h>
-#include <KoCmykColorSpaceTraits.h>
-
-#include <netinet/in.h> // htonl
+#include "psd.h"
+#include "kis_types.h"
+class QIODevice;
+struct ChannelInfo;
namespace PsdPixelUtils
{
-template <class Traits>
-typename Traits::channels_type convertByteOrder(typename Traits::channels_type value);
-// default implementation is undefined for every color space should be added manually
-
-template <>
-inline quint8 convertByteOrder<KoGrayU8Traits>(quint8 value) {
- return value;
-}
-
-template <>
-inline quint16 convertByteOrder<KoGrayU16Traits>(quint16 value) {
- return ntohs(value);
-}
-
-template <>
-inline quint32 convertByteOrder<KoGrayU32Traits>(quint32 value) {
- return ntohs(value);
-}
-
-template <>
-inline quint8 convertByteOrder<KoBgrU8Traits>(quint8 value) {
- return value;
-}
-
-template <>
-inline quint16 convertByteOrder<KoBgrU16Traits>(quint16 value) {
- return ntohs(value);
-}
-
-template <>
-inline quint32 convertByteOrder<KoBgrU32Traits>(quint32 value) {
- return ntohs(value);
-}
-
-template <>
-inline quint8 convertByteOrder<KoCmykU8Traits>(quint8 value) {
- return value;
-}
-
-template <>
-inline quint16 convertByteOrder<KoCmykU16Traits>(quint16 value) {
- return ntohs(value);
-}
-
-template <>
-inline float convertByteOrder<KoCmykF32Traits>(float value) {
- return ntohs(value);
-}
-
-template <>
-inline quint8 convertByteOrder<KoLabU8Traits>(quint8 value) {
- return value;
-}
-
-template <>
-inline quint16 convertByteOrder<KoLabU16Traits>(quint16 value) {
- return ntohs(value);
-}
-
-template <>
-inline float convertByteOrder<KoLabF32Traits>(float value) {
- return ntohs(value);
-}
-
-template <class Traits>
-void readGrayPixel(const QMap<quint16, QByteArray> &channelBytes,
- int col, quint8 *dstPtr)
-{
- typedef typename Traits::Pixel Pixel;
- typedef typename Traits::channels_type channels_type;
-
- const channels_type unitValue = KoColorSpaceMathsTraits<channels_type>::unitValue;
- channels_type opacity = unitValue;
- if (channelBytes.contains(-1)) {
- opacity = channelBytes[-1].constData()[col];
- }
-
- Pixel *pixelPtr = reinterpret_cast<Pixel*>(dstPtr);
-
- channels_type gray = convertByteOrder<Traits>(reinterpret_cast<const channels_type \
*>(channelBytes[0].constData())[col]);
-
- pixelPtr->gray = gray;
- pixelPtr->alpha = opacity;
-}
-
-template <class Traits>
-void readRgbPixel(const QMap<quint16, QByteArray> &channelBytes,
- int col, quint8 *dstPtr)
-{
- typedef typename Traits::Pixel Pixel;
- typedef typename Traits::channels_type channels_type;
-
- const channels_type unitValue = KoColorSpaceMathsTraits<channels_type>::unitValue;
- channels_type opacity = unitValue;
- if (channelBytes.contains(-1)) {
- opacity = channelBytes[-1].constData()[col];
- }
-
- Pixel *pixelPtr = reinterpret_cast<Pixel*>(dstPtr);
-
- channels_type blue = convertByteOrder<Traits>(reinterpret_cast<const channels_type \
*>(channelBytes[2].constData())[col]);
- channels_type green = convertByteOrder<Traits>(reinterpret_cast<const channels_type \
*>(channelBytes[1].constData())[col]);
- channels_type red = convertByteOrder<Traits>(reinterpret_cast<const channels_type \
*>(channelBytes[0].constData())[col]);
-
- pixelPtr->blue = blue;
- pixelPtr->green = green;
- pixelPtr->red = red;
- pixelPtr->alpha = opacity;
-}
-
-template <class Traits>
-void readCmykPixel(const QMap<quint16, QByteArray> &channelBytes,
- int col, quint8 *dstPtr)
-{
- typedef typename Traits::Pixel Pixel;
- typedef typename Traits::channels_type channels_type;
-
- const channels_type unitValue = KoColorSpaceMathsTraits<channels_type>::unitValue;
- channels_type opacity = unitValue;
- if (channelBytes.contains(-1)) {
- opacity = channelBytes[-1].constData()[col];
- }
-
- Pixel *pixelPtr = reinterpret_cast<Pixel*>(dstPtr);
-
- channels_type cyan = unitValue - convertByteOrder<Traits>(reinterpret_cast<const \
channels_type *>(channelBytes[0].constData())[col]);
- channels_type magenta = unitValue - convertByteOrder<Traits>(reinterpret_cast<const \
channels_type *>(channelBytes[1].constData())[col]);
- channels_type yellow = unitValue - convertByteOrder<Traits>(reinterpret_cast<const \
channels_type *>(channelBytes[2].constData())[col]);
- channels_type black = unitValue - convertByteOrder<Traits>(reinterpret_cast<const \
channels_type *>(channelBytes[3].constData())[col]);
-
- pixelPtr->cyan = cyan;
- pixelPtr->magenta = magenta;
- pixelPtr->yellow = yellow;
- pixelPtr->black = black;
- pixelPtr->alpha = opacity;
-}
-
-template <class Traits>
-void readLabPixel(const QMap<quint16, QByteArray> &channelBytes,
- int col, quint8 *dstPtr)
-{
- typedef typename Traits::Pixel Pixel;
- typedef typename Traits::channels_type channels_type;
-
- const channels_type unitValue = KoColorSpaceMathsTraits<channels_type>::unitValue;
- channels_type opacity = unitValue;
- if (channelBytes.contains(-1)) {
- opacity = channelBytes[-1].constData()[col];
- }
-
- Pixel *pixelPtr = reinterpret_cast<Pixel*>(dstPtr);
-
- channels_type L = convertByteOrder<Traits>(reinterpret_cast<const channels_type \
*>(channelBytes[0].constData())[col]);
- channels_type a = convertByteOrder<Traits>(reinterpret_cast<const channels_type \
*>(channelBytes[1].constData())[col]);
- channels_type b = convertByteOrder<Traits>(reinterpret_cast<const channels_type \
*>(channelBytes[2].constData())[col]);
-
- pixelPtr->L = L;
- pixelPtr->a = a;
- pixelPtr->b = b;
- pixelPtr->alpha = opacity;
-}
-
-template <class Traits8, class Traits16, class Traits32>
-inline void readPixelCommon(int channelSize,
- const QMap<quint16, QByteArray> &channelBytes,
- int col, quint8 *dstPtr)
-{
- if (channelSize == 1) {
- readRgbPixel<Traits8>(channelBytes, col, dstPtr);
- } else if (channelSize == 2) {
- readRgbPixel<Traits16>(channelBytes, col, dstPtr);
- } else if (channelSize == 4) {
- readRgbPixel<Traits32>(channelBytes, col, dstPtr);
- }
-}
-
-inline void readRgbPixelCommon(int channelSize,
- const QMap<quint16, QByteArray> &channelBytes,
- int col, quint8 *dstPtr)
-{
- if (channelSize == 1) {
- readRgbPixel<KoBgrU8Traits>(channelBytes, col, dstPtr);
- } else if (channelSize == 2) {
- readRgbPixel<KoBgrU16Traits>(channelBytes, col, dstPtr);
- } else if (channelSize == 4) {
- readRgbPixel<KoBgrU16Traits>(channelBytes, col, dstPtr);
- }
-}
-
-inline void readGrayPixelCommon(int channelSize,
- const QMap<quint16, QByteArray> &channelBytes,
- int col, quint8 *dstPtr)
-{
- if (channelSize == 1) {
- readGrayPixel<KoGrayU8Traits>(channelBytes, col, dstPtr);
- } else if (channelSize == 2) {
- readGrayPixel<KoGrayU16Traits>(channelBytes, col, dstPtr);
- } else if (channelSize == 4) {
- readGrayPixel<KoGrayU32Traits>(channelBytes, col, dstPtr);
- }
-}
-
-inline void readCmykPixelCommon(int channelSize,
- const QMap<quint16, QByteArray> &channelBytes,
- int col, quint8 *dstPtr)
-{
- if (channelSize == 1) {
- readCmykPixel<KoCmykU8Traits>(channelBytes, col, dstPtr);
- } else if (channelSize == 2) {
- readCmykPixel<KoCmykU16Traits>(channelBytes, col, dstPtr);
- } else if (channelSize == 4) {
- readCmykPixel<KoCmykF32Traits>(channelBytes, col, dstPtr);
- }
-}
-
-inline void readLabPixelCommon(int channelSize,
- const QMap<quint16, QByteArray> &channelBytes,
- int col, quint8 *dstPtr)
-{
- if (channelSize == 1) {
- readLabPixel<KoLabU8Traits>(channelBytes, col, dstPtr);
- } else if (channelSize == 2) {
- readLabPixel<KoLabU16Traits>(channelBytes, col, dstPtr);
- } else if (channelSize == 4) {
- readLabPixel<KoLabF32Traits>(channelBytes, col, dstPtr);
- }
-}
+ void readChannels(QIODevice *io,
+ KisPaintDeviceSP device,
+ psd_color_mode colorMode,
+ int channelSize,
+ const QRect &layerRect,
+ QVector<ChannelInfo*> infoRecords);
}
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic