Log inRegister an accountBrowse CSDbHelp & documentationFacts & StatisticsThe forumsAvailable RSS-feeds on CSDbSupport CSDb Commodore 64 Scene Database
You are not logged in - nap
CSDb User Forums


Forums > C64 Coding > Kickassembler - Converting .PNG to Koala
2012-02-21 15:04
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....
 
2012-02-27 13:10
Slammer

Registered: Feb 2004
Posts: 416
getMulticolorByte is for 4 color pictures so you can't use that.

Btw. Have you seen this converter. It might offer some inspiration. http://codebase64.org/doku.php?id=base:double_screen_horizontal..
2012-02-27 21:57
TWW

Registered: Jul 2009
Posts: 545
Ok.

Improvement suggestion: Wouldn't it be cool if you could use the getMCByte on only a part (say a 4x8 pixel block) when you have the BG and the block collors defined 8-D


But then ofcourse Cruizer had done this before. Anyway I like playing around with this to think a little more "scripted".

Now that I know you need to aproach this pixel by pixel it shouldn't be too tough. If it is, atleast there is some inspiration to be found.
2012-02-29 00:13
TWW

Registered: Jul 2009
Posts: 545
Ok, Done. There is definately a lot of improvement potential here but it works.

Thanx for the pointers.


    .macro PNGtoKOALA(PNGpicture,BMPData,Chardata,D800data,BGC) {

        // Create RGB to C64 color index
        .var RGBtoC64 = Hashtable()
        .eval RGBtoC64.put(Black,0)
        .eval RGBtoC64.put(White,1)
        .eval RGBtoC64.put(Red,2)
        .eval RGBtoC64.put(Cyan,3)
        .eval RGBtoC64.put(Purple,4)
        .eval RGBtoC64.put(Green,5)
        .eval RGBtoC64.put(Blue,6)
        .eval RGBtoC64.put(Yellow,7)
        .eval RGBtoC64.put(L_brown,8)
        .eval RGBtoC64.put(D_brown,9)
        .eval RGBtoC64.put(L_red,10)
        .eval RGBtoC64.put(D_grey,11)
        .eval RGBtoC64.put(Grey,12)
        .eval RGBtoC64.put(L_green,13)
        .eval RGBtoC64.put(L_blue,14)
        .eval RGBtoC64.put(L_grey,15)

        // Hashtable for Storing all the colors.
        .var RGBColorTable  = Hashtable()

        // Create a list to hold all the Bitmap and collor data
        .var AllData = List(10000)

        // Load the picture into the data list Graphics
        .var Graphics = LoadPicture(PNGpicture,List())

        // Convert and return the Background Color
        .var BackgroundColor = FindBackgroundColor()

        .pc = BMPData "KOALA - Bitmap Graphics"
        .fill 8000,AllData.get(i)
        .pc = Chardata "KOALA - Character Color Data"
        .fill 1000,AllData.get(i+8000)
        .pc = D800data "KOALA - D800 Color Data"
        .fill 1000,AllData.get(i+9000)
        .pc = BGC "KOALA - Background Collor"
        .fill 1,BackgroundColor

    }

