mirror of
https://github.com/johndoe6345789/SDL3CPlusPlus.git
synced 2026-04-28 15:45:02 +00:00
stuff
This commit is contained in:
315
MaterialX/source/MaterialXRender/ImageHandler.cpp
Normal file
315
MaterialX/source/MaterialXRender/ImageHandler.cpp
Normal file
@@ -0,0 +1,315 @@
|
||||
//
|
||||
// Copyright Contributors to the MaterialX Project
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include <MaterialXRender/ImageHandler.h>
|
||||
|
||||
#include <MaterialXGenShader/Shader.h>
|
||||
#include <MaterialXGenShader/Util.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
MATERIALX_NAMESPACE_BEGIN
|
||||
|
||||
const string IMAGE_PROPERTY_SEPARATOR("_");
|
||||
const string UADDRESS_MODE_SUFFIX(IMAGE_PROPERTY_SEPARATOR + "uaddressmode");
|
||||
const string VADDRESS_MODE_SUFFIX(IMAGE_PROPERTY_SEPARATOR + "vaddressmode");
|
||||
const string FILTER_TYPE_SUFFIX(IMAGE_PROPERTY_SEPARATOR + "filtertype");
|
||||
const string DEFAULT_COLOR_SUFFIX(IMAGE_PROPERTY_SEPARATOR + "default");
|
||||
|
||||
const string ImageLoader::BMP_EXTENSION = "bmp";
|
||||
const string ImageLoader::EXR_EXTENSION = "exr";
|
||||
const string ImageLoader::GIF_EXTENSION = "gif";
|
||||
const string ImageLoader::HDR_EXTENSION = "hdr";
|
||||
const string ImageLoader::JPG_EXTENSION = "jpg";
|
||||
const string ImageLoader::JPEG_EXTENSION = "jpeg";
|
||||
const string ImageLoader::PIC_EXTENSION = "pic";
|
||||
const string ImageLoader::PNG_EXTENSION = "png";
|
||||
const string ImageLoader::PSD_EXTENSION = "psd";
|
||||
const string ImageLoader::TGA_EXTENSION = "tga";
|
||||
const string ImageLoader::TIF_EXTENSION = "tif";
|
||||
const string ImageLoader::TIFF_EXTENSION = "tiff";
|
||||
const string ImageLoader::TX_EXTENSION = "tx";
|
||||
const string ImageLoader::TXT_EXTENSION = "txt";
|
||||
const string ImageLoader::TXR_EXTENSION = "txr";
|
||||
|
||||
//
|
||||
// ImageLoader methods
|
||||
//
|
||||
|
||||
bool ImageLoader::saveImage(const FilePath&, ConstImagePtr, bool)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ImagePtr ImageLoader::loadImage(const FilePath&)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//
|
||||
// ImageHandler methods
|
||||
//
|
||||
|
||||
ImageHandler::ImageHandler(ImageLoaderPtr imageLoader)
|
||||
{
|
||||
addLoader(imageLoader);
|
||||
_zeroImage = createUniformImage(2, 2, 4, Image::BaseType::UINT8, Color4(0.0f));
|
||||
}
|
||||
|
||||
void ImageHandler::addLoader(ImageLoaderPtr loader)
|
||||
{
|
||||
if (loader)
|
||||
{
|
||||
const StringSet& extensions = loader->supportedExtensions();
|
||||
for (const auto& extension : extensions)
|
||||
{
|
||||
_imageLoaders[extension].push_back(loader);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StringSet ImageHandler::supportedExtensions()
|
||||
{
|
||||
StringSet extensions;
|
||||
for (const auto& pair : _imageLoaders)
|
||||
{
|
||||
extensions.insert(pair.first);
|
||||
}
|
||||
return extensions;
|
||||
}
|
||||
|
||||
bool ImageHandler::saveImage(const FilePath& filePath,
|
||||
ConstImagePtr image,
|
||||
bool verticalFlip)
|
||||
{
|
||||
if (!image)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
FilePath foundFilePath = _searchPath.find(filePath);
|
||||
if (foundFilePath.isEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
string extension = foundFilePath.getExtension();
|
||||
for (ImageLoaderPtr loader : _imageLoaders[extension])
|
||||
{
|
||||
bool saved = false;
|
||||
try
|
||||
{
|
||||
saved = loader->saveImage(foundFilePath, image, verticalFlip);
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cerr << "Exception in image I/O library: " << e.what() << std::endl;
|
||||
}
|
||||
if (saved)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ImagePtr ImageHandler::acquireImage(const FilePath& filePath, const Color4& defaultColor)
|
||||
{
|
||||
// Resolve the input filepath.
|
||||
FilePath resolvedFilePath = filePath;
|
||||
if (_resolver)
|
||||
{
|
||||
resolvedFilePath = _resolver->resolve(resolvedFilePath, FILENAME_TYPE_STRING);
|
||||
}
|
||||
|
||||
// Return a cached image if available.
|
||||
ImagePtr cachedImage = getCachedImage(resolvedFilePath);
|
||||
if (cachedImage)
|
||||
{
|
||||
return cachedImage;
|
||||
}
|
||||
|
||||
// Load and cache the requested image.
|
||||
ImagePtr image = loadImage(_searchPath.find(resolvedFilePath));
|
||||
if (image)
|
||||
{
|
||||
cacheImage(resolvedFilePath, image);
|
||||
return image;
|
||||
}
|
||||
|
||||
// No valid image was found, so generate a uniform texture with the given default color.
|
||||
// TODO: This step assumes that the missing image and its default color are in the same
|
||||
// color space, which is not always the case.
|
||||
ImagePtr defaultImage = createUniformImage(1, 1, 4, Image::BaseType::UINT8, defaultColor);
|
||||
cacheImage(resolvedFilePath, defaultImage);
|
||||
return defaultImage;
|
||||
}
|
||||
|
||||
bool ImageHandler::bindImage(ImagePtr, const ImageSamplingProperties&)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ImageHandler::unbindImage(ImagePtr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void ImageHandler::unbindImages()
|
||||
{
|
||||
for (const auto& iter : _imageCache)
|
||||
{
|
||||
unbindImage(iter.second);
|
||||
}
|
||||
}
|
||||
|
||||
bool ImageHandler::createRenderResources(ImagePtr, bool, bool)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void ImageHandler::releaseRenderResources(ImagePtr)
|
||||
{
|
||||
}
|
||||
|
||||
ImageVec ImageHandler::getReferencedImages(ConstDocumentPtr doc)
|
||||
{
|
||||
ImageVec imageVec;
|
||||
for (ElementPtr elem : doc->traverseTree())
|
||||
{
|
||||
if (elem->getActiveSourceUri() != doc->getSourceUri())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
InputPtr input = elem->asA<Input>();
|
||||
if (input && input->getType() == FILENAME_TYPE_STRING)
|
||||
{
|
||||
ImagePtr image = acquireImage(input->getResolvedValueString());
|
||||
if (image)
|
||||
{
|
||||
imageVec.push_back(image);
|
||||
}
|
||||
}
|
||||
}
|
||||
return imageVec;
|
||||
}
|
||||
|
||||
ImagePtr ImageHandler::loadImage(const FilePath& filePath)
|
||||
{
|
||||
string extension = stringToLower(filePath.getExtension());
|
||||
for (ImageLoaderPtr loader : _imageLoaders[extension])
|
||||
{
|
||||
ImagePtr image;
|
||||
try
|
||||
{
|
||||
image = loader->loadImage(filePath);
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cerr << "Exception in image I/O library: " << e.what() << std::endl;
|
||||
}
|
||||
if (image)
|
||||
{
|
||||
return image;
|
||||
}
|
||||
}
|
||||
|
||||
if (!filePath.isEmpty())
|
||||
{
|
||||
if (!filePath.exists())
|
||||
{
|
||||
std::cerr << string("Image file not found: ") + filePath.asString() << std::endl;
|
||||
}
|
||||
else if (!_imageLoaders.count(extension))
|
||||
{
|
||||
std::cerr << string("Unsupported image extension: ") + filePath.asString() << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << string("Image loader failed to parse image: ") + filePath.asString() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ImageHandler::cacheImage(const string& filePath, ImagePtr image)
|
||||
{
|
||||
_imageCache[filePath] = image;
|
||||
}
|
||||
|
||||
ImagePtr ImageHandler::getCachedImage(const FilePath& filePath)
|
||||
{
|
||||
if (_imageCache.count(filePath))
|
||||
{
|
||||
return _imageCache[filePath];
|
||||
}
|
||||
if (!filePath.isAbsolute())
|
||||
{
|
||||
for (const FilePath& path : _searchPath)
|
||||
{
|
||||
FilePath combined = path / filePath;
|
||||
if (_imageCache.count(combined))
|
||||
{
|
||||
return _imageCache[combined];
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//
|
||||
// ImageSamplingProperties methods
|
||||
//
|
||||
|
||||
void ImageSamplingProperties::setProperties(const string& fileNameUniform,
|
||||
const VariableBlock& uniformBlock)
|
||||
{
|
||||
const int INVALID_MAPPED_INT_VALUE = -1; // Any value < 0 is not considered to be invalid
|
||||
|
||||
// Get the additional texture parameters based on image uniform name
|
||||
// excluding the trailing "_file" postfix string
|
||||
string root = fileNameUniform;
|
||||
size_t pos = root.find_last_of(IMAGE_PROPERTY_SEPARATOR);
|
||||
if (pos != string::npos)
|
||||
{
|
||||
root = root.substr(0, pos);
|
||||
}
|
||||
|
||||
const ShaderPort* port = uniformBlock.find(root + UADDRESS_MODE_SUFFIX);
|
||||
ValuePtr intValue = port ? port->getValue() : nullptr;
|
||||
uaddressMode = ImageSamplingProperties::AddressMode(intValue && intValue->isA<int>() ? intValue->asA<int>() : INVALID_MAPPED_INT_VALUE);
|
||||
|
||||
port = uniformBlock.find(root + VADDRESS_MODE_SUFFIX);
|
||||
intValue = port ? port->getValue() : nullptr;
|
||||
vaddressMode = ImageSamplingProperties::AddressMode(intValue && intValue->isA<int>() ? intValue->asA<int>() : INVALID_MAPPED_INT_VALUE);
|
||||
|
||||
port = uniformBlock.find(root + FILTER_TYPE_SUFFIX);
|
||||
intValue = port ? port->getValue() : nullptr;
|
||||
filterType = ImageSamplingProperties::FilterType(intValue && intValue->isA<int>() ? intValue->asA<int>() : INVALID_MAPPED_INT_VALUE);
|
||||
|
||||
port = uniformBlock.find(root + DEFAULT_COLOR_SUFFIX);
|
||||
if (!port)
|
||||
{
|
||||
port = uniformBlock.find(root + DEFAULT_COLOR_SUFFIX + "_cm_in");
|
||||
}
|
||||
ValuePtr colorValue = port ? port->getValue() : nullptr;
|
||||
if (colorValue)
|
||||
{
|
||||
mapValueToColor(colorValue, defaultColor);
|
||||
}
|
||||
}
|
||||
|
||||
bool ImageSamplingProperties::operator==(const ImageSamplingProperties& r) const
|
||||
{
|
||||
return (enableMipmaps == r.enableMipmaps &&
|
||||
uaddressMode == r.uaddressMode &&
|
||||
vaddressMode == r.vaddressMode &&
|
||||
filterType == r.filterType &&
|
||||
defaultColor == r.defaultColor);
|
||||
}
|
||||
|
||||
MATERIALX_NAMESPACE_END
|
||||
Reference in New Issue
Block a user