gdk: Add grayscale and alpha memory formats

This commit is contained in:
Sophie Herold
2023-05-26 14:38:25 +02:00
committed by Matthias Clasen
parent 3dc3d03a08
commit 50115d70c6
3 changed files with 250 additions and 18 deletions

View File

@@ -30,6 +30,8 @@
#include <glib.h>
#include <gdk/version/gdkversionmacros.h>
G_BEGIN_DECLS
/**
@@ -306,6 +308,20 @@ typedef enum
* the alpha value. Since: 4.6
* @GDK_MEMORY_R32G32B32A32_FLOAT: 4 float values; for red, green, blue and
* alpha. Since: 4.6
* @GDK_MEMORY_G8A8_PREMULTIPLIED: 2 bytes; for grayscale, alpha. The color
* values are premultiplied with the alpha value. Since: 4.12
* @GDK_MEMORY_G8A8: 2 bytes; for grayscale, alpha. Since: 4.12
* @GDK_MEMORY_G8: One byte; for grayscale. The data is opaque.
* Since: 4.12
* @GDK_MEMORY_G16A16_PREMULTIPLIED: 2 guint16 values; for grayscale, alpha.
* The color values are premultiplied with the alpha value. Since: 4.12
* @GDK_MEMORY_G16A16: 2 guint16 values; for grayscale, alpha. Since: 4.12
* @GDK_MEMORY_G16: One guint16 value; for grayscale. The data is opaque.
* Since: 4.12
* @GDK_MEMORY_A8: One byte; for alpha.
* Since: 4.12
* @GDK_MEMORY_A16: One guint16 value; for alpha.
* Since: 4.12
* @GDK_MEMORY_N_FORMATS: The number of formats. This value will change as
* more formats get added, so do not rely on its concrete integer.
*
@@ -340,6 +356,14 @@ typedef enum {
GDK_MEMORY_R32G32B32_FLOAT,
GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED,
GDK_MEMORY_R32G32B32A32_FLOAT,
GDK_MEMORY_G8A8_PREMULTIPLIED GDK_AVAILABLE_ENUMERATOR_IN_4_12,
GDK_MEMORY_G8A8 GDK_AVAILABLE_ENUMERATOR_IN_4_12,
GDK_MEMORY_G8 GDK_AVAILABLE_ENUMERATOR_IN_4_12,
GDK_MEMORY_G16A16_PREMULTIPLIED GDK_AVAILABLE_ENUMERATOR_IN_4_12,
GDK_MEMORY_G16A16 GDK_AVAILABLE_ENUMERATOR_IN_4_12,
GDK_MEMORY_G16 GDK_AVAILABLE_ENUMERATOR_IN_4_12,
GDK_MEMORY_A8 GDK_AVAILABLE_ENUMERATOR_IN_4_12,
GDK_MEMORY_A16 GDK_AVAILABLE_ENUMERATOR_IN_4_12,
GDK_MEMORY_N_FORMATS
} GdkMemoryFormat;

View File

@@ -60,6 +60,36 @@ name ## _from_float (guchar *dest_data, \
} \
}
#define TYPED_GRAY_FUNCS(name, T, G, A, bpp, scale) \
static void \
name ## _to_float (float *dest, \
const guchar *src_data, \
gsize n) \
{ \
for (gsize i = 0; i < n; i++) \
{ \
T *src = (T *) (src_data + i * bpp); \
if (G >= 0) dest[0] = (float) src[G] / scale; else dest[0] = 1.0; \
dest[1] = dest[2] = dest[0]; \
if (A >= 0) dest[3] = (float) src[A] / scale; else dest[3] = 1.0; \
dest += 4; \
} \
} \
\
static void \
name ## _from_float (guchar *dest_data, \
const float *src, \
gsize n) \
{ \
for (gsize i = 0; i < n; i++) \
{ \
T *dest = (T *) (dest_data + i * bpp); \
if (G >= 0) dest[G] = CLAMP ((src[0] + src[1] + src[2]) * scale / 3.f + 0.5, 0, scale); \
if (A >= 0) dest[A] = CLAMP (src[3] * scale + 0.5, 0, scale); \
src += 4; \
} \
}
TYPED_FUNCS (b8g8r8a8_premultiplied, guchar, 2, 1, 0, 3, 4, 255)
TYPED_FUNCS (a8r8g8b8_premultiplied, guchar, 1, 2, 3, 0, 4, 255)
TYPED_FUNCS (r8g8b8a8_premultiplied, guchar, 0, 1, 2, 3, 4, 255)
@@ -72,6 +102,15 @@ TYPED_FUNCS (b8g8r8, guchar, 2, 1, 0, -1, 3, 255)
TYPED_FUNCS (r16g16b16, guint16, 0, 1, 2, -1, 6, 65535)
TYPED_FUNCS (r16g16b16a16, guint16, 0, 1, 2, 3, 8, 65535)
TYPED_GRAY_FUNCS (g8a8_premultiplied, guchar, 0, 1, 2, 255)
TYPED_GRAY_FUNCS (g8a8, guchar, 0, 1, 2, 255)
TYPED_GRAY_FUNCS (g8, guchar, 0, -1, 1, 255)
TYPED_GRAY_FUNCS (a8, guchar, -1, 0, 1, 255)
TYPED_GRAY_FUNCS (g16a16_premultiplied, guint16, 0, 1, 4, 65535)
TYPED_GRAY_FUNCS (g16a16, guint16, 0, 1, 4, 65535)
TYPED_GRAY_FUNCS (g16, guint16, 0, -1, 2, 65535)
TYPED_GRAY_FUNCS (a16, guint16, -1, 0, 2, 65535)
static void
r16g16b16_float_to_float (float *dest,
const guchar *src_data,
@@ -230,6 +269,7 @@ struct _GdkMemoryFormatDescription
guint internal_format;
guint format;
guint type;
GLint swizzle[4];
} gl;
/* no premultiplication going on here */
void (* to_float) (float *, const guchar*, gsize);
@@ -251,7 +291,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = {
G_ALIGNOF (guchar),
FALSE,
{ 0, 0, G_MAXUINT, G_MAXUINT },
{ GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE },
{ GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
b8g8r8a8_premultiplied_to_float,
b8g8r8a8_premultiplied_from_float,
},
@@ -261,7 +301,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = {
G_ALIGNOF (guchar),
FALSE,
{ 0, 0, G_MAXUINT, G_MAXUINT },
{ GL_RGBA8, GL_BGRA, GDK_GL_UNSIGNED_BYTE_FLIPPED },
{ GL_RGBA8, GL_BGRA, GDK_GL_UNSIGNED_BYTE_FLIPPED, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
a8r8g8b8_premultiplied_to_float,
a8r8g8b8_premultiplied_from_float,
},
@@ -271,7 +311,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = {
G_ALIGNOF (guchar),
FALSE,
{ 0, 0, 0, 0 },
{ GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE },
{ GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
r8g8b8a8_premultiplied_to_float,
r8g8b8a8_premultiplied_from_float,
},
@@ -281,7 +321,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = {
G_ALIGNOF (guchar),
FALSE,
{ 0, 0, G_MAXUINT, G_MAXUINT },
{ GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE },
{ GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
b8g8r8a8_to_float,
b8g8r8a8_from_float,
},
@@ -291,7 +331,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = {
G_ALIGNOF (guchar),
FALSE,
{ 0, 0, G_MAXUINT, G_MAXUINT },
{ GL_RGBA8, GL_RGBA, GDK_GL_UNSIGNED_BYTE_FLIPPED },
{ GL_RGBA8, GL_RGBA, GDK_GL_UNSIGNED_BYTE_FLIPPED, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
a8r8g8b8_to_float,
a8r8g8b8_from_float,
},
@@ -301,7 +341,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = {
G_ALIGNOF (guchar),
FALSE,
{ 0, 0, 0, 0 },
{ GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE },
{ GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
r8g8b8a8_to_float,
r8g8b8a8_from_float,
},
@@ -311,7 +351,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = {
G_ALIGNOF (guchar),
FALSE,
{ 0, 0, G_MAXUINT, G_MAXUINT },
{ GL_RGBA8, GL_BGRA, GDK_GL_UNSIGNED_BYTE_FLIPPED },
{ GL_RGBA8, GL_BGRA, GDK_GL_UNSIGNED_BYTE_FLIPPED, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
a8b8g8r8_to_float,
a8b8g8r8_from_float,
},
@@ -321,7 +361,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = {
G_ALIGNOF (guchar),
FALSE,
{ 0, 0, 0, 0 },
{ GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE },
{ GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, { GL_RED, GL_GREEN, GL_BLUE, GL_ONE } },
r8g8b8_to_float,
r8g8b8_from_float,
},
@@ -331,7 +371,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = {
G_ALIGNOF (guchar),
FALSE,
{ 0, 0, G_MAXUINT, G_MAXUINT },
{ GL_RGB8, GL_BGR, GL_UNSIGNED_BYTE },
{ GL_RGB8, GL_BGR, GL_UNSIGNED_BYTE, { GL_RED, GL_GREEN, GL_BLUE, GL_ONE } },
b8g8r8_to_float,
b8g8r8_from_float,
},
@@ -341,7 +381,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = {
G_ALIGNOF (guint16),
TRUE,
{ 0, 0, 3, 0 },
{ GL_RGB16, GL_RGB, GL_UNSIGNED_SHORT },
{ GL_RGB16, GL_RGB, GL_UNSIGNED_SHORT, { GL_RED, GL_GREEN, GL_BLUE, GL_ONE } },
r16g16b16_to_float,
r16g16b16_from_float,
},
@@ -351,7 +391,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = {
G_ALIGNOF (guint16),
TRUE,
{ 0, 0, 3, 0 },
{ GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT },
{ GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
r16g16b16a16_to_float,
r16g16b16a16_from_float,
},
@@ -361,7 +401,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = {
G_ALIGNOF (guint16),
TRUE,
{ 0, 0, 3, 0 },
{ GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT },
{ GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
r16g16b16a16_to_float,
r16g16b16a16_from_float,
},
@@ -371,7 +411,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = {
G_ALIGNOF (guint16),
TRUE,
{ 0, 0, 3, 0 },
{ GL_RGB16F, GL_RGB, GL_HALF_FLOAT },
{ GL_RGB16F, GL_RGB, GL_HALF_FLOAT, { GL_RED, GL_GREEN, GL_BLUE, GL_ONE } },
r16g16b16_float_to_float,
r16g16b16_float_from_float,
},
@@ -381,7 +421,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = {
G_ALIGNOF (guint16),
TRUE,
{ 0, 0, 3, 0 },
{ GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT },
{ GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
r16g16b16a16_float_to_float,
r16g16b16a16_float_from_float,
},
@@ -391,7 +431,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = {
G_ALIGNOF (guint16),
TRUE,
{ 0, 0, 3, 0 },
{ GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT },
{ GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
r16g16b16a16_float_to_float,
r16g16b16a16_float_from_float,
},
@@ -401,7 +441,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = {
G_ALIGNOF (float),
TRUE,
{ 0, 0, 3, 0 },
{ GL_RGB32F, GL_RGB, GL_FLOAT },
{ GL_RGB32F, GL_RGB, GL_FLOAT, { GL_RED, GL_GREEN, GL_BLUE, GL_ONE } },
r32g32b32_float_to_float,
r32g32b32_float_from_float,
},
@@ -411,7 +451,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = {
G_ALIGNOF (float),
TRUE,
{ 0, 0, 3, 0 },
{ GL_RGBA32F, GL_RGBA, GL_FLOAT },
{ GL_RGBA32F, GL_RGBA, GL_FLOAT, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
r32g32b32a32_float_to_float,
r32g32b32a32_float_from_float,
},
@@ -421,9 +461,89 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = {
G_ALIGNOF (float),
TRUE,
{ 0, 0, 3, 0 },
{ GL_RGBA32F, GL_RGBA, GL_FLOAT },
{ GL_RGBA32F, GL_RGBA, GL_FLOAT, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
r32g32b32a32_float_to_float,
r32g32b32a32_float_from_float,
},
[GDK_MEMORY_G8A8_PREMULTIPLIED] = {
GDK_MEMORY_ALPHA_PREMULTIPLIED,
2,
G_ALIGNOF (guchar),
FALSE,
{ 0, 0, 3, 0 },
{ GL_RG8, GL_RG, GL_UNSIGNED_BYTE, { GL_RED, GL_RED, GL_RED, GL_GREEN } },
g8a8_premultiplied_to_float,
g8a8_premultiplied_from_float,
},
[GDK_MEMORY_G8A8] = {
GDK_MEMORY_ALPHA_STRAIGHT,
2,
G_ALIGNOF (guchar),
FALSE,
{ 0, 0, 3, 0 },
{ GL_RG8, GL_RG, GL_UNSIGNED_BYTE, { GL_RED, GL_RED, GL_RED, GL_GREEN } },
g8a8_to_float,
g8a8_from_float,
},
[GDK_MEMORY_G8] = {
GDK_MEMORY_ALPHA_OPAQUE,
1,
G_ALIGNOF (guchar),
FALSE,
{ 0, 0, 3, 0 },
{ GL_R8, GL_RED, GL_UNSIGNED_BYTE, { GL_RED, GL_RED, GL_RED, GL_ONE } },
g8_to_float,
g8_from_float,
},
[GDK_MEMORY_G16A16_PREMULTIPLIED] = {
GDK_MEMORY_ALPHA_PREMULTIPLIED,
4,
G_ALIGNOF (guint16),
TRUE,
{ 0, 0, 3, 0 },
{ GL_RG16, GL_RG, GL_UNSIGNED_SHORT, { GL_RED, GL_RED, GL_RED, GL_GREEN } },
g16a16_premultiplied_to_float,
g16a16_premultiplied_from_float,
},
[GDK_MEMORY_G16A16] = {
GDK_MEMORY_ALPHA_STRAIGHT,
4,
G_ALIGNOF (guint16),
TRUE,
{ 0, 0, 3, 0 },
{ GL_RG16, GL_RG, GL_UNSIGNED_SHORT, { GL_RED, GL_RED, GL_RED, GL_GREEN } },
g16a16_to_float,
g16a16_from_float,
},
[GDK_MEMORY_G16] = {
GDK_MEMORY_ALPHA_OPAQUE,
2,
G_ALIGNOF (guint16),
TRUE,
{ 0, 0, 3, 0 },
{ GL_R16, GL_RED, GL_UNSIGNED_SHORT, { GL_RED, GL_RED, GL_RED, GL_ONE } },
g16_to_float,
g16_from_float,
},
[GDK_MEMORY_A8] = {
GDK_MEMORY_ALPHA_STRAIGHT,
1,
G_ALIGNOF (guchar),
FALSE,
{ 0, 0, 3, 0 },
{ GL_R8, GL_RED, GL_UNSIGNED_BYTE, { GL_ONE, GL_ONE, GL_ONE, GL_RED } },
a8_to_float,
a8_from_float,
},
[GDK_MEMORY_A16] = {
GDK_MEMORY_ALPHA_STRAIGHT,
2,
G_ALIGNOF (guint16),
TRUE,
{ 0, 0, 3, 0 },
{ GL_R16, GL_RED, GL_UNSIGNED_SHORT, { GL_ONE, GL_ONE, GL_ONE, GL_RED } },
a16_to_float,
a16_from_float,
}
};

View File

@@ -75,6 +75,16 @@ gdk_memory_format_bytes_per_pixel (GdkMemoryFormat format)
{
switch (format)
{
case GDK_MEMORY_G8:
case GDK_MEMORY_A8:
return 1;
case GDK_MEMORY_G8A8_PREMULTIPLIED:
case GDK_MEMORY_G8A8:
case GDK_MEMORY_G16:
case GDK_MEMORY_A16:
return 2;
case GDK_MEMORY_R8G8B8:
case GDK_MEMORY_B8G8R8:
return 3;
@@ -86,6 +96,8 @@ gdk_memory_format_bytes_per_pixel (GdkMemoryFormat format)
case GDK_MEMORY_A8R8G8B8:
case GDK_MEMORY_R8G8B8A8:
case GDK_MEMORY_A8B8G8R8:
case GDK_MEMORY_G16A16_PREMULTIPLIED:
case GDK_MEMORY_G16A16:
return 4;
case GDK_MEMORY_R16G16B16:
@@ -218,6 +230,82 @@ gdk_memory_format_is_premultiplied (GdkMemoryFormat format)
}
}
static gboolean
gdk_memory_format_has_alpha (GdkMemoryFormat format)
{
switch (format)
{
case GDK_MEMORY_R8G8B8:
case GDK_MEMORY_B8G8R8:
case GDK_MEMORY_R16G16B16:
case GDK_MEMORY_R16G16B16_FLOAT:
case GDK_MEMORY_R32G32B32_FLOAT:
case GDK_MEMORY_G8:
case GDK_MEMORY_G16:
return FALSE;
case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
case GDK_MEMORY_B8G8R8A8:
case GDK_MEMORY_A8R8G8B8:
case GDK_MEMORY_R8G8B8A8:
case GDK_MEMORY_A8B8G8R8:
case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
case GDK_MEMORY_R16G16B16A16:
case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
case GDK_MEMORY_R16G16B16A16_FLOAT:
case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
case GDK_MEMORY_R32G32B32A32_FLOAT:
case GDK_MEMORY_G8A8_PREMULTIPLIED:
case GDK_MEMORY_G8A8:
case GDK_MEMORY_G16A16_PREMULTIPLIED:
case GDK_MEMORY_G16A16:
case GDK_MEMORY_A8:
case GDK_MEMORY_A16:
return TRUE;
case GDK_MEMORY_N_FORMATS:
default:
g_assert_not_reached ();
return TRUE;
}
}
static gboolean
gdk_memory_format_is_premultiplied (GdkMemoryFormat format)
{
switch (format)
{
case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
return TRUE;
case GDK_MEMORY_R8G8B8:
case GDK_MEMORY_B8G8R8:
case GDK_MEMORY_R16G16B16:
case GDK_MEMORY_R16G16B16_FLOAT:
case GDK_MEMORY_R32G32B32_FLOAT:
case GDK_MEMORY_B8G8R8A8:
case GDK_MEMORY_A8R8G8B8:
case GDK_MEMORY_R8G8B8A8:
case GDK_MEMORY_A8B8G8R8:
case GDK_MEMORY_R16G16B16A16:
case GDK_MEMORY_R16G16B16A16_FLOAT:
case GDK_MEMORY_R32G32B32A32_FLOAT:
return FALSE;
case GDK_MEMORY_N_FORMATS:
default:
g_assert_not_reached ();
return FALSE;
}
}
static gboolean
gdk_memory_format_pixel_equal (GdkMemoryFormat format,
gboolean accurate,