From 974a7e858f302d21354bb80c1549e64ffb4ffb22 Mon Sep 17 00:00:00 2001 From: Tanasart Date: Thu, 29 Aug 2024 08:53:19 +0700 Subject: [PATCH] importer --- PixelComposer.resource_order | 1 + PixelComposer.yyp | 1 + .../byte_read_function/byte_read_function.gml | 166 ++++++++++++++++++ scripts/node_canvas/node_canvas.gml | 4 +- scripts/node_image/node_image.gml | 62 +++---- .../node_image_animated.gml | 11 +- scripts/png_reader/png_reader.gml | 28 +++ scripts/png_reader/png_reader.yy | 13 ++ .../sprite_add_functions.gml | 20 ++- 9 files changed, 264 insertions(+), 42 deletions(-) create mode 100644 scripts/png_reader/png_reader.gml create mode 100644 scripts/png_reader/png_reader.yy diff --git a/PixelComposer.resource_order b/PixelComposer.resource_order index f3d3e4d3f..79cf8a183 100644 --- a/PixelComposer.resource_order +++ b/PixelComposer.resource_order @@ -1299,6 +1299,7 @@ {"name":"pcx_parse","order":3,"path":"scripts/pcx_parse/pcx_parse.yy",}, {"name":"pcx_server","order":2,"path":"scripts/pcx_server/pcx_server.yy",}, {"name":"perlin_noise","order":5,"path":"scripts/perlin_noise/perlin_noise.yy",}, + {"name":"png_reader","order":9,"path":"scripts/png_reader/png_reader.yy",}, {"name":"point_direction_positive","order":4,"path":"scripts/point_direction_positive/point_direction_positive.yy",}, {"name":"point_rect_overlap","order":2,"path":"scripts/point_rect_overlap/point_rect_overlap.yy",}, {"name":"point_rotate","order":1,"path":"scripts/point_rotate/point_rotate.yy",}, diff --git a/PixelComposer.yyp b/PixelComposer.yyp index 2a91bdda2..d99db8700 100644 --- a/PixelComposer.yyp +++ b/PixelComposer.yyp @@ -1922,6 +1922,7 @@ {"id":{"name":"pcx_parse","path":"scripts/pcx_parse/pcx_parse.yy",},}, {"id":{"name":"pcx_server","path":"scripts/pcx_server/pcx_server.yy",},}, {"id":{"name":"perlin_noise","path":"scripts/perlin_noise/perlin_noise.yy",},}, + {"id":{"name":"png_reader","path":"scripts/png_reader/png_reader.yy",},}, {"id":{"name":"point_direction_positive","path":"scripts/point_direction_positive/point_direction_positive.yy",},}, {"id":{"name":"point_rect_overlap","path":"scripts/point_rect_overlap/point_rect_overlap.yy",},}, {"id":{"name":"point_rotate","path":"scripts/point_rotate/point_rotate.yy",},}, diff --git a/scripts/byte_read_function/byte_read_function.gml b/scripts/byte_read_function/byte_read_function.gml index 917f30f34..82ff0c52f 100644 --- a/scripts/byte_read_function/byte_read_function.gml +++ b/scripts/byte_read_function/byte_read_function.gml @@ -1,3 +1,5 @@ +/////============= LITTLE ENDIEN ============= + function bin_read_byte(_bin) { return file_bin_read_byte(_bin); } @@ -111,6 +113,15 @@ function bin_read_long64(_bin) { return sig? -lng : lng; } +function bin_read_chars(_bin, _len) { + var ss = ""; + repeat(_len) { + var utf = bin_read_byte(_bin); + ss += chr(utf); + } + return ss; +} + function bin_read_string(_bin) { var len = bin_read_word(_bin); var ss = ""; @@ -140,4 +151,159 @@ function bin_read_pixel(_bin, type) { case 2 : return [ bin_read_byte(_bin) ]; } return 0; +} + +/////=========== BIG ENDIEN =========== + +function Bin_read_byte(_bin) { + return file_bin_read_byte(_bin); +} + +function Bin_read_word(_bin) { + var b1 = file_bin_read_byte(_bin); + var b0 = file_bin_read_byte(_bin); + return b0 + (b1 << 8); +} + +function Bin_read_short(_bin) { + var b1 = file_bin_read_byte(_bin); + var b0 = file_bin_read_byte(_bin); + + var sht = b0 + (b1 << 8); + var sig = sht >> 15; + sht = sht & ~(1 << 15); + return sig? sht - power(2, 15) : sht; +} + +function Bin_read_dword(_bin) { + var b3 = file_bin_read_byte(_bin); + var b2 = file_bin_read_byte(_bin); + var b1 = file_bin_read_byte(_bin); + var b0 = file_bin_read_byte(_bin); + var dw = b0 + (b1 << 8) + (b2 << 16) + (b3 << 24); + return dw; +} + +function Bin_read_long(_bin) { + var b3 = file_bin_read_byte(_bin); + var b2 = file_bin_read_byte(_bin); + var b1 = file_bin_read_byte(_bin); + var b0 = file_bin_read_byte(_bin); + var lng = b0 + (b1 << 8) + (b2 << 16) + (b3 << 24); + + var sig = lng >> 31; + lng = lng & ~(1 << 31); + return sig? lng - power(2, 31) : lng; +} + +function Bin_read_fixed(_bin) { + var b3 = file_bin_read_byte(_bin); + var b2 = file_bin_read_byte(_bin); + var b1 = file_bin_read_byte(_bin); + var b0 = file_bin_read_byte(_bin); + + var fixInt = b0 + (b1 << 8); + var fixFrc = b2 + (b3 << 8); + return fixInt + bin_fraction(fixFrc, 16); +} + +function Bin_read_float(_bin) { + var b3 = file_bin_read_byte(_bin); + var b2 = file_bin_read_byte(_bin); + var b1 = file_bin_read_byte(_bin); + var b0 = file_bin_read_byte(_bin); + var flt = b0 + (b1 << 8) + (b2 << 16) + (b3 << 24); + + var sig = flt >> 31; + var expo = (flt & ~(1 << 31)) >> 23; + var mant = flt & 0b00000000_01111111_11111111_11111111; + + var val = (1 + mant) * power(2, expo - 127); + return sig? -val : val; +} + +function Bin_read_double(_bin) { + var b7 = file_bin_read_byte(_bin); + var b6 = file_bin_read_byte(_bin); + var b5 = file_bin_read_byte(_bin); + var b4 = file_bin_read_byte(_bin); + var b3 = file_bin_read_byte(_bin); + var b2 = file_bin_read_byte(_bin); + var b1 = file_bin_read_byte(_bin); + var b0 = file_bin_read_byte(_bin); + var dub = int64(b0 + (b1 << 8) + (b2 << 16) + (b3 << 24) + (b2 << 32) + (b3 << 40) + (b2 << 48) + (b3 << 56)); + + var sig = dub >> 63; + var expo = (dub & ~(1 << 63)) >> 52; + var mant = dub & 0b00000000_00001111_11111111_11111111_11111111_11111111_11111111_11111111; + + var val = (1 + mant) * power(2, expo - 1023); + return sig? -val : val; +} + +function Bin_read_qword(_bin) { + var b7 = file_bin_read_byte(_bin); + var b6 = file_bin_read_byte(_bin); + var b5 = file_bin_read_byte(_bin); + var b4 = file_bin_read_byte(_bin); + var b3 = file_bin_read_byte(_bin); + var b2 = file_bin_read_byte(_bin); + var b1 = file_bin_read_byte(_bin); + var b0 = file_bin_read_byte(_bin); + return int64(b0 + (b1 << 8) + (b2 << 16) + (b3 << 24) + (b2 << 32) + (b3 << 40) + (b2 << 48) + (b3 << 56)); +} + +function Bin_read_long64(_bin) { + var b7 = file_bin_read_byte(_bin); + var b6 = file_bin_read_byte(_bin); + var b5 = file_bin_read_byte(_bin); + var b4 = file_bin_read_byte(_bin); + var b3 = file_bin_read_byte(_bin); + var b2 = file_bin_read_byte(_bin); + var b1 = file_bin_read_byte(_bin); + var b0 = file_bin_read_byte(_bin); + var lng = int64(b0 + (b1 << 8) + (b2 << 16) + (b3 << 24) + (b2 << 32) + (b3 << 40) + (b2 << 48) + (b3 << 56)); + var sig = lng >> 63; + lng = lng & ~(1 << 63); + return sig? -lng : lng; +} + +function Bin_read_chars(_bin, _len) { + var ss = ""; + repeat(_len) { + var utf = Bin_read_byte(_bin); + ss += chr(utf); + } + return ss; +} + +function Bin_read_string(_bin) { + var len = Bin_read_word(_bin); + var ss = ""; + repeat(len) { + var utf = Bin_read_byte(_bin); + ss += chr(utf); + } + return ss; +} + +function Bin_read_point(_bin) { return [ Bin_read_long(_bin), Bin_read_long(_bin) ]; } +function Bin_read_size(_bin) { return [ Bin_read_long(_bin), Bin_read_long(_bin) ]; } +function Bin_read_rect(_bin) { return [ Bin_read_point(_bin), Bin_read_size(_bin) ]; } + +function Bin_read_color(_bin) { + var r = Bin_read_byte(_bin); + var g = Bin_read_byte(_bin); + var b = Bin_read_byte(_bin); + + return make_color_rgb(r, g, b); +} + +function Bin_read_pixel(_bin, type) { + switch(type) { + case 0 : return [ Bin_read_byte(_bin), Bin_read_byte(_bin), Bin_read_byte(_bin), Bin_read_byte(_bin) ]; + case 1 : return [ Bin_read_byte(_bin), Bin_read_byte(_bin) ]; + case 2 : return [ Bin_read_byte(_bin) ]; + } + return 0; } \ No newline at end of file diff --git a/scripts/node_canvas/node_canvas.gml b/scripts/node_canvas/node_canvas.gml index b3b608c88..de3f0c6d7 100644 --- a/scripts/node_canvas/node_canvas.gml +++ b/scripts/node_canvas/node_canvas.gml @@ -1161,7 +1161,7 @@ function Node_Canvas(_x, _y, _group = noone) : Node(_x, _y, _group) constructor static loadImagePath = function(path, live = false) { if(!file_exists_empty(path)) return noone; - var _spr = sprite_add(path, 0, 0, 0, 0, 0); + var _spr = sprite_add(sprite_path_check_depth(path), 0, 0, 0, 0, 0); if(_spr == -1) return noone; var _sw = sprite_get_width(_spr); @@ -1194,7 +1194,7 @@ function Node_Canvas(_x, _y, _group = noone) : Node(_x, _y, _group) constructor if(tool_selection.is_selected) tool_selection.apply(); - var _spr = sprite_add(path, 0, 0, 0, 0, 0); + var _spr = sprite_add(sprite_path_check_depth(path), 0, 0, 0, 0, 0); if(_spr == -1) return noone; var _sw = sprite_get_width(_spr); diff --git a/scripts/node_image/node_image.gml b/scripts/node_image/node_image.gml index 62419b78b..fe4e76a16 100644 --- a/scripts/node_image/node_image.gml +++ b/scripts/node_image/node_image.gml @@ -45,18 +45,14 @@ function Node_Image(_x, _y, _group = noone) : Node(_x, _y, _group) constructor { array_push(attributeEditors, [ "File Watcher", function() { return attributes.file_checker; }, new checkBox(function() { attributes.file_checker = !attributes.file_checker; }) ]); - on_drop_file = function(path) { + static on_drop_file = function(path) { inputs[0].setValue(path); - if(updatePaths(path)) { - doUpdate(); - return true; - } - + if(updatePaths(path)) { doUpdate(); return true; } return false; } - function createSprite(path) { + static createSprite = function(path) { if(!file_exists(path)) return noone; @@ -69,7 +65,9 @@ function Node_Image(_x, _y, _group = noone) : Node(_x, _y, _group) constructor { case ".jpeg": case ".gif": setDisplayName(_name); - var _spr = sprite_add(path, 1, false, false, 0, 0); + + var _real_path = sprite_path_check_depth(path); + var _spr = sprite_add(_real_path, 1, false, false, 0, 0); if(_spr == -1) { var _txt = $"Image node: File not a valid image."; @@ -84,11 +82,8 @@ function Node_Image(_x, _y, _group = noone) : Node(_x, _y, _group) constructor { return noone; } - function updatePaths(path) { - - if(sprite_exists(spr)) - sprite_delete(spr); - + static updatePaths = function(path) { + if(sprite_exists(spr)) sprite_delete(spr); spr = createSprite(path); } @@ -134,29 +129,28 @@ function Node_Image(_x, _y, _group = noone) : Node(_x, _y, _group) constructor { outputs[0].setValue(_outsurf); - #region splice - if(!attributes.check_splice) return; - attributes.check_splice = false; + if(!attributes.check_splice) return; + attributes.check_splice = false; + + //////////////////////////////////////////////// SPLICE //////////////////////////////////////////////// + + if(LOADING || APPENDING) return; + if(string_pos("strip", display_name) == 0) return; - if(LOADING || APPENDING) return; - if(string_pos("strip", display_name) == 0) return; + var sep_pos = string_pos("strip", display_name) + 5; + var sep = string_copy(display_name, sep_pos, string_length(display_name) - sep_pos + 1); + var amo = toNumber(string_digits(sep)); + + if(amo == 0) return; - var sep_pos = string_pos("strip", display_name) + 5; - var sep = string_copy(display_name, sep_pos, string_length(display_name) - sep_pos + 1); - var amo = toNumber(string_digits(sep)); - - if(amo == 0) return; - - var ww = sprite_get_width(spr) / amo; - var hh = sprite_get_height(spr); - - var _splice = nodeBuild("Node_Image_Sheet", x + w + 64, y); - _splice.inputs[0].setFrom(outputs[0], false); - _splice.inputs[1].setValue([ ww, hh ]); - _splice.inputs[2].setValue(amo); - _splice.inputs[3].setValue([ amo, 1 ]); - - #endregion + var ww = sprite_get_width(spr) / amo; + var hh = sprite_get_height(spr); + + var _splice = nodeBuild("Node_Image_Sheet", x + w + 64, y); + _splice.inputs[0].setFrom(outputs[0], false); + _splice.inputs[1].setValue([ ww, hh ]); + _splice.inputs[2].setValue(amo); + _splice.inputs[3].setValue([ amo, 1 ]); } static dropPath = function(path) { diff --git a/scripts/node_image_animated/node_image_animated.gml b/scripts/node_image_animated/node_image_animated.gml index 1eedb1953..90393c166 100644 --- a/scripts/node_image_animated/node_image_animated.gml +++ b/scripts/node_image_animated/node_image_animated.gml @@ -83,7 +83,7 @@ function Node_Image_Animated(_x, _y, _group = noone) : Node(_x, _y, _group) cons array_push(attributeEditors, [ "File Watcher", function() { return attributes.file_checker; }, new checkBox(function() { attributes.file_checker = !attributes.file_checker; }) ]); - on_drop_file = function(path) { #region + on_drop_file = function(path) { if(directory_exists(path)) { with(dialogCall(o_dialog_drag_folder, WIN_W / 2, WIN_H / 2)) { dir_paths = path; @@ -101,9 +101,9 @@ function Node_Image_Animated(_x, _y, _group = noone) : Node(_x, _y, _group) cons } return false; - } #endregion + } - function updatePaths(paths = path_current) { #region + function updatePaths(paths = path_current) { if(!is_array(paths) && ds_exists(paths, ds_type_list)) paths = ds_list_to_array(paths); @@ -128,7 +128,8 @@ function Node_Image_Animated(_x, _y, _group = noone) : Node(_x, _y, _group) cons case ".png" : case ".jpg" : case ".jpeg" : - var _spr = sprite_add(_path, 1, false, false, 0, 0); + var _real_path = sprite_path_check_depth(path); + var _spr = sprite_add(_real_path, 1, false, false, 0, 0); if(_spr == -1) { var _txt = $"Image node: File not a valid image."; @@ -143,7 +144,7 @@ function Node_Image_Animated(_x, _y, _group = noone) : Node(_x, _y, _group) cons } return true; - } #endregion + } insp1UpdateTooltip = __txt("Refresh"); insp1UpdateIcon = [ THEME.refresh_icon, 1, COLORS._main_value_positive ]; diff --git a/scripts/png_reader/png_reader.gml b/scripts/png_reader/png_reader.gml new file mode 100644 index 000000000..81fafc89d --- /dev/null +++ b/scripts/png_reader/png_reader.gml @@ -0,0 +1,28 @@ +#macro ___PNG_READ_ERROR { if(noti) noti_warning($"PNG header read error."); return noone; } + +function read_png_header(path, noti = true) { + static png_header = [ 137, 80, 78, 71, 13, 10, 26, 10 ]; + + var f = file_bin_open(path, 0); + if(f < 0) ___PNG_READ_ERROR + + var b; + + for (var i = 0, n = array_length(png_header); i < n; i++) { + b = file_bin_read_byte(f); + if(b != png_header[i]) { file_bin_close(f); ___PNG_READ_ERROR } + } + + repeat(4) b = file_bin_read_byte(f); // chunk size + + b = bin_read_chars(f, 4); + if(b != "IHDR") { file_bin_close(f); ___PNG_READ_ERROR } + + var _width = Bin_read_dword(f); + var _height = Bin_read_dword(f); + var _depth = Bin_read_byte(f); + + file_bin_close(f); + + return { width: _width, height: _height, depth: _depth }; +} \ No newline at end of file diff --git a/scripts/png_reader/png_reader.yy b/scripts/png_reader/png_reader.yy new file mode 100644 index 000000000..f647df2ae --- /dev/null +++ b/scripts/png_reader/png_reader.yy @@ -0,0 +1,13 @@ +{ + "$GMScript":"v1", + "%Name":"png_reader", + "isCompatibility":false, + "isDnD":false, + "name":"png_reader", + "parent":{ + "name":"importers", + "path":"folders/functions/importers.yy", + }, + "resourceType":"GMScript", + "resourceVersion":"2.0", +} \ No newline at end of file diff --git a/scripts/sprite_add_functions/sprite_add_functions.gml b/scripts/sprite_add_functions/sprite_add_functions.gml index 816679bd4..9038aadd6 100644 --- a/scripts/sprite_add_functions/sprite_add_functions.gml +++ b/scripts/sprite_add_functions/sprite_add_functions.gml @@ -2,7 +2,8 @@ globalvar SPRITE_PATH_MAP; SPRITE_PATH_MAP = {}; function sprite_add_map(path) { - var _s = sprite_add(path, 1, 0, 0, 0, 0); + var _real_path = sprite_path_check_depth(path); + var _s = sprite_add(_real_path, 1, 0, 0, 0, 0); SPRITE_PATH_MAP[$ path] = _s; return _s; } @@ -17,4 +18,21 @@ function sprite_add_center(path) { sprite_set_offset(_s, _sw / 2, _sh / 2); return _s; +} + +function sprite_path_check_depth(path, noti = true) { + if(filename_ext(path) != ".png") return path; + + var _data = read_png_header(path, noti); + if(_data == noone) return path; + if(_data.depth == 8) return path; + + if(noti) noti_warning($"{_data.depth} bits image is not supported. Proxy will be used."); + + var path_magick = filepath_resolve(PREFERENCES.ImageMagick_path) + "magick.exe"; + var proxy_path = $"{TEMPDIR}{filename_name_only(path)}_{seed_random(6)}.png"; + var shell_cmd = $"convert \"{path}\" -depth 8 \"{proxy_path}\""; + shell_execute(path_magick, shell_cmd, self); + + return proxy_path; } \ No newline at end of file