jpeg compression

This commit is contained in:
Tanasart 2024-06-09 14:56:22 +07:00
parent b4c46e6ffb
commit 0bfcef97b5
22 changed files with 408 additions and 9 deletions

View file

@ -146,6 +146,7 @@
{"name":"corner","order":43,"path":"folders/shader/filter/corner.yy",},
{"name":"dither","order":53,"path":"folders/shader/filter/dither.yy",},
{"name":"edge_shade","order":44,"path":"folders/shader/filter/edge_shade.yy",},
{"name":"jpeg","order":55,"path":"folders/shader/filter/jpeg.yy",},
{"name":"morph","order":45,"path":"folders/shader/filter/morph.yy",},
{"name":"shadow_caster","order":46,"path":"folders/shader/filter/shadow_caster.yy",},
{"name":"shape_seperator","order":47,"path":"folders/shader/filter/shape_seperator.yy",},
@ -822,6 +823,7 @@
{"name":"node_iterator_sort_inline_output","order":2,"path":"scripts/node_iterator_sort_inline_output/node_iterator_sort_inline_output.yy",},
{"name":"node_iterator_sort_input","order":1,"path":"scripts/node_iterator_sort_input/node_iterator_sort_input.yy",},
{"name":"node_iterator_sort_output","order":2,"path":"scripts/node_iterator_sort_output/node_iterator_sort_output.yy",},
{"name":"node_jpeg","order":23,"path":"scripts/node_jpeg/node_jpeg.yy",},
{"name":"node_json_file_read","order":7,"path":"scripts/node_json_file_read/node_json_file_read.yy",},
{"name":"node_json_file_write","order":11,"path":"scripts/node_json_file_write/node_json_file_write.yy",},
{"name":"node_keyframe","order":4,"path":"scripts/node_keyframe/node_keyframe.yy",},
@ -1408,6 +1410,7 @@
{"name":"sh_herringbone_tile","order":5,"path":"shaders/sh_herringbone_tile/sh_herringbone_tile.yy",},
{"name":"sh_image_trace","order":34,"path":"shaders/sh_image_trace/sh_image_trace.yy",},
{"name":"sh_invert","order":17,"path":"shaders/sh_invert/sh_invert.yy",},
{"name":"sh_jpeg_recons","order":1,"path":"shaders/sh_jpeg_recons/sh_jpeg_recons.yy",},
{"name":"sh_kuwahara_ani","order":37,"path":"shaders/sh_kuwahara_ani/sh_kuwahara_ani.yy",},
{"name":"sh_kuwahara","order":36,"path":"shaders/sh_kuwahara/sh_kuwahara.yy",},
{"name":"sh_level_selector","order":15,"path":"shaders/sh_level_selector/sh_level_selector.yy",},
@ -1784,6 +1787,7 @@
{"name":"s_node_iterator_amount","order":26,"path":"sprites/s_node_iterator_amount/s_node_iterator_amount.yy",},
{"name":"s_node_iterator_index","order":8,"path":"sprites/s_node_iterator_index/s_node_iterator_index.yy",},
{"name":"s_node_iterator_length","order":24,"path":"sprites/s_node_iterator_length/s_node_iterator_length.yy",},
{"name":"s_node_JPEG","order":64,"path":"sprites/s_node_JPEG/s_node_JPEG.yy",},
{"name":"s_node_json_file_read","order":33,"path":"sprites/s_node_json_file_read/s_node_json_file_read.yy",},
{"name":"s_node_json_file_write","order":32,"path":"sprites/s_node_json_file_write/s_node_json_file_write.yy",},
{"name":"s_node_kuwahara","order":31,"path":"sprites/s_node_kuwahara/s_node_kuwahara.yy",},

View file

