Add API for reading and decoding graphical texture files

Add a framework for reading and decoding stored graphical texture file
formats. Includes decoders for the PKM and KTX formats.

This is basically the same texture file reading that was added to
qtdeclarative for 5.11, but has been refactored to be independent of
the scenegraph and opengl.

Task-number: QTBUG-67026
Change-Id: I87d8117550d8a2112f4f58c03e9ac6b3249cbc5a
Reviewed-by: Kai Koehne <kai.koehne@qt.io>
Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
This commit is contained in:
Eirik Aavitsland 2018-07-03 12:30:46 +02:00
parent 1ed0b2170d
commit 731538fdd4
16 changed files with 1246 additions and 3 deletions

View File

@ -0,0 +1,189 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qktxhandler_p.h"
#include "qtexturefiledata_p.h"
#include <QtEndian>
#include <QSize>
//#define KTX_DEBUG
QT_BEGIN_NAMESPACE
#define KTX_IDENTIFIER_LENGTH 12
static const char ktxIdentifier[KTX_IDENTIFIER_LENGTH] = { '\xAB', 'K', 'T', 'X', ' ', '1', '1', '\xBB', '\r', '\n', '\x1A', '\n' };
static const quint32 platformEndianIdentifier = 0x04030201;
static const quint32 inversePlatformEndianIdentifier = 0x01020304;
struct KTXHeader {
quint8 identifier[KTX_IDENTIFIER_LENGTH]; // Must match ktxIdentifier
quint32 endianness; // Either platformEndianIdentifier or inversePlatformEndianIdentifier, other values not allowed.
quint32 glType;
quint32 glTypeSize;
quint32 glFormat;
quint32 glInternalFormat;
quint32 glBaseInternalFormat;
quint32 pixelWidth;
quint32 pixelHeight;
quint32 pixelDepth;
quint32 numberOfArrayElements;
quint32 numberOfFaces;
quint32 numberOfMipmapLevels;
quint32 bytesOfKeyValueData;
};
static const int headerSize = sizeof(KTXHeader);
// Currently unused, declared for future reference
struct KTXKeyValuePairItem {
quint32 keyAndValueByteSize;
/*
quint8 keyAndValue[keyAndValueByteSize];
quint8 valuePadding[3 - ((keyAndValueByteSize + 3) % 4)];
*/
};
struct KTXMipmapLevel {
quint32 imageSize;
/*
for each array_element in numberOfArrayElements*
for each face in numberOfFaces
for each z_slice in pixelDepth*
for each row or row_of_blocks in pixelHeight*
for each pixel or block_of_pixels in pixelWidth
Byte data[format-specific-number-of-bytes]**
end
end
end
Byte cubePadding[0-3]
end
end
quint8 mipPadding[3 - ((imageSize + 3) % 4)]
*/
};
bool QKtxHandler::canRead(const QByteArray &suffix, const QByteArray &block)
{
Q_UNUSED(suffix)
return (qstrncmp(block.constData(), ktxIdentifier, KTX_IDENTIFIER_LENGTH) == 0);
}
QTextureFileData QKtxHandler::read()
{
if (!device())
return QTextureFileData();
QByteArray buf = device()->readAll();
if (buf.size() < headerSize || !canRead(QByteArray(), buf)) {
qCDebug(lcQtGuiTextureIO, "Invalid KTX file %s", logName().constData());
return QTextureFileData();
}
const KTXHeader *header = reinterpret_cast<const KTXHeader *>(buf.constData());
if (!checkHeader(*header)) {
qCDebug(lcQtGuiTextureIO, "Unsupported KTX file format in %s", logName().constData());
return QTextureFileData();
}
QTextureFileData texData;
texData.setData(buf);
texData.setSize(QSize(decode(header->pixelWidth), decode(header->pixelHeight)));
texData.setGLFormat(decode(header->glFormat));
texData.setGLInternalFormat(decode(header->glInternalFormat));
texData.setGLBaseInternalFormat(decode(header->glBaseInternalFormat));
//### For now, ignore any additional mipmap levels
texData.setNumLevels(1);
int preambleSize = headerSize + decode(header->bytesOfKeyValueData);
if (buf.size() >= preambleSize + int(sizeof(KTXMipmapLevel))) {
texData.setDataOffset(preambleSize + sizeof(quint32)); // for the imageSize
const KTXMipmapLevel *level = reinterpret_cast<const KTXMipmapLevel *>(buf.constData() + preambleSize);
texData.setDataLength(decode(level->imageSize));
}
if (!texData.isValid()) {
qCDebug(lcQtGuiTextureIO, "Invalid values in header of KTX file %s", logName().constData());
return QTextureFileData();
}
texData.setLogName(logName());
#ifdef KTX_DEBUG
qDebug() << "KTX file handler read" << texData.data();
#endif
return texData;
}
bool QKtxHandler::checkHeader(const KTXHeader &header)
{
if (header.endianness != platformEndianIdentifier && header.endianness != inversePlatformEndianIdentifier)
return false;
inverseEndian = (header.endianness == inversePlatformEndianIdentifier);
#ifdef KTX_DEBUG
QMetaEnum tfme = QMetaEnum::fromType<QOpenGLTexture::TextureFormat>();
QMetaEnum ptme = QMetaEnum::fromType<QOpenGLTexture::PixelType>();
qDebug("Header of %s:", logName().constData());
qDebug(" glType: 0x%x (%s)", decode(header.glType), ptme.valueToKey(decode(header.glType)));
qDebug(" glTypeSize: %u", decode(header.glTypeSize));
qDebug(" glFormat: 0x%x (%s)", decode(header.glFormat), tfme.valueToKey(decode(header.glFormat)));
qDebug(" glInternalFormat: 0x%x (%s)", decode(header.glInternalFormat), tfme.valueToKey(decode(header.glInternalFormat)));
qDebug(" glBaseInternalFormat: 0x%x (%s)", decode(header.glBaseInternalFormat), tfme.valueToKey(decode(header.glBaseInternalFormat)));
qDebug(" pixelWidth: %u", decode(header.pixelWidth));
qDebug(" pixelHeight: %u", decode(header.pixelHeight));
qDebug(" pixelDepth: %u", decode(header.pixelDepth));
qDebug(" numberOfArrayElements: %u", decode(header.numberOfArrayElements));
qDebug(" numberOfFaces: %u", decode(header.numberOfFaces));
qDebug(" numberOfMipmapLevels: %u", decode(header.numberOfMipmapLevels));
qDebug(" bytesOfKeyValueData: %u", decode(header.bytesOfKeyValueData));
#endif
return ((decode(header.glType) == 0) &&
(decode(header.glFormat) == 0) &&
(decode(header.pixelDepth) == 0) &&
(decode(header.numberOfFaces) == 1));
}
quint32 QKtxHandler::decode(quint32 val)
{
return inverseEndian ? qbswap<quint32>(val) : val;
}
QT_END_NAMESPACE

