Commit c8ea2517 authored by Boudewijn Rempt's avatar Boudewijn Rempt

Merge the psd export branch to master

This implements single-layer and multi-layer Photoshop
version 1 file export for Krita.

Squashed commit of the following:

commit 7849fd4a1a5390b5996a7df1fae68762710324b4
Merge: 7374c20 06577f1
Author: Boudewijn Rempt <boud@valdyas.org>
Date:   Tue Dec 4 11:50:13 2012 +0100

    Merge branch 'master' into krita-psd_export-rempt

commit 7374c20bcb1db5a78fb855b7ef7a21db894f27a2
Author: Boudewijn Rempt <boud@valdyas.org>
Date:   Tue Dec 4 11:39:43 2012 +0100

    Fix saving of multiline psd files

    We needed the empty global layer mask info block... Also, Qt' QRect
    bottom != photoshop's idea of a bottom.

commit 2ed3a9f744d776c0555768c64d7ca8a6e6671c6d
Merge: 441c0bc a1f365e
Author: Boudewijn Rempt <boud@valdyas.org>
Date:   Mon Dec 3 15:27:51 2012 +0100

    Merge branch 'master' into krita-psd_export-rempt

commit 441c0bc9abbaae372f0bfc0d6fdbd73b3819838f
Merge: 1119bac 13036ac
Author: Boudewijn Rempt <boud@valdyas.org>
Date:   Sat Dec 1 10:06:24 2012 +0100

    Merge branch 'master' into krita-psd_export-rempt

commit 1119bac1bc11816b89cd5f5fef411198b6f8f0be
Merge: b1fa0a1 81b50ca
Author: Boudewijn Rempt <boud@valdyas.org>
Date:   Sat Nov 24 12:28:12 2012 +0100

    Merge branch 'master' into krita-psd_export-rempt

commit b1fa0a158a9bdbbfe676f69b260f337643cb296b
Author: Boudewijn Rempt <boud@valdyas.org>
Date:   Sat Nov 24 12:26:31 2012 +0100

    Do not swap top and left... Fixes saving to psd with layers

    This makes it possible for krita to load psd files it saved, but the psd
    files still are not correct, gimp cannot load them and krita complains.

commit 9a6f59e356e9e83578274153ee308d337c186408
Author: Boudewijn Rempt <boud@valdyas.org>
Date:   Sat Nov 24 11:21:03 2012 +0100

    at least the first layer now saves correctly, no idea why the other layers are broken

commit e14d0029be3f311dae13bd94f9d00975d6db4473
Author: Boudewijn Rempt <boud@valdyas.org>
Date:   Fri Nov 23 14:31:01 2012 +0100

    Revert "don't try to create the color from itself"

    This reverts commit 348e8c2040a9d0d1068c42d809bbba4be16c7626.

commit 0db1406b1db29e563bc19e182b7761a95faf91fd
Author: Boudewijn Rempt <boud@valdyas.org>
Date:   Fri Nov 23 11:49:12 2012 +0100

    fix reading of pascal strings again

commit 3fca5f7bbc9b91f7008a17fc13b24b195c2d5cd8
Author: Boudewijn Rempt <boud@valdyas.org>
Date:   Fri Nov 23 10:37:52 2012 +0100

    add unittest for compression

commit cf5b7ba8a44da100fd5237f9da8cfabc54f41d41
Merge: c654ae1 a96e6ec
Author: Boudewijn Rempt <boud@valdyas.org>
Date:   Thu Nov 22 13:37:11 2012 +0100

    Merge branch 'master' into krita-psd_export-rempt

commit c654ae182e83aeff9370755ad7520bbdb9269849
Author: Boudewijn Rempt <boud@valdyas.org>
Date:   Thu Nov 22 13:36:58 2012 +0100

    add tests for compression

commit 7b58b94c4f924aeff81303b29419a9f918206a85
Author: Boudewijn Rempt <boud@valdyas.org>
Date:   Thu Nov 22 12:39:16 2012 +0100

    reinstate the unittests

commit 5ef9f4324b5d6f7bf610467c0038ba479da092b9
Merge: 78491ff 368440f
Author: Boudewijn Rempt <boud@valdyas.org>
Date:   Thu Nov 22 11:09:57 2012 +0100

    Merge branch 'master' into krita-psd_export-rempt