@ -275,6 +275,7 @@
{"$GMFolder":"","%Name":"corner","folderPath":"folders/shader/filter/corner.yy","name":"corner","resourceType":"GMFolder","resourceVersion":"2.0",},
{"$GMFolder":"","%Name":"dither","folderPath":"folders/shader/filter/dither.yy","name":"dither","resourceType":"GMFolder","resourceVersion":"2.0",},
{"$GMFolder":"","%Name":"edge_shade","folderPath":"folders/shader/filter/edge_shade.yy","name":"edge_shade","resourceType":"GMFolder","resourceVersion":"2.0",},
{"$GMFolder":"","%Name":"jpeg","folderPath":"folders/shader/filter/jpeg.yy","name":"jpeg","resourceType":"GMFolder","resourceVersion":"2.0",},
{"$GMFolder":"","%Name":"morph","folderPath":"folders/shader/filter/morph.yy","name":"morph","resourceType":"GMFolder","resourceVersion":"2.0",},
{"$GMFolder":"","%Name":"shadow_caster","folderPath":"folders/shader/filter/shadow_caster.yy","name":"shadow_caster","resourceType":"GMFolder","resourceVersion":"2.0",},
{"$GMFolder":"","%Name":"shape_seperator","folderPath":"folders/shader/filter/shape_seperator.yy","name":"shape_seperator","resourceType":"GMFolder","resourceVersion":"2.0",},
@ -1252,6 +1253,7 @@
{"id":{"name":"node_iterator_sort_inline_output","path":"scripts/node_iterator_sort_inline_output/node_iterator_sort_inline_output.yy",},},
{"id":{"name":"node_iterator_sort_input","path":"scripts/node_iterator_sort_input/node_iterator_sort_input.yy",},},
{"id":{"name":"node_iterator_sort_output","path":"scripts/node_iterator_sort_output/node_iterator_sort_output.yy",},},
{"id":{"name":"node_jpeg","path":"scripts/node_jpeg/node_jpeg.yy",},},
{"id":{"name":"node_json_file_read","path":"scripts/node_json_file_read/node_json_file_read.yy",},},
{"id":{"name":"node_json_file_write","path":"scripts/node_json_file_write/node_json_file_write.yy",},},
{"id":{"name":"node_keyframe","path":"scripts/node_keyframe/node_keyframe.yy",},},
@ -1928,6 +1930,8 @@
{"id":{"name":"sh_image_trace","path":"shaders/sh_image_trace/sh_image_trace.yy",},},
{"id":{"name":"sh_interpret_number","path":"shaders/sh_interpret_number/sh_interpret_number.yy",},},
{"id":{"name":"sh_invert","path":"shaders/sh_invert/sh_invert.yy",},},
{"id":{"name":"sh_jpeg_dct","path":"shaders/sh_jpeg_dct/sh_jpeg_dct.yy",},},
{"id":{"name":"sh_jpeg_recons","path":"shaders/sh_jpeg_recons/sh_jpeg_recons.yy",},},
{"id":{"name":"sh_kuwahara_ani","path":"shaders/sh_kuwahara_ani/sh_kuwahara_ani.yy",},},
{"id":{"name":"sh_kuwahara","path":"shaders/sh_kuwahara/sh_kuwahara.yy",},},
{"id":{"name":"sh_level_selector","path":"shaders/sh_level_selector/sh_level_selector.yy",},},
@ -2356,6 +2360,7 @@
{"id":{"name":"s_node_iterator_amount","path":"sprites/s_node_iterator_amount/s_node_iterator_amount.yy",},},
{"id":{"name":"s_node_iterator_index","path":"sprites/s_node_iterator_index/s_node_iterator_index.yy",},},
{"id":{"name":"s_node_iterator_length","path":"sprites/s_node_iterator_length/s_node_iterator_length.yy",},},
{"id":{"name":"s_node_JPEG","path":"sprites/s_node_JPEG/s_node_JPEG.yy",},},
{"id":{"name":"s_node_json_file_read","path":"sprites/s_node_json_file_read/s_node_json_file_read.yy",},},
{"id":{"name":"s_node_json_file_write","path":"sprites/s_node_json_file_write/s_node_json_file_write.yy",},},
{"id":{"name":"s_node_json_parse","path":"sprites/s_node_json_parse/s_node_json_parse.yy",},},

View file

@ -36,10 +36,10 @@
globalvar VERSION, SAVE_VERSION, VERSION_STRING, BUILD_NUMBER, LATEST_VERSION;
LATEST_VERSION = 11700;
VERSION = 11722;
SAVE_VERSION = 11690;
VERSION_STRING = "1.17.2.2";
BUILD_NUMBER = 11721;
VERSION = 11730;
SAVE_VERSION = 11700;
VERSION_STRING = "1.17.3.0";
BUILD_NUMBER = 11730;
globalvar HOTKEYS, HOTKEY_CONTEXT;
HOTKEYS = ds_map_create();

