~ubuntu-branches/ubuntu/raring/calligra/raring-proposed

« back to all changes in this revision

Viewing changes to krita/plugins/formats/psd/psd_layer_record.cpp

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2013-01-15 17:26:10 UTC
  • mfrom: (1.1.17)
  • Revision ID: package-import@ubuntu.com-20130115172610-b193s9546hyssmym
Tags: 1:2.5.94-0ubuntu1
New upstream RC release

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
#include <QStringList>
26
26
 
27
27
#include <kis_debug.h>
 
28
#include <kis_node.h>
 
29
#include "kis_iterator_ng.h"
 
30
#include <kis_paint_layer.h>
28
31
 
29
32
#include "psd_utils.h"
30
33
#include "psd_header.h"
33
36
#include <KoColorSpace.h>
34
37
#include <KoColorSpaceMaths.h>
35
38
#include <KoColorSpaceTraits.h>
36
 
#include "kis_iterator_ng.h"
 
39
 
 
40
#include <netinet/in.h> // htonl
37
41
 
38
42
// Just for pretty debug messages
39
43
QString channelIdToChannelType(int channelId, PSDColorMode colormode)
131
135
            return QString("WARNING: %1").arg(channelId);
132
136
        case RGB:
133
137
        case RGB48:
134
 
            return QString("WARNING: %1").arg(channelId);
 
138
            return QString("alpha: %1").arg(channelId);
135
139
        case Lab:
136
140
        case Lab48:
137
 
            return QString("WARNING: %1").arg(channelId);
 
141
            return QString("alpha: %1").arg(channelId);
138
142
        case CMYK:
139
143
        case CMYK64:
140
144
            return "Key";
154
158
}
155
159
 
156
160
PSDLayerRecord::PSDLayerRecord(const PSDHeader& header)
157
 
    : m_header(header)
 
161
    : top(0)
 
162
    , left(0)
 
163
    , bottom(0)
 
164
    , right(0)
 
165
    , nChannels(0)
 
166
    , opacity(0)
 
167
    , clipping(0)
 
168
    , transparencyProtected(false)
 
169
    , visible(true)
 
170
    , irrelevant(false)
 
171
    , layerName("UNINITIALIZED")
 
172
    , m_header(header)
158
173
{
159
174
}
160
175
 
174
189
 
175
190
    dbgFile << "\ttop" << top << "left" << left << "bottom" << bottom << "right" << right << "number of channels" << nChannels;
176
191
 
 
192
    Q_ASSERT(top <= bottom);
 
193
    Q_ASSERT(left <= right);
 
194
    Q_ASSERT(nChannels > 0);
 
195
 
 
196
 
177
197
    switch(m_header.colormode) {
178
198
    case(Bitmap):
179
199
    case(Indexed):
208
228
            return false;
209
229
        }
210
230
 
211
 
        ChannelInfo* info = new ChannelInfo();
212
 
        info->compressionType = Compression::Unknown;
213
 
        info->channelId = -1;
214
 
        info->channelDataLength = 0;
215
 
        info->channelDataStart = 0;
 
231
        ChannelInfo* info = new ChannelInfo;
216
232
 
217
233
        if (!psdread(io, &info->channelId)) {
218
234
            error = "could not read channel id";
234
250
            return false;
235
251
        }
236
252
 
237
 
        dbgFile << "\tchannel" << i << "id"
238
 
                << channelIdToChannelType(info->channelId, m_header.colormode)
239
 
                << "length" << info->channelDataLength;
 
253
//        dbgFile << "\tchannel" << i << "id"
 
254
//                << channelIdToChannelType(info->channelId, m_header.colormode)
 
255
//                << "length" << info->channelDataLength
 
256
//                << "start" << info->channelDataStart
 
257
//                << "offset" << info->channelOffset
 
258
//                << "channelInfoPosition" << info->channelInfoPosition;
 
259
 
240
260
        channelInfoRecords << info;
241
261
    }
242
262
 
247
267
                .arg(QString(b));
248
268
        return false;
249
269
    }
250
 
 
 
270
    dbgFile << "reading blend mode at pos" << io->pos();
251
271
    blendModeKey = QString(io->read(4));
252
272
    if (blendModeKey.size() != 4) {
253
273
        error = QString("Could not read blend mode key. Got: %1").arg(blendModeKey);
376
396
            return false;
377
397
        }
378
398
 
379
 
        //qDebug() << "blending block data length" << blendingDataLength << ", pos" << io->pos();
 
