Scale2x algorithm that depixelizes and upscales low-resoluti

Share your advanced PureBasic knowledge/code with the community.
kvitaliy
Enthusiast
Enthusiast
Posts: 162
Joined: Mon May 10, 2010 4:02 pm

Scale2x algorithm that depixelizes and upscales low-resoluti

Post by kvitaliy »

EPX/Scale2×

Eric's Pixel Expansion (EPX) is an algorithm developed by Eric Johnston at LucasArts around 1992, when porting the SCUMM engine games from the IBM PC (which ran at 320×200×256 colors)
to the early color Macintosh computers, which ran at more or less double that resolution.The algorithm works as follows:

A --\ 1 2
C P B --/ 3 4
D
1=P; 2=P; 3=P; 4=P;
IF C==A => 1=A
IF A==B => 2=B
IF D==C => 3=C
IF B==D => 4=D
IF of A, B, C, D, three or more are identical: 1=2=3=4=P

Later implementations of this same algorithm (as AdvMAME2× and Scale2×, developed around 2001) have a slightly more efficient but functionally identical implementation:

A --\ 1 2
C P B --/ 3 4
D
1=P; 2=P; 3=P; 4=P;
IF C==A AND C!=D AND A!=B => 1=A
IF A==B AND A!=C AND B!=D => 2=B
IF D==C AND D!=B AND C!=A => 3=C
IF B==D AND B!=A AND D!=C => 4=D

PB code

Code: Select all

Macro S
  x-1,y-1
EndMacro
Macro U
  x+1,y-1
EndMacro
Macro R
  x-1,y+1
EndMacro
Macro Z
  x+1,y+1
EndMacro

Macro A
  x,y-1
EndMacro
Macro B
  x+1,y
EndMacro
Macro C
  x-1,y
EndMacro
Macro D
  x,y+1
EndMacro
Macro P
 x,y
EndMacro

Macro N1
  x*2,y*2
EndMacro

Macro N2
  x*2+1,y*2
EndMacro

Macro N3
  x*2,y*2+1
EndMacro

Macro N4
  x*2+1,y*2+1
EndMacro