View file

@ -0,0 +1,12 @@
{
"isDnD": false,
"isCompatibility": false,
"parent": {
"name": "filter",
"path": "folders/nodes/data/filter.yy",
},
"resourceVersion": "1.0",
"name": "node_alpha_to_grey",
"tags": [],
"resourceType": "GMScript",
}

View file

@ -0,0 +1,12 @@
{
"isDnD": false,
"isCompatibility": false,
"parent": {
"name": "filter",
"path": "folders/nodes/data/filter.yy",
},
"resourceVersion": "1.0",
"name": "node_bw",
"tags": [],
"resourceType": "GMScript",
}

View file

@ -0,0 +1,12 @@
{
"isDnD": false,
"isCompatibility": false,
"parent": {
"name": "filter",
"path": "folders/nodes/data/filter.yy",
},
"resourceVersion": "1.0",
"name": "node_color_adjustment",
"tags": [],
"resourceType": "GMScript",
}

View file

@ -0,0 +1,12 @@
{
"isDnD": false,
"isCompatibility": false,
"parent": {
"name": "process",
"path": "folders/nodes/data/process.yy",
},
"resourceVersion": "1.0",
"name": "node_color_replacement",
"tags": [],
"resourceType": "GMScript",
}

View file

@ -0,0 +1,12 @@
{
"isDnD": false,
"isCompatibility": false,
"parent": {
"name": "filter",
"path": "folders/nodes/data/filter.yy",
},
"resourceVersion": "1.0",
"name": "node_greyscale",
"tags": [],
"resourceType": "GMScript",
}

View file

@ -0,0 +1,76 @@
function Node_JPEG(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) constructor {
name = "JPEG";
inputs[| 0] = nodeValue("Surface in", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, noone);
inputs[| 1] = nodeValue("Active", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, true);
active_index = 1;
inputs[| 2] = nodeValue("Patch Size", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 8);
inputs[| 3] = nodeValue("Compression", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 10);
inputs[| 4] = nodeValue("Reconstruction", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 8);
inputs[| 5] = nodeValue("Mask", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, noone);
inputs[| 6] = nodeValue("Mix", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 1)
.setDisplay(VALUE_DISPLAY.slider);
inputs[| 7] = nodeValue("Channel", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0b1111)
.setDisplay(VALUE_DISPLAY.toggle, { data: array_create(4, THEME.inspector_channel) });
__init_mask_modifier(5); // inputs 8, 9
outputs[| 0] = nodeValue("Surface out", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone);
input_display_list = [ 1,
["Surface", false], 0, 5, 6, 7,
["Effects", false], 2, 3, 4,
];
temp_surface = array_create(2);
attribute_surface_depth();
static step = function() { #region
__step_mask_modifier();
} #endregion
static processData = function(_outSurf, _data, _output_index, _array_index) { #region
var _surf = _data[0];
var _patc = _data[2];
var _comp = _data[3];
var _recn = _data[4];
var _dim = surface_get_dimension(_surf);
for( var i = 0; i < 2; i++ ) temp_surface[i] = surface_verify(temp_surface[i], _dim[0], _dim[1], surface_rgba16float);
surface_set_shader(temp_surface[0], sh_jpeg_dct);
shader_set_f("dimension", _dim);
shader_set_i("patch", _patc);
shader_set_f("compression", _comp);
draw_surface_safe(_surf);
surface_reset_shader();
surface_set_shader(temp_surface[1], sh_jpeg_recons);
shader_set_f("dimension", _dim);
shader_set_i("patch", _patc);
shader_set_i("reconstruct", _recn);
draw_surface_safe(temp_surface[0]);
surface_reset_shader();
surface_set_shader(_outSurf);
draw_surface_safe(temp_surface[1]);
surface_reset_shader();
__process_mask_modifier(_data);
_outSurf = mask_apply(_data[0], _outSurf, _data[5], _data[6]);
_outSurf = channel_apply(_data[0], _outSurf, _data[7]);
return _outSurf;
} #endregion
}

View file

@ -0,0 +1,13 @@
{
"$GMScript":"",
"%Name":"node_jpeg",
"isCompatibility":false,
"isDnD":false,
"name":"node_jpeg",
"parent":{
"name":"effects",
"path":"folders/nodes/data/filter/effects.yy",
},
"resourceType":"GMScript",
"resourceVersion":"2.0",
}

