forked from AuroraMiddleware/gtk
png: Refactor png saving
Do all the memory format shenanigans in GTK now and support all the PNG formats.
This commit is contained in:
parent
1e7fb52b21
commit
c2368cc605
@ -127,85 +127,6 @@ png_simple_warning_callback (png_structp png,
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/* }}} */
|
|
||||||
/* {{{ Format conversion */
|
|
||||||
|
|
||||||
static void
|
|
||||||
unpremultiply (guchar *data,
|
|
||||||
int width,
|
|
||||||
int height)
|
|
||||||
{
|
|
||||||
gsize x, y;
|
|
||||||
|
|
||||||
for (y = 0; y < height; y++)
|
|
||||||
{
|
|
||||||
for (x = 0; x < width; x++)
|
|
||||||
{
|
|
||||||
guchar *b = &data[x * 4];
|
|
||||||
guint32 pixel;
|
|
||||||
guchar alpha;
|
|
||||||
|
|
||||||
memcpy (&pixel, b, sizeof (guint32));
|
|
||||||
alpha = (pixel & 0xff000000) >> 24;
|
|
||||||
if (alpha == 0)
|
|
||||||
{
|
|
||||||
b[0] = 0;
|
|
||||||
b[1] = 0;
|
|
||||||
b[2] = 0;
|
|
||||||
b[3] = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
b[0] = (((pixel & 0x00ff0000) >> 16) * 255 + alpha / 2) / alpha;
|
|
||||||
b[1] = (((pixel & 0x0000ff00) >> 8) * 255 + alpha / 2) / alpha;
|
|
||||||
b[2] = (((pixel & 0x000000ff) >> 0) * 255 + alpha / 2) / alpha;
|
|
||||||
b[3] = alpha;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
data += width * 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
unpremultiply_float_to_16bit (guchar *data,
|
|
||||||
int width,
|
|
||||||
int height)
|
|
||||||
{
|
|
||||||
gsize x, y;
|
|
||||||
float *src = (float *)data;;
|
|
||||||
guint16 *dest = (guint16 *)data;
|
|
||||||
|
|
||||||
for (y = 0; y < height; y++)
|
|
||||||
{
|
|
||||||
for (x = 0; x < width; x++)
|
|
||||||
{
|
|
||||||
float r, g, b, a;
|
|
||||||
|
|
||||||
r = src[0];
|
|
||||||
g = src[1];
|
|
||||||
b = src[2];
|
|
||||||
a = src[3];
|
|
||||||
if (a == 0)
|
|
||||||
{
|
|
||||||
dest[0] = 0;
|
|
||||||
dest[1] = 0;
|
|
||||||
dest[2] = 0;
|
|
||||||
dest[3] = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dest[0] = (guint16) CLAMP (65536.f * r / a, 0.f, 65535.f);
|
|
||||||
dest[1] = (guint16) CLAMP (65536.f * g / a, 0.f, 65535.f);
|
|
||||||
dest[2] = (guint16) CLAMP (65536.f * b / a, 0.f, 65535.f);
|
|
||||||
dest[3] = (guint16) CLAMP (65536.f * a, 0.f, 65535.f);
|
|
||||||
}
|
|
||||||
|
|
||||||
dest += 4;
|
|
||||||
src += 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* }}} */
|
/* }}} */
|
||||||
/* {{{ Public API */
|
/* {{{ Public API */
|
||||||
|
|
||||||
@ -382,11 +303,11 @@ gdk_save_png (GdkTexture *texture)
|
|||||||
png_struct *png = NULL;
|
png_struct *png = NULL;
|
||||||
png_info *info;
|
png_info *info;
|
||||||
png_io io = { NULL, 0, 0 };
|
png_io io = { NULL, 0, 0 };
|
||||||
guint width, height, stride;
|
int width, height;
|
||||||
guchar *data = NULL;
|
gsize stride;
|
||||||
guchar *row;
|
const guchar *data;
|
||||||
int y;
|
int y;
|
||||||
GdkTexture *mtexture;
|
GdkMemoryTexture *memtex;
|
||||||
GdkMemoryFormat format;
|
GdkMemoryFormat format;
|
||||||
int png_format;
|
int png_format;
|
||||||
int depth;
|
int depth;
|
||||||
@ -395,8 +316,6 @@ gdk_save_png (GdkTexture *texture)
|
|||||||
height = gdk_texture_get_height (texture);
|
height = gdk_texture_get_height (texture);
|
||||||
format = gdk_texture_get_format (texture);
|
format = gdk_texture_get_format (texture);
|
||||||
|
|
||||||
mtexture = GDK_TEXTURE (gdk_memory_texture_from_texture (texture, format));
|
|
||||||
|
|
||||||
switch (format)
|
switch (format)
|
||||||
{
|
{
|
||||||
case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
|
case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
|
||||||
@ -406,32 +325,42 @@ gdk_save_png (GdkTexture *texture)
|
|||||||
case GDK_MEMORY_A8R8G8B8:
|
case GDK_MEMORY_A8R8G8B8:
|
||||||
case GDK_MEMORY_R8G8B8A8:
|
case GDK_MEMORY_R8G8B8A8:
|
||||||
case GDK_MEMORY_A8B8G8R8:
|
case GDK_MEMORY_A8B8G8R8:
|
||||||
case GDK_MEMORY_R8G8B8:
|
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||||
case GDK_MEMORY_B8G8R8:
|
format = GDK_MEMORY_R8G8B8A8;
|
||||||
stride = width * 4;
|
#elif G_BYTE_ORDER == G_BIG_ENDIAN
|
||||||
data = g_malloc_n (stride, height);
|
format = GDK_MEMORY_A8B8G8R8;
|
||||||
gdk_texture_download (mtexture, data, stride);
|
#endif
|
||||||
unpremultiply (data, width, height);
|
|
||||||
|
|
||||||
png_format = PNG_COLOR_TYPE_RGB_ALPHA;
|
png_format = PNG_COLOR_TYPE_RGB_ALPHA;
|
||||||
depth = 8;
|
depth = 8;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GDK_MEMORY_R16G16B16:
|
case GDK_MEMORY_R8G8B8:
|
||||||
|
case GDK_MEMORY_B8G8R8:
|
||||||
|
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||||
|
format = GDK_MEMORY_R8G8B8;
|
||||||
|
#elif G_BYTE_ORDER == G_BIG_ENDIAN
|
||||||
|
format = GDK_MEMORY_B8G8R8;
|
||||||
|
#endif
|
||||||
|
png_format = PNG_COLOR_TYPE_RGB;
|
||||||
|
depth = 8;
|
||||||
|
break;
|
||||||
|
|
||||||
case GDK_MEMORY_R16G16B16A16:
|
case GDK_MEMORY_R16G16B16A16:
|
||||||
case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
|
case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
|
||||||
case GDK_MEMORY_R16G16B16_FLOAT:
|
|
||||||
case GDK_MEMORY_R16G16B16A16_FLOAT:
|
case GDK_MEMORY_R16G16B16A16_FLOAT:
|
||||||
case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
|
case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
|
||||||
case GDK_MEMORY_R32G32B32_FLOAT:
|
|
||||||
case GDK_MEMORY_R32G32B32A32_FLOAT:
|
case GDK_MEMORY_R32G32B32A32_FLOAT:
|
||||||
case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
|
case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
|
||||||
data = g_malloc_n (width * 16, height);
|
format = GDK_MEMORY_R16G16B16A16;
|
||||||
gdk_texture_download_float (mtexture, (float *)data, width * 4);
|
|
||||||
unpremultiply_float_to_16bit (data, width, height);
|
|
||||||
|
|
||||||
png_format = PNG_COLOR_TYPE_RGB_ALPHA;
|
png_format = PNG_COLOR_TYPE_RGB_ALPHA;
|
||||||
stride = width * 8;
|
depth = 16;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GDK_MEMORY_R16G16B16:
|
||||||
|
case GDK_MEMORY_R16G16B16_FLOAT:
|
||||||
|
case GDK_MEMORY_R32G32B32_FLOAT:
|
||||||
|
format = GDK_MEMORY_R16G16B16;
|
||||||
|
png_format = PNG_COLOR_TYPE_RGB;
|
||||||
depth = 16;
|
depth = 16;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -458,12 +387,14 @@ gdk_save_png (GdkTexture *texture)
|
|||||||
|
|
||||||
if (sigsetjmp (png_jmpbuf (png), 1))
|
if (sigsetjmp (png_jmpbuf (png), 1))
|
||||||
{
|
{
|
||||||
g_free (data);
|
g_object_unref (memtex);
|
||||||
g_free (io.data);
|
g_free (io.data);
|
||||||
png_destroy_read_struct (&png, &info, NULL);
|
png_destroy_read_struct (&png, &info, NULL);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memtex = gdk_memory_texture_from_texture (texture, format);
|
||||||
|
|
||||||
png_set_write_fn (png, &io, png_write_func, png_flush_func);
|
png_set_write_fn (png, &io, png_write_func, png_flush_func);
|
||||||
|
|
||||||
png_set_IHDR (png, info, width, height, depth,
|
png_set_IHDR (png, info, width, height, depth,
|
||||||
@ -478,14 +409,16 @@ gdk_save_png (GdkTexture *texture)
|
|||||||
png_set_swap (png);
|
png_set_swap (png);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (y = 0, row = data; y < height; y++, row += stride)
|
data = gdk_memory_texture_get_data (memtex);
|
||||||
png_write_rows (png, &row, 1);
|
stride = gdk_memory_texture_get_stride (memtex);
|
||||||
|
for (y = 0; y < height; y++)
|
||||||
|
png_write_row (png, data + y * stride);
|
||||||
|
|
||||||
png_write_end (png, info);
|
png_write_end (png, info);
|
||||||
|
|
||||||
png_destroy_write_struct (&png, &info);
|
png_destroy_write_struct (&png, &info);
|
||||||
|
|
||||||
g_free (data);
|
g_object_unref (memtex);
|
||||||
|
|
||||||
return g_bytes_new_take (io.data, io.size);
|
return g_bytes_new_take (io.data, io.size);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user