Post Reply 
Sprite encoding/decoding for compact graphics data
08-20-2015, 04:10 PM (This post was last modified: 08-21-2015 06:11 AM by komame.)
Post: #1
Sprite encoding/decoding for compact graphics data
Hello,

I just bought a HP Prime and after a few days getting to know the device I started writing my first game.
I was a little disgusted by the fact that the graphics occupies a lot of space. I know that flash memory in the HP Prime is large but in spite of this I started to look for a solution that will allow for more compact storage of graphics in the source code.
Normally in source code each character occupies two bytes because of UNICODE coding (16-bit per character).
Thus, using a list of integers for the DIMGROB_P each character takes also two bytes.
Every pixel needs 4 characters (HEX) to code, so one pixel takes 8 bytes in source code.

Reading the forums I have seen ideas to use STRING to store a more compact graphics data and then apply them (decode) to the GROB using PIXON_P.
I have not found a finished solution, so I decided to make my own, but instead of using the PIXON_P (which is slow I think) I wrote a solution that generates a list of integers to use with DIMGROB_P.

Since Unicode uses 16-bit per character I decided to use it.
We can use CHAR(x) to create characters that represent values from 1 to 65535 (2 bytes) and occupy in string only one character, so we can store 8 bytes in 4-character string:

2-byte integers: 4520, 8610, 9992, 12542.
Now we can store these integers in one string variable using CHAR command:
Code:
CHAR(4520)+CHAR(8610)+CHAR(9992)+CHAR(12542)▶z;

The z variable now cantains:
"ᆨ↢✈ヾ"

Now we can read these 16-bit integers from string variable using array index:
z(1) => we get 4520
z(2) => we get 8610
...

The low-byte and hi-byte from the integer we can get using BITAND and BITSR commands.
Following on from this we can encode four 4-bit values or eight 2-bit values in one character.
The only problem is that we can not store the value 0 (number zero) in the string variable because 0 is a special character that marks the end of a string. However, I found the solution to this problem.

I know there is also a command ICON. However, the size of image data is not as small as my method of coding. Besides, my method allows dynamic creation of images, which helps to create the animation.

I created a two pairs of functions. First is for encoding/decoding list of integers for DIMGROB_P (16-bit color), so you can use it in your finished programs where list of integers is used.

These functions names are: ESFC for encoding and DSFC for decoding.
When your program is already finished only the decoding function should remain in it.

At the moment there is no PC version, so (en/de)coding can be performed only on a calculator or emulator.

---
Example of use the first pair of functions:

In this example I used the stone sprite (16x16) from the Sokoban game.

