Code archives/Algorithms/ScaleEX: Scaling filter for 2D pixel art
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
Scaling filter ala Scale2X, 2xSAI, SuperEagle, HQ2X etc. Great for scaling pixel art or other low-color/cartoony imagery. There are three versions: two of them (relatively) fast and one slow. Try'em all out, the slow one is generally better but this varies in some cases. Inspired by the EPX/Scale2X algorithms and Xenowhirl's and Screaming Duck's expanded versions. Big thanks to Jesse for optimising the code. Usage: For preloading images use it like this in your loading function: P.Pixmap = LoadPixmap("ImagePacks/Hero_Pack1.png") ScaleEX(P.Pixmap) P.Sheet1 = LoadImage(OutputPixmap) If you want to try it in realtime then do something like this in the main loop after all your screen drawing is complete: Local scr:TPixmap = GrabPixmap(0,0,WIDTH,HEIGHT) ScaleEX(scr) scaledscreen = LoadImage(Outputpixmap) DrawImage(scaledscreen,0,0) Flip It's too slow for realtime screenscaling for now, but that *might* change if I ever figure out how to convert the filter to a shader. | |||||
SuperStrict Function ScaleEX(PM:TPixmap) Local PMPixels: Int Ptr = Int Ptr(pm.pixels) Local Pix_W:Int = PixmapWidth(PM) Local Pix_H:Int = PixmapHeight(PM) Local x:Int Local y:Int Local yt:Int Local yb:Int Local xl:Int Local xr:Int Local yt2:Int Local yb2:Int Local xl2:Int Local xr2:Int Local ScaledPM:TPixmap = CreatePixmap(Pix_W*2,Pix_H*2,PF_RGBA8888) Local x2PMPixels:Int Ptr = Int Ptr (ScaledPM.pixels) Local x2Pix_W:Int = PixmapWidth(ScaledPM) Local x2Pix_H:Int = PixmapHeight(ScaledPM) Local P:Int Local A:Int Local B:Int Local C:Int Local D:Int Local FL:Int ' far left pixel (beside C) Local TR:Int ' top right pixel Local FR:Int ' far right pixel (beside B) Local TL:Int ' top left pixel Local FT:Int ' far top pixel Local FB:Int ' far bottom pixel Local BL:Int ' bottom left pixel Local BR:Int ' bottom right pixel Local P_1:Int ' output pixel top-left Local P_2:Int ' output pixel top-right Local P_3:Int ' output pixel bottom-left Local P_4:Int ' output pixel bottom-right ' RotSprite vars Local P_Clr:Int[4] ' 1 = R, 2 = G, 3 = B Local A_Clr:Int[4] ' 1 = R, 2 = G, 3 = B Local B_Clr:Int[4] ' 1 = R, 2 = G, 3 = B Local C_Clr:Int[4] ' 1 = R, 2 = G, 3 = B Local D_Clr:Int[4] ' 1 = R, 2 = G, 3 = B Local P_Value:Int ' holds average of RGB values Local A_Value:Int Local B_Value:Int Local C_Value:Int Local D_Value:Int ' go through all pixels in the image For x = 0 To Pix_W - 1 For y = 0 To Pix_H - 1 yt = (y-1)*Pix_W yb = (y+1)*Pix_W yt2 = (y-2)*Pix_W yb2 = (y+2)*Pix_W xl2 = (x-2) xr2 = (x+2) xl = x-1 xr = x+1 Local yc:Int = y*pix_W ' read the source pixel and its surrounding pixels P = PMPixels[yc+x] If x > 0 And x < Pix_W - 1 And y > 0 And y < Pix_H - 1 A = PMPixels[yt+x] B = PMPixels[yc+xr] C = PMPixels[yc+xl] D = PMPixels[yb+x] Else A = P B = P C = P D = P EndIf P_1 = P P_2 = P P_3 = P P_4 = P ' get colors P_Clr[1] = (P & $FF0000) Shr 16 ' red P_Clr[2] = (P & $FF00) Shr 8 ' green P_Clr[3] = (P & $FF) ' blue A_Clr[1] = (A & $FF0000) Shr 16 ' red A_Clr[2] = (A & $FF00) Shr 8 ' green A_Clr[3] = (A & $FF) ' blue B_Clr[1] = (B & $FF0000) Shr 16 ' red B_Clr[2] = (B & $FF00) Shr 8 ' green B_Clr[3] = (B & $FF) ' blue C_Clr[1] = (C & $FF0000) Shr 16 ' red C_Clr[2] = (C & $FF00) Shr 8 ' green C_Clr[3] = (C & $FF) ' blue D_Clr[1] = (D & $FF0000) Shr 16 ' red D_Clr[2] = (D & $FF00) Shr 8 ' green D_Clr[3] = (D & $FF) ' blue ' set average value from RGB P_Value = (P_Clr[1] + P_Clr[2] + P_Clr[3]) / 3 A_Value = (A_Clr[1] + A_Clr[2] + A_Clr[3]) / 3 B_Value = (B_Clr[1] + B_Clr[2] + B_Clr[3]) / 3 C_Value = (C_Clr[1] + C_Clr[2] + C_Clr[3]) / 3 D_Value = (D_Clr[1] + D_Clr[2] + D_Clr[3]) / 3 ' check for equal pixels around P and modify output pixels accordingly If B <> C And A <> D And (A = C Or A = B Or C = D Or B = D) ' if A = C then check far left and top right pixel to see if it's necessary ' to modify P_2 as well If A = C P_1 = A ' check pixel at far left and top right to see if stepping needs easing If x > 1 Then FL = PMPixels[yc+xl2] ' if FL = C then read another pixel: TR If FL = C If x < Pix_W - 1 And y > 0 Then TR = PMPixels[yt+xr] ' If both = A && C then set P_2 to be A as well. If FL = C And TR = A Then P_2 = A EndIf ' If FL is C and TR is A then we already know what to smooth here so ' we can skip checking for vertical stepping and save CPU load. But if not ' then do another check for P_3 to see if the bottom left and far top ' pixels are the same. If FL <> C Or TR <> A ' check pixel at far top and bottom left to see if stepping needs easing If x > 0 And y < Pix_H - 1 Then BL = PMPixels[yb+xl] If BL = C If y > 1 Then FT = PMPixels[yt2+x] ' If both = A && C then set P_3 to be C as well If BL = C And FT = A Then P_3 = C EndIf EndIf ' if A = B then check far right and top left pixel to see if it's necessary ' to modify P_1 as well ElseIf A = B P_2 = B If x < Pix_W - 2 Then FR = PMPixels[yc+xr2] If FR = B If x > 0 And y > 0 Then TL = PMPixels[yt+xl] If FR = B And TL = A Then P_1 = B EndIf If FR <> B Or TL <> A If x < Pix_W - 1 And y < Pix_H - 1 Then BR = PMPixels[yb+xr] If BR = B If y > 1 Then FT = PMPixels[yt2+x] If BR = B And FT = A Then P_4 = B EndIf EndIf ' if C = D then check far left and bottom right pixel to see if it's necessary ' to modify P_4 as well ElseIf C = D P_3 = C If x > 1 Then FL = PMPixels[yc+xl2] If FL = C If x > 0 And y < Pix_H - 1 Then BR = PMPixels[yb+xr] If FL = C And BR = D Then P_4 = C EndIf If FL <> C Or BR <> D If x > 0 And y > 0 Then TL = PMPixels[yt+xl] If TL = C If y < Pix_H - 2 Then FB = PMPixels[yb2+x] If TL = C And FB = D Then P_1 = C EndIf EndIf ' if B = D then check far right and bottom left pixel to see if it's necessary ' to modify P_3 as well ElseIf B = D P_4 = D If x < Pix_W - 2 Then FR = PMPixels[yc+xr2] If FR = B If x > 0 And y < Pix_H - 1 Then BL = PMPixels[yb+xl] If FR = B And BL = D Then P_3 = D EndIf If FR <> B Or BL <> D If x < Pix_W - 1 And y > 0 Then TR = PMPixels[yt+xr] If TR = B If y < Pix_H - 2 Then FB = PMPixels[yb2+x] If TR = B And FB = D Then P_2 = B EndIf EndIf EndIf EndIf ' if equal pixel conditions aren't met then check for similar pixels instead: If P_1 = P And A <> C ' P_1 is unmodified and A & C are similar but not equal ' if A is similar to C and very different from P then turn P_1 into C If A_Value < C_Value + 40 And A_Value > C_Value - 40 And (P_Value >= A_Value + 40 Or P_Value <= A_Value - 40) And B <> D And A <> B If A <> D And B <> C Then P_1 = C EndIf EndIf If P_2 = P And A <> B ' P_2 is unmodified and A & B are similar but not equal ' if B is similar to A and very different from P then turn P_2 into A If A_Value < B_Value + 40 And A_Value > B_Value - 40 And (P_Value >= B_Value + 40 Or P_Value <= B_Value - 40) And A <> C And B <> D If B <> C And A <> D Then P_2 = A EndIf EndIf If P_3 = P And C <> D ' P_3 is unmodified and C & D are similar but not equal ' if C is similar to D and very different from P then turn P_3 into D If D_Value < C_Value + 40 And D_Value > C_Value - 40 And (P_Value >= C_Value + 40 Or P_Value <= C_Value - 40) And B <> D And C <> A If A <> D And B <> C Then P_3 = D EndIf EndIf If P_4 = P And B <> D ' P_4 is unmodified and B & D are similar but not equal ' if D is similar to B and very different from P then turn P_4 into B If B_Value < D_Value + 40 And B_Value > D_Value - 40 And (P_Value >= D_Value + 40 Or P_Value <= D_Value - 40) And B <> A And D <> C If B <> C And A <> D Then P_4 = B EndIf EndIf x2PMPixels[(y*2 )*ScaledPM.Width+(x*2 )] = P_1 x2PMPixels[(y*2 )*ScaledPM.width+(x*2+1)] = P_2 x2PMPixels[(y*2+1)*ScaledPM.width+(x*2 )] = P_3 x2PMPixels[(y*2+1)*ScaledPM.Width+(x*2+1)] = P_4 Next Next OutputPixmap = ScaledPM End Function ' reads more pixels in some cases - smoother results and less artifacts at roughly the same speed Function ScaleEX_HQ(PM:TPixmap) Local PMPixels: Int Ptr = Int Ptr(pm.pixels) Local Pix_W:Int = PixmapWidth(PM) Local Pix_H:Int = PixmapHeight(PM) Local x:Int Local y:Int Local yt:Int Local yb:Int Local xl:Int Local xr:Int Local yt2:Int Local yb2:Int Local xl2:Int Local xr2:Int Local ScaledPM:TPixmap = CreatePixmap(Pix_W*2,Pix_H*2,PF_RGBA8888) Local x2PMPixels:Int Ptr = Int Ptr (ScaledPM.pixels) Local x2Pix_W:Int = PixmapWidth(ScaledPM) Local x2Pix_H:Int = PixmapHeight(ScaledPM) Local P:Int Local A:Int Local B:Int Local C:Int Local D:Int Local FL:Int ' far left pixel (beside C) Local TR:Int ' top right pixel Local FR:Int ' far right pixel (beside B) Local TL:Int ' top left pixel Local FT:Int ' far top pixel Local FB:Int ' far bottom pixel Local BL:Int ' bottom left pixel Local BR:Int ' bottom right pixel Local P_1:Int ' output pixel top-left Local P_2:Int ' output pixel top-right Local P_3:Int ' output pixel bottom-left Local P_4:Int ' output pixel bottom-right ' RotSprite vars Local P_Clr:Int[4] ' 1 = R, 2 = G, 3 = B Local A_Clr:Int[4] ' 1 = R, 2 = G, 3 = B Local B_Clr:Int[4] ' 1 = R, 2 = G, 3 = B Local C_Clr:Int[4] ' 1 = R, 2 = G, 3 = B Local D_Clr:Int[4] ' 1 = R, 2 = G, 3 = B Local P_Value:Int ' holds average of RGB values Local A_Value:Int Local B_Value:Int Local C_Value:Int Local D_Value:Int ' go through all pixels in the image For x = 0 To Pix_W - 1 For y = 0 To Pix_H - 1 yt = (y-1)*Pix_W yb = (y+1)*Pix_W yt2 = (y-2)*Pix_W yb2 = (y+2)*Pix_W xl2 = (x-2) xr2 = (x+2) xl = x-1 xr = x+1 Local yc:Int = y*pix_W ' read the source pixel and its surrounding pixels P = PMPixels[yc+x] If x > 0 And x < Pix_W - 1 And y > 0 And y < Pix_H - 1 A = PMPixels[yt+x] B = PMPixels[yc+xr] C = PMPixels[yc+xl] D = PMPixels[yb+x] Else A = P B = P C = P D = P EndIf P_1 = P P_2 = P P_3 = P P_4 = P ' get colors P_Clr[1] = (P & $FF0000) Shr 16 ' red P_Clr[2] = (P & $FF00) Shr 8 ' green P_Clr[3] = (P & $FF) ' blue A_Clr[1] = (A & $FF0000) Shr 16 ' red A_Clr[2] = (A & $FF00) Shr 8 ' green A_Clr[3] = (A & $FF) ' blue B_Clr[1] = (B & $FF0000) Shr 16 ' red B_Clr[2] = (B & $FF00) Shr 8 ' green B_Clr[3] = (B & $FF) ' blue C_Clr[1] = (C & $FF0000) Shr 16 ' red C_Clr[2] = (C & $FF00) Shr 8 ' green C_Clr[3] = (C & $FF) ' blue D_Clr[1] = (D & $FF0000) Shr 16 ' red D_Clr[2] = (D & $FF00) Shr 8 ' green D_Clr[3] = (D & $FF) ' blue ' set average value from RGB P_Value = (P_Clr[1] + P_Clr[2] + P_Clr[3]) / 3 A_Value = (A_Clr[1] + A_Clr[2] + A_Clr[3]) / 3 B_Value = (B_Clr[1] + B_Clr[2] + B_Clr[3]) / 3 C_Value = (C_Clr[1] + C_Clr[2] + C_Clr[3]) / 3 D_Value = (D_Clr[1] + D_Clr[2] + D_Clr[3]) / 3 ' check for equal pixels around P and modify output pixels accordingly If B <> C And A <> D And (A = C Or A = B Or C = D Or B = D) ' if A = C then check far left and top right pixel to see if it's necessary ' to modify P_2 as well If A = C P_1 = A ' check pixel at far left and top right to see if stepping needs easing If x > 1 Then FL = PMPixels[yc+xl2] ' if FL = C then read another pixel: TR If FL = C If x < Pix_W - 1 And y > 0 Then TR = PMPixels[yt+xr] ' If both = A && C then set P_2 to be A as well. If FL = C And TR = A Then P_2 = A EndIf ' If FL is C and TR is A then we already know what to smooth here so ' we can skip checking for vertical stepping and save CPU load. But if not ' then do another check for P_3 to see if the bottom left and far top ' pixels are the same. If FL <> C Or TR <> A ' check pixel at far top and bottom left to see if stepping needs easing If x > 0 And y < Pix_H - 1 Then BL = PMPixels[yb+xl] If BL = C If y > 1 Then FT = PMPixels[yt2+x] ' If both = A && C then set P_3 to be C as well If BL = C And FT = A Then P_3 = C EndIf EndIf ' if A = B then check far right and top left pixel to see if it's necessary ' to modify P_1 as well ElseIf A = B P_2 = B If x < Pix_W - 2 Then FR = PMPixels[yc+xr2] If FR = B If x > 0 And y > 0 Then TL = PMPixels[yt+xl] If FR = B And TL = A Then P_1 = B EndIf If FR <> B Or TL <> A If x < Pix_W - 1 And y < Pix_H - 1 Then BR = PMPixels[yb+xr] If BR = B If y > 1 Then FT = PMPixels[yt2+x] If BR = B And FT = A Then P_4 = B EndIf EndIf ' if C = D then check far left and bottom right pixel to see if it's necessary ' to modify P_4 as well ElseIf C = D P_3 = C If x > 1 Then FL = PMPixels[yc+xl2] If FL = C If x > 0 And y < Pix_H - 1 Then BR = PMPixels[yb+xr] If FL = C And BR = D Then P_4 = C EndIf If FL <> C Or BR <> D If x > 0 And y > 0 Then TL = PMPixels[yt+xl] If TL = C If y < Pix_H - 2 Then FB = PMPixels[yb2+x] If TL = C And FB = D Then P_1 = C EndIf EndIf ' if B = D then check far right and bottom left pixel to see if it's necessary ' to modify P_3 as well ElseIf B = D P_4 = D If x < Pix_W - 2 Then FR = PMPixels[yc+xr2] If FR = B If x > 0 And y < Pix_H - 1 Then BL = PMPixels[yb+xl] If FR = B And BL = D Then P_3 = D EndIf If FR <> B Or BL <> D If x < Pix_W - 1 And y > 0 Then TR = PMPixels[yt+xr] If TR = B If y < Pix_H - 2 Then FB = PMPixels[yb2+x] If TR = B And FB = D Then P_2 = B EndIf EndIf EndIf EndIf ' if equal pixel conditions aren't met then check for similar pixels instead: If P_1 = P And A <> C ' P_1 is unmodified and A & C are similar but not equal ' if A is similar to C and very different from P then turn P_1 into C If A_Value < C_Value + 40 And A_Value > C_Value - 40 And (P_Value >= A_Value + 40 Or P_Value <= A_Value - 40) And B <> D And A <> B If A <> D And B <> C ' check top-left pixel; only modify P_1 if TL <> P (no diagonal line from TL to P) If x > 0 And y > 0 Then TL = PMPixels[yt+xl] If TL <> P Then P_1 = C EndIf EndIf EndIf If P_2 = P And A <> B ' P_2 is unmodified and A & B are similar but not equal ' if B is similar to A and very different from P then turn P_2 into A If A_Value < B_Value + 40 And A_Value > B_Value - 40 And (P_Value >= B_Value + 40 Or P_Value <= B_Value - 40) And A <> C And B <> D If B <> C And A <> D ' check top-right pixel; only modify P_2 if TR <> P (no diagonal line from TR to P) If x < Pix_W - 1 And y > 0 Then TR = PMPixels[yt+xr] If TR <> P Then P_2 = A EndIf EndIf EndIf If P_3 = P And C <> D ' P_3 is unmodified and C & D are similar but not equal ' if C is similar to D and very different from P then turn P_3 into D If D_Value < C_Value + 40 And D_Value > C_Value - 40 And (P_Value >= C_Value + 40 Or P_Value <= C_Value - 40) And B <> D And C <> A If A <> D And B <> C ' check bottom-left pixel; only modify P_3 if BL <> P (no diagonal line from BL to P) If x > 0 And y < Pix_H - 1 Then BL = PMPixels[yb+xl] If BL <> P Then P_3 = D EndIf EndIf EndIf If P_4 = P And B <> D ' P_4 is unmodified and B & D are similar but not equal ' if D is similar to B and very different from P then turn P_4 into B If B_Value < D_Value + 40 And B_Value > D_Value - 40 And (P_Value >= D_Value + 40 Or P_Value <= D_Value - 40) And B <> A And D <> C If B <> C And A <> D ' check bottom-right pixel; only modify P_4 if BR <> P (no diagonal line from BR to P) If x < Pix_W - 1 And y < Pix_H - 1 Then BR = PMPixels[yb+xr] If BR <> P Then P_4 = B EndIf EndIf EndIf x2PMPixels[(y*2 )*ScaledPM.Width+(x*2 )] = P_1 x2PMPixels[(y*2 )*ScaledPM.width+(x*2+1)] = P_2 x2PMPixels[(y*2+1)*ScaledPM.width+(x*2 )] = P_3 x2PMPixels[(y*2+1)*ScaledPM.Width+(x*2+1)] = P_4 Next Next OutputPixmap = ScaledPM End Function ' smooths pixels by color groups instead of just RGB averages, ' generally smoother and less artifacty than ScaleEX_HQ but MUCH slower. Function ScaleEX_SQ(PM:TPixmap) Local PMPixels: Int Ptr = Int Ptr(pm.pixels) Local Pix_W:Int = PixmapWidth(PM) Local Pix_H:Int = PixmapHeight(PM) Local x:Int Local y:Int Local yt:Int Local yb:Int Local xl:Int Local xr:Int Local yt2:Int Local yb2:Int Local xl2:Int Local xr2:Int Local ScaledPM:TPixmap = CreatePixmap(Pix_W*2,Pix_H*2,PF_RGBA8888) Local x2PMPixels:Int Ptr = Int Ptr (ScaledPM.pixels) Local x2Pix_W:Int = PixmapWidth(ScaledPM) Local x2Pix_H:Int = PixmapHeight(ScaledPM) Local P:Int Local A:Int Local B:Int Local C:Int Local D:Int Local FL:Int ' far left pixel (beside C) Local TR:Int ' top right pixel Local FR:Int ' far right pixel (beside B) Local TL:Int ' top left pixel Local FT:Int ' far top pixel Local FB:Int ' far bottom pixel Local BL:Int ' bottom left pixel Local BR:Int ' bottom right pixel Local P_1:Int ' output pixel top-left Local P_2:Int ' output pixel top-right Local P_3:Int ' output pixel bottom-left Local P_4:Int ' output pixel bottom-right ' RotSprite vars Local P_Clr:Int[4] ' 1 = R, 2 = G, 3 = B Local A_Clr:Int[4] ' 1 = R, 2 = G, 3 = B Local B_Clr:Int[4] ' 1 = R, 2 = G, 3 = B Local C_Clr:Int[4] ' 1 = R, 2 = G, 3 = B Local D_Clr:Int[4] ' 1 = R, 2 = G, 3 = B Local P_Value:Int ' holds average of RGB values Local A_Value:Int Local B_Value:Int Local C_Value:Int Local D_Value:Int ' Sort by color Local Red:Int = 1 Local Orange:Int = 2 Local Yellow:Int = 3 Local Army:Int = 4 Local Green:Int = 5 Local Jade:Int = 6 Local Cyan:Int = 7 Local Azure:Int = 8 Local Blue:Int = 9 Local Indigo:Int = 10 Local Purple:Int = 11 Local Magenta:Int = 12 Local Grey:Int = 20 Local P_Class:Int Local A_Class:Int Local B_Class:Int Local C_Class:Int Local D_Class:Int ' go through all pixels in the image For x = 0 To Pix_W - 1 For y = 0 To Pix_H - 1 yt = (y-1)*Pix_W yb = (y+1)*Pix_W yt2 = (y-2)*Pix_W yb2 = (y+2)*Pix_W xl2 = (x-2) xr2 = (x+2) xl = x-1 xr = x+1 Local yc:Int = y*pix_W ' read the source pixel and its surrounding pixels P = PMPixels[yc+x] If x > 0 And x < Pix_W - 1 And y > 0 And y < Pix_H - 1 A = PMPixels[yt+x] B = PMPixels[yc+xr] C = PMPixels[yc+xl] D = PMPixels[yb+x] Else A = P B = P C = P D = P EndIf P_1 = P P_2 = P P_3 = P P_4 = P ' get colors P_Clr[1] = (P & $FF0000) Shr 16 ' red P_Clr[2] = (P & $FF00) Shr 8 ' green P_Clr[3] = (P & $FF) ' blue A_Clr[1] = (A & $FF0000) Shr 16 ' red A_Clr[2] = (A & $FF00) Shr 8 ' green A_Clr[3] = (A & $FF) ' blue B_Clr[1] = (B & $FF0000) Shr 16 ' red B_Clr[2] = (B & $FF00) Shr 8 ' green B_Clr[3] = (B & $FF) ' blue C_Clr[1] = (C & $FF0000) Shr 16 ' red C_Clr[2] = (C & $FF00) Shr 8 ' green C_Clr[3] = (C & $FF) ' blue D_Clr[1] = (D & $FF0000) Shr 16 ' red D_Clr[2] = (D & $FF00) Shr 8 ' green D_Clr[3] = (D & $FF) ' blue ' set average value from RGB P_Value = (P_Clr[1] + P_Clr[2] + P_Clr[3]) / 3 A_Value = (A_Clr[1] + A_Clr[2] + A_Clr[3]) / 3 B_Value = (B_Clr[1] + B_Clr[2] + B_Clr[3]) / 3 C_Value = (C_Clr[1] + C_Clr[2] + C_Clr[3]) / 3 D_Value = (D_Clr[1] + D_Clr[2] + D_Clr[3]) / 3 ' get color class ' red If A_Clr[1] > A_Clr[2] + 21 And A_Clr[1] > A_Clr[3] + 21 And (A_Clr[2] < A_Clr[3] + 21 And A_Clr[2] > A_Clr[3] - 21) Then A_Class = Red ' orange If A_Clr[1] > A_Clr[3] + 21 And A_Clr[2] <= A_Clr[1] - 21 And A_Clr[2] >= A_Clr[3] + 21 Then A_Class = Orange ' yellow If A_Clr[1] <= A_Clr[2] + 21 And A_Clr[1] >= A_Clr[2] - 21 And A_Clr[1] >= A_Clr[3] + 21 Then A_Class = Yellow ' army green If A_Clr[2] > A_Clr[3] + 21 And A_Clr[1] <= A_Clr[2] - 21 And A_Clr[1] >= A_Clr[3] + 21 Then A_Class = Army ' green If A_Clr[2] > A_Clr[1] + 21 And A_Clr[2] > A_Clr[3] + 21 And (A_Clr[1] < A_Clr[3] + 21 And A_Clr[1] > A_Clr[3] - 21) Then A_Class = Green ' jade green If A_Clr[2] > A_Clr[1] + 21 And A_Clr[3] <= A_Clr[2] - 21 And A_Clr[3] >= A_Clr[1] + 21 Then A_Class = Jade ' Cyan If A_Clr[2] <= A_Clr[3] + 21 And A_Clr[2] >= A_Clr[3] - 21 And A_Clr[3] >= A_Clr[1] + 21 Then A_Class = Cyan ' Azure blue If A_Clr[3] > A_Clr[1] + 21 And A_Clr[2] <= A_Clr[3] - 21 And A_Clr[2] >= A_Clr[1] + 21 Then A_Class = Azure ' blue If A_Clr[3] > A_Clr[2] + 21 And A_Clr[3] > A_Clr[1] + 21 And (A_Clr[1] < A_Clr[2] + 21 And A_Clr[1] > A_Clr[2] - 21) Then A_Class = Blue ' indigo If A_Clr[3] > A_Clr[2] + 21 And A_Clr[1] <= A_Clr[3] - 21 And A_Clr[1] >= A_Clr[2] + 21 Then A_Class = Indigo ' purple If A_Clr[1] <= A_Clr[3] + 21 And A_Clr[1] >= A_Clr[3] - 21 And A_Clr[1] >= A_Clr[2] + 21 Then A_Class = Purple ' magenta If A_Clr[1] > A_Clr[2] + 21 And A_Clr[3] <= A_Clr[1] - 21 And A_Clr[3] >= A_Clr[2] + 21 Then A_Class = Magenta ' greyscales (includes desaturated colors) If A_Clr[1] <= A_Clr[2] + 21 And A_Clr[1] >= A_Clr[2] - 21 And A_Clr[1] <= A_Clr[3] + 21 And A_Clr[1] >= A_Clr[3] - 21 Then A_Class = Grey ' red If B_Clr[1] > B_Clr[2] + 21 And B_Clr[1] > B_Clr[3] + 21 And (B_Clr[2] < B_Clr[3] + 21 And B_Clr[2] > B_Clr[3] - 21) Then B_Class = Red ' orange If B_Clr[1] > B_Clr[3] + 21 And B_Clr[2] <= B_Clr[1] - 21 And B_Clr[2] >= B_Clr[3] + 21 Then B_Class = Orange ' yellow If B_Clr[1] <= B_Clr[2] + 21 And B_Clr[1] >= B_Clr[2] - 21 And B_Clr[1] >= B_Clr[3] + 21 Then B_Class = Yellow ' army green If B_Clr[2] > B_Clr[3] + 21 And B_Clr[1] <= B_Clr[2] - 21 And B_Clr[1] >= B_Clr[3] + 21 Then B_Class = Army ' green If B_Clr[2] > B_Clr[1] + 21 And B_Clr[2] > B_Clr[3] + 21 And (B_Clr[1] < B_Clr[3] + 21 And B_Clr[1] > B_Clr[3] - 21) Then B_Class = Green ' jade green If B_Clr[2] > B_Clr[1] + 21 And B_Clr[3] <= B_Clr[2] - 21 And B_Clr[3] >= B_Clr[1] + 21 Then B_Class = Jade ' Cyan If B_Clr[2] <= B_Clr[3] + 21 And B_Clr[2] >= B_Clr[3] - 21 And B_Clr[3] >= B_Clr[1] + 21 Then B_Class = Cyan ' Azure blue If B_Clr[3] > B_Clr[1] + 21 And B_Clr[2] <= B_Clr[3] - 21 And B_Clr[2] >= B_Clr[1] + 21 Then B_Class = Azure ' blue If B_Clr[3] > B_Clr[2] + 21 And B_Clr[3] > B_Clr[1] + 21 And (B_Clr[1] < B_Clr[2] + 21 And B_Clr[1] > B_Clr[2] - 21) Then B_Class = Blue ' indigo If B_Clr[3] > B_Clr[2] + 21 And B_Clr[1] <= B_Clr[3] - 21 And B_Clr[1] >= B_Clr[2] + 21 Then B_Class = Indigo ' purple If B_Clr[1] <= B_Clr[3] + 21 And B_Clr[1] >= B_Clr[3] - 21 And B_Clr[1] >= B_Clr[2] + 21 Then B_Class = Purple ' magenta If B_Clr[1] > B_Clr[2] + 21 And B_Clr[3] <= B_Clr[1] - 21 And B_Clr[3] >= B_Clr[2] + 21 Then B_Class = Magenta ' greyscales (includes desaturated colors) If B_Clr[1] <= B_Clr[2] + 21 And B_Clr[1] >= B_Clr[2] - 21 And B_Clr[1] <= B_Clr[3] + 21 And B_Clr[1] >= B_Clr[3] - 21 Then B_Class = Grey ' red If C_Clr[1] > C_Clr[2] + 21 And C_Clr[1] > C_Clr[3] + 21 And (C_Clr[2] < C_Clr[3] + 21 And C_Clr[2] > C_Clr[3] - 21) Then C_Class = Red ' orange If C_Clr[1] > C_Clr[3] + 21 And C_Clr[2] <= C_Clr[1] - 21 And C_Clr[2] >= C_Clr[3] + 21 Then C_Class = Orange ' yellow If C_Clr[1] <= C_Clr[2] + 21 And C_Clr[1] >= C_Clr[2] - 21 And C_Clr[1] >= C_Clr[3] + 21 Then C_Class = Yellow ' army green If C_Clr[2] > C_Clr[3] + 21 And C_Clr[1] <= C_Clr[2] - 21 And C_Clr[1] >= C_Clr[3] + 21 Then C_Class = Army ' green If C_Clr[2] > C_Clr[1] + 21 And C_Clr[2] > C_Clr[3] + 21 And (C_Clr[1] < C_Clr[3] + 21 And C_Clr[1] > C_Clr[3] - 21) Then C_Class = Green ' jade green If C_Clr[2] > C_Clr[1] + 21 And C_Clr[3] <= C_Clr[2] - 21 And C_Clr[3] >= C_Clr[1] + 21 Then C_Class = Jade ' Cyan If C_Clr[2] <= C_Clr[3] + 21 And C_Clr[2] >= C_Clr[3] - 21 And C_Clr[3] >= C_Clr[1] + 21 Then C_Class = Cyan ' Azure blue If C_Clr[3] > C_Clr[1] + 21 And C_Clr[2] <= C_Clr[3] - 21 And C_Clr[2] >= C_Clr[1] + 21 Then C_Class = Azure ' blue If C_Clr[3] > C_Clr[2] + 21 And C_Clr[3] > C_Clr[1] + 21 And (C_Clr[1] < C_Clr[2] + 21 And C_Clr[1] > C_Clr[2] - 21) Then C_Class = Blue ' indigo If C_Clr[3] > C_Clr[2] + 21 And C_Clr[1] <= C_Clr[3] - 21 And C_Clr[1] >= C_Clr[2] + 21 Then C_Class = Indigo ' purple If C_Clr[1] <= C_Clr[3] + 21 And C_Clr[1] >= C_Clr[3] - 21 And C_Clr[1] >= C_Clr[2] + 21 Then C_Class = Purple ' magenta If C_Clr[1] > C_Clr[2] + 21 And C_Clr[3] <= C_Clr[1] - 21 And C_Clr[3] >= C_Clr[2] + 21 Then C_Class = Magenta ' greyscales (includes desaturated colors) If C_Clr[1] <= C_Clr[2] + 21 And C_Clr[1] >= C_Clr[2] - 21 And C_Clr[1] <= C_Clr[3] + 21 And C_Clr[1] >= C_Clr[3] - 21 Then C_Class = Grey ' red If D_Clr[1] > D_Clr[2] + 21 And D_Clr[1] > D_Clr[3] + 21 And (D_Clr[2] < D_Clr[3] + 21 And D_Clr[2] > D_Clr[3] - 21) Then D_Class = Red ' orange If D_Clr[1] > D_Clr[3] + 21 And D_Clr[2] <= D_Clr[1] - 21 And D_Clr[2] >= D_Clr[3] + 21 Then D_Class = Orange ' yellow If D_Clr[1] <= D_Clr[2] + 21 And D_Clr[1] >= D_Clr[2] - 21 And D_Clr[1] >= D_Clr[3] + 21 Then D_Class = Yellow ' army green If D_Clr[2] > D_Clr[3] + 21 And D_Clr[1] <= D_Clr[2] - 21 And D_Clr[1] >= D_Clr[3] + 21 Then D_Class = Army ' green If D_Clr[2] > D_Clr[1] + 21 And D_Clr[2] > D_Clr[3] + 21 And (D_Clr[1] < D_Clr[3] + 21 And D_Clr[1] > D_Clr[3] - 21) Then D_Class = Green ' jade green If D_Clr[2] > D_Clr[1] + 21 And D_Clr[3] <= D_Clr[2] - 21 And D_Clr[3] >= D_Clr[1] + 21 Then D_Class = Jade ' Cyan If D_Clr[2] <= D_Clr[3] + 21 And D_Clr[2] >= D_Clr[3] - 21 And D_Clr[3] >= D_Clr[1] + 21 Then D_Class = Cyan ' Azure blue If D_Clr[3] > D_Clr[1] + 21 And D_Clr[2] <= D_Clr[3] - 21 And D_Clr[2] >= D_Clr[1] + 21 Then D_Class = Azure ' blue If D_Clr[3] > D_Clr[2] + 21 And D_Clr[3] > D_Clr[1] + 21 And (D_Clr[1] < D_Clr[2] + 21 And D_Clr[1] > D_Clr[2] - 21) Then D_Class = Blue ' indigo If D_Clr[3] > D_Clr[2] + 21 And D_Clr[1] <= D_Clr[3] - 21 And D_Clr[1] >= D_Clr[2] + 21 Then D_Class = Indigo ' purple If D_Clr[1] <= D_Clr[3] + 21 And D_Clr[1] >= D_Clr[3] - 21 And D_Clr[1] >= D_Clr[2] + 21 Then D_Class = Purple ' magenta If D_Clr[1] > D_Clr[2] + 21 And D_Clr[3] <= D_Clr[1] - 21 And D_Clr[3] >= D_Clr[2] + 21 Then D_Class = Magenta ' greyscales (includes desaturated colors) If D_Clr[1] <= D_Clr[2] + 21 And D_Clr[1] >= D_Clr[2] - 21 And D_Clr[1] <= D_Clr[3] + 21 And D_Clr[1] >= D_Clr[3] - 21 Then D_Class = Grey ' check for equal pixels around P and modify output pixels accordingly If B <> C And A <> D And (A = C Or A = B Or C = D Or B = D) ' if A = C then check far left and top right pixel to see if it's necessary ' to modify P_2 as well If A = C P_1 = A ' check pixel at far left and top right to see if stepping needs easing If x > 1 Then FL = PMPixels[yc+xl2] ' if FL = C then read another pixel: TR If FL = C If x < Pix_W - 1 And y > 0 Then TR = PMPixels[yt+xr] ' If both = A && C then set P_2 to be A as well. If FL = C And TR = A Then P_2 = A EndIf ' If FL is C and TR is A then we already know what to smooth here so ' we can skip checking for vertical stepping and save CPU load. But if not ' then do another check for P_3 to see if the bottom left and far top ' pixels are the same. If FL <> C Or TR <> A ' check pixel at far top and bottom left to see if stepping needs easing If x > 0 And y < Pix_H - 1 Then BL = PMPixels[yb+xl] If BL = C If y > 1 Then FT = PMPixels[yt2+x] ' If both = A && C then set P_3 to be C as well If BL = C And FT = A Then P_3 = C EndIf EndIf ' if A = B then check far right and top left pixel to see if it's necessary ' to modify P_1 as well ElseIf A = B P_2 = B If x < Pix_W - 2 Then FR = PMPixels[yc+xr2] If FR = B If x > 0 And y > 0 Then TL = PMPixels[yt+xl] If FR = B And TL = A Then P_1 = B EndIf If FR <> B Or TL <> A If x < Pix_W - 1 And y < Pix_H - 1 Then BR = PMPixels[yb+xr] If BR = B If y > 1 Then FT = PMPixels[yt2+x] If BR = B And FT = A Then P_4 = B EndIf EndIf ' if C = D then check far left and bottom right pixel to see if it's necessary ' to modify P_4 as well ElseIf C = D P_3 = C If x > 1 Then FL = PMPixels[yc+xl2] If FL = C If x > 0 And y < Pix_H - 1 Then BR = PMPixels[yb+xr] If FL = C And BR = D Then P_4 = C EndIf If FL <> C Or BR <> D If x > 0 And y > 0 Then TL = PMPixels[yt+xl] If TL = C If y < Pix_H - 2 Then FB = PMPixels[yb2+x] If TL = C And FB = D Then P_1 = C EndIf EndIf ' if B = D then check far right and bottom left pixel to see if it's necessary ' to modify P_3 as well ElseIf B = D P_4 = D If x < Pix_W - 2 Then FR = PMPixels[yc+xr2] If FR = B If x > 0 And y < Pix_H - 1 Then BL = PMPixels[yb+xl] If FR = B And BL = D Then P_3 = D EndIf If FR <> B Or BL <> D If x < Pix_W - 1 And y > 0 Then TR = PMPixels[yt+xr] If TR = B If y < Pix_H - 2 Then FB = PMPixels[yb2+x] If TR = B And FB = D Then P_2 = B EndIf EndIf EndIf EndIf ' if equal pixel conditions aren't met then check for similar pixels instead: If P_1 = P And A <> C ' P_1 is unmodified and A & C are similar but not equal ' if A is similar to C and very different from P then turn P_1 into C If A_Value < C_Value + 70 And A_Value > C_Value - 70 And ((P_Value >= A_Value + 70 Or P_Value <= A_Value - 70) Or (P_Value >= C_Value + 70 Or P_Value <= C_Value - 70)) And B <> D And A <> B If A <> D And B <> C And (A_Class <= C_Class + 1 And (A_Class >= C_Class - 1 And C_Class >= 1)) ' same color? ' check top-left pixel; only modify P_1 if TL <> P (no diagonal line from TL to P) If x > 0 And y > 0 Then TL = PMPixels[yt+xl] If TL <> P Then P_1 = C EndIf EndIf EndIf If P_2 = P And A <> B ' P_2 is unmodified and A & B are similar but not equal ' if B is similar to A and very different from P then turn P_2 into A If A_Value < B_Value + 70 And A_Value > B_Value - 70 And ((P_Value >= B_Value + 70 Or P_Value <= B_Value - 70) Or (P_Value >= B_Value + 70 Or P_Value <= B_Value - 70)) And A <> C And B <> D If B <> C And A <> D And (A_Class <= B_Class + 1 And (A_Class >= B_Class - 1 And B_Class >= 1)) ' same color? ' check top-right pixel; only modify P_2 if TR <> P (no diagonal line from TR to P) If x < Pix_W - 1 And y > 0 Then TR = PMPixels[yt+xr] If TR <> P Then P_2 = A EndIf EndIf EndIf If P_3 = P And C <> D ' P_3 is unmodified and C & D are similar but not equal ' if C is similar to D and very different from P then turn P_3 into D If D_Value < C_Value + 70 And D_Value > C_Value - 70 And ((P_Value >= C_Value + 70 Or P_Value <= C_Value - 70) Or (P_Value >= D_Value + 70 Or P_Value <= D_Value - 70)) And B <> D And C <> A If A <> D And B <> C And P_1 <> C And P_2 <> A And (C_Class <= D_Class + 1 And (C_Class >= D_Class - 1 And D_Class >= 1)) ' same color? ' check bottom-left pixel; only modify P_3 if BL <> P (no diagonal line from BL to P) If x > 0 And y < Pix_H - 1 Then BL = PMPixels[yb+xl] If BL <> P Then P_3 = D EndIf EndIf EndIf If P_4 = P And B <> D ' P_4 is unmodified and B & D are similar but not equal ' if D is similar to B and very different from P then turn P_4 into B If B_Value < D_Value + 70 And B_Value > D_Value - 70 And ((P_Value >= D_Value + 70 Or P_Value <= D_Value - 70) Or (P_Value >= B_Value + 70 Or P_Value <= B_Value - 70)) And B <> A And D <> C If B <> C And A <> D And P_1 <> C And P_2 <> A And (B_Class <= D_Class + 1 And (B_Class >= D_Class - 1 And D_Class >= 1)) ' same color? ' check bottom-right pixel; only modify P_4 if BR <> P (no diagonal line from BR to P) If x < Pix_W - 1 And y < Pix_H - 1 Then BR = PMPixels[yb+xr] If BR <> P Then P_4 = B EndIf EndIf EndIf x2PMPixels[(y*2 )*ScaledPM.Width+(x*2 )] = P_1 x2PMPixels[(y*2 )*ScaledPM.width+(x*2+1)] = P_2 x2PMPixels[(y*2+1)*ScaledPM.width+(x*2 )] = P_3 x2PMPixels[(y*2+1)*ScaledPM.Width+(x*2+1)] = P_4 Next Next OutputPixmap = ScaledPM End Function Global InputPixmap:TPixmap = LoadPixmap("input.bmp") ' alpha'ed pngs also work inputpixmap = inputPixmap.convert(PF_RGBA8888) Global OutputPixmap:TPixmap Global TestImg:TImage Graphics 800,600,32 Local secs:Int= MilliSecs() ScaleEX(InputPixmap) Print MilliSecs() - secs TestImg = LoadImage(OutputPixmap) While Not KeyDown(KEY_ESCAPE) Cls DrawImage(TestImg,0,0) Flip Wend End |
Comments
| ||
great! THX |
| ||
I LOVE this. |
Code Archives Forum