code refactor

This commit is contained in:
ViliusL 2016-02-25 23:57:22 +02:00
parent 0172a98394
commit 76b728a0d5
27 changed files with 7877 additions and 7264 deletions

41
config.js Normal file
View File

@ -0,0 +1,41 @@
/**
* main config file
*
* @author ViliusL
*/
//canvas layers
var canvas_back = document.getElementById("canvas_back").getContext("2d"); //layer for grid/transparency
var canvas_main = document.getElementById("Background").getContext("2d"); //background
var canvas_front = document.getElementById("canvas_front").getContext("2d"); //tmp layer
var canvas_grid = document.getElementById("canvas_grid").getContext("2d"); //grid layer
var canvas_preview = document.getElementById("canvas_preview").getContext("2d"); //mini preview
//global settings
var VERSION = '2.4';
var WIDTH = 800; //default canvas midth
var HEIGHT = 600; //default canvas height
var COLOR = '#0000ff'; //active color
var ALPHA = 255; //active color alpha
var DRAW_TOOLS_CONFIG = [
{name: 'select_tool', title: 'Select object tool', icon: ['all.png', 0+7, 2], attributes: {} },
{name: 'select_square', title: 'Select area tool', icon: ['all.png', -50+4, 5], attributes: {} },
{name: 'magic_wand', title: 'Magic Wand Tool', icon: ['all.png', -150+1, -50+2], attributes: {sensitivity: 40, anti_aliasing: true} },
{name: 'erase', title: 'Erase', icon: ['all.png', -100+3, 4], attributes: {size: 20, circle: true, strict: true} },
{name: 'fill', title: 'Fill', icon: ['all.png', -150+3, 3], attributes: {sensitivity: 0, anti_aliasing: false} },
{name: 'pick_color', title: 'Pick Color', icon: ['all.png', -200+3, 3], attributes: {} },
{name: 'pencil', title: 'Pencil', icon: ['all.png', -250+3, 3], attributes: {} },
{name: 'line', title: 'Draw line', icon: ['all.png', -300+3, 3], attributes: {size: 1, type_values: ['Simple', 'Multi-line', 'Arrow', 'Curve'] } },
{name: 'letters', title: 'Draw letters', icon: ['all.png', -350+3, 4], attributes: {} },
{name: 'draw_square', title: 'Draw rectangle', icon: ['all.png', -400+3, 5], attributes: {fill: false, square: false} },
{name: 'draw_circle', title: 'Draw circle', icon: ['all.png', -450+3, 5], attributes: {fill: false, circle: false} },
{name: 'brush', title: 'Brush', icon: ['all.png', -500+6, 3], attributes: {type: 'Brush', type_values: ['Brush', 'BezierCurve', 'Chrome', 'Fur', 'Grouped', 'Shaded', 'Sketchy'], size: 5, anti_alias: false }, on_update: 'update_brush', },
{name: 'blur_tool', title: 'Blur tool', icon: ['all.png', -250+5, -50+2], attributes: {size: 30, strength: 1} },
{name: 'sharpen_tool', title: 'Sharpen tool', icon: ['all.png', -300+5, -50+2], attributes: {size: 30, strength: 0.5} },
{name: 'burn_dodge_tool', title: 'Burn/Dodge tool', icon: ['all.png', -500+3, -50+4], attributes: {burn: true, size: 30, power: 50} },
{name: 'desaturate_tool', title: 'Desaturate', icon: ['all.png', -550+3, -00+4], attributes: {size: 50, anti_alias: true} },
{name: 'clone_tool', title: 'Clone tool', icon: ['all.png', -350+4, -50+3], attributes: {size: 30, anti_alias: true} },
{name: 'gradient_tool', title: 'Gradient', icon: ['all.png', -400+3, -50+4], attributes: {radial: false, power: 50} },
{name: 'crop_tool', title: 'Crop', icon: ['all.png', -450+2, -50+2], attributes: { } },
];

View File

@ -1,10 +1,11 @@
<!DOCTYPE html>
<html dir="ltr" lang="en-US">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>miniPaint - online image editor</title>
<meta name="description" content="miniPaint is free online image editor using HTML5. Edit, adjust your images, add effects online in your browser, without installing anything..." />
<meta name="keywords" content="photo, image, picture, transparent, layers, free, edit, html5, canvas, javascript, online, photoshop, gimp, effects, sharpen, blur, magic wand tool, clone tool, rotate, resize, photoshop online, online tools, tilt shift, sprites, keypoints" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" type="text/css" href="styles/styles.css" />
<link rel="shortcut icon" href="img/favicon.png" />
</head>
@ -22,17 +23,17 @@
</div>
<div style="clear:both;"></div>
<div id="main_colour_container">
<input type="color" id="main_colour" value="" onchange="TOOLS.set_color(this);" />
<div style="display:none;" id="main_colour_alt" onclick="TOOLS.toggle_color_select();"></div>
<input type="color" id="main_colour" value="" onchange="GUI.set_color(this);" />
<div style="display:none;" id="main_colour_alt" onclick="GUI.toggle_color_select();"></div>
</div>
<div class="block" id="all_colors"></div>
<div class="block">
<input type="text" id="color_hex" value="#000000" /><br />
<div id="main_colour_rgb">
Red: <input id="rgb_r" onKeyUp="TOOLS.set_color_rgb(this, 'r')" type="text" value="255" /><br />
Green: <input id="rgb_g" onKeyUp="TOOLS.set_color_rgb(this, 'g')" type="text" value="255" /><br />
Blue: <input id="rgb_b" onKeyUp="TOOLS.set_color_rgb(this, 'b')" type="text" value="255" /><br />
Alpha: <input id="rgb_a" onKeyUp="TOOLS.set_color_rgb(this, 'a')" type="text" value="255" />
Red: <input id="rgb_r" onKeyUp="GUI.set_color_rgb(this, 'r')" type="text" value="255" /><br />
Green: <input id="rgb_g" onKeyUp="GUI.set_color_rgb(this, 'g')" type="text" value="255" /><br />
Blue: <input id="rgb_b" onKeyUp="GUI.set_color_rgb(this, 'b')" type="text" value="255" /><br />
Alpha: <input id="rgb_a" onKeyUp="GUI.set_color_rgb(this, 'a')" type="text" value="255" />
</div>
</div>
<div class="block" id="info"></div>
@ -53,11 +54,11 @@
<div id="preview">
<canvas id="canvas_preview"></canvas>
<div style="margin-top:105px;padding-left:5px;">
<input onclick="DRAW.zoom(-1);" style="width:30px;" class="layer_add" type="button" value="-" />
<input onclick="DRAW.zoom(+1);" style="width:30px;" class="layer_add" type="button" value="+" />
<input onclick="GUI.zoom(-1);EVENTS.scroll_window();" style="width:30px;" class="layer_add" type="button" value="-" />
<input onclick="GUI.zoom(+1);EVENTS.scroll_window();" style="width:30px;" class="layer_add" type="button" value="+" />
<b>Zoom: </b><span id="zoom_nr">100</span>%
<br />
<input style="width:95%;" id="zoom_range" type="range" value="100" min="50" max="1000" step="50" oninput="DRAW.zoom(this.value);" />
<input style="width:95%;" id="zoom_range" type="range" value="100" min="50" max="1000" step="50" oninput="GUI.zoom(this.value);EVENTS.scroll_window();" />
</div>
</div>
<div id="layers_base">
@ -74,145 +75,145 @@
<li>
<a href="#">File</a>
<ul>
<li><a onclick="MENU.do_menu(['file_new']);" href="#">New</a></li>
<li><a onclick="MENU.do_menu(['file_open']);" href="#">Open...</a></li>
<li><a onclick="MENU.do_menu(['file_save']);" href="#">Save as...</a></li>
<li><a onclick="MENU.do_menu(['file_print']);" href="#">Print...</a></li>
<li><a onclick="call_menu(FILE, 'file_new');" href="#">New</a></li>
<li><a onclick="call_menu(FILE, 'file_open');" href="#">Open...</a></li>
<li><a onclick="call_menu(FILE, 'file_save');" href="#">Save as...</a></li>
<li><a onclick="call_menu(FILE, 'file_print');" href="#">Print...</a></li>
</ul>
</li>
<li>
<a href="#">Edit</a>
<ul>
<li><a onclick="MENU.do_menu(['edit_undo']);" href="#">Undo</a></li>
<li><a onclick="call_menu(EDIT, 'edit_undo');" href="#">Undo</a></li>
<li><div class="mid-line"></div></li>
<li><a onclick="MENU.do_menu(['edit_cut']);" href="#">Cut selection</a></li>
<li><a onclick="MENU.do_menu(['edit_copy']);" href="#">Copy selection</a></li>
<li><a onclick="MENU.do_menu(['edit_paste']);" href="#">Paste selection</a></li>
<li><a onclick="call_menu(EDIT, 'edit_cut');" href="#">Cut selection</a></li>
<li><a onclick="call_menu(EDIT, 'edit_copy');" href="#">Copy selection</a></li>
<li><a onclick="call_menu(EDIT, 'edit_paste');" href="#">Paste selection</a></li>
<li><div class="mid-line"></div></li>
<li><a onclick="MENU.do_menu(['edit_select']);" href="#">Select All</a></li>
<li><a onclick="MENU.do_menu(['edit_clear']);" href="#">Clear selection</a></li>
<li><a onclick="call_menu(EDIT, 'edit_select');" href="#">Select All</a></li>
<li><a onclick="call_menu(EDIT, 'edit_clear');" href="#">Clear selection</a></li>
</ul>
</li>
<li>
<a href="#">Image</a>
<ul>
<li><a onclick="MENU.do_menu(['image_information']);" href="#">Information...</a></li>
<li><a onclick="MENU.do_menu(['image_size']);" href="#">Size...</a></li>
<li><a onclick="MENU.do_menu(['image_trim']);" href="#">Trim</a>
<li><a onclick="MENU.do_menu(['image_crop']);" href="#">Crop Selection</a>
<li><a onclick="call_menu(IMAGE, 'image_information');" href="#">Information...</a></li>
<li><a onclick="call_menu(IMAGE, 'image_size');" href="#">Size...</a></li>
<li><a onclick="call_menu(IMAGE, 'image_trim');" href="#">Trim</a>
<li><a onclick="call_menu(IMAGE, 'image_crop');" href="#">Crop Selection</a>
<li><div class="mid-line"></div></li>
<li><a onclick="MENU.do_menu(['image_resize']);" href="#">Resize...</a></li>
<li><a onclick="call_menu(IMAGE, 'image_resize');" href="#">Resize...</a></li>
<li>
<a href="#">Rotate</a>
<ul>
<li><a onclick="MENU.do_menu(['image_rotate_left']);" href="#">Left</a></li>
<li><a onclick="MENU.do_menu(['image_rotate_right']);" href="#">Right</a></li>
<li><a onclick="MENU.do_menu(['image_rotate']);" href="#">Rotation...</a></li>
<li><a onclick="call_menu(IMAGE, 'image_rotate_left');" href="#">Left</a></li>
<li><a onclick="call_menu(IMAGE, 'image_rotate_right');" href="#">Right</a></li>
<li><a onclick="call_menu(IMAGE, 'image_rotate');" href="#">Rotation...</a></li>
</ul>
</li>
<li>
<a href="#">Flip</a>
<ul>
<li><a onclick="MENU.do_menu(['image_vflip']);" href="#">Vertical</a></li>
<li><a onclick="MENU.do_menu(['image_hflip']);" href="#">Horizontal</a></li>
<li><a onclick="call_menu(IMAGE, 'image_vflip');" href="#">Vertical</a></li>
<li><a onclick="call_menu(IMAGE, 'image_hflip');" href="#">Horizontal</a></li>
</ul>
</li>
<li><div class="mid-line"></div></li>
<li><a onclick="MENU.do_menu(['image_colors']);" href="#">Color corrections...</a></li>
<li><a onclick="MENU.do_menu(['image_auto_adjust']);" href="#">Auto adjust colors</a></li>
<li><a onclick="MENU.do_menu(['image_GrayScale']);" href="#">GrayScale</a>
<li><a onclick="MENU.do_menu(['image_decrease_colors']);" href="#">Decrease color depth...</a></li>
<li><a onclick="MENU.do_menu(['image_negative']);" href="#">Negative</a></li>
<li><a onclick="MENU.do_menu(['image_grid']);" href="#">Grid...</a></li>
<li><a onclick="call_menu(IMAGE, 'image_colors');" href="#">Color corrections...</a></li>
<li><a onclick="call_menu(IMAGE, 'image_auto_adjust');" href="#">Auto adjust colors</a></li>
<li><a onclick="call_menu(IMAGE, 'image_GrayScale');" href="#">GrayScale</a>
<li><a onclick="call_menu(IMAGE, 'image_decrease_colors');" href="#">Decrease color depth...</a></li>
<li><a onclick="call_menu(IMAGE, 'image_negative');" href="#">Negative</a></li>
<li><a onclick="call_menu(IMAGE, 'image_grid');" href="#">Grid...</a></li>
<li><div class="mid-line"></div></li>
<li><a onclick="MENU.do_menu(['image_histogram']);" href="#">Histogram...</a></li>
<li><a onclick="call_menu(IMAGE, 'image_histogram');" href="#">Histogram...</a></li>
</ul>
</li>
<li>
<a href="#">Layer</a>
<ul>
<li><a onclick="MENU.do_menu(['layer_new']);" href="#">New</a></li>
<li><a onclick="MENU.do_menu(['layer_dublicate']);" href="#">Dublicate</a></li>
<li><a onclick="MENU.do_menu(['layer_show_hide']);" href="#">Show / Hide</a></li>
<li><a onclick="MENU.do_menu(['layer_crop']);" href="#">Crop Selection</a>
<li><a onclick="MENU.do_menu(['layer_delete']);" href="#">Delete</a></li>
<li><a onclick="call_menu(LAYER, 'layer_new');" href="#">New</a></li>
<li><a onclick="call_menu(LAYER, 'layer_dublicate');" href="#">Dublicate</a></li>
<li><a onclick="call_menu(LAYER, 'layer_show_hide');" href="#">Show / Hide</a></li>
<li><a onclick="call_menu(LAYER, 'layer_crop');" href="#">Crop Selection</a>
<li><a onclick="call_menu(LAYER, 'layer_delete');" href="#">Delete</a></li>
<li><div class="mid-line"></div></li>
<li>
<a href="#">Move</a>
<ul>
<li><a onclick="MENU.do_menu(['layer_move_up']);" href="#">Up</a></li>
<li><a onclick="MENU.do_menu(['layer_move_down']);" href="#">Down</a></li>
<li><a onclick="call_menu(LAYER, 'layer_move_up');" href="#">Up</a></li>
<li><a onclick="call_menu(LAYER, 'layer_move_down');" href="#">Down</a></li>
</ul>
</li>
<li><a onclick="MENU.do_menu(['layer_opacity']);" href="#">Opacity...</a></li>
<li><a onclick="call_menu(LAYER, 'layer_opacity');" href="#">Opacity...</a></li>
<li><div class="mid-line"></div></li>
<li><a onclick="MENU.do_menu(['layer_trim']);" href="#">Trim</a></li>
<li><a onclick="MENU.do_menu(['layer_resize']);" href="#">Resize...</a></li>
<li><a onclick="MENU.do_menu(['layer_clear']);" href="#">Clear</a></li>
<li><a onclick="call_menu(LAYER, 'layer_trim');" href="#">Trim</a></li>
<li><a onclick="call_menu(LAYER, 'layer_resize');" href="#">Resize...</a></li>
<li><a onclick="call_menu(LAYER, 'layer_clear');" href="#">Clear</a></li>
<li><div class="mid-line"></div></li>
<li><a onclick="MENU.do_menu(['layer_differences']);" href="#">Differences Down</a></li>
<li><a onclick="MENU.do_menu(['layer_merge_down']);" href="#">Merge Down...</a></li>
<li><a onclick="MENU.do_menu(['layer_flatten']);" href="#">Flatten Image</a></li>
<li><a onclick="call_menu(LAYER, 'layer_differences');" href="#">Differences Down</a></li>
<li><a onclick="call_menu(LAYER, 'layer_merge_down');" href="#">Merge Down...</a></li>
<li><a onclick="call_menu(LAYER, 'layer_flatten');" href="#">Flatten Image</a></li>
</ul>
</li>
<li>
<a href="#">Effects</a>
<ul id="effects_list">
<li><a onclick="MENU.do_menu(['effects_bw']);" href="#">Black and White...</a>
<li><a onclick="call_menu(EFFECTS, 'effects_bw');" href="#">Black and White...</a>
<li>
<a href="#">Blur</a>
<ul>
<li><a onclick="MENU.do_menu(['effects_BoxBlur']);" href="#">Blur-Box...</a>
<li><a onclick="MENU.do_menu(['effects_GaussianBlur']);" href="#">Blur-Gaussian...</a>
<li><a onclick="MENU.do_menu(['effects_StackBlur']);" href="#">Blur-Stack...</a>
<li><a onclick="MENU.do_menu(['effects_zoomblur']);" href="#">Blur-Zoom...</a>
<li><a onclick="call_menu(EFFECTS, 'effects_BoxBlur');" href="#">Blur-Box...</a>
<li><a onclick="call_menu(EFFECTS, 'effects_GaussianBlur');" href="#">Blur-Gaussian...</a>
<li><a onclick="call_menu(EFFECTS, 'effects_StackBlur');" href="#">Blur-Stack...</a>
<li><a onclick="call_menu(EFFECTS, 'effects_zoomblur');" href="#">Blur-Zoom...</a>
</ul>
</li>
<li><a onclick="MENU.do_menu(['effects_bulge_pinch']);" href="#">Bulge/Pinch...</a>
<li><a onclick="MENU.do_menu(['effects_colorize']);" href="#">Colorize...</a></li>
<li><a onclick="MENU.do_menu(['effects_denoise']);" href="#">Denoise...</a>
<li><a onclick="MENU.do_menu(['effects_Desaturate']);" href="#">Desaturate...</a>
<li><a onclick="MENU.do_menu(['effects_Dither']);" href="#">Dither...</a>
<li><a onclick="MENU.do_menu(['effects_dot_screen']);" href="#">Dot Screen...</a>
<li><a onclick="MENU.do_menu(['effects_Edge']);" href="#">Edge...</a>
<li><a onclick="MENU.do_menu(['effects_Emboss']);" href="#">Emboss...</a>
<li><a onclick="MENU.do_menu(['effects_Enrich']);" href="#">Enrich...</a>
<li><a onclick="MENU.do_menu(['effects_Gamma']);" href="#">Gamma...</a>
<li><a onclick="MENU.do_menu(['effects_Grains']);" href="#">Grains...</a>
<li><a onclick="MENU.do_menu(['effects_heatmap']);" href="#">Heatmap...</a>
<li><a onclick="MENU.do_menu(['effects_HSLAdjustment']);" href="#">HSL Adjustment...</a>
<li><a onclick="MENU.do_menu(['effects_jpg_vintage']);" href="#">JPG Compression...</a></li>
<li><a onclick="MENU.do_menu(['effects_Mosaic']);" href="#">Mosaic...</a>
<li><a onclick="MENU.do_menu(['effects_Oil']);" href="#">Oil...</a>
<li><a onclick="MENU.do_menu(['effects_perspective']);" href="#">Perspective...</a>
<li><a onclick="MENU.do_menu(['effects_Posterize']);" href="#">Posterize...</a>
<li><a onclick="MENU.do_menu(['effects_Sepia']);" href="#">Sepia...</a>
<li><a onclick="MENU.do_menu(['effects_Sharpen']);" href="#">Sharpen...</a>
<li><a onclick="MENU.do_menu(['effects_Solarize']);" href="#">Solarize...</a>
<li><a onclick="MENU.do_menu(['effects_tilt_shift']);" href="#">Tilt Shift...</a>
<li><a onclick="MENU.do_menu(['effects_vignette']);" href="#">Vignette...</a>
<li><a onclick="MENU.do_menu(['effects_vintage']);" href="#">Vintage...</a>
<li><a onclick="call_menu(EFFECTS, 'effects_bulge_pinch');" href="#">Bulge/Pinch...</a>
<li><a onclick="call_menu(EFFECTS, 'effects_colorize');" href="#">Colorize...</a></li>
<li><a onclick="call_menu(EFFECTS, 'effects_denoise');" href="#">Denoise...</a>
<li><a onclick="call_menu(EFFECTS, 'effects_Desaturate');" href="#">Desaturate...</a>
<li><a onclick="call_menu(EFFECTS, 'effects_Dither');" href="#">Dither...</a>
<li><a onclick="call_menu(EFFECTS, 'effects_dot_screen');" href="#">Dot Screen...</a>
<li><a onclick="call_menu(EFFECTS, 'effects_Edge');" href="#">Edge...</a>
<li><a onclick="call_menu(EFFECTS, 'effects_Emboss');" href="#">Emboss...</a>
<li><a onclick="call_menu(EFFECTS, 'effects_Enrich');" href="#">Enrich...</a>
<li><a onclick="call_menu(EFFECTS, 'effects_Gamma');" href="#">Gamma...</a>
<li><a onclick="call_menu(EFFECTS, 'effects_Grains');" href="#">Grains...</a>
<li><a onclick="call_menu(EFFECTS, 'effects_heatmap');" href="#">Heatmap...</a>
<li><a onclick="call_menu(EFFECTS, 'effects_HSLAdjustment');" href="#">HSL Adjustment...</a>
<li><a onclick="call_menu(EFFECTS, 'effects_jpg_vintage');" href="#">JPG Compression...</a></li>
<li><a onclick="call_menu(EFFECTS, 'effects_Mosaic');" href="#">Mosaic...</a>
<li><a onclick="call_menu(EFFECTS, 'effects_Oil');" href="#">Oil...</a>
<li><a onclick="call_menu(EFFECTS, 'effects_perspective');" href="#">Perspective...</a>
<li><a onclick="call_menu(EFFECTS, 'effects_Posterize');" href="#">Posterize...</a>
<li><a onclick="call_menu(EFFECTS, 'effects_Sepia');" href="#">Sepia...</a>
<li><a onclick="call_menu(EFFECTS, 'effects_Sharpen');" href="#">Sharpen...</a>
<li><a onclick="call_menu(EFFECTS, 'effects_Solarize');" href="#">Solarize...</a>
<li><a onclick="call_menu(EFFECTS, 'effects_tilt_shift');" href="#">Tilt Shift...</a>
<li><a onclick="call_menu(EFFECTS, 'effects_vignette');" href="#">Vignette...</a>
<li><a onclick="call_menu(EFFECTS, 'effects_vintage');" href="#">Vintage...</a>
</ul>
</li>
<li>
<a href="#">Tools</a>
<ul>
<li><a onclick="MENU.do_menu(['tools_borders']);" href="#">Borders...</a></li>
<li><a onclick="MENU.do_menu(['tools_sprites']);" href="#">Sprites...</a></li>
<li><a onclick="MENU.do_menu(['tools_keypoints']);" href="#">Key-points</a></li>
<li><a onclick="MENU.do_menu(['tools_color2alpha']);" href="#">Color to Alpha...</a></li>
<li><a onclick="MENU.do_menu(['tools_color_zoom']);" href="#">Color Zoom...</a></li>
<li><a onclick="MENU.do_menu(['tools_restore_alpha']);" href="#">Restore alpha...</a></li>
<li><a onclick="call_menu(TOOLS, 'tools_borders');" href="#">Borders...</a></li>
<li><a onclick="call_menu(TOOLS, 'tools_sprites');" href="#">Sprites...</a></li>
<li><a onclick="call_menu(TOOLS, 'tools_keypoints');" href="#">Key-points</a></li>
<li><a onclick="call_menu(TOOLS, 'tools_color2alpha');" href="#">Color to Alpha...</a></li>
<li><a onclick="call_menu(TOOLS, 'tools_color_zoom');" href="#">Color Zoom...</a></li>
<li><a onclick="call_menu(TOOLS, 'tools_restore_alpha');" href="#">Restore alpha...</a></li>
</ul>
</li>
<li>
<a href="#">Help</a>
<ul>
<li><a onclick="MENU.do_menu(['help_shortcuts']);" href="#">Keyboard Shortcuts...</a></li>
<li><a onclick="call_menu(HELP, 'help_shortcuts');" href="#">Keyboard Shortcuts...</a></li>
<li><a onclick="window.location='http://viliusle.github.io/miniPaint/';" href="http://viliusle.github.io/miniPaint/">Website</a></li>
<li><a onclick="MENU.do_menu(['help_credits']);" href="#">Credits...</a></li>
<li><a onclick="MENU.do_menu(['help_about']);" href="#">About...</a></li>
<li><a onclick="call_menu(HELP, 'help_credits');" href="#">Credits...</a></li>
<li><a onclick="call_menu(HELP, 'help_about');" href="#">About...</a></li>
</ul>
</li>
</ul>
@ -229,15 +230,22 @@
<script src="libs/vintage.js"></script>
<script src="libs/kdtree.js"></script>
<script src="libs/sift.js"></script>
<script src="js/elements.js"></script>
<script src="js/helpers.js"></script>
<script src="js/popup.js"></script>
<script src="js/controlls.js"></script>
<script src="js/tools.js"></script>
<script src="js/draw.js"></script>
<script src="libs/popup.js"></script>
<script src="js/events.js"></script>
<script src="js/file.js"></script>
<script src="js/edit.js"></script>
<script src="js/image.js"></script>
<script src="js/layers.js"></script>
<script src="js/menu_actions.js"></script>
<script src="js/settings.js"></script>
<script src="js/effects.js"></script>
<script src="js/tools.js"></script>
<script src="js/draw_tools.js"></script>
<script src="js/gui.js"></script>
<script src="js/help.js"></script>
<script src="config.js"></script>
<script src="js/main.js"></script>
</body>
</html>

View File

