void KisKraLoaderTest::testLoading() { KisDocument *doc = KisPart::instance()->createDocument(); doc->loadNativeFormat(QString(FILES_DATA_DIR) + QDir::separator() + "load_test.kra"); KisImageWSP image = doc->image(); image->lock(); QCOMPARE(image->nlayers(), 12); QCOMPARE(doc->documentInfo()->aboutInfo("title"), QString("test image for loading")); QCOMPARE(image->height(), 753); QCOMPARE(image->width(), 1000); QCOMPARE(image->colorSpace()->id(), KoColorSpaceRegistry::instance()->rgb8()->id()); KisNodeSP node = image->root()->firstChild(); QVERIFY(node); QCOMPARE(node->name(), QString("Background")); QVERIFY(node->inherits("KisPaintLayer")); node = node->nextSibling(); QVERIFY(node); QCOMPARE(node->name(), QString("Group 1")); QVERIFY(node->inherits("KisGroupLayer")); QCOMPARE((int) node->childCount(), 2); delete doc; }
QDomElement KisKraSaver::saveXML(QDomDocument& doc, KisImageWSP image) { QDomElement imageElement = doc.createElement("IMAGE"); // Legacy! Q_ASSERT(image); imageElement.setAttribute(NAME, m_d->imageName); imageElement.setAttribute(MIME, NATIVE_MIMETYPE); imageElement.setAttribute(WIDTH, image->width()); imageElement.setAttribute(HEIGHT, image->height()); imageElement.setAttribute(COLORSPACE_NAME, image->colorSpace()->id()); imageElement.setAttribute(DESCRIPTION, m_d->doc->documentInfo()->aboutInfo("comment")); // XXX: Save profile as blob inside the image, instead of the product name. if (image->profile() && image->profile()-> valid()) { imageElement.setAttribute(PROFILE, image->profile()->name()); } imageElement.setAttribute(X_RESOLUTION, image->xRes()*72.0); imageElement.setAttribute(Y_RESOLUTION, image->yRes()*72.0); quint32 count = 1; // We don't save the root layer, but it does count KisSaveXmlVisitor visitor(doc, imageElement, count, true); image->rootLayer()->accept(visitor); m_d->nodeFileNames = visitor.nodeFileNames(); return imageElement; }
void KisPasteActionFactory::run(KisView2 *view) { KisImageWSP image = view->image(); //figure out where to position the clip // XXX: Fix this for internal points & zoom! (BSAR) QWidget * w = view->canvas(); QPoint center = QPoint(w->width() / 2, w->height() / 2); QPoint bottomright = QPoint(w->width(), w->height()); if (bottomright.x() > image->width()) center.setX(image->width() / 2); if (bottomright.y() > image->height()) center.setY(image->height() / 2); const KoCanvasBase* canvasBase = view->canvasBase(); const KoViewConverter* viewConverter = view->canvasBase()->viewConverter(); KisPaintDeviceSP clip = KisClipboard::instance()->clip( QPoint( viewConverter->viewToDocumentX(canvasBase->canvasController()->canvasOffsetX()) + center.x(), viewConverter->viewToDocumentY(canvasBase->canvasController()->canvasOffsetY()) + center.y())); if (clip) { // Pasted layer content could be outside image bounds and invisible, if that is the case move content into the bounds QRect exactBounds = clip->exactBounds(); if (!exactBounds.isEmpty() && !exactBounds.intersects(image->bounds())) { clip->setX(clip->x() - exactBounds.x()); clip->setY(clip->y() - exactBounds.y()); } KisPaintLayer *newLayer = new KisPaintLayer(image.data(), image->nextLayerName() + i18n("(pasted)"), OPACITY_OPAQUE_U8, clip); KisNodeSP aboveNode = view->activeLayer(); KisNodeSP parentNode = aboveNode ? aboveNode->parent() : image->root(); KUndo2Command *cmd = new KisImageLayerAddCommand(image, newLayer, parentNode, aboveNode); KisProcessingApplicator *ap = beginAction(view, cmd->text()); ap->applyCommand(cmd, KisStrokeJobData::SEQUENTIAL, KisStrokeJobData::NORMAL); endAction(ap, KisOperationConfiguration(id()).toXML()); } else { #ifdef __GNUC__ #warning "Add saving of XML data for Paste of shapes" #endif view->canvasBase()->toolProxy()->paste(); } }
KisImportExportFilter::ConversionStatus KisHeightMapExport::convert(const QByteArray& from, const QByteArray& to) { dbgFile << "HeightMap export! From:" << from << ", To:" << to; if (from != "application/x-krita") return KisImportExportFilter::NotImplemented; KisDocument *inputDoc = inputDocument(); QString filename = outputFile(); if (!inputDoc) return KisImportExportFilter::NoDocumentCreated; if (filename.isEmpty()) return KisImportExportFilter::FileNotFound; KisImageWSP image = inputDoc->image(); Q_CHECK_PTR(image); if (inputDoc->image()->width() != inputDoc->image()->height()) { inputDoc->setErrorMessage(i18n("Cannot export this image to a heightmap: it is not square")); return KisImportExportFilter::WrongFormat; } if (inputDoc->image()->colorSpace()->colorModelId() != GrayAColorModelID) { inputDoc->setErrorMessage(i18n("Cannot export this image to a heightmap: it is not grayscale")); return KisImportExportFilter::WrongFormat; } KoDialog* kdb = new KoDialog(0); kdb->setWindowTitle(i18n("HeightMap Export Options")); kdb->setButtons(KoDialog::Ok | KoDialog::Cancel); Ui::WdgOptionsHeightMap optionsHeightMap; QWidget* wdg = new QWidget(kdb); optionsHeightMap.setupUi(wdg); kdb->setMainWidget(wdg); QApplication::restoreOverrideCursor(); QString filterConfig = KisConfig().exportConfiguration("HeightMap"); KisPropertiesConfiguration cfg; cfg.fromXML(filterConfig); optionsHeightMap.intSize->setValue(image->width()); int endianness = cfg.getInt("endianness", 0); QDataStream::ByteOrder bo = QDataStream::LittleEndian; optionsHeightMap.radioPC->setChecked(true); if (endianness == 0) { bo = QDataStream::BigEndian; optionsHeightMap.radioMac->setChecked(true); } if (!getBatchMode()) { if (kdb->exec() == QDialog::Rejected) { return KisImportExportFilter::UserCancelled; } } if (optionsHeightMap.radioMac->isChecked()) { cfg.setProperty("endianness", 0); bo = QDataStream::BigEndian; } else { cfg.setProperty("endianness", 1); bo = QDataStream::LittleEndian; } KisConfig().setExportConfiguration("HeightMap", cfg); bool downscale = false; if (to == "image/x-r8" && image->colorSpace()->colorDepthId() == Integer16BitsColorDepthID) { downscale = (QMessageBox::question(0, i18nc("@title:window", "Downscale Image"), i18n("You specified the .r8 extension for a 16 bit/channel image. Do you want to save as 8 bit? Your image data will not be changed."), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes); } // the image must be locked at the higher levels KIS_SAFE_ASSERT_RECOVER_NOOP(image->locked()); KisPaintDeviceSP pd = new KisPaintDevice(*image->projection()); QFile f(filename); f.open(QIODevice::WriteOnly); QDataStream s(&f); s.setByteOrder(bo); KisRandomConstAccessorSP it = pd->createRandomConstAccessorNG(0, 0); bool r16 = ((image->colorSpace()->colorDepthId() == Integer16BitsColorDepthID) && !downscale); for (int i = 0; i < image->height(); ++i) { for (int j = 0; j < image->width(); ++j) { it->moveTo(i, j); if (r16) { s << KoGrayU16Traits::gray(const_cast<quint8*>(it->rawDataConst())); } else { s << KoGrayU8Traits::gray(const_cast<quint8*>(it->rawDataConst())); } } } f.close(); return KisImportExportFilter::OK; }
KisSpacingInformation KisDuplicateOp::paintAt(const KisPaintInformation& info) { if (!painter()->device()) return 1.0; KisBrushSP brush = m_brush; if (!brush) return 1.0; if (!brush->canPaintFor(info)) return 1.0; if (!m_duplicateStartIsSet) { m_duplicateStartIsSet = true; m_duplicateStart = info.pos(); } KisPaintDeviceSP realSourceDevice = settings->node()->paintDevice(); qreal scale = m_sizeOption.apply(info); if (checkSizeTooSmall(scale)) return KisSpacingInformation(); QPointF hotSpot = brush->hotSpot(scale, scale, 0, info); QPointF pt = info.pos() - hotSpot; setCurrentScale(scale); // Split the coordinates into integer plus fractional parts. The integer // is where the dab will be positioned and the fractional part determines // the sub-pixel positioning. qint32 x, y; qreal xFraction, yFraction; // will not be used splitCoordinate(pt.x(), &x, &xFraction); splitCoordinate(pt.y(), &y, &yFraction); QPoint srcPoint; if(m_moveSourcePoint) { srcPoint = QPoint(x - static_cast<qint32>(settings->offset().x()), y - static_cast<qint32>(settings->offset().y())); } else { srcPoint = QPoint(static_cast<qint32>(settings->position().x() - hotSpot.x()), static_cast<qint32>(settings->position().y() - hotSpot.y())); } qint32 sw = brush->maskWidth(scale, 0.0, xFraction, yFraction, info); qint32 sh = brush->maskHeight(scale, 0.0, xFraction, yFraction, info); if (srcPoint.x() < 0) srcPoint.setX(0); if (srcPoint.y() < 0) srcPoint.setY(0); // Perspective correction ? KisImageWSP image = settings->m_image; if (m_perspectiveCorrection && image && image->perspectiveGrid()->countSubGrids() == 1) { Matrix3qreal startM = Matrix3qreal::Identity(); Matrix3qreal endM = Matrix3qreal::Identity(); // First look for the grid corresponding to the start point KisSubPerspectiveGrid* subGridStart = *image->perspectiveGrid()->begin(); QRect r = QRect(0, 0, image->width(), image->height()); #if 1 if (subGridStart) { startM = KisPerspectiveMath::computeMatrixTransfoFromPerspective(r, *subGridStart->topLeft(), *subGridStart->topRight(), *subGridStart->bottomLeft(), *subGridStart->bottomRight()); } #endif #if 1 // Second look for the grid corresponding to the end point KisSubPerspectiveGrid* subGridEnd = *image->perspectiveGrid()->begin(); if (subGridEnd) { endM = KisPerspectiveMath::computeMatrixTransfoToPerspective(*subGridEnd->topLeft(), *subGridEnd->topRight(), *subGridEnd->bottomLeft(), *subGridEnd->bottomRight(), r); } #endif // Compute the translation in the perspective transformation space: QPointF positionStartPaintingT = KisPerspectiveMath::matProd(endM, QPointF(m_duplicateStart)); QPointF duplicateStartPositionT = KisPerspectiveMath::matProd(endM, QPointF(m_duplicateStart) - QPointF(settings->offset())); QPointF translat = duplicateStartPositionT - positionStartPaintingT; KisRectIteratorSP dstIt = m_srcdev->createRectIteratorNG(0, 0, sw, sh); KisRandomSubAccessorSP srcAcc = realSourceDevice->createRandomSubAccessor(); //Action do { QPointF p = KisPerspectiveMath::matProd(startM, KisPerspectiveMath::matProd(endM, QPointF(dstIt->x() + x, dstIt->y() + y)) + translat); srcAcc->moveTo(p); srcAcc->sampledOldRawData(dstIt->rawData()); } while (dstIt->nextPixel()); } else { KisPainter copyPainter(m_srcdev); copyPainter.setCompositeOp(COMPOSITE_COPY); copyPainter.bitBltOldData(0, 0, realSourceDevice, srcPoint.x(), srcPoint.y(), sw, sh); copyPainter.end(); } // heal ? if (m_healing) { quint16 srcData[4]; quint16 tmpData[4]; qreal* matrix = new qreal[ 3 * sw * sh ]; // First divide const KoColorSpace* srcCs = realSourceDevice->colorSpace(); const KoColorSpace* tmpCs = m_srcdev->colorSpace(); KisHLineConstIteratorSP srcIt = realSourceDevice->createHLineConstIteratorNG(x, y, sw); KisHLineIteratorSP tmpIt = m_srcdev->createHLineIteratorNG(0, 0, sw); qreal* matrixIt = &matrix[0]; for (int j = 0; j < sh; j++) { for (int i = 0; i < sw; i++) { srcCs->toLabA16(srcIt->oldRawData(), (quint8*)srcData, 1); tmpCs->toLabA16(tmpIt->rawData(), (quint8*)tmpData, 1); // Division for (int k = 0; k < 3; k++) { matrixIt[k] = srcData[k] / (qreal)qMax((int)tmpData [k], 1); } srcIt->nextPixel(); tmpIt->nextPixel(); matrixIt += 3; } srcIt->nextRow(); tmpIt->nextRow(); } // Minimize energy { int iter = 0; qreal err; qreal* solution = new qreal [ 3 * sw * sh ]; do { err = minimizeEnergy(&matrix[0], &solution[0], sw, sh); // swap pointers qreal *tmp = matrix; matrix = solution; solution = tmp; iter++; } while (err > 0.00001 && iter < 100); delete [] solution; } // Finaly multiply KisHLineIteratorSP srcIt2 = realSourceDevice->createHLineIteratorNG(x, y, sw); KisHLineIteratorSP tmpIt2 = m_srcdev->createHLineIteratorNG(0, 0, sw); matrixIt = &matrix[0]; for (int j = 0; j < sh; j++) { for (int i = 0; i < sw; i++) { srcCs->toLabA16(srcIt2->rawData(), (quint8*)srcData, 1); tmpCs->toLabA16(tmpIt2->rawData(), (quint8*)tmpData, 1); // Multiplication for (int k = 0; k < 3; k++) { tmpData[k] = (int)CLAMP(matrixIt[k] * qMax((int) tmpData[k], 1), 0, 65535); } tmpCs->fromLabA16((quint8*)tmpData, tmpIt2->rawData(), 1); srcIt2->nextPixel(); tmpIt2->nextPixel(); matrixIt += 3; } srcIt2->nextRow(); tmpIt2->nextRow(); } delete [] matrix; } static const KoColorSpace *cs = KoColorSpaceRegistry::instance()->alpha8(); static KoColor color(Qt::black, cs); KisFixedPaintDeviceSP dab = m_dabCache->fetchDab(cs, color, scale, scale, 0.0, info); QRect dstRect = QRect(x, y, dab->bounds().width(), dab->bounds().height()); if (dstRect.isEmpty()) return 1.0; painter()->bitBltWithFixedSelection(dstRect.x(), dstRect.y(), m_srcdev, dab, dstRect.width(), dstRect.height()); painter()->renderMirrorMaskSafe(dstRect, m_srcdev, 0, 0, dab, !m_dabCache->needSeparateOriginal()); return effectiveSpacing(dstRect.width(), dstRect.height()); }