commit 78491ffa2076279a8dbdc75164cd8cc9c2c0cbcb
Author: Boudewijn Rempt <boud@valdyas.org>
Date:   Thu Nov 22 11:09:54 2012 +0100

    ...

commit 6326e1f5a0151b176b0a01b178ff83023f593e10
Author: Boudewijn Rempt <boud@valdyas.org>
Date:   Thu Nov 22 11:09:36 2012 +0100

    Initialize all variables

commit 348e8c2040a9d0d1068c42d809bbba4be16c7626
Author: Boudewijn Rempt <boud@valdyas.org>
Date:   Thu Nov 22 10:55:30 2012 +0100

    don't try to create the color from itself

commit 3b999307b2e3f92fbf65aa15ec5b07e6493475ce
Author: Boudewijn Rempt <boud@valdyas.org>
Date:   Thu Nov 22 10:55:12 2012 +0100

    initialize variable

commit 96da561fdaef83abeb97becea0164631e74f6d4b
Author: Boudewijn Rempt <boud@valdyas.org>
Date:   Thu Nov 22 10:54:40 2012 +0100

    don't copy the same memory range over itself

commit 9efa3c37d78454ac160a357f409ca59f5f00fb13
Merge: ddf8a8c 3eb3fdf
Author: Boudewijn Rempt <boud@valdyas.org>
Date:   Mon Nov 19 11:00:54 2012 +0100

    Merge branch 'master' into krita-psd_export-rempt

commit ddf8a8cfc991d2d32e9fad60d1fa95fdd98a758e
Author: Boudewijn Rempt <boud@valdyas.org>
Date:   Mon Nov 19 11:00:52 2012 +0100

    some more layer hackery

commit 5fcf27c46949809be79a0ecf46f6b038cf292b7a
Merge: b419049 e07ccbb
Author: Boudewijn Rempt <boud@valdyas.org>
Date:   Wed Nov 14 11:31:15 2012 +0100

    Merge branch 'master' into krita-psd_export-rempt

commit b419049b3c72cf0e99dad8cac4f64de8ea3c218f
Author: Boudewijn Rempt <boud@valdyas.org>
Date:   Mon Nov 12 14:23:14 2012 +0100

    our layers are in the right order for psd

commit a41448d30c1c45f55c12deb2e62c1998bf8fb95c
Author: Boudewijn Rempt <boud@valdyas.org>
Date:   Mon Nov 12 12:03:04 2012 +0100

    make number of layers negative, since we always have alpha in krita

commit 517940f45e35c663787e52d24c5e01fe199315a8
Author: Boudewijn Rempt <boud@valdyas.org>
Date:   Mon Nov 12 11:05:16 2012 +0100

    implement saving of layer data (still a bit broken)

commit 3553d6154738ce8b27a1e7c2c6a73c8047352f44
Author: Boudewijn Rempt <boud@valdyas.org>
Date:   Mon Nov 12 10:05:40 2012 +0100

    Write the layer description records

commit f5fc2faa570eaa004bce33659e1e2674a0f66160
Author: Boudewijn Rempt <boud@valdyas.org>
Date:   Sun Nov 11 13:10:39 2012 +0100

    Correctly save rle-encoded image data

    For now, krita only saves using RLE, not uncompressed or zipped. We
    first need to save the channel lengths in a block, then the channel
    data.

commit 23d91520488aa8e8e8034093862a7d517e6882c8
Author: Boudewijn Rempt <boud@valdyas.org>
Date:   Sun Nov 11 13:10:36 2012 +0100

    write the icc resource block correctly

commit b7c0888d4e4044fc1c2749f7645e3d7af3eb3a89
Author: Boudewijn Rempt <boud@valdyas.org>
Date:   Sun Nov 11 12:52:11 2012 +0100

    when compressing, compress, don't uncompress

commit c344d565c598153976af40d3db9184a89648f95e
Author: Boudewijn Rempt <boud@valdyas.org>
Date:   Sun Nov 11 12:42:41 2012 +0100

    Write the image data section

commit 9519207ee07f3abbe08ad37e5e6605de33f0b300
Author: Boudewijn Rempt <boud@valdyas.org>
Date:   Sun Nov 11 12:42:10 2012 +0100

    Correctly write the resource block

commit 87a8b2c9febaaf9ed5cdfe41505a033f825e3a7b
Author: Boudewijn Rempt <boud@valdyas.org>
Date:   Sun Nov 11 11:59:48 2012 +0100

    conform to coding style

