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

#include <psd_layer_record.h>

Classes

struct  LayerBlendingRanges
 
struct  LayerMaskData
 

Public Member Functions

void addPathShapeToPSDPath (psd_path &path, KoPathShape *shape, double shapeWidth, double shapeHeight)
 addPathShapeToPSDPath add all KoPathShape subpaths to the given psd_path struct.
 
QRect channelRect (ChannelInfo *channel) const
 
KoPathShapeconstructPathShape (psd_path path, double shapeWidth, double shapeHeight)
 constructPathShape create a KoPathshape based on a psd_path struct, used in vector masks and path resources.
 
 PSDLayerRecord (const PSDHeader &header)
 
bool read (QIODevice &io)
 
bool readMask (QIODevice &io, KisPaintDeviceSP dev, ChannelInfo *channel)
 
bool readPixelData (QIODevice &io, KisPaintDeviceSP device)
 
bool valid ()
 
void write (QIODevice &io, KisPaintDeviceSP layerContentDevice, KisNodeSP onlyTransparencyMask, const QRect &maskRect, psd_section_type sectionType, const QDomDocument &stylesXmlDoc, bool useLfxsLayerStyleFormat)
 
void writePixelData (QIODevice &io, psd_compression_type compressionType)
 
 ~PSDLayerRecord ()
 

Public Attributes

LayerBlendingRanges blendingRanges
 
QString blendModeKey
 
qint32 bottom {0}
 
QVector< ChannelInfo * > channelInfoRecords
 
quint8 clipping {0}
 
QString error
 
QDomDocument fillConfig
 
psd_fill_type fillType {psd_fill_solid_color}
 
PsdAdditionalLayerInfoBlock infoBlocks
 
bool irrelevant {false}
 
bool isPassThrough {false}
 
int labelColor {0}
 
LayerMaskData layerMask
 
QString layerName {"UNINITIALIZED"}
 
qint32 left {0}
 
quint16 nChannels {0}
 
quint8 opacity {0}
 
qint32 right {0}
 
psd_layer_type_shape textShape
 
qint32 top {0}
 
bool transparencyProtected {false}
 
psd_vector_mask vectorMask
 
QDomDocument vectorOriginationData
 
QDomDocument vectorStroke
 
bool visible {true}
 

Private Member Functions

KisPaintDeviceSP convertMaskDeviceIfNeeded (KisPaintDeviceSP dev)
 
int kritaColorLabelIndex (quint16 labelColor)
 
quint16 psdLabelColor (int colorLabelIndex)
 
template<psd_byte_order byteOrder = psd_byte_order::psdBigEndian>
bool readImpl (QIODevice &io)
 
template<psd_byte_order byteOrder = psd_byte_order::psdBigEndian>
void writeImpl (QIODevice &io, KisPaintDeviceSP layerContentDevice, KisNodeSP onlyTransparencyMask, const QRect &maskRect, psd_section_type sectionType, const QDomDocument &stylesXmlDoc, bool useLfxsLayerStyleFormat)
 
template<psd_byte_order = psd_byte_order::psdBigEndian>
void writePixelDataImpl (QIODevice &io, psd_compression_type compressionType)
 
template<psd_byte_order = psd_byte_order::psdBigEndian>
void writeTransparencyMaskPixelData (QIODevice &io)
 

Private Attributes

const PSDHeader m_header
 
KisPaintDeviceSP m_layerContentDevice
 
KisNodeSP m_onlyTransparencyMask
 
QRect m_onlyTransparencyMaskRect
 
qint64 m_transparencyMaskSizeOffset {0}
 

Detailed Description

Definition at line 68 of file psd_layer_record.h.

Constructor & Destructor Documentation

◆ PSDLayerRecord()

PSDLayerRecord::PSDLayerRecord ( const PSDHeader & header)

Definition at line 162 of file psd_layer_record.cpp.

163 : infoBlocks(header)
164 , m_header(header)
165{
166}
PsdAdditionalLayerInfoBlock infoBlocks
const PSDHeader m_header

◆ ~PSDLayerRecord()

PSDLayerRecord::~PSDLayerRecord ( )
inline

Definition at line 73 of file psd_layer_record.h.

74 {
75 qDeleteAll(channelInfoRecords);
76 }
QVector< ChannelInfo * > channelInfoRecords

Member Function Documentation

◆ addPathShapeToPSDPath()

void PSDLayerRecord::addPathShapeToPSDPath ( psd_path & path,
KoPathShape * shape,
double shapeWidth,
double shapeHeight )

addPathShapeToPSDPath add all KoPathShape subpaths to the given psd_path struct.

Parameters
shapeWidththe image width in points
shapeHeightthe image height in points

Definition at line 987 of file psd_layer_record.cpp.

988{
989 QTransform tf = QTransform::fromScale(shapeWidth, shapeHeight).inverted();
990 tf = shape->absoluteTransformation()*tf;
991
992
993 for (int i = 0; i < shape->subpathCount(); i++) {
994 psd_path_sub_path subPath;
995 subPath.isClosed = shape->isClosedSubpath(i);
996 while(subPath.nodes.size() < shape->subpathPointCount(i)) {
997 const KoPathPoint *point = shape->pointByIndex(KoPathPointIndex(i, subPath.nodes.size()));
998 psd_path_node node;
999 node.node = tf.map(point->point());
1000 node.control1 = point->activeControlPoint1()? tf.map(point->controlPoint1()): node.node;
1001 node.control2 = point->activeControlPoint2()? tf.map(point->controlPoint2()): node.node;
1002
1003 node.isSmooth = (point->properties().testFlag(KoPathPoint::IsSmooth)
1004 || point->properties().testFlag(KoPathPoint::IsSymmetric));
1005 subPath.nodes.append(node);
1006 }
1007
1008 path.subPaths.append(subPath);
1009 }
1010}
QPair< int, int > KoPathPointIndex
Definition KoPathShape.h:28
A KoPathPoint represents a point in a path.
PointProperties properties
QPointF point
QPointF controlPoint1
@ IsSmooth
it is smooth, both control points on a line through the point
Definition KoPathPoint.h:41
@ IsSymmetric
it is symmetric, like smooth but control points have same distance to point
Definition KoPathPoint.h:42
bool activeControlPoint1
bool activeControlPoint2
QPointF controlPoint2
int subpathPointCount(int subpathIndex) const
Returns the number of points in a subpath.
bool isClosedSubpath(int subpathIndex) const
Checks if a subpath is closed.
int subpathCount() const
Returns the number of subpaths in the path.
KoPathPoint * pointByIndex(const KoPathPointIndex &pointIndex) const
Returns the path point specified by a path point index.
QTransform absoluteTransformation() const
Definition KoShape.cpp:382

References KoShape::absoluteTransformation(), KoPathPoint::activeControlPoint1, KoPathPoint::activeControlPoint2, psd_path_node::control1, psd_path_node::control2, KoPathPoint::controlPoint1, KoPathPoint::controlPoint2, psd_path_sub_path::isClosed, KoPathShape::isClosedSubpath(), KoPathPoint::IsSmooth, psd_path_node::isSmooth, KoPathPoint::IsSymmetric, psd_path_node::node, psd_path_sub_path::nodes, KoPathPoint::point, KoPathShape::pointByIndex(), KoPathPoint::properties, KoPathShape::subpathCount(), and KoPathShape::subpathPointCount().

◆ channelRect()

◆ constructPathShape()

KoPathShape * PSDLayerRecord::constructPathShape ( psd_path path,
double shapeWidth,
double shapeHeight )

constructPathShape create a KoPathshape based on a psd_path struct, used in vector masks and path resources.

Parameters
patha psd path struct.
shapeWidththe image width in points
shapeHeightthe image height in points
vogkextra vector data from the vogk layer info block.
Returns
a KoPathShape.

Definition at line 941 of file psd_layer_record.cpp.

942{
943 KoPathShape *shape = new KoPathShape();
944
945 // psd paths are stored normalized.
946 QTransform tf = QTransform::fromScale(shapeWidth, shapeHeight);
947
948 QString nodeTypes;
949 Q_FOREACH(psd_path_sub_path subPath, path.subPaths) {
950 for (int i = 0; i < subPath.nodes.size(); i++) {
951 psd_path_node node = subPath.nodes.at(i);
952 if (i == 0) {
953 shape->moveTo(tf.map(node.node));
954 } else {
955 psd_path_node previousNode = subPath.nodes.at(i-1);
956 if (previousNode.node == previousNode.control2 && node.node == node.control1) {
957 shape->lineTo(tf.map(node.node));
958 } else {
959 shape->curveTo(tf.map(previousNode.control2), tf.map(node.control1), tf.map(node.node));
960 }
961 }
962 if (node.isSmooth) {
963 nodeTypes.append("s");
964 } else {
965 nodeTypes.append("c");
966 }
967 }
968 if (subPath.isClosed) {
969 psd_path_node lastNode = subPath.nodes.last();
970 psd_path_node firstNode = subPath.nodes.first();
971 if (lastNode.node == lastNode.control2 && firstNode.node == firstNode.control1) {
972 shape->lineTo(tf.map(firstNode.node));
973 } else {
974 shape->curveTo(tf.map(lastNode.control2), tf.map(firstNode.control1), tf.map(firstNode.node));
975 }
976 shape->closeMerge();
977 }
978
979 }
980 if (shape->pointCount() > 0) {
981 shape->loadNodeTypes(nodeTypes);
982 }
983
984 return shape;
985}
The position of a path point within a path shape.
Definition KoPathShape.h:63
KoPathPoint * lineTo(const QPointF &p)
Adds a new line segment.
void closeMerge()
Closes the current subpath.
KoPathPoint * moveTo(const QPointF &p)
Starts a new Subpath.
int pointCount() const
Returns the number of points in the path.
KoPathPoint * curveTo(const QPointF &c1, const QPointF &c2, const QPointF &p)
Adds a new cubic Bezier curve segment.
void loadNodeTypes(const QString &nodeTypes)
Loads node types.

References KoPathShape::closeMerge(), psd_path_node::control1, psd_path_node::control2, KoPathShape::curveTo(), psd_path_sub_path::isClosed, psd_path_node::isSmooth, KoPathShape::lineTo(), KoPathShape::loadNodeTypes(), KoPathShape::moveTo(), psd_path_node::node, psd_path_sub_path::nodes, and KoPathShape::pointCount().

◆ convertMaskDeviceIfNeeded()

KisPaintDeviceSP PSDLayerRecord::convertMaskDeviceIfNeeded ( KisPaintDeviceSP dev)
private

Definition at line 713 of file psd_layer_record.cpp.

714{
715 KisPaintDeviceSP result = dev;
716
717 if (m_header.channelDepth == 16) {
718 result = new KisPaintDevice(*dev);
719 result->convertTo(KoColorSpaceRegistry::instance()->alpha16());
720 } else if (m_header.channelDepth == 32) {
721 result = new KisPaintDevice(*dev);
722 result->convertTo(KoColorSpaceRegistry::instance()->alpha32f());
723 }
724 return result;
725}
void convertTo(const KoColorSpace *dstColorSpace, KoColorConversionTransformation::Intent renderingIntent=KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::ConversionFlags conversionFlags=KoColorConversionTransformation::internalConversionFlags(), KUndo2Command *parentCommand=nullptr, KoUpdater *progressUpdater=nullptr)
quint16 channelDepth
Definition psd_header.h:47
static KoColorSpaceRegistry * instance()

References PSDHeader::channelDepth, KisPaintDevice::convertTo(), KoColorSpaceRegistry::instance(), and m_header.

◆ kritaColorLabelIndex()

int PSDLayerRecord::kritaColorLabelIndex ( quint16 labelColor)
private

Definition at line 764 of file psd_layer_record.cpp.

765{
766 int color = 0;
767 switch (labelColor) {
768 case 0:
769 color = 0;
770 break;
771 case 1: // red
772 color = 6;
773 break;
774 case 2: // Orange
775 color = 4;
776 break;
777 case 3: // Yellow
778 color = 3;
779 break;
780 case 4: // Green
781 color = 2;
782 break;
783 case 5: // Blue
784 color = 1;
785 break;
786 case 6: // Purple
787 color = 7;
788 break;
789 case 7: // Grey
790 color = 8;
791 break;
792 default:
793 color = 0;
794 }
795 return color;
796}

References labelColor.

◆ psdLabelColor()

quint16 PSDLayerRecord::psdLabelColor ( int colorLabelIndex)
private

Definition at line 727 of file psd_layer_record.cpp.

728{
729 quint16 color = 0;
730 switch (colorLabelIndex) {
731 case 0: // none
732 color = 0;
733 break;
734 case 1: // Blue
735 color = 5;
736 break;
737 case 2: // Green
738 color = 4;
739 break;
740 case 3: // Yellow
741 color = 3;
742 break;
743 case 4: // Orange
744 color = 2;
745 break;
746 case 5: // Brown, don't save.
747 color = 0;
748 break;
749 case 6: // Red
750 color = 1;
751 break;
752 case 7: // Purple
753 color = 6;
754 break;
755 case 8: // Grey
756 color = 7;
757 break;
758 default:
759 color = 0;
760 }
761 return color;
762}

