55 return (
a << 24) | (
b << 16) | (
c << 8) |
d;
180 return int(
x * 65536.0f + 0.5f);
185 return x * (1.0f / 65536.0f);
191 qCWarning(lcIcc,
"Failed ICC signature test");
197 qCWarning(lcIcc,
"Failed tag count sanity");
201 qCWarning(lcIcc,
"Failed basic size sanity");
217 if (
header.pcs != 0x58595a20 ) {
228 qCWarning(lcIcc,
"Invalid ICC illuminant");
243 if (trc.
m_type == QColorTrc::Type::Function) {
287 constexpr int tagCount = 9;
288 constexpr uint profileDataOffset = 128 + 4 + 12 * tagCount;
289 constexpr uint variableTagTableOffsets = 128 + 4 + 12 * 5;
290 uint currentOffset = 0;
291 uint rTrcOffset, gTrcOffset, bTrcOffset;
292 uint rTrcSize, gTrcSize, bTrcSize;
293 uint descOffset, descSize;
314 stream <<
IccTag(
'Q',
't', QT_VERSION_MAJOR, QT_VERSION_MINOR);
331 currentOffset = profileDataOffset;
355 rTrcOffset = currentOffset;
357 currentOffset += rTrcSize;
358 if (spaceDPtr->
trc[0] == spaceDPtr->
trc[1]) {
359 gTrcOffset = rTrcOffset;
362 gTrcOffset = currentOffset;
364 currentOffset += gTrcSize;
366 if (spaceDPtr->
trc[0] == spaceDPtr->
trc[2]) {
367 bTrcOffset = rTrcOffset;
370 bTrcOffset = currentOffset;
372 currentOffset += bTrcSize;
375 descOffset = currentOffset;
384 descSize = 90 + description.
size() + 1;
385 currentOffset += descSize;
392 *(
quint32_be *)(iccProfile.
data() + variableTagTableOffsets + 4) = rTrcOffset;
393 *(
quint32_be *)(iccProfile.
data() + variableTagTableOffsets + 8) = rTrcSize;
394 *(
quint32_be *)(iccProfile.
data() + variableTagTableOffsets + 12 + 4) = gTrcOffset;
395 *(
quint32_be *)(iccProfile.
data() + variableTagTableOffsets + 12 + 8) = gTrcSize;
396 *(
quint32_be *)(iccProfile.
data() + variableTagTableOffsets + 2 * 12 + 4) = bTrcOffset;
397 *(
quint32_be *)(iccProfile.
data() + variableTagTableOffsets + 2 * 12 + 8) = bTrcSize;
398 *(
quint32_be *)(iccProfile.
data() + variableTagTableOffsets + 3 * 12 + 4) = descOffset;
399 *(
quint32_be *)(iccProfile.
data() + variableTagTableOffsets + 3 * 12 + 8) = descSize;
401#if !defined(QT_NO_DEBUG) || defined(QT_FORCE_ASSERTS)
418 qCWarning(lcIcc) <<
"Undersized XYZ tag";
423 qCWarning(lcIcc) <<
"Bad XYZ content type";
441 if (
curv.valueCount > (1 << 16))
443 if (tagEntry.
size - 12 < 2 *
curv.valueCount)
446 if (
curv.valueCount == 0) {
447 gamma.
m_type = QColorTrc::Type::Function;
449 }
else if (
curv.valueCount == 1) {
450 const quint16 v = qFromBigEndian<quint16>(
data.constData() + valueOffset);
451 gamma.
m_type = QColorTrc::Type::Function;
457 "GenericTagData has padding. The following code is a subject to UB.");
458 qFromBigEndian<quint16>(
data.constData() + valueOffset,
curv.valueCount, tabl.
data());
461 if (!
table.checkValidity()) {
462 qCWarning(lcIcc) <<
"Invalid curv table";
464 }
else if (!
table.asColorTransferFunction(&curve)) {
465 gamma.
m_type = QColorTrc::Type::Table;
468 qCDebug(lcIcc) <<
"Detected curv table as function";
469 gamma.
m_type = QColorTrc::Type::Function;
480 switch (
para.curveType) {
484 qFromBigEndian<quint32>(
data.constData() + parametersOffset, 1, parameters);
486 gamma.
m_type = QColorTrc::Type::Function;
493 qFromBigEndian<quint32>(
data.constData() + parametersOffset, 3, parameters);
494 if (parameters[1] == 0)
500 gamma.
m_type = QColorTrc::Type::Function;
507 qFromBigEndian<quint32>(
data.constData() + parametersOffset, 4, parameters);
508 if (parameters[1] == 0)
515 gamma.
m_type = QColorTrc::Type::Function;
522 qFromBigEndian<quint32>(
data.constData() + parametersOffset, 5, parameters);
528 gamma.
m_type = QColorTrc::Type::Function;
535 qFromBigEndian<quint32>(
data.constData() + parametersOffset, 7, parameters);
543 gamma.
m_type = QColorTrc::Type::Function;
553 qCWarning(lcIcc) <<
"Invalid TRC data type";
571 if (asciiDescription[
len - 1] !=
'\0')
582 if (
mluc.recordCount < 1)
584 if (
mluc.recordSize < 12)
587 const quint32 stringOffset =
mluc.records[0].offset;
589 if (tagEntry.
size < stringOffset || tagEntry.
size - stringOffset < stringSize )
591 if ((stringSize | stringOffset) & 1)
593 quint32 stringLen = stringSize / 2;
595 qFromBigEndian<char16_t>(
data.constData() + tagEntry.
offset + stringOffset, stringLen,
596 utf16hostendian.
data());
598 if (stringLen > 1 && utf16hostendian[stringLen - 1] == 0)
607 qCWarning(lcIcc) <<
"fromIccProfile: failed size sanity 1";
614 qCWarning(lcIcc) <<
"fromIccProfile: failed size sanity 2";
620 if (offsetToData >
data.size()) {
621 qCWarning(lcIcc) <<
"fromIccProfile: failed index size sanity";
634 qCWarning(lcIcc) <<
"fromIccProfile: failed tag offset sanity 1";
639 qCWarning(lcIcc) <<
"fromIccProfile: failed tag offset sanity 2";
642 if (tagTable.
size < 12) {
643 qCWarning(lcIcc) <<
"fromIccProfile: failed minimal tag size sanity";
647 qCWarning(lcIcc) <<
"fromIccProfile: failed tag offset + size sanity";
650 if (tagTable.
offset & 0x03) {
651 qCWarning(lcIcc) <<
"fromIccProfile: invalid tag offset alignment";
665 qCInfo(lcIcc) <<
"fromIccProfile: Unsupported ICC profile - not three component matrix based";
671 qCWarning(lcIcc) <<
"fromIccProfile: Invalid ICC profile - not valid gray scale based";
692 qCDebug(lcIcc) <<
"fromIccProfile: sRGB primaries detected";
695 qCDebug(lcIcc) <<
"fromIccProfile: Adobe RGB primaries detected";
698 qCDebug(lcIcc) <<
"fromIccProfile: DCI-P3 D65 primaries detected";
702 qCDebug(lcIcc) <<
"fromIccProfile: ProPhoto RGB primaries detected";
711 if (!
qFuzzyCompare(whitePoint.
y, 1.0f) || (1.0f + whitePoint.
z + whitePoint.
x) == 0.0f) {
712 qCWarning(lcIcc) <<
"fromIccProfile: Invalid ICC profile - gray white-point not normalized";
720 float y = 1.0f / (1.0f + whitePoint.
z + whitePoint.
x);
721 float x = whitePoint.
x *
y;
725 qCWarning(lcIcc,
"fromIccProfile: Invalid ICC profile - invalid white-point(%f, %f)",
x,
y);
740 rTrc = tagIndex[Tag::kTRC];
741 gTrc = tagIndex[Tag::kTRC];
742 bTrc = tagIndex[Tag::kTRC];
745 rTrc = tagIndex[Tag::aarg];
746 gTrc = tagIndex[Tag::aagg];
747 bTrc = tagIndex[Tag::aabg];
749 rTrc = tagIndex[Tag::rTRC];
750 gTrc = tagIndex[Tag::gTRC];
751 bTrc = tagIndex[Tag::bTRC];
758 qCWarning(lcIcc) <<
"fromIccProfile: Invalid rTRC";
762 qCWarning(lcIcc) <<
"fromIccProfile: Invalid gTRC";
766 qCWarning(lcIcc) <<
"fromIccProfile: Invalid bTRC";
769 if (rCurve == gCurve && gCurve == bCurve && rCurve.
m_type == QColorTrc::Type::Function) {
771 qCDebug(lcIcc) <<
"fromIccProfile: Linear gamma detected";
774 colorspaceDPtr->
gamma = 1.0f;
776 qCDebug(lcIcc) <<
"fromIccProfile: Simple gamma detected";
781 qCDebug(lcIcc) <<
"fromIccProfile: sRGB gamma detected";
785 colorspaceDPtr->
trc[0] = rCurve;
789 colorspaceDPtr->
trc[1] = colorspaceDPtr->
trc[0];
790 colorspaceDPtr->
trc[2] = colorspaceDPtr->
trc[0];
792 colorspaceDPtr->
trc[0] = rCurve;
793 colorspaceDPtr->
trc[1] = gCurve;
794 colorspaceDPtr->
trc[2] = bCurve;
800 qCWarning(lcIcc) <<
"fromIccProfile: Failed to parse description";
\inmodule QtCore \reentrant
char * data()
\macro QT_NO_CAST_FROM_BYTEARRAY
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
static QColorMatrix toXyzFromSRgb()
static QColorMatrix toXyzFromAdobeRgb()
static QColorMatrix toXyzFromDciP3D65()
static QColorMatrix toXyzFromProPhotoRgb()
QColorMatrix toXyzMatrix() const
QColorSpace::NamedColorSpace namedColorSpace
static const QColorSpacePrivate * get(const QColorSpace &colorSpace)
void identifyColorSpace()
QColorSpace::Primaries primaries
QColorSpace::TransferFunction transferFunction
The QColorSpace class provides a color space abstraction.
bool isValid() const noexcept
Returns true if the color space is valid.
NamedColorSpace
Predefined color spaces.
QString description() const noexcept
Returns the name or short description.
static QColorTransferFunction fromGamma(float gamma)
static QColorTransferFunction fromSRgb()
QList< uint8_t > m_table8
QList< uint16_t > m_table16
QColorTransferFunction m_fun
QColorTransferTable m_table
static constexpr QColorVector D50()
static constexpr QColorVector D65()
\inmodule QtCore\reentrant
bool contains(const Key &key) const noexcept
Returns true if the hash contains an item with the key; otherwise returns false.
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
bool isEmpty() const noexcept
void resize(qsizetype size)
\inmodule QtCore\reentrant
\macro QT_RESTRICTED_CAST_FROM_ASCII
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
static QString fromUtf16(const char16_t *, qsizetype size=-1)
QByteArray toUtf8() const &
bool fromIccProfile(const QByteArray &data, QColorSpace *colorSpace)
QByteArray toIccProfile(const QColorSpace &space)
static int toFixedS1516(float x)
static bool isValidIccProfile(const ICCProfileHeader &header)
bool parseTRC(const QByteArray &data, const TagEntry &tagEntry, QColorTrc &gamma)
static int writeColorTrc(QDataStream &stream, const QColorTrc &trc)
static float fromFixedS1516(int x)
bool parseXyzData(const QByteArray &data, const TagEntry &tagEntry, QColorVector &colorVector)
bool parseDesc(const QByteArray &data, const TagEntry &tagEntry, QString &descName)
Combined button and popup list for selecting options.
#define Q_STATIC_ASSERT(Condition)
AudioChannelLayoutTag tag
static QString header(const QString &name)
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) noexcept
bool qFuzzyIsNull(qfloat16 f) noexcept
size_t qHash(const Tag &key, size_t seed=0)
constexpr quint32 IccTag(uchar a, uchar b, uchar c, uchar d)
#define Q_LOGGING_CATEGORY(name,...)
#define qCInfo(category,...)
#define qCWarning(category,...)
#define qCDebug(category,...)
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat z
GLint GLint GLint GLint GLint x
[0]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLenum GLsizei void * table
static Q_CONSTINIT QBasicAtomicInteger< unsigned > seed
quint32_be asciiDescriptionLength