54 lines
1.4 KiB
C++
54 lines
1.4 KiB
C++
#include <psemek/gfx/pixmap.hpp>
|
|
#include <psemek/gfx/detail/stb_image.h>
|
|
#include <psemek/util/exception.hpp>
|
|
|
|
namespace psemek::gfx
|
|
{
|
|
|
|
template <typename Pixel>
|
|
basic_pixmap<Pixel> read_image(io::istream && is)
|
|
{
|
|
stbi_io_callbacks callbacks;
|
|
|
|
callbacks.read = [](void * user, char * data, int size) -> int
|
|
{
|
|
return reinterpret_cast<io::istream *>(user)->read(data, size);
|
|
};
|
|
|
|
callbacks.skip = [](void * user, int count)
|
|
{
|
|
if (count < 0)
|
|
throw util::exception("unget is not supported in stb_image skip callback");
|
|
|
|
char buffer[1024];
|
|
while (count > 0)
|
|
{
|
|
int read_count = std::min(1024, count);
|
|
count -= reinterpret_cast<io::istream *>(user)->read(buffer, read_count);
|
|
}
|
|
};
|
|
|
|
callbacks.eof = [](void * user)
|
|
{
|
|
return reinterpret_cast<io::istream *>(user)->finished() ? 1 : 0;
|
|
};
|
|
|
|
int width, height, channels;
|
|
auto data = stbi_load_from_callbacks(&callbacks, &is, &width, &height, &channels, sizeof(Pixel));
|
|
|
|
if (!data)
|
|
throw util::exception(stbi_failure_reason());
|
|
|
|
basic_pixmap<Pixel> result({width, height});
|
|
std::copy(data, data + width * height * sizeof(Pixel), reinterpret_cast<stbi_uc *>(result.data()));
|
|
|
|
stbi_image_free(data);
|
|
|
|
return result;
|
|
}
|
|
|
|
template pixmap_monochrome read_image<std::uint8_t>(io::istream && is);
|
|
template pixmap_rgb read_image<color_rgb>(io::istream && is);
|
|
template pixmap_rgba read_image<color_rgba>(io::istream && is);
|
|
|
|
}
|