Sprite has a Texture property - it's usually ImageTexture data type. It's a resource with function get_data() which returns Image object. And this class has function get_pixel(int x, int y, int mipmap_level=0) and put_pixel( int x, int y, Color color, int mipmap_level=0 ). If you don't need to read pixels, you could use shaders. It will be much faster.
Example (add this script to TextureFrame)
extends TextureFrame
var editableImage
var imageSize = Vector2(800, 600)
var imageFormat = Image.FORMAT_RGBA
var imageTexture
func _ready():
#Image is a built-in type
editableImage = Image(imageSize.x, imageSize.y, false, imageFormat)
imageTexture = ImageTexture.new()
imageTexture.create(imageSize.x,imageSize.y, imageFormat, 0)
imageTexture.set_data(editableImage)
set_texture(imageTexture)
set_process_input(true)
func _input(event):
if(event.type == InputEvent.MOUSE_MOTION):
editableImage.put_pixel(event.x,event.y, Color(1.0,1.0,1.0))
imageTexture.set_data(editableImage)
Unfortunately, this code is pretty slow for bigger images (300x200 is fine, 800x600 lags on my computer). And as you can see, you can't draw an uninterrupted line. You would have to rasterize the line between the last point and current point. But even Bresenham's line algorithm would slow this code even more.
If you really want to make a paint application in Godot (I don't think it's a good idea - I'm working on my own pixel art editor in Java), you should probably use CanvasItem's functions draw_line(), draw_circle(), etc. It will be way faster. At "save image" prompt, get a root viewport and call queue_screen_capture(). Wait for a while and call get_screen_capture(). It returns the image you can save by save_png( String path=0 ) call.