Procedure Scale2x(Img)
;   A    --\ 1 2
; C P B  --/ 3 4
;   D 
;  1=P; 2=P; 3=P; 4=P;
;  IF C==A AND C!=D AND A!=B => 1=A
;  IF A==B AND A!=C AND B!=D => 2=B
;  IF B==D AND B!=A AND D!=C => 4=D
;  IF D==C AND D!=B AND C!=A => 3=C
  
  Dim Colors(ImageWidth(Img),ImageHeight(Img))
  Dim NewColors(ImageWidth(Img)*2,ImageHeight(Img)*2)
    StartDrawing( ImageOutput(Img))
       For y = 0 To ImageHeight(Img)-1
           For x =  0 To ImageWidth(Img) -1
              Colors(x,y) = Point(x, y)
           Next
       Next
     StopDrawing()
     
     
    For y = 1 To ImageHeight(Img) -1
      For x = 1 To ImageWidth(Img)-1
        
        NewColors(N1) = Colors(P):NewColors(N2) = Colors(P): NewColors(N3) = Colors(P):NewColors(N4)= Colors(P) 
        If Colors(C)=Colors(A) And Colors(C)<>Colors(D) And Colors(A)<>Colors(B):NewColors(N1) = Colors(A):EndIf
        If Colors(A)=Colors(B) And Colors(A)<>Colors(C) And Colors(B)<>Colors(D):NewColors(N2) = Colors(B):EndIf
        If Colors(B)=Colors(D) And Colors(B)<>Colors(A) And Colors(D)<>Colors(C):NewColors(N4) = Colors(D):EndIf
        If Colors(D)=Colors(C) And Colors(D)<>Colors(B) And Colors(C)<>Colors(A):NewColors(N3) = Colors(C):EndIf
        ;   optimized:
        ;   If (A != D && C != B) {
        ; 	E0 = C == A ? C : P;
        ; 	E1 = A == B ? B : P;
        ; 	E2 = C == D ? C : P;
        ; 	E3 = D == B ? B : P;
        ; } Else {
        ; 	E0 = P;
        ; 	E1 = P;
        ; 	E2 = P;
        ; 	E3 = P;
        
        
        If Colors(A)<>Colors(D) And Colors(C)<>Colors(B)
          If Colors(C)=Colors(A):NewColors(N1)=Colors(C):Else: NewColors(N1)=Colors(P):EndIf
          If Colors(A)=Colors(B):NewColors(N2)=Colors(B):Else: NewColors(N2)=Colors(P):EndIf
          If Colors(C)=Colors(D):NewColors(N3)=Colors(C):Else: NewColors(N3)=Colors(P):EndIf
          If Colors(D)=Colors(B):NewColors(N4)=Colors(B):Else: NewColors(N4)=Colors(P):EndIf
          
        Else
          NewColors(N1) = Colors(P):NewColors(N2) = Colors(P): NewColors(N3) = Colors(P):NewColors(N4)= Colors(P)
          
        EndIf
    
      Next
    Next
    
    img2=CreateImage(#PB_Any,ImageWidth(Img)*2,ImageHeight(Img)*2)
    StartDrawing( ImageOutput(img2))
    ;Box(0,0,ImageWidth(Img)*2,ImageHeight(Img)*2,Colors(0,0))
 For y = 2 To ImageHeight(img2) - 1
   For x = 2 To ImageWidth(img2) - 1
     Plot (x , y, NewColors(x,y))
    Next
 Next
 StopDrawing()
 GrabImage(img2,img3,2,2,ImageWidth(Img2)-3,ImageHeight(Img2)-3)
 ProcedureReturn img3
EndProcedure

Eagle
Eagle works as follows: for every in pixel we will generate 4 out pixels. First, set all 4 to the color of the in pixel we are currently scaling (as nearest-neighbor).
Next look at the three pixels above, to the left, and diagonally above left: if all three are the same color as each other, set the top left pixel of our output square to
that color in preference to the nearest-neighbor color. Work similarly for all four pixels, and then move to the next one.




first: |Then
. . . --\ CC |S T U --\ 1 2
. C . --/ CC |V C W --/ 3 4
. . . |X Y Z
| IF V==S==T => 1=S
| IF T==U==W => 2=U
| IF V==X==Y => 3=X
| IF W==Z==Y => 4=Z


PureBasic code

Code: Select all

Procedure Eagle(Img)
;  1=P; 2=P; 3=P; 4=P
  
; |S A U  --\ 1 2
; |C P B  --/ 3 4
; |R D Z
; | IF C==S==A => 1=S
; | IF A==U==B => 2=U
; | IF C==R==D => 3=R
; | IF B==Z==D => 4=Z
  
  Dim Colors(ImageWidth(Img),ImageHeight(Img))
  Dim NewColors(ImageWidth(Img)*2,ImageHeight(Img)*2)
    StartDrawing( ImageOutput(Img))
       For y = 0 To ImageHeight(Img)-1
           For x =  0 To ImageWidth(Img) -1
              Colors(x,y) = Point(x, y)
           Next
       Next
     StopDrawing()
  
    For y = 1 To ImageHeight(Img) - 1
      For x = 1 To ImageWidth(Img) - 1
        
        NewColors(N1) = Colors(P):NewColors(N2) = Colors(P): NewColors(N3) = Colors(P):NewColors(N4)= Colors(P) 
        If Colors(C)=Colors(S) And Colors(C)=Colors(A):NewColors(N1)=Colors(S):EndIf
        If Colors(A)=Colors(U) And Colors(A)=Colors(B):NewColors(N2)=Colors(U):EndIf
        If Colors(C)=Colors(R) And Colors(C)=Colors(D):NewColors(N3)=Colors(R):EndIf
        If Colors(B)=Colors(Z) And Colors(B)=Colors(D):NewColors(N4)=Colors(Z):EndIf
      Next
    Next
    
    img2=CreateImage(#PB_Any,ImageWidth(Img)*2,ImageHeight(Img)*2)
    StartDrawing( ImageOutput(img2))
    ;Box(0,0,ImageWidth(Img)*2,ImageHeight(Img)*2,Colors(0,0))
 For x = 2 To ImageWidth(img2) - 1
   For y = 2 To ImageHeight(img2) - 1
     Plot (x , y, NewColors(x,y))
   Next
 Next
 StopDrawing()
 GrabImage(img2,img3,2,2,ImageWidth(Img2)-3,ImageHeight(Img2)-3)
 ProcedureReturn img3
EndProcedure
Scale2x algorithm that depixelizes and upscales low-resolution 8-bit “pixel art”

Image

Before applying the algorithm

Image


Original image 30х40 pixels

Image

https://en.wikipedia.org/wiki/Pixel-art ... algorithms


Test code (zip file)
https://www.upload.ee/files/7972298/TestSprite.zip.html
User avatar
J. Baker
Addict
Addict
Posts: 2178
Joined: Sun Apr 27, 2003 8:12 am
Location: USA
Contact:

Re: Scale2x algorithm that depixelizes and upscales low-reso

Post by J. Baker »

Thanks for sharing the code but I prefer the pixels. ;)
www.posemotion.com

PureBasic Tools for OS X: PureMonitor, plist Tool, Data Maker & App Chef

Mac: 10.13.6 / 1.4GHz Core 2 Duo / 2GB DDR3 / Nvidia 320M
PC: Win 7 / AMD 64 4000+ / 3GB DDR / Nvidia 720GT


Even the vine knows it surroundings but the man with eyes does not.
kvitaliy
Enthusiast
Enthusiast
Posts: 162
Joined: Mon May 10, 2010 4:02 pm

Re: Scale2x algorithm that depixelizes and upscales low-reso

Post by kvitaliy »

J. Baker wrote: but I prefer the pixels. ;)
Ок! Many men, many minds. Tastes differ :D
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Scale2x algorithm that depixelizes and upscales low-reso

Post by wilbert »

Nice work :)