◆ read()

bool PSDLayerRecord::read ( QIODevice & io)

Definition at line 168 of file psd_layer_record.cpp.

169{
170 switch (m_header.byteOrder) {
172 return readImpl<psd_byte_order::psdLittleEndian>(io);
173 default:
174 return readImpl(io);
175 }
176}
psd_byte_order byteOrder
Definition psd_header.h:49
bool readImpl(QIODevice &io)

References PSDHeader::byteOrder, m_header, psdLittleEndian, and readImpl().

◆ readImpl()

template<psd_byte_order byteOrder>
bool PSDLayerRecord::readImpl ( QIODevice & io)
private

Definition at line 179 of file psd_layer_record.cpp.

180{
181 dbgFile << "Going to read layer record. Pos:" << io.pos();
182
183 if (!psdread<byteOrder>(io, top) || !psdread<byteOrder>(io, left) || !psdread<byteOrder>(io, bottom) || !psdread<byteOrder>(io, right)
184 || !psdread<byteOrder>(io, nChannels)) {
185 error = "could not read layer record";
186 return false;
187 }
188
189 dbgFile << "\ttop" << top << "left" << left << "bottom" << bottom << "right" << right << "number of channels" << nChannels;
190
191 Q_ASSERT(top <= bottom);
192 Q_ASSERT(left <= right);
193 Q_ASSERT(nChannels > 0);
194
195 if (nChannels < 1) {
196 error = QString("Not enough channels. Got: %1").arg(nChannels);
197 return false;
198 }
199
200 if (nChannels > MAX_CHANNELS) {
201 error = QString("Too many channels. Got: %1").arg(nChannels);
202 return false;
203 }
204
205 for (int i = 0; i < nChannels; ++i) {
206 if (io.atEnd()) {
207 error = "Could not read enough data for channels";
208 return false;
209 }
210
211 ChannelInfo *info = new ChannelInfo;
212
213 if (!psdread<byteOrder>(io, info->channelId)) {
214 error = "could not read channel id";
215 delete info;
216 return false;
217 }
218 bool r;
219 if (m_header.version == 1) {
220 quint32 channelDataLength;
221 r = psdread<byteOrder>(io, channelDataLength);
222 info->channelDataLength = (quint64)channelDataLength;
223 } else {
224 r = psdread<byteOrder>(io, info->channelDataLength);
225 }
226 if (!r) {
227 error = "Could not read length for channel data";
228 delete info;
229 return false;
230 }
231
232 dbgFile << "\tchannel" << i << "id" << channelIdToChannelType(info->channelId, m_header.colormode) << "length" << info->channelDataLength << "start"
233 << info->channelDataStart << "offset" << info->channelOffset << "channelInfoPosition" << info->channelInfoPosition;
234
235 channelInfoRecords << info;
236 }
237
238 if (!psd_read_blendmode<byteOrder>(io, blendModeKey)) {
239 error = QString("Could not read blend mode key. Got: %1").arg(blendModeKey);
240 return false;
241 }
242
243 dbgFile << "\tBlend mode" << blendModeKey << "pos" << io.pos();
244
245 if (!psdread<byteOrder>(io, opacity)) {
246 error = "Could not read opacity";
247 return false;
248 }
249
250 dbgFile << "\tOpacity" << opacity << io.pos();
251
252 if (!psdread<byteOrder>(io, clipping)) {
253 error = "Could not read clipping";
254 return false;
255 }
256
257 dbgFile << "\tclipping" << clipping << io.pos();
258
259 quint8 flags;
260 if (!psdread<byteOrder>(io, flags)) {
261 error = "Could not read flags";
262 return false;
263 }
264 dbgFile << "\tflags" << flags << io.pos();
265
266 transparencyProtected = flags & 1 ? true : false;
267
268 dbgFile << "\ttransparency protected" << transparencyProtected;
269
270 visible = flags & 2 ? false : true;
271
272 dbgFile << "\tvisible" << visible;
273
274 if (flags & 8) {
275 irrelevant = flags & 16 ? true : false;
276 } else {
277 irrelevant = false;
278 }
279
280 dbgFile << "\tirrelevant" << irrelevant;
281
282 dbgFile << "\tfiller at " << io.pos();
283
284 quint8 filler;
285 if (!psdread<byteOrder>(io, filler) || filler != 0) {
286 error = "Could not read padding";
287 return false;
288 }
289
290 dbgFile << "\tGoing to read extra data length" << io.pos();
291
292 quint32 extraDataLength;
293 if (!psdread<byteOrder>(io, extraDataLength) || io.bytesAvailable() < extraDataLength) {
294 error = QString("Could not read extra layer data: %1 at pos %2").arg(extraDataLength).arg(io.pos());
295 return false;
296 }
297
298 dbgFile << "\tExtra data length" << extraDataLength;
299
300 if (extraDataLength > 0) {
301 dbgFile << "Going to read extra data field. Bytes available: " << io.bytesAvailable() << "pos" << io.pos();
302
303 // See https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#50577409_22582
304 quint32 layerMaskLength = 1; // invalid...
305 if (!psdread<byteOrder>(io, layerMaskLength) || io.bytesAvailable() < layerMaskLength) {
306 error = QString("Could not read layer mask length: %1").arg(layerMaskLength);
307 return false;
308 }
309
310 layerMask = {};
311
312 if (layerMaskLength == 0) {
313 dbgFile << "\tNo layer mask/adjustment layer data. pos" << io.pos();
314 } else {
315 dbgFile << "\tReading layer mask/adjustment layer data. Length of block:" << layerMaskLength << "pos"
316 << io.pos();
317
318 if (!psdread<byteOrder>(io, layerMask.top) || !psdread<byteOrder>(io, layerMask.left)
319 || !psdread<byteOrder>(io, layerMask.bottom) || !psdread<byteOrder>(io, layerMask.right)
320 || !psdread<byteOrder>(io, layerMask.defaultColor) || !psdread<byteOrder>(io, flags)) {
321 error = "could not read common records of layer mask";
322 return false;
323 }
324
325 layerMask.positionedRelativeToLayer = (flags & 1) != 0;
326 layerMask.disabled = (flags & 2) != 0;
327 layerMask.invertLayerMaskWhenBlending = (flags & 4) != 0;
328 const bool hasMaskParameters = (flags & 8) != 0;
329
330 dbgFile << "\tLayer mask info (original): position relative" << layerMask.positionedRelativeToLayer
331 << ", disabled" << layerMask.disabled << ", invert" << layerMask.invertLayerMaskWhenBlending
332 << ", needs to read mask parameters" << hasMaskParameters;
333
334 if (layerMaskLength == 20) {
335 quint16 padding = 0;
336 if (!psdread<byteOrder>(io, padding)) {
337 error = "Could not read layer mask padding";
338 return false;
339 }
340 } else {
341 quint32 remainingBlockLength = layerMaskLength - 18;
342
343 dbgFile << "\tReading selective records from layer mask info. Remaining block length"
344 << remainingBlockLength;
345
346 if (hasMaskParameters) {
347 if (!psdread<byteOrder>(io, flags)) {
348 error = "could not read mask parameters";
349 return false;
350 }
351
352 remainingBlockLength -= 1;
353
354 dbgFile << "\t\tMask parameters" << QString::number(flags, 2) << ". Remaining block length"
355 << remainingBlockLength;
356
357 if (flags & 1) {
358 quint8 dummy = 0;
359 if (!psdread<byteOrder>(io, dummy)) {
360 error = "could not read user mask density";
361 return false;
362 }
363 remainingBlockLength -= sizeof(dummy);
364 }
365
366 if (flags & 2) {
367 double dummy = 0;
368 if (!psdread<byteOrder>(io, dummy)) {
369 error = "could not read user mask feather";
370 return false;
371 }
372 remainingBlockLength -= sizeof(dummy);
373 }
374
375 if (flags & 4) {
376 quint8 dummy = 0;
377 if (!psdread<byteOrder>(io, dummy)) {
378 error = "could not read vector mask density";
379 return false;
380 }
381 remainingBlockLength -= sizeof(dummy);
382 }
383
384 if (flags & 8) {
385 double dummy = 0;
386 if (!psdread<byteOrder>(io, dummy)) {
387 error = "could not read vector mask feather";
388 return false;
389 }
390 remainingBlockLength -= sizeof(dummy);
391 }
392 }
393
394 if (remainingBlockLength >= 1) {
395 if (!psdread<byteOrder>(io, flags)) {
396 error = "could not read 'real' mask record";
397 return false;
398 }
399
400 layerMask.positionedRelativeToLayer = (flags & 1) != 0;
401 layerMask.disabled = (flags & 2) != 0;
402 layerMask.invertLayerMaskWhenBlending = (flags & 4) != 0;
403 const bool hasMaskParameters = (flags & 8) != 0;
404
405 dbgFile << "\t\tLayer mask info (real): position relative" << layerMask.positionedRelativeToLayer
406 << ", disabled" << layerMask.disabled << ", invert" << layerMask.invertLayerMaskWhenBlending
407 << ", needs to read mask parameters" << hasMaskParameters;
408
409 remainingBlockLength -= 1;
410
411 dbgFile << "\t\tRemaining block length" << remainingBlockLength;
412 }
413
414 if (remainingBlockLength >= 1) {
415 if (!psdread<byteOrder>(io, layerMask.defaultColor)) {
416 error = "could not read 'real' default color";
417 return false;
418 }
419 remainingBlockLength -= 1;
420 dbgFile << "\t\tRead 'real' default color. Remaining block length" << remainingBlockLength;
421 }
422
423 if (remainingBlockLength >= 16) {
424 if (!psdread<byteOrder>(io, layerMask.top) || !psdread<byteOrder>(io, layerMask.left)
425 || !psdread<byteOrder>(io, layerMask.bottom) || !psdread<byteOrder>(io, layerMask.right)) {
426 error = "could not read 'real' mask rectangle";
427 return false;
428 }
429 remainingBlockLength -= 16;
430 dbgFile << "\t\tRead 'real' mask rectangle. Remaining block length" << remainingBlockLength;
431 }
432 }
433 }
434
435 // layer blending thingies
436 quint32 blendingDataLength = 0;
437 if (!psdread<byteOrder>(io, blendingDataLength) || io.bytesAvailable() < blendingDataLength) {
438 error = "Could not read extra blending data.";
439 return false;
440 }
441
442 quint32 blendingNchannels = blendingDataLength > 0 ? (blendingDataLength - 8) / 4 / 2 : 0;
443
444 dbgFile << "\tNumber of blending channels:" << blendingNchannels;
445
446 if (blendingDataLength > 0) {
447 if (blendingDataLength > 0) {
448 if (!psdread<byteOrder>(io, blendingRanges.compositeGrayRange.first.blackValues[0])
449 || !psdread<byteOrder>(io, blendingRanges.compositeGrayRange.first.blackValues[1])
450 || !psdread<byteOrder>(io, blendingRanges.compositeGrayRange.first.whiteValues[0])
451 || !psdread<byteOrder>(io, blendingRanges.compositeGrayRange.first.whiteValues[1])) {
452 error = "Could not read blending black/white values";
453 return false;
454 }
455 }
456 blendingDataLength -= 4;
457
458 if (blendingDataLength > 0) {
459 if (!psdread<byteOrder>(io, blendingRanges.compositeGrayRange.second.blackValues[0])
460 || !psdread<byteOrder>(io, blendingRanges.compositeGrayRange.second.blackValues[1])
461 || !psdread<byteOrder>(io, blendingRanges.compositeGrayRange.second.whiteValues[0])
462 || !psdread<byteOrder>(io, blendingRanges.compositeGrayRange.second.whiteValues[1])) {
463 error = "Could not read blending black/white values";
464 return false;
465 }
466 }
467 blendingDataLength -= 4;
468
469 dbgFile << "\tBlending ranges:";
470 dbgFile << "\t\tcomposite gray (source) :" << blendingRanges.compositeGrayRange.first;
471 dbgFile << "\t\tcomposite gray (dest):" << blendingRanges.compositeGrayRange.second;
472
473 for (quint32 i = 0; i < blendingNchannels; ++i) {
474 LayerBlendingRanges::LayerBlendingRange src{};
475 LayerBlendingRanges::LayerBlendingRange dst{};
476 if (!psdread<byteOrder>(io, src.blackValues[0]) || !psdread<byteOrder>(io, src.blackValues[1]) || !psdread<byteOrder>(io, src.whiteValues[0])
477 || !psdread<byteOrder>(io, src.whiteValues[1]) || !psdread<byteOrder>(io, dst.blackValues[0]) || !psdread<byteOrder>(io, dst.blackValues[1])
478 || !psdread<byteOrder>(io, dst.whiteValues[0]) || !psdread<byteOrder>(io, dst.whiteValues[1])) {
479 error = QString("could not read src/dst range for channel %1").arg(i);
480 return false;
481 }
482 dbgFile << "\t\tread range " << src << "to" << dst << "for channel" << i;
483 blendingRanges.sourceDestinationRanges << qMakePair(src, dst);
484 }
485 }
486
487 dbgFile << "\tGoing to read layer name at" << io.pos();
488 quint8 layerNameLength;
489 if (!psdread<byteOrder>(io, layerNameLength)) {
490 error = "Could not read layer name length";
491 return false;
492 }
493
494 dbgFile << "\tlayer name length unpadded" << layerNameLength << "pos" << io.pos();
495 layerNameLength = ((layerNameLength + 1 + 3) & ~0x03) - 1;
496
497 dbgFile << "\tlayer name length padded" << layerNameLength << "pos" << io.pos();
498 // XXX: This should use psdread_pascalstring
499 layerName = io.read(layerNameLength);
500 dbgFile << "\tlayer name" << layerName << io.pos();
501
502 dbgFile << "\tAbout to read additional info blocks at" << io.pos();
503
504 if (!infoBlocks.read(io)) {
506 return false;
507 }
508
509 if (infoBlocks.keys.contains("luni") && !infoBlocks.unicodeLayerName.isEmpty()) {
511 }
512
514 }
515
516 return valid();
517}
psd_color_mode colormode
Definition psd_header.h:48
quint16 version
Definition psd_header.h:43
LayerBlendingRanges blendingRanges
int kritaColorLabelIndex(quint16 labelColor)
#define dbgFile
Definition kis_debug.h:53
const int MAX_CHANNELS
Definition psd.h:27
QString channelIdToChannelType(int channelId, psd_color_mode colormode)
quint64 channelDataLength
quint64 channelDataStart
QVector< QPair< LayerBlendingRange, LayerBlendingRange > > sourceDestinationRanges
QPair< LayerBlendingRange, LayerBlendingRange > compositeGrayRange

