How to protect assets?

ddabrahim

Active member
Tutorial Author
Joined
May 3, 2020
Messages
175
Hi.

After I build a desktop application, assets like images, sounds and fonts can be easily extracted from the build.
Is there anyway I can protect these assets, encrypt them?

I don't personally mind, I am "open minded" and I agree the only thing can truly protect the assets is a license included with them.
However, most people freak out when they can see their assets accessible as easily as opening a folder. Is there anyway to please them?

Thank you in advance.
 

dawlane

Well-known member
CX Code Contributor
Joined
Jun 21, 2017
Messages
852
Not with Cerberus directly.
Commercial applications will either store assets internally, i.e. embedded, use a custom virtual file system or custom file format.
Encryption is usually pointless as the data could be extracted from memory once it's decoded.
 
Last edited:

ddabrahim

Active member
Tutorial Author
Joined
May 3, 2020
Messages
175
So, even put it in to a password protected zip or something is not an option with Cerberus?
That's unfortunate.

Yes I know things can be accessed in memory after decode but nobody needs to know that if not asking. I am talking about people who only care not to be able to see the assets and open it in 3rd party tools like image editors 😁
 

Jimmy

Active member
3rd Party Module Dev
Tutorial Author
Joined
Jan 2, 2020
Messages
912
You can create resources like images internally.
 

Attachments

  • creategraphicsOnCreate.cxs.zip
    2 KB · Views: 6

ddabrahim

Active member
Tutorial Author
Joined
May 3, 2020
Messages
175
Interesting, looks like it is what I am after. But how did you get this sprite information that you used to create the images from? Is there any tool I can use to get this info from any image?

Thanks.
 

Jimmy

Active member
3rd Party Module Dev
Tutorial Author
Joined
Jan 2, 2020
Messages
912
It's not my example so I'm not sure how that person got that in there. You need to have ambition I guess :oops:. Probably some custom procedure, it can be anything as long as it works.

This was just meant for inspiration to see what can be done for all files even images.

I'm trying to do the same for wav files right now.
 

dawlane

Well-known member
CX Code Contributor
Joined
Jun 21, 2017
Messages
852
Be warned that embedding image data into your applications will have big disadvantages in application size and memory use.
 

dawlane

Well-known member
CX Code Contributor
Joined
Jun 21, 2017
Messages
852
But how did you get this sprite information that you used to create the images from?
I very much doubt that there will be an application for that.
When it comes to converting image for embedding into applications. There are three main ways.
  • Precompile to object code using a resource compiler and linking into the application.
    • This requires that you a reference pointer to each assets data.
  • Use a dedicated converter to translate the image into C code.
    • A note here is that the XPM format is actually C code to begin with.
  • Hand code your own images byte by byte.
 

ddabrahim

Active member
Tutorial Author
Joined
May 3, 2020
Messages
175
Be warned that embedding image data into your applications will have big disadvantages in application size and memory use.

I was thinking if I store the image data inside an array and then initialise the array only when needed and empty the array when I don't, then it is going to allocate the memory only when I use it and free up when I don't. Would it be not the case?

When it comes to converting image for embedding into applications. There are three main ways.

What I was thinking is maybe I could write a converter to get the color and alpha value of every single pixel of an image and store that inside an Array in Cerberus and then reconstruct the image from this array, pixel by pixel on to a new canvas maybe and create an image from the canvas and finally draw the image on to the screen. But I don't know if it makes sense or is it practical.
 

dawlane

Well-known member
CX Code Contributor
Joined
Jun 21, 2017
Messages
852
I was thinking if I store the image data inside an array and then initialise the array only when needed and empty the array when I don't, then it is going to allocate the memory only when I use it and free up when I don't. Would it be not the case?
Doesn't work like that. When you embed an image into the application as an array, then data is already there. All you do is read the data to a screen buffer or image to display.

What I was thinking is maybe I could write a converter to get the color and alpha value of every single pixel of an image and store that inside an Array in Cerberus and then reconstruct the image from this array, pixel by pixel on to a new canvas maybe and create an image from the canvas and finally draw the image on to the screen. But I don't know if it makes sense or is it practical.
A more easier solution would be to use a third part tool such as png2c to convert the image into raw C/C++ data and then to write a converter that reads this file to your own custom binary file format that you would read in via FileStream.

Here's an example of an embedded png image.
It should be noted that the array is not optimised as each element will be 32 bits long, thus using more memory.
 

Attachments

  • embedded_001.zip
    25.6 KB · Views: 4
Last edited:

ddabrahim

Active member
Tutorial Author
Joined
May 3, 2020
Messages
175
Thank you for the explanation, the png2c converter is definately useful, I'll see what I can do with it. Probably not much, but I'll try 😁
 

ddabrahim

Active member
Tutorial Author
Joined
May 3, 2020
Messages
175
Thanks, really appreciate it. By looking at the code, I thought it is the same that Jimmy has shared. I'll take an other look then.
 

dawlane

Well-known member
CX Code Contributor
Joined
Jun 21, 2017
Messages
852
Another tool for converting images is 'convert'. This is found as part of the ImageMagick package.
Unfortunately, it doesn't output image information when converting to C-Style headers. But it can convert images to uncompressed NetPBM, in particular the PAM format. Which is very easy to parse and read data from.
 

Jimmy

Active member
3rd Party Module Dev
Tutorial Author
Joined
Jan 2, 2020
Messages
912
I hate to see external utilities used when the problem is so simple.

This is half-baked conssideration but it will get you started I think. It reads the image into an array. You just have to write the numbers to a file and paste it into the source, but you must be careful when you change the size and consider handling the width and height correctly. It's not hard but it's easy to make a mistake.

The example will read a specific size in this instance we'll use 320x200, pixels into exacyly 64000 numbers in an array.
Ready to be written as sourcematerial for the loader given at the top.

This is how the creator might've created the using Cerberus-X itself.

⭐ This is my suggestion what to use as a base even if it takes a second or two, and on top of this you only need to write the values to a file and paste into the first source in this thread, and make sure that the width and height is correctly handled.

Code:
Strict
Import mojo2
Import brl.databuffer

Function Main:Int()
    New Game
    Return 0
End

Class Game Extends App

    Field storage:Int[320*200]
    Field xxx:Int, yyy:Int,screen2:Image, sprite:Canvas, canvas:Canvas
    Field pixels:DataBuffer = New DataBuffer(4*320*200), ptr:Int = 0, sourceImage:Image
    Field starter:Int = 0
 
    Method OnCreate:Int()
        canvas=New Canvas
        SetSwapInterval 1 ; SetUpdateRate 0
        sourceImage = Image.Load("screen.png",0,0,0)
        screen2=New Image(320,200,0,0,0)
        sprite=New Canvas(screen2)
        Return 0
    End

    Method OnRender:Int()
            canvas.Clear 0,0,0,0
        If starter < 10
            starter = starter + 1
            If starter > 5 Then sprite.DrawImage sourceImage,0,0
        Endif
        For Local temp:Int = 0 To 99 '  Read  only 100 pixels per frame as we do not want hold up any frames
            yyy = Int(ptr/320) ; xxx = ptr-(yyy*320) ; ptr = ptr + 1
   
         ' Not finished yet so keep reading pixels
        if ptr =< (320*200)
                 sprite.ReadPixels(xxx,yyy,1,1, pixels) ' read just one pixel
                 storage[ptr] = pixels.PeekInt(0)
       Endif
 
       ' Finished!
       If ptr > (320*200)
             ptr = 0
            ' Finished reading the whole image into storage[], ready to write a file and quit!
         Endif
   
        Next
        sprite.Flush
        canvas.DrawImage screen2.0.0
        canvas.Flush
        Return 0
    End
End
 
Last edited:

Jimmy

Active member
3rd Party Module Dev
Tutorial Author
Joined
Jan 2, 2020
Messages
912
This is how you would read all pixels at once, everything in one frame, If we hoped that ONE frame had enough time for all our computation needs. It's simple but not always doable, the other one can do 8K no problem.
Code:
Strict
Import mojo2
Import brl.databuffer

Function Main:Int()
New Game
Return 0
End

Class Game Extends App

Field storage:Int[320*200]
Field xxx:Int, yyy:Int
Field screen2:Image
Field sprite:Canvas
Field canvas:Canvas
Field pixels:DataBuffer = New DataBuffer(4*320*200)
Field sourceImage:Image
Field starter:Int = 0

Method OnCreate:Int() 
canvas=New Canvas
SetSwapInterval 1 ; SetUpdateRate 0
sourceImage = Image.Load("screen.png",0,0,0)
screen2=New Image(320,200,0,0,0)
sprite=New Canvas(screen2)

Return 0
End

Method OnRender:Int()
canvas.Clear

' Trick To get html5 working
' (as we cannot draw in OnCreate or inside OnRender during the first few frames as a HTML5-target)
If starter < 10
starter = starter + 1
If starter > 5
sprite.DrawImage sourceImage,0,0 ; sprite.Flush ' For non-HTML5 platforms you could just stick this line in the OnCreate and forget about this trick
Endif
Endif

' We know that Sprite contains the image now, so let's read it:
If starter = 10
starter = 11
' Lets imagine we have infinite time in one frame and be bold enough to read all the pixels in one go!
sprite.ReadPixels(0,0,320,200, pixels) ' This is the only command that might take time. But big sizes takes a lot of time and boy can it ruin your dayplan.
For Local temp:Int = 0 To 63999
yyy = Int(temp/320) ; xxx = temp-(yyy*320)
storage[temp] = pixels.PeekInt(Int(Int(xxx)*4+Int(yyy)*320*4))
Next
' Save the array into file here
'
Endif

' Just draw what we are doing on the screen, this does nothing important
canvas.DrawImage screen2,0,0
canvas.Flush
Return 0
End


End
 
Last edited:

Jimmy

Active member
3rd Party Module Dev
Tutorial Author
Joined
Jan 2, 2020
Messages
912
This is the only way I know to get the pixels inside Cerberus-X.
I don't know a way to readpixels outside of OnRender but someone else might have a better solution for that. (y)

It works fine. But inside OnRender.. if you are reading pixels.. you have the spotlight on you and you better be quick.
 
Top Bottom