399
        //dbgFile << "blending block data length" << blendingDataLength << ", pos" << io->pos();
380
400
 
381
401
        blendingRanges.data = io->read(blendingDataLength);
382
402
        if ((quint32)blendingRanges.data.size() != blendingDataLength) {
383
403
            error = QString("Got %1 bytes for the blending range block, needed %2").arg(blendingRanges.data.size(), blendingDataLength);
384
404
        }
385
405
        /*
386
 
    // XXX: reading this block correctly failed, I have more channel ranges than I'd expected.
387
 
 
388
 
    if (!psdread(io, &blendingRanges.blackValues[0]) ||
389
 
        !psdread(io, &blendingRanges.blackValues[1]) ||
390
 
        !psdread(io, &blendingRanges.whiteValues[0]) ||
391
 
        !psdread(io, &blendingRanges.whiteValues[1]) ||
392
 
        !psdread(io, &blendingRanges.compositeGrayBlendDestinationRange)) {
393
 
 
394
 
        error = "Could not read blending black/white values";
395
 
        return false;
396
 
    }
397
 
 
398
 
    for (int i = 0; i < nChannels; ++i) {
399
 
        quint32 src;
400
 
        quint32 dst;
401
 
        if (!psdread(io, &src) || !psdread(io, &dst)) {
402
 
            error = QString("could not read src/dst range for channel %1").arg(i);
 
406
        // XXX: reading this block correctly failed, I have more channel ranges than I'd expected.
 
407
 
 
408
        if (!psdread(io, &blendingRanges.blackValues[0]) ||
 
409
            !psdread(io, &blendingRanges.blackValues[1]) ||
 
410
            !psdread(io, &blendingRanges.whiteValues[0]) ||
 
411
            !psdread(io, &blendingRanges.whiteValues[1]) ||
 
412
            !psdread(io, &blendingRanges.compositeGrayBlendDestinationRange)) {
 
413
 
 
414
            error = "Could not read blending black/white values";
403
415
            return false;
404
416
        }
405
 
        dbgFile << "\tread range " << src << "to" << dst << "for channel" << i;
406
 
        blendingRanges.sourceDestinationRanges << QPair<quint32, quint32>(src, dst);
407
 
    }
408
 
    */
 
417
 
 
418
        for (int i = 0; i < nChannels; ++i) {
 
419
            quint32 src;
 
420
            quint32 dst;
 
421
            if (!psdread(io, &src) || !psdread(io, &dst)) {
 
422
                error = QString("could not read src/dst range for channel %1").arg(i);
 
423
                return false;
 
424
            }
 
425
            dbgFile << "\tread range " << src << "to" << dst << "for channel" << i;
 
426
            blendingRanges.sourceDestinationRanges << QPair<quint32, quint32>(src, dst);
 
427
        }
 
428
        */
409
429
        dbgFile << "\tGoing to read layer name at" << io->pos();
410
430
        quint8 layerNameLength;
411
431
        if (!psdread(io, &layerNameLength)) {
414
434
        }
415
435
 
416
436
        dbgFile << "\tlayer name length unpadded" << layerNameLength << "pos" << io->pos();
417
 
 
418
437
        layerNameLength = ((layerNameLength + 1 + 3) & ~0x03) - 1;
419
438
 
420
439
        dbgFile << "\tlayer name length padded" << layerNameLength << "pos" << io->pos();
421
 
 
422
440
        layerName = io->read(layerNameLength);
423
 
 
424
441
        dbgFile << "\tlayer name" << layerName << io->pos();
425
442
 
426
443
        QStringList longBlocks;
445
462
                error = "Could not read key for additional layer info block";
446
463
                return false;
447
464
            }
 
465
            dbgFile << "found info block with key" << key;
448
466
 
449
467
            if (infoBlocks.contains(key)) {
450
468
                error = QString("Duplicate layer info block with key %1").arg(key);
468
486
                return false;
469
487
            }
470
488
 
471
 
            dbgFile << "\tRead layer info block" << infoBlock->data.size();
 
489
            dbgFile << "\tRead layer info block" << key << "for size" << infoBlock->data.size();
 
490
 
 
491
            // get the unicode layer name
 
