ok, got a new version, no need for the extra cleaner pass anymore. I also modified the algorithm so it properly works with equality thresholds. here is the download:
https://mega.co.nz/#!yYohhDCA!jgEe41OL5rueTLzSP3GMYIBaGgc7sjyfy95-8hb8KXc
for the interested reader I’m gonna explain both algorithms:
Scale2xSFX
if anyone used the original scale2x or EPX one can clearly notice single outstanding pixels here and there which are very annoying and the only drawback in my opinion for this method which otherwise pretty much keeps the pixelart style intact.
ok, why does these artifacts (see the first post in this thread for an example screen) come up? first, let’s give those pixels some names:
J
A B C E0 E1
K D E F L E2 E3
G H I
M
where E is the central pixel and E0 to E3 are the 4 subpixels of E (and A0 to A3 are the subpixels of A and so on).
well, let’s say E0 is the artifact pixel. what happened is that the condition to replace E0 is met simultaneously with the ones of B2 and D1. this implies (look at the original algorithm for that) that the surrounding pixels of E0 (which are E1, E2, B2 and D1) are all of the color E and therefore E0 itself is an outstanding pixel because it isn’t E anymore.
the way to fix this is obvious. just check if the conditions for B2 and D1 are also met, if that’s the case then don’t touch E0. well here is the original and the improved algorithm in pseudocode for comparison.
note: to allow the algorithm to work correctly with threshold comparisons the so called parent condition is slightly altered but still aquivalent to the original one in the case of true equality checks.
Scale2x
E0 = B=D & B!=F & D!=H ? 0.5*(B+D) : E
E1 = B=F & B!=D & F!=H ? 0.5*(B+F) : E
E2 = D=H & B!=D & F!=H ? 0.5*(D+H) : E
E3 = F=H & B!=F & D!=H ? 0.5*(F+H) : E
Scale2xSFX
E0 = B=D & B!=F & D!=H & (E!=A | E=C | E=G | A=J | A=K) ? 0.5*(B+D) : E
E1 = B=F & B!=D & F!=H & (E!=C | E=A | E=I | C=J | C=L) ? 0.5*(B+F) : E
E2 = D=H & B!=D & F!=H & (E!=G | E=A | E=I | G=K | G=M) ? 0.5*(D+H) : E
E3 = F=H & B!=F & D!=H & (E!=I | E=C | E=G | I=L | I=M) ? 0.5*(F+H) : E
the actual shader code looks a bit different due to subterm optimization.
Scale3xSFX
the cause of artifacts and how to prevent them is analogue to the case of Scale2x. the interesting flaw from Scale3x is that it doesn’t properly handle 45° lines, on those lines Scale3x only adds pixels but doesn’t “shave” them off. so to fix this we have to add another condition.
but first let’s have a look at the subpixels of E at scale factor 3:
J
A B C E0 E1 E2
K D E F L E3 E4 E5
G H I E6 E7 E8
M
again… A0 to A8 are the subpixels of A and so on.
okay, let’s say the pixels E, C and G are building a 45° line. then the condition for B8 and D8 is met but now at scale factor 3 E0 is standing out like a sore thumb. so to fix this we again use a very simple rule, just check if the condition for B8 or D8 is satisfied. if this is the case then “remove” E0 (replace it with B=D).
and here is the pseudocode comparison:
Scale3x
E4 = E
E0 = B=D & B!=F & D!=H ? 0.5*(B+D) : E
E2 = B=F & B!=D & F!=H ? 0.5*(B+F) : E
E6 = D=H & B!=D & F!=H ? 0.5*(D+H) : E
E8 = F=H & B!=F & D!=H ? 0.5*(F+H) : E
E1 = (B=D & B!=F & D!=H & E!=C) | (B=F & B!=D & F!=H & E!=A) ? B : E;
E3 = (B=D & B!=F & D!=H & E!=G) | (D=H & B!=D & F!=H & E!=A) ? D : E;
E5 = (B=F & B!=D & F!=H & E!=I) | (F=H & B!=F & D!=H & E!=C) ? F : E;
E7 = (D=H & B!=D & F!=H & E!=I) | (F=H & B!=F & D!=H & E!=G) ? H : E;
Scale3xSFX
E4 = E
E0 = (B=D & B!=F & D!=H & (E!=A | E=C | E=G | A=J | A=K)) | (B=D & C=E & C!=J & A!=E)
| (B=D & E=G & A!=E & G!=K) ? 0.5*(B+D) : E
E2 = (B=F & B!=D & F!=H & (E!=C | E=A | E=I | C=J | C=L)) | (B=F & A=E & A!=J & C!=E)
| (B=F & E=I & C!=E & I!=L) ? 0.5*(B+F) : E
E6 = (D=H & B!=D & F!=H & (E!=G | E=A | E=I | G=K | G=M)) | (D=H & A=E & A!=K & E!=G)
| (D=H & E=I & E!=G & I!=M) ? 0.5*(D+H) : E
E8 = (F=H & B!=F & D!=H & (E!=I | E=C | E=G | I=L | I=M)) | (F=H & C=E & C!=L & E!=I)
| (F=H & E=G & E!=I & G!=M) ? 0.5*(F+H) : E
E1 = (B=D & B!=F & D!=H & (E!=A | E=C | E=G | A=J | A=K) & E!=C)
| (B=F & B!=D & F!=H & (E!=C | E=A | E=I | C=J | C=L) & E!=A) ? B : E;
E3 = (B=D & B!=F & D!=H & (E!=A | E=C | E=G | A=J | A=K) & E!=G)
| (D=H & B!=D & F!=H & (E!=G | E=A | E=I | G=K | G=M) & E!=A) ? D : E;
E5 = (F=H & B!=F & D!=H & (E!=I | E=C | E=G | I=L | I=M) & E!=C)
| (B=F & B!=D & F!=H & (E!=C | E=A | E=I | C=J | C=L) & E!=I) ? F : E;
E7 = (F=H & B!=F & D!=H & (E!=I | E=C | E=G | I=L | I=M) & E!=G)
| (D=H & B!=D & F!=H & (E!=G | E=A | E=I | G=K | G=M) & E!=I) ? H : E;
for a more detailed explanation of the original algorithms go visit:
http://scale2x.sourceforge.net/