Skip to content

Simplify texture reader/writer code#132

Open
WeirdRubberDuck wants to merge 8 commits intomasterfrom
feature/texture-reader-rewrite
Open

Simplify texture reader/writer code#132
WeirdRubberDuck wants to merge 8 commits intomasterfrom
feature/texture-reader-rewrite

Conversation

@WeirdRubberDuck
Copy link
Copy Markdown
Contributor

Simplifies the code by:

  • Removing the possibility of adding new readers/writers (which were essentially unused). Now there is just one file for reading and one file for writing, both using STB
  • Getting rid of the class and singleton pattern, and replacing the calls with normal functions in a texture namespace

Note that this breaks the support for reading .cmap files as textures. This has been reimplemented in the OpenSpace part of the PR:

Also not that this is a first step as part of a bigger rewrite to give us more flexibility in the texture reading, now that we can't change the format, etc., of a texture after it's created.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors Ghoul’s texture IO by removing the extensible reader/writer registry and replacing it with STB-based free functions under ghoul::io::texture, updating call sites and build files accordingly.

Changes:

  • Removed TextureReaderBase/TextureWriterBase plus the STB/CMAP concrete reader/writer classes, and simplified the public API to functions in ghoul::io::texture.
  • Implemented STB-based loadTexture/imageSize and saveTexture directly in texturereader.cpp / texturewriter.cpp.
  • Updated Assimp model loading to use the new texture reader API and cleaned up src/CMakeLists.txt sources/headers lists.

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
src/io/texture/texturewriter.cpp Inlined STB-based texture writing into a free-function API
include/ghoul/io/texture/texturewriter.h Replaced class-based writer API with ghoul::io::texture functions/exceptions
src/io/texture/texturereader.cpp Inlined STB-based texture reading and extension support helpers
include/ghoul/io/texture/texturereader.h Replaced class-based reader API with ghoul::io::texture functions/exceptions
src/io/model/modelreaderassimp.cpp Updated embedded/local texture loading to call texture::loadTexture and new exception types
src/CMakeLists.txt Removed deleted texture IO sources/headers from the build
src/io/texture/texturewriterstb.cpp (deleted) Removed STB writer class implementation
include/ghoul/io/texture/texturewriterstb.h (deleted) Removed STB writer class declaration
src/io/texture/texturewriterbase.cpp (deleted) Removed writer base exception implementation
include/ghoul/io/texture/texturewriterbase.h (deleted) Removed writer base abstraction
src/io/texture/texturereaderstb.cpp (deleted) Removed STB reader class implementation
include/ghoul/io/texture/texturereaderstb.h (deleted) Removed STB reader class declaration
src/io/texture/texturereadercmap.cpp (deleted) Removed CMAP reader implementation (per PR note)
include/ghoul/io/texture/texturereadercmap.h (deleted) Removed CMAP reader declaration
src/io/texture/texturereaderbase.cpp (deleted) Removed reader base exception implementation
include/ghoul/io/texture/texturereaderbase.h (deleted) Removed reader base abstraction
Comments suppressed due to low confidence (1)

src/io/model/modelreaderassimp.cpp:156

  • The embedded-texture load path catches texture::InvalidLoadException, but texture::loadTexture(void* memory, ...) no longer throws InvalidLoadException when the format is unsupported; it throws MissingReaderException instead. As a result, unsupported embedded textures may now escape this try/catch and fail the model load rather than falling back to a debug texture.

Either update this catch list to handle texture::MissingReaderException (and/or std::exception) for the embedded case, or restore throwing InvalidLoadException from the reader for unsupported embedded formats.

                    try {
                        textureEntry.texture = texture::loadTexture(
                            static_cast<void*>(texture->pcData),
                            texture->mWidth,
                            2,
                            {},
                            texture->achFormatHint
                        );
                        textureEntry.texture->setName(path.C_Str());
                        meshTexture.texture = textureEntry.texture.get();
                    }
                    catch (const texture::InvalidLoadException& e) {
                        LWARNING(std::format(
                            "Could not load unsupported texture from '{}' with size "
                            "'{}': Replacing with flashy color", e._memory, e._size
                        ));

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +72 to +75

// Make sure the directory for the file exists
std::filesystem::create_directory(std::filesystem::path(filename).parent_path());
writer->saveTexture(texture, filename);

Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

saveTexture unconditionally calls std::filesystem::create_directory(path(filename).parent_path()). If filename is in the current directory (no parent path), parent_path() is empty and create_directory("") can throw std::filesystem::filesystem_error.

Consider guarding with if (!parent.empty()) and using create_directories to handle nested paths.

Copilot uses AI. Check for mistakes.
Comment on lines +84 to +95
if (extension == "jpeg" || extension == "jpg") {
stbi_write_jpg(filename.c_str(), w, h, nComponents, pixels.data(), 0);
}
else if (extension == "png") {
stbi_write_png(filename.c_str(), w, h, nComponents, pixels.data(), 0);
}
else if (extension == "bmp") {
stbi_write_bmp(filename.c_str(), w, h, nComponents, pixels.data());
}
else if (extension == "tga") {
stbi_write_tga(filename.c_str(), w, h, nComponents, pixels.data());
}
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The STB write calls (stbi_write_*) return a success/failure value, but the return is currently ignored. This means write failures (permissions, disk full, invalid path) will silently succeed from the caller's perspective.

Capture the return value and throw TextureWriteException when a write fails so callers can handle errors deterministically.

Copilot uses AI. Check for mistakes.
WeirdRubberDuck and others added 2 commits April 8, 2026 16:35
Co-authored-by: Emma Broman <emmabroman740@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
WeirdRubberDuck and others added 2 commits April 9, 2026 10:34
Co-authored-by: Alexander Bock <mail@alexanderbock.eu>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants