mirror of
https://github.com/matrix-construct/construct
synced 2024-05-23 21:33:44 +02:00
ircd::png: Elaborate callback surface; add logger to prevent libpng writes to stderr.
This commit is contained in:
parent
1d6325949d
commit
66639ee119
|
@ -14,6 +14,8 @@
|
||||||
/// Portable Network Graphics; wrappers a la carte
|
/// Portable Network Graphics; wrappers a la carte
|
||||||
namespace ircd::png
|
namespace ircd::png
|
||||||
{
|
{
|
||||||
|
IRCD_EXCEPTION(ircd::error, error)
|
||||||
|
|
||||||
bool is_animated(const const_buffer &);
|
bool is_animated(const const_buffer &);
|
||||||
|
|
||||||
extern const info::versions version_api, version_abi;
|
extern const info::versions version_api, version_abi;
|
||||||
|
|
153
ircd/png.cc
153
ircd/png.cc
|
@ -10,6 +10,23 @@
|
||||||
|
|
||||||
#include <RB_INC_PNG_H
|
#include <RB_INC_PNG_H
|
||||||
|
|
||||||
|
namespace ircd::png
|
||||||
|
{
|
||||||
|
static void handle_error(png_structp, const char *) noexcept(false);
|
||||||
|
static void handle_warn(png_structp, const char *) noexcept;
|
||||||
|
static void *handle_alloc(png_structp, size_t) noexcept;
|
||||||
|
static void handle_free(png_structp, void *) noexcept;
|
||||||
|
static void handle_read(png_structp, uint8_t *, size_t) noexcept;
|
||||||
|
|
||||||
|
extern log::log log;
|
||||||
|
}
|
||||||
|
|
||||||
|
decltype(ircd::png::log)
|
||||||
|
ircd::png::log
|
||||||
|
{
|
||||||
|
"png"
|
||||||
|
};
|
||||||
|
|
||||||
decltype(ircd::png::version_api)
|
decltype(ircd::png::version_api)
|
||||||
ircd::png::version_api
|
ircd::png::version_api
|
||||||
{
|
{
|
||||||
|
@ -43,7 +60,20 @@ ircd::png::is_animated(const const_buffer &buf)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
png_infop info {nullptr};
|
png_infop info {nullptr};
|
||||||
png_structp handle {nullptr};
|
png_structp handle
|
||||||
|
{
|
||||||
|
png_create_read_struct_2
|
||||||
|
(
|
||||||
|
PNG_LIBPNG_VER_STRING,
|
||||||
|
nullptr,
|
||||||
|
&handle_error,
|
||||||
|
&handle_warn,
|
||||||
|
nullptr,
|
||||||
|
&handle_alloc,
|
||||||
|
&handle_free
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
const unwind destroy
|
const unwind destroy
|
||||||
{
|
{
|
||||||
[&handle, &info]
|
[&handle, &info]
|
||||||
|
@ -52,52 +82,21 @@ ircd::png::is_animated(const const_buffer &buf)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if(unlikely(!(handle = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr))))
|
if(unlikely(!handle))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(unlikely(!(info = png_create_info_struct(handle))))
|
if(unlikely(!(info = png_create_info_struct(handle))))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const_buffer src{buf};
|
const_buffer src {buf};
|
||||||
png_set_read_fn(handle, &src, []
|
png_set_read_fn(handle, &src, &handle_read);
|
||||||
(auto handle, uint8_t *const ptr, size_t sz)
|
|
||||||
{
|
|
||||||
// Destination where libpng wants data
|
|
||||||
const mutable_buffer dst
|
|
||||||
{
|
|
||||||
reinterpret_cast<char *>(ptr), sz
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get source buffer from our callback user data.
|
|
||||||
const_buffer &src
|
|
||||||
{
|
|
||||||
*reinterpret_cast<const_buffer *>(png_get_io_ptr(handle))
|
|
||||||
};
|
|
||||||
|
|
||||||
// Copy from our buffer to libpng buffer.
|
|
||||||
const size_t copied
|
|
||||||
{
|
|
||||||
copy(dst, src)
|
|
||||||
};
|
|
||||||
|
|
||||||
// Advance our source pointer for the amount copied.
|
|
||||||
const size_t consumed
|
|
||||||
{
|
|
||||||
consume(src, copied)
|
|
||||||
};
|
|
||||||
|
|
||||||
assert(copied == consumed);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Invokes the read callback a few times to traverse the buffer.
|
// Invokes the read callback a few times to traverse the buffer.
|
||||||
png_read_info(handle, info);
|
png_read_info(handle, info);
|
||||||
|
|
||||||
// If there's a non-zero result there's acTL for animation.
|
// If there's a non-zero result there's acTL for animation.
|
||||||
uint32_t frames(0), plays(0);
|
uint32_t num_frames {0}, num_plays {0};
|
||||||
if(png_get_acTL(handle, info, &frames, &plays) != 0)
|
return png_get_acTL(handle, info, &num_frames, &num_plays) != 0;
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
{
|
{
|
||||||
|
@ -107,3 +106,83 @@ ircd::png::is_animated(const const_buffer &buf)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void
|
||||||
|
ircd::png::handle_read(png_structp handle,
|
||||||
|
uint8_t *const ptr,
|
||||||
|
size_t size)
|
||||||
|
noexcept
|
||||||
|
{
|
||||||
|
// Destination where libpng wants data
|
||||||
|
const mutable_buffer dst
|
||||||
|
{
|
||||||
|
reinterpret_cast<char *>(ptr), size
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get source buffer from our callback user data.
|
||||||
|
const_buffer &src
|
||||||
|
{
|
||||||
|
*reinterpret_cast<const_buffer *>(png_get_io_ptr(handle))
|
||||||
|
};
|
||||||
|
|
||||||
|
// Copy from our buffer to libpng buffer.
|
||||||
|
const size_t copied
|
||||||
|
{
|
||||||
|
copy(dst, src)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Advance our source pointer for the amount copied.
|
||||||
|
const size_t consumed
|
||||||
|
{
|
||||||
|
consume(src, copied)
|
||||||
|
};
|
||||||
|
|
||||||
|
assert(copied == consumed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
ircd::png::handle_alloc(png_structp handle,
|
||||||
|
size_t size)
|
||||||
|
noexcept
|
||||||
|
{
|
||||||
|
return std::malloc(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ircd::png::handle_free(png_structp handle,
|
||||||
|
void *const ptr)
|
||||||
|
noexcept
|
||||||
|
{
|
||||||
|
std::free(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ircd::png::handle_warn(png_structp handle,
|
||||||
|
const char *const msg)
|
||||||
|
noexcept
|
||||||
|
{
|
||||||
|
log::dwarning
|
||||||
|
{
|
||||||
|
log, "handle(%p) :%s",
|
||||||
|
static_cast<const void *>(handle),
|
||||||
|
msg,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ircd::png::handle_error(png_structp handle,
|
||||||
|
const char *const msg)
|
||||||
|
noexcept(false)
|
||||||
|
{
|
||||||
|
log::error
|
||||||
|
{
|
||||||
|
log, "handle(%p) :%s",
|
||||||
|
static_cast<const void *>(handle),
|
||||||
|
msg,
|
||||||
|
};
|
||||||
|
|
||||||
|
throw error
|
||||||
|
{
|
||||||
|
"%s", msg
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue