182 lines
4.6 KiB
C++
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 }
|
|
};
|
|
|