Assimp IOSystem for Qt Resource paths

This commit is contained in:
Shaun Reed 2023-01-15 16:04:48 -05:00
parent 55dd8e5c3c
commit 195a4ef30d
19 changed files with 373 additions and 86123 deletions

View File

@ -1,5 +1,5 @@
# Created by RapidCompact v4.3.2 | www.rapidcompact.com
mtllib rapid.mtl
mtllib bird.mtl
o mesh_0
v 290.631131412626928068 748.484123578408002686 -224.342122210487644907
v 282.356783853739386814 751.945844816198814442 -222.136356657249308455

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 254 KiB

View File

@ -1,16 +0,0 @@
# Blender MTL File: 'None'
# Material Count: 1
newmtl Lion
Ns 500.000001
Ka 1.000000 1.000000 1.000000
Kd 0.800000 0.800000 0.800000
Ks 0.800000 0.800000 0.800000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 2
map_Bump normal.jpg
map_Kd diffuse.jpg
map_Ns roughness.jpg
refl specular.jpg

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 484 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 562 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 KiB

View File

@ -52,4 +52,79 @@
<file alias="skybox.frag">skybox/skybox.frag</file>
<file alias="skybox.vert">skybox/skybox.vert</file>
</qresource>
<qresource prefix="/models">
<file>models/spartan/spartan.obj</file>
<file>models/alien-hominid/alien.obj</file>
<file>models/spartan/spartan.mtl</file>
<file>models/spartan/Spartan_Ears_Mat_BaseColor.png</file>
<file>models/spartan/Spartan_Undersuit_Mat_Specular.png</file>
<file>models/spartan/Spartan_Undersuit_Mat_Roughness.png</file>
<file>models/spartan/Spartan_Undersuit_Mat_Normal.png</file>
<file>models/spartan/Spartan_Undersuit_Mat_Metallic.png</file>
<file>models/spartan/Spartan_Undersuit_Mat_BaseColor.png</file>
<file>models/spartan/Spartan_Undersuit_Mat_AO.png</file>
<file>models/spartan/Spartan_Shoulder_Mat_Specular.png</file>
<file>models/spartan/Spartan_Shoulder_Mat_Roughness.png</file>
<file>models/spartan/Spartan_Shoulder_Mat_Normal.png</file>
<file>models/spartan/Spartan_Shoulder_Mat_Metallic.png</file>
<file>models/spartan/Spartan_Shoulder_Mat_BaseColor.png</file>
<file>models/spartan/Spartan_Shoulder_Mat_AO.png</file>
<file>models/spartan/Spartan_Legs_Mat_Specular.png</file>
<file>models/spartan/Spartan_Legs_Mat_Roughness.png</file>
<file>models/spartan/Spartan_Legs_Mat_Normal.png</file>
<file>models/spartan/Spartan_Legs_Mat_Metallic.png</file>
<file>models/spartan/Spartan_Legs_Mat_BaseColor.png</file>
<file>models/spartan/Spartan_Legs_Mat_AO.png</file>
<file>models/spartan/Spartan_Helmet_Mat_Specular.png</file>
<file>models/spartan/Spartan_Helmet_Mat_Roughness.png</file>
<file>models/spartan/Spartan_Helmet_Mat_Normal.png</file>
<file>models/spartan/Spartan_Helmet_Mat_Metallic.png</file>
<file>models/spartan/Spartan_Helmet_Mat_BaseColor.png</file>
<file>models/spartan/Spartan_Helmet_Mat_AO.png</file>
<file>models/spartan/Spartan_Ears_Mat_Specular.png</file>
<file>models/spartan/Spartan_Ears_Mat_Roughness.png</file>
<file>models/spartan/Spartan_Ears_Mat_Normal.png</file>
<file>models/spartan/Spartan_Ears_Mat_Metallic.png</file>
<file>models/spartan/Spartan_Ears_Mat_AO.png</file>
<file>models/spartan/Spartan_Chest_Mat_Specular.png</file>
<file>models/spartan/Spartan_Chest_Mat_Roughness.png</file>
<file>models/spartan/Spartan_Chest_Mat_Normal.png</file>
<file>models/spartan/Spartan_Chest_Mat_Metallic.png</file>
<file>models/spartan/Spartan_Chest_Mat_BaseColor.png</file>
<file>models/spartan/Spartan_Chest_Mat_AO.png</file>
<file>models/spartan/Spartan_Arms_Mat_Specular.png</file>
<file>models/spartan/Spartan_Arms_Mat_Roughness.png</file>
<file>models/spartan/Spartan_Arms_Mat_Normal.png</file>
<file>models/spartan/Spartan_Arms_Mat_Metallic.png</file>
<file>models/spartan/Spartan_Arms_Mat_BaseColor.png</file>
<file>models/spartan/Spartan_Arms_Mat_AO.png</file>
<file>models/spartan/lambert1_Roughness.png</file>
<file>models/spartan/lambert1_Nrm.png</file>
<file>models/spartan/lambert1_Colour-Opacity.png</file>
<file>models/backpack/specular.jpg</file>
<file>models/backpack/roughness.jpg</file>
<file>models/backpack/diffuse.jpg</file>
<file>models/backpack/normal.png</file>
<file>models/backpack/backpack.obj</file>
<file>models/backpack/backpack.mtl</file>
<file>models/backpack/ao.jpg</file>
<file>models/alien-hominid/specular.png</file>
<file>models/alien-hominid/roughness.png</file>
<file>models/alien-hominid/normal.png</file>
<file>models/alien-hominid/diffuse.png</file>
<file>models/alien-hominid/blaster_specular.png</file>
<file>models/alien-hominid/blaster_roughness.png</file>
<file>models/alien-hominid/blaster_normal.png</file>
<file>models/alien-hominid/blaster_emissive.png</file>
<file>models/alien-hominid/blaster_diffuse.png</file>
<file>models/alien-hominid/alien.mtl</file>
<file>models/scythe/scythe.obj</file>
<file>models/scythe/scythe.mtl</file>
<file>models/scythe/diffuse.png</file>
<file>models/bird/occlusion.jpg</file>
<file>models/bird/normal.jpg</file>
<file>models/bird/diffuse.jpg</file>
<file>models/bird/bird.obj</file>
<file>models/bird/bird.mtl</file>
</qresource>
</RCC>