@ -1,707 +0,0 @@
/* global HELPER, POP, MAIN, LAYERS, CON, TOOLS, LAYER, DRAW, MENU */
/* global ACTION, canvas_active, canvas_front, WIDTH, HEIGHT, ZOOM, EXIF */
var CON = new CONTROLLS_CLASS();
//keyboard handlers
document.onkeydown = function(e) {return CON.on_keyboard_action(e); };
document.onkeyup = function(e) {return CON.on_keyboardup_action(e); };
//mouse
window.ondrop = function(e){ CON.upload_drop(e); }; //drop
window.ondragover = function(e){e.preventDefault(); };
document.onmousedown = CON.mouse_click; //mouse click
document.onmousemove = CON.mouse_move; //mouse move
document.onmouseup = CON.mouse_release; //mouse resease
document.addEventListener("mousewheel", CON.mouse_wheel_handler, false); //mouse scroll
document.addEventListener("DOMMouseScroll", CON.mouse_wheel_handler, false); //mouse scroll
window.onresize = CON.calc_preview_auto; //window resize
document.oncontextmenu = function(e) {return CON.mouse_right_click(e); }; //mouse right click
document.getElementById('color_hex').onkeyup = function(e){ TOOLS.set_color_manual(e); }; //on main color type
document.getElementById('color_hex').onpaste = function(e){ TOOLS.set_color_manual(e); }; // on paste in main color input
function CONTROLLS_CLASS(){
this.mouse;
this.ctrl_pressed = false; //17
this.shift_pressed = false; //16
this.ZOOM_X = 0;
this.ZOOM_Y = 0;
this.mini_rect_data = { w: 0, h:0 };
this.isDrag = false;
this.sr_size = 8; //selected area resize rects size
this.clear_front_on_release = true;
var autosize = true;
var mouse_click_x = false;
var mouse_click_y = false;
var mouse_x_move_last = false;
var mouse_y_move_last = false;
var resize_all = false;
var mouse_click_valid = false;
var last_pop_click = [0, 0];
var popup_pos_top = 0;
var popup_pos_left = 0;
var popup_dragable = false;
//keyboard actions
this.on_keyboard_action = function(event){
k = event.keyCode; //console.log(k);
if(POP != undefined && POP.active==true && k != 27) return true;
if(document.activeElement.type == 'text') return true;
//up
if(k == 38){
if(ACTION=='select_tool'){
MAIN.save_state();
LAYER.layer_move_active(0, -1);
return false;
}
}
//down
else if(k == 40){
if(ACTION=='select_tool'){
MAIN.save_state();
LAYER.layer_move_active(0, 1);
return false;
}
}
//left
else if(k == 39){
if(ACTION=='select_tool'){
MAIN.save_state();
LAYER.layer_move_active(1, 0);
return false;
}
}
//right
else if(k == 37){
if(ACTION=='select_tool'){
MAIN.save_state();
LAYER.layer_move_active(-1, 0);
return false;
}
}
//esc
else if(k == 27){
if(POP != undefined && POP.active == true)
POP.hide();
delete TOOLS.last_line_x;
delete TOOLS.last_line_y;
TOOLS.curve_points = [];
if(TOOLS.select_data != false){
TOOLS.select_data = false;
canvas_front.clearRect(0, 0, WIDTH, HEIGHT);
TOOLS.select_square_action = '';
}
}
//z - undo
else if(k == 90){
//undo
if(CON.ctrl_pressed==true)
MAIN.undo();
}
//t - trim
else if(k == 84){
MAIN.save_state();
DRAW.trim();
}
//o - open
else if(k == 79)
MENU.open();
//s - save
else if(k == 83){
if(POP != undefined)
MENU.save_dialog(event);
}
//l - rotate left
else if(k == 76){
MAIN.save_state();
MENU.rotate_resize_doc(270, WIDTH, HEIGHT);
MENU.rotate_layer({angle: 270}, canvas_active(), WIDTH, HEIGHT);
}
//r - resize
else if(k == 82)
MENU.resize_box();
//grid
else if(k==71){
if(MAIN.grid == false)
MAIN.grid = true;
else
MAIN.grid = false;
DRAW.draw_grid();
}
//del
else if(k==46){
if(TOOLS.select_data != false){
MAIN.save_state();
canvas_active().clearRect(TOOLS.select_data.x, TOOLS.select_data.y, TOOLS.select_data.w, TOOLS.select_data.h);
TOOLS.select_data = false;
TOOLS.select_square_action = '';
canvas_front.clearRect(0, 0, WIDTH, HEIGHT);
}
}
//shift
else if(k==16)
CON.shift_pressed = true;
//ctrl
else if(k==17){
if(CON.ctrl_pressed == false)
CON.ctrl_pressed = true;
}
//d
else if(k==68){
MENU.do_menu(['layer_dublicate']);
}
//a
else if(k==65){
if(CON.ctrl_pressed == true){
TOOLS.select_data = {
x: 0,
y: 0,
w: WIDTH,
h: HEIGHT
};
TOOLS.draw_selected_area();
return false;
}
}
//v
else if(k==86){
MAIN.save_state();
if(CON.ctrl_pressed == true)
MENU.paste();
}
//f - fix images
else if(k==70){
MAIN.save_state();
DRAW.auto_adjust(canvas_active(), WIDTH, HEIGHT);
}
//h - histogram
else if(k==72){
TOOLS.histogram();
}
//-
else if(k==109)
DRAW.zoom(-1);
//+
else if(k==107)
DRAW.zoom(+1);
//n - new layer
else if(k==78)
MENU.add_layer();
//mac support - ctrl
if(k==17 || event.metaKey || event.ctrlKey){
if(CON.ctrl_pressed == false)
CON.ctrl_pressed = true;
}
DRAW.zoom();
return true;
};
//keyboard release
this.on_keyboardup_action = function(event){
k = event.keyCode;
//shift
if(k==16)
CON.shift_pressed = false;
//ctrl
else if(k==17)
CON.ctrl_pressed = false;
//mac support - ctrl
if(event.metaKey || event.ctrlKey || event.key == 'Meta')
CON.ctrl_pressed = false;
};
// mouse_x, mouse_y, event.pageX, event.pageY
this.get_mouse_position = function(event){
var valid = true;
if(event.offsetX) {
mouse_rel_x = event.offsetX;
mouse_rel_y = event.offsetY;
}
else if(event.layerX) {
mouse_rel_x = event.layerX;
mouse_rel_y = event.layerY;
}
else
return false;
mouse_x = event.pageX;
mouse_y = event.pageY;
var abs_x = event.pageX;
var abs_y = event.pageY;
if(event.target.id == "canvas_front"){
//in canvas area - relative pos
mouse_x = mouse_rel_x;
mouse_y = mouse_rel_y;
if(ZOOM != 100 ){
mouse_x = Math.floor(mouse_x / ZOOM * 100);
mouse_y = Math.floor(mouse_y / ZOOM * 100);
}
}
else{
//outside canvas - absolute pos - canvas offset
mouse_x = mouse_x - 109;
mouse_y = mouse_y - 34;
valid = false;
}
if(event.target.id == "canvas_preview"){
//in preview area - relative pos
mouse_x = mouse_rel_x;
mouse_y = mouse_rel_y;
}
//save - other place will use it too
CON.mouse = {
x: mouse_x,
y: mouse_y,
click_x: mouse_click_x,
click_y: mouse_click_y,
last_x: mouse_x_move_last,
last_y: mouse_y_move_last,
valid: valid,
click_valid: mouse_click_valid,
abs_x: abs_x,
abs_y: abs_y
};
};
//mouse right click
this.mouse_right_click = function(event){
if(POP != undefined && POP.active==true) return true;
CON.get_mouse_position(event);
mouse_click_x = CON.mouse.x;
mouse_click_y = CON.mouse.y;
for (var i in TOOLS){
if(i == ACTION){
return TOOLS[i]('right_click', CON.mouse, event);
break;
}
}
};
//mouse click
this.mouse_click = function(event){
CON.isDrag = true;
if(POP != undefined && POP.active==true){
CON.get_mouse_position(event);
last_pop_click[0] = CON.mouse.abs_x;
last_pop_click[1] = CON.mouse.abs_y;
popup = document.getElementById('popup');
popup_pos_top = parseInt(popup.style.top);
popup_pos_left = parseInt(popup.style.left);
if(event.target.id == "popup_drag")
popup_dragable = true;
else
popup_dragable = false;
return true;
}
if(event.which == 3) return true;
CON.get_mouse_position(event);
mouse_click_x = CON.mouse.x;
mouse_click_y = CON.mouse.y;
if(CON.mouse.valid == false)
mouse_click_valid = false;
else
mouse_click_valid = true;
//check tools functions
for (var i in TOOLS){
if(i == ACTION){
TOOLS[i]('click', CON.mouse, event);
break;
}
}
if(event.target.id == "canvas_preview")
CON.calc_preview_by_mouse(CON.mouse.x, CON.mouse.y);
//main window resize
resize_all = false;
if(ZOOM == 100){
if(event.target.id == "resize-w") resize_all = "w";
else if(event.target.id == "resize-h") resize_all = "h";
else if(event.target.id == "resize-wh") resize_all = "wh";
}
};
//mouse move
this.mouse_move = function(event){
if(POP != undefined && POP.active==true){
//drag popup
if(CON.isDrag==true && popup_dragable == true){
CON.get_mouse_position(event);
popup = document.getElementById('popup');
popup.style.top = (popup_pos_top + CON.mouse.abs_y - last_pop_click[1])+'px';
popup.style.left = (popup_pos_left + CON.mouse.abs_x - last_pop_click[0])+'px';
}
return true;
}
CON.get_mouse_position(event);
if(event.target.id == "canvas_preview" && CON.isDrag==true)
CON.calc_preview_by_mouse(CON.mouse.x, CON.mouse.y);
LAYER.update_info_block();
//main window resize
if(ZOOM == 100){
if(event.target.id == "resize-w") document.body.style.cursor = "w-resize";
else if(event.target.id == "resize-h") document.body.style.cursor = "n-resize";
else if(event.target.id == "resize-wh") document.body.style.cursor = "nw-resize";
else document.body.style.cursor = "auto";
if(resize_all != false && CON.isDrag==true){
document.body.style.cursor = "auto";
if(resize_all == "w"){
new_w = CON.mouse.x;
new_h = HEIGHT;
}
else if(resize_all == "h"){
new_w = WIDTH;
new_h = CON.mouse.y;
}
else if(resize_all == "wh"){
new_w = CON.mouse.x;
new_h = CON.mouse.y;
}
canvas_front.clearRect(0, 0, WIDTH, HEIGHT);
canvas_front.lineWidth = 1;
canvas_front.fillStyle = "#ff0000";
HELPER.dashedRect(canvas_front, 0, 0, new_w-1, new_h-1);
event.preventDefault();
HELPER.remove_selection();
return false;
}
}
//check tools functions
if(CON.isDrag === false){
for (i in TOOLS){
if(i == ACTION){
TOOLS[i]('move', CON.mouse, event);
break;
}
}
}
if(CON.isDrag === false) return false; //only drag now
//check tools functions
for (var i in TOOLS){
if(i == ACTION){
TOOLS[i]('drag', CON.mouse, event);
break;
}
}
if(ACTION != 'select_square')
TOOLS.select_square_action = '';
mouse_x_move_last = CON.mouse.x;
mouse_y_move_last = CON.mouse.y;
};
//release mouse click
this.mouse_release = function(event){
CON.isDrag = false;
if(POP != undefined && POP.active==true) return true;
var mouse = CON.get_mouse_position(event);
mouse_x_move_last = false;
mouse_y_move_last = false;
if(TOOLS.select_square_action == '' && CON.mouse.valid == true)
TOOLS.select_data = false;
//check tools functions
if(CON.clear_front_on_release == true)
canvas_front.clearRect(0, 0, WIDTH, HEIGHT);
TOOLS.draw_selected_area();
for (var i in TOOLS){
if(i == ACTION){
TOOLS[i]('release', CON.mouse, event);
break;
}
}
//main window resize
if(resize_all != false && ZOOM == 100 && CON.mouse.x > 0 && CON.mouse.y > 0){
CON.autosize = false;
document.body.style.cursor = "auto";
if(resize_all == "w")
WIDTH = CON.mouse.x;
else if(resize_all == "h")
HEIGHT = CON.mouse.y;
else if(resize_all == "wh"){
WIDTH = mouse_x;
HEIGHT = CON.mouse.y;
}
RATIO = WIDTH/HEIGHT;
LAYER.set_canvas_size();
DRAW.zoom();
}
resize_all = false;
DRAW.zoom();
};
//upload drop zone
this.upload_drop = function(e){
e.preventDefault();
MAIN.save_state();
var n_valid = 0;
for (var i = 0, f; i < e.dataTransfer.files.length ; i++){
f = e.dataTransfer.files[i];
if(!f.type.match('image.*') && f.type != 'text/xml') continue;
n_valid++;
var FR = new FileReader();
FR.file = e.dataTransfer.files[i];
if(e.dataTransfer.files.length == 1)
SAVE_NAME = f.name.split('.')[f.name.split('.').length - 2];
FR.onload = function(event){
if(this.file.type != 'text/xml'){
//image
LAYER.layer_add(this.file.name, event.target.result, this.file.type);
EXIF.getData(this.file, TOOLS.save_EXIF);
}
else{
//xml
var responce = MAIN.load_xml(event.target.result);
if(responce === true)
return false;
}
};
if(f.type == "text/plain")
FR.readAsText(f);
else if(f.type == "text/xml")
FR.readAsText(f);
else
FR.readAsDataURL(f);
}
if(n_valid == 0)
progress.style.display='none';
};
this.mouse_wheel_handler = function(e){ //return true;
var step = 100; e.preventDefault();
//zoom
if(CON.ctrl_pressed==true){
var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));
if(ZOOM <=100 && delta < 0)
step = 10;
if(ZOOM <100 && delta > 0)
step = 10;
delta = delta * step;
if(ZOOM + delta > 0){
ZOOM = ZOOM + delta;
CON.calc_preview_auto();
DRAW.zoom();
}
if(TOOLS.action_data().name == 'zoom'){
TOOLS.action_data().attributes.zoom = ZOOM;
show_action_attributes();
}
//disable page scroll if ctrl pressed
e.preventDefault();
return false;
}
};
this.scroll_window = function(){
var pad_left = 109;
var pad_top = 34;
var pad_right = 170;
var dim = HELPER.get_dimensions();
var page_w = dim[0];
var page_h = dim[1];
var total_w = (WIDTH * ZOOM/100) + pad_left + pad_right;
var total_h = (HEIGHT * ZOOM/100) + pad_top;
var visible_w = page_w - 60;
var visible_h = page_h - 60;
var scrollbar_w = page_w * visible_w / total_w;
var scrollbar_h = page_h * visible_h / total_h;
xx = total_w * CON.ZOOM_X / (DRAW.PREVIEW_SIZE.w);
yy = total_h * CON.ZOOM_Y / (DRAW.PREVIEW_SIZE.h );
//minuus scrollbar size
xx = xx - scrollbar_w/2;
yy = yy - scrollbar_h/2;
var canvas_wrapper = document.getElementById('canvas_wrapper');
canvas_wrapper.scrollTop = yy;
canvas_wrapper.scrollLeft = xx;
};
this.calc_preview_by_mouse = function(mouse_x, mouse_y){
CON.ZOOM_X = mouse_x - CON.mini_rect_data.w/2;
CON.ZOOM_Y = mouse_y - CON.mini_rect_data.h/2;
if(CON.ZOOM_X < 0) CON.ZOOM_X = 0;
if(CON.ZOOM_Y < 0) CON.ZOOM_Y = 0;
DRAW.zoom(undefined, true);
return true;
};
this.calc_preview_auto = function(){
var pad_left = 109;
var pad_top = 34;
var pad_right = 170;
var dim = HELPER.get_dimensions();
var page_w = dim[0];
var page_h = dim[1];
var total_w = (WIDTH * ZOOM/100) + pad_left + pad_right;
var total_h = (HEIGHT * ZOOM/100) + pad_top;
var visible_w = page_w - 60;
var visible_h = page_h - 60;
CON.mini_rect_data.w = round(visible_w * DRAW.PREVIEW_SIZE.w / total_w);
CON.mini_rect_data.h = round(visible_h * DRAW.PREVIEW_SIZE.h / total_h);
DRAW.redraw_preview();
};
}
//=== Clipboard ================================================================
var CLIPBOARD = new CLIPBOARD_CLASS('cc');
function CLIPBOARD_CLASS(canvas_id){
var _self = this;
var ctrl_pressed = false;
var reading_dom = false;
var text_top = 15;
var pasteCatcher;
var paste_mode;
//handlers
document.addEventListener('keydown', function(e){ _self.on_keyboard_action(e); }, false);
document.addEventListener('keyup', function(e){ _self.on_keyboardup_action(e); }, false);
document.addEventListener('paste', function(e){ _self.paste_auto(e); }, false);
//constructor - prepare
this.init = function(){
//if using auto
if(window.Clipboard) return true;
pasteCatcher = document.createElement("div");
pasteCatcher.setAttribute("id", "paste_ff");
pasteCatcher.setAttribute("contenteditable", "");
pasteCatcher.style.cssText = 'opacity:0;position:fixed;top:0px;left:0px;';
pasteCatcher.style.marginLeft = "-20px";
pasteCatcher.style.width = "10px";
document.body.appendChild(pasteCatcher);
document.getElementById('paste_ff').addEventListener('DOMSubtreeModified', function(){
reading_dom = false;
if(paste_mode == 'auto' || ctrl_pressed == false) return true;
//if paste handle failed - capture pasted object manually
if(pasteCatcher.children.length == 1){
if(pasteCatcher.firstElementChild.src != undefined){
//image
img = pasteCatcher.firstElementChild.src;
_self.paste_createImage(pasteCatcher.firstElementChild.src);
}
else{
//html
/*setTimeout(function(){
if(reading_dom == true) return false;
_self.paste_createText(pasteCatcher.innerHTML, false);
reading_dom = true;
}, 10);*/
}
}
/*else if(pasteCatcher.children.length == 0){
//text
setTimeout(function(){
if(reading_dom == true) return false;
_self.paste_createText(pasteCatcher.innerHTML, false);
reading_dom = true;
}, 10);
}*/
//register cleanup after some time.
setTimeout(function(){
pasteCatcher.innerHTML = '';
}, 20);
},false);
}();
//default paste action
this.paste_auto = function(e){
paste_mode = '';
pasteCatcher.innerHTML = '';
var plain_text_used = false;
if(e.clipboardData){
var items = e.clipboardData.items;
if (items){
paste_mode = 'auto';
//access data directly
for (var i = 0; i < items.length; i++){
if(items[i].type.indexOf("image") !== -1){
//image
var blob = items[i].getAsFile();
var URLObj = window.URL || window.webkitURL;
var source = URLObj.createObjectURL(blob);
this.paste_createImage(source);
}
else if(items[i].type.indexOf("text") !== -1){
//text or html
/*if(plain_text_used == false)
this.paste_createText(e.clipboardData.getData('text/plain'));
plain_text_used = true;*/
}
}
e.preventDefault();
}
else{
//wait for DOMSubtreeModified event
//https://bugzilla.mozilla.org/show_bug.cgi?id=891247
}
}
};
//on keyboard press
this.on_keyboard_action = function(event){
if(POP.active == true) return true;
k = event.keyCode;
//ctrl
if(k==17 || event.metaKey || event.ctrlKey){
if(ctrl_pressed == false)
ctrl_pressed = true;
}
//v
if(k==86){
if(document.activeElement != undefined && document.activeElement.type == 'text'){
//let user paste into some input
return false;
}
if(ctrl_pressed == true && !window.Clipboard)
pasteCatcher.focus();
}
};
//on kaybord release
this.on_keyboardup_action = function(event){
k = event.keyCode;
//ctrl
if(k==17 || event.metaKey || event.ctrlKey || event.key == 'Meta')
ctrl_pressed = false;
};
//draw image
this.paste_createImage = function(source){
var pastedImage = new Image();
pastedImage.onload = function(){
LAYER.layer_add('Paste', source);
};
pastedImage.src = source;
};
//draw text
this.paste_createText = function(text, parsed){
var ctx = canvas_active();
if(text == '') return false;
if(parsed == false){
text = text.replace(/<br\s*[\/]?>/gi, "\n");
text = text.replace(/(<([^>]+)>)/g, "");
text = text.replace(/&nbsp;/gi, " ");
}
ctx.font = '13px Tahoma';
var lines = text.split("\n");
for(var i in lines){
ctx.fillText(lines[i], 10, text_top);
text_top += 15;
}
text_top += 15;
};
};

View File

@ -1,914 +0,0 @@
/* global HELPER, POP, MAIN, LAYERS, CON, LAYER, DRAW, MENU */
/* global ACTION, canvas_active, canvas_front, canvas_preview, canvas_grid, WIDTH, HEIGHT, ZOOM, ImageFilters */
var DRAW = new DRAW_CLASS();
function DRAW_CLASS(){
this.PREVIEW_SIZE = {w: 148, h: 100 };
this.grid_size = [50, 50];
this.draw_grid = function(gap_x, gap_y){
if(MAIN.grid == false){
document.getElementById("canvas_grid").style.display = 'none';
return false;
}
else{
document.getElementById("canvas_grid").style.display = '';
canvas_grid.clearRect(0, 0, WIDTH, HEIGHT);
}
//size
if(gap_x != undefined && gap_y != undefined)
this.grid_size = [gap_x, gap_y];
else{
gap_x = this.grid_size[0];
gap_y = this.grid_size[1];
}
gap_x = parseInt(gap_x);
gap_y = parseInt(gap_y);
if(gap_x<2) gap_x=2;
if(gap_y<2) gap_y=2;
for(var i=gap_x; i<WIDTH; i=i+gap_x){
if(gap_x==0) break;
if(i%(gap_x*5) == 0) //main lines
canvas_grid.strokeStyle = '#222222';
else{
HELPER.dashedLine(canvas_grid, i, 0, i, HEIGHT, 3, '#888888');
continue;
}
canvas_grid.beginPath();
canvas_grid.moveTo(0.5 + i, 0);
canvas_grid.lineTo(0.5 + i, HEIGHT);
canvas_grid.stroke();
}
for(var i=gap_y; i<HEIGHT; i=i+gap_y){
if(gap_y==0) break;
if(i%(gap_y*5) == 0) //main lines
canvas_grid.strokeStyle = '#222222';
else{
HELPER.dashedLine(canvas_grid, 0, i, WIDTH, i, 3, '#888888');
continue;
}
canvas_grid.beginPath();
canvas_grid.moveTo(0, 0.5 + i);
canvas_grid.lineTo(WIDTH, 0.5 + i);
canvas_grid.stroke();
}
};
this.draw_background = function(canvas, W, H, gap, force){
if(MAIN.TRANSPARENCY == false && force == undefined){
canvas.beginPath();
canvas.rect(0, 0, W, H);
canvas.fillStyle = "#ffffff";
canvas.fill();
return false;
}
if(gap == undefined)
gap = 10;
var fill = true;
for(var i=0; i<W; i=i+gap){
if(i%(gap*2) == 0)
fill=true;
else
fill=false;
for(var j=0; j<H; j=j+gap){
if(fill==true){
canvas.fillStyle = '#eeeeee';
canvas.fillRect(i, j, gap, gap);
fill = false;
}
else
fill = true;
}
}
};
//credits to Victor Haydin
this.toolFiller = function(context, W, H, x, y, color_to, sensitivity, anti_aliasing){
canvas_front.clearRect(0, 0, WIDTH, HEIGHT);
var img_tmp = canvas_front.getImageData(0, 0, W, H);
var imgData_tmp = img_tmp.data;
var img = context.getImageData(0, 0, W, H);
var imgData = img.data;
var k = ((y * (img.width * 4)) + (x * 4));
var dx = [ 0, -1, +1, 0];
var dy = [-1, 0, 0, +1];
var color_from = {
r: imgData[k+0],
g: imgData[k+1],
b: imgData[k+2],
a: imgData[k+3]
};
if(color_from.r == color_to.r &&
color_from.g == color_to.g &&
color_from.b == color_to.b &&
color_from.a == color_to.a)
return false;
var stack = [];
stack.push([x, y]);
while (stack.length > 0){
var curPoint = stack.pop();
for (var i = 0; i < 4; i++){
var nextPointX = curPoint[0] + dx[i];
var nextPointY = curPoint[1] + dy[i];
if (nextPointX < 0 || nextPointY < 0 || nextPointX >= W || nextPointY >= H)
continue;
var k = (nextPointY * W + nextPointX) * 4;
if(imgData_tmp[k+3] != 0) continue; //already parsed
//check
if(Math.abs(imgData[k+0] - color_from.r) <= sensitivity &&
Math.abs(imgData[k+1] - color_from.g) <= sensitivity &&
Math.abs(imgData[k+2] - color_from.b) <= sensitivity &&
Math.abs(imgData[k+3] - color_from.a) <= sensitivity){
//fill pixel
imgData_tmp[k] = color_to.r; //r
imgData_tmp[k+1] = color_to.g; //g
imgData_tmp[k+2] = color_to.b; //b
imgData_tmp[k+3] = color_to.a; //a
stack.push([nextPointX, nextPointY]);
}
}
}
canvas_front.putImageData(img_tmp, 0, 0);
if(anti_aliasing == true){
context.shadowColor = "rgba("+color_to.r+", "+color_to.g+", "+color_to.b+", "+color_to.a/255+")";
context.shadowBlur = 5;
}
context.drawImage(document.getElementById("canvas_front"), 0, 0);
//reset
context.shadowBlur = 0;
};
this.tool_magic_wand = function(context, W, H, x, y, sensitivity, anti_aliasing){
canvas_front.clearRect(0, 0, WIDTH, HEIGHT);
canvas_front.rect(0, 0, WIDTH, HEIGHT);
canvas_front.fillStyle = "rgba(255, 255, 255, 0)";
canvas_front.fill();
var img_tmp = canvas_front.getImageData(0, 0, W, H);
var imgData_tmp = img_tmp.data;
var img = context.getImageData(0, 0, W, H);
var imgData = img.data;
var k = ((y * (img.width * 4)) + (x * 4));
var dx = [ 0, -1, +1, 0];
var dy = [-1, 0, 0, +1];
var color_to = {
r: 255,
g: 255,
b: 255,
a: 255
};
var color_from = {
r: imgData[k+0],
g: imgData[k+1],
b: imgData[k+2],
a: imgData[k+3]
};
if(color_from.r == color_to.r &&
color_from.g == color_to.g &&
color_from.b == color_to.b &&
color_from.a == 0){
return false;
}
var stack = [];
stack.push([x, y]);
while (stack.length > 0){
var curPoint = stack.pop();
for (var i = 0; i < 4; i++){
var nextPointX = curPoint[0] + dx[i];
var nextPointY = curPoint[1] + dy[i];
if (nextPointX < 0 || nextPointY < 0 || nextPointX >= W || nextPointY >= H)
continue;
var k = (nextPointY * W + nextPointX) * 4;
if(imgData_tmp[k+3] != 0) continue; //already parsed
if(Math.abs(imgData[k] - color_from.r) <= sensitivity
&& Math.abs(imgData[k+1] - color_from.g) <= sensitivity
&& Math.abs(imgData[k+2] - color_from.b) <= sensitivity
&& Math.abs(imgData[k+3] - color_from.a) <= sensitivity){
imgData_tmp[k] = color_to.r; //r
imgData_tmp[k+1] = color_to.g; //g
imgData_tmp[k+2] = color_to.b; //b
imgData_tmp[k+3] = color_to.a; //a
stack.push([nextPointX, nextPointY]);
}
}
}
//destination-out + blur = anti-aliasing
if(anti_aliasing == true)
img_tmp = ImageFilters.StackBlur(img_tmp, 2);
canvas_front.putImageData(img_tmp, 0, 0);
context.globalCompositeOperation = "destination-out";
context.drawImage(document.getElementById("canvas_front"), 0, 0);
//reset
context.shadowBlur = 0;
context.globalCompositeOperation = 'source-over';
};
this.if_blank = function(canvas){
var img = canvas.getContext("2d").getImageData(0, 0, canvas.width, canvas.height);
var imgData = img.data;
if(MAIN.TRANSPARENCY == false){
//transparency disabled
for(var i = 0; i < imgData.length; i += 4){
if(imgData[i] < 255 || imgData[i+1] < 255 || imgData[i+2] < 255) return false;
}
}
else{
//transparenc enabled
for(var i = 0; i < imgData.length; i += 4){
if(imgData[i+3] == 0) continue; //transparent
if(imgData[i] < 255 || imgData[i+1] < 255 || imgData[i+2] < 255) return false;
}
}
return true;
};
this.trim_info = function(canvas, trim_white, include_white){
var top = 0;
var left = 0;
var bottom = 0;
var right = 0;
var img = canvas.getContext("2d").getImageData(0, 0, canvas.width, canvas.height);
var imgData = img.data;
//check top
main1:
for(var y = 0; y < img.height; y++){
for(var x = 0; x < img.width; x++){
var k = ((y * (img.width * 4)) + (x * 4));
if(imgData[k+3] == 0) continue; //transparent
if(include_white !== true && imgData[k] == 255 && imgData[k+1] == 255 && imgData[k+2] == 255) continue; //white
break main1;
}
top++;
}
//check left
main2:
for(var x = 0; x < img.width; x++){
for(var y = 0; y < img.height; y++){
var k = ((y * (img.width * 4)) + (x * 4));
if(imgData[k+3] == 0) continue; //transparent
if(include_white !== true && imgData[k] == 255 && imgData[k+1] == 255 && imgData[k+2] == 255) continue; //white
break main2;
}
left++;
}
//check bottom
main3:
for(var y = img.height-1; y >= 0; y--){
for(var x = img.width-1; x >= 0; x--){
var k = ((y * (img.width * 4)) + (x * 4));
if(imgData[k+3] == 0) continue; //transparent
if(include_white !== true && imgData[k] == 255 && imgData[k+1] == 255 && imgData[k+2] == 255) continue; //white
break main3;
}
bottom++;
}
//check right
main4:
for(var x = img.width-1; x >= 0; x--){
for(var y = img.height-1; y >= 0; y--){
var k = ((y * (img.width * 4)) + (x * 4));
if(imgData[k+3] == 0) continue; //transparent
if(include_white !== true && imgData[k] == 255 && imgData[k+1] == 255 && imgData[k+2] == 255) continue; //white
break main4;
}
right++;
}
return {
top: top,
left: left,
bottom: bottom,
right: right
};
};
this.trim = function(layer, no_resize, include_white){
var all_top = HEIGHT;
var all_left = WIDTH;
var all_bottom = HEIGHT;
var all_right = WIDTH;
for(var i in LAYERS){
if(layer != undefined && LAYERS[i].name != layer) continue;
var top = 0;
var left = 0;
var bottom = 0;
var right = 0;
var img = document.getElementById(LAYERS[i].name).getContext("2d").getImageData(0, 0, WIDTH, HEIGHT);
var imgData = img.data;
//check top
main1:
for(var y = 0; y < img.height; y++){
for(var x = 0; x < img.width; x++){
var k = ((y * (img.width * 4)) + (x * 4));
if(imgData[k+3] == 0) continue; //transparent
if(include_white !== true && imgData[k] == 255 && imgData[k+1] == 255 && imgData[k+2] == 255) continue; //white
break main1;
}
top++;
}
//check left
main2:
for(var x = 0; x < img.width; x++){
for(var y = 0; y < img.height; y++){
var k = ((y * (img.width * 4)) + (x * 4));
if(imgData[k+3] == 0) continue; //transparent
if(include_white !== true && imgData[k] == 255 && imgData[k+1] == 255 && imgData[k+2] == 255) continue; //white
break main2;
}
left++;
}
//check bottom
main3:
for(var y = img.height-1; y >= 0; y--){
for(var x = img.width-1; x >= 0; x--){
var k = ((y * (img.width * 4)) + (x * 4));
if(imgData[k+3] == 0) continue; //transparent
if(include_white !== true && imgData[k] == 255 && imgData[k+1] == 255 && imgData[k+2] == 255) continue; //white
break main3;
}
bottom++;
}
//check right
main4:
for(var x = img.width-1; x >= 0; x--){
for(var y = img.height-1; y >= 0; y--){
var k = ((y * (img.width * 4)) + (x * 4));
if(imgData[k+3] == 0) continue; //transparent
if(include_white !== true && imgData[k] == 255 && imgData[k+1] == 255 && imgData[k+2] == 255) continue; //white
break main4;
}
right++;
}
all_top = Math.min(all_top, top);
all_left = Math.min(all_left, left);
all_bottom = Math.min(all_bottom, bottom);
all_right = Math.min(all_right, right);
}
//move to top-left corner
for(var i in LAYERS){
if(layer != undefined && LAYERS[i].name != layer) continue;
tmp_data = document.getElementById(LAYERS[i].name).getContext("2d").getImageData(0, 0, WIDTH, HEIGHT);
document.getElementById(LAYERS[i].name).getContext("2d").clearRect(0, 0, WIDTH, HEIGHT);
document.getElementById(LAYERS[i].name).getContext("2d").putImageData(tmp_data, -all_left, -all_top);
var canvas_name = LAYERS[i].name;
}
//resize
if(no_resize != undefined) return false;
if(layer != undefined){
var W = round(WIDTH - all_left - all_right);
var H = round(HEIGHT - all_top - all_bottom);
var imageData = document.getElementById(layer).getContext("2d").getImageData(0, 0, W, H);
document.getElementById(layer).width = W;
document.getElementById(layer).height = H;
document.getElementById(layer).getContext("2d").clearRect(0, 0, W, H);
document.getElementById(layer).getContext("2d").putImageData(imageData, 0, 0);
return {
top: all_top,
left: all_left,
bottom: all_bottom,
right: all_right
};
}
else{
WIDTH = WIDTH - all_left - all_right;
HEIGHT = HEIGHT - all_top - all_bottom;
if(WIDTH<1) WIDTH = 1;
if(HEIGHT<1) HEIGHT = 1;
RATIO = WIDTH/HEIGHT;
LAYER.set_canvas_size();
}
LAYER.update_info_block();
};
this.effect_bw = function(context, W, H, level, dithering){
var img = context.getImageData(0, 0, W, H);
var imgData = img.data;
var grey, c, quant_error, m;
if(dithering !== true){
//no differing
for(var i = 0; i < imgData.length; i += 4){
if(imgData[i+3] == 0) continue; //transparent
grey = round(0.2126 * imgData[i] + 0.7152 * imgData[i+1] + 0.0722 * imgData[i+2]);
if(grey <= level)
c = 0;
else
c = 255;
imgData[i] = c;
imgData[i+1] = c;
imgData[i+2] = c;
}
}
else{
//FloydSteinberg dithering
canvas_front.clearRect(0, 0, W, H); //temp canvas for storing pixel data shifts
var img2 = canvas_front.getImageData(0, 0, W, H);
var imgData2 = img2.data;
for(var j = 0; j < H; j++){
for(var i = 0; i < W; i++){
var k = ((j * (W * 4)) + (i * 4));
if(imgData[k+3] == 0) continue; //transparent
grey = round(0.2126 * imgData[k] + 0.7152 * imgData[k+1] + 0.0722 * imgData[k+2]);
grey = grey + imgData2[k]; //add data shft from previous iterations
c = Math.floor(grey / 256);
if(c == 1)
c = 255;
imgData[k] = c;
imgData[k+1] = c;
imgData[k+2] = c;
quant_error = grey - c;
if(i+1 < W){
m = k + 4;
imgData2[m] += Math.round(quant_error * 7/16);
}
if(i-1 > 0 && j+1 < H){
m = k - 4 + W*4;
imgData2[m] += Math.round(quant_error * 3/16);
}
if(j+1 < H){
m = k + W*4;
imgData2[m] += Math.round(quant_error * 5/16);
}
if(i+1 < W && j+1 < H){
m = k + 4 + W*4;
imgData2[m] += Math.round(quant_error * 1/16);
}
}
}
}
context.putImageData(img, 0, 0);
};
this.decrease_colors = function(canvas_source, canvas_destination, W, H, colors, dithering, greyscale){
var context = canvas_destination.getContext("2d");
var img = context.getImageData(0, 0, W, H);
var imgData = img.data;
var palette = [];
//collect top colors
var block_size = 10;
var ctx = canvas_front; //use temp canvas
ctx.clearRect(0, 0, W, H);
ctx.drawImage(canvas_source, 0, 0, Math.ceil(canvas_source.width/block_size), Math.ceil(canvas_source.height/block_size)); //simple resize
var img_p = ctx.getImageData(0, 0, Math.ceil(canvas_source.width/block_size), Math.ceil(canvas_source.height/block_size));
var imgData_p = img_p.data;
ctx.clearRect(0, 0, W, H);
for(var i = 0; i < imgData_p.length; i += 4){
if(imgData_p[i+3] == 0) continue; //transparent
var grey = round(0.2126 * imgData_p[i] + 0.7152 * imgData_p[i+1] + 0.0722 * imgData_p[i+2]);
palette.push([ imgData_p[i], imgData_p[i+1], imgData_p[i+2], grey ]);
}
//calculate weights
var grey_palette = [];
for(var i = 0; i < 256; i++)
grey_palette[i] = 0;
for(var i = 0; i < palette.length; i++)
grey_palette[palette[i][3]]++;
//remove similar colors
for(var max = 10*3; max < 100*3; max = max + 10*3){
if(palette.length <= colors) break;
for(var i = 0; i < palette.length; i++){
if(palette.length <= colors) break;
var valid = true;
for(var j = 0; j < palette.length; j++){
if(palette.length <= colors) break;
if(i == j) continue;
if(Math.abs(palette[i][0] - palette[j][0]) + Math.abs(palette[i][1] - palette[j][1]) + Math.abs(palette[i][2] - palette[j][2]) < max){
if(grey_palette[palette[i][3]] > grey_palette[palette[j][3]]){
//remove color
palette.splice(j, 1);
j--;
}
else{
valid = false;
break;
}
}
}
//remove color
if(valid == false){
palette.splice(i, 1);
i--;
}
}
}
//change
var p_n = palette.length;
for(var j = 0; j < H; j++){
for(var i = 0; i < W; i++){
var k = ((j * (W * 4)) + (i * 4));
if(imgData[k+3] == 0) continue; //transparent
var grey = round(0.2126 * imgData_p[k] + 0.7152 * imgData_p[k+1] + 0.0722 * imgData_p[k+2]);
//find closest color
var index1 = 0;
var min = 999999;
var diff1;
for(var m=0; m < p_n; m++){
var diff = Math.abs(palette[m][0] - imgData[k]) + Math.abs(palette[m][1] - imgData[k+1]) + Math.abs(palette[m][2] - imgData[k+2]);
if(diff < min){
min = diff;
index1 = m;
diff1 = diff;
}
}
if(dithering == false){
imgData[k] = palette[index1][0];
imgData[k+1] = palette[index1][1];
imgData[k+2] = palette[index1][2];
}
else{
//dithering
if(diff1 >= 10){
//find second close color
var index2;
var min2 = 256*3;
var diff2;
for(var m=0; m < p_n; m++){
if(m== index1) continue; //we already have this
if(palette[index1][3] < grey && palette[m][3] < grey) continue;
if(palette[index1][3] > grey && palette[m][3] > grey) continue;
var diff = Math.abs(palette[m][0] - imgData[k]) + Math.abs(palette[m][1] - imgData[k+1]) + Math.abs(palette[m][2] - imgData[k+2]);
if(diff < min2){
min2 = diff;
index2 = m;
diff2 = diff;
}
}
}
var c;
if(index2 == undefined)
c = palette[index1]; //only 1 match
else{
//randomize
var rand = HELPER.getRandomInt(-diff1, diff2);
if(rand < 0)
c = palette[index2];
else
c = palette[index1];
}
imgData[k] = c[0];
imgData[k+1] = c[1];
imgData[k+2] = c[2];
}
if(greyscale == true){
var mid = round(0.2126 * imgData[k] + 0.7152 * imgData[k+1] + 0.0722 * imgData[k+2]);
imgData[k] = mid;
imgData[k+1] = mid;
imgData[k+2] = mid;
}
}
}
canvas_destination.getContext("2d").putImageData(img, 0, 0);
};
//converts greyscale images to coloured
this.colorize = function(context, W, H, rand_power, max_gap, dither, manual_colors){
if(manual_colors == undefined || manual_colors === true){
var colors = [];
for(var x=0; x < 3; x++){
colors[x] = [];
var pre = HELPER.getRandomInt(-1 * rand_power, rand_power);
for(var i = 0; i <= 255; i++){
colors[x][i] = HELPER.getRandomInt(pre - rand_power, pre + rand_power);
if(colors[x][i] < -1*max_gap) colors[x][i] += 10;
else if(colors[x][i] > max_gap) colors[x][i] -= 10;
pre = colors[x][i];
}
}
if(manual_colors === true)
return colors;
}
else
var colors = manual_colors;
var img = context.getImageData(0, 0, W, H);
//colorize
var imgData = img.data;
for(var i = 0; i < imgData.length; i += 4){
if(imgData[i+3] == 0) continue; //transparent
if(dither == true){
var diff = Math.abs(colors[0][imgData[x]]) + Math.abs(colors[0][imgData[x]]) + Math.abs(colors[0][imgData[x]]);
diff = diff / 3;
}
for(var c = 0; c < 3; c++){
var x = i + c;
if(dither == false)
imgData[x] += colors[c][imgData[x]];
else{
if(diff < rand_power*6)
imgData[x] += colors[c][imgData[x]];
else{
//big difference here - randomize
var rand = HELPER.getRandomInt(Math.min(0, colors[c][imgData[x]]), Math.max(0, colors[c][imgData[x]]));
imgData[x] += rand;
}
}
if(imgData[x] > 255) imgData[x] = 255;
if(imgData[x] < 0) imgData[x] = 0;
}
}
context.putImageData(img, 0, 0);
return false;
};
//fixing white and black color balance
this.auto_adjust = function(context, W, H){
//settings
var white = 240; //white color min
var black = 30; //black color max
var target_white = 1; //how much % white colors should take
var target_black = 0.5; //how much % black colors should take
var modify = 1.1; //color modify strength
document.body.style.cursor = "wait";
var img = context.getImageData(0, 0, W, H);
var imgData = img.data;
var n = 0; //pixels count without transparent
//make sure we have white
var n_valid = 0;
for(var i = 0; i < imgData.length; i += 4){
if(imgData[i+3] == 0) continue; //transparent
if((imgData[i] + imgData[i+1] + imgData[i+2]) / 3 > white) n_valid++;
n++;
}
target = target_white;
var n_fix_white = 0;
var done = false;
for(var j=0; j < 30; j++){
if(n_valid * 100 / n >= target) done = true;
if(done == true) break;
n_fix_white++;
//adjust
for(var i = 0; i < imgData.length; i += 4){
if(imgData[i+3] == 0) continue; //transparent
for(var c = 0; c < 3; c++){
var x = i + c;
if(imgData[x] < 10) continue;
//increase white
imgData[x] *= modify;
imgData[x] = round(imgData[x]);
if(imgData[x] > 255) imgData[x] = 255;
}
}
//recheck
n_valid = 0;
for(var i = 0; i < imgData.length; i += 4){
if(imgData[i+3] == 0) continue; //transparent
if((imgData[i] + imgData[i+1] + imgData[i+2]) / 3 > white) n_valid++;
}
}
//make sure we have black
n_valid = 0;
for(var i = 0; i < imgData.length; i += 4){
if(imgData[i+3] == 0) continue; //transparent
if((imgData[i] + imgData[i+1] + imgData[i+2]) / 3 < black) n_valid++;
}
target = target_black;
var n_fix_black = 0;
var done = false;
for(var j=0; j < 30; j++){
if(n_valid * 100 / n >= target) done = true;
if(done == true) break;
n_fix_black++;
//adjust
for(var i = 0; i < imgData.length; i += 4){
if(imgData[i+3] == 0) continue; //transparent
for(var c = 0; c < 3; c++){
var x = i + c;
if(imgData[x] > 240) continue;
//increase black
imgData[x] -= (255-imgData[x]) * modify - (255-imgData[x]);
imgData[x] = round(imgData[x]);
}
}
//recheck
n_valid = 0;
for(var i = 0; i < imgData.length; i += 4){
if(imgData[i+3] == 0) continue; //transparent
if((imgData[i] + imgData[i+1] + imgData[i+2]) / 3 < black) n_valid++;
}
}
//save
context.putImageData(img, 0, 0);
document.body.style.cursor = "auto";
//log('Iterations: brighten='+n_fix_white+", darken="+n_fix_black);
};
this.zoom = function(recalc, scroll){
if(recalc != undefined){
//zoom-in or zoom-out
if(recalc == 1 || recalc == -1){
var step = 100;
if(ZOOM <= 100 && recalc < 0)
step = 10;
if(ZOOM <100 && recalc > 0)
step = 10;
if(recalc*step + ZOOM > 0){
ZOOM = ZOOM + recalc*step;
if(ZOOM > 100 && ZOOM < 200)
ZOOM = 100;
}
}
//zoom using exact value
else
ZOOM = parseInt(recalc);
CON.calc_preview_auto();
}
document.getElementById("zoom_nr").innerHTML = ZOOM;
document.getElementById("zoom_range").value = ZOOM;
//change scale and repaint
document.getElementById('canvas_back').style.width = round(WIDTH * ZOOM / 100)+"px";
document.getElementById('canvas_back').style.height = round(HEIGHT * ZOOM / 100)+"px";
for(var i in LAYERS){
document.getElementById(LAYERS[i].name).style.width = round(WIDTH * ZOOM / 100)+"px";
document.getElementById(LAYERS[i].name).style.height = round(HEIGHT * ZOOM / 100)+"px";
}
document.getElementById('canvas_front').style.width = round(WIDTH * ZOOM / 100)+"px";
document.getElementById('canvas_front').style.height = round(HEIGHT * ZOOM / 100)+"px";
document.getElementById('canvas_grid').style.width = round(WIDTH * ZOOM / 100)+"px";
document.getElementById('canvas_grid').style.height = round(HEIGHT * ZOOM / 100)+"px";
//check main resize corners
if(ZOOM != 100){
document.getElementById('resize-w').style.display = "none";
document.getElementById('resize-h').style.display = "none";
document.getElementById('resize-wh').style.display = "none";
}
else{
document.getElementById('resize-w').style.display = "block";
document.getElementById('resize-h').style.display = "block";
document.getElementById('resize-wh').style.display = "block";
}
if(scroll != undefined)
CON.scroll_window();
DRAW.redraw_preview();
return true;
};
this.redraw_preview = function(){
canvas_preview.beginPath();
canvas_preview.rect(0, 0, DRAW.PREVIEW_SIZE.w, DRAW.PREVIEW_SIZE.h);
canvas_preview.fillStyle = "#ffffff";
canvas_preview.fill();
DRAW.draw_background(canvas_preview, DRAW.PREVIEW_SIZE.w, DRAW.PREVIEW_SIZE.h, 5);
//redraw preview area
canvas_preview.save();
canvas_preview.scale(DRAW.PREVIEW_SIZE.w/WIDTH, DRAW.PREVIEW_SIZE.h/HEIGHT);
for(var i in LAYERS){
if(LAYERS[i].visible == false) continue;
canvas_preview.drawImage(document.getElementById(LAYERS[i].name), 0, 0, WIDTH, HEIGHT);
}
canvas_preview.restore();
//active zone
z_x = CON.ZOOM_X;
z_y = CON.ZOOM_Y;
if(z_x > DRAW.PREVIEW_SIZE.w - CON.mini_rect_data.w)
z_x = DRAW.PREVIEW_SIZE.w - CON.mini_rect_data.w;
if(z_y > DRAW.PREVIEW_SIZE.h - CON.mini_rect_data.h)
z_y = DRAW.PREVIEW_SIZE.h - CON.mini_rect_data.h;
canvas_preview.lineWidth = 1;
canvas_preview.beginPath();
canvas_preview.rect(round(z_x) + 0.5, round(z_y) + 0.5, CON.mini_rect_data.w, CON.mini_rect_data.h);
canvas_preview.fillStyle = "rgba(0, 0, 0, 0.2)";
canvas_preview.strokeStyle = "#393939";
canvas_preview.fill();
canvas_preview.stroke();
return true;
};
this.draw_arrow = function(context, fromx, fromy, tox, toy, headlen){
if(headlen == undefined)
headlen = 10; // length of head in pixels
var dx = tox-fromx;
var dy = toy-fromy;
var angle = Math.atan2(dy,dx);
context.beginPath();
context.moveTo(fromx, fromy);
context.lineTo(tox, toy);
context.stroke();
context.beginPath();
context.moveTo(tox-headlen*Math.cos(angle-Math.PI/6),toy-headlen*Math.sin(angle-Math.PI/6));
context.lineTo(tox, toy);
context.lineTo(tox-headlen*Math.cos(angle+Math.PI/6),toy-headlen*Math.sin(angle+Math.PI/6));
context.stroke();
};
//hermite resample - classic "rings.gif" 1000x1000 resize to 200x200 record - 0.040
this.resample_hermite = function(canvas, W, H, W2, H2){
var time1 = Date.now();
var img = canvas.getContext("2d").getImageData(0, 0, W, H);
var img2 = canvas.getContext("2d").getImageData(0, 0, W2, H2);
var data = img.data;
var data2 = img2.data;
var ratio_w = W / W2;
var ratio_h = H / H2;
var ratio_w_half = Math.ceil(ratio_w/2);
var ratio_h_half = Math.ceil(ratio_h/2);
for(var j = 0; j < H2; j++){
for(var i = 0; i < W2; i++){
var x2 = (i + j*W2) * 4;
var weight = 0;
var weights = 0;
var weights_alpha = 0;
var gx_r = gx_g = gx_b = gx_a = 0;
var center_y = (j + 0.5) * ratio_h;
for(var yy = Math.floor(j * ratio_h); yy < (j + 1) * ratio_h; yy++){
var dy = Math.abs(center_y - (yy + 0.5)) / ratio_h_half;
var center_x = (i + 0.5) * ratio_w;
var w0 = dy*dy; //pre-calc part of w
for(var xx = Math.floor(i * ratio_w); xx < (i + 1) * ratio_w; xx++){
var dx = Math.abs(center_x - (xx + 0.5)) / ratio_w_half;
var w = Math.sqrt(w0 + dx*dx);
if(w >= -1 && w <= 1){
//hermite filter
weight = 2 * w*w*w - 3*w*w + 1;
if(weight > 0){
dx = 4*(xx + yy*W);
//alpha
gx_a += weight * data[dx + 3];
weights_alpha += weight;
//colors
if(data[dx + 3] < 255)
weight = weight * data[dx + 3] / 250;
gx_r += weight * data[dx];
gx_g += weight * data[dx + 1];
gx_b += weight * data[dx + 2];
weights += weight;
}
}
}
}
data2[x2] = gx_r / weights;
data2[x2 + 1] = gx_g / weights;
data2[x2 + 2] = gx_b / weights;
data2[x2 + 3] = gx_a / weights_alpha;
}
}
console.log("hermite = "+(Math.round(Date.now() - time1)/1000)+" s");
canvas.getContext("2d").clearRect(0, 0, Math.max(W, W2), Math.max(H, H2));
canvas.getContext("2d").putImageData(img2, 0, 0);
};
this.resample_hermite_threads = function(canvas, W, H, W2, H2){
var time1 = Date.now();
var img = canvas.getContext("2d").getImageData(0, 0, W, H);
var img2 = canvas.getContext("2d").getImageData(0, 0, W2, H2);
var data2 = img2.data;
var cores = 8;
var cpu_in_use = 0;
canvas.getContext("2d").clearRect(0, 0, W, H);
for(var c = 0; c < cores; c++){
cpu_in_use++;
var my_worker = new Worker("libs/worker-hermite.js");
my_worker.onmessage = function(event){ //log(event.data);return false;
cpu_in_use--;
var complete = ((cores - cpu_in_use) / cores * 100 | 0);
var offset = event.data.offset; //log( event.data.data.length);
for(var i = 0; i < event.data.data.length; i += 4){
var x = offset + i; //log([ x, event.data.data[i], event.data.data[i+1],event.data.data[i+2],event.data.data[i+3], ]); return false;
data2[x] = event.data.data[i];
data2[x + 1] = event.data.data[i+1];
data2[x + 2] = event.data.data[i+2];
data2[x + 3] = event.data.data[i+3];
}
//finish
if(cpu_in_use <= 0){
console.log("hermite "+cores+" cores = "+(Math.round(Date.now() - time1)/1000)+" s");
canvas.getContext("2d").clearRect(0, 0, W, H);
canvas.getContext("2d").putImageData(img2, 0, 0);
if(MENU.last_menu != 'layer_resize')
DRAW.trim();
DRAW.zoom();
}
};
my_worker.postMessage([img, W, H, W2, H2, c, cores]);
}
};
}

