Added png support

With libpng enabled stickers are converted to png instead of tga.
This commit is contained in:
Vasiliy Vylegzhanin 2017-08-10 00:06:02 +03:00
parent af200e0b38
commit ed2cee3f74
2 changed files with 103 additions and 0 deletions

View file

@ -62,6 +62,15 @@ AS_IF([test "x$enable_libwebp" != "xno"], [
AC_CHECK_LIB([webp], [WebPDecodeRGBA], [], [AC_MSG_ERROR([no libwebp found, try --disable-libwebp, but stickers won't be displayed in the chat])])
])
AC_MSG_CHECKING([for libpng])
AC_ARG_ENABLE([libpng],
AS_HELP_STRING([--disable-libpng], [Disable libpng, stickers won't be converted]))
AS_IF([test "x$enable_libpng" != "xno"], [
AC_MSG_RESULT([enabled])
AC_CHECK_LIB([png], [png_write_png], [], [AC_MSG_ERROR([no libpng found, try --disable-libpng])])
])
AC_ARG_ENABLE([icons],
AS_HELP_STRING([--disable-icons], [Unsupported option. Use 'make noicon_install' instead.]))
AS_IF([test "x$enable_icons" == "xno"], [

View file

@ -24,6 +24,10 @@
#include <webp/decode.h>
#endif
#ifdef HAVE_LIBPNG
#include <png.h>
#endif
PurpleAccount *tls_get_pa (struct tgl_state *TLS) {
return tls_get_data (TLS)->pa;
}
@ -193,6 +197,88 @@ int p2tgl_imgstore_add_with_id_raw (const unsigned char *raw_bgra, unsigned widt
return purple_imgstore_add_with_id (tga, tga_len, NULL);
}
#ifdef HAVE_LIBPNG
struct mem_encode
{
char *buffer;
size_t size;
};
static void p2tgl_png_mem_write (png_structp png_ptr, png_bytep data, png_size_t length) {
struct mem_encode *p = (struct mem_encode *) png_get_io_ptr(png_ptr);
size_t nsize = p->size + length;
if (p->buffer)
p->buffer = g_realloc(p->buffer, nsize);
else
p->buffer = g_malloc(nsize);
memcpy(p->buffer + p->size, data, length);
p->size = nsize;
}
int p2tgl_imgstore_add_with_id_png (const unsigned char *raw_bitmap, unsigned width, unsigned height) {
struct mem_encode state = {NULL, 0};
png_structp png_ptr = NULL;
png_infop info_ptr = NULL;
png_bytepp rows = NULL;
// init png write struct
png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (png_ptr == NULL) {
warning ("error encoding png (create_write_struct failed)");
return 0;
}
// init png info struct
info_ptr = png_create_info_struct (png_ptr);
if (info_ptr == NULL) {
png_destroy_write_struct(&png_ptr, NULL);
warning ("error encoding png (create_info_struct failed)");
return 0;
}
// Set up error handling.
if (setjmp(png_jmpbuf(png_ptr))) {
png_destroy_write_struct(&png_ptr, &info_ptr);
warning ("error while writing png");
return 0;
}
// set img attributes
png_set_IHDR (png_ptr, info_ptr, width, height,
8, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
// alloc row pointers
rows = (png_bytepp) malloc(height * sizeof(png_bytep));
if (rows == NULL) {
png_destroy_write_struct(&png_ptr, &info_ptr);
warning ("error converting to png: malloc failed");
return 0;
}
unsigned i;
for (i = 0; i < height; i++)
rows[i] = (png_bytep)(raw_bitmap + (height - i) * width * 4);
// set own png write function
png_set_write_fn (png_ptr, &state, p2tgl_png_mem_write, NULL);
// write png
png_set_rows (png_ptr, info_ptr, rows);
png_write_png (png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
// cleanup
free(rows);
png_destroy_write_struct (&png_ptr, &info_ptr);
return purple_imgstore_add_with_id (state.buffer, state.size, NULL);
}
#endif /* HAVE_LIBPNG */
#ifdef HAVE_LIBWEBP
static const int MAX_W = 256;
@ -235,7 +321,11 @@ int p2tgl_imgstore_add_with_id_webp (const char *filename) {
}
config.options.use_scaling = 1;
}
#ifdef HAVE_LIBPNG
config.output.colorspace = MODE_RGBA;
#else
config.output.colorspace = MODE_BGRA;
#endif
if (WebPDecode(data, len, &config) != VP8_STATUS_OK) {
warning ("error decoding webp: %s", filename);
g_free ((gchar *)data);
@ -245,7 +335,11 @@ int p2tgl_imgstore_add_with_id_webp (const char *filename) {
const uint8_t *decoded = config.output.u.RGBA.rgba;
// convert and add
#ifdef HAVE_LIBPNG
int imgStoreId = p2tgl_imgstore_add_with_id_png(decoded, config.options.scaled_width, config.options.scaled_height);
#else
int imgStoreId = p2tgl_imgstore_add_with_id_raw(decoded, config.options.scaled_width, config.options.scaled_height);
#endif
WebPFreeDecBuffer (&config.output);
return imgStoreId;
}