View file

@ -0,0 +1,12 @@
{
"isDnD": false,
"isCompatibility": false,
"parent": {
"name": "process",
"path": "folders/nodes/data/process.yy",
},
"resourceVersion": "1.0",
"name": "node_outline",
"tags": [],
"resourceType": "GMScript",
}

View file

@ -342,7 +342,7 @@ function __initNodes() {
addNodeObject(itere_il, "Array Length", s_node_iterator_length, "Node_Iterator_Length", [1, Node_Iterator_Length]).hideRecent();
#endregion
var filter = ds_list_create(); #region //filter
var filter = ds_list_create(); #region //iterate filter
NODE_ADD_CAT("Filter", filter, ["Node_Iterate_Filter"], COLORS.node_blend_loop);
ds_list_add(filter, "Groups");
addNodeObject(filter, "Input", s_node_group_input, "Node_Group_Input", [1, Node_Group_Input]).hideRecent();
@ -354,14 +354,14 @@ function __initNodes() {
addNodeObject(filter, "Array Length", s_node_iterator_length, "Node_Iterator_Each_Length", [1, Node_Iterator_Each_Length]).hideRecent();
#endregion
var filter_il = ds_list_create(); #region //filter inline
var filter_il = ds_list_create(); #region //iterate filter inline
NODE_ADD_CAT("Filter", filter_il, ["Node_Iterate_Filter_Inline"], COLORS.node_blend_loop);
ds_list_add(filter_il, "Loops");
addNodeObject(filter_il, "Index", s_node_iterator_index, "Node_Iterator_Index", [1, Node_Iterator_Index]).hideRecent();
addNodeObject(filter_il, "Array Length", s_node_iterator_length, "Node_Iterator_Length", [1, Node_Iterator_Length]).hideRecent();
#endregion
var feed = ds_list_create(); #region //feedback
var feed = ds_list_create(); #region //iterate feedback
NODE_ADD_CAT("Feedback", feed, ["Node_Feedback"], COLORS.node_blend_feedback);
ds_list_add(feed, "Groups");
addNodeObject(feed, "Input", s_node_feedback_input, "Node_Feedback_Input", [1, Node_Feedback_Input]).hideRecent();
@ -607,7 +607,8 @@ function __initNodes() {
addNodeObject(filter, "Replace Image", s_node_image_replace, "Node_Surface_Replace", [1, Node_Surface_Replace], ["image replace"], "Replace instances of an image with a new one.").setVersion(1140);
addNodeObject(filter, "Chromatic Aberration", s_node_chromatic_abarration, "Node_Chromatic_Aberration", [1, Node_Chromatic_Aberration],, "Apply chromatic aberration effect to the image.");
addNodeObject(filter, "Vignette", s_node_vignette, "Node_Vignette", [1, Node_Vignette],, "Apply vignette effect to the border.").setVersion(11630);
addNodeObject(filter, "FXAA", s_node_FXAA, "Node_FXAA", [1, Node_FXAA],, "Apply fast approximate anti-aliasing to the image.");
addNodeObject(filter, "FXAA", s_node_FXAA, "Node_FXAA", [1, Node_FXAA],, "Apply fast approximate anti-aliasing to te image.");
addNodeObject(filter, "JPEG", s_node_JPEG, "Node_JPEG", [1, Node_JPEG],, "Apply JPEG compression to the image.").setVersion(11730);
//addNodeObject(filter, "Blend Edge", s_node_FXAA, "Node_Blend_Edge", [1, Node_Blend_Edge]).setVersion(11640);
ds_list_add(filter, "Colors");

View file

@ -1999,7 +1999,6 @@ function Panel_Graph(project = PROJECT) : PanelContent() constructor {
draw_clear(bg_color);
node_bg_hovering = drawBasePreview();
drawGrid();
drawViewControl();
var ovy = ui(8);
if(show_view_control == 2)
@ -2015,6 +2014,8 @@ function Panel_Graph(project = PROJECT) : PanelContent() constructor {
drawToolBar();
drawMinimap();
drawViewControl();
if(pFOCUS && !view_hovering)
array_foreach(nodes_selecting, function(node) { node.focusStep(); });

View file

@ -0,0 +1,40 @@
#define PI 3.1415972
#define SQRT2 0.70710678118
varying vec2 v_vTexcoord;
varying vec4 v_vColour;
uniform vec2 dimension;
uniform int patch;
uniform float compression;
float DCTcoeff(vec2 k, vec2 x) { return cos(PI * k.x * x.x) * cos(PI * k.y * x.y); }
float round(float val) { return fract(val) > 0.5? ceil(val) : floor(val); }
vec4 round(vec4 val) { return vec4(round(val.x), round(val.y), round(val.z), round(val.w)); }
void main() {
vec2 tx = dimension * v_vTexcoord;
vec2 k = mod(tx, float(patch)) - .5;
vec2 K = floor(tx - k);
vec4 val = vec4(0.);
for(int x = 0; x < patch; ++x)
for(int y = 0; y < patch; ++y) {
vec4 s = texture2D( gm_BaseTexture, (K + vec2(x, y) + .5) / dimension);
float c = DCTcoeff(k, (vec2(x, y) + .5) / float(patch));
c *= k.x < .5? SQRT2 : 1.;
c *= k.y < .5? SQRT2 : 1.;
val += s * c;
}
vec4 c = val / float(patch) * 2.;
if(compression != 0.)
c = round(c / float(patch) * compression) / compression * float(patch);
c.a = 1.;
gl_FragColor = c;
}

View file

@ -0,0 +1,19 @@
//
// Simple passthrough vertex shader
//
attribute vec3 in_Position; // (x,y,z)
//attribute vec3 in_Normal; // (x,y,z) unused in this shader.
attribute vec4 in_Colour; // (r,g,b,a)
attribute vec2 in_TextureCoord; // (u,v)
varying vec2 v_vTexcoord;
varying vec4 v_vColour;
void main()
{
vec4 object_space_pos = vec4( in_Position.x, in_Position.y, in_Position.z, 1.0);
gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * object_space_pos;
v_vColour = in_Colour;
v_vTexcoord = in_TextureCoord;
}

View file

@ -0,0 +1,12 @@
{
"$GMShader":"",
"%Name":"sh_jpeg_dct",
"name":"sh_jpeg_dct",
"parent":{
"name":"jpeg",
"path":"folders/shader/filter/jpeg.yy",
},
"resourceType":"GMShader",
"resourceVersion":"2.0",
"type":1,
}

View file

@ -0,0 +1,35 @@
#define PI 3.1415972
#define SQRT2 0.70710678118
varying vec2 v_vTexcoord;
varying vec4 v_vColour;
uniform vec2 dimension;
uniform int patch;
uniform int reconstruct;
float DCTcoeff(vec2 k, vec2 x) { return cos(PI * k.x * x.x) * cos(PI * k.y * x.y); }
void main() {
vec2 tx = dimension * v_vTexcoord;
vec2 k = mod(tx, float(patch)) - .5;
vec2 K = floor(tx - k);
vec4 val = vec4(0.);
for(int u = 0; u < reconstruct; ++u)
for(int v = 0; v < reconstruct; ++v) {
vec4 s = texture2D( gm_BaseTexture, (K + vec2(u, v) + .5) / dimension);
float c = DCTcoeff(vec2(u, v), (k + .5) / float(patch));
c *= u == 0? SQRT2 : 1.;
c *= v == 0? SQRT2 : 1.;
val += s * c;
}
vec4 c = val / float(patch) * 2.;
c.a = 1.;
gl_FragColor = c;
}

View file

@ -0,0 +1,19 @@
//
// Simple passthrough vertex shader
//
attribute vec3 in_Position; // (x,y,z)
//attribute vec3 in_Normal; // (x,y,z) unused in this shader.
attribute vec4 in_Colour; // (r,g,b,a)
attribute vec2 in_TextureCoord; // (u,v)
varying vec2 v_vTexcoord;
varying vec4 v_vColour;
void main()
{
vec4 object_space_pos = vec4( in_Position.x, in_Position.y, in_Position.z, 1.0);
gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * object_space_pos;
v_vColour = in_Colour;
v_vTexcoord = in_TextureCoord;
}

View file

@ -0,0 +1,12 @@
{
"$GMShader":"",
"%Name":"sh_jpeg_recons",
"name":"sh_jpeg_recons",
"parent":{
"name":"jpeg",
"path":"folders/shader/filter/jpeg.yy",
},
"resourceType":"GMShader",
"resourceVersion":"2.0",
"type":1,
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View file

@ -0,0 +1,90 @@
{
"$GMSprite":"",
"%Name":"s_node_JPEG",
"bboxMode":0,
"bbox_bottom":63,
"bbox_left":0,
"bbox_right":63,
"bbox_top":0,
"collisionKind":1,
"collisionTolerance":0,
"DynamicTexturePage":false,
"edgeFiltering":false,
"For3D":false,
"frames":[
{"$GMSpriteFrame":"","%Name":"a02bf45d-ddc2-409a-b61d-a54149a7b232","name":"a02bf45d-ddc2-409a-b61d-a54149a7b232","resourceType":"GMSpriteFrame","resourceVersion":"2.0",},
],
"gridX":0,
"gridY":0,
"height":64,
"HTile":false,
"layers":[
{"$GMImageLayer":"","%Name":"924815a4-08c5-44a6-a900-1c42c68313bd","blendMode":0,"displayName":"default","isLocked":false,"name":"924815a4-08c5-44a6-a900-1c42c68313bd","opacity":100.0,"resourceType":"GMImageLayer","resourceVersion":"2.0","visible":true,},
],
"name":"s_node_JPEG",
"nineSlice":null,
"origin":4,
"parent":{
"name":"filter",
"path":"folders/nodes/icons/filter.yy",
},
"preMultiplyAlpha":false,
"resourceType":"GMSprite",
"resourceVersion":"2.0",
"sequence":{
"$GMSequence":"",
"%Name":"s_node_JPEG",
"autoRecord":true,
"backdropHeight":768,
"backdropImageOpacity":0.5,
"backdropImagePath":"",
"backdropWidth":1366,
"backdropXOffset":0.0,
"backdropYOffset":0.0,
"events":{
"$KeyframeStore<MessageEventKeyframe>":"",
"Keyframes":[],
"resourceType":"KeyframeStore<MessageEventKeyframe>",
"resourceVersion":"2.0",
},
"eventStubScript":null,
"eventToFunction":{},
"length":1.0,
"lockOrigin":false,
"moments":{
"$KeyframeStore<MomentsEventKeyframe>":"",
"Keyframes":[],
"resourceType":"KeyframeStore<MomentsEventKeyframe>",
"resourceVersion":"2.0",
},
"name":"s_node_JPEG",
"playback":1,
"playbackSpeed":30.0,
"playbackSpeedType":0,
"resourceType":"GMSequence",
"resourceVersion":"2.0",
"showBackdrop":true,
"showBackdropImage":false,
"timeUnits":1,
"tracks":[
{"$GMSpriteFramesTrack":"","builtinName":0,"events":[],"inheritsTrackColour":true,"interpolation":1,"isCreationTrack":false,"keyframes":{"$KeyframeStore<SpriteFrameKeyframe>":"","Keyframes":[
{"$Keyframe<SpriteFrameKeyframe>":"","Channels":{
"0":{"$SpriteFrameKeyframe":"","Id":{"name":"a02bf45d-ddc2-409a-b61d-a54149a7b232","path":"sprites/s_node_JPEG/s_node_JPEG.yy",},"resourceType":"SpriteFrameKeyframe","resourceVersion":"2.0",},
},"Disabled":false,"id":"f5aefaee-4dd7-4311-9dcc-348ef8adaf02","IsCreationKey":false,"Key":0.0,"Length":1.0,"resourceType":"Keyframe<SpriteFrameKeyframe>","resourceVersion":"2.0","Stretch":false,},
],"resourceType":"KeyframeStore<SpriteFrameKeyframe>","resourceVersion":"2.0",},"modifiers":[],"name":"frames","resourceType":"GMSpriteFramesTrack","resourceVersion":"2.0","spriteId":null,"trackColour":0,"tracks":[],"traits":0,},
],
"visibleRange":null,
"volume":1.0,
"xorigin":32,
"yorigin":32,
},
"swatchColours":null,
"swfPrecision":0.5,
"textureGroupId":{
"name":"Default",
"path":"texturegroups/Default",
},
"type":0,
"VTile":false,
"width":64,
}