492
            if (key == "luni") {
 
493
                QBuffer buf(&infoBlock->data);
 
494
                buf.open(QBuffer::ReadOnly);
 
495
 
 
496
                quint32 stringlen;
 
497
                if (!psdread(&buf, &stringlen)) {
 
498
                    error = "Could not read string length for luni block";
 
499
                    return false;
 
500
                }
 
501
                QString unicodeLayerName;
 
502
 
 
503
                for (uint i = 0; i < stringlen; ++i) {
 
504
                    quint16 ch;
 
505
                    psdread(&buf, &ch);
 
506
                    QChar uch(ch);
 
507
                    unicodeLayerName.append(uch);
 
508
                }
 
509
 
 
510
                dbgFile << "unicodeLayerName" << unicodeLayerName;
 
511
                if (!unicodeLayerName.isEmpty()) {
 
512
                    layerName = unicodeLayerName;
 
513
                }
 
514
            }
 
515
 
472
516
 
473
517
            infoBlocks[key] = infoBlock;
474
518
        }
477
521
    return valid();
478
522
}
479
523
 
480
 
bool PSDLayerRecord::write(QIODevice* io)
481
 
{
482
 
    Q_UNUSED(io);
483
 
    Q_ASSERT(valid());
484
 
    if (!valid()) {
485
 
        error = "Cannot write an invalid Layer Record object";
486
 
        return false;
487
 
    }
488
 
    qFatal("TODO: implement writing the layer record");
489
 
    return false;
 
524
bool PSDLayerRecord::write(QIODevice* io, KisNodeSP node)
 
525
{
 
526
    dbgFile << "writing layer info record" << node->name() << "at" << io->pos();
 
527
 
 
528
    m_node = node;
 
529
 
 
530
    dbgFile << "saving layer record for " << layerName << "at pos" << io->pos();
 
531
    dbgFile << "\ttop" << top << "left" << left << "bottom" << bottom << "right" << right << "number of channels" << nChannels;
 
532
    Q_ASSERT(left <= right);
 
533
    Q_ASSERT(top <= bottom);
 
534
    Q_ASSERT(nChannels > 0);
 
535
    psdwrite(io, (quint32)top);
 
536
    psdwrite(io, (quint32)left);
 
537
    psdwrite(io, (quint32)bottom);
 
538
    psdwrite(io, (quint32)right);
 
539
    psdwrite(io, (quint16)nChannels);
 
540
 
 
541
    foreach(ChannelInfo *channel, channelInfoRecords) {
 
542
        psdwrite(io, (quint16)channel->channelId);
 
543
        channel->channelInfoPosition = io->pos();
 
544
        dbgFile << "ChannelInfo record position:" << channel->channelInfoPosition << "channel id" << channel->channelId;
 
545
        psdwrite(io, (quint32)0); // to be filled in when we know how big each channel block is going to be
 
546
    }
 
547
 
 
548
    // blend mode
 
549
    io->write("8BIM", 4);
 
550
    dbgFile << "blendModeKey" << blendModeKey << "pos" << io->pos();
 
551
    io->write(blendModeKey.toLatin1());
 
552
 
 
553
    // opacity
 
554
    psdwrite(io, opacity);
 
555
 
 
556
    // clipping - unused
 
557
    psdwrite(io, clipping);
 
558
 
 
559
    // visibility and protection
 
560
    quint8 flags = 0;
 
561
    if (transparencyProtected) flags |= 1;
 
562
    if (!visible) flags |= 2;
 
563
    psdwrite(io, flags);
 
564
 
 
565
 
 
566
    // padding byte to make the length even
 
567
    psdwrite(io, (quint8)0);
 
568
 
 
569
    // position of the extra data size
 
570
    quint64 extraDataPos = io->pos();
 
571
    psdwrite(io, (quint32)0); // length of the extra data fields
 
572
 
 
573
    // layer mask data: not implemented for now, so zero
 
574
    psdwrite(io, quint32(0));
 
575
 
 
576
    // Layer blending ranges: not implemented for now, so zero
 
577
    psdwrite(io, quint32(0));
 
578
 
 
579
    // layer name: Pascal string, padded to a multiple of 4 bytes.
 
580
    psdwrite_pascalstring(io, layerName, 4);
 
581
 
 
582
    // write luni data block
 
583
    {
 
584
        quint32 len = qMin(layerName.length(), 255);
 
585
        quint32 xdBlockSize = len;
 
586
 
 
587
        if (len % 2) {
 
588
            xdBlockSize = len + 1;
 
589
        }
 
590
        xdBlockSize = (xdBlockSize * 2) + 4;
 
591
 
 
592
        io->write("8BIMluni", 8);
 
593
        psdwrite(io, xdBlockSize);
 
594
        psdwrite(io, len);
 
595
 
 
596
        const ushort *chars = layerName.utf16();
 
597
        for (uint i = 0; i < len; i++) {
 
598
            psdwrite(io, (quint16)chars[i]);
 
599
        }
 
600
 
 
601
        if (len % 2) {
 
602
            psdwrite(io, (quint16)0); // padding
 
603
        }
 
604
    }
 
605
    // write real length for extra data
 
606
 
 
607
    quint64 eofPos = io->pos();
 
608
    io->seek(extraDataPos);
 
609
    psdwrite(io, (quint32)(eofPos - extraDataPos - sizeof(quint32)));
 
610
    dbgFile << "ExtraData size" << (eofPos - extraDataPos - sizeof(quint32))
 
611
            << "extra data pos" << extraDataPos
 
612
            << "eofpos" << eofPos;
 
613
 
 
614
    // retor to eof to continue writing
 
615
    io->seek(eofPos);
 
616
 
 
617
    return true;
 
618
}
 
619
 
 
620
bool PSDLayerRecord::writePixelData(QIODevice *io)
 
621
{
 
622
    dbgFile << "writing pixel data for layer" << layerName << "at" << io->pos();
 
623
 
 
624
    KisPaintDeviceSP dev = m_node->projection();
 
625
 
 
626
    // now write all the channels in display order
 
627
    QRect rc = dev->extent();
 
628
 
 
629
    // yeah... we read the entire layer into a vector of quint8 arrays
 
630
    dbgFile << "layer" << layerName;
 
631
    dbgFile << "\tnode x" << m_node->x() << "paint device x" << dev->x() << "extent x" << rc.x();
 
632
    dbgFile << "\tnode y" << m_node->y() << "paint device x" << dev->y() << "extent y" << rc.y();
 
633
    QVector<quint8* > tmp = dev->readPlanarBytes(rc.x() - m_node->x(), rc.y() -m_node->y(), rc.width(), rc.height());
 
634
 
 
635
//    KisPaintDeviceSP dev2 = new KisPaintDevice(dev->colorSpace());
 
636
//    dev2->writePlanarBytes(tmp, 0, 0, rc.width(), rc.height());
 
637
//    dev2->convertToQImage(0).save(layerName + ".png");
 
638
 
 
639
    // then reorder the planes to fit the psd model -- alpha first, then display order
 
640
    QVector<quint8* > planes;
 
641
    foreach(KoChannelInfo *ch, KoChannelInfo::displayOrderSorted(dev->colorSpace()->channels())) {
 
642
        if (ch->channelType() == KoChannelInfo::ALPHA) {
 
643
            planes.insert(0, tmp[ch->pos()]);
 
644
        }
 
645
        else {
 
646
            planes.append(tmp[ch->pos()]);
 
647
        }
 
648
    }
 
649
 
 
650
 
 
651
    // here's where we save the total size of the channel data
 
652
    for (int channelInfoIndex = 0; channelInfoIndex  < nChannels; ++channelInfoIndex) {
 
653
 
 
654
        dbgFile << "\tWriting channel" << channelInfoIndex << "psd channel id" << channelInfoRecords[channelInfoIndex]->channelId;
 
655
 
 
656
        // if the bitdepth > 8, place the bytes in the right order
 
657
        // if cmyk, invert the pixel value
 
658
        if (m_header.channelDepth == 8) {
 
659
            if (channelInfoRecords[channelInfoIndex]->channelId >= 0 && (m_header.colormode == CMYK || m_header.colormode == CMYK64)) {
 
660
                for (int i = 0; i < rc.width() * rc.height(); ++i) {
 
661
                    planes[channelInfoIndex][i] = 255 - planes[channelInfoIndex][i];
 
662
                }
 
663
            }
 
664
        }
 
665
        else if (m_header.channelDepth == 16) {
 
666
            quint16 val;
 
667
            for (int i = 0; i < rc.width() * rc.height(); ++i) {
 
668
                val = reinterpret_cast<quint16*>(planes[channelInfoIndex])[i];
 
669
                val = ntohs(val);
 
670
                if (channelInfoRecords[channelInfoIndex]->channelId >= 0 && (m_header.colormode == CMYK || m_header.colormode == CMYK64)) {
 
671
                     val = quint16_MAX - val;
 
672
                }
 
673
                reinterpret_cast<quint16*>(planes[channelInfoIndex])[i] = val;
 
674
            }
 
675
        }
 
676
        quint32 len = 0;
 
677
 
 
678
 
 
679
 
 
680
        // where this block starts, for the total size calculation
 
681
        quint64 startChannelBlockPos = io->pos();
 
682
 
 
683
        // XXX: make the compression settting configurable. For now, always use RLE.
 
684
        psdwrite(io, (quint16)Compression::RLE);
 
685
        len += sizeof(quint16);
 
686
 
 
687
        // where this block starts, for the total size calculation
 
688
        quint64 channelRLESizePos = io->pos();
 
689
 
 
690
        // write zero's for the channel lengths section
 
691
        for(int i = 0; i < rc.height(); ++i) {
 
692
            psdwrite(io, (quint16)0);
 
693
        }
 
694
        len += rc.height() * sizeof(quint16);
 
695
 
 
696
        // here the actual channel data starts; that's where we return after writing
 
697
        // the size of the current row
 
698
        quint64 channelStartPos = io->pos();
 
699
 
 
700
        quint8 *plane = planes[channelInfoIndex];
 
701
        quint32 stride = (m_header.channelDepth / 8) * rc.width();
 
702
        for (qint32 row = 0; row < rc.height(); ++row) {
 
703
 
 
704
            QByteArray uncompressed = QByteArray::fromRawData((const char*)plane + row * stride, stride);
 
705
            QByteArray compressed = Compression::compress(uncompressed, Compression::RLE);
 
706
            quint16 size = compressed.size();
 
707
 
 
708
            io->seek(channelRLESizePos);
 
709
            psdwrite(io, size);
 
710
            channelRLESizePos +=2;
 
711
            io->seek(channelStartPos);
 
712
 
 
713
            if (!io->write(compressed) == size) {
 
714
                error = "Could not write image data";
 
715
                return false;
 
716
            }
 
717
            len += size;
 
718
 
 
719
            // dbgFile << "\t\tUncompressed:" << uncompressed.size() << "compressed" << compressed.size();
 
720
            // QByteArray control = Compression::uncompress(rc.width(), compressed, Compression::RLE);
 
721
            // Q_ASSERT(qstrcmp(control, uncompressed) == 0);
 
722
 
 
723
 
 
724
            // If the layer's size, and therefore the data, is odd, a pad byte will be inserted
 
725
            // at the end of the row. (weirdly enough, that's not true for the image data)
 
726
//            if ((size & 0x01) != 0) {
 
727
//                psdwrite(io, (quint8)0);
 
728
//                size++;
 
729
//            }
 
730
 
 
731
            channelStartPos += size;
 
732
        }
 
733
        // write the size of the channel image data block in the channel info block
 
734
        quint64 currentPos = io->pos();
 
735
        io->seek(channelInfoRecords[channelInfoIndex]->channelInfoPosition);
 
736
        Q_ASSERT(len == currentPos - startChannelBlockPos);
 
737
        dbgFile << "\t\ttotal length" << len << "calculated length" << currentPos - startChannelBlockPos << "writing at" << channelInfoRecords[channelInfoIndex]->channelInfoPosition;
 
738
        psdwrite(io, (quint32)(currentPos - startChannelBlockPos));
 
739
        io->seek(currentPos);
 
740
    }
 
741
 
 
742
    return true;
 
743
 
 
744
 
490
745
}
491
746
 
492
747
bool PSDLayerRecord::valid()
495
750
    return true;
496
751
}
497
752
 
