add "new" rawmodes for 16-bit RGB data

The existing 16-bit RGB rawmodes do not follow the naming convention given in Unpack.c. These new modes do follow that convention, except since these modes do not all use the same number of bits for each band, the sizes of each band are listed.

Old → New
RGB;15 → XBGR;1555
RGB;16 → BGR;565
BGR;5 → XRGB;1555
BGR;15 → XRGB;1555
BGR;16 → RGB;565
RGB;4B → XBGR;4
RGBA;4B → ABGR;4
RGBA;15 → ABGR;1555
BGRA;15 → ARGB;1555
BGRA;15Z → ARGB;1555Z

These new rawmodes also use a slightly different conversion method. The most accurate conversion from 5 to 8 bits is "round(x * 255 / 31.0)". However, that involves floating point numbers and rounding, so it's not as fast. The current method doesn't include the rounding, allowing us to also use integer instead of floating point division. This is faster, but unfortunately not roundtrippable - when converting from 5 to 8 to 5 bits not every value stays the same. The new method is roundtrippable, even faster than the current method since it uses basic bitwise operations instead of multiplication and division, and if you compare the result to what you get with rounding and floating point numbers, it is actually more accurate.
This commit is contained in:
Yay295 2024-04-25 21:20:41 -05:00
parent 7d5771e56d
commit 3af0e2d9cf
3 changed files with 248 additions and 4 deletions

View File