References blendingRanges, blendModeKey, bottom, PSDLayerRecord::LayerMaskData::bottom, ChannelInfo::channelDataLength, ChannelInfo::channelDataStart, ChannelInfo::channelId, channelIdToChannelType(), ChannelInfo::channelInfoPosition, channelInfoRecords, ChannelInfo::channelOffset, clipping, PSDHeader::colormode, PSDLayerRecord::LayerBlendingRanges::compositeGrayRange, dbgFile, PSDLayerRecord::LayerMaskData::defaultColor, PSDLayerRecord::LayerMaskData::disabled, PsdAdditionalLayerInfoBlock::error, error, infoBlocks, PSDLayerRecord::LayerMaskData::invertLayerMaskWhenBlending, irrelevant, PsdAdditionalLayerInfoBlock::keys, kritaColorLabelIndex(), PsdAdditionalLayerInfoBlock::labelColor, labelColor, layerMask, layerName, left, PSDLayerRecord::LayerMaskData::left, m_header, MAX_CHANNELS, nChannels, opacity, PSDLayerRecord::LayerMaskData::positionedRelativeToLayer, PsdAdditionalLayerInfoBlock::read(), right, PSDLayerRecord::LayerMaskData::right, PSDLayerRecord::LayerBlendingRanges::sourceDestinationRanges, top, PSDLayerRecord::LayerMaskData::top, transparencyProtected, PsdAdditionalLayerInfoBlock::unicodeLayerName, valid(), PSDHeader::version, and visible.