commit ac05c1b04581d5d13f865328bc7e1ad22a465e7d
Author: Boudewijn Rempt <boud@valdyas.org>
Date:   Sun Nov 11 11:41:08 2012 +0100

    swap parameters to make api consistent

commit a5d2534c0daffb4f21d12c0302864aec1f7e5477
Author: Boudewijn Rempt <boud@valdyas.org>
Date:   Sun Nov 11 11:40:50 2012 +0100

    start implementing packbits writing

commit 6c542e43a493c8327f5c1329ab3830f84123d108
Author: Boudewijn Rempt <boud@valdyas.org>
Date:   Sat Nov 10 11:51:37 2012 +0100

    Load and save the icc profile

commit bb4b031e947aff249f9200f2419b5909eebd3ba1
Author: Boudewijn Rempt <boud@valdyas.org>
Date:   Fri Nov 9 17:26:18 2012 +0100

    Write the resource section

commit 8a32125aa8d2b4220880dd8400fcea04c2f9e7eb
Author: Boudewijn Rempt <boud@valdyas.org>
Date:   Fri Nov 9 17:19:15 2012 +0100

    implement writing of the colormode block

commit b702c06fde22852d052f2650a2499420d64743e4
Author: Boudewijn Rempt <boud@valdyas.org>
Date:   Fri Nov 9 15:49:56 2012 +0100

    we only save version 1 psd, not psb

commit e4f434dcc0891366102969077a6b903edd3da1b2
Author: Boudewijn Rempt <boud@valdyas.org>
Date:   Fri Nov 9 15:46:17 2012 +0100

    Clean up psd image builder

commit aba7085b342e0f7185e3b5fc9e83195ba14179b4
Author: Boudewijn Rempt <boud@valdyas.org>
Date:   Tue Nov 6 10:46:55 2012 +0100

    Distinguish between different filter errors

    CreationError was used in four cases:

    * couldn't create the filter plugin
    * couldn't create the output document
    * couldn't cast KoDocument to KisDoc2
    * couldn't download the remote file

    So to avoid confusion, distinguish between these cases, and even more,
    distinguish between the case when the filter entry is inexplicably null
    and the case the filter plugin couldn't be instantiated.

commit 58ab418eda6cf7b1cc1c03125328f4a9ee1c3851
Merge: 3a6369e f2bb258
Author: Boudewijn Rempt <boud@valdyas.org>
Date:   Fri Nov 9 15:25:24 2012 +0100

    Merge remote-tracking branch 'origin/master' into krita-psd_export-rempt

commit 3a6369e19586c96a4d135e11e47da74fc2f1a4b5
Merge: 65e21ce 33302e6
Author: Boudewijn Rempt <boud@valdyas.org>
Date:   Fri Nov 9 14:23:17 2012 +0100

    Merge branch 'master' into krita-psd_export-rempt

commit 65e21ce7b858cb105061aa5bca75d7de03e81230
Merge: fa84a95 bf7d2fb
Author: Boudewijn Rempt <boud@valdyas.org>
Date:   Thu Jul 26 10:12:31 2012 +0200

    Merge branch 'master' into krita-psd_export-rempt

commit fa84a95382782ae02fa7080d48c5f2503fd0299f
Author: Boudewijn Rempt <boud@valdyas.org>
Date:   Thu Jul 12 10:44:00 2012 +0200

    Save the psd header correctly

commit 9b9c2c69eaf1c797df3e33537e0c07bd143ac7d8
Author: Boudewijn Rempt <boud@valdyas.org>
Date:   Wed Jul 11 16:55:48 2012 +0200

    start saving the psd file

commit b8d49667085565962e957013ddb70d30c334f67e
Author: Boudewijn Rempt <boud@valdyas.org>
Date:   Wed Jul 11 16:55:37 2012 +0200

    fix some warnings

commit 373be2164d1358c6a0c4a08540931417655d5bfe
Author: Boudewijn Rempt <boud@valdyas.org>
Date:   Wed Jul 11 16:26:32 2012 +0200

    Re-enable the installation of the psd export filter
