bool PSDResourceSection::read(QIODevice* io)
{
    quint32 resourceBlockLength = 0;
    if (!psdread(io, &resourceBlockLength)) {
        error = "Could not read resource block length";
        return false;
    }

    dbgFile << "Resource block length" << resourceBlockLength << "starts at" << io->pos();

    QByteArray ba = io->read(resourceBlockLength);
    if ((quint32)ba.size() != resourceBlockLength) {
        error = "Could not read all resources";
        return false;
    }

    QBuffer buf;
    buf.setBuffer(&ba);
    buf.open(QBuffer::ReadOnly);

    while (!buf.atEnd()) {
        PSDResourceBlock* block = new PSDResourceBlock();
        if (!block->read(&buf)) {
            error = "Error reading block: " + block->error;
            return false;
        }
        dbgFile << "resource block created. Type:" << block->identifier << "size"
                << block->dataSize
                << "," << buf.bytesAvailable() << "bytes to go";
        resources[(PSDResourceID)block->identifier] = block;
    }
    return valid();
}
Esempio n. 2
0
bool psdread_pascalstring(QIODevice* io, QString& s, int padding)
{
    quint8 length;
    if (!psdread(io, &length)) {
        return false;
    }

    if (length == 0) {
        // read the padding
        for (int i = 0; i < padding -1; ++i) {
            io->seek(io->pos() + 1);
        }
        return (length == 0);
    }

    QByteArray chars = io->read(length);
    if (chars.length() != length) {
        return false;
    }

    // read padding byte
    quint32 paddedLength = length + 1;
    if (padding > 0) {
        while (paddedLength % padding != 0) {
            if (!io->seek(io->pos() + 1)) {
                return false;
            }
            paddedLength++;
        }
    }

    s.append(QString::fromLatin1(chars));

    return true;
}
Esempio n. 3
0
void PSDUtilsTest::test_psdread_quint32()
{
    QBuffer buf;
    QVERIFY(buf.open(QBuffer::ReadWrite));
    quint32 s = 300000;
    psdwrite(&buf, s);
    buf.close();
    buf.open(QBuffer::ReadOnly);
    quint32 r;
    QVERIFY(psdread(&buf, &r));
    QCOMPARE(r, s);
}
Esempio n. 4
0
void PSDUtilsTest::test_psdread_quint16()
{
    QBuffer buf;
    buf.open(QBuffer::ReadWrite);
    quint16 s = 1024;
    QVERIFY(psdwrite(&buf, s));
    buf.close();
    buf.open(QBuffer::ReadOnly);
    quint16 r;
    QVERIFY(psdread(&buf, &r));
    QCOMPARE(r, s);
}
Esempio n. 5
0
bool psdread_unicodestring(QIODevice *io, QString &s)
{
    quint32 stringlen;
    if (!psdread(io, &stringlen)) {
        return false;
    }

    for (uint i = 0; i < stringlen; ++i) {
        quint16 ch;
        if (!psdread(io, &ch)) {
            return false;
        }

        if (ch != 0) {
            QChar uch(ch);
            s.append(uch);
        }
    }

    return true;
}
Esempio n. 6
0
static int
sdreadblk(PSDunit *unit, SDpart *part, void *a, vlong off, int mbr)
{
	uchar *b;

	assert(a);			/* sdreadblk */
	if(psdread(unit, part, a, unit->secsize, off) != unit->secsize){
		if(Trace)
			print("%s: read %lud at %lld failed\n", unit->name,
				unit->secsize, (vlong)part->start*unit->secsize+off);
		return -1;
	}
	b = a;
	if(mbr && (b[0x1FE] != 0x55 || b[0x1FF] != 0xAA)){
		if(Trace)
			print("%s: bad magic %.2ux %.2ux at %lld\n",
				unit->name, b[0x1FE], b[0x1FF],
				(vlong)part->start*unit->secsize+off);
		return -1;
	}
	return 0;
}
bool PSDLayerRecord::read(QIODevice* io)
{
    dbgFile << "Going to read layer record. Pos:" << io->pos();

    if (!psdread(io, &top)  ||
            !psdread(io, &left) ||
            !psdread(io, &bottom) ||
            !psdread(io, &right) ||
            !psdread(io, &nChannels)) {

        error = "could not read layer record";
        return false;
    }

    dbgFile << "\ttop" << top << "left" << left << "bottom" << bottom << "right" << right << "number of channels" << nChannels;

    Q_ASSERT(top <= bottom);
    Q_ASSERT(left <= right);
    Q_ASSERT(nChannels > 0);


    switch(m_header.colormode) {
    case(Bitmap):
    case(Indexed):
    case(DuoTone):
    case(Grayscale):
    case(MultiChannel):
        if (nChannels < 1) {
            error = QString("Not enough channels. Got: %1").arg(nChannels);
            return false;
        }
        break;
    case(RGB):
    case(CMYK):
    case(Lab):
    default:
        if (nChannels < 3) {
            error = QString("Not enough channels. Got: %1").arg(nChannels);
            return false;
        }
        break;
    };

    if (nChannels > MAX_CHANNELS) {
        error = QString("Too many channels. Got: %1").arg(nChannels);
        return false;
    }

    for (int i = 0; i < nChannels; ++i) {

        if (io->atEnd()) {
            error = "Could not read enough data for channels";
            return false;
        }

        ChannelInfo* info = new ChannelInfo;

        if (!psdread(io, &info->channelId)) {
            error = "could not read channel id";
            delete info;
            return false;
        }
        bool r;
        if (m_header.version == 1) {
            quint32 channelDataLength;
            r = psdread(io, &channelDataLength);
            info->channelDataLength = (quint64)channelDataLength;
        }
        else {
            r = psdread(io, &info->channelDataLength);
        }
        if (!r) {
            error = "Could not read length for channel data";
            delete info;
            return false;
        }

        dbgFile << "\tchannel" << i << "id"
                << channelIdToChannelType(info->channelId, m_header.colormode)
                << "length" << info->channelDataLength
                << "start" << info->channelDataStart
                << "offset" << info->channelOffset
                << "channelInfoPosition" << info->channelInfoPosition;

        channelInfoRecords << info;

    }

    if (!psd_read_blendmode(io, blendModeKey)) {
        error = QString("Could not read blend mode key. Got: %1").arg(blendModeKey);
        return false;
    }

    dbgFile << "\tBlend mode" << blendModeKey << "pos" << io->pos();

    if (!psdread(io, &opacity)) {
        error = "Could not read opacity";
        return false;
    }

    dbgFile << "\tOpacity" << opacity << io->pos();

    if (!psdread(io, &clipping)) {
        error = "Could not read clipping";
        return false;
    }

    dbgFile << "\tclipping" << clipping << io->pos();

    quint8 flags;
    if (!psdread(io, &flags)) {
        error = "Could not read flags";
        return false;
    }
    dbgFile << "\tflags" << flags << io->pos();

    transparencyProtected = flags & 1 ? true : false;

    dbgFile << "\ttransparency protected" << transparencyProtected;

    visible = flags & 2 ? false : true;

    dbgFile << "\tvisible" << visible;

    if (flags & 8) {
        irrelevant = flags & 16 ? true : false;
    }
    else {
        irrelevant = false;
    }

    dbgFile << "\tirrelevant" << irrelevant;

    dbgFile << "\tfiller at " << io->pos();

    quint8 filler;
    if (!psdread(io, &filler) || filler != 0) {
        error = "Could not read padding";
        return false;
    }

    dbgFile << "\tGoing to read extra data length" << io->pos();

    quint32 extraDataLength;
    if (!psdread(io, &extraDataLength) || io->bytesAvailable() < extraDataLength) {
        error = QString("Could not read extra layer data: %1 at pos %2").arg(extraDataLength).arg(io->pos());
        return false;
    }

    dbgFile << "\tExtra data length" << extraDataLength;

    if (extraDataLength > 0) {

        dbgFile << "Going to read extra data field. Bytes available: "
                << io->bytesAvailable()
                << "pos" << io->pos();

        quint32 layerMaskLength = 1; // invalid...
        if (!psdread(io, &layerMaskLength) ||
                io->bytesAvailable() < layerMaskLength ||
                !(layerMaskLength == 0 || layerMaskLength == 20 || layerMaskLength == 36)) {
            error = QString("Could not read layer mask length: %1").arg(layerMaskLength);
            return false;
        }

        memset(&layerMask, 0, sizeof(LayerMaskData));

        if (layerMaskLength == 20 || layerMaskLength == 36) {
            if (!psdread(io, &layerMask.top)  ||
                    !psdread(io, &layerMask.left) ||
                    !psdread(io, &layerMask.bottom) ||
                    !psdread(io, &layerMask.right) ||
                    !psdread(io, &layerMask.defaultColor) ||
                    !psdread(io, &flags)) {

                error = "could not read mask record";
                return false;
            }
        }
        if (layerMaskLength == 20) {
            quint16 padding;
            if (!psdread(io, &padding)) {
                error = "Could not read layer mask padding";
                return false;
            }
        }


        if (layerMaskLength == 36 ) {
            if (!psdread(io, &flags) ||
                    !psdread(io, &layerMask.defaultColor) ||
                    !psdread(io, &layerMask.top)  ||
                    !psdread(io, &layerMask.left) ||
                    !psdread(io, &layerMask.bottom) ||
                    !psdread(io, &layerMask.top)) {

                error = "could not read 'real' mask record";
                return false;
            }
        }

        layerMask.positionedRelativeToLayer = flags & 1 ? true : false;
        layerMask.disabled = flags & 2 ? true : false;
        layerMask.invertLayerMaskWhenBlending = flags & 4 ? true : false;

        dbgFile << "\tRead layer mask/adjustment layer data. Length of block:"
                << layerMaskLength << "pos" << io->pos();

        // layer blending thingies
        quint32 blendingDataLength;
        if (!psdread(io, &blendingDataLength) || io->bytesAvailable() < blendingDataLength) {
            error = "Could not read extra blending data.";
            return false;
        }

        //dbgFile << "blending block data length" << blendingDataLength << ", pos" << io->pos();

        blendingRanges.data = io->read(blendingDataLength);
        if ((quint32)blendingRanges.data.size() != blendingDataLength) {
            error = QString("Got %1 bytes for the blending range block, needed %2").arg(blendingRanges.data.size(), blendingDataLength);
        }
        /*
        // XXX: reading this block correctly failed, I have more channel ranges than I'd expected.

        if (!psdread(io, &blendingRanges.blackValues[0]) ||
            !psdread(io, &blendingRanges.blackValues[1]) ||
            !psdread(io, &blendingRanges.whiteValues[0]) ||
            !psdread(io, &blendingRanges.whiteValues[1]) ||
            !psdread(io, &blendingRanges.compositeGrayBlendDestinationRange)) {

            error = "Could not read blending black/white values";
            return false;
        }

        for (int i = 0; i < nChannels; ++i) {
            quint32 src;
            quint32 dst;
            if (!psdread(io, &src) || !psdread(io, &dst)) {
                error = QString("could not read src/dst range for channel %1").arg(i);
                return false;
            }
            dbgFile << "\tread range " << src << "to" << dst << "for channel" << i;
            blendingRanges.sourceDestinationRanges << QPair<quint32, quint32>(src, dst);
        }
        */
        dbgFile << "\tGoing to read layer name at" << io->pos();
        quint8 layerNameLength;
        if (!psdread(io, &layerNameLength)) {
            error = "Could not read layer name length";
            return false;
        }

        dbgFile << "\tlayer name length unpadded" << layerNameLength << "pos" << io->pos();
        layerNameLength = ((layerNameLength + 1 + 3) & ~0x03) - 1;

        dbgFile << "\tlayer name length padded" << layerNameLength << "pos" << io->pos();
        layerName = io->read(layerNameLength);
        dbgFile << "\tlayer name" << layerName << io->pos();

        if (!infoBlocks.read(io)) {
            error = infoBlocks.error;
            return false;
        }

        if (infoBlocks.keys.contains("luni") && !infoBlocks.unicodeLayerName.isEmpty()) {
            layerName = infoBlocks.unicodeLayerName;
        }

    }

    return valid();
}
Esempio n. 8
0
/*
 * To facilitate booting from CDs, we create a partition for
 * the FAT filesystem image embedded in a bootable CD.
 */
