SyntaxBoom

Languages & Coding => BlitzMax (NG/Vanilla variants) => Topic started by: _PJ_ on Aug 09, 2025, 08:47 PM

Title: Int To Object
Post by: _PJ_ on Aug 09, 2025, 08:47 PM
(Technically this is NG issue, but I am assuming it is the same in "vanilla" BMax)

So I was wanting to automate the process of building a palette library for a bunch of sprite images (so I can later simplify the images and also do some code-based palette swapping etc)

but I ran into some issues with trying to make a list of the pixel values, as the TList commands refer to Object arguments.

Usually, Strings and whatever can simply recast as "Object" but not Integers it seems:::

Here's a simplified example:
Global Palette:TList

Local Image:TPixmap=LoadPixmap("Test.png")

For Local Y:Int= 0 Until Image.height
For Local X:Int= 0 Until Image.width
Local Pixel:Int=ReadPixel(Image,X,Y)
If ( Not (ExistInPalette(Pixel))) Then AddToPalette(Pixel)
Next
Next

DebugLog("Found "+Palette.Count()+" colours")


Function ExistInPalette:Byte(Pixel:Int)
If (Palette=Null) Then Return False
Return Palette.Contains(Pixel)
End Function

Function AddToPalette(Pixel:Int)
If (Palette=Null) Then Palette=New TList
Palette.AddLast(Pixel)
End Function

Working with an array may be easier, iterating through each array item, but I don't know how big the array may need to be in advance...
Title: Re: Int To Object
Post by: Sledge on Aug 09, 2025, 10:10 PM
You might be better off with an IntMap rather than a List:

https://blitzmax.org/docs/en/api/brl/brl.map/tintmap/

You could use the Int pixel values as keys (the actual value the key returns wouldn't really matter -- a string representation of the key would be my choice). You can check for a key before adding via Contains(), then at the end of the process get a collection of all the keys with Keys(), which would be your entire palette.

It's a bit of a weird case for a Map because the keys themselves are the values that you care about, but hey ho!
Title: Re: Int To Object
Post by: Midimaster on Aug 10, 2025, 12:56 AM
Local Image:TPixmap=LoadPixmap("Test.png")

For Local Y:Int= 0 Until Image.height
For Local X:Int= 0 Until Image.width
Local Pixel:Int=ReadPixel(Image,X,Y)
TPalette.Add Pixel
Next
Next

Type TPalette
Global List:TList= New TList
Field Pixel:Int

Function Add(Pixel:Int)
If Contains(Pixel)=True Then Return
Item:TPalette = New TPalette
Item.Pixel = Pixel
List.AddLast Item
End Function

Function Contains:Int(Pixel)
For Local Item:TPalette = EachIn List
If Item.Pixel=Pixel then Return True
Next
Return False
End Function
End Type
Title: Re: Int To Object
Post by: _PJ_ on Aug 10, 2025, 10:01 AM
Awesome!
Thanks so much for the qwuick replies :)

@Sledge I am not very familiar with the "Map" types and so was a little intimidated to try and risk overcomplicating and making things a lot worse - but thanks for the explanation - it would certainly be a neater approach!


@Midimaster - Thanks. I guess having the Pixel explicit cast as integer within the type scope and then using a custom iteration "contains" helps the compiler to interpret the Object?

What's funny as I originally wrote a function with similar iteration and equivalence check, but then changed it when I remembered the "contains" method :D
Title: Re: Int To Object
Post by: Midimaster on Aug 10, 2025, 10:54 AM
Quote...using a custom iteration "contains" helps the compiler to interpret the Object?...

No it is the Local x:Type EachIn, that picks only the searched type in a list.

If your list contains objects of different types then the code line...

QuoteFor Local Item:TPalette = EachIn List

... already casts and limits the iteration to only one type.
Title: Re: Int To Object
Post by: _PJ_ on Aug 10, 2025, 11:56 AM
Got it!

Thanks, Midimaster