parent 5d137e2f
......@@ -21,8 +21,8 @@
/* FIXME: Think over SSE here */
void KisTiledDataManager::writeBytesBody(const quint8 *data,
qint32 x, qint32 y,
qint32 width, qint32 height)
qint32 x, qint32 y,
qint32 width, qint32 height)
{
if (!data) return;
......@@ -40,15 +40,15 @@ void KisTiledDataManager::writeBytesBody(const quint8 *data,
qint32 imageX = x;
qint32 columnsRemaining = width;
qint32 numContiguousImageRows = numContiguousRows(imageY, imageX,
imageX + width - 1);
imageX + width - 1);
qint32 rowsToWork = qMin(numContiguousImageRows, rowsRemaining);
while (columnsRemaining > 0) {
qint32 numContiguousImageColumns =
numContiguousColumns(imageX, imageY,
imageY + rowsToWork - 1);
numContiguousColumns(imageX, imageY,
imageY + rowsToWork - 1);
qint32 columnsToWork = qMin(numContiguousImageColumns,
columnsRemaining);
......@@ -60,7 +60,7 @@ void KisTiledDataManager::writeBytesBody(const quint8 *data,
const qint32 tileRowStride = rowStride(imageX, imageY);
const quint8 *dataIt = data +
((dataX + (dataY * width)) * pixelSize);
((dataX + (dataY * width)) * pixelSize);
const qint32 dataRowStride = width * pixelSize;
......@@ -104,14 +104,14 @@ void KisTiledDataManager::readBytesBody(quint8 *data,
qint32 imageX = x;
qint32 columnsRemaining = width;
qint32 numContiguousImageRows = numContiguousRows(imageY, imageX,
imageX + width - 1);
imageX + width - 1);
qint32 rowsToWork = qMin(numContiguousImageRows, rowsRemaining);
while (columnsRemaining > 0) {
qint32 numContiguousImageColumns = numContiguousColumns(imageX, imageY,
imageY + rowsToWork - 1);
imageY + rowsToWork - 1);
qint32 columnsToWork = qMin(numContiguousImageColumns,
columnsRemaining);
......@@ -124,7 +124,7 @@ void KisTiledDataManager::readBytesBody(quint8 *data,
const qint32 tileRowStride = rowStride(imageX, imageY);
quint8 *dataIt = data +
((dataX + (dataY * width)) * pixelSize);
((dataX + (dataY * width)) * pixelSize);
const qint32 dataRowStride = width * pixelSize;
......@@ -150,13 +150,13 @@ void KisTiledDataManager::readBytesBody(quint8 *data,
#define forEachChannel(_idx, _channelSize) \
for(qint32 _idx=0, _channelSize=channelSizes[_idx]; \
_idx<numChannels && (_channelSize=channelSizes[_idx], 1); \
_idx++)
_idx<numChannels && (_channelSize=channelSizes[_idx], 1); \
_idx++)
void KisTiledDataManager::writePlanarBytesBody(QVector </*const*/ quint8* > planes,
QVector<qint32> channelSizes,
qint32 x, qint32 y,
qint32 width, qint32 height)
QVector<qint32> channelSizes,
qint32 x, qint32 y,
qint32 width, qint32 height)
{
Q_ASSERT(planes.size() == channelSizes.size());
Q_ASSERT(planes.size() > 0);
......@@ -177,21 +177,21 @@ void KisTiledDataManager::writePlanarBytesBody(QVector </*const*/ quint8* > plan
qint32 imageX = x;
qint32 columnsRemaining = width;
qint32 numContiguousImageRows = numContiguousRows(imageY, imageX,
imageX + width - 1);
imageX + width - 1);
qint32 rowsToWork = qMin(numContiguousImageRows, rowsRemaining);
while (columnsRemaining > 0) {
qint32 numContiguousImageColumns =
numContiguousColumns(imageX, imageY,
imageY + rowsToWork - 1);
numContiguousColumns(imageX, imageY,
imageY + rowsToWork - 1);
qint32 columnsToWork = qMin(numContiguousImageColumns,
columnsRemaining);
const qint32 dataIdx = dataX + dataY * width;
const qint32 tileRowStride = rowStride(imageX, imageY) -
columnsToWork * pixelSize;
columnsToWork * pixelSize;
KisTileDataWrapper tw(this, imageX, imageY,
KisTileDataWrapper::WRITE);
......@@ -228,10 +228,9 @@ void KisTiledDataManager::writePlanarBytesBody(QVector </*const*/ quint8* > plan
}
}
QVector<quint8*> KisTiledDataManager::
readPlanarBytesBody(QVector<qint32> channelSizes,
qint32 x, qint32 y,
qint32 width, qint32 height)
QVector<quint8*> KisTiledDataManager::readPlanarBytesBody(QVector<qint32> channelSizes,
qint32 x, qint32 y,
qint32 width, qint32 height)
{
Q_ASSERT(channelSizes.size() > 0);
......@@ -256,21 +255,21 @@ readPlanarBytesBody(QVector<qint32> channelSizes,
qint32 imageX = x;
qint32 columnsRemaining = width;
qint32 numContiguousImageRows = numContiguousRows(imageY, imageX,
imageX + width - 1);
imageX + width - 1);
qint32 rowsToWork = qMin(numContiguousImageRows, rowsRemaining);
while (columnsRemaining > 0) {
qint32 numContiguousImageColumns =
numContiguousColumns(imageX, imageY,
imageY + rowsToWork - 1);
numContiguousColumns(imageX, imageY,
imageY + rowsToWork - 1);
qint32 columnsToWork = qMin(numContiguousImageColumns,
columnsRemaining);
const qint32 dataIdx = dataX + dataY * width;
const qint32 tileRowStride = rowStride(imageX, imageY) -
columnsToWork * pixelSize;
columnsToWork * pixelSize;
KisTileDataWrapper tw(this, imageX, imageY,
KisTileDataWrapper::READ);
......
......@@ -303,6 +303,7 @@ void KisColorSelector::init()
{
setAcceptDrops(true);
m_lastColorRole = Foreground;
m_ring = new KisColorSelectorRing(this);
m_triangle = new KisColorSelectorTriangle(this);
m_slider = new KisColorSelectorSimple(this);
......
......@@ -62,7 +62,7 @@ KoFilter::ConversionStatus KisBMPExport::convert(const QByteArray& from, const Q
QString filename = m_chain->outputFile();
if (!output)
return KoFilter::CreationError;
return KoFilter::NoDocumentCreated;
if (filename.isEmpty()) return KoFilter::FileNotFound;
......
......@@ -75,7 +75,7 @@ KoFilter::ConversionStatus KisBMPImport::convert(const QByteArray& from, const Q
KisDoc2 * doc = dynamic_cast<KisDoc2*>(m_chain -> outputDocument());
if (!doc)
return KoFilter::CreationError;
return KoFilter::NoDocumentCreated;
QString filename = m_chain -> inputFile();
......
......@@ -91,7 +91,7 @@ KoFilter::ConversionStatus exrExport::convert(const QByteArray& from, const QByt
QString filename = m_chain->outputFile();
if (!output)
return KoFilter::CreationError;
return KoFilter::NoDocumentCreated;
if (filename.isEmpty()) return KoFilter::FileNotFound;
......
......@@ -49,7 +49,7 @@ KoFilter::ConversionStatus exrImport::convert(const QByteArray&, const QByteArra
KisDoc2 * doc = dynamic_cast<KisDoc2*>(m_chain->outputDocument());
if (!doc)
return KoFilter::CreationError;
return KoFilter::NoDocumentCreated;
QString filename = m_chain -> inputFile();
......
......@@ -65,7 +65,7 @@ KoFilter::ConversionStatus jp2Export::convert(const QByteArray& from, const QByt
QString filename = m_chain->outputFile();
if (!output)
return KoFilter::CreationError;
return KoFilter::NoDocumentCreated;
if (filename.isEmpty()) return KoFilter::FileNotFound;
......
......@@ -48,7 +48,7 @@ KoFilter::ConversionStatus jp2Import::convert(const QByteArray&, const QByteArra
KisDoc2 * doc = dynamic_cast<KisDoc2*>(m_chain->outputDocument());
if (!doc)
return KoFilter::CreationError;
return KoFilter::NoDocumentCreated;
QString filename = m_chain -> inputFile();
......
......@@ -164,7 +164,7 @@ KoFilter::ConversionStatus KisJPEGExport::convert(const QByteArray& from, const
QString filename = m_chain->outputFile();
if (!output)
return KoFilter::CreationError;
return KoFilter::NoDocumentCreated;
if (filename.isEmpty()) return KoFilter::FileNotFound;
......
......@@ -51,7 +51,7 @@ KoFilter::ConversionStatus KisJPEGImport::convert(const QByteArray&, const QByte
KisDoc2 * doc = dynamic_cast<KisDoc2*>(m_chain->outputDocument());
if (!doc)
return KoFilter::CreationError;
return KoFilter::NoDocumentCreated;
QString filename = m_chain -> inputFile();
......
......@@ -62,7 +62,7 @@ KoFilter::ConversionStatus KisODGImport::convert(const QByteArray& from, const Q
KisDoc2 * doc = dynamic_cast<KisDoc2*>(m_chain -> outputDocument());
if (!doc)
return KoFilter::CreationError;
return KoFilter::NoDocumentCreated;
QString filename = m_chain->inputFile();
......
......@@ -62,7 +62,7 @@ KoFilter::ConversionStatus KisOiioExport::convert(const QByteArray& from, const
QString filename = m_chain->outputFile();
if (!output)
return KoFilter::CreationError;
return KoFilter::NoDocumentCreated;
if (filename.isEmpty()) return KoFilter::FileNotFound;
......
......@@ -82,7 +82,7 @@ KoFilter::ConversionStatus KisOiioImport::convert(const QByteArray& from, const
KisDoc2 * doc = dynamic_cast<KisDoc2*>(m_chain -> outputDocument());
if (!doc)
return KoFilter::CreationError;
return KoFilter::NoDocumentCreated;
QString filename = m_chain -> inputFile();
......@@ -105,8 +105,6 @@ KoFilter::ConversionStatus KisOiioImport::convert(const QByteArray& from, const
int nSubImages = buf.nsubimages();
// const KoColorSpace *colorSpace = KoColorSpaceRegistry::instance()->colorSpace(RGBAColorModelID.id(),
// Float32BitsColorDepthID.id(),
// "");
......
......@@ -81,7 +81,7 @@ KoFilter::ConversionStatus OraExport::convert(const QByteArray& from, const QByt
QString filename = m_chain->outputFile();
if (!output)
return KoFilter::CreationError;
return KoFilter::NoDocumentCreated;
if (filename.isEmpty()) return KoFilter::FileNotFound;
......
......@@ -47,7 +47,7 @@ KoFilter::ConversionStatus OraImport::convert(const QByteArray&, const QByteArra
KisDoc2 * doc = dynamic_cast<KisDoc2*>(m_chain->outputDocument());
if (!doc)
return KoFilter::CreationError;
return KoFilter::NoDocumentCreated;
QString filename = m_chain -> inputFile();
......
......@@ -127,7 +127,7 @@ KisPDFImport::ConversionStatus KisPDFImport::convert(const QByteArray& , const Q
if (!doc) {
delete pdoc;
delete kdb;
return KoFilter::CreationError;
return KoFilter::NoDocumentCreated;
}
doc -> prepareForImport();
......
......@@ -76,7 +76,7 @@ KoFilter::ConversionStatus KisPNGExport::convert(const QByteArray& from, const Q
QString filename = m_chain->outputFile();
if (!output)
return KoFilter::CreationError;
return KoFilter::NoDocumentCreated;
if (filename.isEmpty()) return KoFilter::FileNotFound;
......
......@@ -51,7 +51,7 @@ KoFilter::ConversionStatus KisPNGImport::convert(const QByteArray&, const QByteA
KisDoc2 * doc = dynamic_cast<KisDoc2*>(m_chain -> outputDocument());
if (!doc)
return KoFilter::CreationError;
return KoFilter::NoDocumentCreated;
QString filename = m_chain -> inputFile();
......
......@@ -147,7 +147,7 @@ KoFilter::ConversionStatus KisPPMExport::convert(const QByteArray& from, const Q
QString filename = m_chain->outputFile();
if (!output)
return KoFilter::CreationError;
return KoFilter::NoDocumentCreated;
if (filename.isEmpty()) return KoFilter::FileNotFound;
......
......@@ -67,7 +67,7 @@ KoFilter::ConversionStatus KisPPMImport::convert(const QByteArray& from, const Q
KisDoc2 * doc = dynamic_cast<KisDoc2*>(m_chain -> outputDocument());
if (!doc)
return KoFilter::CreationError;
return KoFilter::NoDocumentCreated;
QString filename = m_chain -> inputFile();
......
#add_subdirectory(tests)
add_subdirectory(tests)
include_directories( ${KRITA_INCLUDES} )
......@@ -17,7 +17,6 @@ set(LIB_PSD_SRCS
psd_layer_section.cpp
psd_layer_record.cpp
psd_image_data.cpp
compression.cpp
)
......@@ -41,9 +40,9 @@ set(kritapsdexport_PART_SRCS
kde4_add_plugin(kritapsdexport ${kritapsdexport_PART_SRCS})
target_link_libraries(kritapsdexport kritaui )
#install(TARGETS kritapsdexport DESTINATION ${PLUGIN_INSTALL_DIR})
install(TARGETS kritapsdexport DESTINATION ${PLUGIN_INSTALL_DIR})
install( FILES krita_psd_import.desktop
# krita_psd_export.desktop
krita_psd_export.desktop
DESTINATION ${SERVICES_INSTALL_DIR})
install( PROGRAMS krita_psd.desktop DESTINATION ${XDG_APPS_INSTALL_DIR})
......@@ -21,6 +21,72 @@
#include <QBuffer>
#include "psd_utils.h"
#include "kis_debug.h"
#include <netinet/in.h> // htonl
// from gimp's psd-save.c
static quint32 pack_pb_line (const QByteArray &src,
QByteArray &dst)
{
quint32 length = src.size();
quint32 remaining = length;
quint8 i, j;
quint32 dest_ptr = 0;
const char *start = src.constData();
length = 0;
while (remaining > 0)
{
/* Look for characters matching the first */
i = 0;
while ((i < 128) &&
(remaining - i > 0) &&
(start[0] == start[i]) )
i++;
if (i > 1) /* Match found */
{
dst[dest_ptr++] = -(i - 1);
dst[dest_ptr++] = *start;
start += i;
remaining -= i;
length += 2;
}
else /* Look for characters different from the previous */
{
i = 0;
while ((i < 128) &&
(remaining - (i + 1) > 0) &&
(start[i] != start[(i + 1)] ||
remaining - (i + 2) <= 0 || start[i] != start[(i+2)]))
i++;
/* If there's only 1 remaining, the previous WHILE stmt doesn't
catch it */
if (remaining == 1)
{
i = 1;
}
if (i > 0) /* Some distinct ones found */
{
dst[dest_ptr++] = i - 1;
for (j = 0; j < i; j++)
{
dst[dest_ptr++] = start[j];
}
start += i;
remaining -= i;
length += i + 1;
}
}
}
return length;
}
// from gimp's psd-util.c
quint32 decode_packbits(const char *src, char* dst, quint16 packed_len, quint32 unpacked_len)
......@@ -127,45 +193,45 @@ quint32 decode_packbits(const char *src, char* dst, quint16 packed_len, quint32
}
if (error_code)
dbgFile << "Error code" << error_code;
dbgFile << "Error code" << error_code;
return return_val;
}
QByteArray unRLE(int nBytes, QByteArray bytes)
{
char *dst = new char[nBytes];
decode_packbits(bytes.constData(), dst, bytes.length(), nBytes);
return QByteArray(dst, nBytes);
}
QByteArray unzip(quint32 nBytes, QByteArray bytes)
QByteArray Compression::uncompress(quint32 unpacked_len, QByteArray bytes, Compression::CompressionType compressionType)
{
// prepend the expected length of the pixels in big-endian
// format to the byte array as qUncompress expects...
QByteArray b;
QBuffer buf(&b);
psdwrite(&buf, nBytes);
b.append(bytes);
// and let's hope that this is sufficient...
return qUncompress(bytes);
}
if (unpacked_len > 30000) return QByteArray();
if (bytes.size() < 1) return QByteArray();
QByteArray Compression::uncompress(quint32 nBytes, QByteArray bytes, Compression::CompressionType compressionType)
{
switch(compressionType) {
case Uncompressed:
return bytes;
case RLE:
return unRLE(nBytes, bytes);
{
char *dst = new char[unpacked_len];
decode_packbits(bytes.constData(), dst, bytes.length(), unpacked_len);
QByteArray ba(dst, unpacked_len);
delete[] dst;
return ba;
}
case ZIP:
case ZIPWithPrediction:
return unzip(nBytes, bytes);
{
// prepend the expected length of the pixels in big-endian
// format to the byte array as qUncompress expects...
QByteArray b;
QBuffer buf(&b);
quint32 val = ntohl(unpacked_len);
buf.write((char*)&val, 4);
b.append(bytes);
// and let's hope that this is sufficient...
return qUncompress(bytes);
}
default:
qFatal("Cannot uncompress layer data");
qFatal("Cannot uncompress layer data: invalid compression type");
}
......@@ -174,8 +240,24 @@ QByteArray Compression::uncompress(quint32 nBytes, QByteArray bytes, Compression
QByteArray Compression::compress(QByteArray bytes, Compression::CompressionType compressionType)
{
Q_UNUSED(bytes);
Q_UNUSED(compressionType);
if (bytes.size() < 1) return QByteArray();
switch(compressionType) {
case Uncompressed:
return bytes;
case RLE:
{
QByteArray dst;
int packed_len = pack_pb_line(bytes, dst);
Q_ASSERT(packed_len == dst.size());
return dst;
}
case ZIP:
case ZIPWithPrediction:
return qCompress(bytes);
default:
qFatal("Cannot compress layer data: invalid compression type");
}
return QByteArray();
}
......
......@@ -32,7 +32,7 @@ public:
Unknown
};
static QByteArray uncompress(quint32 nBytes, QByteArray bytes, CompressionType compressionType);
static QByteArray uncompress(quint32 unpacked_len, QByteArray bytes, CompressionType compressionType);
static QByteArray compress(QByteArray bytes, CompressionType compressionType);
};
......
......@@ -90,6 +90,37 @@ QString psd_blendmode_to_composite_op(const QString& blendmode)
if (blendmode == "hMix") return COMPOSITE_HARD_MIX; //hard mix
if (blendmode == "pass") return COMPOSITE_PASS_THROUGH; //pass through
return COMPOSITE_UNDEF;
return COMPOSITE_OVER;
}
QString composite_op_to_psd_blendmode(const QString& compositeop)
{
if (compositeop == COMPOSITE_OVER) return "norm"; // normal
if (compositeop == COMPOSITE_DISSOLVE) return "diss"; //dissolve
if (compositeop == COMPOSITE_DARKEN) return "dark"; // darken
if (compositeop == COMPOSITE_LIGHTEN) return "lite"; // lighten
if (compositeop == COMPOSITE_HUE) return "hue " ; // hue
if (compositeop == COMPOSITE_SATURATION) return "sat "; // saturation
if (compositeop == COMPOSITE_COLOR) return "colr"; //color
if (compositeop == COMPOSITE_LUMINIZE) return "lum "; //luminosity
if (compositeop == COMPOSITE_MULT) return "mul "; //multiply
if (compositeop == COMPOSITE_SCREEN) return "scrn"; //screen
if (compositeop == COMPOSITE_OVERLAY) return "over"; //overlay
if (compositeop == COMPOSITE_HARD_LIGHT) return "hLit"; //hard light
if (compositeop == COMPOSITE_SOFT_LIGHT) return "sLit"; //soft light
if (compositeop == COMPOSITE_DIFF) return "diff"; //difference
if (compositeop == COMPOSITE_EXCLUSION) return "smud"; //exclusion
if (compositeop == COMPOSITE_DIVIDE) return "div "; // color dodge
if (compositeop == COMPOSITE_INVERTED_DIVIDE ) return "idiv"; //color burn
if (compositeop == COMPOSITE_BURN) return "lbrn"; //linear burn
if (compositeop == COMPOSITE_DODGE ) return "lddg"; //linear dodge
if (compositeop == COMPOSITE_VIVID_LIGHT) return "vLit"; //vivid light
if (compositeop == COMPOSITE_LINEAR_LIGHT) return "lLit"; //linear light
if (compositeop == COMPOSITE_PIN_LIGHT) return "pLit"; // pin light
if (compositeop == COMPOSITE_HARD_MIX) return "hMix"; //hard mix
if (compositeop == COMPOSITE_PASS_THROUGH) return "pass"; //pass through
return "norm";
}
......@@ -87,4 +87,5 @@ QPair<QString, QString> psd_colormode_to_colormodelid(PSDColorMode colormode, qu
* Convert the Photoshop blend mode strings to Pigment compositeop id's
*/
QString psd_blendmode_to_composite_op(const QString& blendmode);
QString composite_op_to_psd_blendmode(const QString& compositeOp);
#endif // PSD_H
......@@ -58,6 +58,9 @@ bool PSDColorModeBlock::read(QIODevice* io)
i += 2;
}
}
else {
duotoneSpecification = data;
}
return valid();
}
......@@ -65,14 +68,27 @@ bool PSDColorModeBlock::read(QIODevice* io)
bool PSDColorModeBlock::write(QIODevice* io)