gdk: support X11 LSBFirst 4-bpp images

This commit is contained in:
Daemonratte 2026-08-15 14:35:23 +02:00
commit 5d47a3743f

View file

@ -2826,6 +2826,90 @@ gdk_rgb_convert_4_pack (GdkRgbInfo *image_info, GdkImage *image,
}
}
#ifdef GDK_WINDOWING_X11
static void
gdk_rgb_convert_4_pack_lsb (GdkRgbInfo *image_info, GdkImage *image,
gint x0, gint y0, gint width, gint height,
const guchar *buf, int rowstride,
gint x_align, gint y_align,
GdkRgbCmap *cmap)
{
int x, y, ix;
gint bpl;
guchar *obuf, *obptr;
const guchar *bptr, *bp2;
gint r, g, b;
const guchar *dmp;
gint dith;
guchar *colorcube_d = image_info->colorcube_d;
guchar pix0, pix1;
bptr = buf;
bpl = image->bpl;
obuf = ((guchar *)image->mem) + y0 * bpl + (x0 >> 1);
for (y = 0; y < height; y++)
{
dmp = DM[(y_align + y) & (DM_HEIGHT - 1)];
bp2 = bptr;
obptr = obuf;
x = 0;
if (x0 & 1)
{
r = *bp2++;
g = *bp2++;
b = *bp2++;
dith = (dmp[(x_align + x) & (DM_WIDTH - 1)] << 2) | 3;
ix = (((r + dith) & 0x100) >> 2) |
(((g + 258 - dith) & 0x100) >> 5) |
(((b + dith) & 0x100) >> 8);
pix1 = (colorcube_d[ix]);
*obptr = (*obptr & 0x0F) | (pix1 << 4);
obptr++;
x++;
}
while (x + 1 < width)
{
r = *bp2++;
g = *bp2++;
b = *bp2++;
dith = (dmp[(x_align + x) & (DM_WIDTH - 1)] << 2) | 3;
ix = (((r + dith) & 0x100) >> 2) |
(((g + 258 - dith) & 0x100) >> 5) |
(((b + dith) & 0x100) >> 8);
pix0 = (colorcube_d[ix]);
x++;
{
r = *bp2++;
g = *bp2++;
b = *bp2++;
dith = (dmp[(x_align + x) & (DM_WIDTH - 1)] << 2) | 3;
ix = (((r + dith) & 0x100) >> 2) |
(((g + 258 - dith) & 0x100) >> 5) |
(((b + dith) & 0x100) >> 8);
pix1 = (colorcube_d[ix]);
x++;
}
*obptr++ = (pix1 << 4) | pix0;
}
if (x < width)
{
r = *bp2++;
g = *bp2++;
b = *bp2++;
dith = (dmp[(x_align + x) & (DM_WIDTH - 1)] << 2) | 3;
ix = (((r + dith) & 0x100) >> 2) |
(((g + 258 - dith) & 0x100) >> 5) |
(((b + dith) & 0x100) >> 8);
pix0 = (colorcube_d[ix]);
*obptr = (*obptr & 0xF0) | pix0;
}
bptr += rowstride;
obuf += bpl;
}
}
#endif /* GDK_WINDOWING_X11 */
/* This actually works for depths from 3 to 7 */
static void
gdk_rgb_convert_gray4 (GdkRgbInfo *image_info, GdkImage *image,
@ -2874,7 +2958,7 @@ gdk_rgb_convert_gray4_pack (GdkRgbInfo *image_info, GdkImage *image,
gint r, g, b;
gint shift;
guchar pix0, pix1;
/* todo: this is hardcoded to big-endian. Make endian-agile. */
/* Pixel 0 is stored in the high nibble. */
bptr = buf;
bpl = image->bpl;
@ -2920,6 +3004,67 @@ gdk_rgb_convert_gray4_pack (GdkRgbInfo *image_info, GdkImage *image,
}
}
#ifdef GDK_WINDOWING_X11
static void
gdk_rgb_convert_gray4_pack_lsb (GdkRgbInfo *image_info, GdkImage *image,
gint x0, gint y0, gint width, gint height,
const guchar *buf, int rowstride,
gint x_align, gint y_align, GdkRgbCmap *cmap)
{
int x, y;
gint bpl;
guchar *obuf, *obptr;
const guchar *bptr, *bp2;
gint r, g, b;
gint shift;
guchar pix0, pix1;
/* X11 LSBFirst stores pixel 0 in the low nibble. */
bptr = buf;
bpl = image->bpl;
obuf = ((guchar *)image->mem) + y0 * bpl + (x0 >> 1);
shift = 9 - image_info->visual->depth;
for (y = 0; y < height; y++)
{
bp2 = bptr;
obptr = obuf;
x = 0;
if (x0 & 1)
{
r = *bp2++;
g = *bp2++;
b = *bp2++;
pix1 = (g + ((b + r) >> 1)) >> shift;
*obptr = (*obptr & 0x0F) | (pix1 << 4);
obptr++;
x++;
}
while (x < width)
{
r = *bp2++;
g = *bp2++;
b = *bp2++;
pix0 = (g + ((b + r) >> 1)) >> shift;
x++;
if (x == width)
pix1 = (*obptr & 0xF0) >> 4;
else
{
r = *bp2++;
g = *bp2++;
b = *bp2++;
pix1 = (g + ((b + r) >> 1)) >> shift;
x++;
}
*obptr++ = (pix1 << 4) | pix0;
}
bptr += rowstride;
obuf += bpl;
}
}
#endif /* GDK_WINDOWING_X11 */
/* This actually works for depths from 3 to 7 */
static void
gdk_rgb_convert_gray4_d (GdkRgbInfo *image_info, GdkImage *image,
@ -2976,7 +3121,7 @@ gdk_rgb_convert_gray4_d_pack (GdkRgbInfo *image_info, GdkImage *image,
gint prec, right;
gint gray;
guchar pix0, pix1;
/* todo: this is hardcoded to big-endian. Make endian-agile. */
/* Pixel 0 is stored in the high nibble. */
bptr = buf;
bpl = image->bpl;
@ -3030,6 +3175,77 @@ gdk_rgb_convert_gray4_d_pack (GdkRgbInfo *image_info, GdkImage *image,
}
}
#ifdef GDK_WINDOWING_X11
static void
gdk_rgb_convert_gray4_d_pack_lsb (GdkRgbInfo *image_info, GdkImage *image,
gint x0, gint y0, gint width, gint height,
const guchar *buf, int rowstride,
gint x_align, gint y_align, GdkRgbCmap *cmap)
{
int x, y;
gint bpl;
guchar *obuf, *obptr;
const guchar *bptr, *bp2;
gint r, g, b;
const guchar *dmp;
gint prec, right;
gint gray;
guchar pix0, pix1;
/* X11 LSBFirst stores pixel 0 in the low nibble. */
bptr = buf;
bpl = image->bpl;
obuf = ((guchar *)image->mem) + y0 * bpl + (x0 >> 1);
prec = image_info->visual->depth;
right = 8 - prec;
for (y = 0; y < height; y++)
{
bp2 = bptr;
obptr = obuf;
dmp = DM[(y_align + y) & (DM_HEIGHT - 1)];
x = 0;
if (x0 & 1)
{
r = *bp2++;
g = *bp2++;
b = *bp2++;
gray = (g + ((b + r) >> 1)) >> 1;
gray += (dmp[(x_align + x) & (DM_WIDTH - 1)] << 2) >> prec;
pix1 = (gray - (gray >> prec)) >> right;
*obptr = (*obptr & 0x0F) | (pix1 << 4);
obptr++;
x++;
}
while (x < width)
{
r = *bp2++;
g = *bp2++;
b = *bp2++;
gray = (g + ((b + r) >> 1)) >> 1;
gray += (dmp[(x_align + x) & (DM_WIDTH - 1)] << 2) >> prec;
pix0 = (gray - (gray >> prec)) >> right;
x++;
if (x == width)
pix1 = (*obptr & 0xF0) >> 4;
else
{
r = *bp2++;
g = *bp2++;
b = *bp2++;
gray = (g + ((b + r) >> 1)) >> 1;
gray += (dmp[(x_align + x) & (DM_WIDTH - 1)] << 2) >> prec;
pix1 = (gray - (gray >> prec)) >> right;
x++;
}
*obptr++ = (pix1 << 4) | pix0;
}
bptr += rowstride;
obuf += bpl;
}
}
#endif /* GDK_WINDOWING_X11 */
static void
gdk_rgb_convert_1 (GdkRgbInfo *image_info, GdkImage *image,
gint x0, gint y0, gint width, gint height,
@ -3512,16 +3728,42 @@ gdk_rgb_select_conv (GdkRgbInfo *image_info)
{
conv = gdk_rgb_convert_4;
}
#ifdef GDK_WINDOWING_X11
else if (bpp == 4 && depth <= 4 && depth >= 2 &&
(vtype == GDK_VISUAL_STATIC_GRAY
|| vtype == GDK_VISUAL_GRAYSCALE))
(vtype == GDK_VISUAL_STATIC_GRAY
|| vtype == GDK_VISUAL_GRAYSCALE))
{
if (byte_order == GDK_LSB_FIRST)
{
conv = gdk_rgb_convert_gray4_pack_lsb;
conv_d = gdk_rgb_convert_gray4_d_pack_lsb;
}
else
{
conv = gdk_rgb_convert_gray4_pack;
conv_d = gdk_rgb_convert_gray4_d_pack;
}
}
#else
else if (bpp == 4 && depth <= 4 && depth >= 2 &&
(vtype == GDK_VISUAL_STATIC_GRAY
|| vtype == GDK_VISUAL_GRAYSCALE))
{
conv = gdk_rgb_convert_gray4_pack;
conv_d = gdk_rgb_convert_gray4_d_pack;
}
#endif
#ifdef GDK_WINDOWING_X11
else if (bpp == 4 && depth <= 4 && depth >= 2 &&
vtype == GDK_VISUAL_STATIC_COLOR)
vtype == GDK_VISUAL_STATIC_COLOR)
conv = (byte_order == GDK_LSB_FIRST
? gdk_rgb_convert_4_pack_lsb
: gdk_rgb_convert_4_pack);
#else
else if (bpp == 4 && depth <= 4 && depth >= 2 &&
vtype == GDK_VISUAL_STATIC_COLOR)
conv = gdk_rgb_convert_4_pack;
#endif
if (!conv)
g_error ("Visual type=%d depth=%d, image bpp=%d, %s first\n"