CanvasDraw - A powerful pixel-based graphics engine (Draw pixels, lines, triangles, read/modify image data, and much more!)

You can get a lot higher resolution and videos to the point where they last for minutes at a time by using this method + texture atlasing. The real gem is trying to figure out the best way to store them so that you can have them be in datastore.

Over my research the past year I found that a mix of bit packing, base64 encoding, as well as serialization, was the best way to make the storage small for RGB images. There is a better way than RichText, and it is to take advantage of caching. For GUIs you’d just use something like a lookup table for the colors whereas if you wanted to take the parts approach, you layout in your world a pallet of color cubes then change their CFrame on call (by using a CFrame cache). There are problems with both methods, GUIs can only go so high as they are inefficient as you’ll need to create constant UIGradients whereas with parts it is very efficient in terms of CPU usage, but you will use loads of memory with the sheer amount of parts in the cache.

That is why there are basically two methods for images for stuff like art games in Roblox, and because most users want it for an art game, where they can extrapolate it to a surface GUI and still run for mobile users, it is why most people tend to use the UIGradient exploit.

4 Likes

pretty cool stuff, works like black magic :flushed:
here’s osu! (lazer) being streamed at 5-2 fps (slow because of the studio window not being focused):

10 Likes

Gui caching is actually a wonderful idea, but I would love to have a visual example if you don’t mind lol.

1 Like

Amazing! No words, but amazing.

3 Likes

Yep. I sure did. Image processing on this has been around for a month and a bit now, but I honestly don’t think anyone even knows that it existed. half of the capabilities of this module isn’t even know! Maybe my thread on this thing doesn’t say or show enough.

I honestly don’t think it will make that big of a difference in performance since we are still colouring different parts of the ui objects. If anything, and honestly, I believe the rendering process for richtext colours is probably more expensive than just changing frame colours or UI gradients which are probably less expensive in rendering.

I hate to say it, but we will most likely never be getting any real time rendering for any custom canvas with a resolution that high. I would like to point out that the main performance problems are the pixel calculations. Not the actual frames with gradients.

4 Likes

Small Update - v2.3.0

Image SaveObject compression and resolution limit doubled!

This update contains some very impressive features for SaveObjects on CanvasDraw.


Firstly, the resolution limit for image SaveObjects has been increased from 128x128 to 256x256

Wow, now that’s a high quality image for CanvasDraw


Now secondly, the actual method for storing pixel data of images on SaveObjects has been heavily optimised thanks to string compression methods.

Before, SaveObjects used to be able to get as big as 120KB!! Now that’s a really big file size for an instance in your game. But now, SaveObjects have become 80-95% smaller!

Now you can have as many SaveObjects in your place as you want without having to worry about file size!


WARNING:

If you are using SaveObjects in your place that were made before this update, then you will need to delete them and re-import new SaveObjects as the old SaveObjects will not work with CanvasDraw 2.3.0 and above.

You will also need to update the CanvasDraw Image Importer plugin as well.

4 Likes

huh i realized loading a 1 minute video that has a 144p resolution takes a long time to load into roblox for some reason… I wish it was a bit… faster… If i remember correctly, it took longer than 30 minutes to load in the video.

2 Likes

Oh i do not recommend whole videos. Firstly it will take awhile to do import hundreds of PNGs at that high of a resolution. Also you will start to experience some framerate drop when doing videos more than 128p.

Aside from that, i tried making it as fast as possible for importing images without causing lag.

1 Like

hmm, its either i:

  1. Start uploading 90p videos instead of 144p.

or…

  1. Use HTTPService and a webserver to send pixel arrays for each video frame (Not my best option)
1 Like

Honestly 90p to 128p is my best preferred resolution, but it’s the frame count i like to keep below 100. Also I try to keep the framerate for videos at around 30 FPS or less. Cause simply switching pictures with larger resolution causes slight lag. But it pretty minimal and is overall pretty optimised

1 Like

Patch - v2.3.1

Fixed circle not filling with the fill parameter set to true in the DrawCircle() function

This update contains a fix for a bug for the DrawCircle() function that was caused by an update that changed the way how pixels were represented.

In versions 2.0.0 to 2.3.0, the fill parameter for DrawCircle() did not work at all, which will always an outline circle when ever drawn. Thankfully this has been fixed!

CanvasDraw.DrawCircle(
    Vector2.new(50, 50), -- The point on the canvas where you want to place the circle
    5, -- The radius of the circle in pixels
    Color3.new(1, 0, 0), -- The colour for the circle (red in this case)
    true -- Fill the shape (now works again :D)
)
2 Likes

Patch - v2.3.2

Fixed the DrawCricle() function

This update contains a brand new and a much more fast and accurate algorithm for drawing circles. Before, DrawCricle used to leave imperfect circles with weird results at certain radiuses. This has now been fixed!

Fixed up and made the thread and API reference better

This thread has been updated to be a little bit smaller and more straight to the point without filling up the post with useless or repetitive information.

The API reference thread for CanvasDraw has also been updated as well.

2 Likes

Here’s my solution, First things first, I have a code that takes in videos and turns them into different pixel packets (a json file filled with pixel color data).

What happens next is that ill make it store all of the packets into folders or values. Once loaded, ill use CanvasDraw to get those pixels, turn them into images and scroll through them to make up a video…

1 Like

What’s preventing you from using CanvasDraw’s method for images?

CanvasDraw already does this with its image functions and it is quite efficient too since its all cached data from the Image importer plugin.

image

Unless your problem is the speed of importing images with my plugin, otherwise CanvasDraw’s method is already fast enough for GIFs and small videos.

CancasDraw also uses a single instance (an empty folder in this case) to store an image as a compressed string with attributes. So that’s only a few kilobytes of data for an image instance thats like 256x256p in a roblox place that CanvasDraw can load, and then draw.

CanvasDraw.CreateCanvas(CanvasFrame, Vector2.new(256, 256))

local SaveObject = script.Noob -- That folder instance that stores image data as compressed string values

-- Covert the compressed ImageData strings into a cache of readable values for CanvasDraw
local ImageData = CanvasDraw.GetImageDataFromSaveObject(script.Noob)

-- Draw the image to the canvas
CanvasDraw.DrawImage(ImageData)

1 Like

Yeah CanvasDraw doesnt work for videos longer than 1 minute… However the best fix is to split the video into bits and store it into folders… problem is figuring out how to scroll through them.

other way is the way i originally proposed.

But ur right, i can just use the image import system.

2 Likes

Patch - v2.3.3

This update brings some fixes and optimisations to CanvasDraw. These changes include:

  • Optimising the DrawImage() and DrawDistortedImage() functions
  • Optimising the pixel and point fetch methods
  • And fixing GetPoints() and GetPixels() sometimes returning false results
1 Like

Small update - v2.4.0

This update brings some more optimisation updates to CanvasDraw. These changes include:

  • An optimisation and a performance boost of rendering the canvas
  • More optimisation of the image functions
  • Optimisation of the filling method for the DrawCircle() function
  • Some new performant fetch alternative methods for pixels and images
    • GetPixelXY(X, Y) – A performant and more raw version of GetPixel(Point)
    • GetPixelFromImageXY(ImageData, X, Y) – A performant and more raw version of GetPixelFromImage(ImageData, Point)
1 Like

hahehahehahea this would be fun to make a demo out of

I’ve lowkey been wanting to make something like this, aswell, thank you for releasing this!

3 Likes

I’ll for sure use this in every 2D game I have in-mind!

3 Likes

Hello Developers! so im Trying to get Livestreams from youtube inside roblox how could this be done?
if anyone can create such a system for me contact me: Ms.Videoproductions_Ltd#5345
i really would like to use this to play recaps of my events on screens

2 Likes