View File

@ -0,0 +1,78 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QKTXHANDLER_H
#define QKTXHANDLER_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include "qtexturefilehandler_p.h"
QT_BEGIN_NAMESPACE
struct KTXHeader;
class QKtxHandler : public QTextureFileHandler
{
public:
using QTextureFileHandler::QTextureFileHandler;
static bool canRead(const QByteArray &suffix, const QByteArray &block);
QTextureFileData read() override;
private:
bool checkHeader(const KTXHeader &header);
quint32 decode(quint32 val);
bool inverseEndian = false;
};
QT_END_NAMESPACE
#endif // QKTXHANDLER_H

View File

@ -0,0 +1,126 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qpkmhandler_p.h"
#include "qtexturefiledata_p.h"
#include <QFile>
#include <QDebug>
#include <QSize>
#include <qendian.h>
//#define ETC_DEBUG
QT_BEGIN_NAMESPACE
static const int headerSize = 16;
struct PkmType
{
quint32 glFormat;
quint32 bytesPerBlock;
};
static PkmType typeMap[5] = {
{ 0x8D64, 8 }, // GL_ETC1_RGB8_OES
{ 0x9274, 8 }, // GL_COMPRESSED_RGB8_ETC2
{ 0, 0 }, // unused (obsolete)
{ 0x9278, 16}, // GL_COMPRESSED_RGBA8_ETC2_EAC
{ 0x9276, 8 } // GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
};
bool QPkmHandler::canRead(const QByteArray &suffix, const QByteArray &block)
{
Q_UNUSED(suffix)
return block.startsWith("PKM ");
}
QTextureFileData QPkmHandler::read()
{
QTextureFileData texData;
if (!device())
return texData;
QByteArray fileData = device()->readAll();
if (fileData.size() < headerSize || !canRead(QByteArray(), fileData)) {
qCDebug(lcQtGuiTextureIO, "Invalid PKM file %s", logName().constData());
return QTextureFileData();
}
texData.setData(fileData);
const char *rawData = fileData.constData();
// ignore version (rawData + 4 & 5)
// texture type
quint16 type = qFromBigEndian<quint16>(rawData + 6);
if (type > sizeof(typeMap)/sizeof(typeMap[0])) {
qCDebug(lcQtGuiTextureIO, "Unknown compression format in PKM file %s", logName().constData());
return QTextureFileData();
}
texData.setGLFormat(0); // 0 for compressed textures
texData.setGLInternalFormat(typeMap[type].glFormat);
//### setBaseInternalFormat
// texture size
texData.setNumLevels(1);
const int bpb = typeMap[type].bytesPerBlock;
QSize paddedSize(qFromBigEndian<quint16>(rawData + 8), qFromBigEndian<quint16>(rawData + 10));
texData.setDataLength((paddedSize.width() / 4) * (paddedSize.height() / 4) * bpb);
QSize texSize(qFromBigEndian<quint16>(rawData + 12), qFromBigEndian<quint16>(rawData + 14));
texData.setSize(texSize);
texData.setDataOffset(headerSize);
if (!texData.isValid()) {
qCDebug(lcQtGuiTextureIO, "Invalid values in header of PKM file %s", logName().constData());
return QTextureFileData();
}
texData.setLogName(logName());
#ifdef ETC_DEBUG
qDebug() << "PKM file handler read" << texData;
#endif
return texData;
}
QT_END_NAMESPACE