The original code:
Code:
DIMGROB_P(G1,16,16, {#1084108451C74186:64,#1084108410841084:64,#1084108410841084:64,#312651C710​841084:64,#1084108410844186:64,#2D6B2D6B2D6B1CE7:64,#39CE2D6B2D6B2D6B:64,#312610​842D6B2D6B:64,#1CE71CE71CE71084:64,#1CE7108410841084:64,#2D6B2D6B1CE71CE7:64,#10​8439CE5EF739CE:64,#10841CE71CE71084:64,#10841CE72D6B2D6B:64,#5EF75EF739CE1CE7:64​,#10845EF75EF72D6B:64,#10842D6B1CE71084:64,#2D6B10841CE72D6B:64,#5EF739CE1CE739C​E:64,#10845EF75EF72D6B:64,#10842D6B1CE71084:64,#5EF739CE10841CE7:64,#39CE1CE739C​E5EF7:64,#10845EF75EF72D6B:64,#10842D6B1CE71084:64,#39CE39CE2D6B1084:64,#2D6B39C​E5EF75EF7:64,#10845EF75EF72D6B:64,#1CE72D6B1CE71084:64,#39CE39CE2D6B1084:64,#2D6​B5EF75EF739CE:64,#10845EF75EF739CE:64,#10842D6B1CE71084:64,#39CE2D6B10841CE7:64,​#39CE2D6B39CE39CE:64,#10845EF75EF72D6B:64,#10841CE71CE71084:64,#108410842D6B2D6B​:64,#5EF75EF72D6B2D6B:64,#10845EF739CE2D6B:64,#10841CE71CE71084:64,#2D6B39CE39CE​2D6B:64,#39CE39CE39CE2D6B:64,#10845EF739CE2D6B:64,#1CE710841CE71084:64,#39CE39CE​2D6B1CE7:64,#2D6B39CE39CE39CE:64,#10845EF72D6B39CE:64,#1CE710841CE71084:64,#2D6B​2D6B1CE72D6B:64,#39CE2D6B2D6B2D6B:64,#108439CE2D6B39CE:64,#1CE710841CE71084:64,#​2D6B2D6B2D6B1CE7:64,#39CE39CE2D6B2D6B:64,#108439CE2D6B39CE:64,#1CE71CE710844186:​64,#2D6B2D6B1CE71CE7:64,#39CE39CE39CE39CE:64,#4186108439CE39CE:64,#1084108441863​126:64,#1084108410841084:64,#1084108410841084:64,#3126312610841084:64});

Now you can encode the list of integers - just copy the list as a ESFC parameter:
ESFC({#1084108451C74186:64,#1084108410841084:64, ... ,#1084108410841084:64,#3126312610841084:64})
and you get strange string (lot of symbols and other characters).

Then copy the string and paste in the code as DSFC parameter instead of a list of integers.
It should look like this:

Code:
DIMGROB_P(G1,16,16,DSFC("還還퇇솆還還還還還還還還넦퇇還還還還還솆굫굫굫鳧많굫굫굫넦還굫굫鳧鳧鳧還鳧還還還굫굫鳧鳧還많?還鳧鳧還還鳧굫굫?많鳧還?굫還굫鳧還굫還鳧굫?鳧많還?굫還굫鳧還?​還鳧많鳧많??굫還굫鳧還많많굫還굫많?還?굫鳧굫鳧還많많굫還굫?많還?많還굫鳧還많굫還鳧많굫많많還?굫還鳧鳧還還還굫굫?굫굫還?굫還鳧鳧還굫많많굫많많많굫還?굫​鳧還鳧還많많굫鳧굫많많많還?많鳧還鳧還굫굫鳧굫많굫굫굫還많굫많鳧還鳧還굫굫굫鳧많많굫굫還많굫많鳧鳧還솆굫굫鳧鳧많많많많솆還많많還還솆넦還還還還還還還還넦넦還還"));

Of course the decoding function must be added to the program.

The list of integers before conversion takes 1345 characters (2690 bytes!!!).
After encoding to string it takes 241 characters (482 bytes), so we saved 2208 bytes.
Now one pixel is coded in only one character. Before conversion it was 4 characters.

Decoding function takes less than 240 characters, so even for one sprite it is worth using it.

Decoding time of 16x16 sprite average takes 77ms so it is quite fast.
Decoding should not be done on the fly, so it is best to perform the decoding at the initial stage of your program and the results put in the GROBs for later use.


OK, it's time for the second pair of functions.

The second pair is for encoding/decoding 15-color images (every pixel takes 4 bits), so the data graphics are even more compact, because you can store 4 pixels in one character.
We can not store 0 value, so 15 (not 16) colors are available.
I'm still working on this version, but I can show you the first effects.

The attached programs shows the full-color encoding/decoding (EncDecSpriteFC.hpprgm) and the 15-color sprites decoding (EncDecSprite15c.hpprgm).
In the second method there are five 14x14 sprites. After the encoding one sprite takes only 49 characters in the source code.
The encoding function I will write in the near future where as a parameter I will use list of colors or just matrix and color palette.
I have now a initial version of this function with string as input but it is to hard to use for now, so I want to refine it before I give you.

Best regards,
Piotr Kowalewski

P.S. What you see in the EncDecSprite15c.hpprgm is an early outline of what you will see in my game where I had planned to use animations... and sorry for my bad English Wink


Attached File(s)
.zip  Sprite_enc_dec.zip (Size: 2.02 KB / Downloads: 13)
Find all posts by this user
Quote this message in a reply
Post Reply 


Messages In This Thread
Sprite encoding/decoding for compact graphics data - komame - 08-20-2015 04:10 PM



User(s) browsing this thread: 1 Guest(s)