Skip to content

Commit

Permalink
Add RGB5A1 support, used by some VC games
Browse files Browse the repository at this point in the history
  • Loading branch information
xzn committed Feb 2, 2024
1 parent 860293b commit 09355d2
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 9 deletions.
3 changes: 3 additions & 0 deletions include/jpeg/jpegint.h
Expand Up @@ -77,6 +77,9 @@ typedef size_t JUINTPTR;
#define IsExtRGB(cs) \
(cs == JCS_RGB || (cs >= JCS_EXT_RGB && cs <= JCS_EXT_ARGB))

#define IsExtRGB2(cs) \
(cs >= JCS_EXT_RGB565 && cs <= JCS_EXT_RGB4)

/*
* Left shift macro that handles a negative operand without causing any
* sanitizer warnings
Expand Down
3 changes: 3 additions & 0 deletions include/jpeg/jpeglib.h
Expand Up @@ -275,6 +275,9 @@ typedef enum {
JCS_EXT_BGRA, /* blue/green/red/alpha */
JCS_EXT_ABGR, /* alpha/blue/green/red */
JCS_EXT_ARGB, /* alpha/red/green/blue */
JCS_EXT_RGB565,
JCS_EXT_RGB5A1,
JCS_EXT_RGB4,
JCS_RGB565 /* 5-bit red/6-bit green/5-bit blue */
} J_COLOR_SPACE;

Expand Down
66 changes: 60 additions & 6 deletions source/jpeg/jccolor.c
Expand Up @@ -277,8 +277,8 @@ rgb565_ycc_convert(j_compress_ptr cinfo, _JSAMPARRAY input_buf,
output_row++;
for (col = 0; col < num_cols; col++) {
short in = *(short *)inptr;
r = cconvert->rb_5_tab[((in >> 11) & 0x1f)];
g = cconvert->g_6_tab[((in >> 5) & 0x3f)];
r = cconvert->rb_5_tab[(in >> 11) & 0x1f];
g = cconvert->g_6_tab[(in >> 5) & 0x3f];
b = cconvert->rb_5_tab[in & 0x1f];
inptr += 2;
/* If the inputs are 0.._MAXJSAMPLE, the outputs of these equations
Expand All @@ -302,6 +302,54 @@ rgb565_ycc_convert(j_compress_ptr cinfo, _JSAMPARRAY input_buf,
#endif
}

INLINE
LOCAL(void)
rgb5a1_ycc_convert(j_compress_ptr cinfo, _JSAMPARRAY input_buf,
_JSAMPIMAGE output_buf, JDIMENSION output_row,
int num_rows)
{
#if BITS_IN_JSAMPLE != 16
my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert;
register int r, g, b;
register JLONG *ctab = cconvert->rgb_ycc_tab;
register _JSAMPROW inptr;
register _JSAMPROW outptr0, outptr1, outptr2;
register JDIMENSION col;
JDIMENSION num_cols = cinfo->image_width;

while (--num_rows >= 0) {
inptr = *input_buf++;
outptr0 = output_buf[0][output_row];
outptr1 = output_buf[1][output_row];
outptr2 = output_buf[2][output_row];
output_row++;
for (col = 0; col < num_cols; col++) {
short in = *(short *)inptr;
r = cconvert->rb_5_tab[(in >> 11) & 0x1f];
g = cconvert->rb_5_tab[(in >> 6) & 0x1f];
b = cconvert->rb_5_tab[(in >> 1) & 0x1f];
inptr += 2;
/* If the inputs are 0.._MAXJSAMPLE, the outputs of these equations
* must be too; we do not need an explicit range-limiting operation.
* Hence the value being shifted is never negative, and we don't
* need the general RIGHT_SHIFT macro.
*/
/* Y */
outptr0[col] = (_JSAMPLE)((ctab[r + R_Y_OFF] + ctab[g + G_Y_OFF] +
ctab[b + B_Y_OFF]) >> SCALEBITS);
/* Cb */
outptr1[col] = (_JSAMPLE)((ctab[r + R_CB_OFF] + ctab[g + G_CB_OFF] +
ctab[b + B_CB_OFF]) >> SCALEBITS);
/* Cr */
outptr2[col] = (_JSAMPLE)((ctab[r + R_CR_OFF] + ctab[g + G_CR_OFF] +
ctab[b + B_CR_OFF]) >> SCALEBITS);
}
}
#else
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
#endif
}