◆ readMask()

bool PSDLayerRecord::readMask ( QIODevice & io,
KisPaintDeviceSP dev,
ChannelInfo * channel )

Definition at line 909 of file psd_layer_record.cpp.

910{
911 KIS_ASSERT_RECOVER(channelInfo->channelId < -1)
912 {
913 return false;
914 }
915
916 dbgFile << "Going to read" << channelIdToChannelType(channelInfo->channelId, m_header.colormode) << "mask";
917
918 QRect maskRect = channelRect(channelInfo);
919 if (maskRect.isEmpty()) {
920 dbgFile << "Empty Channel";
921 return true;
922 }
923
924 // the device must be a pixel selection
925 KIS_ASSERT_RECOVER(dev->pixelSize() == 1)
926 {
927 return false;
928 }
929
931
932 const int pixelSize = m_header.channelDepth == 16 ? 2 : m_header.channelDepth == 32 ? 4 : 1;
933
934 QVector<ChannelInfo *> infoRecords;
935 infoRecords << channelInfo;
936 PsdPixelUtils::readAlphaMaskChannels(io, dev, pixelSize, maskRect, infoRecords);
937
938 return true;
939}
quint32 pixelSize() const
void setDefaultPixel(const KoColor &defPixel)
const KoColorSpace * colorSpace() const
QRect channelRect(ChannelInfo *channel) const
#define KIS_ASSERT_RECOVER(cond)
Definition kis_assert.h:55
void readAlphaMaskChannels(QIODevice &io, KisPaintDeviceSP device, int channelSize, const QRect &layerRect, QVector< ChannelInfo * > infoRecords, psd_byte_order byteOrder)

References PSDHeader::channelDepth, ChannelInfo::channelId, channelIdToChannelType(), channelRect(), PSDHeader::colormode, KisPaintDevice::colorSpace(), dbgFile, PSDLayerRecord::LayerMaskData::defaultColor, KIS_ASSERT_RECOVER, layerMask, m_header, KisPaintDevice::pixelSize(), PsdPixelUtils::readAlphaMaskChannels(), and KisPaintDevice::setDefaultPixel().

◆ readPixelData()

bool PSDLayerRecord::readPixelData ( QIODevice & io,
KisPaintDeviceSP device )

Definition at line 877 of file psd_layer_record.cpp.

878{
879 dbgFile << "Reading pixel data for layer" << layerName << "pos" << io.pos();
880
881 const int channelSize = m_header.channelDepth / 8;
882 const QRect layerRect = QRect(left, top, right - left, bottom - top);
883
884 try {
885 // WARNING: Pixel data is ALWAYS in big endian!!!
888 device->clear();
889 error = e.what();
890 return false;
891 }
892
893 return true;
894}
virtual void clear()
void readChannels(QIODevice &io, KisPaintDeviceSP device, psd_color_mode colorMode, int channelSize, const QRect &layerRect, QVector< ChannelInfo * > infoRecords, psd_byte_order byteOrder)

References bottom, PSDHeader::channelDepth, channelInfoRecords, KisPaintDevice::clear(), PSDHeader::colormode, dbgFile, error, layerName, left, m_header, psdBigEndian, PsdPixelUtils::readChannels(), right, and top.

