Cropping an image with a preview using jcrop - javascript

I'm using jcrop and trying to make a "live" preview of the cropped area on an image.
The movement of the selected area works perfectly if the "Crop Selection" area is the same height and width as the destination preview div.
Check out the issue here: http://jsfiddle.net/fbaAW/
function showCoords(c)
{
var $this = this.ui.holder;
var original = $this.prev();
var preview = original.parent().find(".image");
var oH = original.height();
var oW = original.width();
var pH = preview.height();
var pW = preview.width();
var sH = c.h;
var sW = c.w;
var differenceH = pH - sH;
var differenceW = pW - sW;
//preview.css('width', c.w);
//preview.css('height', c.h);
//preview.css("background-size", Math.round(oW + differenceW) + "px" + " " + Math.round(oH + differenceH) + "px");
preview.css("background-position", Math.round(c.x) * -1 + "px" + " " + Math.round(c.y) * -1 + "px");
}
As you can see, I've commented out a few of my tests and attempts at getting this code to work properly but I just can't wrap my head around the relationship between the position and the size background properties in order to get this effect to work correctly.

Calculate the horizontal and vertical ratios between the selection size and the preview area size:
var rW = pW / c.w;
var rH = pH / c.h;
Then apply them to the background-size and background-position:
preview.css("background-size", (oW*rW) + "px" + " " + (oH*rH) + "px");
preview.css("background-position", rW * Math.round(c.x) * -1 + "px" + " " + rH * Math.round(c.y) * -1 + "px");
http://jsfiddle.net/fbaAW/1/
So, if the preview size is, say, 3 times the size of your jCrop selection area, it means you have scale the original image by 3, and compensate for the scaling when defining the background position.

Related

How to get drawline to work in Internet Explorer?

I have a function that draws a line inside a div (adapted from this solution), used in an e-learning module (explains the weird parts of the code).
My problem is that it doesn't seem to work in IE11.
Here is the code:
var player = GetPlayer();
var progress = player.GetVar("score");
var h = 600; //the height of your slide, as set in Story Size
var w = 1000; //the width of your slide, as set in Story Size
var t = 4; //the desired thickness of the progress bar in px, as based on the size of the styry slide
var c = "#00cc3399"; //the desired color of the progress bar, in hex. The last 2 digits are opacity. See codes below:
var startY = 40; //the desired start coordinate, from the top of the page
var startX = 0; //the desired start coordinate, from the left side of the page. Set to "0" as standard
var aspectRatio = h/w;
var totalW = $('.slide-container').width(); //get the actual width of the slide. only relevant if storyline is set to "Scale to fill browser window"
var totalH = totalW*aspectRatio; //calculate the actual height of the slide. only relevant if storyline is set to "Scale to fill browser window"
console.log("totalW: " + totalW);
var wFactor = totalW/w; //used to calculate the x-position on the slide. only relevant if storyline is set to "Scale to fill browser window"
var hFactor = totalH/h //used to calculate the y-position on the slide. only relevant if storyline is set to "Scale to fill browser window"
var endPointX = totalW*progress/100; //calculate the length of the progress bar
var endPointY = startY*hFactor; //calculate y-position, based on where you want it to be on the slide. The number is the position on the slide, as seen from the top. This is based on a horizontal progress bar
console.log("endPointX: " + endPointX + ", endPointY: " + endPointY)
x1 = startX, y1 = startY, //Start of the bar
x2 = endPointX, y2 = endPointY; //end of the bar
drawline(x1, y1, x2, y2);
//all the technical stuff:
function drawline(ax, ay, bx, by) {
console.log('ax: ' + ax);
console.log('ay: ' + ay);
console.log('bx: ' + bx);
console.log('by: ' + by);
if (ax > bx) {
bx = ax + bx;
ax = bx - ax;
bx = bx - ax;
by = ay + by;
ay = by - ay;
by = by - ay;
}
console.log('by: ' + by);
var angle = Math.atan((ay - by) / (bx - ax));
angle = (angle * 180 / Math.PI);
angle = -angle;
var length = Math.sqrt((ax - bx) * (ax - bx) + (ay - by) * (ay - by));
console.log('length: ' + length);
var style = ""
style += "left:" + (ax) + "px;"
style += "top:" + (ay) + "px;"
style += "width:" + length + "px;"
style += "height:"+t*hFactor+"px;" //set the thickness of the progress bar
style += "background-color:"+c+";"
style += "position:absolute;"
style += "transform:rotate(" + angle + "deg);"
style += "-ms-transform:rotate(" + angle + "deg);"
style += "transform-origin:0% 0%;"
style += "-moz-transform:rotate(" + angle + "deg);"
style += "-moz-transform-origin:0% 0%;"
style += "-webkit-transform:rotate(" + angle + "deg);"
style += "-webkit-transform-origin:0% 0%;"
style += "-o-transform:rotate(" + angle + "deg);"
style += "-o-transform-origin:0% 0%;"
style += "z-index:99;"
$("<div id='progressBar' style='" + style + "'></div>").appendTo('.slide-container');
};
In chrome this function draws a line based on the user's score. In IE nothing happens.
I found the solution myself. It turns out that IE redefined the 8-digit HEX value to RGBa, and turned it white. Replacing the 8-digit HEX value with it's corresponding RGBa value made it work.

