Support SVG image loading

This commit is contained in:
Dan Paulat 2024-03-04 00:51:14 -06:00
parent 2a8a16e79f
commit 1ad188546a
2 changed files with 84 additions and 20 deletions

View file

@ -28,6 +28,7 @@ find_package(QT NAMES Qt6
OpenGL OpenGL
OpenGLWidgets OpenGLWidgets
Positioning Positioning
Svg
Widgets REQUIRED) Widgets REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} find_package(Qt${QT_VERSION_MAJOR}
@ -38,6 +39,7 @@ find_package(Qt${QT_VERSION_MAJOR}
OpenGL OpenGL
OpenGLWidgets OpenGLWidgets
Positioning Positioning
Svg
Widgets Widgets
REQUIRED) REQUIRED)
@ -552,6 +554,7 @@ target_link_libraries(scwx-qt PUBLIC Qt${QT_VERSION_MAJOR}::Widgets
Qt${QT_VERSION_MAJOR}::OpenGLWidgets Qt${QT_VERSION_MAJOR}::OpenGLWidgets
Qt${QT_VERSION_MAJOR}::Multimedia Qt${QT_VERSION_MAJOR}::Multimedia
Qt${QT_VERSION_MAJOR}::Positioning Qt${QT_VERSION_MAJOR}::Positioning
Qt${QT_VERSION_MAJOR}::Svg
Boost::json Boost::json
Boost::timer Boost::timer
QMapLibre::Core QMapLibre::Core

View file

@ -20,6 +20,9 @@
#include <stb_image.h> #include <stb_image.h>
#include <stb_rect_pack.h> #include <stb_rect_pack.h>
#include <QFile> #include <QFile>
#include <QFileInfo>
#include <QPainter>
#include <QSvgRenderer>
#include <QUrl> #include <QUrl>
#if defined(_MSC_VER) #if defined(_MSC_VER)
@ -49,6 +52,11 @@ public:
static std::shared_ptr<boost::gil::rgba8_image_t> static std::shared_ptr<boost::gil::rgba8_image_t>
LoadImage(const std::string& imagePath); LoadImage(const std::string& imagePath);
static std::shared_ptr<boost::gil::rgba8_image_t>
ReadPngFile(const QString& imagePath);
static std::shared_ptr<boost::gil::rgba8_image_t>
ReadSvgFile(const QString& imagePath);
std::vector<std::shared_ptr<boost::gil::rgba8_image_t>> std::vector<std::shared_ptr<boost::gil::rgba8_image_t>>
registeredTextures_ {}; registeredTextures_ {};
std::shared_mutex registeredTextureMutex_ {}; std::shared_mutex registeredTextureMutex_ {};
@ -376,34 +384,23 @@ TextureAtlas::Impl::LoadImage(const std::string& imagePath)
{ {
logger_->debug("Loading image: {}", imagePath); logger_->debug("Loading image: {}", imagePath);
std::shared_ptr<boost::gil::rgba8_image_t> image = std::shared_ptr<boost::gil::rgba8_image_t> image = nullptr;
std::make_shared<boost::gil::rgba8_image_t>();
QUrl url = QUrl::fromUserInput(QString::fromStdString(imagePath)); QString qImagePath = QString::fromStdString(imagePath);
QUrl url = QUrl::fromUserInput(qImagePath);
if (url.isLocalFile()) if (url.isLocalFile())
{ {
QFile imageFile(imagePath.c_str()); QString suffix = QFileInfo(qImagePath).suffix().toLower();
imageFile.open(QIODevice::ReadOnly); if (suffix == "svg")
if (!imageFile.isOpen())
{ {
logger_->error("Could not open image: {}", imagePath); image = ReadSvgFile(qImagePath);
return nullptr;
} }
else
boost::iostreams::stream<util::IoDeviceSource> dataStream(imageFile);
try
{ {
boost::gil::read_and_convert_image( image = ReadPngFile(qImagePath);
dataStream, *image, boost::gil::png_tag());
}
catch (const std::exception& ex)
{
logger_->error("Error reading image: {}", ex.what());
return nullptr;
} }
} }
else else
@ -442,6 +439,7 @@ TextureAtlas::Impl::LoadImage(const std::string& imagePath)
width * desiredChannels); width * desiredChannels);
// Copy the view to the destination image // Copy the view to the destination image
image = std::make_shared<boost::gil::rgba8_image_t>();
*image = boost::gil::rgba8_image_t(stbView); *image = boost::gil::rgba8_image_t(stbView);
auto& view = boost::gil::view(*image); auto& view = boost::gil::view(*image);
@ -477,6 +475,69 @@ TextureAtlas::Impl::LoadImage(const std::string& imagePath)
return image; return image;
} }
std::shared_ptr<boost::gil::rgba8_image_t>
TextureAtlas::Impl::ReadPngFile(const QString& imagePath)
{
QFile imageFile(imagePath);
imageFile.open(QIODevice::ReadOnly);
if (!imageFile.isOpen())
{
logger_->error("Could not open image: {}", imagePath.toStdString());
return nullptr;
}
boost::iostreams::stream<util::IoDeviceSource> dataStream(imageFile);
std::shared_ptr<boost::gil::rgba8_image_t> image =
std::make_shared<boost::gil::rgba8_image_t>();
try
{
boost::gil::read_and_convert_image(
dataStream, *image, boost::gil::png_tag());
}
catch (const std::exception& ex)
{
logger_->error("Error reading image: {}", ex.what());
return nullptr;
}
return image;
}
std::shared_ptr<boost::gil::rgba8_image_t>
TextureAtlas::Impl::ReadSvgFile(const QString& imagePath)
{
QSvgRenderer renderer {imagePath};
QPixmap pixmap {renderer.defaultSize()};
pixmap.fill(Qt::GlobalColor::transparent);
QPainter painter {&pixmap};
renderer.render(&painter, pixmap.rect());
QImage qImage = pixmap.toImage();
std::shared_ptr<boost::gil::rgba8_image_t> image = nullptr;
if (qImage.width() > 0 && qImage.height() > 0)
{
// Convert to ARGB32 format if not already (equivalent to bgra8_pixel_t)
qImage.convertTo(QImage::Format_ARGB32);
// Create a view pointing to the underlying QImage pixel data
auto view = boost::gil::interleaved_view(
qImage.width(),
qImage.height(),
reinterpret_cast<const boost::gil::bgra8_pixel_t*>(qImage.constBits()),
qImage.width() * 4);
image = std::make_shared<boost::gil::rgba8_image_t>(view);
}
return image;
}
TextureAtlas& TextureAtlas::Instance() TextureAtlas& TextureAtlas::Instance()
{ {
static TextureAtlas instance_ {}; static TextureAtlas instance_ {};