Commit 67e12727 authored by Deucе's avatar Deucе 👌🏾
Browse files

Add an untested width interpolater

SyncTERM doesn't support any "fat-pixel" modes.
parent 34aeeb6d
Pipeline #2170 failed with stage
in 9 minutes and 2 seconds
...@@ -8,6 +8,7 @@ static int r2y_inited; ...@@ -8,6 +8,7 @@ static int r2y_inited;
static void pointy_scale3(uint32_t* src, uint32_t* dest, int width, int height); static void pointy_scale3(uint32_t* src, uint32_t* dest, int width, int height);
static void pointy_scale5(uint32_t* src, uint32_t* dest, int width, int height); static void pointy_scale5(uint32_t* src, uint32_t* dest, int width, int height);
static void interpolate_height(uint32_t* src, uint32_t* dst, int width, int height, int newheight); static void interpolate_height(uint32_t* src, uint32_t* dst, int width, int height, int newheight);
static void interpolate_width(uint32_t* src, uint32_t* dst, int width, int height, int newwidth);
static void multiply_scale(uint32_t* src, uint32_t* dst, int width, int height, int xmult, int ymult); static void multiply_scale(uint32_t* src, uint32_t* dst, int width, int height, int xmult, int ymult);
static struct graphics_buffer *free_list; static struct graphics_buffer *free_list;
...@@ -104,6 +105,7 @@ do_scale(struct rectlist* rect, int* xscale, int* yscale, double ratio) ...@@ -104,6 +105,7 @@ do_scale(struct rectlist* rect, int* xscale, int* yscale, double ratio)
struct graphics_buffer *csrc; struct graphics_buffer *csrc;
uint32_t* nt; uint32_t* nt;
int fheight; int fheight;
int fwidth;
switch (*xscale) { switch (*xscale) {
case 1: case 1:
...@@ -172,10 +174,18 @@ do_scale(struct rectlist* rect, int* xscale, int* yscale, double ratio) ...@@ -172,10 +174,18 @@ do_scale(struct rectlist* rect, int* xscale, int* yscale, double ratio)
} }
// Calculate the scaled height from ratio... // Calculate the scaled height from ratio...
fheight = lround((double)(rect->rect.height * (*yscale)) / ratio); if (ratio < 1)
fheight = lround((double)(rect->rect.height * (*yscale)) / ratio);
else
fheight = rect->rect.height * *yscale;
if (ratio > 1)
fwidth = lround((double)(rect->rect.width * (*xscale)) / ratio);
else
fwidth = rect->rect.width * *xscale;
// Now make sure target is big enough... // Now make sure target is big enough...
size_t needsz = rect->rect.width * (*xscale) * fheight * sizeof(uint32_t); size_t needsz = fwidth * fheight * sizeof(uint32_t);
if (needsz > ret1->sz) { if (needsz > ret1->sz) {
nt = realloc(ret1->data, needsz); nt = realloc(ret1->data, needsz);
if (nt == NULL) if (nt == NULL)
...@@ -259,7 +269,7 @@ do_scale(struct rectlist* rect, int* xscale, int* yscale, double ratio) ...@@ -259,7 +269,7 @@ do_scale(struct rectlist* rect, int* xscale, int* yscale, double ratio)
} }
// And finally, interpolate if needed // And finally, interpolate if needed
if (ratio != 1) { if (ratio < 1) {
interpolate_height(csrc->data, ctarget->data, csrc->w, csrc->h, fheight); interpolate_height(csrc->data, ctarget->data, csrc->w, csrc->h, fheight);
ctarget->h = fheight; ctarget->h = fheight;
ctarget->w = csrc->w; ctarget->w = csrc->w;
...@@ -270,6 +280,17 @@ do_scale(struct rectlist* rect, int* xscale, int* yscale, double ratio) ...@@ -270,6 +280,17 @@ do_scale(struct rectlist* rect, int* xscale, int* yscale, double ratio)
ctarget = ret1; ctarget = ret1;
} }
if (ratio > 1) {
interpolate_width(csrc->data, ctarget->data, csrc->w, csrc->h, fwidth);
ctarget->h = csrc->h;
ctarget->w = fwidth;
csrc = ctarget;
if (ctarget == ret1)
ctarget = ret2;
else
ctarget = ret1;
}
*xscale = newscale; *xscale = newscale;
*yscale = newscale; *yscale = newscale;
release_buffer(ctarget); release_buffer(ctarget);
...@@ -495,6 +516,46 @@ uint32_t blend(const uint32_t c1, const uint32_t c2, const double weight) ...@@ -495,6 +516,46 @@ uint32_t blend(const uint32_t c1, const uint32_t c2, const double weight)
return y2r[(y<<16)|(u<<8)|v]; return y2r[(y<<16)|(u<<8)|v];
} }
/*
* This does non-integer *width* scaling. It does not scale in the other
* direction. This does the interpolation using Y'UV to prevent dimming of
* pixels.
*/
static void
interpolate_width(uint32_t* src, uint32_t* dst, int width, int height, int newwidth)
{
int x, y;
const double mult = (double)width / newwidth;
for (y = 0; y < height; y++) {
for (x = 0; x < newwidth; x++) {
// First, calculate which two pixels this is between.
const double xpos = mult * x;
const int xposi = xpos;
if (x == xpos) {
// Exact match!
*dst = src[width * y + x];
}
else {
const double weight = xpos - xposi;
// Now pick the two pixels
const uint32_t pix1 = src[y * width + xposi] & 0xffffff;
uint32_t pix2;
if (xposi < width - 1)
pix2 = src[y * width + xposi + 1] & 0xffffff;
else
pix2 = src[y * width + xposi] & 0xffffff;
if (pix1 == pix2)
*dst = pix1;
else {
*dst = blend(pix1, pix2, weight);
}
}
dst++;
}
}
}
/* /*
* This does non-integer *height* scaling. It does not scale in the other * This does non-integer *height* scaling. It does not scale in the other
* direction. This does the interpolation using Y'UV to prevent dimming of * direction. This does the interpolation using Y'UV to prevent dimming of
......
...@@ -67,7 +67,7 @@ struct video_params vparams[] = { ...@@ -67,7 +67,7 @@ struct video_params vparams[] = {
/* BW 80x28 */ /* BW 80x28 */
{BW80X28, GREYSCALE_PALETTE, 80, 28, 12, 13, 14, 8, 1, 7, 0, 1, 1, 640, 392}, {BW80X28, GREYSCALE_PALETTE, 80, 28, 12, 13, 14, 8, 1, 7, 0, 1, 1, 640, 392},
/* BW 80x43 */ /* BW 80x43 */
{BW80X43, GREYSCALE_PALETTE, 80, 43, 7, 7, 14, 8, 1, 7, 0, 1, 1, 640, 350}, {BW80X43, GREYSCALE_PALETTE, 80, 43, 7, 7, 14, 8, 1, 7, 0, 729, 1000, 640, 350},
/* BW 80x50 */ /* BW 80x50 */
{BW80X50, GREYSCALE_PALETTE, 80, 50, 7, 7, 8, 8, 1, 7, 0, 833, 1000, 640, 400}, {BW80X50, GREYSCALE_PALETTE, 80, 50, 7, 7, 8, 8, 1, 7, 0, 833, 1000, 640, 400},
/* BW 80x60 */ /* BW 80x60 */
...@@ -87,11 +87,11 @@ struct video_params vparams[] = { ...@@ -87,11 +87,11 @@ struct video_params vparams[] = {
/* Magical C4350 Mode */ /* Magical C4350 Mode */
{C4350, COLOUR_PALETTE, 80, 50, 7, 7, 8, 8, 1, 7, 0, 833, 1000, 640, 400}, {C4350, COLOUR_PALETTE, 80, 50, 7, 7, 8, 8, 1, 7, 0, 833, 1000, 640, 400},
/* Commodore 64 40x25 mode */ /* Commodore 64 40x25 mode */
{C64_40X25, C64_PALETTE, 40, 25, 0, 7, 8, 8, 1, 0x6e, CIOLIB_VIDEO_BGBRIGHT|CIOLIB_VIDEO_NOBLINK, 1, 1, 320, 200}, {C64_40X25, C64_PALETTE, 40, 25, 0, 7, 8, 8, 1, 0x6e, CIOLIB_VIDEO_BGBRIGHT|CIOLIB_VIDEO_NOBLINK, 240, 312, 320, 200},
/* Commodore 128 40x25 mode */ /* Commodore 128 40x25 mode */
{C128_40X25, C64_PALETTE, 40, 25, 0, 7, 8, 8, 1, 0xbd, CIOLIB_VIDEO_BGBRIGHT|CIOLIB_VIDEO_NOBLINK, 1, 1, 320, 200}, {C128_40X25, C64_PALETTE, 40, 25, 0, 7, 8, 8, 1, 0xbd, CIOLIB_VIDEO_BGBRIGHT|CIOLIB_VIDEO_NOBLINK, 240, 312, 320, 200},
/* Commodore 128 80x25 mode */ /* Commodore 128 80x25 mode */
{C128_80X25, COLOUR_PALETTE, 80, 25, 0, 7, 8, 8, 2, 7, CIOLIB_VIDEO_BGBRIGHT|CIOLIB_VIDEO_NOBLINK, 1, 1, 640, 200}, {C128_80X25, COLOUR_PALETTE, 80, 25, 0, 7, 8, 8, 2, 7, CIOLIB_VIDEO_BGBRIGHT|CIOLIB_VIDEO_NOBLINK, 240, 312, 640, 200},
/* Atari 800 40x24 mode */ /* Atari 800 40x24 mode */
{ATARI_40X24, ATARI_PALETTE, 40, 24, 0, 7, 8, 8, 1, 7, 0, 1, 1, 320, 192}, {ATARI_40X24, ATARI_PALETTE, 40, 24, 0, 7, 8, 8, 1, 7, 0, 1, 1, 320, 192},
/* Atari 800 XEP80 80x25 mode */ /* Atari 800 XEP80 80x25 mode */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment