Skip to content
Snippets Groups Projects
Commit e2bbb4d5 authored by Deucе's avatar Deucе :ok_hand_tone4:
Browse files

Use the YCoCg-R colour space instead of YCbCr.

It seems to provide similar perceptual results, and is much faster
to transform with RGB.  It's still slower than the table lookup,
but not crushingly so.
parent cdc21fb0
No related branches found
No related tags found
No related merge requests found
Pipeline #5453 passed
......@@ -748,29 +748,60 @@ pointy_scale3(uint32_t* src, uint32_t* dest, int width, int height)
}
}
struct YCoCg_data {
unsigned Y;
signed Co;
signed Cg;
};
static void
RGB_to_YCoCg(const uint32_t RGB, struct YCoCg_data *YCoCg)
{
signed R, G, B, tmp;
R = (RGB >> 16) & 0xFF;
G = (RGB >> 8) & 0xFF;
B = (RGB) & 0xFF;
YCoCg->Co = R - B;
tmp = B + (YCoCg->Co >> 1);
YCoCg->Cg = G - tmp;
YCoCg->Y = tmp + (YCoCg->Cg >> 1);
}
static uint32_t
blend(const uint32_t c1, const uint32_t c2, uint16_t weight)
YCoCg_to_RGB(struct YCoCg_data *YCoCg)
{
signed Ri, Gi, Bi, tmp;
unsigned R, G, B;
tmp = YCoCg->Y - (YCoCg->Cg >> 1);
Gi = YCoCg->Cg + tmp;
Bi = tmp - (YCoCg->Co >> 1);
Ri = Bi + YCoCg->Co;
R = ((Ri < 0) ? 0 : ((Ri > 255) ? 255 : Ri));
G = ((Gi < 0) ? 0 : ((Gi > 255) ? 255 : Gi));
B = ((Bi < 0) ? 0 : ((Bi > 255) ? 255 : Bi));
return (R << 16) | (G << 8) | B;
}
static uint32_t
blend_YCoCg(const uint32_t c1, const uint32_t c2, uint16_t weight)
{
uint8_t yuv1[4];
uint8_t yuv2[4];
uint8_t yuv3[4];
const uint16_t iw = 65535 - weight;
*(uint32_t *)yuv1 = ciolib_r2yptr[c1];
*(uint32_t *)yuv2 = ciolib_r2yptr[c2];
#ifdef __BIG_ENDIAN__
yuv3[0] = 0;
yuv3[1] = (yuv1[1] * iw + yuv2[1] * weight) / 65535;
yuv3[2] = (yuv1[2] * iw + yuv2[2] * weight) / 65535;
yuv3[3] = (yuv1[3] * iw + yuv2[3] * weight) / 65535;
#else
yuv3[3] = 0;
yuv3[2] = (yuv1[2] * iw + yuv2[2] * weight) / 65535;
yuv3[1] = (yuv1[1] * iw + yuv2[1] * weight) / 65535;
yuv3[0] = (yuv1[0] * iw + yuv2[0] * weight) / 65535;
#endif
struct YCoCg_data ycc1;
struct YCoCg_data ycc2;
struct YCoCg_data ycc3;
RGB_to_YCoCg(c1, &ycc1);
RGB_to_YCoCg(c2, &ycc2);
ycc3.Y = ((uint32_t)ycc1.Y * iw + (uint32_t)ycc2.Y * weight) / 65535;
ycc3.Co = ((int32_t)ycc1.Co * iw + (int32_t)ycc2.Co * weight) / 65535;
ycc3.Cg = ((int32_t)ycc1.Cg * iw + (int32_t)ycc2.Cg * weight) / 65535;
return ciolib_y2rptr[*(uint32_t*)yuv3];
return YCoCg_to_RGB(&ycc3);
}
/*
......@@ -807,7 +838,7 @@ interpolate_width(uint32_t* src, uint32_t* dst, int width, int height, int newwi
if (pix1 == pix2)
*dst = pix1;
else {
*dst = blend(pix1, pix2, weight);
*dst = blend_YCoCg(pix1, pix2, weight);
}
}
dst += newwidth;
......@@ -874,7 +905,7 @@ interpolate_height(uint32_t* src, uint32_t* dst, int width, int height, int newh
if (pix1 == pix2)
*dst = pix1;
else
*dst = blend(pix1, pix2, weight);
*dst = blend_YCoCg(pix1, pix2, weight);
dst++;
}
}
......
......@@ -40,20 +40,40 @@
#undef PI
#endif
static uint32_t pixel_diff(uint32_t x, uint32_t y)
struct YCoCg_data {
unsigned Y;
signed Co;
signed Cg;
};
static void
RGB_to_YCoCg(const uint32_t RGB, struct YCoCg_data *YCoCg)
{
#define YMASK 0xff0000
#define UMASK 0x00ff00
#define VMASK 0x0000ff
#define ABSDIFF(a,b) (abs((int)(a)-(int)(b)))
int R, G, B, tmp;
uint32_t yuv1 = ciolib_r2yptr[x & 0xffffff];
R = (RGB >> 16) & 0xFF;
G = (RGB >> 8) & 0xFF;
B = (RGB) & 0xFF;
YCoCg->Co = R - B;
tmp = B + (YCoCg->Co >> 1);
YCoCg->Cg = G - tmp;
YCoCg->Y = tmp + (YCoCg->Cg >> 1);
}
static uint32_t pixel_diff(uint32_t x, uint32_t y)
{
struct YCoCg_data yccx;
struct YCoCg_data yccy;
//#define ABSDIFF(a,b) (abs((int)(a)-(int)(b)))
#define ABSDIFF(a,b) (a > b ? a - b : b - a)
uint32_t yuv2 = ciolib_r2yptr[y & 0xffffff];
RGB_to_YCoCg(x, &yccx);
RGB_to_YCoCg(y, &yccy);
return (ABSDIFF(yuv1 & YMASK, yuv2 & YMASK) >> 16) +
(ABSDIFF(yuv1 & UMASK, yuv2 & UMASK) >> 8) +
ABSDIFF(yuv1 & VMASK, yuv2 & VMASK);
return (ABSDIFF(yccx.Y, yccy.Y)) +
(ABSDIFF(yccx.Co, yccy.Co) >> 1) +
(ABSDIFF(yccx.Cg, yccy.Cg) >> 1);
}
#define ALPHA_BLEND_128_W(a, b) ((((a) & LB_MASK) >> 1) + (((b) & LB_MASK) >> 1))
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment