145 lines
3.8 KiB
C++
145 lines
3.8 KiB
C++
|
|
/*
|
|
* REminiscence - Flashback interpreter
|
|
* Copyright (C) 2005-2015 Gregory Montoir (cyx@users.sourceforge.net)
|
|
*/
|
|
|
|
#include "scaler.h"
|
|
#include "dynlib.h"
|
|
#include "util.h"
|
|
|
|
static void scale2x(uint32_t *dst, int dstPitch, const uint32_t *src, int srcPitch, int w, int h) {
|
|
const int dstPitch2 = dstPitch * 2;
|
|
for (int y = 0; y < h; ++y) {
|
|
uint32_t *p = dst;
|
|
for (int x = 0; x < w; ++x, p += 2) {
|
|
const uint32_t E = *(src + x);
|
|
const uint32_t B = (y == 0) ? E : *(src + x - srcPitch);
|
|
const uint32_t D = (x == 0) ? E : *(src + x - 1);
|
|
const uint32_t F = (x == w - 1) ? E : *(src + x + 1);
|
|
const uint32_t H = (y == h - 1) ? E : *(src + x + 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;
|
|
}
|
|
}
|
|
dst += dstPitch2;
|
|
src += srcPitch;
|
|
}
|
|
}
|
|
|
|
static void scale3x(uint32_t *dst, int dstPitch, const uint32_t *src, int srcPitch, int w, int h) {
|
|
const int dstPitch2 = dstPitch * 2;
|
|
const int dstPitch3 = dstPitch * 3;
|
|
for (int y = 0; y < h; ++y) {
|
|
uint32_t *p = dst;
|
|
for (int x = 0; x < w; ++x, p += 3) {
|
|
const uint32_t E = *(src + x);
|
|
const uint32_t B = (y == 0) ? E : *(src + x - srcPitch);
|
|
const uint32_t D = (x == 0) ? E : *(src + x - 1);
|
|
const uint32_t F = (x == w - 1) ? E : *(src + x + 1);
|
|
const uint32_t H = (y == h - 1) ? E : *(src + x + srcPitch);
|
|
uint32_t A, C;
|
|
if (y == 0) {
|
|
A = D;
|
|
C = F;
|
|
} else {
|
|
A = (x == 0) ? B : *(src + x - srcPitch - 1);
|
|
C = (x == w - 1) ? B : *(src + x - srcPitch + 1);
|
|
}
|
|
uint32_t G, I;
|
|
if (y == h - 1) {
|
|
G = D;
|
|
I = F;
|
|
} else {
|
|
G = (x == 0) ? H : *(src + x + srcPitch - 1);
|
|
I = (x == w - 1) ? H : *(src + x + 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;
|
|
}
|
|
}
|
|
dst += dstPitch3;
|
|
src += srcPitch;
|
|
}
|
|
}
|
|
|
|
static void scale4x(uint32_t *dst, int dstPitch, const uint32_t *src, int srcPitch, int w, int h) {
|
|
static struct {
|
|
uint32_t *ptr;
|
|
int w, h, pitch;
|
|
int size;
|
|
} buf;
|
|
const int size = (w * 2) * (h * 2) * sizeof(uint32_t);
|
|
if (buf.size < size) {
|
|
free(buf.ptr);
|
|
buf.size = size;
|
|
buf.w = w * 2;
|
|
buf.h = h * 2;
|
|
buf.pitch = buf.w;
|
|
buf.ptr = (uint32_t *)malloc(buf.size);
|
|
if (!buf.ptr) {
|
|
error("Unable to allocate scale4x intermediate buffer");
|
|
}
|
|
}
|
|
scale2x(buf.ptr, buf.pitch, src, srcPitch, w, h);
|
|
scale2x(dst, dstPitch, buf.ptr, buf.pitch, buf.w, buf.h);
|
|
}
|
|
|
|
static void scaleNx(int factor, uint32_t *dst, int dstPitch, const uint32_t *src, int srcPitch, int w, int h) {
|
|
switch (factor) {
|
|
case 2:
|
|
return scale2x(dst, dstPitch, src, srcPitch, w, h);
|
|
case 3:
|
|
return scale3x(dst, dstPitch, src, srcPitch, w, h);
|
|
case 4:
|
|
return scale4x(dst, dstPitch, src, srcPitch, w, h);
|
|
}
|
|
}
|
|
|
|
const Scaler _internalScaler = {
|
|
SCALER_TAG,
|
|
"scaleNx",
|
|
2, 4,
|
|
scaleNx,
|
|
};
|
|
|
|
static DynLib *dynLib;
|
|
|
|
static const char *kSoSym = "getScaler";
|
|
|
|
const Scaler *findScaler(const char *name) {
|
|
dynLib = new DynLib(name);
|
|
void *symbol = dynLib->getSymbol(kSoSym);
|
|
if (symbol) {
|
|
typedef const Scaler *(*GetScalerProc)();
|
|
return ((GetScalerProc)symbol)();
|
|
}
|
|
return 0;
|
|
}
|