REminiscence/scaler.cpp

182 lines
4.6 KiB
C++

/*
* REminiscence - Flashback interpreter
* Copyright (C) 2005-2015 Gregory Montoir (cyx@users.sourceforge.net)
*/
#include "scaler.h"
#include "util.h"
static void point1x(uint16_t *dst, int dstPitch, const uint16_t *src, int srcPitch, int w, int h) {
dstPitch >>= 1;
while (h--) {
memcpy(dst, src, w * 2);
dst += dstPitch;
src += srcPitch;
}
}
static void point2x(uint16_t *dst, int dstPitch, const uint16_t *src, int srcPitch, int w, int h) {
dstPitch >>= 1;
const int dstPitch2 = dstPitch * 2;
while (h--) {
uint16_t *p = dst;
for (int i = 0; i < w; ++i, p += 2) {
const uint16_t c = *(src + i);
for (int j = 0; j < 2; ++j) {
*(p + j) = *(p + dstPitch + j) = c;
}
}
dst += dstPitch2;
src += srcPitch;
}
}
static void point3x(uint16_t *dst, int dstPitch, const uint16_t *src, int srcPitch, int w, int h) {
dstPitch >>= 1;
const int dstPitch2 = dstPitch * 2;
const int dstPitch3 = dstPitch * 3;
while (h--) {
uint16_t *p = dst;
for (int i = 0; i < w; ++i, p += 3) {
const uint16_t c = *(src + i);
for (int j = 0; j < 3; ++j) {
*(p + j) = *(p + dstPitch + j) = *(p + dstPitch2 + j) = c;
}
}
dst += dstPitch3;
src += srcPitch;
}
}
static void point4x(uint16_t *dst, int dstPitch, const uint16_t *src, int srcPitch, int w, int h) {
dstPitch >>= 1;
const int dstPitch2 = dstPitch * 2;
const int dstPitch3 = dstPitch * 3;
const int dstPitch4 = dstPitch * 4;
while (h--) {
uint16_t *p = dst;
for (int i = 0; i < w; ++i, p += 4) {
const uint16_t c = *(src + i);
for (int j = 0; j < 4; ++j) {
*(p + j) = *(p + dstPitch + j) = *(p + dstPitch2 + j) = *(p + dstPitch3 + j) = c;
}
}
dst += dstPitch4;
src += srcPitch;
}
}
static void scale2x(uint16_t *dst, int dstPitch, const uint16_t *src, int srcPitch, int w, int h) {
dstPitch >>= 1;
const int dstPitch2 = dstPitch * 2;
while (h--) {
uint16_t *p = dst;
uint16_t D = *(src - 1);
uint16_t E = *(src);
for (int i = 0; i < w; ++i, p += 2) {
uint16_t B = *(src + i - srcPitch);
uint16_t F = *(src + i + 1);
uint16_t H = *(src + i + srcPitch);
if (B != H && D != F) {
*(p) = D == B ? D : E;
*(p + 1) = B == F ? F : E;
*(p + dstPitch) = D == H ? D : E;
*(p + dstPitch + 1) = H == F ? F : E;
} else {
*(p) = E;
*(p + 1) = E;
*(p + dstPitch) = E;
*(p + dstPitch + 1) = E;
}
D = E;
E = F;
}
dst += dstPitch2;
src += srcPitch;
}
}
static void scale3x(uint16_t *dst, int dstPitch, const uint16_t *src, int srcPitch, int w, int h) {
dstPitch >>= 1;
const int dstPitch2 = dstPitch * 2;
const int dstPitch3 = dstPitch * 3;
while (h--) {
uint16_t *p = dst;
uint16_t A = *(src - srcPitch - 1);
uint16_t B = *(src - srcPitch);
uint16_t D = *(src - 1);
uint16_t E = *(src);
uint16_t G = *(src + srcPitch - 1);
uint16_t H = *(src + srcPitch);
for (int i = 0; i < w; ++i, p += 3) {
uint16_t C = *(src + i - srcPitch + 1);
uint16_t F = *(src + i + 1);
uint16_t I = *(src + i + srcPitch + 1);
if (B != H && D != F) {
*(p) = D == B ? D : E;
*(p + 1) = (D == B && E != C) || (B == F && E != A) ? B : E;
*(p + 2) = B == F ? F : E;
*(p + dstPitch) = (D == B && E != G) || (D == B && E != A) ? D : E;
*(p + dstPitch + 1) = E;
*(p + dstPitch + 2) = (B == F && E != I) || (H == F && E != C) ? F : E;
*(p + dstPitch2) = D == H ? D : E;
*(p + dstPitch2 + 1) = (D == H && E != I) || (H == F && E != G) ? H : E;
*(p + dstPitch2 + 2) = H == F ? F : E;
} else {
*(p) = E;
*(p + 1) = E;
*(p + 2) = E;
*(p + dstPitch) = E;
*(p + dstPitch + 1) = E;
*(p + dstPitch + 2) = E;
*(p + dstPitch2) = E;
*(p + dstPitch2 + 1) = E;
*(p + dstPitch2 + 2) = E;
}
A = B;
B = C;
D = E;
E = F;
G = H;
H = I;
}
dst += dstPitch3;
src += srcPitch;
}
}
void scale4x(uint16_t *dst, int dstPitch, const uint16_t *src, int srcPitch, int w, int h) {
static struct {
uint16_t *ptr;
int w, h, pitch;
int size;
} buf;
const int size = (w * 2 + 2) * (h * 2 + 2) * sizeof(uint16_t);
if (buf.size < size) {
free(buf.ptr);
buf.size = size;
buf.w = w * 2;
buf.h = h * 2;
buf.pitch = buf.w + 2;
buf.ptr = (uint16_t *)malloc(buf.size);
if (!buf.ptr) {
error("Unable to allocate scale4x intermediate buffer");
}
}
scale2x(buf.ptr + buf.pitch + 1, buf.pitch * sizeof(uint16_t), src, srcPitch, w, h);
scale2x(dst, dstPitch, buf.ptr + buf.pitch + 1, buf.pitch, w * 2, h * 2);
}
const Scaler _scalers[] = {
{ "point1x", &point1x, 1 },
{ "point2x", &point2x, 2 },
{ "scale2x", &scale2x, 2 },
{ "point3x", &point3x, 3 },
{ "scale3x", &scale3x, 3 },
{ "point4x", &point4x, 4 },
{ "scale4x", &scale4x, 4 },
{ 0, 0, 0 }
};