Looking at the Wikipedia page you mentioned, I was surprised by the quality of the hqnx family and the xBR family.
Windows (x64)
Raspberry Pi OS (Arm64)
walbus
Addict
Addict
Posts: 929
Joined: Sat Mar 02, 2013 9:17 am

Re: Scale2x algorithm that depixelizes and upscales low-reso

Post by walbus »

Very nice
Last edited by walbus on Fri Feb 02, 2018 6:26 pm, edited 1 time in total.
acreis
Enthusiast
Enthusiast
Posts: 182
Joined: Fri Jun 01, 2012 12:20 am

Re: Scale2x algorithm that depixelizes and upscales low-reso

Post by acreis »

Great! Thanks for sharing!
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5357
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: Scale2x algorithm that depixelizes and upscales low-reso

Post by Kwai chang caine »

Thanks for sharing 8)
ImageThe happiness is a road...
Not a destination
davido
Addict
Addict
Posts: 1890
Joined: Fri Nov 09, 2012 11:04 pm
Location: Uttoxeter, UK

Re: Scale2x algorithm that depixelizes and upscales low-reso

Post by davido »

Excellent! Thank you for sharing.
DE AA EB
Fred
Administrator
Administrator
Posts: 16688
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: Scale2x algorithm that depixelizes and upscales low-reso

Post by Fred »

Interesting upscale algo
walbus
Addict
Addict
Posts: 929
Joined: Sat Mar 02, 2013 9:17 am

Re: Scale2x algorithm that depixelizes and upscales low-reso

Post by walbus »

A little Hint
The procedure above is not runnable
kvitaliy
Enthusiast
Enthusiast
Posts: 162
Joined: Mon May 10, 2010 4:02 pm

Re: Scale2x algorithm that depixelizes and upscales low-reso

Post by kvitaliy »

walbus wrote:A little Hint
The procedure above is not runnable
For work it is necessary to take MACRO from the very first code
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Scale2x algorithm that depixelizes and upscales low-reso

Post by wilbert »

If performance is important, you probably could optimize things by not using Point and Plot.
Windows (x64)
Raspberry Pi OS (Arm64)
kvitaliy
Enthusiast
Enthusiast
Posts: 162
Joined: Mon May 10, 2010 4:02 pm

Re: Scale2x algorithm that depixelizes and upscales low-reso

Post by kvitaliy »

wilbert wrote:If performance is important, you probably could optimize things by not using Point and Plot.
I think that it is possible to optimize. But for me the principle of such work, rather than practical application, was more important.
If someone will bring this code to perfection, then I will be very happy!
walbus
Addict
Addict
Posts: 929
Joined: Sat Mar 02, 2013 9:17 am

Re: Scale2x algorithm that depixelizes and upscales low-reso

Post by walbus »

I meant that it is helpful if the posted codes are directly executable.

For the low resolutions on which it is based, doubling with point and plot should always be fast enough.
Post Reply