View File

@ -0,0 +1,70 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QPKMHANDLER_H
#define QPKMHANDLER_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include "qtexturefilehandler_p.h"
QT_BEGIN_NAMESPACE
class QPkmHandler : public QTextureFileHandler
{
public:
using QTextureFileHandler::QTextureFileHandler;
static bool canRead(const QByteArray &suffix, const QByteArray &block);
QTextureFileData read() override;
};
QT_END_NAMESPACE
#endif // QPKMHANDLER_H

View File

@ -0,0 +1,279 @@
/****************************************************************************
**
** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qtexturefiledata_p.h"
#include <QMetaEnum>
#if QT_CONFIG(opengl)
#include <QOpenGLTexture>
#endif
QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(lcQtGuiTextureIO, "qt.gui.textureio");
class QTextureFileDataPrivate : public QSharedData
{
public:
QTextureFileDataPrivate()
{
}
QTextureFileDataPrivate(const QTextureFileDataPrivate &other)
: QSharedData(other),
logName(other.logName),
data(other.data),
offsets(other.offsets),
lengths(other.lengths),
size(other.size),
format(other.format)
{
}
~QTextureFileDataPrivate()
{
}
void ensureLevels(int num, bool force = false)
{
const int newSize = force ? num : qMax(offsets.size(), num);
offsets.resize(newSize);
lengths.resize(newSize);
}
QByteArray logName;
QByteArray data;
QVector<int> offsets;
QVector<int> lengths;
QSize size;
quint32 format = 0;
quint32 internalFormat = 0;
quint32 baseInternalFormat = 0;
};
QTextureFileData::QTextureFileData()
{
}
QTextureFileData::QTextureFileData(const QTextureFileData &other)
: d(other.d)
{
}
QTextureFileData &QTextureFileData::operator=(const QTextureFileData &other)
{
d = other.d;
return *this;
}
QTextureFileData::~QTextureFileData()
{
}
bool QTextureFileData::isNull() const
{
return !d;
}
bool QTextureFileData::isValid() const
{
if (!d)
return false;
if (d->data.isEmpty() || d->size.isEmpty() || (!d->format && !d->internalFormat))
return false;
const int numChunks = d->offsets.size();
if (numChunks == 0 || (d->lengths.size() != numChunks))
return false;
const qint64 sz = d->data.size();
for (int i = 0; i < numChunks; i++) {
qint64 offi = d->offsets.at(i);
qint64 leni = d->lengths.at(i);
if (offi < 0 || offi >= sz || leni <= 0 || (offi + leni > sz))
return false;
}
return true;
}
void QTextureFileData::clear()
{
d = nullptr;
}
QByteArray QTextureFileData::data() const
{
return d ? d->data : QByteArray();
}
void QTextureFileData::setData(const QByteArray &data)
{
if (!d.constData()) //### uh think about this design, this is the only way to create; should be constructor instead at least
d = new QTextureFileDataPrivate;
d->data = data;
}
int QTextureFileData::dataOffset(int level) const
{
return (d && d->offsets.size() > level) ? d->offsets.at(level) : 0;
}
void QTextureFileData::setDataOffset(int offset, int level)
{
if (d.constData() && level >= 0) {
d->ensureLevels(level + 1);
d->offsets[level] = offset;
}
}
int QTextureFileData::dataLength(int level) const
{
return (d && d->lengths.size() > level) ? d->lengths.at(level) : 0;
}
void QTextureFileData::setDataLength(int length, int level)
{
if (d.constData() && level >= 0) {
d->ensureLevels(level + 1);
d->lengths[level] = length;
}
}
int QTextureFileData::numLevels() const
{
return d ? d->offsets.size() : 0;
}
void QTextureFileData::setNumLevels(int num)
{
if (d && num >= 0)
d->ensureLevels(num, true);
}
QSize QTextureFileData::size() const
{
return d ? d->size : QSize();
}
void QTextureFileData::setSize(const QSize &size)
{
if (d.constData())
d->size = size;
}
quint32 QTextureFileData::glFormat() const
{
return d ? d->format : 0;
}
void QTextureFileData::setGLFormat(quint32 format)
{
if (d.constData())
d->format = format;
}
quint32 QTextureFileData::glInternalFormat() const
{
return d ? d->internalFormat : 0;
}
void QTextureFileData::setGLInternalFormat(quint32 format)
{
if (d.constData())
d->internalFormat = format;
}
quint32 QTextureFileData::glBaseInternalFormat() const
{
return d ? d->baseInternalFormat : 0;
}
void QTextureFileData::setGLBaseInternalFormat(quint32 format)
{
if (d.constData())
d->baseInternalFormat = format;
}
QByteArray QTextureFileData::logName() const
{
return d ? d->logName : QByteArray();
}
void QTextureFileData::setLogName(const QByteArray &name)
{
if (d.constData())
d->logName = name;
}
QByteArray glFormatName(quint32 fmt)
{
const char *id = 0;
#if QT_CONFIG(opengl)
id = QMetaEnum::fromType<QOpenGLTexture::TextureFormat>().valueToKey(fmt);
#endif
QByteArray res(id ? id : "(?)");
res += " [0x" + QByteArray::number(fmt, 16).rightJustified(4, '0') + ']';
return res;
}
QDebug operator<<(QDebug dbg, const QTextureFileData &d)
{
QDebugStateSaver saver(dbg);
dbg.nospace() << "QTextureFileData(";
if (!d.isNull()) {
dbg.space() << d.logName() << d.size();
dbg << "glFormat:" << glFormatName(d.glFormat());
dbg << "glInternalFormat:" << glFormatName(d.glInternalFormat());
dbg << "glBaseInternalFormat:" << glFormatName(d.glBaseInternalFormat());
dbg.nospace() << "Levels: " << d.numLevels();
if (!d.isValid())
dbg << " {Invalid}";
dbg << ")";
} else {
dbg << "null)";
}
return dbg;
}
QT_END_NAMESPACE

View File

@ -0,0 +1,115 @@
/****************************************************************************
**
** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QTEXTUREFILEDATA_P_H
#define QTEXTUREFILEDATA_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include <QtGui/qtguiglobal.h>
#include <QSharedDataPointer>
#include <QLoggingCategory>
#include <QDebug>
QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(lcQtGuiTextureIO)
class QTextureFileDataPrivate;
class Q_GUI_EXPORT QTextureFileData
{
public:
QTextureFileData();
QTextureFileData(const QTextureFileData &other);
QTextureFileData &operator=(const QTextureFileData &other);
~QTextureFileData();
bool isNull() const;
bool isValid() const;
void clear();
QByteArray data() const;
void setData(const QByteArray &data);
int dataOffset(int level = 0) const;
void setDataOffset(int offset, int level = 0);
int dataLength(int level = 0) const;
void setDataLength(int length, int level = 0);
int numLevels() const;
void setNumLevels(int num);
QSize size() const;
void setSize(const QSize &size);
quint32 glFormat() const;
void setGLFormat(quint32 format);
quint32 glInternalFormat() const;
void setGLInternalFormat(quint32 format);
quint32 glBaseInternalFormat() const;
void setGLBaseInternalFormat(quint32 format);
QByteArray logName() const;
void setLogName(const QByteArray &name);
private:
QSharedDataPointer<QTextureFileDataPrivate> d;
};
Q_DECLARE_TYPEINFO(QTextureFileData, Q_MOVABLE_TYPE);
Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QTextureFileData &d);
QT_END_NAMESPACE
#endif // QABSTRACTLAYOUTSTYLEINFO_P_H

View File

@ -0,0 +1,79 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QTEXTUREFILEHANDLER_P_H
#define QTEXTUREFILEHANDLER_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include "qtexturefiledata_p.h"
QT_BEGIN_NAMESPACE
class QTextureFileHandler
{
public:
QTextureFileHandler(QIODevice *device, const QByteArray &logName = QByteArray())
: m_device(device)
{
m_logName = !logName.isEmpty() ? logName : QByteArrayLiteral("(unknown)");
}
virtual ~QTextureFileHandler() {}
virtual QTextureFileData read() = 0;
QIODevice *device() const { return m_device; }
QByteArray logName() const { return m_logName; }
private:
QIODevice *m_device = nullptr;
QByteArray m_logName;
};
QT_END_NAMESPACE
#endif // QTEXTUREFILEHANDLER_P_H

View File

@ -0,0 +1,102 @@
/****************************************************************************
**
** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qtexturefilereader_p.h"
#include "qpkmhandler_p.h"
#include "qktxhandler_p.h"
#include <QFileInfo>
QT_BEGIN_NAMESPACE
QTextureFileReader::QTextureFileReader(QIODevice *device, const QString &fileName)
: m_device(device), m_fileName(fileName)
{
}
QTextureFileReader::~QTextureFileReader()
{
delete m_handler;
}
QTextureFileData QTextureFileReader::read()
{
if (!canRead())
return QTextureFileData();
return m_handler->read();
}
bool QTextureFileReader::canRead()
{
if (!checked) {
checked = true;
if (!init())
return false;
QByteArray headerBlock = m_device->peek(64);
QFileInfo fi(m_fileName);
QByteArray suffix = fi.suffix().toLower().toLatin1();
QByteArray logName = fi.fileName().toUtf8();
// Currently the handlers are hardcoded; later maybe a list of plugins
if (QPkmHandler::canRead(suffix, headerBlock)) {
m_handler = new QPkmHandler(m_device, logName);
} else if (QKtxHandler::canRead(suffix, headerBlock)) {
m_handler = new QKtxHandler(m_device, logName);
}
// else if OtherHandler::canRead() ...etc.
}
return (m_handler != nullptr);
}
QList<QByteArray> QTextureFileReader::supportedFileFormats()
{
// Hardcoded for now
return {QByteArrayLiteral("pkm"), QByteArrayLiteral("ktx")};
}
bool QTextureFileReader::init()
{
if (!m_device)
return false;
return m_device->isReadable();
}
QT_END_NAMESPACE

View File

@ -0,0 +1,88 @@
/****************************************************************************
**
** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QTEXTUREFILEREADER_H
#define QTEXTUREFILEREADER_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include "qtexturefiledata_p.h"
#include <QString>
#include <QFileInfo>
QT_BEGIN_NAMESPACE
class QIODevice;
class QTextureFileHandler;
class Q_GUI_EXPORT QTextureFileReader
{
public:
QTextureFileReader(QIODevice *device, const QString &fileName = QString()); //### drop this logname thing?
~QTextureFileReader();
bool canRead();
QTextureFileData read();
// TBD access function to params
// TBD ask for identified fmt
static QList<QByteArray> supportedFileFormats();
private:
bool init();
QIODevice *m_device = nullptr;
QString m_fileName;
QTextureFileHandler *m_handler = nullptr;
bool checked = false;
};
QT_END_NAMESPACE
#endif // QTEXTUREFILEREADER_H

View File

@ -14,7 +14,12 @@ HEADERS += \
util/qshaderlanguage_p.h \
util/qshadernode_p.h \
util/qshadernodeport_p.h \
util/qshadernodesloader_p.h
util/qshadernodesloader_p.h \
util/qtexturefiledata_p.h \
util/qtexturefilereader_p.h \
util/qtexturefilehandler_p.h \
util/qpkmhandler_p.h \
util/qktxhandler_p.h
SOURCES += \
util/qdesktopservices.cpp \
@ -29,4 +34,8 @@ SOURCES += \
util/qshaderlanguage.cpp \
util/qshadernode.cpp \
util/qshadernodeport.cpp \
util/qshadernodesloader.cpp
util/qshadernodesloader.cpp \
util/qtexturefiledata.cpp \
util/qtexturefilereader.cpp \
util/qpkmhandler.cpp \
util/qktxhandler.cpp

View File

@ -0,0 +1,5 @@
CONFIG += testcase
QT += testlib gui-private
SOURCES += tst_qtexturefilereader.cpp
TARGET = tst_qtexturefilereader
RESOURCES += qtexturefilereader.qrc

View File

@ -0,0 +1,6 @@
<RCC>
<qresource prefix="/">
<file>texturefiles/car.ktx</file>
<file>texturefiles/pattern.pkm</file>
</qresource>
</RCC>

View File

@ -0,0 +1,97 @@
/****************************************************************************
**
** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <private/qtexturefilereader_p.h>
#include <QtTest>
class tst_qtexturefilereader : public QObject
{
Q_OBJECT
private slots:
void checkHandlers_data();
void checkHandlers();
};
void tst_qtexturefilereader::checkHandlers_data()
{
QTest::addColumn<QString>("fileName");
QTest::addColumn<QSize>("size");
QTest::addColumn<quint32>("glFormat");
QTest::addColumn<quint32>("glInternalFormat");
// todo: glBaseInternalFormat
QTest::addColumn<int>("levels");
QTest::addColumn<int>("dataOffset");
QTest::addColumn<int>("dataLength");
QTest::addRow("pattern.pkm") << QStringLiteral(":/texturefiles/pattern.pkm")
<< QSize(64, 64)
<< quint32(0x0)
<< quint32(0x8d64)
<< 1
<< 16
<< 2048;
QTest::addRow("car.ktx") << QStringLiteral(":/texturefiles/car.ktx")
<< QSize(146, 80)
<< quint32(0x0)
<< quint32(0x9278)
<< 1
<< 68
<< 11840;
}
void tst_qtexturefilereader::checkHandlers()
{
QFETCH(QString, fileName);
QFETCH(QSize, size);
QFETCH(quint32, glFormat);
QFETCH(quint32, glInternalFormat);
QFETCH(int, levels);
QFETCH(int, dataOffset);
QFETCH(int, dataLength);
QFile f(fileName);
QVERIFY(f.open(QIODevice::ReadOnly));
QTextureFileReader r(&f, fileName);
QVERIFY(r.canRead());
QTextureFileData tex = r.read();
QVERIFY(!tex.isNull());
QVERIFY(tex.isValid());
QCOMPARE(tex.size(), size);
QCOMPARE(tex.glFormat(), glFormat);
QCOMPARE(tex.glInternalFormat(), glInternalFormat);
QCOMPARE(tex.numLevels(), levels);
QCOMPARE(tex.dataOffset(), dataOffset);
QCOMPARE(tex.dataLength(), dataLength);
}
QTEST_MAIN(tst_qtexturefilereader)
#include "tst_qtexturefilereader.moc"

View File

@ -10,4 +10,4 @@ SUBDIRS= \
qshadergraphloader \
qshadernodes \
qshadernodesloader \
qtexturefilereader