498
 
bool PSDLayerRecord::readChannels(QIODevice *io, KisPaintDeviceSP device)
 
753
bool PSDLayerRecord::readPixelData(QIODevice *io, KisPaintDeviceSP device)
499
754
{
 
755
    dbgFile << "Reading pixel data for layer" << layerName << "pos" << io->pos();
500
756
    switch (m_header.colormode) {
501
757
    case Bitmap:
502
 
        return false; // Not supported;
 
758
        error = "Unsupported color mode: bitmap";
 
759
        return false; // Not supported;
 
760
    case Indexed:
 
761
        error = "Unsupported color mode: indexed";
 
762
        return false; // Not supported;
 
763
    case MultiChannel:
 
764
        error = "Unsupported color mode: indexed";
 
765
        return false; // Not supported
 
766
    case DuoTone:
 
767
        error = "Unsupported color mode: Duotone";
 
768
        return false; // Not supported
503
769
    case Grayscale:
504
770
        return doGrayscale(device, io);
505
 
    case Indexed:
506
 
        break;
507
771
    case RGB:
508
772
        return doRGB(device, io);
509
773
    case CMYK:
510
 
        return doCMYK(device,io);
511
 
    case MultiChannel:
512
 
        return false; // Not supported
513
 
    case DuoTone:
514
 
        return false; // Not supported
 
774
        return doCMYK(device, io);
515
775
    case Lab:
516
776
        return doLAB(device, io);
517
777
    case UNKNOWN:
530
790
bool PSDLayerRecord::doRGB(KisPaintDeviceSP dev, QIODevice *io)
531
791
{
532
792
    quint64 oldPosition = io->pos();
533
 
 
534
 
    quint64 width = right - left;
 
793
    qint64 width = right - left;
 
794
 
 
795
    if (width <= 0) {
 
796
        dbgFile << "Empty layer";
 
797
        return true;
 
798
    }
 
799
 
535
800
    int channelSize = m_header.channelDepth / 8;
536
801
    int uncompressedLength = width * channelSize;
537
802
 
538
803
    if (channelInfoRecords.first()->compressionType == Compression::ZIP
539
804
            || channelInfoRecords.first()->compressionType == Compression::ZIPWithPrediction) {
540
805
 
541
 
        // Zip needs to be implemented here.
 
806
        error = "Unsupported Compression mode: zip";
542
807
        return false;
543
808
    }
544
809
 
548
813
        QMap<quint16, QByteArray> channelBytes;
549
814
 
550
815
        foreach(ChannelInfo *channelInfo, channelInfoRecords) {
551
 
 
552
816
            io->seek(channelInfo->channelDataStart + channelInfo->channelOffset);
553
817
 
554
818
            if (channelInfo->compressionType == Compression::Uncompressed) {
563
827
                channelInfo->channelOffset += rleLength;
564
828
 
565
829
            }
 
830
            else {
 
831
                error = "Unsupported Compression mode: " + channelInfo->compressionType;
 
832
                return false;
 
833
            }
566
834
        }
567
835
 
568
 
        for (quint64 col = 0; col < width; col++){
 
836
        for (qint64 col = 0; col < width; col++){
569
837
 
570
838
            if (channelSize == 1) {
571
839
                quint8 opacity = OPACITY_OPAQUE_U8;
633
901
 
634
902
bool PSDLayerRecord::doCMYK(KisPaintDeviceSP dev, QIODevice *io)
635
903
{
636
 
    qDebug() << "doCMYK for" << layerName << "channels:" << channelInfoRecords.size() << "compression" << channelInfoRecords.first()->compressionType;
637
 
    qDebug() << "top" << top << "bottom" << bottom << "left" << left << "right" << right;
 
904
    dbgFile << "doCMYK for" << layerName << "channels:" << channelInfoRecords.size() << "compression" << channelInfoRecords.first()->compressionType;
 
905
    dbgFile << "top" << top << "bottom" << bottom << "left" << left << "right" << right;
638
906
    quint64 oldPosition = io->pos();
639
907
 
640
908
    quint64 width = right - left;
644
912
 
645
913
    if (channelInfoRecords.first()->compressionType == Compression::ZIP
646
914
            || channelInfoRecords.first()->compressionType == Compression::ZIPWithPrediction) {
647
 
        qDebug() << "zippedy-do-da!";
 
915
        dbgFile << "zippedy-do-da!";
648
916
        // Zip needs to be implemented here.
649
917
        return false;
650
918
    }
690
958
                memset(pixel + 1, 255 - channelBytes[1].constData()[col], 1);
691
959
                memset(pixel + 2, 255 - channelBytes[2].constData()[col], 1);
692
960
                memset(pixel + 3, 255 - channelBytes[3].constData()[col], 1);
693
 
                //qDebug() << "C" << pixel[0] << "M" << pixel[1] << "Y" << pixel[2] << "K" << pixel[3] << "A" << pixel[4];
 
961
                //dbgFile << "C" << pixel[0] << "M" << pixel[1] << "Y" << pixel[2] << "K" << pixel[3] << "A" << pixel[4];
694
962
                memcpy(it->rawData(), pixel, 5);
695
963
            }
696
964
 
752
1020
{    quint64 oldPosition = io->pos();
753
1021
 
754
1022
     quint64 width = right - left;
755
 
     int channelSize = m_header.channelDepth / 8;
756
 
     int uncompressedLength = width * channelSize;
757
 
 
758
 
     if (channelInfoRecords.first()->compressionType == Compression::ZIP
759
 
             || channelInfoRecords.first()->compressionType == Compression::ZIPWithPrediction) {
760
 
 
761
 
         // Zip needs to be implemented here.
762
 
         return false;
763
 
     }
764
 
 
765
 
     KisHLineIteratorSP it = dev->createHLineIteratorNG(left, top, width);
766
 
     for (int row = top ; row < bottom; row++)
767
 
     {
768
 
 
769
 
         QMap<quint16, QByteArray> channelBytes;
770
 
 
771
 
         foreach(ChannelInfo *channelInfo, channelInfoRecords) {
772
 
 
773
 
             io->seek(channelInfo->channelDataStart + channelInfo->channelOffset);
774
 
 
775
 
             if (channelInfo->compressionType == Compression::Uncompressed) {
776
 
                 channelBytes[channelInfo->channelId] = io->read(uncompressedLength);
777
 
                 channelInfo->channelOffset += uncompressedLength;
778
 
             }
779
 
             else if (channelInfo->compressionType == Compression::RLE) {
780
 
                 int rleLength = channelInfo->rleRowLengths[row - top];
781
 
                 QByteArray compressedBytes = io->read(rleLength);
782
 
                 QByteArray uncompressedBytes = Compression::uncompress(uncompressedLength, compressedBytes, channelInfo->compressionType);
783
 
                 channelBytes.insert(channelInfo->channelId, uncompressedBytes);
784
 
                 channelInfo->channelOffset += rleLength;
785
 
 
786
 
             }
787
 
         }
788
 
 
789
 
         for (quint64 col = 0; col < width; col++){
790
 
 
791
 
             if (channelSize == 1) {
792
 
                 quint8 opacity = OPACITY_OPAQUE_U8;
793
 
                 if (channelBytes.contains(-1)) {
794
 
                     opacity = channelBytes[-1].constData()[col];
795
 
                 }
796
 
                 KoLabTraits<quint8>::setOpacity(it->rawData(), opacity, 1);
797
 
 
798
 
                 quint8 L = ntohs(reinterpret_cast<const quint8 *>(channelBytes[0].constData())[col]);
799
 
                 KoLabTraits<quint8>::setL(it->rawData(),L);
800
 
 
801
 
                 quint8 A = ntohs(reinterpret_cast<const quint8 *>(channelBytes[1].constData())[col]);
802
 
                 KoLabTraits<quint8>::setA(it->rawData(),A);
803
 
 
804
 
                 quint8 B = ntohs(reinterpret_cast<const quint8 *>(channelBytes[2].constData())[col]);
805
 
                 KoLabTraits<quint8>::setB(it->rawData(),B);
806
 
 
807
 
 
808
 
             }
809
 
 
810
 
             else if (channelSize == 2) {
811
 
 
812
 
                 quint16 opacity = quint16_MAX;
813
 
                 if (channelBytes.contains(-1)) {
814
 
                     opacity = channelBytes[-1].constData()[col];
815
 
                 }
816
 
                 // We don't have a convenient setOpacity function :-(
817
 
                 memcpy(it->rawData() + KoLabU16Traits::alpha_pos, &opacity, sizeof(quint16));
818
 
                // KoLabTraits<quint16>::setOpacity(it->rawData(), opacity, 1);
819
 
 
820
 
                 quint16 L = ntohs(reinterpret_cast<const quint16 *>(channelBytes[0].constData())[col]);
821
 
                 KoLabTraits<quint16>::setL(it->rawData(),L);
822
 
 
823
 
                 quint16 A = ntohs(reinterpret_cast<const quint16 *>(channelBytes[1].constData())[col]);
824
 
                 KoLabTraits<quint16>::setA(it->rawData(),A);
825
 
 
826
 
                 quint16 B = ntohs(reinterpret_cast<const quint16 *>(channelBytes[2].constData())[col]);
827
 
                 KoLabTraits<quint16>::setB(it->rawData(),B);
828
 
             }
829
 
             else {
830
 
                 // Unsupported channel sizes for now
831
 
                 return false;
832
 
             }
833
 
 
834
 
             it->nextPixel();
835
 
         }
836
 
         it->nextRow();
837
 
     }
838
 
     // go back to the old position, because we've been seeking all over the place
839
 
     io->seek(oldPosition);
840
 
     return true;
 
1023
      int channelSize = m_header.channelDepth / 8;
 
1024
       int uncompressedLength = width * channelSize;
 
1025
 
 
1026
        if (channelInfoRecords.first()->compressionType == Compression::ZIP
 
1027
                || channelInfoRecords.first()->compressionType == Compression::ZIPWithPrediction) {
 
1028
 
 
1029
            // Zip needs to be implemented here.
 
1030
            return false;
 
1031
        }
 
1032
 
 
1033
        KisHLineIteratorSP it = dev->createHLineIteratorNG(left, top, width);
 
1034
         for (int row = top ; row < bottom; row++)
 
1035
         {
 
1036
 
 
1037
             QMap<quint16, QByteArray> channelBytes;
 
1038
 
 
1039
             foreach(ChannelInfo *channelInfo, channelInfoRecords) {
 
1040
 
 
1041
                 io->seek(channelInfo->channelDataStart + channelInfo->channelOffset);
 
1042
 
 
1043
                 if (channelInfo->compressionType == Compression::Uncompressed) {
 
1044
                     channelBytes[channelInfo->channelId] = io->read(uncompressedLength);
 
1045
                     channelInfo->channelOffset += uncompressedLength;
 
1046
                 }
 
1047
                 else if (channelInfo->compressionType == Compression::RLE) {
 
1048
                     int rleLength = channelInfo->rleRowLengths[row - top];
 
1049
                     QByteArray compressedBytes = io->read(rleLength);
 
1050
                     QByteArray uncompressedBytes = Compression::uncompress(uncompressedLength, compressedBytes, channelInfo->compressionType);
 
1051
                     channelBytes.insert(channelInfo->channelId, uncompressedBytes);
 
1052
                     channelInfo->channelOffset += rleLength;
 
1053
 
 
1054
                 }
 
1055
             }
 
1056
 
 
1057
             for (quint64 col = 0; col < width; col++){
 
1058
 
 
1059
                 if (channelSize == 1) {
 
1060
                     quint8 opacity = OPACITY_OPAQUE_U8;
 
1061
                     if (channelBytes.contains(-1)) {
 
1062
                         opacity = channelBytes[-1].constData()[col];
 
1063
                     }
 
1064
                     KoLabTraits<quint8>::setOpacity(it->rawData(), opacity, 1);
 
1065
 
 
1066
                     quint8 L = ntohs(reinterpret_cast<const quint8 *>(channelBytes[0].constData())[col]);
 
1067
                     KoLabTraits<quint8>::setL(it->rawData(),L);
 
1068
 
 
1069
                     quint8 A = ntohs(reinterpret_cast<const quint8 *>(channelBytes[1].constData())[col]);
 
1070
                     KoLabTraits<quint8>::setA(it->rawData(),A);
 
1071
 
 
1072
                     quint8 B = ntohs(reinterpret_cast<const quint8 *>(channelBytes[2].constData())[col]);
 
1073
                     KoLabTraits<quint8>::setB(it->rawData(),B);
 
1074
 
 
1075
 
 
1076
                 }
 
1077
 
 
1078
                 else if (channelSize == 2) {
 
1079
 
 
1080
                     quint16 opacity = quint16_MAX;
 
1081
                     if (channelBytes.contains(-1)) {
 
1082
                         opacity = channelBytes[-1].constData()[col];
 
1083
                     }
 
1084
                     // We don't have a convenient setOpacity function :-(
 
1085
                     memcpy(it->rawData() + KoLabU16Traits::alpha_pos, &opacity, sizeof(quint16));
 
1086
                     // KoLabTraits<quint16>::setOpacity(it->rawData(), opacity, 1);
 
1087
 
 
1088
                     quint16 L = ntohs(reinterpret_cast<const quint16 *>(channelBytes[0].constData())[col]);
 
1089
                     KoLabTraits<quint16>::setL(it->rawData(),L);
 
1090
 
 
1091
                     quint16 A = ntohs(reinterpret_cast<const quint16 *>(channelBytes[1].constData())[col]);
 
1092
                     KoLabTraits<quint16>::setA(it->rawData(),A);
 
1093
 
 
1094
                     quint16 B = ntohs(reinterpret_cast<const quint16 *>(channelBytes[2].constData())[col]);
 
1095
                     KoLabTraits<quint16>::setB(it->rawData(),B);
 
1096
                 }
 
1097
                 else {
 
1098
                     // Unsupported channel sizes for now
 
1099
                     return false;
 
1100
                 }
 
1101
 
 
1102
                 it->nextPixel();
 
1103
             }
 
1104
             it->nextRow();
 
1105
         }
 
1106
          // go back to the old position, because we've been seeking all over the place
 
1107
          io->seek(oldPosition);
 
1108
           return true;
841
1109
}
842
1110
 
843
1111