Exemple #1
0
void PSDUtilsTest::test_psdread_pascalstring()
{
    QBuffer buf;

    QString s;
    QString r;

    // test null string
    buf.open(QBuffer::ReadWrite);
    QVERIFY(psdwrite_pascalstring(&buf, s));
    buf.close();
    buf.open(QBuffer::ReadOnly);
    psdread_pascalstring(&buf, r, 2);
    QCOMPARE(r, s);
    QVERIFY(buf.bytesAvailable() == 0);

    // test even string
    buf.close();
    buf.buffer().clear();
    r.clear();
    buf.open(QBuffer::ReadWrite);
    s = QString("bl");
    QVERIFY(psdwrite_pascalstring(&buf, s));
    buf.close();
    buf.open(QBuffer::ReadOnly);
    psdread_pascalstring(&buf, r, 1);
    QCOMPARE(r, s);
    QVERIFY(buf.bytesAvailable() == 0);

    // test uneven string
    buf.close();
    buf.buffer().clear();
    r.clear();
    buf.open(QBuffer::ReadWrite);
    s = QString("bla");
    QVERIFY(psdwrite_pascalstring(&buf, s, 2));
    buf.close();
    buf.open(QBuffer::ReadOnly);
    psdread_pascalstring(&buf, r, 2);
    QCOMPARE(r, s);
    dbgKrita << buf.bytesAvailable();
    QVERIFY(buf.bytesAvailable() == 0);
}
Exemple #2
0
void PSDUtilsTest::test_psdwrite_pascalstring()
{
    QBuffer buf;
    buf.open(QBuffer::ReadWrite);

    // test null string
    QString s;
    QVERIFY(psdwrite_pascalstring(&buf, s));
    QCOMPARE(buf.buffer().size(), 2);
    QCOMPARE(buf.buffer().at(0), '\0');
    QCOMPARE(buf.buffer().at(1), '\0');

    buf.close();
    buf.buffer().clear();
    buf.open(QBuffer::ReadWrite);

    // test even string
    s = QString("bl");
    QVERIFY(psdwrite_pascalstring(&buf, s));
    QCOMPARE(buf.buffer().size(), 3);
    QCOMPARE(buf.buffer().at(0), '\2');
    QCOMPARE(buf.buffer().at(1), 'b');
    QCOMPARE(buf.buffer().at(2), 'l');

    buf.close();
    buf.buffer().clear();
    buf.open(QBuffer::ReadWrite);

    // test uneven string
    s = QString("bla");
    QVERIFY(psdwrite_pascalstring(&buf, s));
    QCOMPARE(buf.buffer().size(), 5);
    QCOMPARE(buf.buffer().at(0), '\3');
    QCOMPARE(buf.buffer().at(1), 'b');
    QCOMPARE(buf.buffer().at(2), 'l');
    QCOMPARE(buf.buffer().at(3), 'a');
    QCOMPARE(buf.buffer().at(4), '\0');
}
Exemple #3
0
bool PSDResourceBlock::write(QIODevice* io) const
{

    dbgFile << "Writing Resource Block" << PSDImageResourceSection::idToString((PSDImageResourceSection::PSDResourceID)identifier) << identifier;

    if (resource && !resource->valid()) {
        error = QString("Cannot write an invalid Resource Block");
        return false;
    }

    if (identifier == PSDImageResourceSection::LAYER_STATE ||
        identifier == PSDImageResourceSection::LAYER_GROUP ||
        identifier == PSDImageResourceSection::LAYER_COMPS ||
        identifier == PSDImageResourceSection::LAYER_GROUP_ENABLED_ID ||
        identifier == PSDImageResourceSection::LAYER_SELECTION_ID) {

        /**
         * We can actually handle LAYER_SELECTION_ID. It consists
         * of a number of layers and a list of IDs to select, which
         * are retrieved from 'lyid' additional layer block.
         */
        dbgFile << "Skip writing resource block" << identifier << displayText();
        return true;
    }

    QByteArray ba;

    // createBlock returns true by default but does not change the data.
    if (resource && !resource->createBlock(ba)) {
        error = resource->error;
        return false;
    }
    else if (!resource) {
        // reconstruct from the data
        QBuffer buf(&ba);
        buf.open(QBuffer::WriteOnly);
        buf.write("8BIM", 4);
        psdwrite(&buf, identifier);
        psdwrite_pascalstring(&buf, name);
        psdwrite(&buf, dataSize);
        buf.write(data);
        buf.close();
    }
    if (io->write(ba.constData(), ba.size()) != ba.size()) {
        error = QString("Could not write complete resource");
        return false;
    }

    return true;
}
void PSDLayerRecord::write(QIODevice* io,
                           KisPaintDeviceSP layerContentDevice,
                           KisNodeSP onlyTransparencyMask,
                           const QRect &maskRect,
                           psd_section_type sectionType,
                           const QDomDocument &stylesXmlDoc)
{
    dbgFile << "writing layer info record" << "at" << io->pos();

    m_layerContentDevice = layerContentDevice;
    m_onlyTransparencyMask = onlyTransparencyMask;
    m_onlyTransparencyMaskRect = maskRect;

    dbgFile << "saving layer record for " << layerName << "at pos" << io->pos();
    dbgFile << "\ttop" << top << "left" << left << "bottom" << bottom << "right" << right << "number of channels" << nChannels;
    Q_ASSERT(left <= right);
    Q_ASSERT(top <= bottom);
    Q_ASSERT(nChannels > 0);

    try {
        const QRect layerRect(left, top, right - left, bottom - top);
        KisAslWriterUtils::writeRect(layerRect, io);

        {
            quint16 realNumberOfChannels = nChannels + bool(m_onlyTransparencyMask);
            SAFE_WRITE_EX(io, realNumberOfChannels);
        }

        foreach(ChannelInfo *channel, channelInfoRecords) {
            SAFE_WRITE_EX(io, (quint16)channel->channelId);

            channel->channelInfoPosition = io->pos();

            // to be filled in when we know how big channel block is
            const quint32 fakeChannelSize = 0;
            SAFE_WRITE_EX(io, fakeChannelSize);
        }

        if (m_onlyTransparencyMask) {
            const quint16 userSuppliedMaskChannelId = -2;
            SAFE_WRITE_EX(io, userSuppliedMaskChannelId);

            m_transparencyMaskSizeOffset = io->pos();

            const quint32 fakeTransparencyMaskSize = 0;
            SAFE_WRITE_EX(io, fakeTransparencyMaskSize);
        }

        // blend mode
        dbgFile  << ppVar(blendModeKey) << ppVar(io->pos());

        KisAslWriterUtils::writeFixedString("8BIM", io);
        KisAslWriterUtils::writeFixedString(blendModeKey, io);

        SAFE_WRITE_EX(io, opacity);
        SAFE_WRITE_EX(io, clipping); // unused

        // visibility and protection
        quint8 flags = 0;
        if (transparencyProtected) flags |= 1;
        if (!visible) flags |= 2;
        if (irrelevant) {
            flags |= (1 << 3) | (1 << 4);
        }

        SAFE_WRITE_EX(io, flags);

        {
            quint8 padding = 0;
            SAFE_WRITE_EX(io, padding);
        }

        {
            // extra fields with their own length tag
            KisAslWriterUtils::OffsetStreamPusher<quint32> extraDataSizeTag(io);

            if (m_onlyTransparencyMask) {
                {
                    const quint32 layerMaskDataSize = 20; // support simple case only
                    SAFE_WRITE_EX(io, layerMaskDataSize);
                }

                KisAslWriterUtils::writeRect(m_onlyTransparencyMaskRect, io);

                {
                    KIS_ASSERT_RECOVER_NOOP(m_onlyTransparencyMask->paintDevice()->pixelSize() == 1);
                    const quint8 defaultPixel = *m_onlyTransparencyMask->paintDevice()->defaultPixel();
                    SAFE_WRITE_EX(io, defaultPixel);
                }

                {
                    const quint8 maskFlags = 0; // nothing serious
                    SAFE_WRITE_EX(io, maskFlags);

                    const quint16 padding = 0; // 2-byte padding
                    SAFE_WRITE_EX(io, padding);
                }
            } else {
                const quint32 nullLayerMaskDataSize = 0;
                SAFE_WRITE_EX(io, nullLayerMaskDataSize);
            }

            {
                // blending ranges are not implemented yet
                const quint32 nullBlendingRangesSize = 0;
                SAFE_WRITE_EX(io, nullBlendingRangesSize);
            }

            // layer name: Pascal string, padded to a multiple of 4 bytes.
            psdwrite_pascalstring(io, layerName, 4);


            PsdAdditionalLayerInfoBlock additionalInfoBlock(m_header);

            // write 'luni' data block
            additionalInfoBlock.writeLuniBlockEx(io, layerName);

            // write 'lsct' data block
            if (sectionType != psd_other) {
                additionalInfoBlock.writeLsctBlockEx(io, sectionType, isPassThrough, blendModeKey);
            }

            // write 'lfx2' data block
            if (!stylesXmlDoc.isNull()) {
                additionalInfoBlock.writeLfx2BlockEx(io, stylesXmlDoc);
            }
        }
    } catch (KisAslWriterUtils::ASLWriteException &e) {