B4J Question Map Bug?

techknight

Well-Known Member
Licensed User
Longtime User
So encountered an issue that I cant figure out how to work around.

So I am building an RGB palette index table. Easiest way is a Map, the RGB in hexstring as the Key, and the "index" as the value. so if I pass in the RGB, I can get the correct index back.

Anyways, Here is my code:
B4X:
    'Load Radar Palette
    Dim PaletteString As String = File.ReadString(File.DirAssets, "Radar.pal")
    Dim RadarPalette() As String = Regex.Split("#", PaletteString.ToUpperCase)
    'Dim RGBVal As String
    RadarImagePalette.Initialize
    For I = 0 To RadarPalette.Length-1
        RadarImagePalette.Put(RadarPalette(I), I)
    Next
 
    For Each k As String In RadarImagePalette.Keys
        Log(k)
        Log(RadarImagePalette.Get(k))
    Next

    Dim k As String = "000000" 'This is one of the values stored as a Key.
    Log(RadarImagePalette.Get(k)) 'Returns Null

Problem is, if I try to to a GET of anything, all I retrieve is null. No matter what RGB I try, that the routine above puts into the table. I did a Log in the loop to know that the key is there. But its not there...

I attached my palette text file.

any ideas?
 

Attachments

  • Radar.zip
    1.1 KB · Views: 103

Roycefer

Well-Known Member
Licensed User
Longtime User
Your text file has each item on its own line. That means each item is separated by a # and a CRLF. You are only splitting on # which means you are getting a CRLF at the end of each RadarPalette array item. Try this instead:
B4X:
RadarImagePalette.Put(RadarPalette(I).Trim, I) 'this will remove the CRLF before adding it to your Map.

In a broader context, consider storing your Maps with File.WriteMap and reading them with File.ReadMap instead of trying to split on Strings.
 
Upvote 0

emexes

Expert
Licensed User
Roycefer beat me to it, but try this anyway - effectively does the .Trim by filtering for hex digits/numbers only:
B4X:
'Load Radar Palette
Dim PaletteString As String = File.ReadString(File.DirAssets, "Radar.pal")

Dim HexMatcher As Matcher = Regex.Matcher("[0-9a-fA-F]+", PaletteString)

RadarImagePalette.Initialize
Dim IndexNumber As Int = 0
Do While HexMatcher.Find
    RadarImagePalette.Put(HexMatcher.Match.ToUpperCase, IndexNumber)
    IndexNumber = IndexNumber + 1
Loop

For Each k As String In RadarImagePalette.Keys
    Log(k)
    Log(RadarImagePalette.Get(k))
Next

Dim k As String = "000000" 'This is one of the values stored as a Key.
Log(RadarImagePalette.Get(k)) 'Returns Null - YE OF LITTLE FAITH ;-)
 
Last edited:
Upvote 0

emexes

Expert
Licensed User
Dim RadarPalette() As String = Regex.Split("#", PaletteString.ToUpperCase)
Or change the hex-number separator to be anything-but-hex:
B4X:
Dim RadarPalette() As String = Regex.Split("[^0-9a-fA-F]+", PaletteString.ToUpperCase)

edit: in fact, since the input string is obviously uppercase, you could even just:
B4X:
Dim RadarPalette() As String = Regex.Split("[^0-9A-F]+", PaletteString.ToUpperCase)
 
Upvote 0

techknight

Well-Known Member
Licensed User
Longtime User
Thanks for the ideas and programming efficiency thoughts. Ultimately, the CrLF was the problem.

It took me a complete re-write to get away from Maps and indexes to a plain Array just to figure that one out. LOL..... anyways, live and learn.

BTW the txt/pal file was generated by the Palette Export in GIMP, so thats how it puts out the files natively.
 
Upvote 0

emexes

Expert
Licensed User
While we're doing another lap on this topic, I'd like to present a revised one-line-change solution:
B4X:
Dim RadarPalette() As String = Regex.Split("[^0-9A-F]+", "#" & PaletteString.ToUpperCase & "#")
since the previous suggestion would return empty strings in the first and/or last elements of RadarPalette if there was a leading and/or trailing separator.

By adding a separator character front and back, we have made the situation more constant: the first and last elements are now *always* empty, and thus the actual palette is in elements 1..RadarPalette.Length-2 rather than the more usual/expected 0..RadarPalette.Length-1

edit: then I realised this is actually a three-line-change solution, because we need to update the For..Next loop and the Map Key, eg:
B4X:
For I = 1 To RadarPalette.Length - 2    'skip first and last elements since always empty
    RadarImagePalette.Put(RadarPalette(I - 1), I - 1)    'array and palette both zero-based, hence "- 1" for each
Next
Spewin!

But I'm not feeling too guilty, because the same problem would have been occurring with the original Regex.Split too :-/
 
Last edited:
Upvote 0

techknight

Well-Known Member
Licensed User
Longtime User
Well at least now I know there are multiple ways to skin a cat!

Anyways, the utility that does this takes an indexed GIF image and converts it into binary pixel array of index values. and the palette itself is extracted.

This gets sent to an older index color-based genlock graphics card run by a microcontroller.
 
Upvote 0
Top