Krita Source Code Documentation
Loading...
Searching...
No Matches
PSDLoader Class Reference

#include <psd_loader.h>

+ Inheritance diagram for PSDLoader:

Public Slots

virtual void cancel ()
 

Public Member Functions

KisImportExportErrorCode buildImage (QIODevice &io)
 
KisImageSP image ()
 
 PSDLoader (KisDocument *doc, KisImportUserFeedbackInterface *feedbackInterface)
 
 ~PSDLoader () override
 

Private Member Functions

KisImportExportErrorCode decode (QIODevice &io)
 

Private Attributes

KisDocumentm_doc
 
KisImportUserFeedbackInterfacem_feedbackInterface {nullptr}
 
KisImageSP m_image
 
bool m_stop
 

Detailed Description

Definition at line 19 of file psd_loader.h.

Constructor & Destructor Documentation

◆ PSDLoader()

PSDLoader::PSDLoader ( KisDocument * doc,
KisImportUserFeedbackInterface * feedbackInterface )

Definition at line 62 of file psd_loader.cpp.

63 : m_image(0)
64 , m_doc(doc)
65 , m_stop(false)
66 , m_feedbackInterface(feedbackInterface)
67{
68}
KisDocument * m_doc
Definition psd_loader.h:42
KisImageSP m_image
Definition psd_loader.h:41
bool m_stop
Definition psd_loader.h:43
KisImportUserFeedbackInterface * m_feedbackInterface
Definition psd_loader.h:44

◆ ~PSDLoader()

PSDLoader::~PSDLoader ( )
override

Definition at line 70 of file psd_loader.cpp.

71{
72}

Member Function Documentation

◆ buildImage()

KisImportExportErrorCode PSDLoader::buildImage ( QIODevice & io)

Definition at line 659 of file psd_loader.cpp.

660{
661 return decode(io);
662}
KisImportExportErrorCode decode(QIODevice &io)

References decode().

◆ cancel

void PSDLoader::cancel ( )
virtualslot

Definition at line 670 of file psd_loader.cpp.

671{
672 m_stop = true;
673}

References m_stop.

◆ decode()

KisImportExportErrorCode PSDLoader::decode ( QIODevice & io)
private

PSD has a weird "optimization": if a group layer has only one child layer, it omits it's 'psd_bounding_divider' section. So fi you ever see an unbalanced layers group in PSD, most probably, it is just a single layered group.

In some files saved by PS CS6 the group layer sections seem to be unbalanced. I don't know why it happens because the reporter didn't provide us an example file. So here we just check if the new layer was created, and if not, skip the initialization of masks.

See bug: 357559

Definition at line 74 of file psd_loader.cpp.