1598
js/draw_tools.js Normal file

File diff suppressed because it is too large Load Diff

148
js/edit.js Normal file
View File

@ -0,0 +1,148 @@
/* global MAIN, POP, LAYER, DRAW, GUI */
/* global WIDTH, HEIGHT, canvas_active, canvas_front */
var EDIT = new EDIT_CLASS();
/**
* manages edit actions
*
* @author ViliusL
*/
function EDIT_CLASS() {
/**
* used to store internal copied objects data
*/
var PASTE_DATA = false;
/**
* latest 3 saved states of all layers for undo
*/
var layers_archive = [{}, {}, {}];
/**
* on undo, current data index in layers_archive array
*/
var undo_level = 0;
//undo
this.edit_undo = function () {
this.undo();
};
//cut
this.edit_cut = function () {
this.save_state();
if (DRAW.select_data != false) {
this.copy_to_clipboard();
canvas_active().clearRect(DRAW.select_data.x, DRAW.select_data.y, DRAW.select_data.w, DRAW.select_data.h);
DRAW.select_data = false;
canvas_front.clearRect(0, 0, WIDTH, HEIGHT);
}
};
//copy
this.edit_copy = function () {
if (DRAW.select_data != false) {
this.copy_to_clipboard();
}
};
//paste
this.edit_paste = function () {
this.save_state();
this.paste('menu');
};
//select all
this.edit_select = function () {
DRAW.select_data = {
x: 0,
y: 0,
w: WIDTH,
h: HEIGHT
};
canvas_front.clearRect(0, 0, WIDTH, HEIGHT);
GUI.draw_selected_area();
};
//clear selection
this.edit_clear = function () {
DRAW.select_data = false;
canvas_front.clearRect(0, 0, WIDTH, HEIGHT);
};
this.copy_to_clipboard = function () {
PASTE_DATA = false;
PASTE_DATA = document.createElement("canvas");
PASTE_DATA.width = DRAW.select_data.w;
PASTE_DATA.height = DRAW.select_data.h;
PASTE_DATA.getContext("2d").drawImage(canvas_active(true), DRAW.select_data.x, DRAW.select_data.y, DRAW.select_data.w, DRAW.select_data.h, 0, 0, DRAW.select_data.w, DRAW.select_data.h);
};
this.paste = function (type) {
if (PASTE_DATA == false) {
if (type == 'menu') {
POP.add({title: "Error:", value: 'Empty data'});
POP.add({title: "Notice:", value: 'To paste from clipboard, use Ctrl-V.'});
POP.show('Notice', '');
}
return false;
}
tmp = new Array();
var new_name = 'Layer #' + (LAYER.layers.length + 1);
LAYER.create_canvas(new_name);
LAYER.layers.push({name: new_name, visible: true});
LAYER.layer_active = LAYER.layers.length - 1;
canvas_active().drawImage(PASTE_DATA, 0, 0);
LAYER.layer_renew();
};
this.save_state = function () {
undo_level = 0;
j = 0;
//move previous
layers_archive[2] = layers_archive[1];
layers_archive[1] = layers_archive[0];
//save last state
layers_archive[j] = {};
layers_archive[j].width = WIDTH;
layers_archive[j].height = HEIGHT;
layers_archive[j].data = {};
for (var i in LAYER.layers) {
layers_archive[j].data[LAYER.layers[i].name] = document.createElement('canvas');
layers_archive[j].data[LAYER.layers[i].name].width = WIDTH;
layers_archive[j].data[LAYER.layers[i].name].height = HEIGHT;
layers_archive[j].data[LAYER.layers[i].name].getContext('2d').drawImage(document.getElementById(LAYER.layers[i].name), 0, 0);
}
return true;
};
//supports 3 levels undo system - more levels requires more memory
this.undo = function () {
if (layers_archive.length == 0)
return false;
j = undo_level;
undo_level++;
if (layers_archive[j] == undefined || layers_archive[j].width == undefined)
return false;
if (WIDTH != layers_archive[j].width || HEIGHT != layers_archive[j].height) {
WIDTH = layers_archive[j].width;
HEIGHT = layers_archive[j].height;
LAYER.set_canvas_size(true);
return true; //size changed, cant undo
}
//undo
for (var i in LAYER.layers) {
if (layers_archive[j].data[LAYER.layers[i].name] != undefined) {
document.getElementById(LAYER.layers[i].name).getContext("2d").clearRect(0, 0, WIDTH, HEIGHT);
document.getElementById(LAYER.layers[i].name).getContext("2d").drawImage(layers_archive[j].data[LAYER.layers[i].name], 0, 0);
}
}
GUI.zoom();
return true;
};
}

1178
js/effects.js vendored Normal file

File diff suppressed because it is too large Load Diff

289
js/elements.js Normal file
View File

@ -0,0 +1,289 @@
/* global WIDTH, HEIGHT */
var EL = new ELEMENTS_CLASS();
/**
* class that draw simple elements
*
* @author ViliusL
*/
function ELEMENTS_CLASS() {
//draw lines
this.line = function(ctx, from_x, from_y, to_x, to_y, size){
ctx.beginPath();
if(size != undefined)
ctx.lineWidth = size;
ctx.moveTo(from_x + 0.5, from_y + 0.5);
ctx.lineTo(to_x + 0.5, to_y + 0.5);
ctx.stroke();
};
//draws rectangle
this.rectangle = function (ctx, x, y, width, height, fill, stroke) {
x = x + 0.5;
y = y + 0.5;
if (typeof stroke == "undefined")
stroke = true;
if(fill == false && stroke == undefined)
stroke = true;
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x + width, y);
ctx.quadraticCurveTo(x + width, y, x + width, y);
ctx.lineTo(x + width, y + height);
ctx.quadraticCurveTo(x + width, y + height, x + width, y + height);
ctx.lineTo(x, y + height);
ctx.quadraticCurveTo(x, y + height, x, y + height);
ctx.lineTo(x, y);
ctx.quadraticCurveTo(x, y, x, y);
ctx.closePath();
if (stroke) {
ctx.stroke();
}
if (fill) {
ctx.fill();
}
};
//draws square
this.square = function (ctx, x, y, width, height, fill, stroke) {
x = x + 0.5;
y = y + 0.5;
if (typeof stroke == "undefined")
stroke = true;
if(fill == false && stroke == undefined)
stroke = true;
if (Math.abs(width) < Math.abs(height)){
if(width > 0)
width = Math.abs(height);
else
width = -Math.abs(height);
}
else{
if(height > 0)
height = Math.abs(width);
else
height = -Math.abs(width);
}
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x + width, y);
ctx.quadraticCurveTo(x + width, y, x + width, y);
ctx.lineTo(x + width, y + height);
ctx.quadraticCurveTo(x + width, y + height, x + width, y + height);
ctx.lineTo(x, y + height);
ctx.quadraticCurveTo(x, y + height, x, y + height);
ctx.lineTo(x, y);
ctx.quadraticCurveTo(x, y, x, y);
ctx.closePath();
if (stroke) {
ctx.stroke();
}
if (fill) {
ctx.fill();
}
};
this.circle = function (ctx, x, y, size, color) {
ctx.lineWidth = 1;
if(color != undefined)
ctx.strokeStyle = color;
else
ctx.strokeStyle = "#000000";
ctx.beginPath();
ctx.arc(x, y, size / 2, 0, Math.PI * 2, true);
ctx.stroke();
};
this.ellipse_by_center = function (ctx, cx, cy, w, h, color, fill) {
this.ellipse(ctx, cx - w / 2.0, cy - h / 2.0, w, h, color, fill);
};
this.ellipse = function (ctx, x, y, w, h, color, fill) {
var kappa = .5522848,
ox = (w / 2) * kappa, // control point offset horizontal
oy = (h / 2) * kappa, // control point offset vertical
xe = x + w, // x-end
ye = y + h, // y-end
xm = x + w / 2, // x-middle
ym = y + h / 2; // y-middle
ctx.beginPath();
ctx.moveTo(x, ym);
ctx.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y);
ctx.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym);
ctx.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye);
ctx.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym);
ctx.closePath();
ctx.fillStyle = color;
ctx.strokeStyle = color;
if (fill == undefined)
ctx.stroke();
else
ctx.fill();
};
this.arrow = function (context, fromx, fromy, tox, toy, headlen) {
if (headlen == undefined)
headlen = 10; // length of head in pixels
var dx = tox - fromx;
var dy = toy - fromy;
var angle = Math.atan2(dy, dx);
context.beginPath();
context.moveTo(fromx, fromy);
context.lineTo(tox, toy);
context.stroke();
context.beginPath();
context.moveTo(tox - headlen * Math.cos(angle - Math.PI / 6), toy - headlen * Math.sin(angle - Math.PI / 6));
context.lineTo(tox, toy);
context.lineTo(tox - headlen * Math.cos(angle + Math.PI / 6), toy - headlen * Math.sin(angle + Math.PI / 6));
context.stroke();
};
//dashed objects
this.rectangle_dashed = function (canvas, x1, y1, x2, y2, dashLen, color) {
this.line_dashed(canvas, x1, y1, x2, y1, dashLen, color);
this.line_dashed(canvas, x2, y1, x2, y2, dashLen, color);
this.line_dashed(canvas, x2, y2, x1, y2, dashLen, color);
this.line_dashed(canvas, x1, y2, x1, y1, dashLen, color);
};
this.line_dashed = function (canvas, x1, y1, x2, y2, dashLen, color) {
x1 = x1 + 0.5;
y1 = y1 + 0.5;
x2 = x2 + 0.5;
y2 = y2 + 0.5;
if (color != undefined)
canvas.strokeStyle = color;
else
canvas.strokeStyle = "#000000";
if (dashLen == undefined)
dashLen = 4;
canvas.beginPath();
canvas.moveTo(x1, y1);
var dX = x2 - x1;
var dY = y2 - y1;
var dashes = Math.floor(Math.sqrt(dX * dX + dY * dY) / dashLen);
var dashX = dX / dashes;
var dashY = dY / dashes;
var q = 0;
while (q++ < dashes) {
x1 += dashX;
y1 += dashY;
canvas[q % 2 == 0 ? 'moveTo' : 'lineTo'](x1, y1);
}
canvas[q % 2 == 0 ? 'moveTo' : 'lineTo'](x2, y2);
canvas.stroke();
canvas.closePath();
};
this.image_round = function (canvas, mouse_x, mouse_y, size, img_data, canvas_tmp, anti_alias) {
var size_half = Math.round(size / 2);
var ctx_tmp = canvas_tmp.getContext("2d");
var xx = mouse_x - size_half;
var yy = mouse_y - size_half;
if (xx < 0)
xx = 0;
if (yy < 0)
yy = 0;
ctx_tmp.clearRect(0, 0, WIDTH, HEIGHT);
ctx_tmp.save();
//draw main data
try {
ctx_tmp.drawImage(img_data, mouse_x - size_half, mouse_y - size_half, size, size);
}
catch (err) {
try {
ctx_tmp.putImageData(img_data, xx, yy);
}
catch (err) {
console.log("Error: " + err.message);
}
}
ctx_tmp.globalCompositeOperation = 'destination-in';
//create form
ctx_tmp.fillStyle = '#ffffff';
if (anti_alias == true) {
var gradient = ctx_tmp.createRadialGradient(mouse_x, mouse_y, 0, mouse_x, mouse_y, size_half);
gradient.addColorStop(0, '#ffffff');
gradient.addColorStop(0.8, '#ffffff');
gradient.addColorStop(1, 'rgba(25115,255,255,0');
ctx_tmp.fillStyle = gradient;
}
ctx_tmp.beginPath();
ctx_tmp.arc(mouse_x, mouse_y, size_half, 0, 2 * Math.PI, true);
ctx_tmp.fill();
//draw final data
if (xx + size > WIDTH)
size = WIDTH - xx;
if (yy + size > HEIGHT)
size = HEIGHT - yy;
canvas.drawImage(canvas_tmp, xx, yy, size, size, xx, yy, size, size);
//reset
ctx_tmp.restore();
ctx_tmp.clearRect(0, 0, WIDTH, HEIGHT);
};
}
//http://www.script-tutorials.com/html5-canvas-custom-brush1/
var BezierCurveBrush = {
// inner variables
iPrevX: 0,
iPrevY: 0,
points: null,
// initialization function
init: function () {
},
startCurve: function (x, y) {
this.iPrevX = x;
this.iPrevY = y;
this.points = new Array();
},
getPoint: function (iLength, a) {
var index = a.length - iLength, i;
for (i = index; i < a.length; i++) {
if (a[i]) {
return a[i];
}
}
},
draw: function (ctx, color_rgb, x, y, size) {
if (Math.abs(this.iPrevX - x) > 5 || Math.abs(this.iPrevY - y) > 5) {
this.points.push([x, y]);
// draw main path stroke
ctx.beginPath();
ctx.moveTo(this.iPrevX, this.iPrevY);
ctx.lineTo(x, y);
ctx.lineWidth = size;
ctx.lineCap = 'round';
ctx.lineJoin = 'round';
ctx.strokeStyle = 'rgba(' + color_rgb.r + ', ' + color_rgb.g + ', ' + color_rgb.b + ', 0.9)';
ctx.stroke();
ctx.closePath();
// draw extra strokes
ctx.lineWidth = 1;
ctx.strokeStyle = 'rgba(' + color_rgb.r + ', ' + color_rgb.g + ', ' + color_rgb.b + ', 0.2)';
ctx.beginPath();
var iStartPoint = this.getPoint(25, this.points);
var iFirstPoint = this.getPoint(1, this.points);
var iSecondPoint = this.getPoint(5, this.points);
ctx.moveTo(iStartPoint[0], iStartPoint[1]);
ctx.bezierCurveTo(iFirstPoint[0], iFirstPoint[1], iSecondPoint[0], iSecondPoint[1], x, y);
ctx.stroke();
ctx.closePath();
this.iPrevX = x;
this.iPrevY = y;
}
}
};

784
js/events.js Normal file
View File