View File

@ -15,11 +15,9 @@ set(
debugconsole.cpp debugconsole.ui
toolbox.cpp toolbox.ui
treeview.cpp treeview.ui
qtkmainwindow.cpp qtkmainwindow.ui
)
set(
QTK_PLUGIN_LIBRARY_HEADERS
qtkmainwindow.h
qtkwidget.h
debugconsole.h
toolbox.h
@ -53,16 +51,16 @@ install(
# Qtk Widget Collection Plugin
################################################################################
# Create a Qt Designer plugin for a collection of widgets from our library.
qt_add_plugin(qtk-collection)
qt_add_plugin(qtk_collection STATIC)
target_sources(
qtk-collection PRIVATE
qtk_collection PRIVATE
widgetplugincollection.cpp widgetplugincollection.h
widgetplugin.cpp widgetplugin.h
)
target_link_libraries(qtk-collection PUBLIC qtk-plugin-library)
target_link_libraries(qtk_collection PUBLIC qtk-plugin-library)
install(
TARGETS qtk-collection
TARGETS qtk_collection
RUNTIME DESTINATION "${QTK_PLUGIN_INSTALL_DIR}"
BUNDLE DESTINATION "${QTK_PLUGIN_INSTALL_DIR}"
LIBRARY DESTINATION "${QTK_PLUGIN_INSTALL_DIR}"
@ -75,10 +73,11 @@ install(
set(
QTK_APP_SOURCES
examplescene.cpp examplescene.h
qtkmainwindow.cpp qtkmainwindow.h qtkmainwindow.ui
main.cpp
)
qt6_add_resources(QTK_APP_SOURCES "${QTK_RESOURCES}/resources.qrc")
qt6_add_big_resources(QTK_APP_SOURCES "${QTK_RESOURCES}/resources.qrc")
configure_file(
resources.h.in
"${CMAKE_CURRENT_BINARY_DIR}/resources.h"
@ -105,10 +104,10 @@ install(
qt_generate_deploy_app_script(
TARGET qtk-main
FILENAME_VARIABLE deploy_script
FILENAME_VARIABLE QTK_DEPLOY_SCRIPT
NO_UNSUPPORTED_PLATFORM_ERROR
)
install(SCRIPT ${deploy_script})
install(SCRIPT ${QTK_DEPLOY_SCRIPT})
if(WIN32)
get_target_property(_qt6_qmake_location Qt6::qmake IMPORTED_LOCATION)

View File

@ -41,7 +41,8 @@ void ExampleScene::init() {
myCube->setColor(RED);
addObject(myCube);
auto mySpartan = new Model("My spartan", PATH("/models/spartan/spartan.obj"));
auto mySpartan =
new Model("My spartan", ":/models/models/spartan/spartan.obj");
mySpartan->getTransform().setTranslation(0.0f, 0.5f, 0.0f);
mySpartan->getTransform().setScale(0.5f);
addObject(mySpartan);
@ -79,35 +80,30 @@ void ExampleScene::init() {
// 3D Model loading
auto model = addObject(
new Qtk::Model("backpack", PATH("/models/backpack/backpack.obj")));
auto test = PATH("/models/backpack/backpack.obj");
new Qtk::Model("backpack", ":/models/models/backpack/backpack.obj"));
// Sometimes model textures need flipped in certain directions
model->flipTexture("diffuse.jpg", false, true);
model->getTransform().setTranslation(0.0f, 0.0f, -10.0f);
model = addObject(new Qtk::Model("bird", PATH("/models/bird/bird.obj")));
model = addObject(new Qtk::Model("bird", ":/models/models/bird/bird.obj"));
model->getTransform().setTranslation(2.0f, 2.0f, -10.0f);
// Sometimes the models are very large
model->getTransform().scale(0.0025f);
model->getTransform().rotate(-110.0f, 0.0f, 1.0f, 0.0f);
model = addObject(new Qtk::Model("lion", PATH("/models/lion/lion.obj")));
model->getTransform().setTranslation(-3.0f, -1.0f, -10.0f);
model->getTransform().scale(0.15f);
model = addObject(
new Qtk::Model("alien", PATH("/models/alien-hominid/alien.obj")));
new Qtk::Model("alien", ":/models/models/alien-hominid/alien.obj"));
model->getTransform().setTranslation(2.0f, -1.0f, -5.0f);
model->getTransform().scale(0.15f);
model =
addObject(new Qtk::Model("scythe", PATH("/models/scythe/scythe.obj")));
addObject(new Qtk::Model("scythe", ":/models/models/scythe/scythe.obj"));
model->getTransform().setTranslation(-6.0f, 0.0f, -10.0f);
model->getTransform().rotate(-90.0f, 1.0f, 0.0f, 0.0f);
model->getTransform().rotate(90.0f, 0.0f, 1.0f, 0.0f);
model = addObject(
new Qtk::Model("masterChief", PATH("/models/spartan/spartan.obj")));
new Qtk::Model("masterChief", ":/models/models/spartan/spartan.obj"));
model->getTransform().setTranslation(-1.5f, 0.5f, -2.0f);
@ -233,7 +229,7 @@ void ExampleScene::init() {
/* Test alien Model with phong lighting and specular mapping. */
model = addObject(new Qtk::Model(
"alienTest", PATH("/models/alien-hominid/alien.obj"),
"alienTest", ":/models/models/alien-hominid/alien.obj",
":/shaders/model-specular.vert", ":/shaders/model-specular.frag"));
model->getTransform().setTranslation(3.0f, -1.0f, 10.0f);
model->getTransform().scale(0.15f);
@ -259,7 +255,7 @@ void ExampleScene::init() {
/* Test spartan Model with phong lighting, specular and normal mapping. */
model = addObject(new Qtk::Model(
"spartanTest", PATH("/models/spartan/spartan.obj"),
"spartanTest", ":/models/models/spartan/spartan.obj",
":/shaders/model-normals.vert", ":/shaders/model-normals.frag"));
model->getTransform().setTranslation(0.0f, -1.0f, 10.0f);
model->getTransform().scale(2.0f);

View File

@ -1,8 +1,6 @@
#ifndef QTK_RESOURCES_H_IN_H
#define QTK_RESOURCES_H_IN_H
#define RESOURCES "@CMAKE_SOURCE_DIR@/resources"
#define PATH(a) RESOURCES a
// Not currently in use, but will be in the future.
#endif // QTK_RESOURCES_H_IN_H

View File

@ -12,13 +12,15 @@ set(
QTK_LIBRARY_PUBLIC_HEADERS
camera3d.h
input.h
shape.h
meshrenderer.h
model.h
modelmesh.h
object.h
qtkapi.h
qtkiostream.h
qtkiosystem.h
scene.h
shape.h
skybox.h
texture.h
transform3D.h
@ -28,18 +30,20 @@ set(
QTK_LIBRARY_SOURCES
camera3d.cpp
input.cpp
shape.cpp
meshrenderer.cpp
model.cpp
modelmesh.cpp
object.cpp
qtkiostream.cpp
qtkiosystem.cpp
scene.cpp
shape.cpp
skybox.cpp
texture.cpp
transform3D.cpp
)
qt6_add_resources(QTK_LIBRARY_SOURCES "${QTK_RESOURCES}/resources.qrc")
qt6_add_big_resources(QTK_LIBRARY_SOURCES "${QTK_RESOURCES}/resources.qrc")
qt_add_library(qtk-library STATIC)
target_sources(qtk-library PRIVATE ${QTK_LIBRARY_SOURCES})
target_sources(

View File

@ -7,9 +7,8 @@
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ##
##############################################################################*/
#include <QFileInfo>
#include "model.h"
#include "qtkiosystem.h"
#include "scene.h"
#include "texture.h"
@ -65,27 +64,27 @@ Model * Qtk::Model::getInstance(const char * name) {
void Model::loadModel(const std::string & path) {
Assimp::Importer import;
// JIC a relative path was used, get the absolute file path
QFileInfo info(path.c_str());
info.makeAbsolute();
mDirectory = info.absoluteFilePath().toStdString();
// If using a Qt Resource path, use QtkIOSystem for file handling.
if(path.front() == ':') {
import.SetIOHandler(new QtkIOSystem());
}
// Used as base path for loading model textures.
mDirectory = path.substr(0, path.find_last_of('/'));
// Import the model, converting non-triangular geometry to triangles
// + And flipping texture UVs, etc..
// Assimp options: http://assimp.sourceforge.net/lib_html/postprocess_8h.html
const aiScene * scene = import.ReadFile(
mDirectory, aiProcess_Triangulate | aiProcess_FlipUVs
| aiProcess_GenSmoothNormals | aiProcess_CalcTangentSpace
| aiProcess_OptimizeMeshes | aiProcess_SplitLargeMeshes);
path.c_str(), aiProcess_Triangulate | aiProcess_FlipUVs
| aiProcess_GenSmoothNormals
| aiProcess_CalcTangentSpace | aiProcess_OptimizeMeshes
| aiProcess_SplitLargeMeshes);
// If there were errors, print and return
if(!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) {
qDebug() << "Error::ASSIMP::" << import.GetErrorString() << "\n";
return;
}
// If there were no errors, find the directory that contains this model
mDirectory = mDirectory.substr(0, mDirectory.find_last_of('/'));
// Pass the pointers to the root node and the scene to recursive function
// + Base case breaks when no nodes left to process on model
@ -182,7 +181,6 @@ ModelMesh Model::processMesh(aiMesh * mesh, const aiScene * scene) {
if(mesh->mMaterialIndex >= 0) {
// Get the material attached to the model using Assimp
aiMaterial * material = scene->mMaterials[mesh->mMaterialIndex];
// Get all diffuse textures from the material
ModelMesh::Textures diffuseMaps = loadMaterialTextures(
material, aiTextureType_DIFFUSE, "texture_diffuse");

82
src/qtk/qtkiostream.cpp Normal file
View File

@ -0,0 +1,82 @@
/*##############################################################################
## Author: Shaun Reed ##
## Legal: All Content (c) 2023 Shaun Reed, all rights reserved ##
## About: Custom IO stream for Qtk to support Qt Resource paths in Assimp ##
## ##
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ##
##############################################################################*/
#include "qtkiostream.h"
using namespace Qtk;
/*******************************************************************************
* Constructors, Destructors
******************************************************************************/
QtkIOStream::QtkIOStream(const char * pFile, const char * pMode) :
mFile(pFile) {
QString mode(pMode);
bool read = mode.contains('r');
bool write = mode.contains('w');
if(read && write) {
mFile.open(QIODevice::ReadWrite);
} else if(read) {
mFile.open(QIODevice::ReadOnly);
} else if(write) {
mFile.open(QIODevice::WriteOnly);
} else {
qDebug() << "[Qtk::QtkIOStream] Invalid file open mode: " << mode << "\n";
}
}
/*******************************************************************************
* Public Member Functions
******************************************************************************/
size_t QtkIOStream::Read(void * pvBuffer, size_t pSize, size_t pCount) {
size_t read = 0;
do {
auto readSize = mFile.read((char *)pvBuffer + read, pSize);
if(readSize < 0) {
qDebug() << "[Qtk::QtkIOStream] Failed to read (" << pSize
<< ") bytes from file at: " << mFile.filesystemFileName().c_str()
<< "\n";
return -1;
}
read += readSize;
} while(pCount--);
return read;
}
size_t QtkIOStream::Write(const void * pvBuffer, size_t pSize, size_t pCount) {
size_t wrote = 0;
do {
auto writeSize = mFile.write((char *)pvBuffer + wrote, pSize);
if(writeSize < 0) {
qDebug() << "[Qtk::QtkIOStream] Failed to write buffer with size ("
<< pSize
<< ") to file at: " << mFile.filesystemFileName().c_str()
<< "\n";
return -1;
}
wrote += writeSize;
} while(pCount--);
return wrote;
}
aiReturn QtkIOStream::Seek(size_t pOffset, aiOrigin pOrigin) {
return mFile.seek(pOffset) ? aiReturn_SUCCESS : aiReturn_FAILURE;
}
size_t QtkIOStream::Tell() const {
return mFile.pos();
}
size_t QtkIOStream::FileSize() const {
return mFile.size();
}
void QtkIOStream::Flush() {
mFile.flush();
}

85
src/qtk/qtkiostream.h Normal file
View File

@ -0,0 +1,85 @@
/*##############################################################################
## Author: Shaun Reed ##
## Legal: All Content (c) 2023 Shaun Reed, all rights reserved ##
## About: Custom IO stream for Qtk to support Qt Resource paths in Assimp ##
## ##
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ##
##############################################################################*/
#include <QFile>
#include <QFileInfo>
#include <assimp/IOStream.hpp>
#include <assimp/IOSystem.hpp>
#ifndef QTK_QTKIOSTREAM_H
#define QTK_QTKIOSTREAM_H
namespace Qtk {
/**
* Custom Assimp IO stream to support QtkIOSystem file handling.
* Allows direct use of Qt Resource paths for loading models in Assimp.
*/
class QtkIOStream : public Assimp::IOStream {
friend class QtkIOSystem;
protected:
/** Constructor protected for private usage by QtkIOSystem */
QtkIOStream(const char * pFile, const char * pMode);
public:
~QtkIOStream() = default;
/**
* Reads data into pvBuffer in pCount batches of length pSize.
* The final pvBuffer will contain data read from all batches.
*
* @param pvBuffer Buffer to read data into.
* @param pSize Size in bytes for each read.
* @param pCount Number of reads to perform.
* @return Length of total bytes read into pvBuffer, or -1 on failure.
*/
size_t Read(void * pvBuffer, size_t pSize, size_t pCount) override;
/**
* Writes data from pvBuffer in pCount batches of length pSize.
* The final mFile member will contain all input data from pvBuffer.
*
* @param pvBuffer Buffer to write data from.
* @param pSize Size in bytes for each write.
* @param pCount Number of writes to perfom.
* @return Length of total bytes wrote into buffer, or -1 on failure.
*/
size_t Write(const void * pvBuffer, size_t pSize, size_t pCount) override;
/**
* Change the current read position in the mFile Qt resource.
*
* @param pOffset Offset position to set.
* @param pOrigin Origin position to use for relative offset.
* @return aiReturn_SUCCESS, or aiReturn_FAILURE on failure.
*/
aiReturn Seek(size_t pOffset, aiOrigin pOrigin) override;
/**
* @return The current position in mFile.
*/
[[nodiscard]] size_t Tell() const override;
/**
* @return The total size of mFile.
*/
[[nodiscard]] size_t FileSize() const override;
/**
* Flushes buffered data to mFile.
*/
void Flush() override;
private:
// Corresponding file for Qt Resource path.
QFile mFile;
};
} // namespace Qtk
#endif // QTK_QTKIOSTREAM_H

39
src/qtk/qtkiosystem.cpp Normal file
View File

@ -0,0 +1,39 @@
/*##############################################################################
## Author: Shaun Reed ##
## Legal: All Content (c) 2023 Shaun Reed, all rights reserved ##
## About: Custom IO system for Qtk to support Qt Resource paths in Assimp ##
## ##
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ##
##############################################################################*/
#include "qtkiosystem.h"
using namespace Qtk;
/*******************************************************************************
* Public Member Functions
******************************************************************************/
bool QtkIOSystem::Exists(const char * pFile) const {
return QFileInfo::exists(pFile);
}
char QtkIOSystem::getOsSeparator() const {
#ifndef _WIN32
return '/';
#else
return '\\';
#endif
}
Assimp::IOStream * QtkIOSystem::Open(const char * pFile, const char * pMode) {
if(!QFileInfo::exists(pFile)) {
qDebug() << "[Qtk::QtkIOSystem] failed to open file: " << pFile << "\n";
return nullptr;
}
return new QtkIOStream(pFile, pMode);
}
void QtkIOSystem::Close(Assimp::IOStream * pFile) {
delete pFile;
}

53
src/qtk/qtkiosystem.h Normal file
View File

@ -0,0 +1,53 @@
/*##############################################################################
## Author: Shaun Reed ##
## Legal: All Content (c) 2023 Shaun Reed, all rights reserved ##
## About: Custom IO system for Qtk to support Qt Resource paths in Assimp ##
## ##
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ##
##############################################################################*/
#include <assimp/IOStream.hpp>
#include <assimp/IOSystem.hpp>
#include "qtkapi.h"
#include "qtkiostream.h"
#ifndef QTK_QTKIOSYSTEM_H
#define QTK_QTKIOSYSTEM_H
namespace Qtk {
/**
* Assimp IO system for loading models with assimp, using Qt Resource paths.
*/
class QtkIOSystem : public Assimp::IOSystem {
public:
QtkIOSystem() = default;
~QtkIOSystem() = default;
/**
* @param pFile File path to check.
* @return True if the file exists, else false.
*/
bool Exists(const char * pFile) const override;
/**
* @return Path separator for platform OS.
*/
[[nodiscard]] char getOsSeparator() const override;
/**
* @param pFile File to open for read / writing.
* @param pMode Mode to open file. See `man fopen`.
* @return QtkIOStream for the opened file.
*/
Assimp::IOStream * Open(
const char * pFile, const char * pMode = "rb") override;
/**
* @param pFile File to close.
*/
void Close(Assimp::IOStream * pFile) override;
};
} // namespace Qtk
#endif // QTK_QTKIOSYSTEM_H

View File

@ -19,8 +19,8 @@ QImage * OpenGLTextureFactory::initImage(
QImageReader::setAllocationLimit(512);
auto loadedImage = new QImage(QImage(image).mirrored(flipX, flipY));
if(loadedImage->isNull()) {
qDebug() << "Error loading image: " << image << "\n";
qDebug() << QImageReader::supportedImageFormats();
qDebug() << "[Qtk::OpenGLTextureFactory] Error loading image: " << image
<< "\nSupported types: " << QImageReader::supportedImageFormats();
return Q_NULLPTR;
}