//=============================================================================
    // ColorTable-Hashtable has to be defined outside the function.
    .function FindBackgroundColor() {

        // Hastable for storing 4x8 block colordata
        .var BlockColors = Hashtable()

        // Hashtable for potential background Colors from inside one block
        .var BG = Hashtable()

        // Hashtable for keeping track of background color candidates from all blocks
        .var BGCandidate  = List(4)

        // Declare some variables
        .var CurrentBlock = 0     // Keeps track of which block is being checked
        .var BGRemaining  = 4     // Remaining backgound color candidates (begins with 4 since the first block get's it's 4 colors copied into the BGCandidate Hastable)
        .var ColorCounter = 0     // Counter for keeping track of how many colors are found inside each block
        .var FirstMatch   = true  // Used to diferensiate between the first 4 color block (It has to contain the backgound color) and the rest of the blocks

        // Loop for checking all 1000 blocks
        .for (CurrentBlock=0 ; CurrentBlock<1000 ; CurrentBlock++) {

            // Clear out any block colors from the hashtable
            .eval BlockColors = Hashtable()

            // Fetch 4x8 pixel block colors (32 total)
            .for (var Pixel = 0 ; Pixel < 32 ; Pixel++) {
                .var PixelColor = Graphics.getPixel([8*CurrentBlock+[[Pixel<<1]&7]]-[320*[floor(CurrentBlock/40)]] , [8*floor(CurrentBlock/40)]+[Pixel>>2])
                .eval BlockColors.put(PixelColor,Pixel)
            }

            // Reset the block color counter
            .eval ColorCounter = 0

            // Store the block colors in BG
            .if (BlockColors.containsKey(Black)  ==true) { .eval BG.put(ColorCounter,Black)   .eval RGBColorTable.put([ColorCounter+[4*CurrentBlock]],Black)   .eval ColorCounter=ColorCounter+1 }
            .if (BlockColors.containsKey(White)  ==true) { .eval BG.put(ColorCounter,White)   .eval RGBColorTable.put([ColorCounter+[4*CurrentBlock]],White)   .eval ColorCounter=ColorCounter+1 }
            .if (BlockColors.containsKey(Red)    ==true) { .eval BG.put(ColorCounter,Red)     .eval RGBColorTable.put([ColorCounter+[4*CurrentBlock]],Red)     .eval ColorCounter=ColorCounter+1 }
            .if (BlockColors.containsKey(Cyan)   ==true) { .eval BG.put(ColorCounter,Cyan)    .eval RGBColorTable.put([ColorCounter+[4*CurrentBlock]],Cyan)    .eval ColorCounter=ColorCounter+1 }
            .if (BlockColors.containsKey(Purple) ==true) { .eval BG.put(ColorCounter,Purple)  .eval RGBColorTable.put([ColorCounter+[4*CurrentBlock]],Purple)  .eval ColorCounter=ColorCounter+1 }
            .if (BlockColors.containsKey(Green)  ==true) { .eval BG.put(ColorCounter,Green)   .eval RGBColorTable.put([ColorCounter+[4*CurrentBlock]],Green)   .eval ColorCounter=ColorCounter+1 }
            .if (BlockColors.containsKey(Blue)   ==true) { .eval BG.put(ColorCounter,Blue)    .eval RGBColorTable.put([ColorCounter+[4*CurrentBlock]],Blue)    .eval ColorCounter=ColorCounter+1 }
            .if (BlockColors.containsKey(Yellow) ==true) { .eval BG.put(ColorCounter,Yellow)  .eval RGBColorTable.put([ColorCounter+[4*CurrentBlock]],Yellow)  .eval ColorCounter=ColorCounter+1 }
            .if (BlockColors.containsKey(L_brown)==true) { .eval BG.put(ColorCounter,L_brown) .eval RGBColorTable.put([ColorCounter+[4*CurrentBlock]],L_brown) .eval ColorCounter=ColorCounter+1 }
            .if (BlockColors.containsKey(D_brown)==true) { .eval BG.put(ColorCounter,D_brown) .eval RGBColorTable.put([ColorCounter+[4*CurrentBlock]],D_brown) .eval ColorCounter=ColorCounter+1 }
            .if (BlockColors.containsKey(L_red)  ==true) { .eval BG.put(ColorCounter,L_red)   .eval RGBColorTable.put([ColorCounter+[4*CurrentBlock]],L_red)   .eval ColorCounter=ColorCounter+1 }
            .if (BlockColors.containsKey(D_grey) ==true) { .eval BG.put(ColorCounter,D_grey)  .eval RGBColorTable.put([ColorCounter+[4*CurrentBlock]],D_grey)  .eval ColorCounter=ColorCounter+1 }
            .if (BlockColors.containsKey(Grey)   ==true) { .eval BG.put(ColorCounter,Grey)    .eval RGBColorTable.put([ColorCounter+[4*CurrentBlock]],Grey)    .eval ColorCounter=ColorCounter+1 }
            .if (BlockColors.containsKey(L_green)==true) { .eval BG.put(ColorCounter,L_green) .eval RGBColorTable.put([ColorCounter+[4*CurrentBlock]],L_green) .eval ColorCounter=ColorCounter+1 }
            .if (BlockColors.containsKey(L_blue) ==true) { .eval BG.put(ColorCounter,L_blue)  .eval RGBColorTable.put([ColorCounter+[4*CurrentBlock]],L_blue)  .eval ColorCounter=ColorCounter+1 }
            .if (BlockColors.containsKey(L_grey) ==true) { .eval BG.put(ColorCounter,L_grey)  .eval RGBColorTable.put([ColorCounter+[4*CurrentBlock]],L_grey)  .eval ColorCounter=ColorCounter+1 }

            // Carry out a background color check when there are 4 colors in a block
            .if (ColorCounter == 4 && BGCandidate.size()>1) {

                // Check if it is the first block with 4 collors
                .if (FirstMatch) {

                    // Copy the 4 collors as possible candidates
                    .eval BGCandidate.add(BG.get(0))
                    .eval BGCandidate.add(BG.get(1))
                    .eval BGCandidate.add(BG.get(2))
                    .eval BGCandidate.add(BG.get(3))
                    .eval FirstMatch = false
                } else {
                    .for (var i = 0 ; i < BGCandidate.size() ; 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)
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }


    .var BackgroundColor = BGCandidate.get(0)


    // Test BG Color
    .print BackgroundColor

        // Variable for keeping track of which byte is in use
        .var ByteNumber = 0

        // Create hashtable and ascociate bitmap patterns to RGB Colors (one for bit patterns and one for collor referance)
        .var ColorIndex = Hashtable()
        .var ColorIndex2 = Hashtable()

        // Define the BG Color into the Color Indexes
        .eval ColorIndex.put(BackgroundColor,0)
        .eval ColorIndex2.put(0,BackgroundColor)

        .for (var BlockNumber = 0 ; BlockNumber < 1000 ; BlockNumber++) {

            // Variable for keeping track of which collor is to be used inside the block
            .var colpos = 1

            // Place the RGB color data into the color indexes (Multicolor Bit-combinations 01, 10 & 11 assigned the 3 colors)
            .for (var i = 0 ; i < 4 ; i++) {
                .if (RGBColorTable.get(i+[BlockNumber*4]) != BackgroundColor) {
                    .if (RGBColorTable.get(i+[BlockNumber*4]) != null) {
                        .eval ColorIndex.put(RGBColorTable.get(i+[BlockNumber*4]),colpos)
                        .eval ColorIndex2.put(colpos,RGBColorTable.get(i+[BlockNumber*4]))
                        .eval colpos = colpos+1
                    }
                }
            }

            // Read Pixel Collors in current block and fill in BMPData accordingly
            .for (var Byte = 0 ; Byte < 8 ; Byte++) {

                // Temp Storage for bitmap byte, bitmap pattern and the pixelcolor
                .var BMPByte = 0
                .var BMPPattern = 0
                .var PixelColor = 0

                // Find the pixel collors and cross ref. with the bit patterns to create the BMP data
                .for (var Pixel = 0 ; Pixel < 4 ; Pixel++) {
                        .eval PixelColor = Graphics.getPixel([[8*BlockNumber]+[[Pixel<<1]&7]]-[320*[floor(BlockNumber/40)]] , [8*floor(BlockNumber/40)]+Byte)
                        .eval BMPPattern = ColorIndex.get(PixelColor)
                        .eval BMPByte = BMPByte|[BMPPattern << [6 - Pixel*2]]
                }

                // Set the done BMP data into final data storage
                .eval AllData.set(ByteNumber,BMPByte)
                .eval ByteNumber = ByteNumber+1
            }

            // Create the color data
            .var CharacterColor = 0
            .var D800Color = 0

            .if (RGBtoC64.get(ColorIndex2.get(1)) != null) { .eval CharacterColor = [RGBtoC64.get(ColorIndex2.get(1))<<4] }
            .if (RGBtoC64.get(ColorIndex2.get(2)) != null) { .eval CharacterColor = CharacterColor|RGBtoC64.get(ColorIndex2.get(2)) }
            .if (RGBtoC64.get(ColorIndex2.get(3)) != null) { .eval D800Color = RGBtoC64.get(ColorIndex2.get(3)) }

            // Store the colors into final data storage
            .eval AllData.set(8000+BlockNumber,CharacterColor)
            .eval AllData.set(9000+BlockNumber,D800Color)
        }

    // Return background color:
    .return BackgroundColor

    }


EDIT: Fixed some bugs and small optimalizations.
2012-04-13 16:09
Total Chaos

Registered: Mar 2006
Posts: 74
Since I'm stupid I don't get where do I put filename and addresses into that one?

Also, could it be modified to handle other size bitmaps (like 348 pixels wide)?

Please talk to me like I'm a 5-year old...

//TC
2012-04-13 18:38
andym00

Registered: Jun 2009
Posts: 45
The very first line of the macro contains the parameters you need to pass in..
.macro PNGtoKOALA(PNGpicture,BMPData,Chardata,D800data,BGC)

So filename and 4 sets of addresses for the respective components of the bitmap..
2012-04-13 19:22
Total Chaos

Registered: Mar 2006
Posts: 74
.macro PNGtoKOALA(PNGpicture,BMPData,Chardata,D800data,BGC)

PNGpicture=name
or just replace it?
2012-04-14 07:25
Total Chaos

Registered: Mar 2006
Posts: 74
PNGtoKOALA(PNGpicture=320x200.png,BMPData=$2000,Chardata=$4000,D800data=$5000,BG C=$6000)
PNGtoKOALA(PNGpicture=320x200.png,BMPData=2000,Chardata=4000,D800data=5000,BGC=6 000)
PNGtoKOALA(320x200.png,$2000,$4000,$5000,$6000)

none of these worked



2012-04-14 09:18
andym00

Registered: Jun 2009
Posts: 45
:PNGtoKOALA("320x200.png", $2000,$4000,$5000,$6000)
2012-04-14 10:36
Total Chaos

Registered: Mar 2006
Posts: 74
Didn't work.
2012-04-17 00:47
TWW

Registered: Jul 2009
Posts: 545
Any chance you could be a little more specific?

Are you sure you have the same RGB values?
Do you get any error messages?
How do you verify it doesen't work if there are no errors?


EDIT: I also posted this code on codebase (Down for maintenance right now) and I am unsure if I made any fixes to it there compared with this one. The codebase one should be the best one atleast (There was some bug I rectified but can't remeber what).
Previous - 1 | 2 | 3 | 4 | 5 - Next
RefreshSubscribe to this thread:

You need to be logged in to post in the forum.

Search the forum:
Search   for   in  
All times are CET.
Search CSDb
Advanced
Users Online
Dr. Doom/RAD
Majikeyric
Scrap/Genesis Project
Sulevi/Virtual Dreams
Guests online: 98
Top Demos
1 Next Level  (9.7)
2 13:37  (9.7)
3 Mojo  (9.7)
4 Coma Light 13  (9.6)
5 Edge of Disgrace  (9.6)
6 What Is The Matrix 2  (9.6)
7 The Demo Coder  (9.6)
8 Uncensored  (9.6)
9 Comaland 100%  (9.6)
10 Wonderland XIV  (9.6)
Top onefile Demos
1 No Listen  (9.6)
2 Layers  (9.6)
3 Cubic Dream  (9.6)
4 Party Elk 2  (9.6)
5 Copper Booze  (9.6)
6 Dawnfall V1.1  (9.5)
7 Rainbow Connection  (9.5)
8 Onscreen 5k  (9.5)
9 Morph  (9.5)
10 Libertongo  (9.5)
Top Groups
1 Performers  (9.3)
2 Booze Design  (9.3)
3 Oxyron  (9.3)
4 Triad  (9.3)
5 Censor Design  (9.3)
Top Diskmag Editors
1 Magic  (9.8)
2 hedning  (9.6)
3 Jazzcat  (9.5)
4 Elwix  (9.1)
5 Remix  (9.1)

Home - Disclaimer
Copyright © No Name 2001-2024
Page generated in: 0.069 sec.