◆ valid()

bool PSDLayerRecord::valid ( )

Definition at line 871 of file psd_layer_record.cpp.

872{
873 // XXX: check validity!
874 return true;
875}

◆ write()

void PSDLayerRecord::write ( QIODevice & io,
KisPaintDeviceSP layerContentDevice,
KisNodeSP onlyTransparencyMask,
const QRect & maskRect,
psd_section_type sectionType,
const QDomDocument & stylesXmlDoc,
bool useLfxsLayerStyleFormat )

Definition at line 519 of file psd_layer_record.cpp.

526{
527 switch (m_header.byteOrder) {
529 return writeImpl<psd_byte_order::psdLittleEndian>(io,
530 layerContentDevice,
531 onlyTransparencyMask,
532 maskRect,
533 sectionType,
534 stylesXmlDoc,
535 useLfxsLayerStyleFormat);
536 default:
537 return writeImpl(io, layerContentDevice, onlyTransparencyMask, maskRect, sectionType, stylesXmlDoc, useLfxsLayerStyleFormat);
538 }
539}
void writeImpl(QIODevice &io, KisPaintDeviceSP layerContentDevice, KisNodeSP onlyTransparencyMask, const QRect &maskRect, psd_section_type sectionType, const QDomDocument &stylesXmlDoc, bool useLfxsLayerStyleFormat)

References PSDHeader::byteOrder, m_header, psdLittleEndian, and writeImpl().

◆ writeImpl()

template<psd_byte_order byteOrder>
void PSDLayerRecord::writeImpl ( QIODevice & io,
KisPaintDeviceSP layerContentDevice,
KisNodeSP onlyTransparencyMask,
const QRect & maskRect,
psd_section_type sectionType,
const QDomDocument & stylesXmlDoc,
bool useLfxsLayerStyleFormat )
private

Definition at line 542 of file psd_layer_record.cpp.

549{
550 dbgFile << "writing layer info record"
551 << "at" << io.pos();
552
553 m_layerContentDevice = layerContentDevice;
554 m_onlyTransparencyMask = onlyTransparencyMask;
556
557 dbgFile << "saving layer record for " << layerName << "at pos" << io.pos();
558 dbgFile << "\ttop" << top << "left" << left << "bottom" << bottom << "right" << right << "number of channels" << nChannels;
559 Q_ASSERT(left <= right);
560 Q_ASSERT(top <= bottom);
561 Q_ASSERT(nChannels > 0);
562
563 try {
564 {
565 const QRect layerRect(left, top, right - left, bottom - top);
566 KisAslWriterUtils::writeRect<byteOrder>(layerRect, io);
567 }
568
569 {
570 quint16 realNumberOfChannels = nChannels + bool(m_onlyTransparencyMask);
571 SAFE_WRITE_EX(byteOrder, io, realNumberOfChannels);
572 }
573
574 Q_FOREACH (ChannelInfo *channel, channelInfoRecords) {
575 SAFE_WRITE_EX(byteOrder, io, (quint16)channel->channelId);
576
577 channel->channelInfoPosition = static_cast<int>(io.pos());
578
579 // to be filled in when we know how big channel block is
580 const quint32 fakeChannelSize = 0;
581 SAFE_WRITE_EX(byteOrder, io, fakeChannelSize);
582 }
583
585 const quint16 userSuppliedMaskChannelId = -2;
586 SAFE_WRITE_EX(byteOrder, io, userSuppliedMaskChannelId);
587
589
590 const quint32 fakeTransparencyMaskSize = 0;
591 SAFE_WRITE_EX(byteOrder, io, fakeTransparencyMaskSize);
592 }
593
594 // blend mode
595 dbgFile << ppVar(blendModeKey) << ppVar(io.pos());
596
597 KisAslWriterUtils::writeFixedString<byteOrder>("8BIM", io);
598 KisAslWriterUtils::writeFixedString<byteOrder>(blendModeKey, io);
599
600 SAFE_WRITE_EX(byteOrder, io, opacity);
601 SAFE_WRITE_EX(byteOrder, io, clipping); // unused
602
603 // visibility and protection
604 quint8 flags = 0;
606 flags |= 1;
607 if (!visible)
608 flags |= 2;
609 flags |= (1 << 3);
610 if (irrelevant) {
611 flags |= (1 << 4);
612 }
613
614 SAFE_WRITE_EX(byteOrder, io, flags);
615
616 {
617 quint8 padding = 0;
618 SAFE_WRITE_EX(byteOrder, io, padding);
619 }
620
621 {
622 // extra fields with their own length tag
624
626 {
627 const quint32 layerMaskDataSize = 20; // support simple case only
628 SAFE_WRITE_EX(byteOrder, io, layerMaskDataSize);
629 }
630
631 KisAslWriterUtils::writeRect<byteOrder>(m_onlyTransparencyMaskRect, io);
632
633 {
634 // NOTE: in PSD the default color of the mask is stored in 1 byte value!
635 // Even when the mask is actually 16/32 bit! I have no idea how it is
636 // actually treated in this case.
638 const quint8 defaultPixel = *m_onlyTransparencyMask->paintDevice()->defaultPixel().data();
639 SAFE_WRITE_EX(byteOrder, io, defaultPixel);
640 }
641
642 {
643 quint8 maskFlags = 0; // nothing serious
644 if (!vectorMask.path.subPaths.isEmpty()) {
645 maskFlags |= 8; // bit 3 = indicates that the user mask actually came from rendering other data
646 }
647 SAFE_WRITE_EX(byteOrder, io, maskFlags);
648
649 const quint16 padding = 0; // 2-byte padding
650 SAFE_WRITE_EX(byteOrder, io, padding);
651 }
652 } else {
653 const quint32 nullLayerMaskDataSize = 0;
654 SAFE_WRITE_EX(byteOrder, io, nullLayerMaskDataSize);
655 }
656
657 {
658 // blending ranges are not implemented yet
659 const quint32 nullBlendingRangesSize = 0;
660 SAFE_WRITE_EX(byteOrder, io, nullBlendingRangesSize);
661 }
662
663 // layer name: Pascal string, padded to a multiple of 4 bytes.
664 psdwrite_pascalstring<byteOrder>(io, layerName, 4);
665
666 PsdAdditionalLayerInfoBlock additionalInfoBlock(m_header);
667
668 // write 'luni' data block
669 additionalInfoBlock.writeLuniBlockEx(io, layerName);
670
671 additionalInfoBlock.writeLclrBlockEx(io, psdLabelColor(labelColor));
672
673 // write 'lsct' data block
674 if (sectionType != psd_other) {
675 additionalInfoBlock.writeLsctBlockEx(io, sectionType, isPassThrough, blendModeKey);
676 }
677
678 // write 'lfx2' data block
679 if (!stylesXmlDoc.isNull()) {
680 additionalInfoBlock.writeLfx2BlockEx(io, stylesXmlDoc, useLfxsLayerStyleFormat);
681 }
682
683 // write SoCo, GdFl, PtFl data blocks.
684 if (!fillConfig.isNull()) {
685 additionalInfoBlock.writeFillLayerBlockEx(io, fillConfig, fillType);
686 }
687
688 // write 'vmsk' data block
689 if (!vectorMask.path.subPaths.isEmpty()) {
690 additionalInfoBlock.writeVmskBlockEx(io, vectorMask);
691 }
692
693 // write 'tysh' data block
694 if (!textShape.engineData.isEmpty()) {
695 additionalInfoBlock.writeTypeToolBlockEx(io, textShape);
696 }
697
698 // write 'vstk' data block
699 if (!vectorStroke.isNull()) {
700 additionalInfoBlock.writeVectorStrokeDataEx(io, vectorStroke);
701 }
702
703 if (!vectorOriginationData.isNull()) {
704 additionalInfoBlock.writeVectorOriginationDataEx(io, vectorOriginationData);
705 }
706
707 }
710 }
711}
KoColor defaultPixel() const
quint8 * data()
Definition KoColor.h:144
qint64 m_transparencyMaskSizeOffset
QRect m_onlyTransparencyMaskRect
psd_fill_type fillType
psd_vector_mask vectorMask
psd_layer_type_shape textShape
QDomDocument vectorOriginationData
KisPaintDeviceSP m_layerContentDevice
quint16 psdLabelColor(int colorLabelIndex)
QDomDocument vectorStroke
QDomDocument fillConfig
KisNodeSP m_onlyTransparencyMask
The PsdAdditionalLayerInfoBlock class implements the Additional Layer Information block.
#define SAFE_WRITE_EX(byteOrder, device, varname)
#define KIS_ASSERT_RECOVER_NOOP(cond)
Definition kis_assert.h:97
#define PREPEND_METHOD(msg)
Definition kis_debug.h:172
#define ppVar(var)
Definition kis_debug.h:155
@ psd_other
Definition psd.h:144
virtual KisPaintDeviceSP paintDevice() const =0
QList< psd_path_sub_path > subPaths

