void KisGmicSimpleConvertor::convertToGmicImage(KisPaintDeviceSP dev, gmic_image< float >& gmicImage) { const KoColorSpace *rgbaFloat32bitcolorSpace = KoColorSpaceRegistry::instance()->colorSpace(RGBAColorModelID.id(), Float32BitsColorDepthID.id(), KoColorSpaceRegistry::instance()->rgb8()->profile()); Q_CHECK_PTR(rgbaFloat32bitcolorSpace); dev->convertTo(rgbaFloat32bitcolorSpace); QRect rc = dev->exactBounds(); m_planarBytes = dev->readPlanarBytes(rc.x(), rc.y(), rc.width(), rc.height()); setChannelSize(rc.width() * rc.height()); int greenOffset = gmicImage._width * gmicImage._height; int blueOffset = greenOffset * 2; int alphaOffset = greenOffset * 3; quint8 * redChannelBytes = m_planarBytes.at(KoRgbF32Traits::red_pos); quint8 * greenChannelBytes = m_planarBytes.at(KoRgbF32Traits::green_pos); quint8 * blueChannelBytes = m_planarBytes.at(KoRgbF32Traits::blue_pos); quint8 * alphaChannelBytes = m_planarBytes.at(KoRgbF32Traits::alpha_pos); unsigned int channelSize = sizeof(float); memcpy(gmicImage._data ,redChannelBytes ,gmicImage._width * gmicImage._height * channelSize); memcpy(gmicImage._data + greenOffset ,greenChannelBytes ,gmicImage._width * gmicImage._height * channelSize); memcpy(gmicImage._data + blueOffset ,blueChannelBytes ,gmicImage._width * gmicImage._height * channelSize); memcpy(gmicImage._data + alphaOffset ,alphaChannelBytes ,gmicImage._width * gmicImage._height * channelSize); }
bool PSDImageData::write(QIODevice *io, KisPaintDeviceSP dev) { // XXX: make the compression settting configurable. For now, always use RLE. psdwrite(io, (quint16)Compression::RLE); // now write all the channels in display order // fill in the channel chooser, in the display order, but store the pixel index as well. QRect rc(0, 0, m_header->width, m_header->height); QVector<quint8* > tmp = dev->readPlanarBytes(0, 0, rc.width(), rc.height()); // then reorder the planes to fit the psd model -- alpha first, then display order QVector<quint8* > planes; QList<KoChannelInfo*> origChannels = dev->colorSpace()->channels(); quint8* alphaPlane = 0; foreach(KoChannelInfo *ch, KoChannelInfo::displayOrderSorted(origChannels)) { int channelIndex = KoChannelInfo::displayPositionToChannelIndex(ch->displayPosition(), origChannels); //qDebug() << ppVar(ch->name()) << ppVar(ch->pos()) << ppVar(ch->displayPosition()) << ppVar(channelIndex); if (ch->channelType() == KoChannelInfo::ALPHA) { alphaPlane = tmp[channelIndex]; } else { planes.append(tmp[channelIndex]); } }
void KisPaintDeviceTest::testPlanarReadWrite() { const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8(); KisPaintDeviceSP dev = new KisPaintDevice(cs); quint8* pixel = new quint8[cs->pixelSize()]; cs->fromQColor(QColor(255, 200, 155, 100), pixel); dev->fill(0, 0, 5000, 5000, pixel); delete[] pixel; QColor c1; dev->pixel(5, 5, &c1); QVector<quint8*> planes = dev->readPlanarBytes(500, 500, 100, 100); QVector<quint8*> swappedPlanes; QCOMPARE((int)planes.size(), (int)dev->channelCount()); for (int i = 0; i < 100*100; i++) { // BGRA encoded QVERIFY(planes.at(2)[i] == 255); QVERIFY(planes.at(1)[i] == 200); QVERIFY(planes.at(0)[i] == 155); QVERIFY(planes.at(3)[i] == 100); } for (uint i = 1; i < dev->channelCount() + 1; ++i) { swappedPlanes.append(planes[dev->channelCount() - i]); } dev->writePlanarBytes(swappedPlanes, 0, 0, 100, 100); dev->convertToQImage(0, 0, 0, 1000, 1000).save("planar.png"); dev->pixel(5, 5, &c1); QVERIFY(c1.red() == 200); QVERIFY(c1.green() == 255); QVERIFY(c1.blue() == 100); QVERIFY(c1.alpha() == 155); dev->pixel(75, 50, &c1); QVERIFY(c1.red() == 200); QVERIFY(c1.green() == 255); QVERIFY(c1.blue() == 100); QVERIFY(c1.alpha() == 155); // check if one of the planes is Null. Q_ASSERT(planes.size() == 4); delete planes[2]; planes[2] = 0; dev->writePlanarBytes(planes, 0, 0, 100, 100); dev->convertToQImage(0, 0, 0, 1000, 1000).save("planar_noR.png"); dev->pixel(75, 50, &c1); QCOMPARE(c1.red(), 200); QCOMPARE(c1.green(), 200); QCOMPARE(c1.blue(), 155); QCOMPARE(c1.alpha(), 100); qDeleteAll(planes); swappedPlanes.clear(); }