Scaling and centering SVG with JS

Learning SVG / snap. With some help I can pull a region from a map and load it onto a modal per the fiddle here.
I am now trying to keep the SVG within a 200px by 200px div, maintaining its aspect ratio, and to scale, so each region in the modal will fit in the above box but remain to scale against other regions.
var m = Snap('#world-map');
var d = Snap('#svg-region');
var regionSVG = m.select('#' + region);
var p = regionSVG.clone();
d.append(p);
var bb = regionSVG.getBBox();
var vb = bb.x + ' ' + bb.y + ' ' + bb.width + ' ' + bb.height;
d.attr({
viewBox: vb
})
I tried processing the data in the bbox to create a scale, but failed miserably.
function zoomBBox(bbox)
{
var zbbox, ratio, diffx, diffy;
var length = 200;
if (bbox.width > bbox.height) {
ratio = bbox.width / length;
zbbox.width = length;
zbbox.height = bbox.height * ratio;
} else {
ratio = bbox.height / length;
zbbox.width = bbox.width * ratio;
zbbox.height = length;
}
diffx = (zbbox.width - length) / 2;
diffy = (zbbox.height - length) / 2;
zbbox.x = bbox.x + diffx;
zbbox.y = bbox.y + diffy;
return zbbox;
}
just add
.modal-body svg {
max-width: 100%;
max-height: 100%;
}
https://jsfiddle.net/0djhebes/7/
You just need the power of CSS :D
You need to define in the SVG #svg-region inside the modal via css HEIGHT & WIDTH that you want that they appear at their maximum.
For example 100px & 100px and they will be rendered inside that box
#svg-region{width:100px; height:100px;}
For aligning it, use a as wrapper around #svg-region with the following css (I think that should work, didn't test it to align vertically and horizontally)
.wrapper{display:flex; jusfity-alignment:center; align-item:center;}

How to crop images using bounding box

How do i crop an image while rendering to browser using the bounding box returned by aws rekognition indexFaces api? below is the bounding box example
Face: {
BoundingBox: {
Height: 0.16555599868297577,
Left: 0.30963000655174255,
Top: 0.7066670060157776,
Width: 0.22074100375175476
},
Confidence: 100,
FaceId: "29a75abe-397b-5101-ba4f-706783b2246c",
ImageId: "147fdf82-7a71-52cf-819b-e786c7b9746e"
},
Similarity: 97.04154968261719 }
I have faced the same issue. You have to perform some calculations on BoundingBox values. Note the estimated orientation returned in the response's OrientationCorrection field. It is the key value here. You have to find Top and Left from those confusing values. Here is the hint:
If OrientationCorrection = ROTATE_0
Left = image.width*BoundingBox.Left
Top = image.height*BoundingBox.To
If OrientationCorrection = ROTATE_90
Left = image.height * (1 - (BoundingBox.Top + .BoundingBox.Height))
Top = image.width * BoundingBox.Left
If OrientationCorrection = ROTATE_180
Left = image.width - (image.width*(BoundingBox.Left + BoundingBox.Width))
Top = image.height * (1 - (BoundingBox.Top + BoundingBox.Height))
If OrientationCorrection = ROTATE_270
Left = image.height * BoundingBox.top
Top = image.width * (1 - BoundingBox.Left - BoundingBox.Width)
Here is sample code of python which I have used.
import boto3
import io
from PIL import Image
# Calculate positions from from estimated rotation
def ShowBoundingBoxPositions(imageHeight, imageWidth, box, rotation):
left = 0
top = 0
if rotation == 'ROTATE_0':
left = imageWidth * box['Left']
top = imageHeight * box['Top']
if rotation == 'ROTATE_90':
left = imageHeight * (1 - (box['Top'] + box['Height']))
top = imageWidth * box['Left']
if rotation == 'ROTATE_180':
left = imageWidth - (imageWidth * (box['Left'] + box['Width']))
top = imageHeight * (1 - (box['Top'] + box['Height']))
if rotation == 'ROTATE_270':
left = imageHeight * box['Top']
top = imageWidth * (1- box['Left'] - box['Width'] )
print('Left: ' + '{0:.0f}'.format(left))
print('Top: ' + '{0:.0f}'.format(top))
print('Face Width: ' + "{0:.0f}".format(imageWidth * box['Width']))
print('Face Height: ' + "{0:.0f}".format(imageHeight * box['Height']))
if __name__ == "__main__":
photo='input.png'
client=boto3.client('rekognition')
#Get image width and height
image = Image.open(open(photo,'rb'))
width, height = image.size
print ('Image information: ')
print (photo)
print ('Image Height: ' + str(height))
print('Image Width: ' + str(width))
# call detect faces and show face age and placement
# if found, preserve exif info
stream = io.BytesIO()
if 'exif' in image.info:
exif=image.info['exif']
image.save(stream,format=image.format, exif=exif)
else:
image.save(stream, format=image.format)
image_binary = stream.getvalue()
response = client.detect_faces(Image={'Bytes': image_binary}, Attributes=['ALL'])
print('Detected faces for ' + photo)
for faceDetail in response['FaceDetails']:
print ('Face:')
if 'OrientationCorrection' in response:
print('Orientation: ' + response['OrientationCorrection'])
ShowBoundingBoxPositions(height, width, faceDetail['BoundingBox'], response['OrientationCorrection'])
else:
print ('No estimated orientation. Check Exif data')
print('The detected face is estimated to be between ' + str(faceDetail['AgeRange']['Low'])
+ ' and ' + str(faceDetail['AgeRange']['High']) + ' years')
print()
It will return the Top, Left, Height, Width of the face in the image. If you use python than you can easily crop image with PIL like this.
from PIL import Image
image = Image.open(open("Main_Image", 'rb'))
area = (Left, Top, Left + Width, Top + Height)
face = image.crop(area)
face.show()
It will show the cropped face from the image.
Happy Coding

