ಮೀಡಿಯವಿಕಿ:Cropimage.js
ಗೋಚರ
Note: After publishing, you may have to bypass your browser's cache to see the changes.
- Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
- Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
- Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
/**
* Tutorial script: ExtractImage ("Extract area typically image from pdf/djvu files of pages")
*
* A user script which adds a link to the toolbox to show a pop-up
* dialog with page graphic of a book and enable a selection of an area(typically image) in it.
*
* Demonstrates:
* - Use of the API
* - Use of jQuery
* - Use of ResourceLoader and some of the default modules that come with it
* - Use of localization
*
* (Be bold and improve it!)
*
* Authors:
* Arjuna Rao Chavala, 2015, Public domain
*
* Maintenace:
* User:Jayprakash12345, 2018
*
*/
//$(document).ready(function() {
//$(function(mw) {
// Import the jQuery dialog plugin before starting the rest of this script
mw.loader.using(['jquery.ui'], function() {
// var cancel = function() {
// $("#myDialog").dialog("close");
// }
var dialogobjcreated;
function renderCropImageDialog(pageLinks) {
dialogobj = $(this);
// dialogobj.dialog('destroy');
var cictext=[""];
var scale=1.50;
$dialog = $('<div></div>')
.html(
'<div id="container">' +
'<canvas id="canvas1" width="300" height="400" style="border: 1px solid black;">' +
'This text is displayed if your browser does not support HTML5 Canvas.' +
'</canvas>' +
'</div>'
// pageLinks.join( '<br /><li>' ) + '</ul>'
)
.dialog({
autoOpen: true,
title: 'Crop image!',
dialogClass: "no-close",
width: '70%',
modal: true,
closeOnEscape: false,
// open: function (event, ui) {
// $(".ui-dialog-titlebar-close", ui.dialog || ui).hide();
// },
buttons: {
"Done": function() {
getTemplatetext(cictext,scale);
console.log(cictext[0]);
//add to document
var $txt = $('#wpTextbox1');
// $txt.prepend(cictext[0]); //did not work on page namespace
$("#wpTextbox1").val(cictext[0]+$("#wpTextbox1").val());
$(this).dialog('destroy').remove();
},
"Cancel": function(event, ui) {
$(this).dialog('destroy').remove(); //cancel
}
},
});
}
function cropimage() {
var myPageLinks = [];
// remdering and data preparations to be done
renderCropImageDialog(myPageLinks);
shapeinit();
}
// By Simon Sarris
// www.simonsarris.com
// sarris@acm.org
//
// Code from the following pages merged by Andrew Clark (amclark7@gmail.com):
// http://simonsarris.com/blog/510-making-html5-canvas-useful
// http://simonsarris.com/blog/225-canvas-selecting-resizing-shape
// Last update June 2013
//
// Free to use and distribute at will
// So long as you are nice to people, etc
// Constructor for Shape objects to hold data for all drawn objects.
// For now they will just be defined as rectangles.
function Shape(state, x, y, w, h, fill) {
"use strict";
// This is a very simple and unsafe constructor. All we're doing is checking if the values exist.
// "x || 0" just means "if there is a value for x, use that. Otherwise use 0."
// But we aren't checking anything else! We could put "Lalala" for the value of x
this.state = state;
this.x = x || 0;
this.y = y || 0;
this.w = w || 1;
this.h = h || 1;
this.fill = fill || '#AAAAAA';
}
// Draws this shape to a given context
Shape.prototype.draw = function(ctx, optionalColor) {
"use strict";
var i, cur, half;
ctx.fillStyle = this.fill;
ctx.fillRect(this.x, this.y, this.w, this.h);
if (this.state.selection === this) {
ctx.strokeStyle = this.state.selectionColor;
ctx.lineWidth = this.state.selectionWidth;
ctx.strokeRect(this.x, this.y, this.w, this.h);
// draw the boxes
half = this.state.selectionBoxSize / 2;
// 0 1 2
// 3 4
// 5 6 7
// top left, middle, right
this.state.selectionHandles[0].x = this.x - half;
this.state.selectionHandles[0].y = this.y - half;
this.state.selectionHandles[1].x = this.x + this.w / 2 - half;
this.state.selectionHandles[1].y = this.y - half;
this.state.selectionHandles[2].x = this.x + this.w - half;
this.state.selectionHandles[2].y = this.y - half;
//middle left
this.state.selectionHandles[3].x = this.x - half;
this.state.selectionHandles[3].y = this.y + this.h / 2 - half;
//middle right
this.state.selectionHandles[4].x = this.x + this.w - half;
this.state.selectionHandles[4].y = this.y + this.h / 2 - half;
//bottom left, middle, right
this.state.selectionHandles[6].x = this.x + this.w / 2 - half;
this.state.selectionHandles[6].y = this.y + this.h - half;
this.state.selectionHandles[5].x = this.x - half;
this.state.selectionHandles[5].y = this.y + this.h - half;
this.state.selectionHandles[7].x = this.x + this.w - half;
this.state.selectionHandles[7].y = this.y + this.h - half;
ctx.fillStyle = this.state.selectionBoxColor;
for (i = 0; i < 8; i += 1) {
cur = this.state.selectionHandles[i];
ctx.fillRect(cur.x, cur.y, this.state.selectionBoxSize, this.state.selectionBoxSize);
}
}
};
// Determine if a point is inside the shape's bounds
Shape.prototype.contains = function(mx, my) {
"use strict";
// All we have to do is make sure the Mouse X,Y fall in the area between
// the shape's X and (X + Height) and its Y and (Y + Height)
return (this.x <= mx) && (this.x + this.w >= mx) &&
(this.y <= my) && (this.y + this.h >= my);
};
var myState=[]; //need to access it for return values for shape code
var imageObj = new Image();
var curResourceCounter = 0;
var initcomplete = false;
function CanvasState(canvas) {
"use strict";
// **** First some setup! ****
this.canvas = canvas;
this.width = canvas.width;
this.height = canvas.height;
this.ctx = canvas.getContext('2d');
// This complicates things a little but but fixes mouse co-ordinate problems
// when there's a border or padding. See getMouse for more detail
var stylePaddingLeft, stylePaddingTop, styleBorderLeft, styleBorderTop,
html, i;
if (document.defaultView && document.defaultView.getComputedStyle) {
this.stylePaddingLeft = parseInt(document.defaultView.getComputedStyle(canvas, null).paddingLeft, 10) || 0;
this.stylePaddingTop = parseInt(document.defaultView.getComputedStyle(canvas, null).paddingTop, 10) || 0;
this.styleBorderLeft = parseInt(document.defaultView.getComputedStyle(canvas, null).borderLeftWidth, 10) || 0;
this.styleBorderTop = parseInt(document.defaultView.getComputedStyle(canvas, null).borderTopWidth, 10) || 0;
}
// Some pages have fixed-position bars (like the stumbleupon bar) at the top or left of the page
// They will mess up mouse coordinates and this fixes that
html = document.body.parentNode;
this.htmlTop = html.offsetTop;
this.htmlLeft = html.offsetLeft;
// **** Keep track of state! ****
this.valid = false; // when set to false, the canvas will redraw everything
this.shapes = []; // the collection of things to be drawn
this.dragging = false; // Keep track of when we are dragging
this.resizeDragging = false; // Keep track of resize
this.expectResize = -1; // save the # of the selection handle
// the current selected object. In the future we could turn this into an array for multiple selection
this.selection = null;
this.dragoffx = 0; // See mousedown and mousemove events for explanation
this.dragoffy = 0;
// New, holds the 8 tiny boxes that will be our selection handles
// the selection handles will be in this order:
// 0 1 2
// 3 4
// 5 6 7
this.selectionHandles = [];
for (i = 0; i < 8; i += 1) {
this.selectionHandles.push(new Shape(this));
}
this.displayedImageWidth = 0;
this.displayedImageHeight = 0;
this.horScalingFactor = 0;
this.verScalingFactor = 0;
// this.img = imageObj;// keep imageObj outside of myState
// **** Then events! ****
// This is an example of a closure!
// Right here "this" means the CanvasState. But we are making events on the Canvas itself,
// and when the events are fired on the canvas the variable "this" is going to mean the canvas!
// Since we still want to use this particular CanvasState in the events we have to save a reference to it.
// This is our reference!
myState = this;
//fixes a problem where double clicking causes text to get selected on the canvas
canvas.addEventListener('selectstart', function(e) {
e.preventDefault();
return false;
}, false);
// Up, down, and move are for dragging
canvas.addEventListener('mousedown', function(e) {
var mouse, mx, my, shapes, l, i, mySel;
if (myState.expectResize !== -1) {
myState.resizeDragging = true;
return;
}
mouse = myState.getMouse(e);
mx = mouse.x;
my = mouse.y;
shapes = myState.shapes;
l = shapes.length;
for (i = l - 1; i >= 0; i -= 1) {
if (shapes[i].contains(mx, my)) {
mySel = shapes[i];
// Keep track of where in the object we clicked
// so we can move it smoothly (see mousemove)
myState.dragoffx = mx - mySel.x;
myState.dragoffy = my - mySel.y;
myState.dragging = true;
myState.selection = mySel;
myState.valid = false;
return;
}
}
// havent returned means we have failed to select anything.
// If there was an object selected, we deselect it
if (myState.selection) {
myState.selection = null;
myState.valid = false; // Need to clear the old selection border
}
}, true);
canvas.addEventListener('mousemove', function(e) {
var mouse = myState.getMouse(e),
mx = mouse.x,
my = mouse.y,
oldx, oldy, i, cur;
if (myState.dragging) {
mouse = myState.getMouse(e);
// We don't want to drag the object by its top-left corner, we want to drag it
// from where we clicked. Thats why we saved the offset and use it here
myState.selection.x = mouse.x - myState.dragoffx;
myState.selection.y = mouse.y - myState.dragoffy;
myState.valid = false; // Something's dragging so we must redraw
} else if (myState.resizeDragging) {
// time ro resize!
oldx = myState.selection.x;
oldy = myState.selection.y;
// 0 1 2
// 3 4
// 5 6 7
switch (myState.expectResize) {
case 0:
myState.selection.x = mx;
myState.selection.y = my;
myState.selection.w += oldx - mx;
myState.selection.h += oldy - my;
break;
case 1:
myState.selection.y = my;
myState.selection.h += oldy - my;
break;
case 2:
myState.selection.y = my;
myState.selection.w = mx - oldx;
myState.selection.h += oldy - my;
break;
case 3:
myState.selection.x = mx;
myState.selection.w += oldx - mx;
break;
case 4:
myState.selection.w = mx - oldx;
break;
case 5:
myState.selection.x = mx;
myState.selection.w += oldx - mx;
myState.selection.h = my - oldy;
break;
case 6:
myState.selection.h = my - oldy;
break;
case 7:
myState.selection.w = mx - oldx;
myState.selection.h = my - oldy;
break;
}
myState.valid = false; // Something's dragging so we must redraw
}
// if there's a selection see if we grabbed one of the selection handles
if (myState.selection !== null && !myState.resizeDragging) {
for (i = 0; i < 8; i += 1) {
// 0 1 2
// 3 4
// 5 6 7
cur = myState.selectionHandles[i];
// we dont need to use the ghost context because
// selection handles will always be rectangles
if (mx >= cur.x && mx <= cur.x + myState.selectionBoxSize &&
my >= cur.y && my <= cur.y + myState.selectionBoxSize) {
// we found one!
myState.expectResize = i;
myState.valid = false;
switch (i) {
case 0:
this.style.cursor = 'nw-resize';
break;
case 1:
this.style.cursor = 'n-resize';
break;
case 2:
this.style.cursor = 'ne-resize';
break;
case 3:
this.style.cursor = 'w-resize';
break;
case 4:
this.style.cursor = 'e-resize';
break;
case 5:
this.style.cursor = 'sw-resize';
break;
case 6:
this.style.cursor = 's-resize';
break;
case 7:
this.style.cursor = 'se-resize';
break;
}
return;
}
}
// not over a selection box, return to normal
myState.resizeDragging = false;
myState.expectResize = -1;
this.style.cursor = 'auto';
}
}, true);
canvas.addEventListener('mouseup', function(e) {
myState.dragging = false;
myState.resizeDragging = false;
myState.expectResize = -1;
if (myState.selection !== null) {
if (myState.selection.w < 0) {
myState.selection.w = -myState.selection.w;
myState.selection.x -= myState.selection.w;
}
if (myState.selection.h < 0) {
myState.selection.h = -myState.selection.h;
myState.selection.y -= myState.selection.h;
}
}
}, true);
// double click for making new shapes .. not needed
//canvas.addEventListener('dblclick', function(e) {
// var mouse = myState.getMouse(e);
// myState.addShape(new Shape(myState, mouse.x - 10, mouse.y - 10, 20, 20, 'rgba(0,255,0,.6)'));
//}, true);
// **** Options! ****
this.selectionColor = '#CC0000';
this.selectionWidth = 2;
this.selectionBoxSize = 6;
this.selectionBoxColor = 'darkred';
this.interval = 30;
// this.bSize=0; //to store displayed image width
setInterval(function() {
myState.draw();
}, myState.interval);
}
CanvasState.prototype.addShape = function(shape) {
"use strict";
this.shapes.push(shape);
this.valid = false;
};
CanvasState.prototype.clear = function() {
"use strict";
this.ctx.clearRect(0, 0, this.width, this.height);
};
// While draw is called as often as the INTERVAL variable demands,
// It only ever does something if the canvas gets invalidated by our code
CanvasState.prototype.draw = function() {
"use strict";
var ctx, shapes, l, i, shape, mySel, img;
// if our state is invalid, redraw and validate!
if (!this.valid) {
ctx = this.ctx;
shapes = this.shapes;
img = imageObj;
this.clear();
//log shape location
// console.log("Scaled image width, height:",displayedImageWidth,displayedImageHeight);
// console.log("Ext Image location:", shapes[0].x,shapes[0].y);
// console.log("Ext extents:",shapes[0].w,shapes[0].h);
//output Template text
// ** Add stuff you want drawn in the background all the time here **
//*** Background picture on which graphic part is to be selected**
//add background image
if (curResourceCounter > 0) {
// if height is more than width make height is equal to canvas height
if (img.height >= img.width) {
this.displayedImageHeight = this.height;
this.verScalingFactor = this.height / img.height;
this.displayedImageWidth = Math.round(this.verScalingFactor * img.width);
this.horScalingFactor = this.verScalingFactor;
} else {
this.displayedImageWidth = this.width;
this.horScalingFactor = this.width / img.width;
this.displayedImageHeight = Math.round(this.horScalingFactor * img.height);
this.verScalingFactor = this.horScalingFactor;
}
// if width is more than height make width equal to canvas height
// this.bSize=displayedImageWidth;
// imgSmall.removeAttr("class").removeAttr("height").removeAttr("style").css("width", "inherit");
// append to DOM for drawing
// $("canvas1").append(imgSmall);
ctx.drawImage(img, 0, 0, this.displayedImageWidth, this.displayedImageHeight);
//first time setting of shape for center of image
if (initcomplete ){
shapes[0].x = Math.round(this.displayedImageWidth / 2 - 0.1 * this.displayedImageWidth);
shapes[0].y = Math.round(this.displayedImageHeight / 2 - 0.1 * this.displayedImageHeight);
shapes[0].w = Math.round(0.2 * this.displayedImageWidth);
shapes[0].h = Math.round(0.2 * this.displayedImageHeight);
initcomplete = false;
}
}
// draw all shapes
l = shapes.length;
for (i = 0; i < l; i += 1) {
shape = shapes[i];
// We can skip the drawing of elements that have moved off the screen:
if (shape.x <= this.width && shape.y <= this.height &&
shape.x + shape.w >= 0 && shape.y + shape.h >= 0) {
shapes[i].draw(ctx);
}
}
// draw selection
// right now this is just a stroke along the edge of the selected Shape
if (this.selection !== null) {
ctx.strokeStyle = this.selectionColor;
ctx.lineWidth = this.selectionWidth;
mySel = this.selection;
ctx.strokeRect(mySel.x, mySel.y, mySel.w, mySel.h);
}
// ** Add stuff you want drawn on top all the time here **
this.valid = true;
}
};
// Creates an object with x and y defined, set to the mouse position relative to the state's canvas
// If you wanna be super-correct this can be tricky, we have to worry about padding and borders
CanvasState.prototype.getMouse = function(e) {
"use strict";
var element = this.canvas,
offsetX = 0,
offsetY = 0,
mx, my;
// Compute the total offset
if (element.offsetParent !== undefined) {
do {
offsetX += element.offsetLeft;
offsetY += element.offsetTop;
element = element.offsetParent;
} while (element);
}
// Add padding and border style widths to offset
// Also add the <html> offsets in case there's a position:fixed bar
offsetX += this.stylePaddingLeft + this.styleBorderLeft + this.htmlLeft;
offsetY += this.stylePaddingTop + this.styleBorderTop + this.htmlTop;
mx = e.pageX - offsetX;
my = e.pageY - offsetY;
// We return a simple javascript object (a hash) with x and y defined
return {
x: mx,
y: my
};
};
var getTemplatetext = function(a,scale) {
//{{Css image crop
var cic = {
Image: "",
Page: 0,
bSize: 0,
cWidth: 0,
cHeight: 0,
oTop: 0,
oLeft: 0,
Location: "",
Description: ""
};
var str="";
//|Image =TeluguVariJanapadaKalarupalu.djvu
//|Page = 35
//|bSize = 351
//|cWidth = 274
//|cHeight = 165
//|oTop =210
//|oLeft = 17
//|Location = center
//|Description =
//}}
var cictext=a[0];
// console.log('{{Css image crop');
str = imageObj.src;
if (str===null){
alert('Wait for scan image of page to load completely and then try');
}
cic.Image = str.substring(str.search("px-") + 3, str.search(".jpg"));
str = str.match(/page[0-9]+/);
cic.Page = str[0].replace("page", "");
cic.bSize = Math.round(myState.displayedImageWidth*scale);
cic.cWidth = Math.round(myState.shapes[0].w*scale);
cic.cHeight = Math.round(myState.shapes[0].h*scale);
cic.oTop = Math.round(myState.shapes[0].y*scale);
cic.oLeft = Math.round(myState.shapes[0].x*scale);
cic.Location = "center";
cic.Description = "";
//compose string
//{"Image":"file:///home/arjun/extractimagejq/images/page35-3091px-TeluguVariJanapadaKalarupalu.djvu.jpg","Page":1,"bSize":281,"cWidth":56,"cHeight":80,"oTop":160,"oLeft":112,"Location":"","Description":""}
cictext = "{{Css image crop\n";
cictext += "|Image = " + decodeURIComponent(cic.Image) + "\n";
cictext += "|Page = " + cic.Page + "\n";
cictext += "|bSize = " + cic.bSize + "\n";
cictext += "|cWidth = " + cic.cWidth + "\n";
cictext += "|cHeight = " + cic.cHeight + "\n";
cictext += "|oTop = " + cic.oTop + "\n";
cictext += "|oLeft = " + cic.oLeft + "\n";
cictext += "|Location = " + cic.Location + "\n";
cictext += "|Description = " + cic.Description + "\n}}\n";
a[0]=cictext;
return true;
};
// If you dont want to use <body onLoad='init()'>
// You could uncomment this init() reference and place the script reference inside the body tag
//init();
function shapeinit() {
"use strict";
var s = new CanvasState(document.getElementById('canvas1'));
// add a large green rectangle dummy will be set after img size is available
s.addShape(new Shape(s, 0, 0, 50, 50, 'rgba(0,205,0,0.7)'));
var imgSmall = $('.prp-page-image img');
imageObj.height = imgSmall.attr('height');
imageObj.width = imgSmall.attr('width');
imageObj.onload = function () {
++curResourceCounter;
initcomplete = true;
myState.valid = false;
// alert("img loaded "+imageObj.src);
};
imageObj.src = imgSmall.attr('src');
// alert("img src "+imageObj.src);
// add a green-blue rectangle
// s.addShape(new Shape(s, 240, 120, 40, 40, 'rgba(2,165,165,0.7)'));
// add a smaller purple rectangle
// s.addShape(new Shape(s, 5, 60, 25, 25, 'rgba(150,150,250,0.7)'));
}
var customizeToolbar = function() {
if (mw.config.get("wgCanonicalNamespace")=="Page") {
// if ( typeof $ != 'undefined' && typeof $.fn.wikiEditor != 'undefined' ) {$( function() {
$('#wpTextbox1').wikiEditor('addToToolbar', {
section: 'main',
group: 'insert',
tools: {
"strikethrough": {
label: 'Crop image',
type: 'button',
// filters: ['body.ns-250, body.ns-page'],
icon: '//upload.wikimedia.org/wikipedia/commons/thumb/e/e4/Crop_button.svg/23px-Crop_button.svg.png',
action: {
type: 'callback',
execute: function(context) {
cropimage();
}
}
}
}
});
}
};
/* Check if view is in edit mode and that the required modules are available. Then, customize the toolbar … */
if ( $.inArray( mw.config.get( 'wgAction' ), [ 'edit', 'submit' ] ) !== -1 ) {
$.when( mw.loader.using( 'ext.wikiEditor' ), $.ready)
.then( customizeToolbar );
}
});
//});
//})(mediawiki);