static int
part9660(PSDunit *unit)
{
	ulong a, n, i, j;
	uchar drecsz;
	uchar *p;
	uchar buf[Maxsec];
	Drec *rootdrec, *drec;
	Voldesc *v;
	static char stdid[] = "CD001\x01";

	if(unit->secsize == 0)
		unit->secsize = Cdsec;
	if(unit->secsize != Cdsec)
		return -1;

	if(psdread(unit, &unit->part[0], buf, Cdsec, VOLDESC*Cdsec) < 0)
		return -1;
	if(buf[0] != PrimaryIso ||
	    memcmp((char*)buf+1, stdid, sizeof stdid - 1) != 0)
		return -1;

	v = (Voldesc *)buf;
	rootdrec = (Drec *)v->z.desc.rootdir;
	assert(rootdrec);
	p = rootdrec->addr;
	a = p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24);
	p = rootdrec->size;
	n = p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24);
//	print("part9660: read %uld %uld\n", n, a);	/* debugging */

	if(n < Cdsec){
		print("warning: bad boot file size %ld in iso directory", n);
		n = Cdsec;
	}

	drec = nil;
	for(j = 0; j*Cdsec < n; j++){
		if(psdread(unit, &unit->part[0], buf, Cdsec, (a + j)*Cdsec) < 0)
			return -1;
		for(i = 0; i + j*Cdsec <= n && i < Cdsec; i += drecsz){
			drec = (Drec *)&buf[i];
			drecsz = drec->reclen;
			if(drecsz == 0 || drecsz + i > Cdsec)
				break;
			if(cistrncmp("bootdisk.img", (char *)drec->name, 12) == 0)
				goto Found;
		}
	}