@ -63,9 +63,13 @@ def get_pack_parameters() -> UnPackParamTypes:
# Mode RGB
params += [
("RGB", "XRGB;1555", b"\x00\x86\x01\x8c", [(8, 131, 0), (24, 0, 8)]),
("RGB", "RGB;565", b"\x00\n\x00\x1c", [(8, 64, 0), (24, 129, 0)]),
("RGB", "RGB", 3, [(1, 2, 3), (4, 5, 6), (7, 8, 9)]),
("RGB", "RGBX", b"\x01\x02\x03\xff\x05\x06\x07\xff", [(1, 2, 3), (5, 6, 7)]),
("RGB", "XRGB", b"\x00\x02\x03\x04\x00\x06\x07\x08", [(2, 3, 4), (6, 7, 8)]),
("RGB", "XBGR;1555", b"\x00\x86\x01\x8c", [(0, 131, 8), (8, 0, 24)]),
("RGB", "BGR;565", b"\x00\n\x00\x1c", [(0, 64, 8), (0, 129, 24)]),
("RGB", "BGR", 3, [(3, 2, 1), (6, 5, 4), (9, 8, 7)]),
("RGB", "BGRX", b"\x01\x02\x03\x00\x05\x06\x07\x00", [(3, 2, 1), (7, 6, 5)]),
("RGB", "XBGR", b"\x00\x02\x03\x04\x00\x06\x07\x08", [(4, 3, 2), (8, 7, 6)]),
@ -322,10 +326,19 @@ def get_unpack_parameters() -> UnPackParamTypes:
("RGB", "RGB;16B", 6, [(1, 3, 5), (7, 9, 11)]),
("RGB", "BGR", 3, [(3, 2, 1), (6, 5, 4), (9, 8, 7)]),
("RGB", "RGB;15", 2, [(8, 131, 0), (24, 0, 8)]),
("RGB", "XRGB;1555", 2, [(0, 132, 8), (8, 0, 24)]),
("RGB", "ARGB;1555", 2, [(0, 132, 8), (8, 0, 24)]),
("RGB", "ARGB;1555Z", 2, [(0, 132, 8), (8, 0, 24)]),
("RGB", "BGR;15", 2, [(0, 131, 8), (8, 0, 24)]),
("RGB", "XBGR;1555", 2, [(8, 132, 0), (24, 0, 8)]),
("RGB", "ABGR;1555", 2, [(8, 132, 0), (24, 0, 8)]),
("RGB", "RGB;16", 2, [(8, 64, 0), (24, 129, 0)]),
("RGB", "RGB;565", 2, [(0, 65, 8), (0, 130, 24)]),
("RGB", "BGR;16", 2, [(0, 64, 8), (0, 129, 24)]),
("RGB", "BGR;565", 2, [(8, 65, 0), (24, 130, 0)]),
("RGB", "RGB;4B", 2, [(17, 0, 34), (51, 0, 68)]),
("RGB", "XBGR;4", 2, [(17, 0, 34), (51, 0, 68)]),
("RGB", "ABGR;4", 2, [(17, 0, 34), (51, 0, 68)]),
("RGB", "RGBX", 4, [(1, 2, 3), (5, 6, 7), (9, 10, 11)]),
("RGB", "RGBX;L", 4, [(1, 4, 7), (2, 5, 8), (3, 6, 9)]),
("RGB", "BGRX", 4, [(3, 2, 1), (7, 6, 5), (11, 10, 9)]),
@ -481,8 +494,12 @@ def get_unpack_parameters() -> UnPackParamTypes:
),
("RGBA", "RGBA;L", 4, [(1, 4, 7, 10), (2, 5, 8, 11), (3, 6, 9, 12)]),
("RGBA", "RGBA;15", 2, [(8, 131, 0, 0), (24, 0, 8, 0)]),
("RGBA", "ARGB;1555", 2, [(0, 132, 8, 0), (8, 0, 24, 0)]),
("RGBA", "ARGB;1555Z", 2, [(0, 132, 8, X), (8, 0, 24, X)]),
("RGBA", "BGRA;15", 2, [(0, 131, 8, 0), (8, 0, 24, 0)]),
("RGBA", "ABGR;1555", 2, [(8, 132, 0, 0), (24, 0, 8, 0)]),
("RGBA", "RGBA;4B", 2, [(17, 0, 34, 0), (51, 0, 68, 0)]),
("RGBA", "ABGR;4", 2, [(17, 0, 34, 0), (51, 0, 68, 0)]),
("RGBA", "RGBA;16L", 8, [(2, 4, 6, 8), (10, 12, 14, 16)]),
("RGBA", "RGBA;16B", 8, [(1, 3, 5, 7), (9, 11, 13, 15)]),
("RGBA", "BGRA;16L", 8, [(6, 4, 2, 8), (14, 12, 10, 16)]),
@ -545,8 +562,13 @@ def get_unpack_parameters() -> UnPackParamTypes:
("RGBX", "RGB;16B", 6, [(1, 3, 5, X), (7, 9, 11, X)]),
("RGBX", "BGR", 3, [(3, 2, 1, X), (6, 5, 4, X), (9, 8, 7, X)]),
("RGBX", "RGB;15", 2, [(8, 131, 0, X), (24, 0, 8, X)]),
("RGBX", "XRGB;1555", 2, [(0, 132, 8, X), (8, 0, 24, X)]),
("RGBX", "RGB;565", 2, [(0, 65, 8, X), (0, 130, 24, X)]),
("RGBX", "BGR;15", 2, [(0, 131, 8, X), (8, 0, 24, X)]),
("RGBX", "XBGR;1555", 2, [(8, 132, 0, X), (24, 0, 8, X)]),
("RGBX", "BGR;565", 2, [(8, 65, 0, X), (24, 130, 0, X)]),
("RGBX", "RGB;4B", 2, [(17, 0, 34, X), (51, 0, 68, X)]),
("RGBX", "XBGR;4", 2, [(17, 0, 34, X), (51, 0, 68, X)]),
("RGBX", "RGBX", 4, [(1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12)]),
("RGBX", "RGBXX", 5, [(1, 2, 3, 4), (6, 7, 8, 9), (11, 12, 13, 14)]),
("RGBX", "RGBXXX", 6, [(1, 2, 3, 4), (7, 8, 9, 10), (13, 14, 15, 16)]),

View File