Positioning transformed divs (Trigonometric solution)

I am trying to position some diamond divs using some trigonometry in javascript but it seems my logic fails somewhere.
You can see that I tried this formula: pos + trig * dimension. I hoped it would give me the right coordinates so that I can construct my diamond grid. So my question is, how can I align the diamond borders with trigonometry?
var div = document.getElementsByTagName('div');
var x1 = div[0].offsetTop + Math.cos(45) * div[0].offsetHeight;
var y1 = div[0].offsetLeft + Math.sin(45) * div[0].offsetWidth;
div[1].style.top = y1 + 'px';
div[1].style.left = x1 + 'px';
The entire jsfiddle can be found here: https://jsfiddle.net/hmfxmvvs/
Edit: My intended result is this: https://jsfiddle.net/hmfxmvvs/5/
Try removing .offsetHeight , .offsetWidth from calculations
var x1 = div[0].offsetTop + (Math.cos(45));
var y1 = div[0].offsetLeft + (Math.sin(45));
div[1].style.top = Math.round(y1) + 'px';
div[1].style.left = Math.round(x1) - 9 + 'px';
jsfiddle https://jsfiddle.net/hmfxmvvs/2/

How to draw a line between two divs?

I'm currently trying to draw a diagonal line between the bottom right corner of one div to the top right corner of another. If possible, I would like to do it without jQuery. Is this possible?
http://jsfiddle.net/cnmsc1tm/
This won't work with IE8 or below because of CSS limitations.
function getOffset( el ) {
var rect = el.getBoundingClientRect();
return {
left: rect.left + window.pageXOffset,
top: rect.top + window.pageYOffset,
width: rect.width || el.offsetWidth,
height: rect.height || el.offsetHeight
};
}
function connect(div1, div2, color, thickness) { // draw a line connecting elements
var off1 = getOffset(div1);
var off2 = getOffset(div2);
// bottom right
var x1 = off1.left + off1.width;
var y1 = off1.top + off1.height;
// top right
var x2 = off2.left + off2.width;
var y2 = off2.top;
// distance
var length = Math.sqrt(((x2-x1) * (x2-x1)) + ((y2-y1) * (y2-y1)));
// center
var cx = ((x1 + x2) / 2) - (length / 2);
var cy = ((y1 + y2) / 2) - (thickness / 2);
// angle
var angle = Math.atan2((y1-y2),(x1-x2))*(180/Math.PI);
// make hr
var htmlLine = "<div style='padding:0px; margin:0px; height:" + thickness + "px; background-color:" + color + "; line-height:1px; position:absolute; left:" + cx + "px; top:" + cy + "px; width:" + length + "px; -moz-transform:rotate(" + angle + "deg); -webkit-transform:rotate(" + angle + "deg); -o-transform:rotate(" + angle + "deg); -ms-transform:rotate(" + angle + "deg); transform:rotate(" + angle + "deg);' />";
//
// alert(htmlLine);
document.body.innerHTML += htmlLine;
}
The Distance Formula
Finding the Center Of Two Points
Finding the Angle Between Two Points
CSS Transform:Rotate
HTML Element offset[Width|Height|Top|Left] properties
Edit (for others with the same problem):
If you need to, for example, create a line from two corners that are not the top right and bottom right divs, go to this section of the code:
// bottom right
var x1 = off1.left + off1.width;
var y1 = off1.top + off1.height;
// top right
var x2 = off2.left + off2.width;
var y2 = off2.top;
where you see + off1.width and + off1.height, that means that the code is calculating the position of the bottom or the right of the div. Remove the + off1.width or the + off1.height to get the left or the top of the div.
EDIT updated to a more standard getOffset function. If you want to get really anal you'd probably also have to add document.documentElement.client[Left/Top] and walk the offsetParent tree, but I think getBoundingClientRect() and window.page[X/Y]Offset are sufficient for an example like this.
There is a way to do it without jQ.
Find the position of your divs using offset.
Find the slope
draw 1x1px points from start to end position using the slope in your loop.

Categories

Resources