PageSourceSearch

https://www.toolpic.com/app/editor/js/tools.js

js toolpic.com collected 2026-10-02 10:53:46 UTC 11,829 bytes, 366 lines download raw bytes

1/* global POP, MAIN, SIFT, LAYER, IMAGE, EVENTS, HELPER, EDIT, GUI, EL */
2/* global WIDTH, HEIGHT, COLOR, canvas_active */
3
4var TOOLS = new TOOLS_CLASS();
5
6/** 
7 * manages various tools
8 * 
9 * @author toolpic.com
10 */
11function TOOLS_CLASS() {
12
13	//sprites
14	this.tools_sprites = function () {
15		POP.add({name: "param1", title: "Gap:", value: "50", values: ["0", "10", "50", "100"]});
16		POP.add({name: "param2", title: "Width:", value: WIDTH});
17		POP.show('Sprites', function (response) {
18			EDIT.save_state();
19			var param1 = parseInt(response.param1);
20			var sprite_width = parseInt(response.param2);
21			TOOLS.generate_sprites(param1, sprite_width);
22		});
23	};
24
25	//show keypoints
26	this.tools_keypoints = function () {
27		SIFT.generate_keypoints(canvas_active(true), true);
28	};
29
30	//create panorama
31	this.tools_panorama = function () {
32		SIFT.panorama();
33	};
34
35	//extract alpha channel
36	this.tools_color2alpha = function () {
37		POP.add({name: "param1", title: "Color:", value: COLOR, type: 'color'});
38		POP.show(
39			'Color to alpha',
40			function (user_response) {
41				EDIT.save_state();
42				var param1 = user_response.param1;
43				TOOLS.convert_color_to_alpha(canvas_active(), WIDTH, HEIGHT, param1);
44				GUI.zoom();
45			},
46			function (user_response, canvas_preview, w, h) {
47				var param1 = user_response.param1;
48				TOOLS.convert_color_to_alpha(canvas_preview, w, h, param1);
49			}
50		);
51	};
52
53	//expands colors
54	this.tools_color_zoom = function () {
55		POP.add({name: "param1", title: "Zoom:", value: "2", range: [2, 20], });
56		POP.add({name: "param2", title: "Center:", value: "128", range: [0, 255]});
57		POP.show(
58			'Color Zoom',
59			function (user_response) {
60				EDIT.save_state();
61				var param1 = parseInt(user_response.param1);
62				var param2 = parseInt(user_response.param2);
63
64				TOOLS.color_zoom(canvas_active(), WIDTH, HEIGHT, param1, param2);
65				GUI.zoom();
66			},
67			function (user_response, canvas_preview, w, h) {
68				var param1 = parseInt(user_response.param1);
69				var param2 = parseInt(user_response.param2);
70
71				TOOLS.color_zoom(canvas_preview, w, h, param1, param2);
72			}
73		);
74	};
75
76	//recover alpha channel values
77	this.tools_restore_alpha = function () {
78		POP.add({name: "param", title: "Level:", value: "128", range: [0, 255]});
79		POP.show(
80			'Recover alpha',
81			function (user_response) {
82				EDIT.save_state();
83				var param = parseInt(user_response.param);
84
85				TOOLS.recover_alpha(canvas_active(), WIDTH, HEIGHT, param);
86				GUI.zoom();
87			},
88			function (user_response, canvas_preview, w, h) {
89				var param = parseInt(user_response.param);
90
91				TOOLS.recover_alpha(canvas_preview, w, h, param);
92			}
93		);
94	};
95
96	//adds borders
97	this.tools_borders = function () {
98		POP.add({name: "color", title: "Color:", value: COLOR, type: 'color'});
99		POP.add({name: "shadow", title: "Shadow:", values: ["No", "Yes"]});
100		POP.add({name: "size", title: "Size:", value: "5", range: [1, 100]});
101		POP.show(
102			'Borders',
103			function (user_response) {
104				EDIT.save_state();
105				var color = user_response.color;
106				var size = Math.round(WIDTH / 100 * user_response.size);
107				var shadow = false;
108				if(user_response.shadow == 'Yes')
109					shadow = true;
110
111				TOOLS.add_borders(canvas_active(), WIDTH, HEIGHT, color, size, shadow);
112				GUI.zoom();
113			},
114			function (user_response, canvas_preview, w, h) {
115				var color = user_response.color;
116				var size = Math.round(w / 100 * user_response.size);
117				var shadow = false;
118				if(user_response.shadow == 'Yes')
119					shadow = true;
120				
121				TOOLS.add_borders(canvas_preview, w, h, color, size, shadow);
122			}
123		);
124	};
125	
126	this.generate_sprites = function (gap, sprite_width) {
127		if (LAYER.layers.length == 1)
128			return false;
129		EDIT.save_state();
130		LAYER.layer_add();
131		var xx = 0;
132		var yy = 0;
133		var max_height = 0;
134		var tmp = document.createElement("canvas");
135		tmp.setAttribute('id', "tmp_canvas");
136		tmp.width = sprite_width;
137		tmp.height = HEIGHT;
138		var W = sprite_width;
139		var H = HEIGHT;
140		
141		//prepare width
142		WIDTH = sprite_width;
143		LAYER.set_canvas_size();
144		
145		for(var i = LAYER.layers.length-1; i >=0; i--){
146			if (i == LAYER.layer_active)
147				continue;	//end
148			if (LAYER.layers[i].visible == false)
149				continue;
150
151			tmp.getContext("2d").clearRect(0, 0, W, H);
152			tmp.getContext("2d").drawImage(document.getElementById(LAYER.layers[i].name), 0, 0);
153
154			var trim_details = IMAGE.trim_info(tmp, false); //trim
155			if (WIDTH == trim_details.left)
156				continue; //empty layer
157			var width = W - trim_details.left - trim_details.right;
158			var height = H - trim_details.top - trim_details.bottom;
159
160			if (xx + width > sprite_width) {
161				xx = 0;
162				yy += max_height;
163				max_height = 0;
164			}
165			if (yy % gap > 0 && gap > 0)
166				yy = yy - yy % gap + gap;
167			if (yy + height > HEIGHT) {
168				EVENTS.autosize = false;
169				HEIGHT = yy + height;
170				LAYER.set_canvas_size();
171			}
172
173			canvas_active().drawImage(tmp, trim_details.left, trim_details.top, width, height, xx, yy, width, height);
174			xx += width;
175			if (gap > 0)
176				xx = xx - xx % gap + gap;
177
178			if (height > max_height)
179				max_height = height;
180			if (xx > sprite_width) {
181				xx = 0;
182				yy += max_height;
183				max_height = 0;
184			}
185		}
186		
187		//remove other layers
188		for(var i = LAYER.layers.length-1; i >= 0; i--) {
189			if (i == LAYER.layer_active)
190				continue;
191			LAYER.layer_remove(i, true);
192		}
193		LAYER.layer_renew();
194	};
195	
196	this.convert_color_to_alpha = function (context, W, H, color) {
197		var img = context.getImageData(0, 0, W, H);
198		var imgData = img.data;
199		var back_color = HELPER.hex2rgb(color);
200
201		for (var i = 0; i < imgData.length; i += 4) {
202			if (imgData[i + 3] == 0)
203				continue;	//transparent
204
205			//calculate difference from requested color, and change alpha
206			var diff = Math.abs(imgData[i] - back_color.r) + Math.abs(imgData[i + 1] - back_color.g) + Math.abs(imgData[i + 2] - back_color.b) / 3;
207			imgData[i + 3] = Math.round(diff);
208
209			//combining 2 layers in future will change colors, so make changes to get same colors in final image
210			//color_result = color_1 * (alpha_1 / 255) * (1 - A2 / 255) + color_2 * (alpha_2 / 255)
211			//color_2 = (color_result - color_1 * (alpha_1 / 255) * (1 - A2 / 255)) / (alpha_2 / 255)
212			imgData[i] = Math.ceil((imgData[i] - back_color.r * (1 - imgData[i + 3] / 255)) / (imgData[i + 3] / 255));
213			imgData[i + 1] = Math.ceil((imgData[i + 1] - back_color.g * (1 - imgData[i + 3] / 255)) / (imgData[i + 3] / 255));
214			imgData[i + 2] = Math.ceil((imgData[i + 2] - back_color.b * (1 - imgData[i + 3] / 255)) / (imgData[i + 3] / 255));
215		}
216		context.putImageData(img, 0, 0);
217	};
218	
219	this.color_zoom = function (context, W, H, zoom, center) {
220		var img = context.getImageData(0, 0, W, H);
221		var imgData = img.data;
222		var grey;
223		for (var i = 0; i < imgData.length; i += 4) {
224			if (imgData[i + 3] == 0)
225				continue;	//transparent
226
227			grey = Math.round(0.2126 * imgData[i] + 0.7152 * imgData[i + 1] + 0.0722 * imgData[i + 2]);
228
229			for (var j = 0; j < 3; j++) {
230				var k = i + j;
231				if (grey > center)
232					imgData[k] += (imgData[k] - center) * zoom;
233				else if (grey < center)
234					imgData[k] -= (center - imgData[k]) * zoom;
235				if (imgData[k] < 0)
236					imgData[k] = 0;
237				if (imgData[k] > 255)
238					imgData[k] = 255;
239			}
240		}
241		context.putImageData(img, 0, 0);
242	};
243	
244	this.recover_alpha = function (context, W, H, level) {
245		var img = context.getImageData(0, 0, W, H);
246		var imgData = img.data;
247		var tmp;
248		level = parseInt(level);
249		for (var i = 0; i < imgData.length; i += 4) {
250			tmp = imgData[i + 3] + level;
251			if (tmp > 255)
252				tmp = 255;
253			imgData[i + 3] = tmp;
254		}
255		context.putImageData(img, 0, 0);
256	};
257	
258	this.add_borders = function (context, W, H, color, size, shadow) {
259		context.save();
260		if(shadow == true){
261			//with shadow
262			context.beginPath();
263			context.lineWidth = size;
264			context.strokeStyle = 'green';
265			context.shadowColor = color;
266			context.shadowBlur = size/2;
267			context.rect(-size/2, -size/2, W+size, H+size);
268			context.stroke();
269			context.stroke();
270			context.stroke();
271			context.stroke();
272			context.stroke();			
273		}
274		else{
275			context.strokeStyle = color;
276			context.lineWidth = size;
277			EL.rectangle(context, 0, 0, W-1, H-1, false, true);
278		}
279		context.restore();
280	};
281	
282	this.tools_replace_color = function(){
283		POP.add({name: "target", title: "Target:", value: COLOR, type: 'color'});
284		POP.add({name: "repalcement", title: "Replacement:", value: '#ff0000', type: 'color'});
285		POP.add({name: "power", title: "Power:", value: "20", range: [0, 255]});
286		POP.add({name: "alpha", title: "Alpha:", value: "255", range: [0, 255]});
287		POP.add({name: "mode", title: "Mode:", values: ['Advanced', 'Simple']});
288		POP.show(
289			'Replace color',
290			function (user_response) {
291				EDIT.save_state();
292				var target = user_response.target;
293				var repalcement = user_response.repalcement;
294				var power = user_response.power;
295				var alpha = user_response.alpha;
296				var advanced_mode = true;
297				if(user_response.mode == 'Simple')
298					advanced_mode = false;
299				
300				TOOLS.replace_color_process(canvas_active(), WIDTH, HEIGHT, target, repalcement, power, alpha, advanced_mode);
301				GUI.zoom();
302			},
303			function (user_response, canvas_preview, w, h) {
304				var target = user_response.target;
305				var repalcement = user_response.repalcement;
306				var power = user_response.power;
307				var alpha = user_response.alpha;
308				var advanced_mode = true;
309				if(user_response.mode == 'Simple')
310					advanced_mode = false;
311				
312				TOOLS.replace_color_process(canvas_preview, w, h, target, repalcement, power, alpha, advanced_mode);
313			}
314		);
315	};
316	
317	this.replace_color_process = function(context, W, H, target, replacement, power, alpha, advanced_mode){
318		var img = context.getImageData(0, 0, W, H);
319		var imgData = img.data;
320		var target_rgb = HELPER.hex2rgb(target);
321		var target_hsl = HELPER.rgbToHsl(target_rgb.r, target_rgb.g, target_rgb.b);
322		var target_normalized = HELPER.hslToRgb(target_hsl[0], target_hsl[1], 0.5);
323		
324		var replacement_rgb = HELPER.hex2rgb(replacement);
325		var replacement_hsl = HELPER.rgbToHsl(replacement_rgb.r, replacement_rgb.g, replacement_rgb.b);
326		
327		for (var i = 0; i < imgData.length; i += 4) {
328			if (imgData[i + 3] == 0)
329				continue;	//transparent
330
331			if(advanced_mode == false){
332				//simple replace
333				
334				//calculate difference from requested color, and change alpha
335				var diff = (Math.abs(imgData[i] - target_rgb.r) + Math.abs(imgData[i + 1] - target_rgb.g) + Math.abs(imgData[i + 2] - target_rgb.b) ) / 3;
336				if(diff > power)
337					continue;
338				
339				imgData[i] = replacement_rgb.r;
340				imgData[i + 1] = replacement_rgb.g;
341				imgData[i + 2] = replacement_rgb.b;
342				if(alpha < 255)
343					imgData[i + 3] = alpha;
344			}
345			else{
346				//advanced replace using HSL
347				
348				var hsl = HELPER.rgbToHsl(imgData[i], imgData[i+1], imgData[i+2]);
349				var normalized = HELPER.hslToRgb(hsl[0], hsl[1], 0.5);
350				var diff = (Math.abs(normalized[0] - target_normalized[0]) + Math.abs(normalized[1] - target_normalized[1]) + Math.abs(normalized[2] - target_normalized[2]) ) / 3;
351				if(diff > power)
352					continue;
353				
354				//change to new color with exiting luminance
355				var replacement_normalized = HELPER.hslToRgb(replacement_hsl[0], replacement_hsl[1], hsl[2] * (replacement_hsl[2]*255) / 120);
356				
357				imgData[i] = replacement_normalized[0];
358				imgData[i + 1] = replacement_normalized[1];
359				imgData[i + 2] = replacement_normalized[2];
360				if(alpha < 255)
361					imgData[i + 3] = alpha;
362			}
363		}
364		context.putImageData(img, 0, 0);
365	};
366}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.