References blendModeKey, bottom, ChannelInfo::channelId, ChannelInfo::channelInfoPosition, channelInfoRecords, clipping, KoColor::data(), dbgFile, KisPaintDevice::defaultPixel(), psd_layer_type_shape::engineData, fillConfig, fillType, irrelevant, isPassThrough, KIS_ASSERT_RECOVER_NOOP, labelColor, layerName, left, m_header, m_layerContentDevice, m_onlyTransparencyMask, m_onlyTransparencyMaskRect, m_transparencyMaskSizeOffset, nChannels, opacity, KisBaseNode::paintDevice(), psd_vector_mask::path, KisPaintDevice::pixelSize(), ppVar, PREPEND_METHOD, psd_other, psdLabelColor(), right, SAFE_WRITE_EX, psd_path::subPaths, textShape, top, transparencyProtected, vectorMask, vectorOriginationData, vectorStroke, visible, PsdAdditionalLayerInfoBlock::writeFillLayerBlockEx(), PsdAdditionalLayerInfoBlock::writeLclrBlockEx(), PsdAdditionalLayerInfoBlock::writeLfx2BlockEx(), PsdAdditionalLayerInfoBlock::writeLsctBlockEx(), PsdAdditionalLayerInfoBlock::writeLuniBlockEx(), PsdAdditionalLayerInfoBlock::writeTypeToolBlockEx(), PsdAdditionalLayerInfoBlock::writeVectorOriginationDataEx(), PsdAdditionalLayerInfoBlock::writeVectorStrokeDataEx(), and PsdAdditionalLayerInfoBlock::writeVmskBlockEx().

◆ writePixelData()

void PSDLayerRecord::writePixelData ( QIODevice & io,
psd_compression_type compressionType )

Definition at line 818 of file psd_layer_record.cpp.

819{
820 try {
821 switch (m_header.byteOrder) {
823 writePixelDataImpl<psd_byte_order::psdLittleEndian>(io, compressionType);
824 break;
825 default:
826 writePixelDataImpl(io, compressionType);
827 break;
828 }
831 }
832}
void writePixelDataImpl(QIODevice &io, psd_compression_type compressionType)

References PSDHeader::byteOrder, m_header, PREPEND_METHOD, psdLittleEndian, and writePixelDataImpl().

◆ writePixelDataImpl()

template<psd_byte_order byteOrder>
void PSDLayerRecord::writePixelDataImpl ( QIODevice & io,
psd_compression_type compressionType )
private

Definition at line 835 of file psd_layer_record.cpp.

836{
837 dbgFile << "writing pixel data for layer" << layerName << "at" << io.pos();
838
840 const QRect rc(left, top, right - left, bottom - top);
841
842 if (rc.isEmpty()) {
843 dbgFile << "Layer is empty! Writing placeholder information.";
844
845 for (int i = 0; i < nChannels; i++) {
846 const ChannelInfo *channelInfo = channelInfoRecords[i];
847 KisAslWriterUtils::OffsetStreamPusher<quint32, byteOrder> channelBlockSizeExternalTag(io, 0, channelInfo->channelInfoPosition);
848 SAFE_WRITE_EX(byteOrder, io, static_cast<quint16>(psd_compression_type::Uncompressed));
849 }
850
851 writeTransparencyMaskPixelData<byteOrder>(io);
852
853 return;
854 }
855
856 // now write all the channels in display order
857 dbgFile << "layer" << layerName;
858
859 const int channelSize = m_header.channelDepth / 8;
860 const psd_color_mode colorMode = m_header.colormode;
861
863 Q_FOREACH (const ChannelInfo *channelInfo, channelInfoRecords) {
864 writingInfoList << PsdPixelUtils::ChannelWritingInfo(channelInfo->channelId, channelInfo->channelInfoPosition);
865 }
866
867 PsdPixelUtils::writePixelDataCommon(io, dev, rc, colorMode, channelSize, true, true, writingInfoList, compressionType, byteOrder);
868 writeTransparencyMaskPixelData<byteOrder>(io);
869}
void writePixelDataCommon(QIODevice &io, KisPaintDeviceSP dev, const QRect &rc, psd_color_mode colorMode, int channelSize, bool alphaFirst, const bool writeCompressionType, QVector< ChannelWritingInfo > &writingInfoList, psd_compression_type compressionType, psd_byte_order byteOrder)
@ Uncompressed
Definition psd.h:40
psd_color_mode
Definition psd.h:50