Found:
	if(j*Cdsec >= n || drec == nil)
		return -1;

	p = drec->addr;
	a = p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24);
	p = drec->size;
	n = p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24);

	print("found partition %s!9fat; %lud+%lud\n", unit->name, a, n);
	n /= Cdsec;
	psdaddpart(unit, "9fat", a, a+n);
	return 0;
}
Esempio n. 9
0
bool PSDResourceBlock::read(QIODevice* io)
{
    dbgFile << "Reading resource block";
    if (io->atEnd()) {
        error = "Could not read resource block: no bytes left.";
        return false;
    }

    QByteArray b;
    b = io->read(4);
    if(b.size() != 4 || QString(b) != "8BIM") {
        error = QString("Could not read resource block signature. Got %1.")
                .arg(QString(b));
        return false;
    }

    if (!psdread(io, &identifier)) {
        error = "Could not read resource block identifier";
        return false;
    }

    dbgFile << "\tresource block identifier" << PSDImageResourceSection::idToString((PSDImageResourceSection::PSDResourceID)identifier) << identifier;

    m_type = QString("PSD Resource Block: %1").arg(identifier);


    if (!psdread_pascalstring(io, name, 2)) {
        error = "Could not read name of resource block";
        return false;
    }

    dbgFile << "\tresource block name" << name;

    if (!psdread(io, &dataSize)) {
        error = QString("Could not read datasize for resource block with name %1 of type %2").arg(name).arg(identifier);
        return false;
    }

    if ((dataSize & 0x01) != 0) {
        dataSize++;
    }

    dbgFile << "\tresource block size" << dataSize;

    m_description = PSDImageResourceSection::idToString((PSDImageResourceSection::PSDResourceID)identifier);

    data = io->read(dataSize);
    if (data.size() != (int)dataSize) {
        error = QString("Could not read data for resource block with name %1 of type %2").arg(name).arg(identifier);
        return false;
    }

    m_annotation = data;

    switch (identifier) {
//    case PSDImageResourceSection::MAC_PRINT_INFO:
//        resource = new MAC_PRINT_INFO_1001;
//        break;
    case PSDImageResourceSection::RESN_INFO:
        resource = new RESN_INFO_1005;
        break;
//    case PSDImageResourceSection::ALPHA_NAMES:
//        resource = new ALPHA_NAMES_1006;
//        break;
//    case PSDImageResourceSection::DISPLAY_INFO:
//        resource = new DISPLAY_INFO_1007;
//        break;
//    case PSDImageResourceSection::CAPTION:
//        resource = new CAPTION_1008;
//        break;
//    case PSDImageResourceSection::BORDER_INFO:
//        resource = new BORDER_INFO_1009;
//        break;
//    case PSDImageResourceSection::BACKGROUND_COL:
//        resource = new BACKGROUND_COL_1010;
//        break;
//    case PSDImageResourceSection::PRINT_FLAGS:
//        resource = new PRINT_FLAGS_1011;
//        break;
//    case PSDImageResourceSection::GREY_HALFTONE:
//        resource = new GREY_HALFTONE_1012;
//        break;
//    case PSDImageResourceSection::COLOR_HALFTONE:
//        resource = new COLOR_HALFTONE_1013;
//        break;
//    case PSDImageResourceSection::DUOTONE_HALFTONE:
//        resource = new DUOTONE_HALFTONE_1014;
//        break;
//    case PSDImageResourceSection::GREY_XFER:
//        resource = new GREY_XFER_1015;
//        break;
//    case PSDImageResourceSection::COLOR_XFER:
//        resource = new COLOR_XFER_1016;
//        break;
//    case PSDImageResourceSection::DUOTONE_XFER:
//        resource = new DUOTONE_XFER_1017;
//        break;
//    case PSDImageResourceSection::DUOTONE_INFO:
//        resource = new DUOTONE_INFO_1018;
//        break;
//    case PSDImageResourceSection::EFFECTIVE_BW:
//        resource = new EFFECTIVE_BW_1019;
//        break;
//    case PSDImageResourceSection::EPS_OPT:
//        resource = new  EPS_OPT_1021;
//        break;
//    case PSDImageResourceSection::QUICK_MASK:
//        resource = new QUICK_MASK_1022;
//        break;
//    case PSDImageResourceSection::LAYER_STATE:
//        resource = new  LAYER_STATE_1024;
//        break;
//    case PSDImageResourceSection::WORKING_PATH:
//        resource = new WORKING_PATH_1025;
//        break;
//    case PSDImageResourceSection::LAYER_GROUP:
//        resource = new LAYER_GROUP_1026;
//        break;
//    case PSDImageResourceSection::IPTC_NAA_DATA:
//        resource = new IPTC_NAA_DATA_1028;
//        break;
//    case PSDImageResourceSection::IMAGE_MODE_RAW:
//        resource = new IMAGE_MODE_RAW_1029;
//        break;
//    case PSDImageResourceSection::JPEG_QUAL:
//        resource = new JPEG_QUAL_1030;
//        break;
//    case PSDImageResourceSection::GRID_GUIDE:
//        resource = new GRID_GUIDE_1032;
//        break;
//    case PSDImageResourceSection::THUMB_RES:
//        resource = new THUMB_RES_1033;
//        break;
//    case PSDImageResourceSection::COPYRIGHT_FLG:
//        resource = new COPYRIGHT_FLG_1034;
//        break;
//    case PSDImageResourceSection::URL:
//        resource = new URL_1035;
//        break;
//    case PSDImageResourceSection::THUMB_RES2:
//        resource = new THUMB_RES2_1036;
//        break;
    case PSDImageResourceSection::GLOBAL_ANGLE:
        resource = new GLOBAL_ANGLE_1037;
        break;
//    case PSDImageResourceSection::COLOR_SAMPLER:
//        resource = new COLOR_SAMPLER_1038;
//        break;
    case PSDImageResourceSection::ICC_PROFILE:
        resource = new ICC_PROFILE_1039;
        break;
//    case PSDImageResourceSection::WATERMARK:
//        resource = new WATERMARK_1040;
//        break;
//    case PSDImageResourceSection::ICC_UNTAGGED:
//        resource = new ICC_UNTAGGED_1041;
//        break;
//    case PSDImageResourceSection::EFFECTS_VISIBLE:
//        resource = new EFFECTS_VISIBLE_1042;
//        break;
//    case PSDImageResourceSection::SPOT_HALFTONE:
//        resource = new SPOT_HALFTONE_1043;
//        break;
//    case PSDImageResourceSection::DOC_IDS:
//        resource = new DOC_IDS_1044;
//        break;
//    case PSDImageResourceSection::ALPHA_NAMES_UNI:
//        resource = new ALPHA_NAMES_UNI_1045;
//        break;
//    case PSDImageResourceSection::IDX_COL_TAB_CNT:
//        resource = new IDX_COL_TAB_CNT_1046;
//        break;
//    case PSDImageResourceSection::IDX_TRANSPARENT:
//        resource = new IDX_TRANSPARENT_1047;
//        break;
    case PSDImageResourceSection::GLOBAL_ALT:
        resource = new GLOBAL_ALT_1049;
        break;
//    case PSDImageResourceSection::SLICES:
//        resource = new SLICES_1050;
//        break;
//    case PSDImageResourceSection::WORKFLOW_URL_UNI:
//        resource = new WORKFLOW_URL_UNI_1051;
//        break;
//    case PSDImageResourceSection::JUMP_TO_XPEP:
//        resource = new JUMP_TO_XPEP_1052;
//        break;
//    case PSDImageResourceSection::ALPHA_ID:
//        resource = new ALPHA_ID_1053;
//        break;
//    case PSDImageResourceSection::URL_LIST_UNI:
//        resource = new URL_LIST_UNI_1054;
//        break;
//    case PSDImageResourceSection::VERSION_INFO:
//        resource = new VERSION_INFO_1057;
//        break;
//    case PSDImageResourceSection::EXIF_DATA:
//        resource = new EXIF_DATA_1058;
//        break;
//    case PSDImageResourceSection::XMP_DATA:
//        resource = new XMP_DATA_1060;
//        break;
//    case PSDImageResourceSection::PATH_INFO_FIRST:
//        resource = new PATH_INFO_FIRST_2000;
//        break;
//    case PSDImageResourceSection::PATH_INFO_LAST:
//        resource = new PATH_INFO_LAST_2998;
//        break;
//    case PSDImageResourceSection::CLIPPING_PATH:
//        resource = new CLIPPING_PATH_2999;
//        break;
//    case PSDImageResourceSection::PRINT_FLAGS_2:
//        resource = new PRINT_FLAGS_2_10000;
//        break;
    default:
        ;
    }

    if (resource) {
        resource->interpretBlock(data);
    }

    return valid();
}
Esempio n. 10
0
bool PSDLayerSection::read(QIODevice* io)
{
    dbgFile << "reading layer section. Pos:" << io->pos() <<  "bytes left:" << io->bytesAvailable();

    layerMaskBlockSize = 0;
    if (m_header.version == 1) {
        quint32 _layerMaskBlockSize = 0;
        if (!psdread(io, &_layerMaskBlockSize) || _layerMaskBlockSize > (quint64)io->bytesAvailable()) {
            error = QString("Could not read layer + mask block size. Got %1. Bytes left %2")
                    .arg(_layerMaskBlockSize).arg(io->bytesAvailable());
            return false;
        }
        layerMaskBlockSize = _layerMaskBlockSize;
    }
    else if (m_header.version == 2) {
        if (!psdread(io, &layerMaskBlockSize) || layerMaskBlockSize > (quint64)io->bytesAvailable()) {
            error = QString("Could not read layer + mask block size. Got %1. Bytes left %2")
                    .arg(layerMaskBlockSize).arg(io->bytesAvailable());
            return false;
        }
    }
    dbgFile << "layer + mask section size" << layerMaskBlockSize;

    if (layerMaskBlockSize == 0) {
        dbgFile << "No layer + mask info, so no layers, only a background layer";
        return true;
    }

    dbgFile << "reading layer info block. Bytes left" << io->bytesAvailable() << "position" << io->pos();
    if (m_header.version == 1) {
        quint32 _layerInfoSize;
        if (!psdread(io, &_layerInfoSize) || _layerInfoSize > (quint64)io->bytesAvailable()) {
            error = "Could not read layer section size";
            return false;
        }
        layerInfoSize = _layerInfoSize;
    }
    else if (m_header.version == 2) {
        if (!psdread(io, &layerInfoSize) || layerInfoSize > (quint64)io->bytesAvailable()) {
            error = "Could not read layer section size";
            return false;
        }
    }
    dbgFile << "Layer info block size" << layerInfoSize;


    if (layerInfoSize > 0 ) {

        // rounded to a multiple of 2
        if ((layerInfoSize & 0x01) != 0) {
            layerInfoSize++;
        }
        dbgFile << "Layer info block size after rounding" << layerInfoSize;

        if (!psdread(io, &nLayers) || nLayers == 0) {
            error = QString("Could not read read number of layers or no layers in image. %1").arg(nLayers);
            return false;
        }

        if (nLayers < 0) {
            hasTransparency = true; // first alpha channel is the alpha channel of the projection.
            nLayers = -nLayers;
        }
        else {
            hasTransparency = false;
        }
        dbgFile << "transparency" << hasTransparency;

        dbgFile << "Number of layers" << nLayers << "transparency" << hasTransparency;

        for (int i = 0; i < nLayers; ++i) {

            dbgFile << "Going to read layer " << i << "pos" << io->pos();
            PSDLayerRecord *layerRecord = new PSDLayerRecord(m_header);
            if (!layerRecord->read(io)) {
                error = QString("Could not load layer %1: %2").arg(i).arg(layerRecord->error);
                return false;
            }
            dbgFile << "Read layer" << i << layerRecord->layerName << "blending mode"
                    << layerRecord->blendModeKey << io->pos();
            layers << layerRecord;
        }
    }

    // get the positions for the channels belonging to each layer
    for (int i = 0; i < nLayers; ++i) {

        dbgFile << "Going to seek channel positions for layer" << i << "pos" << io->pos();
        Q_ASSERT(i < layers.size());
        if (i > layers.size()) {
            error = QString("Expected layer %1, but only have %2 layers").arg(i).arg(layers.size());
            return false;
        }

        PSDLayerRecord *layerRecord = layers.at(i);

        for (int j = 0; j < layerRecord->nChannels; ++j) {
            // save the current location so we can jump beyond this block later on.
            quint64 channelStartPos = io->pos();

            dbgFile << "\tReading channel image data for" << j << "from pos" << io->pos();

            Q_ASSERT(j < layerRecord->channelInfoRecords.size());
            if (j > layerRecord->channelInfoRecords.size()) {
                error = QString("Expected channel %1, but only have %2 channels for layer %3")
                        .arg(j)
                        .arg(layerRecord->channelInfoRecords.size())
                        .arg(i);
                return false;
            }

            PSDLayerRecord::ChannelInfo* channelInfo = layerRecord->channelInfoRecords.at(j);

            quint16 compressionType;
            if (!psdread(io, &compressionType)) {
                error = "Could not read compression type for channel";
                return false;
            }
            channelInfo->compressionType = (Compression::CompressionType)compressionType;
            dbgFile << "\t\tChannel" << j << "has compression type" << compressionType;

            // read the rle row lengths;
            if (channelInfo->compressionType == Compression::RLE) {
                for(quint64 row = 0; row < (layerRecord->bottom - layerRecord->top); ++row) {

                    //dbgFile << "Reading the RLE bytecount position of row" << row << "at pos" << io->pos();

                    quint32 byteCount;
                    if (m_header.version == 1) {
                        quint16 _byteCount;
                        if (!psdread(io, &_byteCount)) {
                            error = QString("Could not read byteCount for rle-encoded channel");
                            return 0;
                        }
                        byteCount = _byteCount;
                    }
                    else {
                        if (!psdread(io, &byteCount)) {
                            error = QString("Could not read byteCount for rle-encoded channel");
                            return 0;
                        }
                    }
                    //qDebug() << "rle byte count" << byteCount;
                    channelInfo->rleRowLengths << byteCount;
                }
            }

            // we're beyond all the length bytes, rle bytes and whatever, this is the
            // location of the real pixel data
            channelInfo->channelDataStart = io->pos();

            dbgFile << "\t\tstart" << channelStartPos
                    << "data start" << channelInfo->channelDataStart
                    << "data length" << channelInfo->channelDataLength
                    << "pos" << io->pos();

            // make sure we are at the start of the next channel data block
            io->seek(channelStartPos + channelInfo->channelDataLength);

            // this is the length of the actual channel data bytes
            channelInfo->channelDataLength = channelInfo->channelDataLength - (channelInfo->channelDataStart - channelStartPos);

            dbgFile << "\t\tchannel record" << j << "for layer" << i << "with id" << channelInfo->channelId
                    << "starting postion" << channelInfo->channelDataStart
                    << "with length" << channelInfo->channelDataLength
                    << "and has compression type" << channelInfo->compressionType;

        }
    }

    quint32 globalMaskBlockLength;
    if (!psdread(io, &globalMaskBlockLength) || globalMaskBlockLength > (quint64)io->bytesAvailable()) {
        error = "Could not read global mask info block";
        return false;
    }

    if (globalMaskBlockLength > 0) {

        if (!psdread(io, &overlayColorSpace)) {
            error = "Could not read global mask info overlay colorspace";
            return false;
        }

        for (int i = 0; i < 4; ++i) {
            if (!psdread(io, &colorComponents[i])) {
                error = QString("Could not read mask info visualizaion color component %1").arg(i);
                return false;
            }
        }

        if (!psdread(io, &opacity)) {
            error = "Could not read global mask info visualization opacity";
            return false;
        }

        if (!psdread(io, &kind)) {
            error = "Could not read global mask info visualization type";
            return false;
        }
    }

    return valid();
}
Esempio n. 11
0
bool PSDImageData::read(QIODevice *io, KisPaintDeviceSP dev ) {



    psdread(io, &m_compression);
    quint64 start = io->pos();
    m_channelSize = m_header->channelDepth/8;
    m_channelDataLength = m_header->height * m_header->width * m_channelSize;

    dbgFile << "Reading Image Data Block: compression" << m_compression << "channelsize" << m_channelSize << "number of channels" << m_header->nChannels;

    switch (m_compression) {

    case 0: // Uncompressed

        for (int channel = 0; channel < m_header->nChannels; channel++) {
            m_channelOffsets << 0;
            ChannelInfo channelInfo;
            channelInfo.channelId = channel;
            channelInfo.compressionType = Compression::Uncompressed;
            channelInfo.channelDataStart = start;
            channelInfo.channelDataLength = m_header->width * m_header->height * m_channelSize;
            start += channelInfo.channelDataLength;
            m_channelInfoRecords.append(channelInfo);

        }

        break;

    case 1: // RLE
    {
        quint32 rlelength = 0;

        // The start of the actual channel data is _after_ the RLE rowlengths block
        if (m_header->version == 1) {
            start += m_header->nChannels * m_header->height * 2;
        }
        else if (m_header->version == 2) {
            start += m_header->nChannels * m_header->height * 4;
        }

        for (int channel = 0; channel < m_header->nChannels; channel++) {
            m_channelOffsets << 0;
            quint32 sumrlelength = 0;
            ChannelInfo channelInfo;
            channelInfo.channelId = channel;
            channelInfo.channelDataStart = start;
            channelInfo.compressionType = Compression::RLE;
            for (quint32 row = 0; row < m_header->height; row++ ) {
                if (m_header->version == 1) {
                    psdread(io,(quint16*)&rlelength);
                }
                else if (m_header->version == 2) {
                    psdread(io,&rlelength);
                }
                channelInfo.rleRowLengths.append(rlelength);
                sumrlelength += rlelength;
            }
            channelInfo.channelDataLength = sumrlelength;
            start += channelInfo.channelDataLength;
            m_channelInfoRecords.append(channelInfo);
        }

        break;
    }
    case 2: // ZIP without prediction
    case 3: // ZIP with prediction
    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);
        }

        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;
        }

    }

    return true;
}
Esempio n. 12
0
bool PSDImageData::read(QIODevice *io, KisPaintDeviceSP dev ) {
    psdread(io, &m_compression);
    quint64 start = io->pos();
    m_channelSize = m_header->channelDepth/8;
    m_channelDataLength = m_header->height * m_header->width * m_channelSize;

    switch (m_compression) {

    case 0: // Uncompressed

        for (int channel = 0; channel < m_header->nChannels; channel++) {
            m_channelOffsets << 0;
            ChannelInfo channelInfo;
            channelInfo.channelId = channel;
            channelInfo.compressionType = Compression::Uncompressed;
            channelInfo.channelDataStart = start;
            channelInfo.channelDataLength = m_header->width * m_header->height * m_channelSize;
            start += channelInfo.channelDataLength;
            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 1: // RLE
    {

        quint32 rlelength = 0;

        // The start of the actual channel data is _after_ the RLE rowlengths block
        if (m_header->version == 1) {
            start += m_header->nChannels * m_header->height * 2;
        }
        else if (m_header->version == 2) {
            start += m_header->nChannels * m_header->height * 4;
        }

        for (int channel = 0; channel < m_header->nChannels; channel++) {
            m_channelOffsets << 0;
            quint32 sumrlelength = 0;
            ChannelInfo channelInfo;
            channelInfo.channelId = channel;
            channelInfo.channelDataStart = start;
            channelInfo.compressionType = Compression::RLE;
            for (quint32 row = 0; row < m_header->height; row++ ) {
                if (m_header->version == 1) {
                    psdread(io,(quint16*)&rlelength);
                }
                else if (m_header->version == 2) {
                    psdread(io,&rlelength);
                }
                channelInfo.rleRowLengths.append(rlelength);
                sumrlelength += rlelength;
            }
            channelInfo.channelDataLength = sumrlelength;
            start += channelInfo.channelDataLength;
            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

        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;
        }
        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;
        }

        break;
    default:
        break;
    }

    return true;
}