Implemented serialization for PaintCanvas image data.

This commit is contained in:
Relintai 2022-11-19 20:43:40 +01:00
parent 4f06946cf5
commit 4eec1ffcb4
2 changed files with 82 additions and 0 deletions

View File

@ -19,6 +19,12 @@
#include "paint_project.h"
#include "scene/resources/texture.h"
#include "modules/modules_enabled.gen.h"
#ifdef MODULE_LZ4_ENABLED
#include "modules/lz4/lz4_compressor.h"
#endif
bool PaintCanvas::get_symmetry_x() const {
return _symmetry_x;
}
@ -342,6 +348,75 @@ Ref<Image> PaintCanvas::_get_save_image() {
return _image;
}
PoolByteArray PaintCanvas::get_image_data_compressed() {
PoolByteArray arr;
#ifdef MODULE_LZ4_ENABLED
if (_image->empty()) {
return arr;
}
PoolByteArray data = _image->get_data();
int size = data.size();
PoolByteArray::Read dr = data.read();
const uint8_t *ch = dr.ptr();
int bound = LZ4Compressor::LZ4_compressBound(size);
int additional_data_size = 3 * sizeof(int);
arr.resize(bound + additional_data_size);
PoolByteArray::Write w = arr.write();
uint8_t *wptr = w.ptr();
Vector2i node_size = get_size();
reinterpret_cast<int *>(wptr)[0] = node_size.x;
reinterpret_cast<int *>(wptr)[1] = node_size.y;
reinterpret_cast<int *>(wptr)[2] = data.size();
int ns = LZ4Compressor::LZ4_compress_default(reinterpret_cast<const char *>(ch), reinterpret_cast<char *>(&wptr[additional_data_size]), size, bound);
w.release();
arr.resize(ns + additional_data_size);
#endif
return arr;
}
void PaintCanvas::set_image_data_compressed(const PoolByteArray &data) {
#ifdef MODULE_LZ4_ENABLED
int additional_data_size = 3 * sizeof(int);
int ds = data.size();
if (ds <= additional_data_size) {
set_size(Vector2i());
return;
}
PoolByteArray::Read dr = data.read();
const uint8_t *ch = dr.ptr();
Vector2i node_size;
node_size.x = reinterpret_cast<const int *>(ch)[0];
node_size.y = reinterpret_cast<const int *>(ch)[1];
int size = reinterpret_cast<const int *>(ch)[2];
PoolByteArray arr;
arr.resize(size);
PoolByteArray::Write w = arr.write();
uint8_t *wptr = w.ptr();
int ns = LZ4Compressor::LZ4_decompress_safe(reinterpret_cast<const char *>(&ch[additional_data_size]), reinterpret_cast<char *>(wptr), ds - additional_data_size, size);
if (ns != size) {
arr.resize(ns);
ERR_PRINT("ns != size");
return;
}
set_size(node_size);
_image->create(node_size.x, node_size.y, false, Image::FORMAT_RGBA8, arr);
update_textures();
#endif
}
void PaintCanvas::handle_draw(const Vector2 &local_position, const Ref<InputEvent> &event) {
PaintProject *proj = get_paint_project();
@ -954,6 +1029,10 @@ void PaintCanvas::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_previous_tool"), &PaintCanvas::get_previous_tool);
ClassDB::bind_method(D_METHOD("get_image_data_compressed"), &PaintCanvas::get_image_data_compressed);
ClassDB::bind_method(D_METHOD("set_image_data_compressed", "val"), &PaintCanvas::set_image_data_compressed);
ADD_PROPERTY(PropertyInfo(Variant::POOL_BYTE_ARRAY, "image_data_compressed"), "set_image_data_compressed", "get_image_data_compressed");
ClassDB::bind_method(D_METHOD("is_inside_canvas", "x", "y"), &PaintCanvas::is_inside_canvas);
ClassDB::bind_method(D_METHOD("set_pixel_arr", "pixels", "color"), &PaintCanvas::set_pixel_arr);

View File

@ -84,6 +84,9 @@ public:
Ref<Image> _get_save_image();
PoolByteArray get_image_data_compressed();
void set_image_data_compressed(const PoolByteArray &arr);
void handle_draw(const Vector2 &local_position, const Ref<InputEvent> &event);
Color get_current_color();
void update_mouse_position(const Vector2 &local_position, const Ref<InputEvent> &event);