References bottom, PSDHeader::channelDepth, ChannelInfo::channelId, ChannelInfo::channelInfoPosition, channelInfoRecords, PSDHeader::colormode, dbgFile, layerName, left, m_header, m_layerContentDevice, nChannels, right, SAFE_WRITE_EX, top, Uncompressed, and PsdPixelUtils::writePixelDataCommon().

◆ writeTransparencyMaskPixelData()

template<psd_byte_order byteOrder>
void PSDLayerRecord::writeTransparencyMaskPixelData ( QIODevice & io)
private

Definition at line 799 of file psd_layer_record.cpp.

800{
803
804 QByteArray buffer(static_cast<int>(device->pixelSize()) * m_onlyTransparencyMaskRect.width() * m_onlyTransparencyMaskRect.height(), 0);
805 device->readBytes((quint8 *)buffer.data(), m_onlyTransparencyMaskRect);
806
808 (quint8 *)buffer.data(),
809 static_cast<int>(device->pixelSize()),
812 -1,
813 true,
814 byteOrder);
815 }
816}
void readBytes(quint8 *data, qint32 x, qint32 y, qint32 w, qint32 h) const
KisPaintDeviceSP convertMaskDeviceIfNeeded(KisPaintDeviceSP dev)
void writeChannelDataRLE(QIODevice &io, const quint8 *plane, const int channelSize, const QRect &rc, const qint64 sizeFieldOffset, const qint64 rleBlockOffset, const bool writeCompressionType, psd_byte_order byteOrder)

References convertMaskDeviceIfNeeded(), m_onlyTransparencyMask, m_onlyTransparencyMaskRect, m_transparencyMaskSizeOffset, KisBaseNode::paintDevice(), KisPaintDevice::pixelSize(), KisPaintDevice::readBytes(), and PsdPixelUtils::writeChannelDataRLE().

Member Data Documentation

◆ blendingRanges

LayerBlendingRanges PSDLayerRecord::blendingRanges

Definition at line 173 of file psd_layer_record.h.

◆ blendModeKey

QString PSDLayerRecord::blendModeKey

Definition at line 125 of file psd_layer_record.h.

◆ bottom

qint32 PSDLayerRecord::bottom {0}

Definition at line 118 of file psd_layer_record.h.

118{0};

◆ channelInfoRecords

QVector<ChannelInfo *> PSDLayerRecord::channelInfoRecords

Definition at line 123 of file psd_layer_record.h.

◆ clipping

quint8 PSDLayerRecord::clipping {0}

Definition at line 129 of file psd_layer_record.h.

129{0};

◆ error

QString PSDLayerRecord::error

Definition at line 114 of file psd_layer_record.h.

◆ fillConfig

QDomDocument PSDLayerRecord::fillConfig

Definition at line 137 of file psd_layer_record.h.

◆ fillType

psd_fill_type PSDLayerRecord::fillType {psd_fill_solid_color}

Definition at line 136 of file psd_layer_record.h.

@ psd_fill_solid_color
Definition psd.h:124

◆ infoBlocks

PsdAdditionalLayerInfoBlock PSDLayerRecord::infoBlocks

Definition at line 177 of file psd_layer_record.h.

◆ irrelevant

bool PSDLayerRecord::irrelevant {false}

Definition at line 132 of file psd_layer_record.h.

132{false};

◆ isPassThrough

bool PSDLayerRecord::isPassThrough {false}

Definition at line 126 of file psd_layer_record.h.

126{false};

◆ labelColor

int PSDLayerRecord::labelColor {0}

Definition at line 134 of file psd_layer_record.h.

134{0};

◆ layerMask

LayerMaskData PSDLayerRecord::layerMask

Definition at line 159 of file psd_layer_record.h.

◆ layerName

QString PSDLayerRecord::layerName {"UNINITIALIZED"}

Definition at line 175 of file psd_layer_record.h.

175{"UNINITIALIZED"}; // pascal, not unicode!

◆ left

qint32 PSDLayerRecord::left {0}

Definition at line 117 of file psd_layer_record.h.

117{0};

◆ m_header

const PSDHeader PSDLayerRecord::m_header
private

Definition at line 209 of file psd_layer_record.h.

◆ m_layerContentDevice

KisPaintDeviceSP PSDLayerRecord::m_layerContentDevice
private

Definition at line 204 of file psd_layer_record.h.

◆ m_onlyTransparencyMask

KisNodeSP PSDLayerRecord::m_onlyTransparencyMask
private

Definition at line 205 of file psd_layer_record.h.

◆ m_onlyTransparencyMaskRect

QRect PSDLayerRecord::m_onlyTransparencyMaskRect
private

Definition at line 206 of file psd_layer_record.h.

◆ m_transparencyMaskSizeOffset

qint64 PSDLayerRecord::m_transparencyMaskSizeOffset {0}
private

Definition at line 207 of file psd_layer_record.h.

207{0};

◆ nChannels

quint16 PSDLayerRecord::nChannels {0}

Definition at line 121 of file psd_layer_record.h.

121{0};

◆ opacity

quint8 PSDLayerRecord::opacity {0}

Definition at line 128 of file psd_layer_record.h.

128{0};

◆ right

qint32 PSDLayerRecord::right {0}

Definition at line 119 of file psd_layer_record.h.

119{0};

◆ textShape

psd_layer_type_shape PSDLayerRecord::textShape

Definition at line 140 of file psd_layer_record.h.

◆ top

qint32 PSDLayerRecord::top {0}

Definition at line 116 of file psd_layer_record.h.

116{0};

◆ transparencyProtected

bool PSDLayerRecord::transparencyProtected {false}

Definition at line 130 of file psd_layer_record.h.

130{false};

◆ vectorMask

psd_vector_mask PSDLayerRecord::vectorMask

Definition at line 139 of file psd_layer_record.h.

◆ vectorOriginationData

QDomDocument PSDLayerRecord::vectorOriginationData

Definition at line 142 of file psd_layer_record.h.

◆ vectorStroke

QDomDocument PSDLayerRecord::vectorStroke

Definition at line 141 of file psd_layer_record.h.

◆ visible

bool PSDLayerRecord::visible {true}

Definition at line 131 of file psd_layer_record.h.

131{true};

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