@ -254,6 +254,30 @@ packLAL(UINT8 *out, const UINT8 *in, int pixels) {
}
}
static void
ImagingPackXRGB1555(UINT8 *out, const UINT8 *in, int pixels) {
for (int i = 0; i < pixels; out += 2, in += 4, i++) {
/* XRGB, 1/5/5/5 bits per pixel, little-endian */
const UINT8 r = in[0] >> 3;
const UINT8 g = in[1] >> 3;
const UINT8 b = in[2] >> 3;
out[1] = 0x80 | (r << 2) | (g >> 3);
out[0] = (g << 5) | b;
}
}
static void
ImagingPackRGB565(UINT8 *out, const UINT8 *in, int pixels) {
for (int i = 0; i < pixels; out += 2, in += 4, i++) {
/* RGB, 5/6/5 bits per pixel, little-endian */
const UINT8 r = in[0] >> 3;
const UINT8 g = in[1] >> 2;
const UINT8 b = in[2] >> 3;
out[1] = (r << 3) | (g >> 3);
out[0] = (g << 5) | b;
}
}
void
ImagingPackRGB(UINT8 *out, const UINT8 *in, int pixels) {
int i = 0;
@ -284,6 +308,30 @@ ImagingPackXRGB(UINT8 *out, const UINT8 *in, int pixels) {
}
}
static void
ImagingPackXBGR1555(UINT8 *out, const UINT8 *in, int pixels) {
for (int i = 0; i < pixels; out += 2, in += 4, i++) {
/* XBGR, 1/5/5/5 bits per pixel, little-endian */
const UINT8 r = in[0] >> 3;
const UINT8 g = in[1] >> 3;
const UINT8 b = in[2] >> 3;
out[1] = 0x80 | (b << 2) | (g >> 3);
out[0] = (g << 5) | r;
}
}
static void
ImagingPackBGR565(UINT8 *out, const UINT8 *in, int pixels) {
for (int i = 0; i < pixels; out += 2, in += 4, i++) {
/* BGR, 5/6/5 bits per pixel, little-endian */
const UINT8 r = in[0] >> 3;
const UINT8 g = in[1] >> 2;
const UINT8 b = in[2] >> 3;
out[1] = (b << 3) | (g >> 3);
out[0] = (g << 5) | r;
}
}
void
ImagingPackBGR(UINT8 *out, const UINT8 *in, int pixels) {
int i;
@ -561,10 +609,14 @@ static struct {
{"PA", "PA;L", 16, packLAL},
/* true colour */
{"RGB", "XRGB;1555", 16, ImagingPackXRGB1555},
{"RGB", "RGB;565", 16, ImagingPackRGB565},
{"RGB", "RGB", 24, ImagingPackRGB},
{"RGB", "RGBX", 32, copy4},
{"RGB", "RGBA", 32, copy4},
{"RGB", "XRGB", 32, ImagingPackXRGB},
{"RGB", "XBGR;1555", 16, ImagingPackXBGR1555},
{"RGB", "BGR;565", 16, ImagingPackBGR565},
{"RGB", "BGR", 24, ImagingPackBGR},
{"RGB", "BGRX", 32, ImagingPackBGRX},
{"RGB", "XBGR", 32, ImagingPackXBGR},

View File

@ -764,10 +764,129 @@ ImagingUnpackBGR16(UINT8 *out, const UINT8 *in, int pixels) {
}
}
static void
ImagingUnpackXRGB1555(UINT8 *out, const UINT8 *in, const int pixels) {
/* XRGB, 1/5/5/5 bits per pixel, little-endian */
for (int i = 0; i < pixels; i++) {
const UINT16 pixel = ((UINT16)in[1] << 8) | in[0];
const UINT8 r = (pixel >> 10) & 31;
const UINT8 g = (pixel >> 5) & 31;
const UINT8 b = pixel & 31;
out[R] = (r << 3) | (r >> 2);
out[G] = (g << 3) | (g >> 2);
out[B] = (b << 3) | (b >> 2);
out[A] = 255;
out += 4;
in += 2;
}
}
static void
ImagingUnpackARGB1555(UINT8 *out, const UINT8 *in, const int pixels) {
/* ARGB, 1/5/5/5 bits per pixel, little-endian */
for (int i = 0; i < pixels; i++) {
const UINT16 pixel = ((UINT16)in[1] << 8) | in[0];
const UINT8 r = (pixel >> 10) & 31;
const UINT8 g = (pixel >> 5) & 31;
const UINT8 b = pixel & 31;
out[R] = (r << 3) | (r >> 2);
out[G] = (g << 3) | (g >> 2);
out[B] = (b << 3) | (b >> 2);
out[A] = (pixel >> 15) * 255;
out += 4;
in += 2;
}
}
static void
ImagingUnpackARGB1555Z(UINT8 *out, const UINT8 *in, const int pixels) {
/* ARGB, 1/5/5/5 bits per pixel, little-endian, inverted alpha */
for (int i = 0; i < pixels; i++) {
const UINT16 pixel = ((UINT16)in[1] << 8) | in[0];
const UINT8 r = (pixel >> 10) & 31;
const UINT8 g = (pixel >> 5) & 31;
const UINT8 b = pixel & 31;
out[R] = (r << 3) | (r >> 2);
out[G] = (g << 3) | (g >> 2);
out[B] = (b << 3) | (b >> 2);
out[A] = ~((pixel >> 15) * 255);
out += 4;
in += 2;
}
}
static void
ImagingUnpackXBGR1555(UINT8 *out, const UINT8 *in, const int pixels) {
/* XBGR, 1/5/5/5 bits per pixel, little-endian */
for (int i = 0; i < pixels; i++) {
const UINT16 pixel = ((UINT16)in[1] << 8) | in[0];
const UINT8 b = (pixel >> 10) & 31;
const UINT8 g = (pixel >> 5) & 31;
const UINT8 r = pixel & 31;
out[R] = (r << 3) | (r >> 2);
out[G] = (g << 3) | (g >> 2);
out[B] = (b << 3) | (b >> 2);
out[A] = 255;
out += 4;
in += 2;
}
}
static void
ImagingUnpackABGR1555(UINT8 *out, const UINT8 *in, const int pixels) {
/* ABGR, 1/5/5/5 bits per pixel, little-endian */
for (int i = 0; i < pixels; i++) {
const UINT16 pixel = ((UINT16)in[1] << 8) | in[0];
const UINT8 b = (pixel >> 10) & 31;
const UINT8 g = (pixel >> 5) & 31;
const UINT8 r = pixel & 31;
out[R] = (r << 3) | (r >> 2);
out[G] = (g << 3) | (g >> 2);
out[B] = (b << 3) | (b >> 2);
out[A] = (pixel >> 15) * 255;
out += 4;
in += 2;
}
}
static void
ImagingUnpackRGB565(UINT8 *out, const UINT8 *in, const int pixels) {
/* RGB, 5/6/5 bits per pixel, little-endian */
for (int i = 0; i < pixels; i++) {
const UINT16 pixel = ((UINT16)in[1] << 8) | in[0];
const UINT8 r = (pixel >> 11) & 31;
const UINT8 g = (pixel >> 5) & 63;
const UINT8 b = pixel & 31;
out[R] = (r << 3) | (r >> 2);
out[G] = (g << 2) | (g >> 4);
out[B] = (b << 3) | (b >> 2);
out[A] = 255;
out += 4;
in += 2;
}
}
static void
ImagingUnpackBGR565(UINT8 *out, const UINT8 *in, const int pixels) {
/* BGR, 5/6/5 bits per pixel, little-endian */
for (int i = 0; i < pixels; i++) {
const UINT16 pixel = ((UINT16)in[1] << 8) | in[0];
const UINT8 b = (pixel >> 11) & 31;
const UINT8 g = (pixel >> 5) & 63;
const UINT8 r = pixel & 31;
out[R] = (r << 3) | (r >> 2);
out[G] = (g << 2) | (g >> 4);
out[B] = (b << 3) | (b >> 2);
out[A] = 255;
out += 4;
in += 2;
}
}
void
ImagingUnpackRGB4B(UINT8 *out, const UINT8 *in, int pixels) {
int i, pixel;
/* RGB, 4 bits per pixel */
/* RGB, 4 bits per pixel, little-endian */
for (i = 0; i < pixels; i++) {
pixel = in[0] + (in[1] << 8);
out[R] = (pixel & 15) * 17;
@ -782,7 +901,7 @@ ImagingUnpackRGB4B(UINT8 *out, const UINT8 *in, int pixels) {
void
ImagingUnpackRGBA4B(UINT8 *out, const UINT8 *in, int pixels) {
int i, pixel;
/* RGBA, 4 bits per pixel */
/* RGBA, 4 bits per pixel, little-endian */
for (i = 0; i < pixels; i++) {
pixel = in[0] + (in[1] << 8);
out[R] = (pixel & 15) * 17;
@ -794,6 +913,39 @@ ImagingUnpackRGBA4B(UINT8 *out, const UINT8 *in, int pixels) {
}
}
static void
ImagingUnpackXBGR4(UINT8 *out, const UINT8 *in, const int pixels) {
/* XBGR, 4 bits per pixel, little-endian */
for (int i = 0; i < pixels; i++) {
const UINT8 b = in[1] & 0x0F;
const UINT8 g = in[0] & 0xF0;
const UINT8 r = in[0] & 0x0F;
out[R] = (r << 4) | r;
out[G] = g | (g >> 4);
out[B] = (b << 4) | b;
out[A] = 255;
out += 4;
in += 2;
}
}
static void
ImagingUnpackABGR4(UINT8 *out, const UINT8 *in, const int pixels) {
/* ABGR, 4 bits per pixel, little-endian */
for (int i = 0; i < pixels; i++) {
const UINT8 a = in[1] & 0xF0;
const UINT8 b = in[1] & 0x0F;
const UINT8 g = in[0] & 0xF0;
const UINT8 r = in[0] & 0x0F;
out[R] = (r << 4) | r;
out[G] = g | (g >> 4);
out[B] = (b << 4) | b;
out[A] = a | (a >> 4);
out += 4;
in += 2;
}
}
static void
ImagingUnpackBGRX(UINT8 *_out, const UINT8 *in, int pixels) {
int i;
@ -1620,13 +1772,22 @@ static struct {
{"RGB", "RGB;16B", 48, unpackRGB16B},
{"RGB", "BGR", 24, ImagingUnpackBGR},
{"RGB", "RGB;15", 16, ImagingUnpackRGB15},
{"RGB", "XRGB;1555", 16, ImagingUnpackXRGB1555},
{"RGB", "ARGB;1555", 16, ImagingUnpackARGB1555},
{"RGB", "ARGB;1555Z", 16, ImagingUnpackARGB1555Z},
{"RGB", "BGR;15", 16, ImagingUnpackBGR15},
{"RGB", "XBGR;1555", 16, ImagingUnpackXBGR1555},
{"RGB", "ABGR;1555", 16, ImagingUnpackABGR1555},
{"RGB", "RGB;16", 16, ImagingUnpackRGB16},
{"RGB", "RGB;565", 16, ImagingUnpackRGB565},
{"RGB", "BGR;16", 16, ImagingUnpackBGR16},
{"RGB", "BGR;565", 16, ImagingUnpackBGR565},
{"RGB", "RGB;4B", 16, ImagingUnpackRGB4B},
{"RGB", "XBGR;4", 16, ImagingUnpackXBGR4},
{"RGB", "ABGR;4", 16, ImagingUnpackABGR4},
{"RGB", "BGR;5", 16, ImagingUnpackBGR15}, /* compat */
{"RGB", "RGBX;16L", 64, unpackRGBA16L},
{"RGB", "RGBX;16B", 64, unpackRGBA16B},
{"RGB", "RGB;4B", 16, ImagingUnpackRGB4B},
{"RGB", "BGR;5", 16, ImagingUnpackBGR15}, /* compat */
{"RGB", "RGBX", 32, copy4},
{"RGB", "RGBX;L", 32, unpackRGBAL},
{"RGB", "RGBXX", 40, copy4skip1},
@ -1656,6 +1817,9 @@ static struct {
/* true colour w. alpha */
{"RGBA", "LA", 16, unpackRGBALA},
{"RGBA", "LA;16B", 32, unpackRGBALA16B},
{"RGBA", "ARGB;1555", 16, ImagingUnpackARGB1555},
{"RGBA", "ARGB;1555Z", 16, ImagingUnpackARGB1555Z},
{"RGBA", "ABGR;1555", 16, ImagingUnpackABGR1555},
{"RGBA", "RGBA", 32, copy4},
{"RGBA", "RGBAX", 40, copy4skip1},
{"RGBA", "RGBAXX", 48, copy4skip2},
@ -1671,6 +1835,7 @@ static struct {
{"RGBA", "BGRA;15", 16, ImagingUnpackBGRA15},
{"RGBA", "BGRA;15Z", 16, ImagingUnpackBGRA15Z},
{"RGBA", "RGBA;4B", 16, ImagingUnpackRGBA4B},
{"RGBA", "ABGR;4", 16, ImagingUnpackABGR4},
{"RGBA", "RGBA;16L", 64, unpackRGBA16L},
{"RGBA", "RGBA;16B", 64, unpackRGBA16B},
{"RGBA", "BGRA", 32, unpackBGRA},
@ -1733,8 +1898,13 @@ static struct {
{"RGBX", "RGB;16B", 48, unpackRGB16B},
{"RGBX", "BGR", 24, ImagingUnpackBGR},
{"RGBX", "RGB;15", 16, ImagingUnpackRGB15},
{"RGBX", "XRGB;1555", 16, ImagingUnpackXRGB1555},
{"RGBX", "RGB;565", 16, ImagingUnpackRGB565},
{"RGBX", "BGR;15", 16, ImagingUnpackBGR15},
{"RGBX", "XBGR;1555", 16, ImagingUnpackXBGR1555},
{"RGBX", "BGR;565", 16, ImagingUnpackBGR565},
{"RGBX", "RGB;4B", 16, ImagingUnpackRGB4B},
{"RGBX", "XBGR;4", 16, ImagingUnpackXBGR4},
{"RGBX", "BGR;5", 16, ImagingUnpackBGR15}, /* compat */
{"RGBX", "RGBX", 32, copy4},
{"RGBX", "RGBXX", 40, copy4skip1},