75{
76 // open the file
77
78 dbgFile << "pos:" << io.pos();
79
80 PSDHeader header;
81 if (!header.read(io)) {
82 dbgFile << "failed reading header: " << header.error;
84 }
85
86 dbgFile << header;
87 dbgFile << "Read header. pos:" << io.pos();
88
89 PSDColorModeBlock colorModeBlock(header.colormode);
90 if (!colorModeBlock.read(io)) {
91 dbgFile << "failed reading colormode block: " << colorModeBlock.error;
93 }
94
95 dbgFile << "Read color mode block. pos:" << io.pos();
96
97 PSDImageResourceSection resourceSection;
98 if (!resourceSection.read(io)) {
99 dbgFile << "failed image reading resource section: " << resourceSection.error;
101 }
102 dbgFile << "Read image resource section. pos:" << io.pos();
103
104 PSDLayerMaskSection layerSection(header);
105 if (!layerSection.read(io)) {
106 dbgFile << "failed reading layer/mask section: " << layerSection.error;
108 }
109 dbgFile << "Read layer/mask section. " << layerSection.nLayers << "layers. pos:" << io.pos();
110
111 // Done reading, except possibly for the image data block, which is only relevant if there
112 // are no layers.
113
114 // Get the right colorspace
115 QPair<QString, QString> colorSpaceId = psd_colormode_to_colormodelid(header.colormode,
116 header.channelDepth);
117 if (colorSpaceId.first.isNull()) {
118 dbgFile << "Unsupported colorspace" << header.colormode << header.channelDepth;
120 }
121
122 // Get the icc profile from the image resource section
123 const KoColorProfile* profile = 0;
124 if (resourceSection.resources.contains(PSDImageResourceSection::ICC_PROFILE)) {
125 ICC_PROFILE_1039 *iccProfileData = dynamic_cast<ICC_PROFILE_1039*>(resourceSection.resources[PSDImageResourceSection::ICC_PROFILE]->resource);
126 if (iccProfileData ) {
127 profile = KoColorSpaceRegistry::instance()->createColorProfile(colorSpaceId.first,
128 colorSpaceId.second,
129 iccProfileData->icc);
130 dbgFile << "Loaded ICC profile" << profile->name();
131 delete resourceSection.resources.take(PSDImageResourceSection::ICC_PROFILE);
132 }
133 }
134
135 // Create the colorspace
136 const KoColorSpace* cs = KoColorSpaceRegistry::instance()->colorSpace(colorSpaceId.first, colorSpaceId.second, profile);
137 if (!cs) {
139 }
140
141 // Creating the KisImage
142 QFile *file = dynamic_cast<QFile *>(&io);
143 QString name = file ? file->fileName() : "Imported";
144 m_image = new KisImage(m_doc->createUndoStore(), header.width, header.height, cs, name);
145 Q_CHECK_PTR(m_image);
146
147 KisImageBarrierLock lock(m_image);
148
149 // set the correct resolution
150 if (resourceSection.resources.contains(PSDImageResourceSection::RESN_INFO)) {
151 RESN_INFO_1005 *resInfo = dynamic_cast<RESN_INFO_1005*>(resourceSection.resources[PSDImageResourceSection::RESN_INFO]->resource);
152 if (resInfo) {
153 // check resolution size is not zero
154 if (resInfo->hRes * resInfo->vRes > 0)
156 // let's skip the unit for now; we can only set that on the KisDocument, and krita doesn't use it.
157 delete resourceSection.resources.take(PSDImageResourceSection::RESN_INFO);
158 }
159 }
160
161 if (resourceSection.resources.contains(PSDImageResourceSection::GRID_GUIDE)) {
162 GRID_GUIDE_1032 *gridGuidesInfo = dynamic_cast<GRID_GUIDE_1032*>(resourceSection.resources[PSDImageResourceSection::GRID_GUIDE]->resource);
163 if (gridGuidesInfo) {
165 Q_FOREACH(quint32 guide, gridGuidesInfo->verticalGuides) {
166 config.addGuideLine(Qt::Vertical, guide / m_image->xRes());
167 }
168 Q_FOREACH(quint32 guide, gridGuidesInfo->horizontalGuides) {
169 config.addGuideLine(Qt::Horizontal, guide / m_image->yRes());
170 }
171 config.setShowGuides(true);
172 m_doc->setGuidesConfig(config);
173 }
174 }
175
176 // Preserve all the annotations
177 Q_FOREACH (PSDResourceBlock *resourceBlock, resourceSection.resources.values()) {
178 m_image->addAnnotation(resourceBlock);
179 }
180
181 // Preserve the duotone colormode block for saving back to psd
182 if (header.colormode == DuoTone) {
183 KisAnnotationSP annotation = new KisAnnotation("DuotoneColormodeBlock",
184 i18n("Duotone Colormode Block"),
185 colorModeBlock.data);
186 m_image->addAnnotation(annotation);
187 }
188
189 // Load embedded patterns early for fill layers.
190
191 const QVector<QDomDocument> &embeddedPatterns =
192 layerSection.globalInfoSection.embeddedPatterns;
193
194 const QString storageLocation = m_doc->embeddedResourcesStorageId();
195
196 KisEmbeddedResourceStorageProxy resourceProxy(storageLocation);
197
199 if (!embeddedPatterns.isEmpty()) {
200 Q_FOREACH (const QDomDocument &doc, embeddedPatterns) {
201 serializer.registerPSDPattern(doc);
202 }
203 Q_FOREACH (KoPatternSP pattern, serializer.patterns()) {
204 if (pattern && pattern->valid()) {
205 resourceProxy.addResource(pattern);
206 dbgFile << "Loaded embedded pattern: " << pattern->name();
207 }
208 else {
209 qWarning() << "Invalid or empty pattern" << pattern;
210 }
211 }
212 }
213
214 // Read the projection into our single layer. Since we only read the projection when
215 // we have just one layer, we don't need to later on apply the alpha channel of the
216 // first layer to the projection if the number of layers is negative/
217 // See https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#50577409_16000.
218 if (layerSection.nLayers == 0) {
219 dbgFile << "Position" << io.pos() << "Going to read the projection into the first layer, which Photoshop calls 'Background'";
220
221 KisPaintLayerSP layer = new KisPaintLayer(m_image, i18nc("Name for the bottom-most layer in the layerstack", "Background"), OPACITY_OPAQUE_U8);
222
223 PSDImageData imageData(&header);
224 imageData.read(io, layer->paintDevice());
225
226 m_image->addNode(layer, m_image->rootLayer());
227
228 // Only one layer, the background layer, so we're done.
230 }
231
232 // More than one layer, so now construct the Krita image from the info we read.
233
234 QStack<KisGroupLayerSP> groupStack;
235 groupStack.push(m_image->rootLayer());
236
243 KisNodeSP lastAddedLayer;
244
245 typedef QPair<QDomDocument, KisLayerSP> LayerStyleMapping;
246 QVector<LayerStyleMapping> allStylesXml;
247 using namespace std::placeholders;
248
249 bool convertTextToShape = true;
250 for (int i = 0; i < layerSection.nLayers; i++) {
251 if (!layerSection.layers.at(i)->infoBlocks.textData.isNull()) {
253 m_feedbackInterface->askUser([&] (QWidget *parent) {
254 QMessageBox::StandardButton btn = QMessageBox::question(parent,
255 i18nc("@title:window PSD import question about text.", "Found Text Layers"),
256 i18nc("PSD import question about text",
257 "Found text objects, do you wish to load them as editable text shapes? "
258 "If not, they will be loaded as pixel data, which will be visually"
259 " more accurate to the original file."));
260 return (btn == QMessageBox::Yes);
261 });
262 convertTextToShape = (result == KisImportUserFeedbackInterface::Success
264 break;
265 }
266 }
267
268 // read the channels for the various layers
269 for(int i = 0; i < layerSection.nLayers; ++i) {
270
271 PSDLayerRecord* layerRecord = layerSection.layers.at(i);
272 dbgFile << "Going to read channels for layer" << i << layerRecord->layerName;
273 KisLayerSP newLayer;
274 if (layerRecord->infoBlocks.keys.contains("lsct") &&
275 layerRecord->infoBlocks.sectionDividerType != psd_other) {
276
277 if (layerRecord->infoBlocks.sectionDividerType == psd_bounding_divider && !groupStack.isEmpty()) {
278 KisGroupLayerSP groupLayer = new KisGroupLayer(m_image, "temp", OPACITY_OPAQUE_U8);
279 m_image->addNode(groupLayer, groupStack.top());
280 groupStack.push(groupLayer);
281 newLayer = groupLayer;
282 }
283 else if ((layerRecord->infoBlocks.sectionDividerType == psd_open_folder ||
285 (groupStack.size() > 1 || (lastAddedLayer && !groupStack.isEmpty()))) {
286 KisGroupLayerSP groupLayer;
287
288 if (groupStack.size() <= 1) {
289 groupLayer = new KisGroupLayer(m_image, "temp", OPACITY_OPAQUE_U8);
290 m_image->addNode(groupLayer, groupStack.top());
291 m_image->moveNode(lastAddedLayer, groupLayer, KisNodeSP());
292 } else {
293 groupLayer = groupStack.pop();
294 }
295
296 const QDomDocument &styleXml = layerRecord->infoBlocks.layerStyleXml;
297
298 if (!styleXml.isNull()) {
299 allStylesXml << LayerStyleMapping(styleXml, groupLayer);
300 }
301
302 groupLayer->setName(layerRecord->layerName);
303 groupLayer->setVisible(layerRecord->visible);
304
305 QString compositeOp = psd_blendmode_to_composite_op(layerRecord->infoBlocks.sectionDividerBlendMode);
306
307 // Krita doesn't support pass-through blend
308 // mode. Instead it is just a property of a group
309 // layer, so flip it
310 if (compositeOp == COMPOSITE_PASS_THROUGH) {
311 compositeOp = COMPOSITE_OVER;
312 groupLayer->setPassThroughMode(true);
313 }
314
315 groupLayer->setCompositeOpId(compositeOp);
316
317 newLayer = groupLayer;
318 } else {
329 warnKrita << "WARNING: Provided PSD has unbalanced group "
330 << "layer markers. Some masks and/or layers can "
331 << "be lost while loading this file. Please "
332 << "report a bug to Krita developers and attach "
333 << "this file to the bugreport\n"
334 << " " << ppVar(layerRecord->layerName) << "\n"
335 << " " << ppVar(layerRecord->infoBlocks.sectionDividerType) << "\n"
336 << " " << ppVar(groupStack.size());
337 continue;
338 }
339 } else {
340 KisLayerSP layer;
341 if (!layerRecord->infoBlocks.fillConfig.isNull()) {
343 QDomDocument fillConfig;
345
346 KoShape *vectorMask = nullptr;
347 if (layerRecord->infoBlocks.keys.contains("vmsk") || layerRecord->infoBlocks.keys.contains("vsms")) {
349 if (!layerRecord->infoBlocks.vectorOriginationData.isNull()) {
351 psd_vector_origination_data::setupCatcher("/null", catcher, &data);
352 KisAslXmlParser parser;
353 parser.parseXML(layerRecord->infoBlocks.vectorOriginationData, catcher);
354 }
355 QString shapeName = data.shapeName();
357 if (!(data.canMakeParametricShape() && f)) {
358 double width = m_image->width() / m_image->xRes();
359 double height = m_image->height() / m_image->yRes();
360 vectorMask = layerRecord->constructPathShape(layerRecord->infoBlocks.vectorMask.path, width, height);
361 vectorMask->setUserData(new KisShapeSelectionMarker);
362 } else {
363 QSizeF size;
364 double angle;
365 data.OriginalSizeAndAngle(size, angle);
366 double resMultiplier = data.originResolution/72.0;
367 QTransform scaleToPt = QTransform::fromScale(resMultiplier, resMultiplier).inverted();
368 size = QSizeF(size.width()/resMultiplier, size.height()/resMultiplier);
369
371 KoProperties props;
372 if (shapeName == "RectangleShape") {
373 props.setProperty("x", 0);
374 props.setProperty("y", 0);
375 props.setProperty("width", size.width());
376 props.setProperty("height", size.height());
377 } else if (shapeName == "StarShape") {
378 props.setProperty("corners", data.originPolySides);
379 props.setProperty("convex", !data.isStar);
380
381 double angle = 360.0/(data.originPolySides*2);
382 double a = cos(kisDegreesToRadians(angle)) * 100.0;
383 double totalHeight = a + 100.0;
384 double l = size.height() / totalHeight * 100.0;
385
386 if (data.isStar) {
387 // 100% is a normal polygon.
388 a = cos(kisDegreesToRadians(angle)) * ((data.originPolyStarRatio*0.01) * l);
389 props.setProperty("baseRadius", a);
390 }
391 props.setProperty("tipRadius", l);
392 props.setProperty("baseRoundness", 0.0);
393 props.setProperty("tipRoundness", 0.0);
394 }
395 KoShape *shape = f->createShape(&props, &manager);
396 if (!shape)
397 continue;
398 shape->setSize(size);
399 QTransform t;
400 t.rotate(360.0-angle);
401
402 shape->setTransformation(t * scaleToPt.inverted() * data.transform * scaleToPt);
403 shape->setAbsolutePosition(scaleToPt.map(data.originShapeBBox.center()));
404
405 vectorMask = shape;
406 }
407 }
408 if (layerRecord->infoBlocks.fillType == psd_fill_gradient) {
409 cfg = KisGeneratorRegistry::instance()->value("gradient")->defaultConfiguration(resourceProxy.resourcesInterface());
410
412 fill.imageWidth = m_image->width();
413 fill.imageHeight = m_image->height();
414 psd_layer_gradient_fill::setupCatcher("/null", catcher, &fill);
415 KisAslXmlParser parser;
416 parser.parseXML(layerRecord->infoBlocks.fillConfig, catcher);
417 fillConfig = fill.getFillLayerConfig();
418 if (vectorMask) {
419 vectorMask->setBackground(fill.getBackground());
420 }
421
422 } else if (layerRecord->infoBlocks.fillType == psd_fill_pattern) {
423 cfg = KisGeneratorRegistry::instance()->value("pattern")->defaultConfiguration(resourceProxy.resourcesInterface());
424
426 psd_layer_pattern_fill::setupCatcher("/null", catcher, &fill);
427
428 KisAslXmlParser parser;
429 parser.parseXML(layerRecord->infoBlocks.fillConfig, catcher);
430 fillConfig = fill.getFillLayerConfig();
431 if (vectorMask) {
432 vectorMask->setBackground(fill.getBackground(resourceProxy));
433 }
434
435 } else {
436 cfg = KisGeneratorRegistry::instance()->value("color")->defaultConfiguration(resourceProxy.resourcesInterface());
437
439 fill.cs = m_image->colorSpace();
440 psd_layer_solid_color::setupCatcher("/null", catcher, &fill);
441 KisAslXmlParser parser;
442 parser.parseXML(layerRecord->infoBlocks.fillConfig, catcher);
443
444 fillConfig = fill.getFillLayerConfig();
445 if (vectorMask) {
446 vectorMask->setBackground(fill.getBackground());
447 }
448 }
449 if (vectorMask) {
450 KisShapeLayerSP shapeLayer = new KisShapeLayer(m_doc->shapeController(), m_image, layerRecord->layerName, layerRecord->opacity);
451
452
453 if (!layerRecord->infoBlocks.vectorStroke.isNull()) {
454 KoShapeStrokeSP stroke(new KoShapeStroke());
458 fill.cs = m_image->colorSpace();
459 KisAslCallbackObjectCatcher strokeCatcher;
460 psd_vector_stroke_data::setupCatcher("", strokeCatcher, &data);
461 psd_layer_solid_color::setupCatcher("/strokeStyle/strokeStyleContent", strokeCatcher, &fill);
462 psd_layer_gradient_fill::setupCatcher("/strokeStyle/strokeStyleContent", strokeCatcher, &grad);
463 KisAslXmlParser parser;
464 parser.parseXML(layerRecord->infoBlocks.vectorStroke, strokeCatcher);
465
466 if (!data.fillEnabled) {
468 }
469 if (data.strokeEnabled) {
470 QColor c = fill.getBrush().color();
471 c.setAlphaF(data.opacity);
472 stroke->setColor(c);
473 if (!grad.gradient.isNull()) {
474 stroke->setLineBrush(grad.getBrush());
475 }
476 } else {
477 stroke->setColor(Qt::transparent);
478 }
479 data.setupShapeStroke(stroke);
480
481 vectorMask->setStroke(stroke);
482 }
483
484 shapeLayer->addShape(vectorMask);
485 layer = shapeLayer;
486 } else {
487 cfg->fromXML(fillConfig.firstChildElement());
488 cfg->createLocalResourcesSnapshot();
489 KisGeneratorLayerSP genlayer = new KisGeneratorLayer(m_image, layerRecord->layerName, cfg, m_image->globalSelection());
490 genlayer->setFilter(cfg);
491 layer = genlayer;
492 }
493
494
495 } else if (!layerRecord->infoBlocks.textData.isNull() && convertTextToShape) {
496 KisShapeLayerSP textLayer = new KisShapeLayer(m_doc->shapeController(), m_image, layerRecord->layerName, layerRecord->opacity);
499 psd_layer_type_shape::setupCatcher(QString(), catcher, &text);
500 KisAslXmlParser parser;
501 parser.parseXML(layerRecord->infoBlocks.textData, catcher);
502 KoSvgTextShape *shape = new KoSvgTextShape();
503 PsdTextDataConverter converter;
504 KoSvgTextShapeMarkupConverter svgConverter(shape);
505
506 QString svg;
507 QString styles;
508 // This is to align inlinesize appropriately.
509 bool offsetByAscent = false;
510 QPointF offset1;
511 // PSD text layers have all their coordinates in pixels, and because fonts can be very precise-unit sensitive,
512 // we want to ensure all values are scaled appropriately.
513
514 QTransform scaleToPt = QTransform::fromScale(m_image->xRes(), m_image->yRes()).inverted();
515 bool res = converter.convertPSDTextEngineDataToSVG(text.engineData,
516 layerSection.globalInfoSection.txt2Data,
518 text.textIndex,
519 &svg, &styles,
520 offset1, offsetByAscent,
521 text.isHorizontal, scaleToPt);
522 if (!res || !converter.errors().isEmpty()) {
523 qWarning() << converter.errors();
524 }
525 dbgFile << converter.warnings();
526 svgConverter.convertFromSvg(svg, styles, m_image->bounds(), m_image->xRes()*72.0);
527 if (offsetByAscent) {
528 QPointF offset2 = QPointF() - shape->outlineRect().topLeft();
529 if (text.isHorizontal) {
530 offset2.setX(offset1.x());
531 } else {
532 offset2.setY(offset1.y());
533 }
534 shape->setTransformation(QTransform::fromTranslate(offset2.x(), offset2.y()) * scaleToPt.inverted()
535 * layerRecord->infoBlocks.textTransform * scaleToPt);
536 } else {
537 shape->setTransformation(scaleToPt.inverted() * layerRecord->infoBlocks.textTransform * scaleToPt);
538 }
539 textLayer->addShape(shape);
540 layer = textLayer;
541 } else {
542 layer = new KisPaintLayer(m_image, layerRecord->layerName, layerRecord->opacity);
543 if (!layerRecord->readPixelData(io, layer->paintDevice())) {
544 dbgFile << "failed reading channels for layer: " << layerRecord->layerName << layerRecord->error;
546 }
547 }
549
550 layer->setColorLabelIndex(layerRecord->labelColor);
551
552 const QDomDocument &styleXml = layerRecord->infoBlocks.layerStyleXml;
553
554 if (!styleXml.isNull()) {
555 allStylesXml << LayerStyleMapping(styleXml, layer);
556 }
557
558 if (!groupStack.isEmpty()) {
559 m_image->addNode(layer, groupStack.top());
560 }
561 else {
562 m_image->addNode(layer, m_image->root());
563 }
564 layer->setVisible(layerRecord->visible);
565 newLayer = layer;
566
567 }
568
569 Q_FOREACH (ChannelInfo *channelInfo, layerRecord->channelInfoRecords) {
570 if (channelInfo->channelId < -1) {
571 const KisGeneratorLayer *fillLayer = qobject_cast<KisGeneratorLayer *>(newLayer.data());
572 const KisShapeLayer *shapeLayer = qobject_cast<KisShapeLayer *>(newLayer.data());
573 KoPathShape *vectorMask = new KoPathShape();
574 if (layerRecord->infoBlocks.keys.contains("vmsk") || layerRecord->infoBlocks.keys.contains("vsms")) {
575 double width = m_image->width() / m_image->xRes();
576 double height = m_image->height() / m_image->yRes();
577 vectorMask = layerRecord->constructPathShape(layerRecord->infoBlocks.vectorMask.path, width, height);
578 vectorMask->setUserData(new KisShapeSelectionMarker);
579 }
580 bool hasVectorMask = vectorMask->pointCount() > 0 && layerRecord->infoBlocks.vectorMask.path.subPaths.size() > 0;
581 if (fillLayer) {
582 if (!layerRecord->readMask(io, fillLayer->paintDevice(), channelInfo)) {
583 dbgFile << "failed reading masks for generator layer: " << layerRecord->layerName << layerRecord->error;
584 }
585 if (hasVectorMask) {
586 KisShapeSelection* shapeSelection = new KisShapeSelection(m_doc->shapeController(), fillLayer->internalSelection());
587 fillLayer->internalSelection()->convertToVectorSelectionNoUndo(shapeSelection);
588 shapeSelection->addShape(vectorMask);
589 fillLayer->internalSelection()->updateProjection();
590 }
591 } else {
592 if (!(shapeLayer && hasVectorMask)) {
593 KisTransparencyMaskSP mask = new KisTransparencyMask(m_image, i18n("Transparency Mask"));
594 mask->initSelection(newLayer);
595 if (!layerRecord->readMask(io, mask->paintDevice(), channelInfo)) {
596 dbgFile << "failed reading masks for layer: " << layerRecord->layerName << layerRecord->error;
597 }
598 if (hasVectorMask) {
599 KisShapeSelection* shapeSelection = new KisShapeSelection(m_doc->shapeController(), mask->selection());
600 mask->selection()->convertToVectorSelectionNoUndo(shapeSelection);
601 shapeSelection->addShape(vectorMask);
602 mask->selection()->updateProjection();
603 }
604 m_image->addNode(mask, newLayer);
605 }
606 }
607 }
608 }
609
610 lastAddedLayer = newLayer;
611 }
612
613 if (!allStylesXml.isEmpty()) {
614 Q_FOREACH (const LayerStyleMapping &mapping, allStylesXml) {
615
616 serializer.readFromPSDXML(mapping.first);
617
618 if (serializer.styles().size() == 1) {
619 KisPSDLayerStyleSP layerStyle = serializer.styles().first();
620 KisLayerSP layer = mapping.second;
621
622 Q_FOREACH (KoAbstractGradientSP gradient, serializer.gradients()) {
623 if (gradient && gradient->valid()) {
624 resourceProxy.addResource(gradient);
625 }
626 else {
627 qWarning() << "Invalid or empty gradient" << gradient;
628 }
629 }
630
631 Q_FOREACH (const KoPatternSP &pattern, serializer.patterns()) {
632 if (pattern && pattern->valid()) {
633 resourceProxy.addResource(pattern);
634 } else {
635 qWarning() << "Invalid or empty pattern" << pattern;
636 }
637 }
638
639 layerStyle->setName(layer->name());
640 layerStyle->setResourcesInterface(resourceProxy.detachedResourcesInterface());
641 if (!layerStyle->uuid().isNull()) {
642 layerStyle->setUuid(QUuid::createUuid());
643 }
644 layerStyle->setValid(true);
645
646 resourceProxy.addResource(layerStyle);
647
648 layer->setLayerStyle(layerStyle->cloneWithResourcesSnapshot(layerStyle->resourcesInterface(), 0));
649 } else {
650 warnKrita << "WARNING: Couldn't read layer style!" << ppVar(serializer.styles());
651 }
652
653 }
654 }
655
657}
const quint8 OPACITY_OPAQUE_U8
const QString COMPOSITE_OVER
const QString COMPOSITE_PASS_THROUGH
constexpr qreal POINT_TO_INCH(qreal px)
Definition KoUnit.h:37
A data extension mechanism for Krita.
QVector< KoAbstractGradientSP > gradients() const
QVector< KisPSDLayerStyleSP > styles() const
void readFromPSDXML(const QDomDocument &doc)
void registerPSDPattern(const QDomDocument &doc)
QHash< QString, KoPatternSP > patterns() const
void parseXML(const QDomDocument &doc, KisAslObjectCatcher &catcher)
KisUndoStore * createUndoStore()
KisShapeController * shapeController
QString embeddedResourcesStorageId() const
void setGuidesConfig(const KisGuidesConfig &data)
KisGuidesConfig guidesConfig
static KisGeneratorRegistry * instance()
void setShowGuides(bool value)
void addGuideLine(Qt::Orientation orientation, qreal position)
Add a guide line to the canvas.
void addAnnotation(KisAnnotationSP annotation)
KisGroupLayerSP rootLayer() const
const KoColorSpace * colorSpace() const
qint32 width() const
double xRes() const
double yRes() const
qint32 height() const
KisSelectionSP globalSelection() const
Definition kis_image.cc:695
QRect bounds() const override
void setResolution(double xres, double yres)
virtual Result askUser(AskCallback callback)=0
ask the user a question about the loading process
const T value(const QString &id) const
The position of a path point within a path shape.
Definition KoPathShape.h:63
int pointCount() const
Returns the number of points in the path.
void setProperty(const QString &name, const QVariant &value)
void addShape(KoShape *shape)
static KoShapeRegistry * instance()
virtual void setStroke(KoShapeStrokeModelSP stroke)
Definition KoShape.cpp:1081
void setTransformation(const QTransform &matrix)
Definition KoShape.cpp:417
virtual void setBackground(QSharedPointer< KoShapeBackground > background)
Definition KoShape.cpp:918
void setUserData(KoShapeUserData *userData)
Definition KoShape.cpp:705
void setAbsolutePosition(const QPointF &newPosition, KoFlake::AnchorPosition anchor=KoFlake::Center)
Definition KoShape.cpp:668
virtual void setSize(const QSizeF &size)
Resize the shape.
Definition KoShape.cpp:276
QRectF outlineRect() const override
bool read(QIODevice &device)
QString error
Definition psd_header.h:52
QMap< PSDResourceID, PSDResourceBlock * > resources
PsdAdditionalLayerInfoBlock infoBlocks
bool readPixelData(QIODevice &io, KisPaintDeviceSP device)
QVector< ChannelInfo * > channelInfoRecords
KoPathShape * constructPathShape(psd_path path, double shapeWidth, double shapeHeight)
constructPathShape create a KoPathshape based on a psd_path struct, used in vector masks and path res...
bool readMask(QIODevice &io, KisPaintDeviceSP dev, ChannelInfo *channel)
The PsdTextDataConverter class.
bool convertPSDTextEngineDataToSVG(const QVariantHash tySh, const QVariantHash txt2, const KoColorSpace *imageCs, const int textIndex, QString *svgText, QString *svgStyles, QPointF &offset, bool &offsetByAscent, bool &isHorizontal, QTransform scaleToPt=QTransform())
#define warnKrita
Definition kis_debug.h:87
#define ppVar(var)
Definition kis_debug.h:155
#define dbgFile
Definition kis_debug.h:53
T kisDegreesToRadians(T degrees)
Definition kis_global.h:176
KisSharedPtr< KisNode > KisNodeSP
Definition kis_types.h:86
const char * name(StandardAction id)
int size(const Forest< T > &forest)
Definition KisForest.h:1232
KisImportExportErrorCode workaroundUnsuitableImageColorSpace(KisImageSP image, KisImportUserFeedbackInterface *feedbackInterface, KisImageBarrierLock &lock)
QPair< QString, QString > psd_colormode_to_colormodelid(psd_color_mode colormode, quint16 channelDepth)
Definition psd.cpp:16
QString psd_blendmode_to_composite_op(const QString &blendmode)
Definition psd.cpp:59
@ psd_other
Definition psd.h:144
@ psd_open_folder
Definition psd.h:144
@ psd_closed_folder
Definition psd.h:144
@ psd_bounding_divider
Definition psd.h:144
@ psd_fill_gradient
Definition psd.h:125
@ psd_fill_pattern
Definition psd.h:126
@ DuoTone
Definition psd.h:57
QList< quint32 > verticalGuides
QList< quint32 > horizontalGuides
virtual void setVisible(bool visible, bool loading=false)
void setColorLabelIndex(int index)
void setName(const QString &name)
virtual KisPaintDeviceSP paintDevice() const =0
QString name() const
void setCompositeOpId(const QString &compositeOpId)
virtual KisFilterConfigurationSP defaultConfiguration(KisResourcesInterfaceSP resourcesInterface) const
void setFilter(KisFilterConfigurationSP filterConfig, bool checkCompareConfig=true) override
void setPassThroughMode(bool value)
void setLayerStyle(KisPSDLayerStyleSP layerStyle)
Definition kis_layer.cc:254
void initSelection(KisSelectionSP copyFrom, KisLayerSP parentLayer)
initSelection initializes the selection for the mask from the given selection's projection.
Definition kis_mask.cc:157
KisSelectionSP selection
Definition kis_mask.cc:44
KisPaintDeviceSP paintDevice() const override
Definition kis_mask.cc:223
bool addNode(KisNodeSP node, KisNodeSP parent=KisNodeSP(), KisNodeAdditionFlags flags=KisNodeAdditionFlag::None)
bool moveNode(KisNodeSP node, KisNodeSP parent, KisNodeSP aboveThis)
KisPaintDeviceSP paintDevice
KisSelectionSP internalSelection() const
void updateProjection(const QRect &rect)
void convertToVectorSelectionNoUndo(KisSelectionComponent *shapeSelection)
const KoColorSpace * colorSpace(const QString &colorModelId, const QString &colorDepthId, const KoColorProfile *profile)
static KoColorSpaceRegistry * instance()
const KoColorProfile * createColorProfile(const QString &colorModelId, const QString &colorDepthId, const QByteArray &rawData)
static void setupCatcher(const QString path, KisAslCallbackObjectCatcher &catcher, psd_layer_gradient_fill *data)
QSharedPointer< KoShapeBackground > getBackground()
QSharedPointer< KoShapeBackground > getBackground(KisEmbeddedResourceStorageProxy &embeddedProxy)
static void setupCatcher(const QString path, KisAslCallbackObjectCatcher &catcher, psd_layer_pattern_fill *data)
QSharedPointer< KoShapeBackground > getBackground()
static void setupCatcher(const QString path, KisAslCallbackObjectCatcher &catcher, psd_layer_solid_color *data)
static void setupCatcher(const QString path, KisAslCallbackObjectCatcher &catcher, psd_layer_type_shape *data)
QList< psd_path_sub_path > subPaths
static void setupCatcher(const QString path, KisAslCallbackObjectCatcher &catcher, psd_vector_origination_data *data)
double originResolution
Resolution of the coordinates.
void OriginalSizeAndAngle(QSizeF &size, double &angle)
double originPolyStarRatio
Only for 8, percentage of small radius to big radius.
static void setupCatcher(const QString path, KisAslCallbackObjectCatcher &catcher, psd_vector_stroke_data *data)
void setupShapeStroke(KoShapeStrokeSP stroke)

References KisImage::addAnnotation(), KisGuidesConfig::addGuideLine(), KisNodeFacade::addNode(), KisEmbeddedResourceStorageProxy::addResource(), KoShapeContainer::addShape(), KisImportUserFeedbackInterface::askUser(), PSDLayerRecord::blendModeKey, KisImage::bounds(), psd_vector_origination_data::canMakeParametricShape(), PSDHeader::channelDepth, ChannelInfo::channelId, PSDLayerRecord::channelInfoRecords, PSDHeader::colormode, KisImage::colorSpace(), KoColorSpaceRegistry::colorSpace(), COMPOSITE_OVER, COMPOSITE_PASS_THROUGH, PSDLayerRecord::constructPathShape(), KoSvgTextShapeMarkupConverter::convertFromSvg(), PsdTextDataConverter::convertPSDTextEngineDataToSVG(), KisSelection::convertToVectorSelectionNoUndo(), KoColorSpaceRegistry::createColorProfile(), KisDocument::createUndoStore(), psd_layer_solid_color::cs, KisSharedPtr< T >::data(), PSDColorModeBlock::data, dbgFile, KisBaseProcessor::defaultConfiguration(), KisEmbeddedResourceStorageProxy::detachedResourcesInterface(), DuoTone, PsdAdditionalLayerInfoBlock::embeddedPatterns, KisDocument::embeddedResourcesStorageId(), psd_layer_type_shape::engineData, PSDHeader::error, PSDLayerRecord::error, PSDLayerMaskSection::error, PSDImageResourceSection::error, PSDColorModeBlock::error, PsdTextDataConverter::errors(), ImportExportCodes::FileFormatIncorrect, PsdAdditionalLayerInfoBlock::fillConfig, psd_vector_stroke_data::fillEnabled, PsdAdditionalLayerInfoBlock::fillType, ImportExportCodes::FormatColorSpaceUnsupported, psd_layer_solid_color::getBackground(), psd_layer_gradient_fill::getBackground(), psd_layer_pattern_fill::getBackground(), psd_layer_solid_color::getBrush(), psd_layer_gradient_fill::getBrush(), psd_layer_solid_color::getFillLayerConfig(), psd_layer_gradient_fill::getFillLayerConfig(), psd_layer_pattern_fill::getFillLayerConfig(), PSDLayerMaskSection::globalInfoSection, KisImage::globalSelection(), psd_layer_gradient_fill::gradient, KisAslLayerStyleSerializer::gradients(), PSDImageResourceSection::GRID_GUIDE, KisDocument::guidesConfig, KisImage::height(), PSDHeader::height, GRID_GUIDE_1032::horizontalGuides, RESN_INFO_1005::hRes, ICC_PROFILE_1039::icc, PSDImageResourceSection::ICC_PROFILE, psd_layer_gradient_fill::imageHeight, psd_layer_gradient_fill::imageWidth, PSDLayerRecord::infoBlocks, KisMask::initSelection(), KoShapeRegistry::instance(), KisGeneratorRegistry::instance(), KoColorSpaceRegistry::instance(), KisSelectionBasedLayer::internalSelection(), psd_layer_type_shape::isHorizontal, psd_vector_origination_data::isStar, PsdAdditionalLayerInfoBlock::keys, kisDegreesToRadians(), PSDLayerRecord::labelColor, PSDLayerRecord::layerName, PSDLayerMaskSection::layers, PsdAdditionalLayerInfoBlock::layerStyleXml, m_doc, m_feedbackInterface, m_image, KisNodeFacade::moveNode(), KisBaseNode::name(), KoColorProfile::name, PSDLayerMaskSection::nLayers, ImportExportCodes::OK, psd_vector_stroke_data::opacity, PSDLayerRecord::opacity, OPACITY_OPAQUE_U8, psd_vector_origination_data::OriginalSizeAndAngle(), psd_vector_origination_data::originPolySides, psd_vector_origination_data::originPolyStarRatio, psd_vector_origination_data::originResolution, psd_vector_origination_data::originShapeBBox, KoSvgTextShape::outlineRect(), KisBaseNode::paintDevice(), KisMask::paintDevice(), KisPaintLayer::paintDevice, KisSelectionBasedLayer::paintDevice, KisAslXmlParser::parseXML(), psd_vector_mask::path, KisAslLayerStyleSerializer::patterns(), POINT_TO_INCH(), KoPathShape::pointCount(), ppVar, psd_blendmode_to_composite_op(), psd_bounding_divider, psd_closed_folder, psd_colormode_to_colormodelid(), psd_fill_gradient, psd_fill_pattern, psd_open_folder, psd_other, PSDHeader::read(), PSDLayerMaskSection::read(), PSDImageResourceSection::read(), PSDColorModeBlock::read(), PSDImageData::read(), KisAslLayerStyleSerializer::readFromPSDXML(), PSDLayerRecord::readMask(), PSDLayerRecord::readPixelData(), KisAslLayerStyleSerializer::registerPSDPattern(), PSDImageResourceSection::RESN_INFO, PSDImageResourceSection::resources, KisEmbeddedResourceStorageProxy::resourcesInterface(), KisNodeFacade::root, KisImage::rootLayer(), PsdAdditionalLayerInfoBlock::sectionDividerBlendMode, PsdAdditionalLayerInfoBlock::sectionDividerType, KisMask::selection, KoShape::setAbsolutePosition(), KoShape::setBackground(), KisBaseNode::setColorLabelIndex(), KisBaseNode::setCompositeOpId(), KisGeneratorLayer::setFilter(), KisDocument::setGuidesConfig(), KisLayer::setLayerStyle(), KisBaseNode::setName(), KisGroupLayer::setPassThroughMode(), KoProperties::setProperty(), KisImage::setResolution(), KisGuidesConfig::setShowGuides(), KoShape::setSize(), KoShape::setStroke(), KoShape::setTransformation(), psd_layer_gradient_fill::setupCatcher(), psd_layer_pattern_fill::setupCatcher(), psd_layer_solid_color::setupCatcher(), psd_layer_type_shape::setupCatcher(), psd_vector_origination_data::setupCatcher(), psd_vector_stroke_data::setupCatcher(), psd_vector_stroke_data::setupShapeStroke(), KoShape::setUserData(), KisBaseNode::setVisible(), KisDocument::shapeController, psd_vector_origination_data::shapeName(), psd_vector_stroke_data::strokeEnabled, KisAslLayerStyleSerializer::styles(), psd_path::subPaths, KisImportUserFeedbackInterface::Success, KisImportUserFeedbackInterface::SuppressedByBatchMode, PsdAdditionalLayerInfoBlock::textData, psd_layer_type_shape::textIndex, PsdAdditionalLayerInfoBlock::textTransform, psd_vector_origination_data::transform, PsdAdditionalLayerInfoBlock::txt2Data, KisSelection::updateProjection(), KoGenericRegistry< T >::value(), PsdAdditionalLayerInfoBlock::vectorMask, PsdAdditionalLayerInfoBlock::vectorOriginationData, PsdAdditionalLayerInfoBlock::vectorStroke, GRID_GUIDE_1032::verticalGuides, PSDLayerRecord::visible, RESN_INFO_1005::vRes, PsdTextDataConverter::warnings(), warnKrita, KisImage::width(), PSDHeader::width, KritaUtils::workaroundUnsuitableImageColorSpace(), KisImage::xRes(), and KisImage::yRes().

◆ image()

KisImageSP PSDLoader::image ( )

Definition at line 665 of file psd_loader.cpp.

666{
667 return m_image;
668}

References m_image.

Member Data Documentation

◆ m_doc

KisDocument* PSDLoader::m_doc
private

Definition at line 42 of file psd_loader.h.

◆ m_feedbackInterface

KisImportUserFeedbackInterface* PSDLoader::m_feedbackInterface {nullptr}
private

Definition at line 44 of file psd_loader.h.

44{nullptr};

◆ m_image

KisImageSP PSDLoader::m_image
private

Definition at line 41 of file psd_loader.h.

◆ m_stop

bool PSDLoader::m_stop
private

Definition at line 43 of file psd_loader.h.


The documentation for this class was generated from the following files: