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

Update: I’ve had to disable Relight plugin by Elttob to fix image editor not working correctly. Not sure why was this happening but I assume it had something to do with it sinking inputs. Are you using ContextActionService aswell to determine when to start/stop drawing?

Nope. Just normal plugin mouse and ui button events

1 Like

Is their anyway to zoom in? I half created something however it resulted in odd behavior when drawing

With the module or the image editor plugin? Currently there is no zooming on the plugin, but I plan to change that soon

Zooming in using the module. I tried resetting the resolution and creating a new canvas with the image data copied over however it basically made the canvas unusable

Th easiest way to do zooming is to just put the canvas in another frame, and then use ClipDescendants on that frame, and then you can change the size and position scale properties on the canvas’s frame to zoom and pan

I tried that as well but it gave me some interesting results, Although I was using 10x10 resolution, i’ll try it with 256x256

Also hate to be annoying but do you have any methods of compressing data using the legacy version, currently sending the entire image data over using a remote event causes quite big lag spikes

Not officially with the legacy version. One way though is to use CanvasDraw.CreateSaveObject() and then use the attributes from the created instance. If you want to load an ImageData from attributes, reconstruct the SaveObject instance with the attributes and then use CanvasDraw.GetImageData()

2 Likes

Ethan, does this use any type of greedy… pixeling? Would drawing rectangles be better for EditableImage?
Running at just 100x100 resolution already lags a lot.

I wonder if you know any optimizations?

  • I create a bunch of rays
  • Then raycast them
  • Then use SetPixel() for each pixel.

The only thing going on is Color.
Also please make a Canvas export type. Such that I can write

local my_canvas: CanvasDraw.Canvas = CanvasDraw.new()

Raycasting is causing you the lag here. Its very well known that calling raycast on every pixel will lag quite a bit.

That would be far slower than just indexing the pixel array. You have to remember this is for rendering engines, and each pixel has to be unique

2 Likes

This is a really cool resource. It’d be awesome if it could support Bezier Curves, as that would create some unique possibilities like custom font rendering and more!

ParallelScheduler would be a good way to optimize this, if raycasts are causing lag!

3 Likes

Makes sense, anyways I got some nice renders for you :smiley:





image

10 Likes

Hello, first of all, I would like to express my infinite appreciation for your project. Previously, I had a lot of trouble making my own pixel canvas, but thanks to your project, It saved my life lol
I’m working on a simple drawing app.


스크린샷 2024-08-08 200644

This is the result of randomly coloring a 192*108 canvas, compressing it once and converting it into json data. I get a string of 130,000 characters, which is too big. I think I made a mistake on something. Can you help me?

local CanvasDraw = require(ReplicatedStorage:WaitForChild("CanvasDraw"))
local CanvasSize = CanvasFrame.AbsoluteSize
local Canvas = CanvasDraw.new(CanvasFrame, Vector2.new(192, 108))

local function FillCanvasWithRandomColors()
	for x = 0, Canvas.Resolution.X - 1 do
		for y = 0, Canvas.Resolution.Y - 1 do
			-- Generate a random color for each pixel
			local randomColor = Color3.fromRGB(math.random(0, 255), math.random(0, 255), math.random(0, 255))
			-- Set the pixel at (x, y) to the random color
			Canvas:SetPixel(x, y, randomColor)
		end
	end
end

FillCanvasWithRandomColors()

local imageData = Canvas:CreateImageDataFromCanvas()
local compressedImageData = CanvasDraw.CompressImageData(imageData)
print(compressedImageData)
local jsonImageData = HttpService:JSONEncode(compressedImageData)
print(#jsonImageData)
1 Like

Nothing is wrong with your code at all, your use of using compressed image data is correct. Your problem here is that you are trying to compress something that is basically uncompressible. You generated random noise where every pixel has a completely different colour. Meaning this image is super detailed, so trying to compress it will only compress it by a little bit.

So basically, the less colours your image has, the less string characters you will get.

You can run the same test, but for a blank image and it should return a value like 3000 characters or something compared to 136,939.

Also this result is still under roblox’s 200,000 character string limit and it definitely wont get any higher than that, so either way you should be fine at that resolution

EDIT: Unrelated to the image compression, but I just noticed something with your code.

A canvases coordinates starts at 1, 1. Not 0, 0!

image

Treating 0, 0 as a starting point will cause problems as that is a pixel that doesn’t exist

for x = 1, Canvas.Resolution.X do
		for y = 1, Canvas.Resolution.Y do
1 Like

I was doing the wrong thing… I’m sorry!!!

don’t stress haha, you didn’t do anything wrong! Just trying to prevent any future issues with non-accurate coordinates! :)

4 Likes

Anyway to have a transparent canvas so I can place an image behind it?

Two ways. You can call Canvas:SetClearingRGBA() and enter your rgba values (a = alpha/transparency) And then call Canvas:Clear()

Or alternatively you can loop through every pixel and use Canvas:SetAlpha()

1 Like