function Node_Palette_Shrink(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) constructor {
	name = "Shrink Palette";	
	setDimension(96);
	
	newInput(0, nodeValue_Palette("Palette in", self, array_clone(DEF_PALETTE)))
		.setVisible(true, true);
	
	newInput(1, nodeValue_Enum_Button("Algorithm", self,  1, [ "Histogram", "K-mean" ]))
		.rejectArray();
	
	newInput(2, nodeValue_Int("Amount", self, 4));
	
	newInput(3, nodeValueSeed(self));
	
	newInput(4, nodeValue_Enum_Button("Color Space", self, 0, [ "RGB", "HSV" ]))
	
	newOutput(0, nodeValue_Output("Palette", self, VALUE_TYPE.color, []))
		.setDisplay(VALUE_DISPLAY.palette);
	
	input_display_list = [
        0, 4, 1, 2, 
	];
	
	function kmean(_pal) {
		_size  = max(1, getInputData(2));
		_space = getInputData(4);
		
		_min = [ 1, 1, 1 ];
		_max = [ 0, 0, 0 ];
		var _cc, col = 0, colors = [];
		
		for( var i = 0, n = array_length(_pal); i < n; i++ ) {
			_cc = _pal[i];
			
			switch(_space) {
				case 0 : col = [ _color_get_red(_cc), _color_get_green(_cc),      _color_get_blue(_cc),  0 ]; break;
				case 1 : col = [ _color_get_hue(_cc), _color_get_saturation(_cc), _color_get_value(_cc), 0 ]; break;
			}
			
			array_push(colors, col);
			
			_min[0] = min(_min[0], col[0]); _max[0] = max(_max[0], col[0]);
			_min[1] = min(_min[1], col[1]); _max[1] = max(_max[1], col[1]);
			_min[2] = min(_min[2], col[2]); _max[2] = max(_max[2], col[2]);
		}
			
// 		random_set_seed(_seed);
// 		var cnt = array_create_ext(_size, () => [ random_range(_min[0], _max[0]), random_range(_min[1], _max[1]), random_range(_min[2], _max[2]), 0 ]);
		var cnt = array_create_ext(_size, function(i) /*=>*/ {return [ lerp(_min[0], _max[0], i / (_size - 1)), lerp(_min[1], _max[1], i / (_size - 1)), lerp(_min[2], _max[2], i / (_size - 1)), 0 ]});
		
		repeat(8) {
			// var _cnt = array_create_ext(_size, (i) => [ cnt[i][0], cnt[i][1], cnt[i][2], 0 ]);
			
			for( var i = 0, n = array_length(colors); i < n; i++ ) {
				var ind  = 0;
				var dist = 999;
				var _cl  = colors[i];
				
				for( var j = 0; j < _size; j++ ) {
					var _cn = cnt[j];
					var d   = point_distance_3d(_cl[0], _cl[1], _cl[2], _cn[0], _cn[1], _cn[2]);
					
					if(d < dist) {
						dist = d;
						ind  = j;
					}
				}
				
				colors[i][3] = ind;
			}
			
			for( var i = 0; i < _size; i++ )
				cnt[i] = [ 0, 0, 0, 0 ];
				
			for( var i = 0, n = array_length(colors); i < n; i++ ) {
				var _cl = colors[i];
				var _co = _cl[3];
				
				cnt[_co][0] += _cl[0];
				cnt[_co][1] += _cl[1];
				cnt[_co][2] += _cl[2];
				cnt[_co][3]++;
			}
			
			for( var i = 0; i < _size; i++ ) {
				var _cc = cnt[i];
				cnt[i][0] = _cc[3]? _cc[0] / _cc[3] : 0;
				cnt[i][1] = _cc[3]? _cc[1] / _cc[3] : 0;
				cnt[i][2] = _cc[3]? _cc[2] / _cc[3] : 0;
			}
			
			// var del = array_reduce(cnt, (prev, cur, i) => max(prev, point_distance_3d(cnt[i][0], cnt[i][1], cnt[i][2], cur[0], cur[1], cur[2])), 0);
			// if(del < 0.001) break;
		}
		
		var palette = [];
		var clr; 
		
		for( var i = 0; i < _size; i++ ) {
			var closet = 0;
			var dist   = 999;
			var _cl    = cnt[i];
			
			for( var j = 0, n = array_length(colors); j < n; j++ ) {
				var _cn = colors[j];
				var d   = point_distance_3d(_cl[0], _cl[1], _cl[2], _cn[0], _cn[1], _cn[2]);
				
				if(d < dist) {
					dist   = d;
					closet = j;
				}
			}
			
			var _cc = colors[closet];
			
			switch(_space) {
				case 0 : clr = make_color_rgba(_cc[0] * 255, _cc[1] * 255, _cc[2] * 255, 255); break;
				case 1 : clr = make_color_hsva(_cc[0] * 255, _cc[1] * 255, _cc[2] * 255, 255); break;
			}
			
			array_push_unique(palette, clr);
		}
		
		return palette;
	}
	
	function histogram(_pal) {
		var _size  = max(1, getInputData(2));
		var _space = getInputData(4);
		
		var _min = [ 1, 1, 1 ];
		var _max = [ 0, 0, 0 ];
		var _cc, col, colors = [];
		
		for( var i = 0, n = array_length(_pal); i < n; i++ ) {
			_cc = _pal[i];
			
			switch(_space) {
				case 0 : col = [ _color_get_red(_cc), _color_get_green(_cc),      _color_get_blue(_cc),  0 ]; break;
				case 1 : col = [ _color_get_hue(_cc), _color_get_saturation(_cc), _color_get_value(_cc), 0 ]; break;
			}
			
			array_push(colors, col);
			
			_min[0] = min(_min[0], col[0]); _max[0] = max(_max[0], col[0]);
			_min[1] = min(_min[1], col[1]); _max[1] = max(_max[1], col[1]);
			_min[2] = min(_min[2], col[2]); _max[2] = max(_max[2], col[2]);
		}
		
		var palette = array_create(_size);
		var clr, _c0, _c1, _c2;
		
		for( var i = 0, n = array_length(palette); i < n; i++ ) {
		    _c0 = lerp(_min[0], _max[0], i / (n - 1)) * 255;
		    _c1 = lerp(_min[1], _max[1], i / (n - 1)) * 255;
		    _c2 = lerp(_min[2], _max[2], i / (n - 1)) * 255;
			
			switch(_space) {
				case 0 : clr = make_color_rgba(_c0, _c1, _c2, 255); break;
				case 1 : clr = make_color_hsva(_c0, _c1, _c2, 255); break;
			}
			
		    palette[i] = clr;
		}
		
		return palette;
	}
	
	static processData = function(_outSurf, _data, _output_index, _array_index) {
		var _pal = _data[0];
		var _alg = _data[1];
		if(!is_array(_pal)) return;
		
		switch(_alg) {
		    case 0 : return histogram(_pal); 
		    case 1 : return kmean(_pal); 
		}
		
		return _pal;
	}
	
	static onDrawNode = function(xx, yy, _mx, _my, _s, _hover, _focus) {
		var bbox = drawGetBbox(xx, yy, _s);
		if(bbox.h < 1) return;
		
		var pal = outputs[0].getValue();
		if(array_empty(pal)) return;
		if(!is_array(pal[0])) pal = [ pal ];
		
		var _h = array_length(pal) * 32;
		var _y = bbox.y0;
		var gh = bbox.h / array_length(pal);
			
		for( var i = 0, n = array_length(pal); i < n; i++ ) {
			drawPalette(pal[i], bbox.x0, _y, bbox.w, gh);
			_y += gh;
		}
		
		if(_h != min_h) will_setHeight = true;
		min_h = _h;	
	}
}