Synchronet now requires the libarchive development package (e.g. libarchive-dev on Debian-based Linux distros, libarchive.org for more info) to build successfully.

Commits (1)
......@@ -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_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_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 struct graphics_buffer *free_list;
......@@ -104,6 +105,7 @@ do_scale(struct rectlist* rect, int* xscale, int* yscale, double ratio)
struct graphics_buffer *csrc;
uint32_t* nt;
int fheight;
int fwidth;
switch (*xscale) {
case 1:
......@@ -172,10 +174,18 @@ do_scale(struct rectlist* rect, int* xscale, int* yscale, double 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...
size_t needsz = rect->rect.width * (*xscale) * fheight * sizeof(uint32_t);
size_t needsz = fwidth * fheight * sizeof(uint32_t);
if (needsz > ret1->sz) {
nt = realloc(ret1->data, needsz);
if (nt == NULL)
......@@ -259,7 +269,7 @@ do_scale(struct rectlist* rect, int* xscale, int* yscale, double ratio)
}
// And finally, interpolate if needed
if (ratio != 1) {
if (ratio < 1) {
interpolate_height(csrc->data, ctarget->data, csrc->w, csrc->h, fheight);
ctarget->h = fheight;
ctarget->w = csrc->w;
......@@ -270,6 +280,17 @@ do_scale(struct rectlist* rect, int* xscale, int* yscale, double ratio)
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;
*yscale = newscale;
release_buffer(ctarget);
......@@ -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];
}
/*
* 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
* direction. This does the interpolation using Y'UV to prevent dimming of
......
......@@ -67,7 +67,7 @@ struct video_params vparams[] = {
/* BW 80x28 */
{BW80X28, GREYSCALE_PALETTE, 80, 28, 12, 13, 14, 8, 1, 7, 0, 1, 1, 640, 392},
/* 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 */
{BW80X50, GREYSCALE_PALETTE, 80, 50, 7, 7, 8, 8, 1, 7, 0, 833, 1000, 640, 400},
/* BW 80x60 */
......@@ -87,11 +87,11 @@ struct video_params vparams[] = {
/* Magical C4350 Mode */
{C4350, COLOUR_PALETTE, 80, 50, 7, 7, 8, 8, 1, 7, 0, 833, 1000, 640, 400},
/* 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 */
{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 */
{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_40X24, ATARI_PALETTE, 40, 24, 0, 7, 8, 8, 1, 7, 0, 1, 1, 320, 192},
/* Atari 800 XEP80 80x25 mode */
......