@ -0,0 +1,784 @@
/* global FILE, EDIT, HELPER, POP, MAIN, EVENTS, LAYER, IMAGE, GUI, DRAW */
/* global canvas_active, canvas_front, WIDTH, HEIGHT, EXIF */
var EVENTS = new EVENTS_CLASS();
//keyboard handlers
document.onkeydown = function(e) { return EVENTS.on_keyboard_action(e); };
document.onkeyup = function(e) {return EVENTS.on_keyboardup_action(e); };
//mouse
window.ondrop = function(e) { EVENTS.upload_drop(e); }; //drop
window.ondragover = function(e) { e.preventDefault(); };
window.onresize = function(e){ EVENTS.on_resize(); }; //window resize
document.onmousedown = EVENTS.mouse_click; //mouse click
document.onmousemove = EVENTS.mouse_move; //mouse move
document.onmouseup = EVENTS.mouse_release; //mouse resease
document.addEventListener("mousewheel", EVENTS.mouse_wheel_handler, false); //mouse scroll
document.addEventListener("DOMMouseScroll", EVENTS.mouse_wheel_handler, false); //mouse scroll
document.oncontextmenu = function (e) { return EVENTS.mouse_right_click(e); }; //mouse right click
document.getElementById('color_hex').onkeyup = function (e) { GUI.set_color_manual(e); }; //on main color type
document.getElementById('color_hex').onpaste = function (e) { GUI.set_color_manual(e); }; // on paste in main color input
/**
* all events handling
*
* @author ViliusL
*/
function EVENTS_CLASS() {
/**
* mouse data, like positions, clicks
*/
this.mouse;
/**
* if user is holding ctrl
*/
this.ctrl_pressed = false; //17
/**
* if use is holding shift
*/
this.shift_pressed = false; //16
/**
* active area start position in preview canvas in right sidebar
*/
this.ZOOM_POS = [0, 0];
/**
* active area dimensions in preview canvas in right sidebar
*/
this.mini_rect_data = {w: 0, h: 0};
/**
* if use is draging
*/
this.isDrag = false;
/**
* selected area resize rect. size (controlls, where you can resize area)
*/
this.sr_size = 8;
/**
* if false, font canvas is not cleared on mouse release
*/
this.clear_front_on_release = true;
/**
* if canvas size was not changed - autosize possible
*/
var autosize = true;
/**
* mouse click positions
*/
var mouse_click_pos = [false, false];
/**
* last mouse move position
*/
var mouse_move_last = [false, false];
/**
* main canvas resize action
*/
var resize_all = false;
/**
* if mouse was click on canvas
*/
var mouse_click_valid = false;
/**
* mouse click position of popup drag start
*/
var last_pop_click = [0, 0];
/**
* popup position for drgable ability
*/
var popup_pos = [0, 0];
/**
* if popup is dragged
*/
var popup_dragable = false;
//keyboard actions
this.on_keyboard_action = function (event) {
k = event.keyCode; //console.log(k);
if (k != 27) {
if (POP != undefined && POP.active == true)
return true; //dialog active
if (document.activeElement.type == 'text')
return true; //text input selected
}
//up
if (k == 38) {
if (DRAW.active_tool == 'select_tool') {
EDIT.save_state();
LAYER.layer_move_active(0, -1);
return false;
}
}
//down
else if (k == 40) {
if (DRAW.active_tool == 'select_tool') {
EDIT.save_state();
LAYER.layer_move_active(0, 1);
return false;
}
}
//left
else if (k == 39) {
if (DRAW.active_tool == 'select_tool') {
EDIT.save_state();
LAYER.layer_move_active(1, 0);
return false;
}
}
//right
else if (k == 37) {
if (DRAW.active_tool == 'select_tool') {
EDIT.save_state();
LAYER.layer_move_active(-1, 0);
return false;
}
}
//esc
else if (k == 27) {
if (POP != undefined && POP.active == true)
POP.hide();
DRAW.last_line = [false, false];
DRAW.curve_points = [];
if (DRAW.select_data != false) {
DRAW.select_data = false;
canvas_front.clearRect(0, 0, WIDTH, HEIGHT);
DRAW.select_square_action = '';
}
}
//z - undo
else if (k == 90) {
//undo
if (EVENTS.ctrl_pressed == true)
EDIT.undo();
}
//t - trim
else if (k == 84) {
EDIT.save_state();
IMAGE.trim();
}
//o - open
else if (k == 79)
FILE.open();
//s - save
else if (k == 83) {
if (POP != undefined)
FILE.save_dialog(event);
}
//l - rotate left
else if (k == 76) {
EDIT.save_state();
IMAGE.rotate_resize_doc(270, WIDTH, HEIGHT);
IMAGE.rotate_layer({angle: 270}, canvas_active(), WIDTH, HEIGHT);
}
//r - resize
else if (k == 82)
IMAGE.resize_box();
//grid
else if (k == 71) {
if (GUI.grid == false)
GUI.grid = true;
else
GUI.grid = false;
GUI.draw_grid();
}
//del
else if (k == 46) {
if (DRAW.select_data != false) {
EDIT.save_state();
canvas_active().clearRect(DRAW.select_data.x, DRAW.select_data.y, DRAW.select_data.w, DRAW.select_data.h);
DRAW.select_data = false;
DRAW.select_square_action = '';
canvas_front.clearRect(0, 0, WIDTH, HEIGHT);
}
}
//shift
else if (k == 16)
EVENTS.shift_pressed = true;
//ctrl
else if (k == 17) {
if (EVENTS.ctrl_pressed == false)
EVENTS.ctrl_pressed = true;
}
//d
else if (k == 68) {
call_menu(LAYER, 'layer_dublicate');
}
//a
else if (k == 65) {
if (EVENTS.ctrl_pressed == true) {
DRAW.select_data = {
x: 0,
y: 0,
w: WIDTH,
h: HEIGHT
};
GUI.draw_selected_area();
return false;
}
}
//v
else if (k == 86) {
EDIT.save_state();
if (EVENTS.ctrl_pressed == true)
EDIT.paste();
}
//f - fix images
else if (k == 70) {
EDIT.save_state();
IMAGE.auto_adjust(canvas_active(), WIDTH, HEIGHT);
}
//h - histogram
else if (k == 72) {
IMAGE.histogram();
}
//-
else if (k == 109)
GUI.zoom(-1);
//+
else if (k == 107)
GUI.zoom(+1);
//n - new layer
else if (k == 78)
LAYER.add_layer();
//mac support - ctrl
if (k == 17 || event.metaKey || event.ctrlKey) {
if (EVENTS.ctrl_pressed == false)
EVENTS.ctrl_pressed = true;
}
GUI.zoom();
return true;
};
//keyboard release
this.on_keyboardup_action = function (event) {
k = event.keyCode;
//shift
if (k == 16)
EVENTS.shift_pressed = false;
//ctrl
else if (k == 17)
EVENTS.ctrl_pressed = false;
//mac support - ctrl
if (event.metaKey || event.ctrlKey || event.key == 'Meta')
EVENTS.ctrl_pressed = false;
};
// mouse_x, mouse_y, event.pageX, event.pageY
this.get_mouse_position = function (event) {
var valid = true;
if (event.offsetX) {
mouse_rel_x = event.offsetX;
mouse_rel_y = event.offsetY;
}
else if (event.layerX) {
mouse_rel_x = event.layerX;
mouse_rel_y = event.layerY;
}
else
return false;
mouse_x = event.pageX;
mouse_y = event.pageY;
var abs_x = event.pageX;
var abs_y = event.pageY;
if (event.target.id == "canvas_front") {
//in canvas area - relative pos
mouse_x = mouse_rel_x;
mouse_y = mouse_rel_y;
if (GUI.ZOOM != 100) {
mouse_x = Math.floor(mouse_x / GUI.ZOOM * 100);
mouse_y = Math.floor(mouse_y / GUI.ZOOM * 100);
}
}
else {
//outside canvas - absolute pos - canvas offset
mouse_x = mouse_x - 109;
mouse_y = mouse_y - 34;
valid = false;
}
if (event.target.id == "canvas_preview") {
//in preview area - relative pos
mouse_x = mouse_rel_x;
mouse_y = mouse_rel_y;
}
//save - other place will use it too
EVENTS.mouse = {
x: mouse_x,
y: mouse_y,
click_x: mouse_click_pos[0],
click_y: mouse_click_pos[1],
last_x: mouse_move_last[0],
last_y: mouse_move_last[1],
valid: valid,
click_valid: mouse_click_valid,
abs_x: abs_x,
abs_y: abs_y
};
};
//mouse right click
this.mouse_right_click = function (event) {
if (POP != undefined && POP.active == true)
return true;
EVENTS.get_mouse_position(event);
mouse_click_pos[0] = EVENTS.mouse.x;
mouse_click_pos[1] = EVENTS.mouse.y;
for (var i in DRAW) {
if (i == DRAW.active_tool) {
return DRAW[i]('right_click', EVENTS.mouse, event);
break;
}
}
};
//mouse click
this.mouse_click = function (event) {
EVENTS.isDrag = true;
if (POP != undefined && POP.active == true) {
EVENTS.get_mouse_position(event);
last_pop_click[0] = EVENTS.mouse.abs_x;
last_pop_click[1] = EVENTS.mouse.abs_y;
popup = document.getElementById('popup');
popup_pos[0] = parseInt(popup.style.top);
popup_pos[1] = parseInt(popup.style.left);
if (event.target.id == "popup_drag")
popup_dragable = true;
else
popup_dragable = false;
return true;
}
if (event.which == 3)
return true;
EVENTS.get_mouse_position(event);
mouse_click_pos[0] = EVENTS.mouse.x;
mouse_click_pos[1] = EVENTS.mouse.y;
if (EVENTS.mouse.valid == false)
mouse_click_valid = false;
else
mouse_click_valid = true;
//check tools functions
for (var i in DRAW) {
if (i == DRAW.active_tool) {
DRAW[i]('click', EVENTS.mouse, event);
break;
}
}
if (event.target.id == "canvas_preview")
EVENTS.calc_preview_by_mouse(EVENTS.mouse.x, EVENTS.mouse.y);
//main window resize
resize_all = false;
if (GUI.ZOOM == 100) {
if (event.target.id == "resize-w")
resize_all = "w";
else if (event.target.id == "resize-h")
resize_all = "h";
else if (event.target.id == "resize-wh")
resize_all = "wh";
}
};
//mouse move
this.mouse_move = function (event) {
if (POP != undefined && POP.active == true) {
//drag popup
if (EVENTS.isDrag == true && popup_dragable == true) {
EVENTS.get_mouse_position(event);
popup = document.getElementById('popup');
popup.style.top = (popup_pos[0] + EVENTS.mouse.abs_y - last_pop_click[1]) + 'px';
popup.style.left = (popup_pos[1] + EVENTS.mouse.abs_x - last_pop_click[0]) + 'px';
}
return true;
}
EVENTS.get_mouse_position(event);
if (event.target.id == "canvas_preview" && EVENTS.isDrag == true)
EVENTS.calc_preview_by_mouse(EVENTS.mouse.x, EVENTS.mouse.y);
LAYER.update_info_block();
//main window resize
if (GUI.ZOOM == 100) {
if (event.target.id == "resize-w")
document.body.style.cursor = "w-resize";
else if (event.target.id == "resize-h")
document.body.style.cursor = "n-resize";
else if (event.target.id == "resize-wh")
document.body.style.cursor = "nw-resize";
else
document.body.style.cursor = "auto";
if (resize_all != false && EVENTS.isDrag == true) {
document.body.style.cursor = "auto";
if (resize_all == "w") {
new_w = EVENTS.mouse.x;
new_h = HEIGHT;
}
else if (resize_all == "h") {
new_w = WIDTH;
new_h = EVENTS.mouse.y;
}
else if (resize_all == "wh") {
new_w = EVENTS.mouse.x;
new_h = EVENTS.mouse.y;
}
canvas_front.clearRect(0, 0, WIDTH, HEIGHT);
canvas_front.lineWidth = 1;
canvas_front.fillStyle = "#ff0000";
EL.rectangle_dashed(canvas_front, 0, 0, new_w - 1, new_h - 1);
event.preventDefault();
HELPER.remove_selection();
return false;
}
}
//check tools functions
if (EVENTS.isDrag === false) {
for (i in DRAW) {
if (i == DRAW.active_tool) {
DRAW[i]('move', EVENTS.mouse, event);
break;
}
}
}
if (EVENTS.isDrag === false)
return false; //only drag now
//check tools functions
for (var i in DRAW) {
if (i == DRAW.active_tool) {
DRAW[i]('drag', EVENTS.mouse, event);
break;
}
}
if (DRAW.active_tool != 'select_square')
DRAW.select_square_action = '';
mouse_move_last[0] = EVENTS.mouse.x;
mouse_move_last[1] = EVENTS.mouse.y;
};
//release mouse click
this.mouse_release = function (event) {
EVENTS.isDrag = false;
if (POP != undefined && POP.active == true)
return true;
var mouse = EVENTS.get_mouse_position(event);
mouse_move_last[0] = false;
mouse_move_last[1] = false;
if (DRAW.select_square_action == '' && EVENTS.mouse.valid == true)
DRAW.select_data = false;
//check tools functions
if (EVENTS.clear_front_on_release == true)
canvas_front.clearRect(0, 0, WIDTH, HEIGHT);
GUI.draw_selected_area();
for (var i in DRAW) {
if (i == DRAW.active_tool) {
DRAW[i]('release', EVENTS.mouse, event);
break;
}
}
//main window resize
if (resize_all != false && GUI.ZOOM == 100 && EVENTS.mouse.x > 0 && EVENTS.mouse.y > 0) {
EVENTS.autosize = false;
document.body.style.cursor = "auto";
if (resize_all == "w")
WIDTH = EVENTS.mouse.x;
else if (resize_all == "h")
HEIGHT = EVENTS.mouse.y;
else if (resize_all == "wh") {
WIDTH = mouse_x;
HEIGHT = EVENTS.mouse.y;
}
LAYER.set_canvas_size();
GUI.zoom();
}
resize_all = false;
GUI.zoom();
};
//upload drop zone
this.upload_drop = function (e) {
e.preventDefault();
EDIT.save_state();
var n_valid = 0;
for (var i = 0, f; i < e.dataTransfer.files.length; i++) {
f = e.dataTransfer.files[i];
if (!f.type.match('image.*') && f.type != 'text/xml')
continue;
n_valid++;
var FR = new FileReader();
FR.file = e.dataTransfer.files[i];
if (e.dataTransfer.files.length == 1)
FILE.SAVE_NAME = f.name.split('.')[f.name.split('.').length - 2];
FR.onload = function (event) {
if (this.file.type != 'text/xml') {
//image
LAYER.layer_add(this.file.name, event.target.result, this.file.type);
EXIF.getData(this.file, FILE.save_EXIF);
}
else {
//xml
var responce = MAIN.load_xml(event.target.result);
if (responce === true)
return false;
}
};
if (f.type == "text/plain")
FR.readAsText(f);
else if (f.type == "text/xml")
FR.readAsText(f);
else
FR.readAsDataURL(f);
}
};
this.mouse_wheel_handler = function (e) { //return true;
var step = 100;
e.preventDefault();
//zoom
if (EVENTS.ctrl_pressed == true) {
var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));
if (GUI.ZOOM <= 100 && delta < 0)
step = 10;
if (GUI.ZOOM < 100 && delta > 0)
step = 10;
delta = delta * step;
if (GUI.ZOOM + delta > 0) {
GUI.ZOOM = GUI.ZOOM + delta;
EVENTS.calc_preview_auto();
GUI.zoom();
}
if (GUI.action_data().name == 'zoom') {
GUI.action_data().attributes.zoom = GUI.ZOOM;
show_action_attributes();
}
EVENTS.scroll_window();
//disable page scroll if ctrl pressed
e.preventDefault();
return false;
}
};
this.scroll_window = function () {
var total_w = (WIDTH * GUI.ZOOM / 100);
var total_h = (HEIGHT * GUI.ZOOM / 100);
xx = total_w * EVENTS.ZOOM_POS[0] / (GUI.PREVIEW_SIZE.w);
yy = total_h * EVENTS.ZOOM_POS[1] / (GUI.PREVIEW_SIZE.h);
var canvas_wrapper = document.querySelector('#canvas_wrapper');
canvas_wrapper.scrollTop = yy;
canvas_wrapper.scrollLeft = xx;
};
this.calc_preview_by_mouse = function (mouse_x, mouse_y) {
EVENTS.ZOOM_POS[0] = mouse_x - EVENTS.mini_rect_data.w / 2;
EVENTS.ZOOM_POS[1] = mouse_y - EVENTS.mini_rect_data.h / 2;
if (EVENTS.ZOOM_POS[0] < 0)
EVENTS.ZOOM_POS[1] = 0;
if (EVENTS.ZOOM_Y < 0)
EVENTS.ZOOM_Y = 0;
GUI.zoom(undefined, true);
return true;
};
this.calc_preview_auto = function () {
var canvas_wrapper = document.querySelector('#canvas_wrapper');
var page_w = canvas_wrapper.clientWidth;
var page_h = canvas_wrapper.clientHeight;
var total_w = (WIDTH * GUI.ZOOM / 100);
var total_h = (HEIGHT * GUI.ZOOM / 100);
EVENTS.mini_rect_data.w = Math.round(page_w * GUI.PREVIEW_SIZE.w / total_w);
EVENTS.mini_rect_data.h = Math.round(page_h * GUI.PREVIEW_SIZE.h / total_h);
GUI.redraw_preview();
};
this.on_resize = function(){
EVENTS.calc_preview_auto();
//recalc popup position
var dim = HELPER.get_dimensions();
popup = document.getElementById('popup');
popup.style.top = 150 + 'px';
popup.style.left = Math.round(dim[0] / 2) + 'px';
};
}
function call_menu(class_name, function_name) {
$('#main_menu').find('.selected').click(); //close menu
GUI.last_menu = function_name;
//exec
class_name[function_name]();
GUI.zoom();
}
//=== Clipboard ================================================================
var CLIPBOARD = new CLIPBOARD_CLASS('', false);
/**
* image pasting into canvas
*
* @param {string} canvas_id - canvas id
* @param {boolean} autoresize - if canvas will be resized
*/
function CLIPBOARD_CLASS(canvas_id, autoresize) {
var _self = this;
if (canvas_id != ''){
var canvas = document.getElementById(canvas_id);
var ctx = document.getElementById(canvas_id).getContext("2d");
}
var ctrl_pressed = false;
var reading_dom = false;
var text_top = 15;
var pasteCatcher;
var paste_mode;
//handlers
document.addEventListener('keydown', function (e) {
_self.on_keyboard_action(e);
}, false); //firefox fix
document.addEventListener('keyup', function (e) {
_self.on_keyboardup_action(e);
}, false); //firefox fix
document.addEventListener('paste', function (e) {
_self.paste_auto(e);
}, false); //official paste handler
//constructor - prepare
this.init = function () {
//if using auto
if (window.Clipboard)
return true;
pasteCatcher = document.createElement("div");
pasteCatcher.setAttribute("id", "paste_ff");
pasteCatcher.setAttribute("contenteditable", "");
pasteCatcher.style.cssText = 'opacity:0;position:fixed;top:0px;left:0px;';
pasteCatcher.style.marginLeft = "-20px";
pasteCatcher.style.width = "10px";
document.body.appendChild(pasteCatcher);
// create an observer instance
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
if (paste_mode == 'auto' || ctrl_pressed == false || mutation.type != 'childList')
return true;
//if paste handle failed - capture pasted object manually
if(mutation.addedNodes.length == 1) {
if (mutation.addedNodes[0].src != undefined) {
//image
_self.paste_createImage(mutation.addedNodes[0].src);
}
//register cleanup after some time.
setTimeout(function () {
pasteCatcher.innerHTML = '';
}, 20);
}
});
});
var target = document.getElementById('paste_ff');
var config = { attributes: true, childList: true, characterData: true };
observer.observe(target, config);
}();
//default paste action
this.paste_auto = function (e) {
paste_mode = '';
pasteCatcher.innerHTML = '';
var plain_text_used = false;
if (e.clipboardData) {
var items = e.clipboardData.items;
if (items) {
paste_mode = 'auto';
//access data directly
for (var i = 0; i < items.length; i++) {
if (items[i].type.indexOf("image") !== -1) {
//image
var blob = items[i].getAsFile();
var URLObj = window.URL || window.webkitURL;
var source = URLObj.createObjectURL(blob);
this.paste_createImage(source);
}
}
e.preventDefault();
}
else {
//wait for DOMSubtreeModified event
//https://bugzilla.mozilla.org/show_bug.cgi?id=891247
}
}
};
//on keyboard press
this.on_keyboard_action = function (event) {
if (POP.active == true)
return true;
k = event.keyCode;
//ctrl
if (k == 17 || event.metaKey || event.ctrlKey) {
if (ctrl_pressed == false)
ctrl_pressed = true;
}
//v
if (k == 86) {
if (document.activeElement != undefined && document.activeElement.type == 'text') {
//let user paste into some input
return false;
}
if (ctrl_pressed == true && !window.Clipboard)
pasteCatcher.focus();
}
};
//on kaybord release
this.on_keyboardup_action = function (event) {
k = event.keyCode;
//ctrl
if (k == 17 || event.metaKey || event.ctrlKey || event.key == 'Meta')
ctrl_pressed = false;
};
//draw image
this.paste_createImage = function (source) {
var pastedImage = new Image();
pastedImage.onload = function () {
if(canvas_id != ''){
if(autoresize == true){
//resize
canvas.width = pastedImage.width;
canvas.height = pastedImage.height;
}
else{
//clear canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
}
LAYER.layer_add('Paste', source);
};
pastedImage.src = source;
};
}

378
js/file.js Normal file
View File

@ -0,0 +1,378 @@
/* global MAIN, POP, LAYER, EXIF, HELPER, IMAGE, GUI */
/* global SAVE_TYPES */
var FILE = new FILE_CLASS();
/**
* manages files actions
*
* @author ViliusL
*/
function FILE_CLASS() {
/**
* exif data
*/
this.EXIF = false;
/**
* default name used for saving file
*/
this.SAVE_NAME = 'example'; //default save name
/**
* save types config
*/
this.SAVE_TYPES = [
"PNG - Portable Network Graphics", //default
"JPG - JPG/JPEG Format", //autodetect on photos where png useless?
"XML - Full layers data", //aka PSD
"BMP - Windows Bitmap", //firefox only, useless?
"WEBP - Weppy File Format", //chrome only
];
//new
this.file_new = function () {
POP.add({name: "width", title: "Width:", value: WIDTH});
POP.add({name: "height", title: "Height:", value: HEIGHT});
POP.add({name: "transparency", title: "Transparent:", values: ['Yes', 'No']});
POP.show(
'New file...',
function (response) {
var width = parseInt(response.width);
var height = parseInt(response.height);
if (response.transparency == 'Yes')
GUI.TRANSPARENCY = true;
else
GUI.TRANSPARENCY = false;
GUI.ZOOM = 100;
WIDTH = width;
HEIGHT = height;
MAIN.init();
}
);
};
//open
this.file_open = function () {
this.open();
};
//save
this.file_save = function () {
this.save_dialog();
};
//print
this.file_print = function () {
window.print();
};
this.open = function () {
document.getElementById("tmp").innerHTML = '';
var a = document.createElement('input');
a.setAttribute("id", "file_open");
a.type = 'file';
a.multiple = 'multiple ';
document.getElementById("tmp").appendChild(a);
document.getElementById('file_open').addEventListener('change', this.open_handler, false);
//force click
document.querySelector('#file_open').click();
};
this.open_handler = function (e) {
var files = e.target.files;
for (var i = 0, f; i < files.length; i++) {
f = files[i];
if (!f.type.match('image.*') && f.type != 'text/xml')
continue;
if (files.length == 1)
this.SAVE_NAME = f.name.split('.')[f.name.split('.').length - 2];
var FR = new FileReader();
FR.file = e.target.files[i];
FR.onload = function (event) {
if (this.file.type != 'text/xml') {
//image
LAYER.layer_add(this.file.name, event.target.result, this.file.type);
EXIF.getData(this.file, this.save_EXIF);
}
else {
//xml
var responce = MAIN.load_xml(event.target.result);
if (responce === true)
return false;
}
};
if (f.type == "text/plain")
FR.readAsText(f);
else if (f.type == "text/xml")
FR.readAsText(f);
else
FR.readAsDataURL(f);
}
};
this.save_dialog = function (e) {
//find default format
var save_default = this.SAVE_TYPES[0]; //png
if (HELPER.getCookie('save_default') == 'jpg')
save_default = this.SAVE_TYPES[1]; //jpg
POP.add({name: "name", title: "File name:", value: this.SAVE_NAME});
POP.add({name: "type", title: "Save as type:", values: this.SAVE_TYPES, value: save_default});
POP.add({name: "quality", title: "Quality (1-100):", value: 90, range: [1, 100]});
POP.add({name: "layers", title: "Save layers:", values: ['All', 'Selected']});
POP.add({name: "trim", title: "Trim:", values: ['No', 'Yes']});
POP.show('Save as ...', [FILE, 'save']);
document.getElementById("pop_data_name").select();
if (e != undefined)
e.preventDefault();
};
this.save = function (user_response) {
fname = user_response.name;
var tempCanvas = document.createElement("canvas");
var tempCtx = tempCanvas.getContext("2d");
tempCanvas.width = WIDTH;
tempCanvas.height = HEIGHT;
//save choosen type
var save_default = this.SAVE_TYPES[0]; //png
if (HELPER.getCookie('save_default') == 'jpg')
save_default = this.SAVE_TYPES[1]; //jpg
if (user_response.type != save_default && user_response.type == this.SAVE_TYPES[0])
HELPER.setCookie('save_default', 'png', 30);
else if (user_response.type != save_default && user_response.type == this.SAVE_TYPES[1])
HELPER.setCookie('save_default', 'jpg', 30);
if (GUI.TRANSPARENCY == false) {
tempCtx.beginPath();
tempCtx.rect(0, 0, WIDTH, HEIGHT);
tempCtx.fillStyle = "#ffffff";
tempCtx.fill();
}
//take data
for (var i in LAYER.layers) {
if (LAYER.layers[i].visible == false)
continue;
if (user_response.layers == 'Selected' && user_response.type != 'XML' && i != LAYER.layer_active)
continue;
tempCtx.drawImage(document.getElementById(LAYER.layers[i].name), 0, 0, WIDTH, HEIGHT);
}
if (user_response.trim == 'Yes' && user_response.type != 'XML') {
//trim
var trim_info = IMAGE.trim_info(tempCanvas);
tmp_data = tempCtx.getImageData(0, 0, WIDTH, HEIGHT);
tempCtx.clearRect(0, 0, WIDTH, HEIGHT);
tempCanvas.width = WIDTH - trim_info.right - trim_info.left;
tempCanvas.height = HEIGHT - trim_info.bottom - trim_info.top;
tempCtx.putImageData(tmp_data, -trim_info.left, -trim_info.top);
}
//detect type
var parts = user_response.type.split(" ");
user_response.type = parts[0];
//auto detect?
if (HELPER.strpos(fname, '.png') !== false)
user_response.type = 'PNG';
else if (HELPER.strpos(fname, '.jpg') !== false)
user_response.type = 'JPG';
else if (HELPER.strpos(fname, '.xml') !== false)
user_response.type = 'XML';
else if (HELPER.strpos(fname, '.bmp') !== false)
user_response.type = 'BMP';
else if (HELPER.strpos(fname, '.webp') !== false)
user_response.type = 'WEBP';
//prepare data
if (user_response.type == 'PNG') {
//png - default format
var data = tempCanvas.toDataURL("image/png");
var data_header = "image/png";
if (HELPER.strpos(fname, '.png') == false)
fname = fname + ".png";
}
else if (user_response.type == 'JPG') {
//jpg
var quality = parseInt(user_response.quality);
if (quality > 100 || quality < 1 || isNaN(quality) == true)
quality = 90;
quality = quality / 100;
var data = tempCanvas.toDataURL('image/jpeg', quality);
var data_header = "image/jpeg";
if (HELPER.strpos(fname, '.jpg') == false)
fname = fname + ".jpg";
}
else if (user_response.type == 'BMP') {
//bmp - lets hope user really needs this - chrome do not support it
var data = tempCanvas.toDataURL("image/bmp");
var data_header = "image/bmp";
if (HELPER.strpos(fname, '.bmp') == false)
fname = fname + ".bmp";
}
else if (user_response.type == 'WEBP') {
//WEBP - new format for chrome only
if (HELPER.strpos(fname, '.webp') == false)
fname = fname + ".webp";
var data_header = "image/webp";
var data = tempCanvas.toDataURL("image/webp");
}
else if (user_response.type == 'XML') {
//xml - full data with layers
if (HELPER.strpos(fname, '.xml') == false)
fname = fname + ".xml";
var data_header = "text/plain";
var XML = '';
//basic info
XML += "<xml>\n";
XML += " <info>\n";
XML += " <width>" + WIDTH + "</width>\n";
XML += " <height>" + HEIGHT + "</height>\n";
XML += " </info>\n";
//add layers info
XML += " <layers>\n";
for (var i in LAYER.layers) {
XML += " <layer>\n";
XML += " <name>" + LAYER.layers[i].name + "</name>\n";
if (LAYER.layers[i].visible == true)
XML += " <visible>1</visible>\n";
else
XML += " <visible>0</visible>\n";
XML += " <opacity>" + LAYER.layers[i].opacity + "</opacity>\n";
XML += " </layer>\n";
}
XML += " </layers>\n";
//add data ???
XML += " <image_data>\n";
for (var i in LAYER.layers) {
var data_tmp = document.getElementById(LAYER.layers[i].name).toDataURL("image/png");
XML += " <data>\n";
XML += " <name>" + LAYER.layers[i].name + "</name>\n";
XML += " <data>" + data_tmp + "</data>\n";
XML += " </data>\n";
}
XML += " </image_data>\n";
XML += "</xml>\n";
var bb = new Blob([XML], {type: data_header});
var data = window.URL.createObjectURL(bb);
}
else
return false;
//check support
var actualType = data.replace(/^data:([^;]*).*/, '$1');
if (data_header != actualType && data_header != "text/plain") {
//error - no support
POP.add({title: "Error:", value: "Your browser do not support " + user_response.type});
POP.show('Sorry', '');
return false;
}
//push data to user
window.URL = window.webkitURL || window.URL;
var a = document.createElement('a');
if (typeof a.download != "undefined") {
//a.download is supported
a.setAttribute("id", "save_data");
a.download = fname;
a.href = data;
a.textContent = 'Downloading...';
document.getElementById("tmp").appendChild(a);
//release memory
a.onclick = function (e) {
this.save_cleanup(this);
};
//force click
document.querySelector('#save_data').click();
}
else {
//poor browser or poor user - not sure here. No support
if (user_response.type == 'PNG')
window.open(data);
else if (user_response.type == 'JPG')
window.open(data, quality);
}
};
this.save_cleanup = function (a) {
a.textContent = 'Downloaded';
setTimeout(function () {
a.href = '';
var element = document.getElementById("save_data");
element.parentNode.removeChild(element);
}, 1500);
};
this.save_EXIF = function () {
this.EXIF = this.exifdata;
//check length
var n = 0;
for (var i in this.EXIF){
n++;
}
if (n == 0)
this.EXIF = false;
};
this.load_xml = function (data) {
var xml = $.parseXML(data);
w = $(xml).find("width").text();
h = $(xml).find("height").text();
//delete old layers
for (var i in LAYER.layers)
LAYER.layer_remove(i);
//init new file
GUI.ZOOM = 100;
MAIN.init();
//set attributes
WIDTH = w;
HEIGHT = h;
LAYER.set_canvas_size();
//add layers
$('layer', xml).each(function (i) {
var name = $(this).find("name").text();
var visible = $(this).find("visible").text();
var opacity = $(this).find("opacity").text();
if (i > 0) { //first layer exists by default - Background
LAYER.layer_add(name);
//update attributes
LAYER.layers[LAYER.layer_active].name = name;
if (visible == 0)
LAYER.layer_visibility(LAYER.layer_active);
LAYER.layers[LAYER.layer_active].opacity = opacity;
}
});
LAYER.layer_renew();
//add data
$('data', xml).each(function (i) {
var name = $(this).find("name").text();
var data = $(this).find("data").text();
var img = new Image();
img.src = data;
img.onload = function () {
document.getElementById(name).getContext('2d').drawImage(img, 0, 0);
LAYER.layer_renew();
GUI.zoom();
};
});
};
}

607
js/gui.js Normal file
View File

@ -0,0 +1,607 @@
/* global EVENTS, HELPER, POP, DRAW, LAYER, EL */
/* global WIDTH, HEIGHT, canvas_front, DRAW_TOOLS_CONFIG, canvas_grid, canvas_preview */
var GUI = new GUI_CLASS();
/**
* manages grapchic interface functionality: left/right sidebar actions
*
* @author ViliusL
*/
function GUI_CLASS() {
/**
* preview mini window size on right sidebar
*/
this.PREVIEW_SIZE = {w: 148, h: 100};
/**
* last used menu id
*/
this.last_menu = '';
/**
* grid dimnesions config
*/
this.grid_size = [50, 50];
/**
* if grid is visible
*/
this.grid = false;
/**
* true if using transparecy, false if using white background
*/
this.TRANSPARENCY = true;
/**
* zoom level, original - 100%, can vary from 10% to 1000%
*/
this.ZOOM = 100;
/**
* last color copy
*/
var COLOR_copy;
this.draw_helpers = function () {
//left menu
var html = '';
for (var i in DRAW_TOOLS_CONFIG) {
html += '<a title="' + DRAW_TOOLS_CONFIG[i].title + '"';
html += ' style="background: #989898 url(\'img/' + DRAW_TOOLS_CONFIG[i].icon[0] + '\') no-repeat ' + DRAW_TOOLS_CONFIG[i].icon[1] + 'px ' + DRAW_TOOLS_CONFIG[i].icon[2] + 'px;"';
if (DRAW_TOOLS_CONFIG[i].name == DRAW.active_tool)
html += ' class="active"';
html += ' onclick="return GUI.action(\'' + DRAW_TOOLS_CONFIG[i].name + '\');"';
html += ' id="' + DRAW_TOOLS_CONFIG[i].name + '"';
html += ' href="#"></a>' + "\n";
}
document.getElementById("menu_left_container").innerHTML = html;
//draw colors
var html = '';
var colors_data = [
['#ff0000', '#ff5b31', '#ffa500', '#ff007f', '#ff00ff'], //red
['#00ff00', '#008000', '#7fff00', '#00ff7f', '#8ac273'], //green
['#0000ff', '#007fff', '#37629c', '#000080', '#8000ff'], //blue
['#ffff00', '#ffff80', '#ddd06a', '#808000', '#bcb88a'], //yellow
['#ffffff', '#c0c0c0', '#808080', '#404040', '#000000'] //grey
];
for (var i in colors_data) {
for (var j in colors_data[i]) {
html += '<div style="background-color:' + colors_data[i][j] + ';" class="mini-color" onclick="GUI.set_color(this);"></div>' + "\n";
}
html += '<div style="clear:both;"></div>' + "\n";
}
document.getElementById("all_colors").innerHTML = html;
};
this.draw_background = function (canvas, W, H, gap, force) {
if (this.TRANSPARENCY == false && force == undefined) {
canvas.beginPath();
canvas.rect(0, 0, W, H);
canvas.fillStyle = "#ffffff";
canvas.fill();
return false;
}
if (gap == undefined)
gap = 10;
var fill = true;
for (var i = 0; i < W; i = i + gap) {
if (i % (gap * 2) == 0)
fill = true;
else
fill = false;
for (var j = 0; j < H; j = j + gap) {
if (fill == true) {
canvas.fillStyle = '#eeeeee';
canvas.fillRect(i, j, gap, gap);
fill = false;
}
else
fill = true;
}
}
};
this.draw_grid = function (gap_x, gap_y) {
if (this.grid == false) {
document.getElementById("canvas_grid").style.display = 'none';
return false;
}
else {
document.getElementById("canvas_grid").style.display = '';
canvas_grid.clearRect(0, 0, WIDTH, HEIGHT);
}
//size
if (gap_x != undefined && gap_y != undefined)
this.grid_size = [gap_x, gap_y];
else {
gap_x = this.grid_size[0];
gap_y = this.grid_size[1];
}
gap_x = parseInt(gap_x);
gap_y = parseInt(gap_y);
if (gap_x < 2)
gap_x = 2;
if (gap_y < 2)
gap_y = 2;
for (var i = gap_x; i < WIDTH; i = i + gap_x) {
if (gap_x == 0)
break;
if (i % (gap_x * 5) == 0) //main lines
canvas_grid.strokeStyle = '#222222';
else {
EL.line_dashed(canvas_grid, i, 0, i, HEIGHT, 3, '#888888');
continue;
}
canvas_grid.beginPath();
canvas_grid.moveTo(0.5 + i, 0);
canvas_grid.lineTo(0.5 + i, HEIGHT);
canvas_grid.stroke();
}
for (var i = gap_y; i < HEIGHT; i = i + gap_y) {
if (gap_y == 0)
break;
if (i % (gap_y * 5) == 0) //main lines
canvas_grid.strokeStyle = '#222222';
else {
EL.line_dashed(canvas_grid, 0, i, WIDTH, i, 3, '#888888');
continue;
}
canvas_grid.beginPath();
canvas_grid.moveTo(0, 0.5 + i);
canvas_grid.lineTo(WIDTH, 0.5 + i);
canvas_grid.stroke();
}
};
this.redraw_preview = function () {
canvas_preview.beginPath();
canvas_preview.rect(0, 0, GUI.PREVIEW_SIZE.w, GUI.PREVIEW_SIZE.h);
canvas_preview.fillStyle = "#ffffff";
canvas_preview.fill();
this.draw_background(canvas_preview, GUI.PREVIEW_SIZE.w, GUI.PREVIEW_SIZE.h, 5);
//redraw preview area
canvas_preview.save();
canvas_preview.scale(GUI.PREVIEW_SIZE.w / WIDTH, GUI.PREVIEW_SIZE.h / HEIGHT);
for (var i in LAYER.layers) {
if (LAYER.layers[i].visible == false)
continue;
canvas_preview.drawImage(document.getElementById(LAYER.layers[i].name), 0, 0, WIDTH, HEIGHT);
}
canvas_preview.restore();
//active zone
z_x = EVENTS.ZOOM_POS[0];
z_y = EVENTS.ZOOM_POS[1];
if (z_x > GUI.PREVIEW_SIZE.w - EVENTS.mini_rect_data.w - 1)
z_x = GUI.PREVIEW_SIZE.w - EVENTS.mini_rect_data.w - 1;
if (z_y > GUI.PREVIEW_SIZE.h - EVENTS.mini_rect_data.h - 1)
z_y = GUI.PREVIEW_SIZE.h - EVENTS.mini_rect_data.h - 1;
canvas_preview.lineWidth = 1;
canvas_preview.beginPath();
canvas_preview.rect(Math.round(z_x) + 0.5, Math.round(z_y) + 0.5, EVENTS.mini_rect_data.w, EVENTS.mini_rect_data.h);
canvas_preview.fillStyle = "rgba(0, 0, 0, 0.2)";
canvas_preview.strokeStyle = "#393939";
canvas_preview.fill();
canvas_preview.stroke();
return true;
};
this.zoom = function (recalc, scroll) {
if (recalc != undefined) {
//zoom-in or zoom-out
if (recalc == 1 || recalc == -1) {
var step = 100;
if (this.ZOOM <= 100 && recalc < 0)
step = 10;
if (this.ZOOM < 100 && recalc > 0)
step = 10;
if (recalc * step + this.ZOOM > 0) {
this.ZOOM = this.ZOOM + recalc * step;
if (this.ZOOM > 100 && this.ZOOM < 200)
this.ZOOM = 100;
}
}
//zoom using exact value
else
this.ZOOM = parseInt(recalc);
EVENTS.calc_preview_auto();
}
document.getElementById("zoom_nr").innerHTML = this.ZOOM;
document.getElementById("zoom_range").value = this.ZOOM;
//change scale and repaint
document.getElementById('canvas_back').style.width = Math.round(WIDTH * this.ZOOM / 100) + "px";
document.getElementById('canvas_back').style.height = Math.round(HEIGHT * this.ZOOM / 100) + "px";
for (var i in LAYER.layers) {
document.getElementById(LAYER.layers[i].name).style.width = Math.round(WIDTH * this.ZOOM / 100) + "px";
document.getElementById(LAYER.layers[i].name).style.height = Math.round(HEIGHT * this.ZOOM / 100) + "px";
}
document.getElementById('canvas_front').style.width = Math.round(WIDTH * this.ZOOM / 100) + "px";
document.getElementById('canvas_front').style.height = Math.round(HEIGHT * this.ZOOM / 100) + "px";
document.getElementById('canvas_grid').style.width = Math.round(WIDTH * this.ZOOM / 100) + "px";
document.getElementById('canvas_grid').style.height = Math.round(HEIGHT * this.ZOOM / 100) + "px";
//check main resize corners
if (this.ZOOM != 100) {
document.getElementById('resize-w').style.display = "none";
document.getElementById('resize-h').style.display = "none";
document.getElementById('resize-wh').style.display = "none";
}
else {
document.getElementById('resize-w').style.display = "block";
document.getElementById('resize-h').style.display = "block";
document.getElementById('resize-wh').style.display = "block";
}
if (scroll != undefined)
EVENTS.scroll_window();
this.redraw_preview();
return true;
};
this.update_attribute = function (object, next_value) {
var max_value = 500;
for (var k in this.action_data().attributes) {
if (k != object.id)
continue;
if (this.action_data().attributes[k] === true || this.action_data().attributes[k] === false) {
//true / false
var value;
if (next_value == 0)
value = true;
else
value = false;
//save
this.action_data().attributes[k] = value;
this.show_action_attributes();
}
else if (typeof this.action_data().attributes[k] == 'object') {
//select
var key = k.replace("_values", "");
this.action_data().attributes[key] = object.value;
}
else if (this.action_data().attributes[k][0] == '#') {
//color
var key = k.replace("_values", "");
this.action_data().attributes[key] = object.value;
}
else {
//numbers
if (next_value != undefined) {
if (next_value > 0) {
if (parseInt(this.action_data().attributes[k]) == 0)
object.value = 1;
else if (parseInt(this.action_data().attributes[k]) == 1)
object.value = 5;
else if (parseInt(this.action_data().attributes[k]) == 5)
object.value = 10;
else
object.value = parseInt(this.action_data().attributes[k]) + next_value;
}
else if (next_value < 0) {
if (parseInt(this.action_data().attributes[k]) == 1)
object.value = 0;
else if (parseInt(this.action_data().attributes[k]) <= 5)
object.value = 1;
else if (parseInt(this.action_data().attributes[k]) <= 10)
object.value = 5;
else if (parseInt(this.action_data().attributes[k]) <= 20)
object.value = 10;
else
object.value = parseInt(this.action_data().attributes[k]) + next_value;
}
if (object.value < 0)
object.value = 0;
if (object.value > max_value)
object.value = max_value;
}
else {
if (object.value.length == 0)
return false;
object.value = parseInt(object.value);
object.value = Math.abs(object.value);
if (object.value == 0 || isNaN(object.value) || value > max_value)
object.value = this.action_data().attributes[k];
}
if (k == 'power' && object.value > 100)
object.value = 100;
//save
this.action_data().attributes[k] = object.value;
document.getElementById(k).value = object.value;
}
if (this.action_data().on_update != undefined)
DRAW[this.action_data().on_update](object.value);
}
};
this.action = function (key) {
DRAW[key]('init', {valid: true});
if (DRAW.active_tool == key)
return false;
//change
if (DRAW.active_tool != '')
document.getElementById(DRAW.active_tool).className = "";
DRAW.active_tool = key;
document.getElementById(key).className = "active";
this.show_action_attributes();
return false;
};
this.action_data = function () {
for (var i in DRAW_TOOLS_CONFIG) {
if (DRAW_TOOLS_CONFIG[i].name == DRAW.active_tool)
return DRAW_TOOLS_CONFIG[i];
}
};
this.show_action_attributes = function () {
html = '';
var step = 10;
for (var k in this.action_data().attributes) {
var title = k[0].toUpperCase() + k.slice(1);
title = title.replace("_", " ");
if (this.action_data().attributes[k + "_values"] != undefined)
continue;
if (this.action_data().attributes[k] === true || this.action_data().attributes[k] === false) {
//true / false
if (this.action_data().attributes[k] == true)
html += '<div onclick="GUI.update_attribute(this, 1)" style="background-color:#5680c1;" class="attribute-area" id="' + k + '">' + title + '</div>';
else
html += '<div onclick="GUI.update_attribute(this, 0)" class="attribute-area" id="' + k + '">' + title + '</div>';
}
else if (typeof GUI.action_data().attributes[k] == 'object') {
//drop down select
html += '<select style="font-size:11px;margin-bottom:10px;" onchange="GUI.update_attribute(this);" id="' + k + '">';
for (var j in GUI.action_data().attributes[k]) {
var sel = '';
var key = k.replace("_values", "");
if (GUI.action_data().attributes[key] == GUI.action_data().attributes[k][j])
sel = 'selected="selected"';
html += '<option ' + sel + ' name="' + GUI.action_data().attributes[k][j] + '">' + GUI.action_data().attributes[k][j] + '</option>';
}
html += '</select>';
}
else if (GUI.action_data().attributes[k][0] == '#') {
//color
html += '<table style="width:100%;">'; //table for 100% width
html += '<tr>';
html += '<td style="font-weight:bold;width:45px;">' + title + ':</td>';
html += '<td><input onchange="GUI.update_attribute(this);" type="color" id="' + k + '" value="' + GUI.action_data().attributes[k] + '" /></td>';
html += '</tr>';
html += '</table>';
}
else {
//numbers
html += '<div id="' + k + '_container">';
html += '<table style="width:100%;">'; //table for 100% width
html += '<tr>';
html += '<td style="font-weight:bold;padding-right:2px;white-space:nowrap;">' + title + ':</td>';
html += '<td><input onKeyUp="GUI.update_attribute(this);" type="text" id="' + k + '" value="' + GUI.action_data().attributes[k] + '" /></td>';
html += '</tr>';
html += '</table>';
html += '<div style="float:left;width:32px;" onclick="GUI.update_attribute(this, ' + (step) + ')" class="attribute-area" id="' + k + '">+</div>';
html += '<div style="margin-left:48px;margin-bottom:15px;" onclick="GUI.update_attribute(this, ' + (-step) + ')" class="attribute-area" id="' + k + '">-</div>';
html += '</div>';
}
}
document.getElementById("action_attributes").innerHTML = html;
};
this.set_color = function (object) {
if (HELPER.chech_input_color_support('main_colour') == true && object.id == 'main_colour')
COLOR = object.value;
else
COLOR = HELPER.rgb2hex_all(object.style.backgroundColor);
COLOR_copy = COLOR;
if (HELPER.chech_input_color_support('main_colour') == true)
document.getElementById("main_colour").value = COLOR; //supported
else
document.getElementById("main_colour_alt").style.backgroundColor = COLOR; //not supported
document.getElementById("color_hex").value = COLOR;
var colours = HELPER.hex2rgb(COLOR);
document.getElementById("rgb_r").value = colours.r;
document.getElementById("rgb_g").value = colours.g;
document.getElementById("rgb_b").value = colours.b;
};
this.set_color_manual = function (event) {
var object = event.target;
if (object.value.length == 6 && object.value[0] != '#') {
COLOR = '#' + object.value;
this.sync_colors();
}
if (object.value.length == 7) {
COLOR = object.value;
this.sync_colors();
}
else if (object.value.length > 7)
object.value = COLOR;
};
this.set_color_rgb = function (object, c) {
var colours = HELPER.hex2rgb(COLOR);
if (object.value.length > 3) {
object.value = colours[c];
}
else if (object.value.length > 0) {
value = object.value;
value = parseInt(value);
if (isNaN(value) || value != object.value || value > 255 || value < 0) {
object.value = colours[c];
return false;
}
COLOR = "#" + ("000000" + HELPER.rgbToHex(document.getElementById("rgb_r").value, document.getElementById("rgb_g").value, document.getElementById("rgb_b").value)).slice(-6);
ALPHA = document.getElementById("rgb_a").value;
document.getElementById("rgb_a").value = ALPHA;
this.sync_colors();
}
};
this.sync_colors = function () {
document.getElementById("color_hex").value = COLOR;
if (HELPER.chech_input_color_support('main_colour') == true)
document.getElementById("main_colour").value = COLOR; //supported
else
document.getElementById("main_colour_alt").style.backgroundColor = COLOR; //not supported
var colours = HELPER.hex2rgb(COLOR);
document.getElementById("rgb_r").value = colours.r;
document.getElementById("rgb_g").value = colours.g;
document.getElementById("rgb_b").value = colours.b;
};
this.toggle_color_select = function () {
if (POP.active == false) {
POP.add({
title: 'Colour:',
function: function () {
COLOR_copy = COLOR;
var html = '<canvas style="position:relative;margin-bottom:5px;" id="c_all" width="300" height="300"></canvas>';
html += '<table>';
html += '<tr>';
html += ' <td><b>Lum:</b></td>';
html += ' <td><input id="lum_ranger" oninput="GUI.change_lum(this.value);document.getElementById(\'lum_preview\').innerHTML=this.value;" type="range" value="0" min="-255" max="255" step="1"></td>';
html += ' <td style="padding-left:10px;width:30px;" id="lum_preview">0</td>';
html += '</tr>';
html += '<tr>';
html += ' <td><b>Alpha:</b></td>';
html += ' <td><input oninput="GUI.change_alpha(this.value);document.getElementById(\'alpha_preview\').innerHTML=this.value;" type="range" value="' + ALPHA + '" min="0" max="255" step="1"></td>';
html += ' <td style="padding-left:10px;" id="alpha_preview">' + ALPHA + '</td></tr>';
html += '</tr>';
html += '</table>';
return html;
}
});
POP.show(
'Select color',
function (user_response) {
var param1 = parseInt(user_response.param1);
},
undefined,
this.toggle_color_select_onload
);
}
else{
POP.hide();
}
};
this.change_lum = function (lumi) {
lumi = parseInt(lumi);
var c3 = HELPER.hex2rgb(COLOR_copy);
c3.r += lumi;
c3.g += lumi;
c3.b += lumi;
if (c3.r < 0)
c3.r = 0;
if (c3.g < 0)
c3.g = 0;
if (c3.b < 0)
c3.b = 0;
if (c3.r > 255)
c3.r = 255;
if (c3.g > 255)
c3.g = 255;
if (c3.b > 255)
c3.b = 255;
COLOR = "#" + ("000000" + HELPER.rgbToHex(c3.r, c3.g, c3.b)).slice(-6);
this.sync_colors();
};
this.change_alpha = function (value) {
ALPHA = parseInt(value);
document.getElementById("rgb_a").value = ALPHA;
};
this.toggle_color_select_onload = function () {
var img = new Image();
img.onload = function () {
document.getElementById("c_all").getContext("2d").drawImage(img, 0, 0);
document.getElementById("c_all").onmousedown = function (event) {
if (event.offsetX) {
mouse_x = event.offsetX;
mouse_y = event.offsetY;
}
else if (event.layerX) {
mouse_x = event.layerX;
mouse_y = event.layerY;
}
var c = document.getElementById("c_all").getContext("2d").getImageData(mouse_x, mouse_y, 1, 1).data;
COLOR = "#" + ("000000" + HELPER.rgbToHex(c[0], c[1], c[2])).slice(-6);
this.sync_colors();
COLOR_copy = COLOR;
document.getElementById("lum_ranger").value = 0;
};
};
img.src = 'img/colorwheel.png';
};
this.draw_selected_area = function (no_resize) {
if (DRAW.select_data == false)
return false;
//draw area
canvas_front.clearRect(0, 0, WIDTH, HEIGHT);
var x = DRAW.select_data.x;
var y = DRAW.select_data.y;
var w = DRAW.select_data.w;
var h = DRAW.select_data.h;
if (this.ZOOM != 100) {
x = Math.round(x);
y = Math.round(y);
w = Math.round(w);
h = Math.round(h);
}
//fill
canvas_front.fillStyle = "rgba(0, 255, 0, 0.3)";
canvas_front.fillRect(x, y, w, h);
if (this.ZOOM <= 100) {
//borders
canvas_front.strokeStyle = "rgba(0, 255, 0, 1)";
canvas_front.lineWidth = 1;
canvas_front.strokeRect(x + 0.5, y + 0.5, w, h);
}
if (no_resize == true)
return true;
//draw carners
square(x, y, 0, 0);
square(x + w, y, -1, 0);
square(x, y + h, 0, -1);
square(x + w, y + h, -1, -1);
//draw centers
square(x + w / 2, y, 0, 0);
square(x, y + h / 2, 0, 0);
square(x + w / 2, y + h, 0, -1);
square(x + w, y + h / 2, -1, 0);
function square(x, y, mx, my) {
var sr_size = Math.ceil(EVENTS.sr_size / this.ZOOM * 100);
x = Math.round(x);
y = Math.round(y);
canvas_front.beginPath();
canvas_front.rect(x + mx * Math.round(sr_size), y + my * Math.round(sr_size), sr_size, sr_size);
canvas_front.fillStyle = "#0000ff";
canvas_front.fill();
}
};
}

67
js/help.js Normal file
View File

@ -0,0 +1,67 @@
/* global POP */
/* global VERSION */
var HELP = new HELP_CLASS();
/**
* manages help actions
*
* @author ViliusL
*/
function HELP_CLASS() {
/**
* credits list config
*/
var CREDITS = [
{title: 'Brush styles', name: 'Harmony', link: 'http://ricardocabello.com/blog/post/689' },
{title: 'Effects library', name: 'glfx.js', link: 'http://evanw.github.io/glfx.js/' },
{title: 'EXIF', name: 'exif.js', link: 'https://github.com/jseidelin/exif-js' },
{title: 'Image filters', name: 'ImageFilters.js',link: 'https://github.com/arahaya/ImageFilters.js' },
{title: 'KD-tree', name: 'kdtree.js', link: 'http://jsdo.it/peko/wKvk' },
];
//shortcuts
this.help_shortcuts = function () {
POP.add({title: "D", value: 'Dublicate'});
POP.add({title: "Del", value: 'Delete selection'});
POP.add({title: "F", value: 'Auto adjust colors'});
POP.add({title: "G", value: 'Grid on/off'});
POP.add({title: "L", value: 'Rotate left'});
POP.add({title: "N", value: 'New layer'});
POP.add({title: "O", value: 'Open file(s)'});
POP.add({title: "R", value: 'Resize'});
POP.add({title: "S", value: 'Save'});
POP.add({title: "T", value: 'Trim'});
POP.add({title: "-", value: 'Zoom out'});
POP.add({title: "+", value: 'Zoom in'});
POP.add({title: "CTRL + Z", value: 'Undo'});
POP.add({title: "CTRL + A", value: 'Select all'});
POP.add({title: "CTRL + V", value: 'Paste'});
POP.add({title: "Arrow keys", value: 'Move active layer by 10px'});
POP.add({title: "CTRL + Arrow keys", value: 'Move active layer by 50px'});
POP.add({title: "SHIFT + Arrow keys", value: 'Move active layer by 1px'});
POP.add({title: "Drag & Drop", value: 'Imports images/xml data'});
POP.show('Keyboard Shortcuts', '');
};
//credits
this.help_credits = function () {
for (var i in CREDITS) {
if (CREDITS[i].link != undefined)
POP.add({title: CREDITS[i].title, html: '<a href="' + CREDITS[i].link + '">' + CREDITS[i].name + '</a>'});
else
POP.add({title: CREDITS[i].title, html: CREDITS[i].name});
}
POP.show('Credits', '');
};
//about
this.help_about = function () {
var email = 'www.viliusl@gmail.com';
POP.add({title: "Name:", value: "miniPaint " + VERSION});
POP.add({title: "Description:", value: 'online image editor'});
POP.add({title: "Author:", value: 'ViliusL'});
POP.add({title: "Email:", html: '<a href="mailto:' + email + '">' + email + '</a>'});
POP.add({title: "Source:", html: '<a href="https://github.com/viliusle/miniPaint">github.com/viliusle/miniPaint</a>'});
POP.show('About', '');
};
}

View File

@ -2,441 +2,176 @@
var HELPER = new HELPER_CLASS();
function HELPER_CLASS(){
/**
* various helpers
*
* @author ViliusL
*/
function HELPER_CLASS() {
var time;
this.drawImage_round = function(canvas, mouse_x, mouse_y, size, img_data, canvas_tmp, anti_alias){
var size_half = Math.round(size/2);
var ctx_tmp = canvas_tmp.getContext("2d");
var xx = mouse_x - size_half;
var yy = mouse_y - size_half;
if(xx < 0) xx = 0;
if(yy < 0) yy = 0;
ctx_tmp.clearRect(0, 0, WIDTH, HEIGHT);
ctx_tmp.save();
//draw main data
try{
ctx_tmp.drawImage(img_data, mouse_x - size_half, mouse_y - size_half, size, size);
}
catch(err){
try{
ctx_tmp.putImageData(img_data, xx, yy);
}
catch(err){
console.log("Error: "+err.message);
}
}
ctx_tmp.globalCompositeOperation = 'destination-in';
//create form
ctx_tmp.fillStyle = '#ffffff';
if(anti_alias == true){
var gradient = ctx_tmp.createRadialGradient(mouse_x, mouse_y, 0, mouse_x, mouse_y, size_half);
gradient.addColorStop(0, '#ffffff');
gradient.addColorStop(0.8, '#ffffff');
gradient.addColorStop(1, 'rgba(25115,255,255,0');
ctx_tmp.fillStyle = gradient;
}
ctx_tmp.beginPath();
ctx_tmp.arc(mouse_x, mouse_y, size_half, 0, 2*Math.PI, true);
ctx_tmp.fill();
//draw final data
if(xx + size > WIDTH)
size = WIDTH - xx;
if(yy + size > HEIGHT)
size = HEIGHT - yy;
canvas.drawImage(canvas_tmp, xx, yy, size, size, xx, yy, size, size);
//reset
ctx_tmp.restore();
ctx_tmp.clearRect(0, 0, WIDTH, HEIGHT);
};
this.timer_init = function(){
this.timer_init = function () {
time = Date.now();
};
this.timer = function(s, echo){
var str = "time("+s+") = "+(Math.round(Date.now() - time)/1000)+" s";
if(echo === true)
};
this.timer = function (s, echo) {
var str = "time(" + s + ") = " + (Math.round(Date.now() - time) / 1000) + " s";
if (echo === true)
return str;
else
console.log(str);
};
//get url param
this.get_url_param = function(name){
name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
var regexS = "[\\?&]"+name+"=([^&#]*)";
var regex = new RegExp( regexS );
var results = regex.exec( window.location.href );
if( results == null )
return "";
else
return results[1];
};
this.strpos = function(haystack, needle, offset) {
var i = (haystack+'').indexOf(needle, (offset || 0));
};
this.strpos = function (haystack, needle, offset) {
var i = (haystack + '').indexOf(needle, (offset || 0));
return i === -1 ? false : i;
};
this.sleep = function(millis){
var date = new Date();
var curDate = null;
do { curDate = new Date(); }
while(curDate-date < millis);
};
this.js_dump = function(arr,level) {
var dumped_text = "";
if(!level) level = 0;
//The padding given at the beginning of the line.
var level_padding = "";
for(var j=0;j<level+1;j++) level_padding += " ";
if(typeof(arr) == 'object') { //Array/Hashes/Objects
for(var item in arr) {
var value = arr[item];
if(typeof(value) == 'object') { //If it is an array,
dumped_text += level_padding + "'" + item + "' ...\n";
dumped_text += dump(value,level+1);
} else {
dumped_text += level_padding + "'" + item + "' => \"" + value + "\"\n";
}
};
this.getCookie = function (NameOfCookie) {
if (document.cookie.length > 0){
begin = document.cookie.indexOf(NameOfCookie + "=");
if (begin != -1){
begin += NameOfCookie.length + 1;
end = document.cookie.indexOf(";", begin);
if (end == -1)
end = document.cookie.length;
return unescape(document.cookie.substring(begin, end));
}
} else { //Stings/Chars/Numbers etc.
dumped_text = "===>"+arr+"<===("+typeof(arr)+")";
}
alert(dumped_text);
};
this.unique = function(list){
var o = {}, i, l = list.length, r = [];
for(i=0; i<l;i+=1) o[list[i]] = list[i];
for(i in o) r.push(o[i]);
return r;
};
this.preload = function(image) {
var imageObj = new Image();
imageObj.src=image;
};
this.getCookie = function(NameOfCookie){
if (document.cookie.length > 0)
{ begin = document.cookie.indexOf(NameOfCookie+"=");
if (begin != -1)
{ begin += NameOfCookie.length+1;
end = document.cookie.indexOf(";", begin);
if (end == -1) end = document.cookie.length;
return unescape(document.cookie.substring(begin, end)); }
}
return '';
};
this.setCookie = function(NameOfCookie, value, expiredays){
var ExpireDate = new Date ();
};
this.setCookie = function (NameOfCookie, value, expiredays) {
var ExpireDate = new Date();
ExpireDate.setTime(ExpireDate.getTime() + (expiredays * 24 * 3600 * 1000));
document.cookie = NameOfCookie + "=" + escape(value) +
((expiredays == null) ? "" : "; expires=" + ExpireDate.toGMTString());
};
this.delCookie = function(NameOfCookie){
((expiredays == null) ? "" : "; expires=" + ExpireDate.toGMTString());
};
this.delCookie = function (NameOfCookie) {
if (HELPER.getCookie(NameOfCookie)) {
document.cookie = NameOfCookie + "=" +
"; expires=Thu, 01-Jan-70 00:00:01 GMT";
}
};
/*
ctx.strokeStyle = "#2d6";
ctx.fillStyle = "#abc";
HELPER.roundRect(ctx, 100, 200, 200, 100, 50, true);
*/
this.roundRect = function(ctx, x, y, width, height, radius, fill, stroke){
if (typeof stroke == "undefined" ){
stroke = true;
}
if (typeof radius === "undefined"){
radius = 5;
}
ctx.beginPath();
ctx.moveTo(x + radius, y);
ctx.lineTo(x + width - radius, y);
ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
ctx.lineTo(x + width, y + height - radius);
ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
ctx.lineTo(x + radius, y + height);
ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
ctx.lineTo(x, y + radius);
ctx.quadraticCurveTo(x, y, x + radius, y);
ctx.closePath();
if (stroke){
ctx.stroke();
}
if (fill){
ctx.fill();
}
};
this.getRandomInt = function(min, max) {
"; expires=Thu, 01-Jan-70 00:00:01 GMT";
}
};
this.getRandomInt = function (min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
};
//dashed objects
this.dashedRect = function(canvas, x1, y1, x2, y2, dashLen, color) {
HELPER.dashedLine(canvas, x1, y1, x2, y1, dashLen, color);
HELPER.dashedLine(canvas, x2, y1, x2, y2, dashLen, color);
HELPER.dashedLine(canvas, x2, y2, x1, y2, dashLen, color);
HELPER.dashedLine(canvas, x1, y2, x1, y1, dashLen, color);
};
this.dashedLine = function(canvas, x1, y1, x2, y2, dashLen, color) {
x1 = x1 + 0.5;
y1 = y1 + 0.5;
x2 = x2 + 0.5;
y2 = y2 + 0.5;
if(color != undefined)
canvas.strokeStyle = color;
else
canvas.strokeStyle = "#000000";
if(dashLen == undefined) dashLen = 4;
canvas.beginPath();
canvas.moveTo(x1, y1);
var dX = x2 - x1;
var dY = y2 - y1;
var dashes = Math.floor(Math.sqrt(dX * dX + dY * dY) / dashLen);
var dashX = dX / dashes;
var dashY = dY / dashes;
var q = 0;
while (q++ < dashes){
x1 += dashX;
y1 += dashY;
canvas[q % 2 == 0 ? 'moveTo' : 'lineTo'](x1, y1);
}
canvas[q % 2 == 0 ? 'moveTo' : 'lineTo'](x2, y2);
canvas.stroke();
canvas.closePath();
};
this.font_pixel_to_height = function(px){
return Math.round(px*0.75);
};
this.rgbToHex = function(r, g, b) {
};
this.font_pixel_to_height = function (px) {
return Math.round(px * 0.75);
};
this.rgbToHex = function (r, g, b) {
if (r > 255 || g > 255 || b > 255)
throw "Invalid color component";
return ((r << 16) | (g << 8) | b).toString(16);
};
this.rgb2hex_all = function(rgb){
};
this.rgb2hex_all = function (rgb) {
rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
return "#" + HELPER.hex(rgb[1]) + HELPER.hex(rgb[2]) + HELPER.hex(rgb[3]);
};
this.hex = function(x){
};
this.hex = function (x) {
return ("0" + parseInt(x).toString(16)).slice(-2);
};
this.hex2rgb = function(hex) {
if (hex[0]=="#") hex=hex.substr(1);
if (hex.length==3) {
var temp=hex; hex='';
};
this.hex2rgb = function (hex) {
if (hex[0] == "#")
hex = hex.substr(1);
if (hex.length == 3) {
var temp = hex;
hex = '';
temp = /^([a-f0-9])([a-f0-9])([a-f0-9])$/i.exec(temp).slice(1);
for (var i=0;i<3;i++) hex+=temp[i]+temp[i];
}
for (var i = 0; i < 3; i++)
hex += temp[i] + temp[i];
}
var triplets = /^([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})$/i.exec(hex).slice(1);
return {
r: parseInt(triplets[0],16),
g: parseInt(triplets[1],16),
b: parseInt(triplets[2],16),
r: parseInt(triplets[0], 16),
g: parseInt(triplets[1], 16),
b: parseInt(triplets[2], 16),
a: 255
};
};
this.ColorLuminance = function(hex, lum){
// validate hex string
hex = String(hex).replace(/[^0-9a-f]/gi, '');
lum = lum || 0;
// convert to decimal and change luminosity
var rgb = "#", c, i;
for (i = 0; i < 3; i++){
c = parseInt(hex.substr(i*2,2), 16);
c = Math.round(Math.min(Math.max(0, c + (c * lum)), 255)).toString(16);
rgb += ("00"+c).substr(c.length);
}
return rgb;
};
this.drawImage_rotated = function(canvas, file, x, y, width, height, angle){
var TO_RADIANS = Math.PI/180;
var img = new Image();
img.src = file;
canvas.save();
canvas.translate(x, y);
canvas.rotate(angle * TO_RADIANS);
canvas.drawImage(img, -(width/2), -(height/2));
canvas.restore();
};
this.drawEllipseByCenter = function(ctx, cx, cy, w, h, color, fill) {
HELPER.drawEllipse(ctx, cx - w/2.0, cy - h/2.0, w, h, color, fill);
};
this.drawEllipse = function(ctx, x, y, w, h, color, fill) {
var kappa = .5522848,
ox = (w / 2) * kappa, // control point offset horizontal
oy = (h / 2) * kappa, // control point offset vertical
xe = x + w, // x-end
ye = y + h, // y-end
xm = x + w / 2, // x-middle
ym = y + h / 2; // y-middle
};
ctx.beginPath();
ctx.moveTo(x, ym);
ctx.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y);
ctx.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym);
ctx.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye);
ctx.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym);
ctx.closePath();
ctx.fillStyle = color;
ctx.strokeStyle = color;
if(fill==undefined)
ctx.stroke();
else
ctx.fill();
};
this.remove_selection = function(){
this.remove_selection = function () {
if (window.getSelection) {
if (window.getSelection().empty) // Chrome
if (window.getSelection().empty) // Chrome
window.getSelection().empty();
else if (window.getSelection().removeAllRanges) // Firefox
else if (window.getSelection().removeAllRanges) // Firefox
window.getSelection().removeAllRanges();
}
else if (document.selection) // IE?
}
else if (document.selection) // IE?
document.selection.empty();
};
this.get_dimensions = function(){
};
this.get_dimensions = function () {
var theWidth, theHeight;
if (window.innerWidth) {
theWidth=window.innerWidth;
}
theWidth = window.innerWidth;
}
else if (document.documentElement && document.documentElement.clientWidth) {
theWidth=document.documentElement.clientWidth;
}
theWidth = document.documentElement.clientWidth;
}
else if (document.body) {
theWidth=document.body.clientWidth;
}
theWidth = document.body.clientWidth;
}
if (window.innerHeight) {
theHeight=window.innerHeight;
}
theHeight = window.innerHeight;
}
else if (document.documentElement && document.documentElement.clientHeight) {
theHeight=document.documentElement.clientHeight;
}
theHeight = document.documentElement.clientHeight;
}
else if (document.body) {
theHeight=document.body.clientHeight;
}
theHeight = document.body.clientHeight;
}
return [theWidth, theHeight];
};
this.save_as_chrome = function(fileContents, fileName){
var link = document.createElement('a');
link.download = fileName;
link.href = 'data:,' + fileContents;
link.click();
};
};
//credits: richard maloney 2006
this.darkenColor = function(color, v){
if (color.length >6){
color = color.substring(1,color.length);
}
var rgb = parseInt(color, 16);
var r = Math.abs(((rgb >> 16) & 0xFF)+v); if (r>255) r=r-(r-255);
var g = Math.abs(((rgb >> 8) & 0xFF)+v); if (g>255) g=g-(g-255);
var b = Math.abs((rgb & 0xFF)+v); if (b>255) b=b-(b-255);
r = Number(r < 0 || isNaN(r)) ? 0 : ((r > 255) ? 255 : r).toString(16);
if (r.length == 1) r = '0' + r;
g = Number(g < 0 || isNaN(g)) ? 0 : ((g > 255) ? 255 : g).toString(16);
if (g.length == 1) g = '0' + g;
b = Number(b < 0 || isNaN(b)) ? 0 : ((b > 255) ? 255 : b).toString(16);
if (b.length == 1) b = '0' + b;
this.darkenColor = function (color, v) {
if (color.length > 6) {
color = color.substring(1, color.length);
}
var rgb = parseInt(color, 16);
var r = Math.abs(((rgb >> 16) & 0xFF) + v);
if (r > 255)
r = r - (r - 255);
var g = Math.abs(((rgb >> 8) & 0xFF) + v);
if (g > 255)
g = g - (g - 255);
var b = Math.abs((rgb & 0xFF) + v);
if (b > 255)
b = b - (b - 255);
r = Number(r < 0 || isNaN(r)) ? 0 : ((r > 255) ? 255 : r).toString(16);
if (r.length == 1)
r = '0' + r;
g = Number(g < 0 || isNaN(g)) ? 0 : ((g > 255) ? 255 : g).toString(16);
if (g.length == 1)
g = '0' + g;
b = Number(b < 0 || isNaN(b)) ? 0 : ((b > 255) ? 255 : b).toString(16);
if (b.length == 1)
b = '0' + b;
return "#" + r + g + b;
};
};
//IntegraXor Web SCADA - JavaScript Number Formatter, author: KPL, KHL
this.number_format = function(n, decPlaces, thouSeparator, decSeparator){
this.number_format = function (n, decPlaces, thouSeparator, decSeparator) {
var decPlaces = isNaN(decPlaces = Math.abs(decPlaces)) ? 2 : decPlaces;
var decSeparator = decSeparator == undefined ? "." : decSeparator;
var thouSeparator = thouSeparator == undefined ? "," : thouSeparator;
var sign = n < 0 ? "-" : "";
var n = Math.abs(+n || 0).toFixed(decPlaces);
var i = parseInt(n);
var i = parseInt(n = Math.abs(+n || 0).toFixed(decPlaces)) + "";
var j = (j = i.length) > 3 ? j % 3 : 0;
return sign + (j ? i.substr(0, j) + thouSeparator : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + thouSeparator) + (decPlaces ? decSeparator + Math.abs(n - i).toFixed(decPlaces).slice(2) : "");
};
this.length = function(object){
var n = 0;
for(var i in object){
n++;
}
return n;
};
this.chech_input_color_support = function(id){
if(document.getElementById(id).value != undefined && document.getElementById(id).value[0] == '#')
};
this.chech_input_color_support = function (id) {
if (document.getElementById(id).value != undefined && document.getElementById(id).value[0] == '#')
return true;
return false;
};
}
//http://www.script-tutorials.com/html5-canvas-custom-brush1/
var BezierCurveBrush = {
// inner variables
iPrevX: 0,
iPrevY: 0,
points: null,
// initialization function
init: function () {
},
startCurve: function (x, y) {
this.iPrevX = x;
this.iPrevY = y;
this.points = new Array();
},
getPoint: function (iLength, a) {
var index = a.length - iLength, i;
for (i = index; i < a.length; i++) {
if (a[i]) {
return a[i];
}
}
},
draw: function (ctx, color_rgb, x, y, size) {
if (Math.abs(this.iPrevX - x) > 5 || Math.abs(this.iPrevY - y) > 5) {
this.points.push([x, y]);
// draw main path stroke
ctx.beginPath();
ctx.moveTo(this.iPrevX, this.iPrevY);
ctx.lineTo(x, y);
ctx.lineWidth = size;
ctx.lineCap = 'round';
ctx.lineJoin = 'round';
ctx.strokeStyle = 'rgba(' + color_rgb.r + ', ' + color_rgb.g + ', ' + color_rgb.b + ', 0.9)';
ctx.stroke();
ctx.closePath();
// draw extra strokes
ctx.lineWidth = 1;
ctx.strokeStyle = 'rgba(' + color_rgb.r + ', ' + color_rgb.g + ', ' + color_rgb.b + ', 0.2)';
ctx.beginPath();
var iStartPoint = this.getPoint(25, this.points);
var iFirstPoint = this.getPoint(1, this.points);
var iSecondPoint = this.getPoint(5, this.points);
ctx.moveTo(iStartPoint[0],iStartPoint[1]);
ctx.bezierCurveTo(iFirstPoint[0], iFirstPoint[1], iSecondPoint[0], iSecondPoint[1], x, y);
ctx.stroke();
ctx.closePath();
this.iPrevX = x;
this.iPrevY = y;
}
}
};
//quick access short functions
function log(object){
if(typeof object != 'object')
console.log(object);
else{
var str = '[';
for(var i in object){
if(typeof object[i] == 'number')
str += Math.round(object[i]*1000)/1000+", ";
else
str += object[i]+", ";
}
str += ']';
log(str);
}
}
function round(number){
return Math.round(number);
}
};
}

1052
js/image.js Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,92 +1,327 @@
/* global HELPER, POP, MAIN, LAYERS, CON, LAYER, DRAW, MENU, TOOLS */
/* global WIDTH, HEIGHT, ZOOM, LAYERS, canvas_front, canvas_back */
/* global HELPER, POP, MAIN, EVENTS, LAYER, IMAGE, DRAW, EDIT, GUI */
/* global WIDTH, HEIGHT, canvas_front, canvas_back */
var LAYER = new LAYER_CLASS();
function LAYER_CLASS(){
this.layer_active = 0;
var imageData_tmp;
var layer_max_index = 0;
/**
* layers class - manages layers
*
* @author ViliusL
*/
function LAYER_CLASS() {
/**
* active layer index
*/
this.layer_active = 0;
/**
* data layers array
*/
this.layers = [];
/**
* latest layer index
*/
var layer_max_index = 0;
//new layer
this.layer_new = function () {
this.add_layer();
};
//dublicate
this.layer_dublicate = function () {
EDIT.save_state();
if (DRAW.select_data != false) {
//selection
this.copy_to_clipboard();
DRAW.select_data = false;
canvas_front.clearRect(0, 0, WIDTH, HEIGHT);
var tmp = LAYER.layer_active;
this.paste('menu');
LAYER.layer_active = tmp;
LAYER.layer_renew();
}
else {
//copy all layer
tmp_data = document.createElement("canvas");
tmp_data.width = WIDTH;
tmp_data.height = HEIGHT;
tmp_data.getContext("2d").drawImage(canvas_active(true), 0, 0);
//create
var new_name = 'Layer #' + (this.layers.length + 1);
LAYER.create_canvas(new_name);
this.layers.push({name: new_name, visible: true});
LAYER.layer_active = this.layers.length - 1;
canvas_active().drawImage(tmp_data, 0, 0);
LAYER.layer_renew();
}
};
//show / hide
this.layer_show_hide = function () {
LAYER.layer_visibility(LAYER.layer_active);
};
//crop
this.layer_crop = function () {
EDIT.save_state();
if (DRAW.select_data == false) {
POP.add({html: 'Select area first'});
POP.show('Error', '');
}
else {
var layer = LAYER.canvas_active();
var tmp = layer.getImageData(DRAW.select_data.x, DRAW.select_data.y, DRAW.select_data.w, DRAW.select_data.h);
layer.clearRect(0, 0, WIDTH, HEIGHT);
layer.putImageData(tmp, 0, 0);
DRAW.select_data = false;
canvas_front.clearRect(0, 0, WIDTH, HEIGHT);
}
};
//delete
this.layer_delete = function () {
EDIT.save_state();
LAYER.layer_remove(LAYER.layer_active);
};
//move up
this.layer_move_up = function () {
EDIT.save_state();
LAYER.move_layer('up');
};
//move down
this.layer_move_down = function () {
EDIT.save_state();
LAYER.move_layer('down');
};
//opacity
this.layer_opacity = function () {
LAYER.set_alpha();
};
//trim
this.layer_trim = function () {
EDIT.save_state();
IMAGE.trim(this.layers[LAYER.layer_active].name, true);
};
//resize
this.layer_resize = function () {
IMAGE.resize_box();
};
//clear
this.layer_clear = function () {
EDIT.save_state();
canvas_active().clearRect(0, 0, WIDTH, HEIGHT);
};
//show differences
this.layer_differences = function () {
if (parseInt(LAYER.layer_active) + 1 >= this.layers.length) {
POP.add({html: 'This can not be last layer'});
POP.show('Error', '');
return false;
}
POP.add({name: "param1", title: "Sensitivity:", value: "0", range: [0, 255]});
POP.show(
'Differences',
function (response) {
var param1 = parseInt(response.param1);
LAYER.calc_differences(param1);
},
function (user_response, canvas_preview, w, h) {
var param1 = parseInt(user_response.param1);
LAYER.calc_differences(param1, canvas_preview, w, h);
}
);
};
//merge
this.layer_merge_down = function () {
var compositions = ["source-over", "source-in", "source-out", "source-atop",
"destination-over", "destination-in", "destination-out", "destination-atop",
"lighter", "darker", "copy", "xor"];
var blend_modes = ["normal", "multiply", "screen", "overlay", "darken", "lighten",
"color-dodge", "color-burn", "hard-light", "soft-light", "difference",
"exclusion", "hue", "saturation", "color", "luminosity"];
if (parseInt(LAYER.layer_active) + 1 >= this.layers.length) {
POP.add({html: 'This can not be last layer.'});
POP.show('Error', '');
return false;
}
POP.add({name: "param1", title: "Composition:", values: compositions});
POP.add({name: "param2", title: "Blend:", values: blend_modes});
POP.add({name: "param3", title: "Mode:", values: ["Composite", "Blend"]});
POP.show(
'Merge',
function (response) {
var param1 = response.param1;
var param2 = response.param2;
var param3 = response.param3;
EDIT.save_state();
//copy
LAYER.layer_active++;
var tmp_data = document.createElement("canvas");
tmp_data.width = WIDTH;
tmp_data.height = HEIGHT;
tmp_data.getContext("2d").drawImage(LAYER.canvas_active(true), 0, 0);
//paste
LAYER.layer_active--;
LAYER.canvas_active().save();
if (param3 == "Composite")
LAYER.canvas_active().globalCompositeOperation = param1;
else
LAYER.canvas_active().globalCompositeOperation = param2;
LAYER.canvas_active().drawImage(tmp_data, 0, 0);
LAYER.canvas_active().restore();
//remove next layer
LAYER.layer_remove(LAYER.layer_active + 1);
LAYER.layer_renew();
},
function (response, canvas_preview, w, h) {
var param1 = response.param1;
var param2 = response.param2;
var param3 = response.param3;
//copy
LAYER.layer_active++;
var tmp_data = document.createElement("canvas");
tmp_data.width = w;
tmp_data.height = h;
tmp_data.getContext("2d").drawImage(LAYER.canvas_active(true), 0, 0, WIDTH, HEIGHT, 0, 0, w, h);
//paste
LAYER.layer_active--;
canvas_preview.save();
if (param3 == "Composite")
canvas_preview.globalCompositeOperation = param1;
else
canvas_preview.globalCompositeOperation = param2;
canvas_preview.drawImage(tmp_data, 0, 0);
canvas_preview.restore();
}
);
};
//flatten all
this.layer_flatten = function () {
EDIT.save_state();
if (this.layers.length == 1)
return false;
tmp_data = document.createElement("canvas");
tmp_data.width = WIDTH;
tmp_data.height = HEIGHT;
for (var i = 1; i < this.layers.length; i++) {
//copy
LAYER.layer_active = i;
tmp_data.getContext("2d").clearRect(0, 0, WIDTH, HEIGHT);
tmp_data.getContext("2d").drawImage(canvas_active(true), 0, 0);
//paste
LAYER.layer_active = 0;
canvas_active().drawImage(tmp_data, 0, 0);
}
for (var i = this.layers.length - 1; i > 0; i--) {
//delete layer
LAYER.layer_active = i;
LAYER.layer_remove(LAYER.layer_active);
}
LAYER.layer_renew();
};
//create layer
this.layer_add = function(name, data, type){
this.layer_add = function (name, data, type) {
tmp = new Array();
if(data == undefined){
if (data == undefined) {
//empty layer
if(name==undefined){
if (name == undefined) {
layer_max_index++;
name = 'Layer #'+(layer_max_index+1);
}
name = 'Layer #' + (layer_max_index + 1);
}
tmp.name = name;
tmp.visible = true;
tmp.opacity = 1;
if(LAYERS.length==0)
if (this.layers.length == 0)
tmp.primary = 1;
else
LAYER.create_canvas(name);
LAYERS.push(tmp);
}
else{
this.layers.push(tmp);
}
else {
var img = new Image();
if(data.substring(0,4) == 'http')
if (data.substring(0, 4) == 'http')
img.crossOrigin = "Anonymous"; //data from other domain - turn on CORS
img.onload = function(){
var _this = this;
img.onload = function () {
//check size
var size_increased = false;
if(img.width > WIDTH || img.height > HEIGHT){
if(img.width > WIDTH)
if (img.width > WIDTH || img.height > HEIGHT) {
if (img.width > WIDTH)
WIDTH = img.width;
if(img.height > HEIGHT)
if (img.height > HEIGHT)
HEIGHT = img.height;
RATIO = WIDTH/HEIGHT;
LAYER.set_canvas_size();
size_increased = true;
}
if(LAYERS.length == 1 && CON.autosize == true && size_increased == false){
var trim_info = DRAW.trim_info(document.getElementById("Background"));
if(trim_info.left == WIDTH){
}
if (_this.layers.length == 1 && EVENTS.autosize == true && size_increased == false) {
var trim_info = IMAGE.trim_info(document.getElementById("Background"));
if (trim_info.left == WIDTH) {
WIDTH = img.width;
HEIGHT = img.height;
RATIO = WIDTH/HEIGHT;
LAYER.set_canvas_size(false);
}
}
for(var i in LAYERS){
if(LAYERS[i].name == name){
}
for (var i in _this.layers) {
if (_this.layers[i].name == name) {
layer_max_index++;
name = 'Layer #'+(layer_max_index+1);
}
name = 'Layer #' + (layer_max_index + 1);
}
}
LAYER.create_canvas(name);
LAYERS.push({
name: name,
_this.layers.push({
name: name,
visible: true,
opacity: 1
});
LAYER.layer_active = LAYERS.length-1;
});
LAYER.layer_active = _this.layers.length - 1;
document.getElementById(name).getContext("2d").globalAlpha = 1;
document.getElementById(name).getContext('2d').drawImage(img, 0, 0);
LAYER.layer_renew();
DRAW.zoom();
};
img.onerror = function(ex){
GUI.zoom();
};
img.onerror = function (ex) {
POP.add({html: '<b>The image could not be loaded.<br /><br /></b>'});
if(data.substring(0,4) == 'http')
if (data.substring(0, 4) == 'http')
POP.add({title: "Reason:", value: 'Cross-origin resource sharing (CORS) not supported. Try to save image first.'});
POP.show('Error', '.');
};
};
img.src = data;
}
LAYER.layer_active = LAYERS.length-1;
document.getElementById(LAYERS[LAYER.layer_active].name).getContext("2d").globalAlpha = 1;
}
LAYER.layer_active = this.layers.length - 1;
document.getElementById(this.layers[LAYER.layer_active].name).getContext("2d").globalAlpha = 1;
this.layer_renew();
};
this.create_canvas = function(canvas_id){
};
this.create_canvas = function (canvas_id) {
var new_canvas = document.createElement('canvas');
new_canvas.setAttribute('id', canvas_id);
document.getElementById('canvas_more').appendChild(new_canvas);
new_canvas.width = WIDTH;
new_canvas.height = HEIGHT;
@ -94,32 +329,37 @@ function LAYER_CLASS(){
new_canvas.getContext("2d").webkitImageSmoothingEnabled = false;
new_canvas.getContext("2d").ImageSmoothingEnabled = false;
//sync zoom
new_canvas.style.width = round(WIDTH * ZOOM / 100)+"px";
new_canvas.style.height = round(HEIGHT * ZOOM / 100)+"px";
};
this.move_layer = function(direction){
if(LAYERS.length < 2) return false;
if(LAYERS[LAYER.layer_active].primary == 1) return false;
new_canvas.style.width = Math.round(WIDTH * GUI.ZOOM / 100) + "px";
new_canvas.style.height = Math.round(HEIGHT * GUI.ZOOM / 100) + "px";
};
this.move_layer = function (direction) {
if (this.layers.length < 2)
return false;
if (this.layers[LAYER.layer_active].primary == 1)
return false;
LAYER.layer_active = parseInt(LAYER.layer_active);
var layer_from = LAYERS[LAYER.layer_active];
var content = document.getElementById(LAYERS[LAYER.layer_active].name);
var layer_from = this.layers[LAYER.layer_active];
var content = document.getElementById(this.layers[LAYER.layer_active].name);
var parent = content.parentNode;
if(direction == 'up'){
if(LAYERS[LAYER.layer_active-1] == undefined) return false;
if(LAYERS[LAYER.layer_active-1].primary == 1) return false;
var layer_to = LAYERS[LAYER.layer_active-1];
if (direction == 'up') {
if (this.layers[LAYER.layer_active - 1] == undefined)
return false;
if (this.layers[LAYER.layer_active - 1].primary == 1)
return false;
var layer_to = this.layers[LAYER.layer_active - 1];
parent.insertBefore(content, parent.firstChild);
}
else{
if(LAYERS[LAYER.layer_active+1] == undefined) return false;
var layer_to = LAYERS[LAYER.layer_active+1];
var content = document.getElementById(LAYERS[LAYER.layer_active+1].name);
}
else {
if (this.layers[LAYER.layer_active + 1] == undefined)
return false;
var layer_to = this.layers[LAYER.layer_active + 1];
var content = document.getElementById(this.layers[LAYER.layer_active + 1].name);
parent.insertBefore(content, parent.firstChild);
}
}
//switch name
var tmp = layer_to.name;
layer_to.name = layer_from.name;
@ -132,229 +372,326 @@ function LAYER_CLASS(){
var tmp = layer_to.opacity;
layer_to.opacity = layer_from.opacity;
layer_from.opacity = tmp;
LAYER.layer_active = LAYERS.length-1;
for(var i in LAYERS){
if(LAYERS[i].name == layer_to.name){
LAYER.layer_active = this.layers.length - 1;
for (var i in this.layers) {
if (this.layers[i].name == layer_to.name) {
LAYER.layer_active = i;
break;
}
}
}
this.layer_renew();
DRAW.zoom();
GUI.zoom();
return true;
};
this.layer_visibility = function(i){
if(LAYERS[i].visible == true){
LAYERS[i].visible = false;
document.getElementById(LAYERS[i].name).style.visibility = 'hidden';
document.getElementById('layer_'+i).src = "img/yes-grey.png";
}
else{
LAYERS[i].visible = true;
document.getElementById(LAYERS[i].name).style.visibility = 'visible';
document.getElementById('layer_'+i).src = "img/yes.png";
}
};
this.layer_visibility = function (i) {
if (this.layers[i].visible == true) {
this.layers[i].visible = false;
document.getElementById(this.layers[i].name).style.visibility = 'hidden';
document.getElementById('layer_' + i).src = "img/yes-grey.png";
}
else {
this.layers[i].visible = true;
document.getElementById(this.layers[i].name).style.visibility = 'visible';
document.getElementById('layer_' + i).src = "img/yes.png";
}
this.layer_renew();
DRAW.redraw_preview();
};
this.layer_remove = function(i){
if(LAYERS[i].primary == 1) return false;
element = document.getElementById(LAYERS[i].name);
GUI.redraw_preview();
};
this.layer_remove = function (i) {
if (this.layers[i].primary == 1)
return false;
element = document.getElementById(this.layers[i].name);
element.getContext("2d").clearRect(0, 0, WIDTH, HEIGHT);
element.parentNode.removeChild(element);
LAYERS.splice(i, 1);
if(LAYER.layer_active >= LAYERS.length)
LAYER.layer_active = LAYERS.length-1;
this.layers.splice(i, 1);
if (LAYER.layer_active >= this.layers.length)
LAYER.layer_active = this.layers.length - 1;
this.layer_renew();
DRAW.redraw_preview();
};
this.layer_move_active = function(x, y){
GUI.redraw_preview();
};
this.layer_move_active = function (x, y) {
var distance = 10;
if(CON.ctrl_pressed == true)
if (EVENTS.ctrl_pressed == true)
distance = 50;
if(CON.shift_pressed == true)
if (EVENTS.shift_pressed == true)
distance = 1;
//move
dx = x*distance;
dy = y*distance;
dx = x * distance;
dy = y * distance;
var tmp = canvas_active().getImageData(0, 0, WIDTH, HEIGHT);
canvas_active().clearRect(0, 0, WIDTH, HEIGHT);
canvas_active().putImageData(tmp, dx, dy);
};
this.select_layer = function(i){
if(LAYER.layer_active != i){
};
this.select_layer = function (i) {
if (LAYER.layer_active != i) {
LAYER.layer_active = i; //select
this.layer_renew();
}
}
LAYER.shake(i);
};
this.layer_renew = function(){
};
this.layer_renew = function () {
var html = '';
for(var i in LAYERS){
for (var i in this.layers) {
//create
if(LAYER.layer_active==i)
if (LAYER.layer_active == i)
html += '<div class="layer active">';
else
html += '<div class="layer">';
var title = LAYERS[i].name;
html += '<span class="layer_title" onclick="LAYER.select_layer(\''+i+'\')">'+title+'</span>';
if(LAYERS[i].primary != 1){
html += '<a class="layer_visible" onclick="LAYER.layer_remove(\''+i+'\');return false;" title="delete" href="#"></a>';
}
var title = this.layers[i].name;
html += '<span class="layer_title" onclick="LAYER.select_layer(\'' + i + '\')">' + title + '</span>';
if (this.layers[i].primary != 1) {
html += '<a class="layer_visible" onclick="LAYER.layer_remove(\'' + i + '\');return false;" title="delete" href="#"></a>';
}
else
html += '<a style="visibility:hidden;" class="layer_visible" href="#"></a>';
//hide
if(LAYERS[i].visible == true)
html += '<a class="layer_delete" id="layer_'+i+'" onclick="LAYER.layer_visibility(\''+i+'\');return false;" title="hide" href="#"></a>';
if (this.layers[i].visible == true)
html += '<a class="layer_delete" id="layer_' + i + '" onclick="LAYER.layer_visibility(\'' + i + '\');return false;" title="hide" href="#"></a>';
else
html += '<a class="layer_delete layer_unvisible" id="layer_'+i+'" onclick="LAYER.layer_visibility(\''+i+'\');return false;" title="show" href="#"></a>';
html += '<a class="layer_delete layer_unvisible" id="layer_' + i + '" onclick="LAYER.layer_visibility(\'' + i + '\');return false;" title="show" href="#"></a>';
html += '</div>';
//show
document.getElementById('layers').innerHTML = html;
}
};
this.shake = function(i, nr){
}
};
this.shake = function (i, nr) {
var step = 3;
var n = 10;
if(nr == undefined){
if (nr == undefined) {
//begin
nr = 0;
canvas_front.drawImage(canvas_active(true), 0, 0);
}
var dx = step * (nr%2);
if(dx == 0)
}
var dx = step * (nr % 2);
if (dx == 0)
dx = -step;
var element = document.getElementById('canvas_front');
element.style.marginLeft = dx+"px";
if(nr < n)
setTimeout(function(){LAYER.shake(i, nr + 1);}, 15);
else{
element.style.marginLeft = dx + "px";
if (nr < n)
setTimeout(function () {
LAYER.shake(i, nr + 1);
}, 15);
else {
//finish shaking
element.style.marginLeft = "0px";
element.style.marginLeft = "0px";
canvas_front.clearRect(0, 0, WIDTH, HEIGHT);
}
};
this.update_info_block = function(){
}
};
this.update_info_block = function () {
var html = '';
html += '<span style="font-weight:bold;min-width:45px;display:block;float:left;">Size:</span> '+WIDTH+"x"+HEIGHT+"<br />";
html += '<span style="font-weight:bold;min-width:45px;display:block;float:left;">Size:</span> ' + WIDTH + "x" + HEIGHT + "<br />";
var x = 0;
var y = 0;
if(CON.mouse != undefined){
x = CON.mouse.x;
y = CON.mouse.y;
}
html += '<span style="font-weight:bold;min-width:45px;display:block;float:left;">Mouse:</span> '+x+", "+y+"<br />";
if(TOOLS.select_data != false){
html += '<span style="font-weight:bold;min-width:45px;display:block;float:left;">XY:</span> '+TOOLS.select_data.x+", "+TOOLS.select_data.y+"<br />";
html += '<span style="font-weight:bold;min-width:45px;display:block;float:left;">Area:</span> '+TOOLS.select_data.w+", "+TOOLS.select_data.h+"<br />";
}
if (EVENTS.mouse != undefined) {
x = EVENTS.mouse.x;
y = EVENTS.mouse.y;
}
html += '<span style="font-weight:bold;min-width:45px;display:block;float:left;">Mouse:</span> ' + x + ", " + y + "<br />";
if (DRAW.select_data != false) {
html += '<span style="font-weight:bold;min-width:45px;display:block;float:left;">XY:</span> ' + DRAW.select_data.x + ", " + DRAW.select_data.y + "<br />";
html += '<span style="font-weight:bold;min-width:45px;display:block;float:left;">Area:</span> ' + DRAW.select_data.w + ", " + DRAW.select_data.h + "<br />";
}
document.getElementById('info').innerHTML = html;
};
this.set_canvas_size = function(repaint){
var W = round(WIDTH);
var H = round(W / RATIO);
};
this.set_canvas_size = function (repaint) {
var ratio = WIDTH/HEIGHT;
var W = Math.round(WIDTH);
var H = Math.round(W / ratio);
this.resize_canvas("canvas_back");
DRAW.draw_background(canvas_back, WIDTH, HEIGHT);
GUI.draw_background(canvas_back, WIDTH, HEIGHT);
this.resize_canvas("canvas_front", false);
this.resize_canvas("canvas_grid", true);
for(var i in LAYERS){
if(repaint === false)
this.resize_canvas(LAYERS[i].name, false);
for (var i in this.layers) {
if (repaint === false)
this.resize_canvas(this.layers[i].name, false);
else
this.resize_canvas(LAYERS[i].name, true);
}
DRAW.draw_grid();
this.resize_canvas(this.layers[i].name, true);
}
GUI.draw_grid();
document.getElementById('resize-w').style.marginLeft = W + "px";
document.getElementById('resize-w').style.marginTop = Math.round(H/2) + "px";
document.getElementById('resize-h').style.marginLeft = Math.round(W/2) + "px";
document.getElementById('resize-w').style.marginTop = Math.round(H / 2) + "px";
document.getElementById('resize-h').style.marginLeft = Math.round(W / 2) + "px";
document.getElementById('resize-h').style.marginTop = H + "px";
document.getElementById('resize-wh').style.marginLeft = W + "px";
document.getElementById('resize-wh').style.marginTop = H + "px";
this.update_info_block();
CON.calc_preview_auto();
DRAW.zoom();
};
this.resize_canvas = function(canvas_name, repaint){
var W = round(WIDTH );
var H = round(W / RATIO);
EVENTS.calc_preview_auto();
GUI.zoom();
};
this.resize_canvas = function (canvas_name, repaint) {
var ratio = WIDTH/HEIGHT;
var W = Math.round(WIDTH);
var H = Math.round(W / ratio);
var canvas = document.getElementById(canvas_name);
var ctx = canvas.getContext("2d");
if(repaint==false){
if (repaint == false) {
canvas.width = W;
canvas.height = H;
}
else{
}
else {
//save
var buffer = document.createElement('canvas');
buffer.width = WIDTH;
buffer.height = HEIGHT;
buffer.getContext('2d').drawImage(canvas, 0, 0);
canvas.width = W;
canvas.height = H;
//restore
ctx.drawImage(buffer, 0, 0);
}
};
this.set_alpha = function(){
if(LAYERS[LAYER.layer_active].opacity == undefined)
LAYERS[LAYER.layer_active].opacity = 1;
POP.add({name: "param1", title: "Alpha:", value: LAYERS[LAYER.layer_active].opacity, range: [0, 1], step: 0.01 });
POP.show('Opacity', function(user_response){
var param1 = parseFloat(user_response.param1);
LAYERS[LAYER.layer_active].opacity = param1;
canvas_active().globalAlpha = param1;
var img = canvas_active().getImageData(0, 0, WIDTH, HEIGHT);
var imgData = img.data;
var new_alpha = 255*param1;
if(new_alpha < 10)
new_alpha = 10;
canvas_active().clearRect(0, 0, WIDTH, HEIGHT);
for(var y = 0; y < img.height; y++){
for(var x = 0; x < img.width; x++){
var k = ((y * (img.width * 4)) + (x * 4));
if(imgData[k+3] > 0)
imgData[k+3] = new_alpha;
}
};
this.set_alpha = function () {
if (this.layers[LAYER.layer_active].opacity == undefined)
this.layers[LAYER.layer_active].opacity = 1;
POP.add({name: "param1", title: "Alpha:", value: this.layers[LAYER.layer_active].opacity, range: [0, 1], step: 0.01});
POP.show(
'Opacity',
function (user_response) {
var param1 = parseFloat(user_response.param1);
this.layers[LAYER.layer_active].opacity = param1;
canvas_active().globalAlpha = param1;
var img = canvas_active().getImageData(0, 0, WIDTH, HEIGHT);
var imgData = img.data;
var new_alpha = 255 * param1;
if (new_alpha < 10)
new_alpha = 10;
canvas_active().clearRect(0, 0, WIDTH, HEIGHT);
for (var y = 0; y < img.height; y++) {
for (var x = 0; x < img.width; x++) {
var k = ((y * (img.width * 4)) + (x * 4));
if (imgData[k + 3] > 0)
imgData[k + 3] = new_alpha;
}
}
canvas_active().putImageData(img, 0, 0);
DRAW.zoom();
});
};
this.canvas_active = function(base){
for(var i in LAYERS){
if(LAYER.layer_active==i){
if(base == undefined)
return document.getElementById(LAYERS[i].name).getContext("2d");
else
return document.getElementById(LAYERS[i].name);
}
}
};
}
canvas_active().putImageData(img, 0, 0);
function canvas_active(base){
for(var i in LAYERS){
if(LAYER.layer_active==i){
if(base == undefined)
return document.getElementById(LAYERS[i].name).getContext("2d");
else
return document.getElementById(LAYERS[i].name);
GUI.zoom();
}
);
};
this.canvas_active = function (base) {
for (var i in this.layers) {
if (LAYER.layer_active == i) {
if (base == undefined)
return document.getElementById(this.layers[i].name).getContext("2d");
else
return document.getElementById(this.layers[i].name);
}
}
};
this.add_layer = function () {
EDIT.save_state();
var tmp = false;
var last_layer = LAYER.layer_active;
if (DRAW.select_data != false) {
tmp = document.createElement("canvas");
tmp.width = DRAW.select_data.w;
tmp.height = DRAW.select_data.h;
tmp.getContext("2d").drawImage(canvas_active(true), DRAW.select_data.x, DRAW.select_data.y, DRAW.select_data.w, DRAW.select_data.h, 0, 0, DRAW.select_data.w, DRAW.select_data.h);
}
//crete layer
LAYER.layer_add();
if (DRAW.select_data != false) {
//copy user selected data to new layer
canvas_active().drawImage(tmp, 0, 0);
LAYER.layer_renew();
//clear selection
DRAW.select_data = false;
canvas_front.clearRect(0, 0, WIDTH, HEIGHT);
//switch back to old layer
LAYER.layer_active = last_layer;
LAYER.layer_renew();
}
};
this.calc_differences = function (sensitivity, canvas_preview, w, h) {
vlayer_active = parseInt(LAYER.layer_active);
//first layer
var img1 = canvas_active().getImageData(0, 0, WIDTH, HEIGHT);
var imgData1 = img1.data;
//second layer
var context2 = document.getElementById(this.layers[vlayer_active + 1].name).getContext("2d");
var img2 = context2.getImageData(0, 0, WIDTH, HEIGHT);
var imgData2 = img2.data;
//result layer
if (canvas_preview == undefined) {
//add differences layer
LAYER.layer_add();
canvas_active().rect(0, 0, WIDTH, HEIGHT);
canvas_active().fillStyle = "#ffffff";
canvas_active().fill();
var img3 = canvas_active().getImageData(0, 0, WIDTH, HEIGHT);
}
else {
//work on preview layer
var canvas_tmp = document.createElement("canvas");
canvas_tmp.width = WIDTH;
canvas_tmp.height = HEIGHT;
var img3 = canvas_tmp.getContext("2d").getImageData(0, 0, WIDTH, HEIGHT);
}
var imgData3 = img3.data;
for (var xx = 0; xx < WIDTH; xx++) {
for (var yy = 0; yy < HEIGHT; yy++) {
var x = (xx + yy * WIDTH) * 4;
if (Math.abs(imgData1[x] - imgData2[x]) > sensitivity
|| Math.abs(imgData1[x + 1] - imgData2[x + 1]) > sensitivity
|| Math.abs(imgData1[x + 2] - imgData2[x + 2]) > sensitivity
|| Math.abs(imgData1[x + 3] - imgData2[x + 3]) > sensitivity) {
imgData3[x] = 255;
imgData3[x + 1] = 0;
imgData3[x + 2] = 0;
imgData3[x + 3] = 255;
}
}
}
if (canvas_preview == undefined)
canvas_active().putImageData(img3, 0, 0);
else {
canvas_tmp.getContext("2d").rect(0, 0, WIDTH, HEIGHT);
canvas_tmp.getContext("2d").fillStyle = "#ffffff";
canvas_tmp.getContext("2d").fill();
canvas_tmp.getContext("2d").putImageData(img3, 0, 0);
canvas_preview.clearRect(0, 0, w, h);
canvas_preview.save();
canvas_preview.scale(w / WIDTH, h / HEIGHT);
canvas_preview.drawImage(canvas_tmp, 0, 0);
canvas_preview.restore();
}
};
}
function canvas_active(base) {
for (var i in LAYER.layers) {
if (LAYER.layer_active == i) {
if (base == undefined)
return document.getElementById(LAYER.layers[i].name).getContext("2d");
else
return document.getElementById(LAYER.layers[i].name);
}
}
console.log('Error, can not find active layer.');
}

View File

@ -1,143 +1,50 @@
/* global HELPER, POP, MAIN, LAYERS, CON, LAYER, DRAW, MENU, TOOLS */
/* global canvas_main, canvas_back, COLOUR, ALPHA, canvas_grid */
/* global HELPER, EVENTS, LAYER, POP, FILE, GUI, DRAW */
/* global WIDTH, HEIGHT, canvas_main, canvas_back, canvas_grid, COLOR, ALPHA */
var MAIN = new MAIN_CLASS();
document.onload = MAIN.init(true);
function MAIN_CLASS(){
this.grid = false;
this.TRANSPARENCY = true;
var LAYERS_ARCHIVE = [{}, {}, {}];
var undo_level = 0;
this.init = function(first_load){
if(first_load===true){
TOOLS.draw_helpers();
/**
* main class - initialize app
*
* @author ViliusL
*/
function MAIN_CLASS() {
this.init = function (first_load) {
if (first_load === true) {
GUI.draw_helpers();
POP.height_mini = Math.round(POP.width_mini * HEIGHT / WIDTH);
}
CON.autosize = true;
TOOLS.EXIF = false;
TOOLS.select_data = false;
for(i=1; i<LAYERS.length; i++)
}
EVENTS.autosize = true;
FILE.EXIF = false;
DRAW.select_data = false;
for (i = 1; i < LAYER.layers.length; i++)
LAYER.layer_remove(i);
LAYERS = [];
LAYER.layers = [];
canvas_main.clearRect(0, 0, WIDTH, HEIGHT);
LAYER.layer_add("Background");
LAYER.set_canvas_size();
DRAW.draw_background(canvas_back, WIDTH, HEIGHT);
document.getElementById("canvas_preview").width = DRAW.PREVIEW_SIZE.w;
document.getElementById("canvas_preview").height = DRAW.PREVIEW_SIZE.h;
var color_rgb = HELPER.hex2rgb(COLOUR);
GUI.draw_background(canvas_back, WIDTH, HEIGHT);
document.getElementById("canvas_preview").width = GUI.PREVIEW_SIZE.w;
document.getElementById("canvas_preview").height = GUI.PREVIEW_SIZE.h;
var color_rgb = HELPER.hex2rgb(COLOR);
document.getElementById("rgb_r").value = color_rgb.r;
document.getElementById("rgb_g").value = color_rgb.g;
document.getElementById("rgb_b").value = color_rgb.b;
document.getElementById("rgb_a").value = ALPHA;
DRAW.redraw_preview();
GUI.redraw_preview();
//detect color support
if(HELPER.chech_input_color_support('main_colour') == true)
document.getElementById("main_colour").value = COLOUR; //supported
else{
if (HELPER.chech_input_color_support('main_colour') == true)
document.getElementById("main_colour").value = COLOR; //supported
else {
//not supported
document.getElementById("main_colour").style.display = 'none';
document.getElementById("main_colour_alt").style.display = '';
document.getElementById("main_colour_alt").style.backgroundColor = COLOUR;
}
document.getElementById("main_colour_alt").style.backgroundColor = COLOR;
}
canvas_grid.globalAlpha = 0.8;
};
this.save_state = function(){
undo_level = 0;
j = 0;
//move previous
LAYERS_ARCHIVE[2] = LAYERS_ARCHIVE[1];
LAYERS_ARCHIVE[1] = LAYERS_ARCHIVE[0];
//save last state
LAYERS_ARCHIVE[j] = {};
LAYERS_ARCHIVE[j].width = WIDTH;
LAYERS_ARCHIVE[j].height = HEIGHT;
LAYERS_ARCHIVE[j].data = {};
for(var i in LAYERS){
LAYERS_ARCHIVE[j].data[LAYERS[i].name] = document.createElement('canvas');
LAYERS_ARCHIVE[j].data[LAYERS[i].name].width = WIDTH;
LAYERS_ARCHIVE[j].data[LAYERS[i].name].height = HEIGHT;
LAYERS_ARCHIVE[j].data[LAYERS[i].name].getContext('2d').drawImage(document.getElementById(LAYERS[i].name), 0, 0);
}
return true;
};
//supports 3 levels undo system - more levels requires more memory - max 1 gb?
this.undo = function(){
if(LAYERS_ARCHIVE.length == 0) return false;
j = undo_level;
undo_level++;
if(LAYERS_ARCHIVE[j] == undefined || LAYERS_ARCHIVE[j].width == undefined) return false;
if(WIDTH != LAYERS_ARCHIVE[j].width || HEIGHT != LAYERS_ARCHIVE[j].height){
WIDTH = LAYERS_ARCHIVE[j].width;
HEIGHT = LAYERS_ARCHIVE[j].height;
RATIO = WIDTH/HEIGHT;
LAYER.set_canvas_size(true);
return true; //size changed, cant undo
}
//undo
for(var i in LAYERS){
if(LAYERS_ARCHIVE[j].data[LAYERS[i].name] != undefined){
document.getElementById(LAYERS[i].name).getContext("2d").clearRect(0, 0, WIDTH, HEIGHT);
document.getElementById(LAYERS[i].name).getContext("2d").drawImage(LAYERS_ARCHIVE[j].data[LAYERS[i].name], 0, 0);
}
}
DRAW.zoom();
return true;
};
this.load_xml = function(data){
var xml = $.parseXML(data);
w = $(xml).find("width").text();
h = $(xml).find("height").text();
//delete old layers
for(var i in LAYERS)
LAYER.layer_remove(i);
//init new file
ZOOM = 100;
MAIN.init();
//set attributes
WIDTH = w;
HEIGHT = h;
RATIO = WIDTH/HEIGHT;
LAYER.set_canvas_size();
//add layers
$('layer', xml).each(function(i){
var name = $(this).find("name").text();
var visible = $(this).find("visible").text();
var opacity = $(this).find("opacity").text();
if(i > 0){ //first layer exists by default - Background
LAYER.layer_add(name);
//update attributes
LAYERS[LAYER.layer_active].name = name;
if(visible == 0)
LAYER.layer_visibility(LAYER.layer_active);
LAYERS[LAYER.layer_active].opacity = opacity;
}
});
LAYER.layer_renew();
//add data
$('data', xml).each(function(i){
var name = $(this).find("name").text();
var data = $(this).find("data").text();
var img = new Image();
img.src = data;
img.onload = function(){
document.getElementById(name).getContext('2d').drawImage(img, 0, 0);
LAYER.layer_renew();
DRAW.zoom();
};
});
};
}
};
}

File diff suppressed because it is too large Load Diff

View File

@ -1,430 +0,0 @@
/*
Usage:
var POP = new popup();
POP.add({name: "param1", title: "Value1:" });
POP.add(...);
POP.show('title', main_handler, 'preview_handler', 'onload_handler');
POP.add() parameters:
name type example
---------------------------------------------------------------
name string 'parameter1'
title string 'Enter value:'
type string 'select', 'textarea', 'color'
value string '314'
values array fo strings ['One', 'Two', 'Three']
range numbers interval [0, 255]
step int/float 1
placeholder text 'Enter number here'
html html text '<b>bold</b>'
function function 'cutom_function'
onchange function 'CLASS.onchange_function'
*/
/* global HELPER, MENU, DRAW, POP, LAYER */
/* global FILTERS_LIST, LAYERS, canvas_front, WIDTH, HEIGHT */
var POP = new popup();
function popup(){
this.active = false;
this.handler = '';
this.preview = false;
this.onload = false;
this.width_mini = 195;
this.height_mini = 195;
this.preview_in_main = false;
this.effects = false;
this.id = 0;
var parameters = [];
var layer_active_small = document.createElement("canvas");
var layer_active_small_ctx = layer_active_small.getContext("2d");
this.constructor = new function(){
var dim = HELPER.get_dimensions();
popup = document.getElementById('popup');
popup.style.top = 150+'px';
popup.style.left = Math.round(dim[0]/2)+'px';
};
//add parameter
this.add = function(object){
parameters.push(object);
};
//show popup window
this.show = function(title, handler, preview_handler, onload_handler){
POP.id = HELPER.getRandomInt(0, 999999999);
if(this.active == true){
this.hide();
return false;
}
this.active = true;
this.handler = handler;
if(preview_handler != undefined)
this.preview = preview_handler;
if(onload_handler != undefined)
this.onload = onload_handler;
var html = '';
var dim = HELPER.get_dimensions();
popup = document.getElementById('popup');
popup.style.top = 150+'px';
popup.style.left = Math.round(dim[0]/2)+'px';
if(this.effects == true){
var index;
for(var i=0; i<FILTERS_LIST.length; i++){
if(FILTERS_LIST[i].name == MENU.last_menu){
index = i;
break;
}
}
var prev_index = index-1;
if(prev_index < 0){
prev_index = 0;
}
var next_index = index+1;
if(next_index > FILTERS_LIST.length-1){
next_index = FILTERS_LIST.length-1;
}
html += '<span style="float:right;">';
html += '<input id="previous_filter" type="button" value="&lt;"> ';
html += '<select id="effect_browser">';
html += '<option value="">--- Select effect ---</option>';
for(var i=0; i<FILTERS_LIST.length; i++){
var selected = '';
if(FILTERS_LIST[i].name == MENU.last_menu)
var selected = 'selected';
html += ' <option ' + selected +' value="' + i + '">' + FILTERS_LIST[i].title + '</option>';
}
html += '</select>';
html += ' <input id="next_filter" onclick="" type="button" value="&gt;"> ';
html += '</span>';
}
html += '<h2 id="popup_drag">'+title+'</h2>';
//preview area
if(this.preview !== false && this.preview_in_main == false){
html += '<div style="margin-top:15px;margin-bottom:15px;">';
html += '<canvas style="position:relative;float:left;margin-right:5px;border:1px solid #393939;" width="'+POP.width_mini+'" height="'+POP.height_mini+'" id="pop_pre"></canvas>';
html += '<canvas style="position:relative;border:1px solid #393939;background-color:#ffffff;" width="'+POP.width_mini+'" height="'+POP.height_mini+'" id="pop_post"></canvas>';
html += '</div>';
}
//settings
html += '<table style="width:99%;">';
for(var i in parameters){
var parameter = parameters[i];
html += '<tr>';
if(title != 'Error')
html += '<td style="font-weight:bold;padding-right:3px;width:130px;">'+parameter.title+'</td>';
if(parameter.name != undefined){
if(parameter.values != undefined){
var onchange = '';
if(parameter.onchange != undefined)
onchange = ' onchange="'+parameter.onchange+';" ';
if(parameter.values.length > 10 || parameter.type == 'select'){
//drop down
if(onchange == '' && preview_handler != undefined)
onchange = ' onchange="POP.view();" ';
html += '<td colspan="2"><select '+onchange+' style="font-size:12px;" id="pop_data_'+parameter.name+'">';
var k = 0;
for(var j in parameter.values){
var sel = '';
if(parameter.value == parameter.values[j])
sel = 'selected="selected"';
if(parameter.value == undefined && k == 0)
sel = 'selected="selected"';
html += '<option '+sel+' name="'+parameter.values[j]+'">'+parameter.values[j]+'</option>';
k++;
}
html += '</select></td>';
}
else{
//radio
html += '<td colspan="2">';
if(parameter.values.length > 2)
html += '<div class="group">';
var k = 0;
for(var j in parameter.values){
var ch = '';
if(parameter.value == parameter.values[j])
ch = 'checked="checked"';
if(parameter.value == undefined && k == 0)
ch = 'checked="checked"';
if(onchange == '' && preview_handler != undefined)
onchange = ' onchange="POP.view();" ';
html += '<input type="radio" '+onchange+' '+ch+' name="'+parameter.name+'" id="pop_data_'+parameter.name+"_poptmp"+j+'" value="'+parameter.values[j]+'">';
html += '<label style="margin-right:20px;" for="pop_data_'+parameter.name+"_poptmp"+j+'">'+parameter.values[j]+'</label>';
if(parameter.values.length > 2)
html += '<br />';
k++;
}
if(parameter.values.length > 2)
html += '</div>';
html += '</td>';
}
}
else if(parameter.value != undefined){
//input, range, textarea, color
var step = 1;
if(parameter.step != undefined)
step = parameter.step;
if(parameter.range != undefined){
//range
var preview_code = '';
if(this.preview !== false)
preview_code = 'POP.view();';
html += '<td><input type="range" id="pop_data_'+parameter.name+'" value="'+parameter.value+'" min="'+parameter.range[0]+'" max="'+parameter.range[1]+'" step="'+step+'" " oninput="document.getElementById(\'pv'+i+'\').innerHTML=Math.round(this.value*100)/100;'+preview_code+'" /></td>';
html += '<td style="padding-left:10px;width:50px;" id="pv'+i+'">'+parameter.value+'</td>';
}
else if(parameter.type == 'color'){
//color
html += '<td><input type="color" id="pop_data_'+parameter.name+'" value="'+parameter.value+'" /></td>';
}
else{
//input or textarea
if(parameter.placeholder == undefined)
parameter.placeholder = '';
if(parameter.type == 'textarea')
html += '<td><textarea style="height:80px;" id="pop_data_'+parameter.name+'" placeholder="'+parameter.placeholder+'">'+parameter.value+'</textarea></td>';
else
html += '<td colspan="2"><input type="text" id="pop_data_'+parameter.name+'" value="'+parameter.value+'" placeholder="'+parameter.placeholder+'" onkeyup="POP.validate(this);" /></td>';
}
}
}
else if(parameter.function != undefined){
//custom function
if(typeof parameter.function == 'string')
var result = window[parameter.function]();
else
var result = parameter.function();
html += '<td colspan="3">'+result+'</td>';
}
else if(parameter.html != undefined){
//html
html += '<td style="padding-bottom:3px;padding-top:3px;" colspan="2">'+parameter.html+'</td>';
}
else{
//locked fields
str = ""+parameter.value;
var id_tmp = parameter.title.toLowerCase().replace(/[^\w]+/g,'').replace(/ +/g,'-');
id_tmp = id_tmp.substring(0, 10);
if(str.length < 40)
html += '<td colspan="2"><input style="color:#393939;" disabled="disabled" type="text" id="pop_data_'+id_tmp+'" value="'+parameter.value+'" /></td>';
else
html += '<td style="font-size:11px;" colspan="2"><textarea disabled="disabled">'+parameter.value+'</textarea></td>';
}
html += '</tr>';
}
html += '</table>';
//action buttons
html += '<div style="text-align:center;margin-top:20px;margin-bottom:15px;">';
html += '<input type="button" onclick="POP.save();" class="button" value="OK" />';
html += '<input type="button" onclick="POP.hide();" class="button" value="Cancel" />';
if(this.preview_in_main !== false)
html += '<input type="button" onclick="POP.view();" class="button" value="Preview" />';
html += '</div>';
document.getElementById("popup").innerHTML = html;
document.getElementById("popup").style.display="block";
if(parameters.length > 15)
document.getElementById("popup").style.overflowY="scroll";
else
document.getElementById("popup").style.overflowY='hidden';
//onload
if(this.onload != ''){
if(typeof this.onload == "string")
window[this.onload]();
else
this.onload();
}
//some events for effects browser
if(this.effects == true){
document.getElementById('previous_filter').disabled = false;
document.getElementById('next_filter').disabled = false;
if(index == 0){
document.getElementById('previous_filter').disabled = true;
}
if(index == FILTERS_LIST.length-1){
document.getElementById('next_filter').disabled = true;
}
//previous
document.getElementById('previous_filter').addEventListener('click', function(event){
POP.hide();
MENU.last_menu = FILTERS_LIST[prev_index].name;
MENU.do_menu([FILTERS_LIST[prev_index].name]);
});
//next
document.getElementById('next_filter').addEventListener('click', function(event){
POP.hide();
MENU.last_menu = FILTERS_LIST[next_index].name;
MENU.do_menu([FILTERS_LIST[next_index].name]);
});
//onchange
var effect_browser = document.getElementById('effect_browser');
effect_browser.addEventListener('change', function(event){
var value = effect_browser.options[effect_browser.selectedIndex].value;
POP.hide();
MENU.last_menu = FILTERS_LIST[value].name;
MENU.do_menu([FILTERS_LIST[value].name]);
});
}
//load preview?
if(this.preview !== false && this.preview_in_main == false){
//original
var pop_pre = document.getElementById("pop_pre").getContext("2d");
pop_pre.rect(0, 0, POP.width_mini, POP.height_mini);
pop_pre.fillStyle = "#ffffff";
pop_pre.fill();
DRAW.draw_background(pop_pre, POP.width_mini, POP.height_mini, 5);
pop_pre.drawImage(document.getElementById(LAYERS[LAYER.layer_active].name), 0, 0, POP.width_mini, POP.height_mini);
//copy
pop_post = document.getElementById("pop_post").getContext("2d");
pop_post.rect(0, 0, POP.width_mini, POP.height_mini);
pop_post.fillStyle = "#ffffff";
pop_post.fill();
DRAW.draw_background(pop_post, POP.width_mini, POP.height_mini, 5);
pop_post.drawImage(document.getElementById(LAYERS[LAYER.layer_active].name), 0, 0, POP.width_mini, POP.height_mini);
//prepare temp canvas
layer_active_small.width = POP.width_mini;
layer_active_small.height = POP.height_mini;
layer_active_small_ctx.drawImage(document.getElementById(LAYERS[LAYER.layer_active].name), 0, 0, POP.width_mini, POP.height_mini);
POP.view();
}
};
//hide popup
this.hide = function(){
document.getElementById('popup').style.display='none';
parameters = [];
this.handler = '';
this.active = false;
this.preview = false;
this.onload = false;
this.preview_in_main = false;
this.effects = false;
canvas_front.clearRect(0, 0, WIDTH, HEIGHT);
};
//renders preview. If input=range supported, is called on every param update - must be fast...
this.view = function(){
if(this.preview !== false){
if(this.preview_in_main == false){
//reset mini view
pop_post.clearRect(0, 0, POP.width_mini, POP.height_mini);
pop_post.drawImage(layer_active_small, 0, 0);
}
//prepare
var response = {};
inputs = document.getElementsByTagName('input');
for (i = 0; i<inputs.length; i++){
if(inputs[i].id.substr(0,9)=='pop_data_'){
var key = inputs[i].id.substr(9);
if(HELPER.strpos(key, "_poptmp") != false)
key = key.substring(0, HELPER.strpos(key, "_poptmp"));
var value = inputs[i].value;
if(inputs[i].type == 'radio'){
if(inputs[i].checked==true)
response[key] = value;
}
else
response[key] = value;
}
}
selects = document.getElementsByTagName('select');
for (i = 0; i<selects.length; i++) {
if(selects[i].id.substr(0,9)=='pop_data_'){
var key = selects[i].id.substr(9);
var value = selects[i].value;
response[key] = value;
}
}
textareas = document.getElementsByTagName('textarea');
for (i = 0; i<textareas.length; i++){
if(textareas[i].id.substr(0,9)=='pop_data_'){
var key = textareas[i].id.substr(9);
var value = textareas[i].value;
response[key] = value;
}
}
//call handler
if(this.preview_in_main == false)
this.preview(response, pop_post, POP.width_mini, POP.height_mini);
else
this.preview(response);
}
};
//OK pressed - prepare data and call handlers
this.save = function(){
this.active = false;
document.getElementById("popup").style.display="none";
var response={};
inputs = document.getElementsByTagName('input');
for (i = 0; i<inputs.length; i++){
if(inputs[i].id.substr(0,9)=='pop_data_'){
var key = inputs[i].id.substr(9);
if(HELPER.strpos(key, "_poptmp") != false)
key = key.substring(0, HELPER.strpos(key, "_poptmp"));
var value = inputs[i].value;
if(inputs[i].type == 'radio'){
if(inputs[i].checked==true)
response[key] = value;
}
else
response[key] = value;
}
}
selects = document.getElementsByTagName('select');
for (i = 0; i<selects.length; i++) {
if(selects[i].id.substr(0,9)=='pop_data_'){
var key = selects[i].id.substr(9);
var value = selects[i].value;
response[key] = value;
}
}
textareas = document.getElementsByTagName('textarea');
for (i = 0; i<textareas.length; i++){
if(textareas[i].id.substr(0,9)=='pop_data_'){
var key = textareas[i].id.substr(9);
var value = textareas[i].value;
response[key] = value;
}
}
parameters = [];
this.preview = false;
this.onload = false;
this.preview_in_main = false;
this.effects = false;
if(this.handler != ''){
if(typeof this.handler == "string")
window[this.handler](response);
else
this.handler(response);
}
this.handler = '';
};
//validate input field, unless browser supports input=range
this.validate = function(field){
for(var i in parameters){
var parameter = parameters[i];
if("pop_data_"+parameter.name == field.id && parameter.range != undefined){
if(field.value == '-' || field.value == '') return true;
var value = parseFloat(field.value);
if(isNaN(value) || value != field.value)
field.value = parameter.value; //not number
if(value < parameter.range[0])
field.value = parameter.range[0]; //less then min
else if(value > parameter.range[1])
field.value = parameter.range[1]; //more then max
}
}
};
}

View File

@ -1,90 +0,0 @@
//canvas layers
var canvas_back = document.getElementById("canvas_back").getContext("2d"); //layer for grid/transparency
var canvas_main = document.getElementById("Background").getContext("2d"); //background
//new layers insert convas here
var canvas_front = document.getElementById("canvas_front").getContext("2d"); //tmp layer
var canvas_grid = document.getElementById("canvas_grid").getContext("2d"); //grid layer
var canvas_preview = document.getElementById("canvas_preview").getContext("2d"); //mini preview
//settings
var AUTHOR = 'ViliusL';
var EMAIL = 'www.viliusl@gmail.com';
var VERSION = '2.4';
var WIDTH = 800; //canvas midth
var HEIGHT = 600; //canvas height
var RATIO = WIDTH/HEIGHT; //width & height ratio
var LAYERS = []; //layers data
var ACTION = 'select_tool'; ///default action
var COLOUR = '#0000ff'; //current color
var ZOOM = 100; //zoom level 10 - infinity
var ALPHA = 255; //default alpha
var SAVE_NAME = 'example'; //default save name
var SAVE_TYPES = [
"PNG - Portable Network Graphics", //default
"JPG - JPG/JPEG Format", //autodetect on photos where png useless?
"XML - Full layers data", //aka PSD
"BMP - Windows Bitmap", //firefox only, useless?
"WEBP - Weppy File Format", //chrome only
];
var ACTION_DATA = [
{name: 'select_tool', title: 'Select object tool', icon: ['all.png', 0+7, 2], attributes: {} },
{name: 'select_square', title: 'Select area tool', icon: ['all.png', -50+4, 5], attributes: {} },
{name: 'magic_wand', title: 'Magic Wand Tool', icon: ['all.png', -150+1, -50+2], attributes: {sensitivity: 40, anti_aliasing: true} },
{name: 'erase', title: 'Erase', icon: ['all.png', -100+3, 4], attributes: {size: 20, circle: true, strict: true} },
{name: 'fill', title: 'Fill', icon: ['all.png', -150+3, 3], attributes: {sensitivity: 0, anti_aliasing: false} },
{name: 'pick_color', title: 'Pick Color', icon: ['all.png', -200+3, 3], attributes: {} },
{name: 'pencil', title: 'Pencil', icon: ['all.png', -250+3, 3], attributes: {} },
{name: 'line', title: 'Draw line', icon: ['all.png', -300+3, 3], attributes: {size: 1, type_values: ['Simple', 'Multi-line', 'Arrow', 'Curve'] } },
{name: 'letters', title: 'Draw letters', icon: ['all.png', -350+3, 4], attributes: {} },
{name: 'draw_square', title: 'Draw rectangle', icon: ['all.png', -400+3, 5], attributes: {fill: false, square: false, round: 0} },
{name: 'draw_circle', title: 'Draw circle', icon: ['all.png', -450+3, 5], attributes: {fill: false, circle: false} },
{name: 'brush', title: 'Brush', icon: ['all.png', -500+6, 3], attributes: {type: 'Brush', type_values: ['Brush', 'BezierCurve', 'Chrome', 'Fur', 'Grouped', 'Shaded', 'Sketchy'], size: 5, anti_alias: false }, on_update: 'update_brush', },
{name: 'blur_tool', title: 'Blur tool', icon: ['all.png', -250+5, -50+2], attributes: {size: 30, strength: 1} },
{name: 'sharpen_tool', title: 'Sharpen tool', icon: ['all.png', -300+5, -50+2], attributes: {size: 30, strength: 0.5} },
{name: 'burn_dodge_tool', title: 'Burn/Dodge tool', icon: ['all.png', -500+3, -50+4], attributes: {burn: true, size: 30, power: 50} },
{name: 'desaturate_tool', title: 'Desaturate', icon: ['all.png', -550+3, -00+4], attributes: {size: 50, anti_alias: true} },
{name: 'clone_tool', title: 'Clone tool', icon: ['all.png', -350+4, -50+3], attributes: {size: 30, anti_alias: true} },
{name: 'gradient_tool', title: 'Gradient', icon: ['all.png', -400+3, -50+4], attributes: {radial: false, power: 50} },
{name: 'crop_tool', title: 'Crop', icon: ['all.png', -450+2, -50+2], attributes: { } },
];
var CREDITS = [
{title: 'Brush styles', name: 'Harmony', link: 'http://ricardocabello.com/blog/post/689' },
{title: 'Effects library', name: 'glfx.js', link: 'http://evanw.github.io/glfx.js/' },
{title: 'EXIF', name: 'exif.js', link: 'https://github.com/jseidelin/exif-js' },
{title: 'Image filters', name: 'ImageFilters.js',link: 'https://github.com/arahaya/ImageFilters.js' },
{title: 'KD-tree', name: 'kdtree.js', link: 'http://jsdo.it/peko/wKvk' },
];
var FILTERS_LIST = [
{title: 'Black and White', name: 'effects_bw' },
{title: 'Blur-Box', name: 'effects_BoxBlur' },
{title: 'Blur-Gaussian', name: 'effects_GaussianBlur' },
{title: 'Blur-Stack', name: 'effects_StackBlur' },
{title: 'Blur-Zoom', name: 'effects_zoomblur' },
{title: 'Bulge/Pinch', name: 'effects_bulge_pinch' },
{title: 'Colorize', name: 'effects_colorize' },
{title: 'Denoise', name: 'effects_denoise' },
{title: 'Desaturate', name: 'effects_Desaturate' },
{title: 'Dither', name: 'effects_Dither' },
{title: 'Dot Screen', name: 'effects_dot_screen' },
{title: 'Edge', name: 'effects_Edge' },
{title: 'Emboss', name: 'effects_Emboss' },
{title: 'Enrich', name: 'effects_Enrich' },
{title: 'Gamma', name: 'effects_Gamma' },
{title: 'Grains', name: 'effects_Grains' },
{title: 'Heatmap', name: 'effects_heatmap' },
{title: 'HSL Adjustment', name: 'effects_HSLAdjustment' },
{title: 'JPG Compression', name: 'effects_jpg_vintage' },
{title: 'Mosaic', name: 'effects_Mosaic' },
{title: 'Oil', name: 'effects_Oil' },
{title: 'Posterize', name: 'effects_Posterize' },
{title: 'Sepia', name: 'effects_Sepia' },
{title: 'Sharpen', name: 'effects_Sharpen' },
{title: 'Solarize', name: 'effects_Solarize' },
{title: 'Tilt Shift', name: 'effects_tilt_shift' },
{title: 'Vignette', name: 'effects_vignette' },
{title: 'Vintage', name: 'effects_vintage' },
];

File diff suppressed because it is too large Load Diff

View File

@ -254,7 +254,6 @@ ImageFilters.utils = {
};
// TODO
ImageFilters.Translate = function (srcImageData, x, y, interpolation) {
};
@ -1181,15 +1180,11 @@ ImageFilters.Desaturate = function (srcImageData) {
return dstImageData;
};
/**
* TODO: use bilinear
*/
ImageFilters.DisplacementMapFilter = function (srcImageData, mapImageData, mapX, mapY, componentX, componentY, scaleX, scaleY, mode) {
var srcPixels = srcImageData.data,
srcWidth = srcImageData.width,
srcHeight = srcImageData.height,
srcLength = srcPixels.length,
// dstImageData = this.utils.createImageData(srcWidth, srcHeight),
dstImageData = ImageFilters.Clone(srcImageData),
dstPixels = dstImageData.data;
@ -1993,7 +1988,6 @@ ImageFilters.Twril = function (srcImageData, centerX, centerY, radius, angle, ed
} else {
// nearest neighbor
// round tx, ty
// TODO edge actions!!
srcIndex = ((ty + 0.5 | 0) * srcWidth + (tx + 0.5 | 0)) << 2;
dstPixels[dstIndex] = srcPixels[srcIndex];
dstPixels[dstIndex + 1] = srcPixels[srcIndex + 1];

9
libs/jquery.js vendored

File diff suppressed because one or more lines are too long

434
libs/popup.js Normal file
View File

@ -0,0 +1,434 @@
/* global MAIN, HELPER, POP, LAYER, EFFECTS, GUI */
/* global canvas_front, WIDTH, HEIGHT */
var POP = new popup();
/**
* user dialogs library
*
* @author ViliusL
*
* Usage:
* var POP = new popup();
* POP.add({name: "param1", title: "Value1:" });
* POP.add(...);
* POP.show('title', main_handler, preview_handler, onload_handler);
*
* POP.add() parameters:
* - name type example
* - ---------------------------------------------------------------
* - name string 'parameter1'
* - title string 'Enter value:'
* - type string 'select', 'textarea', 'color'
* - value string '314'
* - values array fo strings ['One', 'Two', 'Three']
* - range numbers interval [0, 255]
* - step int/float 1
* - placeholder text 'Enter number here'
* - html html text '<b>bold</b>'
* - function function 'cutom_function'
* - onchange function 'CLASS.onchange_function'
*/
function popup() {
this.active = false;
this.handler = '';
this.preview = false;
this.onload = false;
this.width_mini = 184;
this.height_mini = 195;
this.preview_in_main = false;
this.effects = false;
this.id = 0;
var parameters = [];
var layer_active_small = document.createElement("canvas");
var layer_active_small_ctx = layer_active_small.getContext("2d");
//add parameter
this.add = function (object) {
parameters.push(object);
};
//show popup window
this.show = function (title, handler, preview_handler, onload_handler) {
POP.id = HELPER.getRandomInt(0, 999999999);
if (this.active == true) {
this.hide();
return false;
}
this.active = true;
this.handler = handler;
if (preview_handler != undefined)
this.preview = preview_handler;
if (onload_handler != undefined)
this.onload = onload_handler;
var html = '';
var dim = HELPER.get_dimensions();
popup = document.getElementById('popup');
popup.style.top = 150 + 'px';
popup.style.left = Math.round(dim[0] / 2) + 'px';
if (this.effects == true) {
var index;
for (var i = 0; i < EFFECTS.FILTERS_LIST.length; i++) {
if (EFFECTS.FILTERS_LIST[i].name == GUI.last_menu) {
index = i;
break;
}
}
var prev_index = index - 1;
if (prev_index < 0) {
prev_index = 0;
}
var next_index = index + 1;
if (next_index > EFFECTS.FILTERS_LIST.length - 1) {
next_index = EFFECTS.FILTERS_LIST.length - 1;
}
html += '<span style="float:right;">';
html += '<input id="previous_filter" type="button" value="&lt;"> ';
html += '<select id="effect_browser">';
html += '<option value="">--- Select effect ---</option>';
for (var i = 0; i < EFFECTS.FILTERS_LIST.length; i++) {
var selected = '';
if (EFFECTS.FILTERS_LIST[i].name == GUI.last_menu)
var selected = 'selected';
html += ' <option ' + selected + ' value="' + i + '">' + EFFECTS.FILTERS_LIST[i].title + '</option>';
}
html += '</select>';
html += ' <input id="next_filter" onclick="" type="button" value="&gt;"> ';
html += '</span>';
}
html += '<h2 id="popup_drag">' + title + '</h2>';
//preview area
if (this.preview !== false && this.preview_in_main == false) {
html += '<div style="margin-top:15px;margin-bottom:15px;">';
html += '<canvas style="position:relative;float:left;margin-right:5px;border:1px solid #393939;" width="' + POP.width_mini + '" height="' + POP.height_mini + '" id="pop_pre"></canvas>';
html += '<canvas style="position:relative;border:1px solid #393939;background-color:#ffffff;" width="' + POP.width_mini + '" height="' + POP.height_mini + '" id="pop_post"></canvas>';
html += '</div>';
}
//settings
html += '<table style="width:99%;">';
for (var i in parameters) {
var parameter = parameters[i];
html += '<tr>';
if (title != 'Error')
html += '<td style="font-weight:bold;padding-right:3px;width:130px;">' + parameter.title + '</td>';
if (parameter.name != undefined) {
if (parameter.values != undefined) {
var onchange = '';
if (parameter.onchange != undefined)
onchange = ' onchange="' + parameter.onchange + ';" ';
if (parameter.values.length > 10 || parameter.type == 'select') {
//drop down
if (onchange == '' && preview_handler != undefined)
onchange = ' onchange="POP.view();" ';
html += '<td colspan="2"><select ' + onchange + ' style="font-size:12px;" id="pop_data_' + parameter.name + '">';
var k = 0;
for (var j in parameter.values) {
var sel = '';
if (parameter.value == parameter.values[j])
sel = 'selected="selected"';
if (parameter.value == undefined && k == 0)
sel = 'selected="selected"';
html += '<option ' + sel + ' name="' + parameter.values[j] + '">' + parameter.values[j] + '</option>';
k++;
}
html += '</select></td>';
}
else {
//radio
html += '<td colspan="2">';
if (parameter.values.length > 2)
html += '<div class="group">';
var k = 0;
for (var j in parameter.values) {
var ch = '';
if (parameter.value == parameter.values[j])
ch = 'checked="checked"';
if (parameter.value == undefined && k == 0)
ch = 'checked="checked"';
if (onchange == '' && preview_handler != undefined)
onchange = ' onchange="POP.view();" ';
html += '<input type="radio" ' + onchange + ' ' + ch + ' name="' + parameter.name + '" id="pop_data_' + parameter.name + "_poptmp" + j + '" value="' + parameter.values[j] + '">';
html += '<label style="margin-right:20px;" for="pop_data_' + parameter.name + "_poptmp" + j + '">' + parameter.values[j] + '</label>';
if (parameter.values.length > 2)
html += '<br />';
k++;
}
if (parameter.values.length > 2)
html += '</div>';
html += '</td>';
}
}
else if (parameter.value != undefined) {
//input, range, textarea, color
var step = 1;
if (parameter.step != undefined)
step = parameter.step;
if (parameter.range != undefined) {
//range
var preview_code = '';
if (this.preview !== false)
preview_code = 'POP.view();';
html += '<td><input type="range" id="pop_data_' + parameter.name + '" value="' + parameter.value + '" min="' + parameter.range[0] + '" max="' + parameter.range[1] + '" step="' + step + '" " oninput="document.getElementById(\'pv' + i + '\').innerHTML=Math.round(this.value*100)/100;' + preview_code + '" /></td>';
html += '<td style="padding-left:10px;width:50px;" id="pv' + i + '">' + parameter.value + '</td>';
}
else if (parameter.type == 'color') {
//color
html += '<td><input type="color" id="pop_data_' + parameter.name + '" value="' + parameter.value + '" /></td>';
}
else {
//input or textarea
if (parameter.placeholder == undefined)
parameter.placeholder = '';
if (parameter.type == 'textarea')
html += '<td><textarea style="height:80px;" id="pop_data_' + parameter.name + '" placeholder="' + parameter.placeholder + '">' + parameter.value + '</textarea></td>';
else
html += '<td colspan="2"><input type="text" id="pop_data_' + parameter.name + '" value="' + parameter.value + '" placeholder="' + parameter.placeholder + '" onkeyup="POP.validate(this);" /></td>';
}
}
}
else if (parameter.function != undefined) {
//custom function
if (typeof parameter.function == 'string')
var result = window[parameter.function]();
else
var result = parameter.function();
html += '<td colspan="3">' + result + '</td>';
}
else if (parameter.html != undefined) {
//html
html += '<td style="padding-bottom:3px;padding-top:3px;" colspan="2">' + parameter.html + '</td>';
}
else {
//locked fields
str = "" + parameter.value;
var id_tmp = parameter.title.toLowerCase().replace(/[^\w]+/g, '').replace(/ +/g, '-');
id_tmp = id_tmp.substring(0, 10);
if (str.length < 40)
html += '<td colspan="2"><input style="color:#393939;" disabled="disabled" type="text" id="pop_data_' + id_tmp + '" value="' + parameter.value + '" /></td>';
else
html += '<td style="font-size:11px;" colspan="2"><textarea disabled="disabled">' + parameter.value + '</textarea></td>';
}
html += '</tr>';
}
html += '</table>';
//action buttons
html += '<div style="text-align:center;margin-top:20px;margin-bottom:15px;">';
html += '<input type="button" onclick="POP.save();" class="button" value="OK" />';
html += '<input type="button" onclick="POP.hide();" class="button" value="Cancel" />';
if (this.preview_in_main !== false)
html += '<input type="button" onclick="POP.view();" class="button" value="Preview" />';
html += '</div>';
document.getElementById("popup").innerHTML = html;
document.getElementById("popup").style.display = "block";
if (parameters.length > 15)
document.getElementById("popup").style.overflowY = "scroll";
else
document.getElementById("popup").style.overflowY = 'hidden';
//onload
if (this.onload != '') {
if (typeof this.onload == "string")
window[this.onload]();
else
this.onload();
}
//some events for effects browser
if (this.effects == true) {
document.getElementById('previous_filter').disabled = false;
document.getElementById('next_filter').disabled = false;
if (index == 0) {
document.getElementById('previous_filter').disabled = true;
}
if (index == EFFECTS.FILTERS_LIST.length - 1) {
document.getElementById('next_filter').disabled = true;
}
//previous
document.getElementById('previous_filter').addEventListener('click', function (event) {
POP.hide();
GUI.last_menu = EFFECTS.FILTERS_LIST[prev_index].name;
call_menu(EFFECTS, EFFECTS.FILTERS_LIST[prev_index].name);
});
//next
document.getElementById('next_filter').addEventListener('click', function (event) {
POP.hide();
GUI.last_menu = EFFECTS.FILTERS_LIST[next_index].name;
call_menu(EFFECTS, EFFECTS.FILTERS_LIST[next_index].name);
});
//onchange
var effect_browser = document.getElementById('effect_browser');
effect_browser.addEventListener('change', function (event) {
var value = effect_browser.options[effect_browser.selectedIndex].value;
POP.hide();
GUI.last_menu = EFFECTS.FILTERS_LIST[value].name;
call_menu(EFFECTS, EFFECTS.FILTERS_LIST[value].name);
});
}
//load preview?
if (this.preview !== false && this.preview_in_main == false) {
//original
var pop_pre = document.getElementById("pop_pre").getContext("2d");
pop_pre.rect(0, 0, POP.width_mini, POP.height_mini);
pop_pre.fillStyle = "#ffffff";
pop_pre.fill();
GUI.draw_background(pop_pre, POP.width_mini, POP.height_mini, 5);
pop_pre.drawImage(document.getElementById(LAYER.layers[LAYER.layer_active].name), 0, 0, POP.width_mini, POP.height_mini);
//copy
pop_post = document.getElementById("pop_post").getContext("2d");
pop_post.rect(0, 0, POP.width_mini, POP.height_mini);
pop_post.fillStyle = "#ffffff";
pop_post.fill();
GUI.draw_background(pop_post, POP.width_mini, POP.height_mini, 5);
pop_post.drawImage(document.getElementById(LAYER.layers[LAYER.layer_active].name), 0, 0, POP.width_mini, POP.height_mini);
//prepare temp canvas
layer_active_small.width = POP.width_mini;
layer_active_small.height = POP.height_mini;
layer_active_small_ctx.drawImage(document.getElementById(LAYER.layers[LAYER.layer_active].name), 0, 0, POP.width_mini, POP.height_mini);
POP.view();
}
};
//hide popup
this.hide = function () {
document.getElementById('popup').style.display = 'none';
parameters = [];
this.handler = '';
this.active = false;
this.preview = false;
this.onload = false;
this.preview_in_main = false;
this.effects = false;
canvas_front.clearRect(0, 0, WIDTH, HEIGHT);
};
//renders preview. If input=range supported, is called on every param update - must be fast...
this.view = function () {
if (this.preview !== false) {
if (this.preview_in_main == false) {
//reset mini view
pop_post.clearRect(0, 0, POP.width_mini, POP.height_mini);
pop_post.drawImage(layer_active_small, 0, 0);
}
//prepare
var response = {};
inputs = document.getElementsByTagName('input');
for (i = 0; i < inputs.length; i++) {
if (inputs[i].id.substr(0, 9) == 'pop_data_') {
var key = inputs[i].id.substr(9);
if (HELPER.strpos(key, "_poptmp") != false)
key = key.substring(0, HELPER.strpos(key, "_poptmp"));
var value = inputs[i].value;
if (inputs[i].type == 'radio') {
if (inputs[i].checked == true)
response[key] = value;
}
else
response[key] = value;
}
}
selects = document.getElementsByTagName('select');
for (i = 0; i < selects.length; i++) {
if (selects[i].id.substr(0, 9) == 'pop_data_') {
var key = selects[i].id.substr(9);
var value = selects[i].value;
response[key] = value;
}
}
textareas = document.getElementsByTagName('textarea');
for (i = 0; i < textareas.length; i++) {
if (textareas[i].id.substr(0, 9) == 'pop_data_') {
var key = textareas[i].id.substr(9);
var value = textareas[i].value;
response[key] = value;
}
}
//call handler
if (this.preview_in_main == false)
this.preview(response, pop_post, POP.width_mini, POP.height_mini);
else
this.preview(response);
}
};
//OK pressed - prepare data and call handlers
this.save = function () {
this.active = false;
document.getElementById("popup").style.display = "none";
var response = {};
inputs = document.getElementsByTagName('input');
for (i = 0; i < inputs.length; i++) {
if (inputs[i].id.substr(0, 9) == 'pop_data_') {
var key = inputs[i].id.substr(9);
if (HELPER.strpos(key, "_poptmp") != false)
key = key.substring(0, HELPER.strpos(key, "_poptmp"));
var value = inputs[i].value;
if (inputs[i].type == 'radio') {
if (inputs[i].checked == true)
response[key] = value;
}
else
response[key] = value;
}
}
selects = document.getElementsByTagName('select');
for (i = 0; i < selects.length; i++) {
if (selects[i].id.substr(0, 9) == 'pop_data_') {
var key = selects[i].id.substr(9);
var value = selects[i].value;
response[key] = value;
}
}
textareas = document.getElementsByTagName('textarea');
for (i = 0; i < textareas.length; i++) {
if (textareas[i].id.substr(0, 9) == 'pop_data_') {
var key = textareas[i].id.substr(9);
var value = textareas[i].value;
response[key] = value;
}
}
parameters = [];
this.preview = false;
this.onload = false;
this.preview_in_main = false;
this.effects = false;
if (this.handler != '') {
if (typeof this.handler == "object")
this.handler[0][this.handler[1]](response);
else if (typeof this.handler == "function")
this.handler(response);
else
console.log('Error: wrong function type: ' + this.handler);
}
this.handler = '';
};
//validate input field, unless browser supports input=range
this.validate = function (field) {
for (var i in parameters) {
var parameter = parameters[i];
if ("pop_data_" + parameter.name == field.id && parameter.range != undefined) {
if (field.value == '-' || field.value == '')
return true;
var value = parseFloat(field.value);
if (isNaN(value) || value != field.value)
field.value = parameter.value; //not number
if (value < parameter.range[0])
field.value = parameter.range[0]; //less then min
else if (value > parameter.range[1])
field.value = parameter.range[1]; //more then max
}
}
};
}

View File

@ -1,22 +1,32 @@
//about: SIFT: scale-invariant-feature-transform, keypoints, panorama
//author: ViliusL
/**
* SIFT: scale-invariant-feature-transform, keypoints, panorama
*
* @author ViliusL
*/
/* global HELPER, DRAW, ImageFilters, LAYER, canvas_active */
/* global HELPER, IMAGE, ImageFilters, LAYER, canvas_active */
var SIFT = new SIFT_CLASS();
function SIFT_CLASS(){
var avg_offset = 50; //contrast check, smaller - more points, better accuracy, but slower
var avg_step = 4; //how much pixels to check for each side to get average
function SIFT_CLASS() {
/**
* contrast check, smaller - more points, better accuracy, but slower
*/
var avg_offset = 50;
/**
* how much pixels to check for each side to get average
*/
var avg_step = 4;
//generate key points for image
this.generate_keypoints = function(canvas, show_points){
this.generate_keypoints = function (canvas, show_points) {
var W = canvas.width;
var H = canvas.height;
HELPER.timer_init();
//check whitespace
var trim_details = DRAW.trim_info(canvas);
var trim_details = IMAGE.trim_info(canvas);
W = W - trim_details.left - trim_details.right;
H = H - trim_details.top - trim_details.bottom;
//make copy
@ -25,85 +35,84 @@ function SIFT_CLASS(){
clone.height = H;
var ctx = clone.getContext("2d");
ctx.drawImage(canvas, -trim_details.left, -trim_details.top, canvas.width, canvas.height);
//DRAW.auto_adjust(ctx, W, H); //normalize
//greyscale
var imageData = ctx.getImageData(0, 0, W, H);
var filtered = ImageFilters.GrayScale(imageData); //add effect
ctx.putImageData(filtered, 0, 0);
//make few copies and blur each
var n = 5;
var copies = [];
for(var i = 0; i < n; i++){
for (var i = 0; i < n; i++) {
var tmp_canvas = document.createElement("canvas");
tmp_canvas.width = W;
tmp_canvas.height = H;
var ctx_i = tmp_canvas.getContext("2d");
ctx_i.drawImage(clone, 0, 0);
//gausian blur
var imageData = ctx_i.getImageData(0, 0, W, H);
var filtered = ImageFilters.GaussianBlur(imageData, i + 0.5); //add effect
ctx_i.putImageData(filtered, 0, 0);
copies.push(tmp_canvas);
}
}
//find extreme points
var points = [];
var points = [];
var n0 = avg_step * 2 + 1;
for(var c = 1; c < copies.length - 1; c++){
for (var c = 1; c < copies.length - 1; c++) {
var imageData = copies[c].getContext("2d").getImageData(0, 0, W, H).data;
var imageData0 = copies[c-1].getContext("2d").getImageData(0, 0, W, H).data;
var imageData2 = copies[c+1].getContext("2d").getImageData(0, 0, W, H).data;
for(var j = avg_step; j < H - avg_step; j++){
for(var i = avg_step; i < W - avg_step; i++){
var x = (i + j*W) * 4;
if(imageData[x+3] == 0) continue; //transparent
if(imageData[x] < imageData[x-4] || imageData[x] < imageData[x+4] || imageData[x] > imageData[x-4] || imageData[x] > imageData[x+4]){
var x_pre = (i + (j-1)*W) * 4;
var x_post = (i + (j+1)*W) * 4;
var imageData0 = copies[c - 1].getContext("2d").getImageData(0, 0, W, H).data;
var imageData2 = copies[c + 1].getContext("2d").getImageData(0, 0, W, H).data;
for (var j = avg_step; j < H - avg_step; j++) {
for (var i = avg_step; i < W - avg_step; i++) {
var x = (i + j * W) * 4;
if (imageData[x + 3] == 0)
continue; //transparent
if (imageData[x] < imageData[x - 4] || imageData[x] < imageData[x + 4] || imageData[x] > imageData[x - 4] || imageData[x] > imageData[x + 4]) {
var x_pre = (i + (j - 1) * W) * 4;
var x_post = (i + (j + 1) * W) * 4;
//calc average
var area_average = 0;
for(var l = -avg_step; l <= avg_step; l++){
var avgi = (i + (j-l)*W) * 4;
for(var a = -avg_step; a <= avg_step; a++){
area_average += imageData[avgi + 4*a];
}
for (var l = -avg_step; l <= avg_step; l++) {
var avgi = (i + (j - l) * W) * 4;
for (var a = -avg_step; a <= avg_step; a++) {
area_average += imageData[avgi + 4 * a];
}
area_average = area_average / (n0*n0);
}
area_average = area_average / (n0 * n0);
//max
if(imageData[x] + avg_offset < area_average){
var min = Math.min(imageData[x_pre-4], imageData[x_pre], imageData[x_pre+4], imageData[x-4], imageData[x+4], imageData[x_post-4], imageData[x_post], imageData[x_post+4]);
if(imageData[x] <= min){
var min0 = Math.min(imageData0[x_pre-4], imageData0[x_pre], imageData0[x_pre+4], imageData0[x-4], imageData0[x+4], imageData0[x_post-4], imageData0[x_post], imageData0[x_post+4]);
if(imageData[x] <= min0){
var min2 = Math.min(imageData2[x_pre-4], imageData2[x_pre], imageData2[x_pre+4], imageData2[x-4], imageData2[x+4], imageData2[x_post-4], imageData2[x_post], imageData2[x_post+4]);
if(imageData[x] <= min2)
if (imageData[x] + avg_offset < area_average) {
var min = Math.min(imageData[x_pre - 4], imageData[x_pre], imageData[x_pre + 4], imageData[x - 4], imageData[x + 4], imageData[x_post - 4], imageData[x_post], imageData[x_post + 4]);
if (imageData[x] <= min) {
var min0 = Math.min(imageData0[x_pre - 4], imageData0[x_pre], imageData0[x_pre + 4], imageData0[x - 4], imageData0[x + 4], imageData0[x_post - 4], imageData0[x_post], imageData0[x_post + 4]);
if (imageData[x] <= min0) {
var min2 = Math.min(imageData2[x_pre - 4], imageData2[x_pre], imageData2[x_pre + 4], imageData2[x - 4], imageData2[x + 4], imageData2[x_post - 4], imageData2[x_post], imageData2[x_post + 4]);
if (imageData[x] <= min2)
points.push({
x: i + trim_details.left,
y: j + trim_details.top,
w: round(area_average - imageData[x] - avg_offset)
});
}
w: Math.round(area_average - imageData[x] - avg_offset)
});
}
continue;
}
continue;
}
//min
if(imageData[x] - avg_offset > area_average){
var max = Math.max(imageData[x_pre-4], imageData[x_pre], imageData[x_pre+4], imageData[x-4], imageData[x+4], imageData[x_post-4], imageData[x_post], imageData[x_post+4]);
if(imageData[x] >= max){
var max0 = Math.max(imageData0[x_pre-4], imageData0[x_pre], imageData0[x_pre+4], imageData0[x-4], imageData0[x+4], imageData0[x_post-4], imageData0[x_post], imageData0[x_post+4]);
if(imageData[x] >= max0){
var max2 = Math.max(imageData2[x_pre-4], imageData2[x_pre], imageData2[x_pre+4], imageData2[x-4], imageData2[x+4], imageData2[x_post-4], imageData2[x_post], imageData2[x_post+4]);
if(imageData[x] >= max2)
if (imageData[x] - avg_offset > area_average) {
var max = Math.max(imageData[x_pre - 4], imageData[x_pre], imageData[x_pre + 4], imageData[x - 4], imageData[x + 4], imageData[x_post - 4], imageData[x_post], imageData[x_post + 4]);
if (imageData[x] >= max) {
var max0 = Math.max(imageData0[x_pre - 4], imageData0[x_pre], imageData0[x_pre + 4], imageData0[x - 4], imageData0[x + 4], imageData0[x_post - 4], imageData0[x_post], imageData0[x_post + 4]);
if (imageData[x] >= max0) {
var max2 = Math.max(imageData2[x_pre - 4], imageData2[x_pre], imageData2[x_pre + 4], imageData2[x - 4], imageData2[x + 4], imageData2[x_post - 4], imageData2[x_post], imageData2[x_post + 4]);
if (imageData[x] >= max2){
points.push({
x: i + trim_details.left,
y: j + trim_details.top,
w: round(imageData[x] - area_average - avg_offset)
});
w: Math.round(imageData[x] - area_average - avg_offset)
});
}
}
}
@ -111,59 +120,64 @@ function SIFT_CLASS(){
}
}
}
}
//make unique
for(var i=0; i<points.length; i++){
for(var j=0; j<points.length; j++){
if(i != j && points[i].x == points[j].x && points[i].y == points[j].y){
points.splice(i, 1); i--;
for (var i = 0; i < points.length; i++) {
for (var j = 0; j < points.length; j++) {
if (i != j && points[i].x == points[j].x && points[i].y == points[j].y) {
points.splice(i, 1);
i--;
break;
}
}
}
//show points?
if(show_points === true){
var time = HELPER.timer('', true);
log('key points: '+points.length+", "+time);
LAYER.layer_add();
var size = 3;
canvas_active().fillStyle = "#ff0000";
for(var i in points){
var point = points[i];
canvas_active().beginPath();
canvas_active().rect(point.x - Math.floor(size/2) + 1, point.y - Math.floor(size/2) + 1, size, size);
canvas_active().fill();
}
}
else{
}
//show points?
if (show_points === true) {
var time = HELPER.timer('', true);
log('key points: ' + points.length + ", " + time);
LAYER.layer_add();
var size = 3;
canvas_active().fillStyle = "#ff0000";
for (var i in points) {
var point = points[i];
canvas_active().beginPath();
canvas_active().rect(point.x - Math.floor(size / 2) + 1, point.y - Math.floor(size / 2) + 1, size, size);
canvas_active().fill();
}
}
else {
//sort by weights
points.sort(function(a,b) { return parseFloat(b.w) - parseFloat(a.w); } );
points.sort(function (a, b) {
return parseFloat(b.w) - parseFloat(a.w);
});
return {
points: points,
trim_details: trim_details
};
}
};
};
}
};
//returns average value of requested area from greyscale image
//area = {x, y, w, h}
this.get_area_average = function(area, imageData, i, j, size){
this.get_area_average = function (area, imageData, i, j, size) {
var imgData = imageData.data;
var sum = 0;
var n = 0;
size = size / 100; //prepare to use 1-100% values
var stop_x = i + Math.round(size*area.x) + Math.round(size*area.w);
var stop_y = j + Math.round(size*area.y) + Math.round(size*area.h);
var stop_x = i + Math.round(size * area.x) + Math.round(size * area.w);
var stop_y = j + Math.round(size * area.y) + Math.round(size * area.h);
var img_width4 = imageData.width * 4;
var k0, k;
for(var y = j + Math.round(size*area.y); y < stop_y; y++){
for (var y = j + Math.round(size * area.y); y < stop_y; y++) {
k0 = y * img_width4;
for(var x = i + Math.round(size*area.x); x < stop_x; x++){
for (var x = i + Math.round(size * area.x); x < stop_x; x++) {
k = k0 + (x * 4);
sum = sum + imgData[k];
n++;
}
}
return Math.round(sum/n);
};
}
}
return Math.round(sum / n);
};
}

View File

@ -1,162 +1,179 @@
/*
author: ViliusL
version: 1.1
about: adds vintage effect, functions:
adjust_color
lower_contrast
blur
light_leak
chemicals
exposure
grains
grains_big
optics
dusts
usage: VINTAGE.___function___(canvas_ctx, width, height, param1, param2);
theory: Ken, http://stackoverflow.com/questions/13355119/vintage-ing-image-with-javascript/18862003#18862003
libs: imagefilters.js, url: https://github.com/arahaya/ImageFilters.js
glfx.js url: http://evanw.github.com/glfx.js/
*/
/* global fx, ImageFilters, canvas_active */
var VINTAGE = new VINTAGE_CLASS();
function VINTAGE_CLASS(){
/**
* adds vintage effect
*
* @author ViliusL
*
* Functions:
* - adjust_color
* - lower_contrast
* - blur
* - light_leak
* - chemicals
* - exposure
* - grains
* - grains_big
* - optics
* - dusts
*
* Usage: VINTAGE.___function___(canvas_ctx, width, height, param1, param2, ...);
*
* libs:
* - imagefilters.js, url: https://github.com/arahaya/ImageFilters.js
* - glfx.js url: http://evanw.github.com/glfx.js/
*/
function VINTAGE_CLASS() {
var fx_filter = fx.canvas();
//increasing red color
this.adjust_color = function(context, W, H, level_red){ //level = [0, 200], default 70
this.adjust_color = function (context, W, H, level_red) { //level = [0, 200], default 70
var param_green = 0;
var param_blue = 0;
var imageData = context.getImageData(0, 0, W, H);
var filtered = ImageFilters.ColorTransformFilter(imageData, 1, 1, 1, 1, level_red, param_green, param_blue, 1);
context.putImageData(filtered, 0, 0);
};
};
//decreasing contrast
this.lower_contrast = function(context, W, H, level){ //level = [0, 50], default 15
this.lower_contrast = function (context, W, H, level) { //level = [0, 50], default 15
var imageData = context.getImageData(0, 0, W, H);
var filtered = ImageFilters.BrightnessContrastPhotoshop(imageData, 0, -level);
context.putImageData(filtered, 0, 0);
};
};
//adding blur
this.blur = function(context, W, H, level){ //level = [0, 2], default 0
if(level < 1) return context;
this.blur = function (context, W, H, level) { //level = [0, 2], default 0
if (level < 1)
return context;
var imageData = context.getImageData(0, 0, W, H);
var filtered = ImageFilters.GaussianBlur(imageData, level);
context.putImageData(filtered, 0, 0);
};
};
//creating transparent #ffa500 radial gradients
this.light_leak = function(context, W, H, level){ //level = [0, 150], default 90
this.light_leak = function (context, W, H, level) { //level = [0, 150], default 90
var click_x = this.getRandomInt(0, W);
var click_y = this.getRandomInt(0, H);
var distance = Math.min(W, H) * 0.6;
var radgrad = canvas_active().createRadialGradient(
click_x, click_y, distance*level/255,
click_x, click_y, distance * level / 255,
click_x, click_y, distance);
radgrad.addColorStop(0, "rgba(255, 165, 0, "+level/255+")");
radgrad.addColorStop(0, "rgba(255, 165, 0, " + level / 255 + ")");
radgrad.addColorStop(1, "rgba(255, 255, 255, 0)");
context.fillStyle = radgrad;
context.fillRect(0, 0, W, H);
};
};
//de-saturate
this.chemicals = function(context, W, H, level){ //level = [0, 100], default 40
this.chemicals = function (context, W, H, level) { //level = [0, 100], default 40
var imageData = context.getImageData(0, 0, W, H);
var filtered = ImageFilters.HSLAdjustment(imageData, 0, -level, 0);
context.putImageData(filtered, 0, 0);
};
};
//creating transparent vertical black-to-white gradients
this.exposure = function(context, W, H, level){ //level = [0, 150], default 80
this.exposure = function (context, W, H, level) { //level = [0, 150], default 80
context.rect(0, 0, W, H);
var grd = canvas_active().createLinearGradient(0, 0, 0, H);
if(this.getRandomInt(1, 10) < 5){
if (this.getRandomInt(1, 10) < 5) {
//dark at top
grd.addColorStop(0, "rgba(0, 0, 0, "+level/255+")");
grd.addColorStop(1, "rgba(255, 255, 255, "+level/255+")");
}
else{
grd.addColorStop(0, "rgba(0, 0, 0, " + level / 255 + ")");
grd.addColorStop(1, "rgba(255, 255, 255, " + level / 255 + ")");
}
else {
//bright at top
grd.addColorStop(0, "rgba(255, 255, 255, "+level/255+")");
grd.addColorStop(1, "rgba(0, 0, 0, "+level/255+")");
}
grd.addColorStop(0, "rgba(255, 255, 255, " + level / 255 + ")");
grd.addColorStop(1, "rgba(0, 0, 0, " + level / 255 + ")");
}
context.fillStyle = grd;
context.fill();
};
};
//add grains, noise
this.grains = function(context, W, H, level){ //level = [0, 50], default 10
if(level == 0) return context;
this.grains = function (context, W, H, level) { //level = [0, 50], default 10
if (level == 0)
return context;
var img = context.getImageData(0, 0, W, H);
var imgData = img.data;
for(var j = 0; j < H; j++){
for(var i = 0; i < W; i++){
var x = (i + j*W) * 4;
if(imgData[x+3] == 0) continue; //transparent
var imgData = img.data;
for (var j = 0; j < H; j++) {
for (var i = 0; i < W; i++) {
var x = (i + j * W) * 4;
if (imgData[x + 3] == 0)
continue; //transparent
//increase it's lightness
var delta = this.getRandomInt(0, level);
if(delta == 0) continue;
if(imgData[x] - delta < 0)
if (delta == 0)
continue;
if (imgData[x] - delta < 0)
imgData[x] = -(imgData[x] - delta);
else
imgData[x] = imgData[x] - delta;
if(imgData[x+1] - delta < 0)
imgData[x+1] = -(imgData[x+1] - delta);
if (imgData[x + 1] - delta < 0)
imgData[x + 1] = -(imgData[x + 1] - delta);
else
imgData[x+1] = imgData[x+1] - delta;
if(imgData[x+2] - delta < 0)
imgData[x+2] = -(imgData[x+2] - delta);
imgData[x + 1] = imgData[x + 1] - delta;
if (imgData[x + 2] - delta < 0)
imgData[x + 2] = -(imgData[x + 2] - delta);
else
imgData[x+2] = imgData[x+2] - delta;
}
}
imgData[x + 2] = imgData[x + 2] - delta;
}
}
context.putImageData(img, 0, 0);
};
};
//add big grains, noise
this.grains_big = function(context, W, H, level){ //level = [0, 50], default 20
if(level == 0) return context;
var n = W*H/100*level; //density
this.grains_big = function (context, W, H, level) { //level = [0, 50], default 20
if (level == 0)
return context;
var n = W * H / 100 * level; //density
var color = 200;
for(var i = 0; i < n; i++){
var power = this.getRandomInt(5, 10+level);
for (var i = 0; i < n; i++) {
var power = this.getRandomInt(5, 10 + level);
var size = 2;
var x = this.getRandomInt(0, W);
var y = this.getRandomInt(0, H);
context.fillStyle = "rgba("+color+", "+color+", "+color+", "+power/255+")";
context.fillStyle = "rgba(" + color + ", " + color + ", " + color + ", " + power / 255 + ")";
context.fillRect(x, y, size, size);
}
};
}
};
//adding vignette effect - blured dark borders
this.optics = function(context, W, H, param1, param2){ //param1 [0, 0.5], param2 [0, 0.7], default 0.3, 0.5
this.optics = function (context, W, H, param1, param2) { //param1 [0, 0.5], param2 [0, 0.7], default 0.3, 0.5
var texture = fx_filter.texture(context.getImageData(0, 0, W, H));
fx_filter.draw(texture).vignette(param1, param2).update();
context.drawImage(fx_filter, 0, 0);
};
};
//add dust and hairs
this.dusts = function(context, W, H, level){ //level = [0, 100], default 70
this.dusts = function (context, W, H, level) { //level = [0, 100], default 70
var n = level / 100 * (W * H) / 1000;
//add dust
context.fillStyle = "rgba(200, 200, 200, 0.3)";
for(var i=0; i<n; i++){
for (var i = 0; i < n; i++) {
var x = this.getRandomInt(0, W);
var y = this.getRandomInt(0, H);
var mode = this.getRandomInt(1, 2);
if(mode == 1){
if (mode == 1) {
var w = 1;
var h = this.getRandomInt(1, 3);
}
else if(mode == 2){
}
else if (mode == 2) {
var w = this.getRandomInt(1, 3);
var h = 1;
}
}
context.beginPath();
context.rect(x, y, w, h);
context.fill();
}
}
//add hairs
context.strokeStyle = "rgba(200, 200, 200, 0.2)";
for(var i=0; i<n/3; i++){
for (var i = 0; i < n / 3; i++) {
var x = this.getRandomInt(0, W);
var y = this.getRandomInt(0, H);
var radius = this.getRandomInt(5, 15);
@ -166,12 +183,13 @@ function VINTAGE_CLASS(){
context.beginPath();
context.arc(x, y, radius, start_angle, end_angle);
context.stroke();
}
}
return context;
};
};
//random number generator
this.getRandomInt = function(min, max) {
this.getRandomInt = function (min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
};
}
};
}

View File

@ -1,57 +0,0 @@
//https://github.com/viliusle/Hermite-resize
onmessage = function (event){
var img = event.data[0];
var data = img.data;
var W = event.data[1];
var H = event.data[2];
var W2 = event.data[3];
var H2 = event.data[4];
var core = event.data[5];
var max_cores = event.data[6];
var data2 = [];
var ratio_w = W / W2;
var ratio_h = H / H2;
var ratio_w_half = Math.ceil(ratio_w/2);
var ratio_h_half = Math.ceil(ratio_h/2);
var start_row = Math.ceil(H2*core/max_cores)-1;
if(start_row < 0) start_row = 0;
var offset = Math.floor(H2*core/max_cores) * W2 * 4;
for(var j = start_row; j < start_row + Math.ceil(H2/max_cores); j++){
for(var i = 0; i < W2; i++){
var x2 = (i + j*W2) * 4;
var weight = 0;
var weights = 0;
var gx_r = gx_g = gx_b = gx_a = 0;
var center_y = (j + 0.5) * ratio_h;
for(var yy = Math.floor(j * ratio_h); yy < (j + 1) * ratio_h; yy++){
var dy = Math.abs(center_y - (yy + 0.5)) / ratio_h_half;
var center_x = (i + 0.5) * ratio_w;
var w0 = dy*dy; //pre-calc part of w
for(var xx = Math.floor(i * ratio_w); xx < (i + 1) * ratio_w; xx++){
var dx = Math.abs(center_x - (xx + 0.5)) / ratio_w_half;
var w = Math.sqrt(w0 + dx*dx);
if(w >= -1 && w <= 1){
//hermite filter
weight = 2 * w*w*w - 3*w*w + 1;
if(weight > 0){
dx = 4*(xx + yy*W);
gx_r += weight * data[dx];
gx_g += weight * data[dx + 1];
gx_b += weight * data[dx + 2];
gx_a += weight * data[dx + 3];
weights += weight;
}
}
}
}
var x2 = (i + j*W2) * 4 - offset;
data2[x2] = gx_r / weights;
data2[x2 + 1] = gx_g / weights;
data2[x2 + 2] = gx_b / weights;
data2[x2 + 3] = gx_a / weights;
}
}
postMessage({offset: offset, data: data2});
};

View File

@ -8,13 +8,12 @@ body {
color: #000000;
margin: 0px;
padding: 0px;
padding-top: 25px;
padding-top: 30px;
background-color:#727272;
font-weight: normal;
overflow: hidden;
}
}
canvas{
border:1px solid #808080;
position: absolute;
outline: none;
/* disable select canvas */
@ -25,14 +24,14 @@ canvas{
-ms-user-select: none;
user-select: none;
-webkit-tap-highlight-color: rgba(255, 255, 255, 0); /* mobile webkit */
/* disable antialiasing */
image-rendering: -moz-crisp-edges; /* Firefox */
image-rendering: -o-crisp-edges; /* Opera */
image-rendering: -webkit-optimize-contrast;/* Webkit (non-standard naming) */
image-rendering: crisp-edges;
-ms-interpolation-mode: nearest-neighbor; /* IE (non-standard property) */
}
}
img{
border: none;
}
@ -51,14 +50,14 @@ table{
input[type="text"], input[type="button"], select, input[type="number"]{
border:1px solid #393939;
padding:1px 3px;
}
}
input[type="range"]{
margin-left:0px;
width:100%;
}
}
input[type="button"]:disabled {
visibility:hidden;
}
}
input[type="button"]{
background: #dddddd;
}
@ -66,28 +65,32 @@ input[type="button"]{
/* ==== ID ================================================================== */
#wrapper{
margin:10px 5px 5px 5px;
margin: 5px;
position:relative;
min-height: 500px;
}
}
#sidebar_left{
position: absolute;
width: 100px;
z-index: 100;
}
}
#sidebar_right{
position: absolute;
width: 152px;
right:0;
top:0;
z-index: 100;
}
}
#canvas_wrapper{
position:relative;
margin: 0 157px 0 105px;
overflow: hidden;
height: calc(100vh - 35px);
}
}
#canvas_wrapper canvas{
border: 1px solid #393939;
box-sizing: content-box;
}
#logo{
display: block;
height: 30px;
@ -99,10 +102,10 @@ input[type="button"]{
font-weight: bold;
color: #ffffff;
font-size: 13px;
}
}
#logo:hover{
animation: shake 0.82s cubic-bezier(.36,.07,.19,.97) both;
}
}
@keyframes shake {
10%, 90% {
background-position: 2px 0px;
@ -121,10 +124,12 @@ input[type="button"]{
border:1px solid #808080;
position: absolute;
margin-left:105px;
}
}
#canvas_back{
position: absolute;
background-color:#ffffff;
}
outline: none;
}
#main_colour{
border:1px solid #393939;
background-color:#727272;
@ -133,41 +138,41 @@ input[type="button"]{
height:40px;
margin:0px;
padding:0px;
}
}
#main_colour_alt{
border:1px solid #393939;
margin-top:10px;
width:100%;
height:40px;
}
}
#main_colour_rgb{
margin-top:5px;
width:100%;
color:#000000;
text-align:right;
}
}
#main_colour_rgb input{
width:35px;
}
}
#preview{
width:150px;
height:150px;
background-color:#989898;
border:1px solid #393939;
margin-bottom: 5px;
}
}
#preview canvas{
cursor: pointer;
}
}
#layers_base{
background-color: #989898;
border: 1px solid #393939;
padding: 5px;
margin-bottom: 5px;
}
}
#menu_left_container .active{
background-color: #5680c1 !important;
}
}
#menu_left_container a{
float:left;
border: 1px solid #393939;
@ -177,20 +182,20 @@ input[type="button"]{
margin:0px 1px 1px 0px;
overflow:hidden;
display:block;
}
}
#action_attributes{
min-height:20px;
font-size:11px;
}
}
#info{
padding:5px 3px 5px 2px;
min-height:57px;
font-size:11px;
}
}
#action_attributes input{
font-size:11px;
width:100%;
}
}
#popup{
position:fixed;
border:1px solid #000000;
@ -206,29 +211,30 @@ input[type="button"]{
padding:10px;
font-size:12px;
color: #333;
}
z-index: 100;
}
#popup h2{
margin-top:0px;
cursor:move;
}
}
#popup td{
height:20px;
}
}
#popup textarea{
color:#000000;
width:100%;
border:1px solid #393939;
padding-left:5px;
}
}
#popup .button{
margin-right:5px;
background-color:#5680c1;
width:60px;
height:25px;
}
}
#popup input[type="text"], #popup input[type="number"], #popup textarea{
width:100%;
}
}
#resize-w, #resize-h, #resize-wh{
background-color:#393939;
width:5px;
@ -236,22 +242,18 @@ input[type="button"]{
margin-left:105px;
position:absolute;
top:0;
}
}
#color_hex{
width: 100%;
border:1px solid #393939;
}
#canvas_grid{
display:none;
pointer-events:none;
}
#all_colors{
margin-top:10px;
padding:3px 0px 3px 3px;
}
#canvas_front{
position:relative;
}
/* ==== classes ============================================================= */
@ -260,7 +262,7 @@ input[type="button"]{
padding:5px;
margin-top:5px;
background-color:#818181;
}
}
.layer{
margin-bottom:2px;
border:1px solid #393939;
@ -271,7 +273,7 @@ input[type="button"]{
height:19px;
overflow:hidden;
color:#333333;
}
}
.layers_arrow{
text-decoration:none;
color:#000000;
@ -282,7 +284,7 @@ input[type="button"]{
padding:0px 5px 0px 5px;
border:1px solid #393939;
font-size:11px;
}
}
.layer_title{
display:block;
float:left;
@ -290,10 +292,10 @@ input[type="button"]{
min-width:85px;
width:10px;
overflow:hidden;
}
}
#layers_base .active{
background-color:#5680c1;
}
}
.layer_delete{
float:right;
cursor:pointer;
@ -301,7 +303,7 @@ input[type="button"]{
width:12px;
height:12px;
background: url('../img/all.png') no-repeat 0px -50px;
}
}
.layer_visible{
float:right;
cursor:pointer;
@ -309,31 +311,31 @@ input[type="button"]{
width:12px;
height:12px;
background: url('../img/all.png') no-repeat -100px -50px;
}
}
.layer_unvisible{
background: url('../img/all.png') no-repeat -50px -50px;
}
}
.layer_add{
border:1px solid #393939;
padding:0px 4px 0px 4px;
text-decoration:none;
background-color:#5680c1;
cursor:pointer;
}
}
.mini-color{
width:16px;
height:16px;
margin:0px 3px 3px 0px;
float:left;
border:1px solid #393939;
}
}
.mini-color:hover{
cursor:pointer;
}
}
.attribute-title{
text-align:center;
font-weight:bold;
}
}
.attribute-area{
border:1px solid #393939;
background-color:#989898;
@ -344,7 +346,7 @@ input[type="button"]{
/* disable select */
-webkit-user-select:none;
-moz-user-select:none;
}
}
.error{
padding:20px;
margin:10px;
@ -352,12 +354,12 @@ input[type="button"]{
background-color:#ffffff;
width:400px;
font-weight:bold;
}
}
.group{
border:1px solid #888888;
margin:5px 0px 5px 0px;
padding:5px;
}
}
/* ==== menu ================================================================ */
@ -371,43 +373,44 @@ input[type="button"]{
background: #2D2D2D;
width: 100%;
padding-left:10px;
}
}
.ddsmoothmenu ul{
z-index:100;
margin: 0;
padding: 0;
list-style-type: none;
}
}
.ddsmoothmenu ul li{
position: relative;
display: inline;
float: left;
color: #2d2b2b;
}
}
.ddsmoothmenu ul li .rightarrowclass{
display: none !important;
}
}
.ddsmoothmenu ul li ul li .rightarrowclass{
display: block !important;
}
}
.ddsmoothmenu ul li a{
display: block;
color: #2D2D2D;
padding: 8px 10px;
padding: 7px 10px 0 10px;
text-decoration: none;
color: #cccccc;
}
height:30px;
}
.ddsmoothmenu ul li a.selected {
background: #FFFFFF !important;
color: #2d2b2b;
}
}
.ddsmoothmenu ul li ul li a.selected {
background-color:#E4EBF8 !important;
}
}
.ddsmoothmenu ul li a:hover{
background: #E4EBF8;
color: #2D2D2D;
}
}
.ddsmoothmenu .hide_ul{
position: absolute;
left: -3000px;
@ -415,7 +418,7 @@ input[type="button"]{
visibility: hidden;
border:1px solid #5680C1;
border-top:0px;
}
}
.ddsmoothmenu ul li ul{
position: absolute;
left: -3000px;
@ -423,32 +426,34 @@ input[type="button"]{
visibility: hidden;
border:1px solid #5680C1;
border-top:0px;
}
margin-left: -1px;
}
.ddsmoothmenu ul li ul li{
display: list-item;
background: #ffffff;
float: none;
}
}
.ddsmoothmenu ul li ul li ul{
top: 0;
border-top:1px solid #5680C1;
}
}
.ddsmoothmenu ul li ul li a{
padding: 4px 5px 4px 5px;
padding-left: 5px;
padding-right:5px;
margin: 0;
color: #2D2D2D;
}
}
* html .ddsmoothmenu{height: 1%;} /*Hack for IE7 and below*/
.downarrowclass{
position: absolute;
top: 12px;
right: 7px;
}
}
.rightarrowclass{
position: absolute;
top: 6px;
right: 5px;
}
}
.ddshadow{
position: absolute;
left: 0;
@ -456,13 +461,13 @@ input[type="button"]{
width: 0;
height: 0;
background-color: #ccc;
}
}
.ddsmoothmenu .mid-line{
background-color:#ff0000;
border-top:1px solid #e5e5e5;
font-size:0;
padding:0 8px 0 8px;
}
}
/* ==== print =============================================================== */
@ -490,11 +495,11 @@ input[type="button"]{
#canvas_wrapper{
margin:0px;
padding:0px;
}
}
canvas{
border:0px;
position: absolute;
top:0px;
left:0px;
}
}
}