B4J Question Resize Picture - Nearest neighbor

Hypnos

Active Member
Licensed User
Longtime User
Anyone know how to resize a image using "Nearest neighbor" method ?
I try to use bitmap creator to resize an image but and output is not what I want.
 
Solution
The chicken test seems to be working. Using your before image, here is the after result of resizing to 16x16:

1704383290964.png


The code that did that is:

B4X:
Sub ResizeNN(SrcBmp As B4XBitmap, NewWidth As Int, NewHeight As Int) As B4XBitmap

    Dim SrcWidth As Int = SrcBmp.Width
    Dim SrcHeight As Int = SrcBmp.Height
     
    Dim srcbc As BitmapCreator    'old source image
    srcbc.Initialize(SrcWidth, SrcHeight)
    srcbc.CopyPixelsFromBitmap(SrcBmp)
 
    Dim newbc As BitmapCreator    'new destination image
    newbc.Initialize(NewWidth, NewHeight)

    Dim SrcX As Int
    Dim SrcY As Int
 
    'copy+resize from srcbc to newbc
    For NewX = 0 To NewWidth - 1
        For NewY = 0 To NewHeight - 1
            SrcX = (NewX * 2 + 1) *...

emexes

Expert
Licensed User
Nearest neighbor results can be pretty awful, both for upscaling and downscaling, and so perhaps this:
output is not what I want.
indicates bitmap creator is doing just what you asked for. I don't *know* for sure, but your assessment is what I'd expect if it is.

On a more positive note, if you really truly absolutely do want nearest neighbor, and you can live with "manual" code that does it pixel-by-pixel, then the math is pretty simple and I will happily bung up an example if you can't find a library function that already does it.
 
Last edited:
Upvote 0

Hypnos

Active Member
Licensed User
Longtime User
For my case, I got the best result in photoshop using "Nearest neighbor" (I'm down scaling a picture to a very small pixel art (e.g. 64x64, 32x32, 16x16).
Can you give me some sample code please? Thanks!

Picture below from left to right: Original Image -> Resize using Bitmap Creator -> Photoshop Resize (Nearest Neighbor)
Screenshot 2024-01-04 173233.png
 
Last edited:
Upvote 0

emexes

Expert
Licensed User
Resize using Bitmap Creator

That isn't nearest neighbour scaling. There should be no pixel colours in the destination that aren't in the source.

I have a vague recollection that bitmap creator coordinates are actually of the top-left of the pixel, rather than the centre, so there's that too.

I'll do it after dinner. I can give you a heads-up now, that the code will look like:

B4X:
For DX = 0 to DXSize - 1
    For DY = 0 to DYSize - 1
        SX = SXSize * (DX + 0.5) / DXSize
        SY = SYSize * (DY + 0.5) / DYSize
      
        Destination Pixel (DX, DY) = Source Pixel (SX, SY)
    Next DY
Next DX

although I suspect that might be out by the half-pixel coordinate offset too, so I'll have to play around with that

but at least it'll pass the "no pixel colours in destination that aren't in source" test
 
Last edited:
Upvote 0

emexes

Expert
Licensed User
The chicken test seems to be working. Using your before image, here is the after result of resizing to 16x16:

1704383290964.png


The code that did that is:

B4X:
Sub ResizeNN(SrcBmp As B4XBitmap, NewWidth As Int, NewHeight As Int) As B4XBitmap

    Dim SrcWidth As Int = SrcBmp.Width
    Dim SrcHeight As Int = SrcBmp.Height
     
    Dim srcbc As BitmapCreator    'old source image
    srcbc.Initialize(SrcWidth, SrcHeight)
    srcbc.CopyPixelsFromBitmap(SrcBmp)
 
    Dim newbc As BitmapCreator    'new destination image
    newbc.Initialize(NewWidth, NewHeight)

    Dim SrcX As Int
    Dim SrcY As Int
 
    'copy+resize from srcbc to newbc
    For NewX = 0 To NewWidth - 1
        For NewY = 0 To NewHeight - 1
            SrcX = (NewX * 2 + 1) * SrcWidth / (NewWidth * 2)    'can be hoisted up one line since doesn't change in inner loop
            SrcY = (NewY * 2 + 1) * SrcHeight / (NewHeight * 2)    
            newbc.SetColor(NewX, NewY, srcbc.GetColor(SrcX, SrcY))    'copy pixel
        Next
    Next

    Return newbc.Bitmap

End Sub
 
Last edited:
Upvote 0
Solution
Top