/*
* Convert some rows of samples to the JPEG colorspace.
*/
Expand Down Expand Up @@ -339,10 +387,14 @@ rgb_ycc_convert(j_compress_ptr cinfo, _JSAMPARRAY input_buf,
extxrgb_ycc_convert_internal(cinfo, input_buf, output_buf, output_row,
num_rows);
break;
case JCS_RGB565:
case JCS_EXT_RGB565:
rgb565_ycc_convert(cinfo, input_buf, output_buf, output_row,
num_rows);
break;
case JCS_EXT_RGB5A1:
rgb5a1_ycc_convert(cinfo, input_buf, output_buf, output_row,
num_rows);
break;
default:
rgb_ycc_convert_internal(cinfo, input_buf, output_buf, output_row,
num_rows);
Expand Down Expand Up @@ -644,7 +696,9 @@ _jinit_color_converter(j_compress_ptr cinfo)
ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
break;

case JCS_RGB565:
case JCS_EXT_RGB565:
case JCS_EXT_RGB5A1:
case JCS_EXT_RGB4:
case JCS_YCbCr:
if (cinfo->input_components != 3)
ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
Expand Down Expand Up @@ -718,9 +772,9 @@ _jinit_color_converter(j_compress_ptr cinfo)
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
if (cinfo->num_components != 3)
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
if (IsExtRGB(cinfo->in_color_space) || cinfo->in_color_space == JCS_RGB565) {
if (IsExtRGB(cinfo->in_color_space) || IsExtRGB2(cinfo->in_color_space)) {
#ifdef WITH_SIMD
if (jsimd_can_rgb_ycc() && cinfo->in_color_space != JCS_RGB565)
if (jsimd_can_rgb_ycc() && !IsExtRGB2(cinfo->in_color_space))
cconvert->pub._color_convert = jsimd_rgb_ycc_convert;
else
#endif
Expand Down
4 changes: 3 additions & 1 deletion source/jpeg/jcparam.c
Expand Up @@ -301,7 +301,9 @@ jpeg_default_colorspace(j_compress_ptr cinfo)
case JCS_EXT_BGRA:
case JCS_EXT_ABGR:
case JCS_EXT_ARGB:
case JCS_RGB565:
case JCS_EXT_RGB565:
case JCS_EXT_RGB5A1:
case JCS_EXT_RGB4:
if (cinfo->master->lossless)
jpeg_set_colorspace(cinfo, JCS_RGB);
else
Expand Down
8 changes: 6 additions & 2 deletions source/nwm/rp_nwm.c
Expand Up @@ -587,7 +587,11 @@ static void rpReadyWork(BLIT_CONTEXT *ctx, u32 work_next) {
cinfo->image_width = ctx->height;
cinfo->image_height = ctx->width;
cinfo->input_components = ctx->format == 0 ? 4 : 3;
cinfo->in_color_space = ctx->format == 0 ? JCS_EXT_XBGR : ctx->format == 1 ? JCS_EXT_BGR : JCS_RGB565;
cinfo->in_color_space =
ctx->format == 0 ? JCS_EXT_XBGR :
ctx->format == 1 ? JCS_EXT_BGR :
ctx->format == 2 ? JCS_EXT_RGB565 :
ctx->format == 3 ? JCS_EXT_RGB5A1 : JCS_EXT_RGB4;

cinfo->restart_in_rows = jpeg_adjusted_rows[work_next];
cinfo->restart_interval = cinfo->restart_in_rows * mcus_per_row;
Expand Down Expand Up @@ -972,7 +976,7 @@ static int rpCaptureScreen(u32 work_next, int isTop) {

u32 format = (isTop ? tl_format : bl_format) & 0x0f;

if (format >= 3)
if (format > 3) // TODO add RGB4 support (in modified libjpeg-turbo)
goto final;

u32 bpp; /* bytes per pixel */
Expand Down

0 comments on commit 09355d2

Please sign in to comment.