| |
TWW
Registered: Jul 2009 Posts: 545 |
Kickassembler - Converting .PNG to Koala
Hey fellow hackers.
I wanted to write a converter in Kickassembler which can take any .PNG MC Bitmap screenshot from VICE (Then I don't need to worry about the RGB values since they are known) and convert into raw data you can use in your productions.
This is the way I imagine doing it:
#1 - Determin the background collor based on the most used collor in the picture
#2 - Verify there is no 4x8 block containing more than 3 collors+BG
#3 - Convert each 4x8 block afterwards and write the data into 3 lists (1 for BMP data, 1 for Charcollors and 1 for collmem).
#4 - Add BG collor at the end :-)
I'm looking for improvement comments on this or maybee I need to revise the way I think about this? |
|
... 37 posts hidden. Click here to view all posts.... |
| |
enthusi
Registered: May 2004 Posts: 677 |
The approach to brute force BG has the advantage that you can as well convert pictures that do not match MCbitmap restrictions that way (weighting via least_clashes, etc...).
In general I personally dislike the idea to integrate such things into kickassembler (or any assembler).
I dont like the simplified interface to implement SID files already. I see hordes of beginners to not get what's working why and how.
But then again, that might just be me thinking that way.
PS:
You can aswell use vice-dumps directly if your method relies on vice bitmaps anyway. There you can simply read out all colors. Check here i.e.:
Vice Snapshot Grabber 4.2 |
| |
Cruzer
Registered: Dec 2001 Posts: 1048 |
I personally think it's a better idea to have as much import, convert and precalc functionality as an assembler script, since it's much easier to customize for the situation than external tools, which also have a tendency to be windows-only, unlike KickAssembler. The only drawback is that it slows down the assembly time if it's too complex. In these cases I usually save the generated data when it has reached a usable state, and have an option to turn on/off whether to load or regenerate it. |
| |
TWW
Registered: Jul 2009 Posts: 545 |
I'm with Cruiser on this one. I've been coding assembler on the 64 since the late eigthies so if I can't figgure that part out then screw it :-) Perhaps for a beginner it would be more prudent to do it the hard way but I'm past that stage and I want it as easy and fast as possible.
There are too many small tools and stuff anyway so why not implement some of the trivial ones yourself. This way I get a chance to learn more about script language in the process^^
I don't know about the sid stuff though. |
| |
enthusi
Registered: May 2004 Posts: 677 |
Sorry, dont get me wrong: Coding something like Kickassembler is extremely cool ;-) But that differs from my opinion about its existance :) |
| |
TWW
Registered: Jul 2009 Posts: 545 |
Alright, this is what I got so far. It seems to be working but I have feeling it is extreemly bloated. Could some script guru take a look ang give me some pointers is something is done bad/wrong/unoptimized?
(Assuming collor palette is pre-defined)
.macro PNGtoKOALA(PNGpicture,BMPdata,Chardata,D800data) {
// Hastable for storing 4x8 collordata
.var BlockCollors = Hashtable()
// Hash table for holding potential BackGround Collors from a block
.var BG = Hashtable()
// Hashtable for keeping track of candidates
.var BGCandidate = Hashtable()
// Declare some variables
.var Id = 0
.var CurrentBlock = 0
.var BGRemaining = 4
.var CollCounter = 0
.var FirstMatch = true
.var i = 0
// Load the picture into gfx
.var gfx = LoadPicture(PNGpicture,List())
// Block Pointer Variable
.for (CurrentBlock=0 ; CurrentBlock<1000&&BGRemaining > 1 ; CurrentBlock++) {
// Fetch 4x8 pixel block collors
.for (var Id = 0 ; Id < 32 ; Id++) {
.var PixelCollor = gfx.getPixel([8*CurrentBlock+[[Id<<1]&7]]-[320*[floor(CurrentBlock/40)]], [8*floor(CurrentBlock/40)]+[Id>>2])
.eval BlockCollors.put(PixelCollor,Id)
}
// First check for 4 collors in a block
.if (BlockCollors.containsKey(Black) ==true) { .eval BG.put(CollCounter,Black) .eval CollCounter=CollCounter+1 }
.if (BlockCollors.containsKey(White) ==true) { .eval BG.put(CollCounter,White) .eval CollCounter=CollCounter+1 }
.if (BlockCollors.containsKey(Red) ==true) { .eval BG.put(CollCounter,Red) .eval CollCounter=CollCounter+1 }
.if (BlockCollors.containsKey(Cyan) ==true) { .eval BG.put(CollCounter,Cyan) .eval CollCounter=CollCounter+1 }
.if (BlockCollors.containsKey(Purple) ==true) { .eval BG.put(CollCounter,Purple) .eval CollCounter=CollCounter+1 }
.if (BlockCollors.containsKey(Green) ==true) { .eval BG.put(CollCounter,Green) .eval CollCounter=CollCounter+1 }
.if (BlockCollors.containsKey(Blue) ==true) { .eval BG.put(CollCounter,Blue) .eval CollCounter=CollCounter+1 }
.if (BlockCollors.containsKey(Yellow) ==true) { .eval BG.put(CollCounter,Yellow) .eval CollCounter=CollCounter+1 }
.if (BlockCollors.containsKey(L_brown)==true) { .eval BG.put(CollCounter,L_brown) .eval CollCounter=CollCounter+1 }
.if (BlockCollors.containsKey(D_brown)==true) { .eval BG.put(CollCounter,D_brown) .eval CollCounter=CollCounter+1 }
.if (BlockCollors.containsKey(L_red) ==true) { .eval BG.put(CollCounter,L_red) .eval CollCounter=CollCounter+1 }
.if (BlockCollors.containsKey(D_grey) ==true) { .eval BG.put(CollCounter,D_grey) .eval CollCounter=CollCounter+1 }
.if (BlockCollors.containsKey(Grey) ==true) { .eval BG.put(CollCounter,Grey) .eval CollCounter=CollCounter+1 }
.if (BlockCollors.containsKey(L_green)==true) { .eval BG.put(CollCounter,L_green) .eval CollCounter=CollCounter+1 }
.if (BlockCollors.containsKey(L_blue) ==true) { .eval BG.put(CollCounter,L_blue) .eval CollCounter=CollCounter+1 }
.if (BlockCollors.containsKey(L_grey) ==true) { .eval BG.put(CollCounter,L_grey) .eval CollCounter=CollCounter+1 }
.if (CollCounter == 4) {
// Check if it is the first block with 4 collors
.if (FirstMatch) {
// Copy the 4 collors as possible candidates
.eval BGCandidate.put(0,BG.get(0))
.eval BGCandidate.put(1,BG.get(1))
.eval BGCandidate.put(2,BG.get(2))
.eval BGCandidate.put(3,BG.get(3))
.eval FirstMatch = false
} else {
// Check BG candidate #0 = BG #0->3 => Next if some match OR Remove value / Decrease BGReamining
.for (var i = 0 ; i < BGRemaining ; i++) {
.if (BGCandidate.get(i)!=BG.get(0)) {
.if (BGCandidate.get(i)!=BG.get(1)) {
.if (BGCandidate.get(i)!=BG.get(2)) {
.if (BGCandidate.get(i)!=BG.get(3)) {
.eval BGCandidate.remove(i)
.eval BGRemaining = BGRemaining-1
}
}
}
}
}
}
}
// Clear out the Block Collors
.eval BlockCollors = Hashtable()
// Reset the Block Collor Counter
.eval CollCounter = 0
}
// Verification of BG Coll:
.print "BG Collor is: " + BGCandidate.get(0)
}
|
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Try the following:
When you have a time-consuming program, with pure script commands - then place them in a .define block or in a function and it will be faster.
The technical reason for this (which you don't need to know but some might find interesting):
When Kick Assembler evaluates a function or dircetive it saves the result, so it doesn't have to evaluate it in the next pass. The directive will only be reevaluated if the result is invalid (That happens if the result depends on a label that is defined later in the sourcecode). However if you have too many saved intermediate results, it damages the performace and the memory usage. Placing your script inside a function or .define block will save only one result and not all the intermediate results.
So this will be more effective:
.var bgColor = findBgColor(params)
.function findBgColor(params) {
...
}
|
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Btw. if you dont want to restructure your code then just place a define directive inside your code that takes care of those for-loops. |
| |
TWW
Registered: Jul 2009 Posts: 545 |
Ok. Slammer, thanx.
I will try out your suggestions and come back with the result whne it's done. (not today coz I got a party to go to 8-D) |
| |
TWW
Registered: Jul 2009 Posts: 545 |
EDIT: EDIT: I am a idiot!
Figgured it out... |
| |
TWW
Registered: Jul 2009 Posts: 545 |
Alright. Got the background sorted. I decieded to do a full scan of all blocks to simultaniously extract the collors used which I now have neatly stored into a indexed collor hashtable.
The only thing remaining is to capture the actual bmp-data and make sure the Background collor is mapped with #%00 bitmpair (transparent).
I tried this:
// Load the picture into the data list Graphics
.var Graphics = LoadPicture(PNGpicture,List().add(BackgroundColor))
// Fill in the Bitmap data
.pc = BMPdata
.fill 8000,[Graphics.getMulticolorByte(floor(i/8)-40*floor(i/320),i-[floor(i/8)-40*flo or(i/320)]*8-312*floor(i/320))]
Which works perfectly for the BG collor. However I thought if I left out the three last bitpair definitions in the getMulticolorByte function, that any other collor then BG would be treated as if no bitpair collor was defined (I.e. get mapped progressivly by the function using the three last bitpair combinations #%01 #%10 & #%11)
So before I go ahead and make a bigger job out of this and check every pixel on the picture to determine which bitpair should be used, I want to check if I am missing something or doing this in the wrong way. |
Previous - 1 | 2 | 3 | 4 | 5 - Next |