Calculating Crop Coordinates - php

I am trying to figure out how to calculate the cropping coordinates for the full size image from a much smaller image, lets say the full size image is 1775 x 2664, the image that the user sees on the cropping page (uses jCrop) is 533 X 800.
The cropping coordinates on the smaller image are: 20,11,230,305
(start from left, start from top, end from left, end from top)
How do i scale the coordinates to the full size image.
I need to allow the user to select the portion of the image on the preview page and then use php to extract the appropriate part of the image from the full size image..

To give you some reference: http://en.wikipedia.org/wiki/Rule_of_three_%28mathematics%29#Rule_of_Three
// assuming fixed ratio on width and height
// which is the case in your example: ~33% for both dimensions
$FULL_WIDTH = 1775;
$SCALED_WIDTH = 533;
$ratio = $SCALED_WIDTH / $FULL_WIDTH;
$scaled_crop_coordinates = array(20, 11, 230, 305);
$full_crop_coordinates = array();
foreach($scaled_crop_coordinates as $val)
{
$full_crop_coordinates[] = floor($val / $ratio);
}
var_dump($full_crop_coordinates);

that should work:
left = 20 * (1775/533)
top = 11 * (2664/800)
right = 230 * (1775/533)
bottom = 305 * (2664/800)

Related

Crop the image from encoded data on submission - ( File Pond - FilePondPluginFileEncode - imageEditEditor- Doka - Crop - PHP )

Is there any proper PHP code to use when cropping the image using the data that get passed from the hidden field when using the 'FilePondPluginFileEncode'? ( I'm using Doka as image editor) https://pqina.nl/doka/?ref=filepond
The below options get passed as encoded meta data from file-pond in a hidden field when I select an image and then edit crop. + the base64 image string ( https://pqina.nl/filepond/docs/patterns/plugins/file-encode/)
{"crop":{
"center":{"x":0.6019359981,"y":0.5843676986},
"rotation":0,
"zoom":1,
"aspectRatio":0.6567346851,
"flip":{"horizontal":false,"vertical":false},
"scaleToFit":true},
"image":{"width":225,"height":148,"orientation":-1},
"size":{"upscale":true,"mode":"cover","width":null,"height":null},
"output":{"type":null,"quality":null,"background":null},
"filter":null,
"color":{"contrast":{"value":1,"matrix":[1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0]},"
exposure":{"value":1,"matrix":[1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0]},"brightness":
{"value":0,"matrix":[1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0]},"saturation":
{"value":1,"matrix":[1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0]}
},"markup":[],
"colorMatrix":[1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0]
}
On submit: This is what i have written to crop. It dose crop, but it's not exactly cropping as we select from file-pond doka image editor
<?php
if (isset($file_format['metadata']['crop'])) {
$im = new \Imagick($uploaded_file->getRealPath());
$aspectRatio = $file_format['metadata']['crop']['aspectRatio'];
$crop_center_x = $file_format['metadata']['crop']['center']['x'];//percentage
$crop_center_y = $file_format['metadata']['crop']['center']['y'];//percentage
$scale = $file_format['metadata']['crop']['zoom'];
//Doka formula for aspectRatio = height/width
//scale to original size but this crop width and height is slightly larger that what we select
//this may need some improvement
$crop_width = ($im->getImageHeight()/$aspectRatio)/$scale; //width of crop selected
$crop_height = ($im->getImageWidth()*$aspectRatio )/$scale; //height of crop selected
//x_of_crop
$x_center_crop = $im->getImageWidth() * $crop_center_x; //pixels from left to crop center
$y_center_crop = $im->getImageHeight() * $crop_center_y; //pixels from top to crop center
$x_left = $x_center_crop - ($crop_width/2);//left position of crop
$y_top = $y_center_crop - ($crop_height/2);//top position of crop
$im->cropImaxge($crop_width,$crop_height,$x_left,$y_top);
file_put_contents($filePath, $im);
$uploaded_file = new UploadedFile($filePath, $file_format['name'], null, null, true);
}
?>
Are we doing this correct or do we have any option to update the base64 string with the cropped image data, so we don't have to do cropping in the server side?
Any help would be appreciated.
Remember to add the FilePondPluginImageTransform, and FilePondPluginFileEncode, to your FilePond.registerPlugin when using imageEditEditor: Doka.create({}) in FilePond instance.
FilePond.registerPlugin(
**FilePondPluginImageTransform,**
FilePondPluginFileEncode,
FilePondPluginFileValidateSize,
FilePondPluginFileValidateType,
FilePondPluginImagePreview,
FilePondPluginImageEdit
);
FilePond.create(
field.
{
imageEditEditor: Doka.create({})
}
)
by adding FilePondPluginImageTransform file-pond will update the cropped image based64 data as well. without that it will only update the meta-data field. https://github.com/pqina/filepond-docs/blob/master/content/patterns/plugins/image-transform.md
so no need of PHP to the cropping. Javascript will crop and give you the cropped image base64 string in the data.
example without using encoded string:
https://medium.com/web-design-web-developer-magazine/leveraging-js-file-uploader-libraries-in-php-forms-example-using-filepond-754cdc9a8b48
Available plugins : https://github.com/pqina/filepond-docs/blob/master/content/patterns/plugins/introduction.md

How we can do same operations (Scale & Rotation) on image in php which applied on canvas using fabric Js?

I have added one image (resized image) to canvas & applied scale and rotation operation on it. Canvas Width is 380px And Height is 217.143px .
Case 1). Json after Applied only Scaling:
[{"objects":[{"type":"image","originX":"left","originY":"top","left":-39,"top":-62.76,"width":1000,"height":667,"fill":"rgb(0,0,0)","stroke":null,"strokeWidth":0,"strokeDashArray":null,"strokeLineCap":"butt","strokeLineJoin":"miter","strokeMiterLimit":10,"scaleX":0.83,"scaleY":0.83,"angle":0,"flipX":false,"flipY":false,"opacity":1,"shadow":null,"visible":true,"clipTo":null,"backgroundColor":"","fillRule":"nonzero","globalCompositeOperation":"source-over","transformMatrix":null,"skewX":0,"skewY":0,"src":"http:\/\/127.0.0.1\/greatcanvasprints\/web\/media\/designtool\/canvasprints\/single-print\/1813\/small_=_=_=26961_1499666667USA91235_1of12_1Panel_8x8_0-_-_-0_test.75_BorderColor_HooksforHanging_Original_1pcs_P_","filters":[],"resizeFilters":[],"crossOrigin":"","alignX":"none","alignY":"none","meetOrSlice":"meet"}],"background":null}]
Case 2). Json after Applied Scaling & Rotation :
[{"objects":[{"type":"image","originX":"left","originY":"top","left":278.28,"top":-275.14,"width":1000,"height":667,"fill":"rgb(0,0,0)","stroke":null,"strokeWidth":0,"strokeDashArray":null,"strokeLineCap":"butt","strokeLineJoin":"miter","strokeMiterLimit":10,"scaleX":0.83,"scaleY":0.83,"angle":45,"flipX":false,"flipY":false,"opacity":1,"shadow":null,"visible":true,"clipTo":null,"backgroundColor":"","fillRule":"nonzero","globalCompositeOperation":"source-over","transformMatrix":null,"skewX":0,"skewY":0,"src":"http:\/\/127.0.0.1\/greatcanvasprints\/web\/media\/designtool\/canvasprints\/single-print\/1813\/small_=_=_=26961_1499666667USA91235_1of12_1Panel_8x8_0-_-_-0_test.75_BorderColor_HooksforHanging_Original_1pcs_P_","filters":[],"resizeFilters":[],"crossOrigin":"","alignX":"none","alignY":"none","meetOrSlice":"meet"}],"background":null}]
I want to do same operations on original image in PHP And I need only designed area (canvas area). Below is some code in PHP:
Php Code workng fine with first case : while applied only scaling
get Original File
$originalImg = imagecreatefromjpeg('26961_1499666667USA91235_1of12_1Panel_8x8_0-_-_-0_test.75_BorderColor_HooksforHanging_Original_1pcs_P_');
Here is width and height (pixels) of resized image which used in canvas
$inToolUsedFileWidth = 1000;
$inToolUsedFileHeight = 667;
here is width & height (pixels) of Original File
$originalFileWidth = 5760;
$originalFileHeight = 3840;
$scaleX = 0.83
$scaleY = 0.83
$ratioWidth = ($originalFileWidth/$inToolUsedFileWidth) * (1 / $scaleX);
$ratioHeight = ($originalFileHeight/$inToolUsedFileHeight) * (1 / $scaleY);
380 default canvas width
$canvasWidth = 380 * $ratioWidth;
217.143 default canvas height
$canvasHeight = 217.143 * $ratioHeight;
same As first json value
$left = -39;
$top = -62.76;
$croppArr = array('x' => (abs($left) * $ratioWidth),'y' => (abs($top) * $ratioHeight),'width' => $canvasWidth,'height' => $canvasHeight);
$croppedImg = $this->imageCrop($originalImg,$croppArr);
Working Fine with Only Scaling
Case 2: after applied Rotation
But while applied Rotation, I have just rotate original image. But does not get exact design portion which designed on canvas.
$originalImg = imagecreatefromjpeg('26961_1499666667USA91235_1of12_1Panel_8x8_0-_-_-0_test.75_BorderColor_HooksforHanging_Original_1pcs_P_');
// Same as second Json angle value
$antiRotation = (float) -(45); // here anti clockwise rotation in php so prepend nagetive value
$originalImg = imagerotate($originalImg,$antiRotation,0);
Then use above code & just changed left & top values as per second json.
Didn't get exact output which designed on canvas.
I want to know how we recalculate left & top position of object after rotation in Fabric Js.
In First Case : Left = -39 , Top = -62.76 And Angle = 0
In Second case : Left = 278.28 , Top = -275.14 And Angle = 45
which logic applied on left & top position, after rotation.
I want to do same with PHP.
Not able to attachment of original image due to high size.
Image 1
Image 2
I have no idea what php side tool are you using.
You should just read the math of the transform pipeline in fabricjs and replicate it.
1) set fabric to originX, originY 'center', 'center'. This will simplify the logic.
2) once done that top,left of image will be the exact center
3) in php move to center (top, left)
4) rotate the canvas
5) scale the of the right amount
6) draw the image at -width/2, -height/2
Or if your php tool allows the use of transform matrix, replicate the fabricjs method object.calcTransformMatrix apply the result to your canvas, draw the image at at -width/2, -height/2.

Upload Large Image & Crop Easier

I want to allow users to upload large photos of their home and crop it to fit properly into a slideshow. So I set it up that when the user uploads their large home photo it will store that and copy it and re-size the new copy to be a more manageable size. (ex. resizing a 5000x3333px image to 600x400px) Then this new image is displayed to the user to allow them to crop that image. After the image has been cropped 4 values are returned: x, y, w, and h. These are the values of the cropped area on the smaller image, but now we want to crop the original image not this smaller one. This means the w & h have to be increased and the x & y got to stay in correct position but this is the part that I'm so confused about. How do I properly scale up the w & h and keep x & y in right place to match the crop from the small image to the original large one?
Here is a code snippet of the final function that crops. This is using some of my homemade function, understand they are just there for convenience.
//User inputs from the crop area on the small image
$user_input_x = $_POST['x'];
$user_input_y = $_POST['y'];
$user_input_w = $_POST['w'];
$user_input_h = $_POST['h'];
//Grab original, small, and final image locations
$original_image_src = '/tmp/original_image';
$small_image_src = '/tmp/small_image';
$final_image_location = '/final/image';
//Return the extension for both the original and small image
if(($image_ext = imageCheck($original_image_src)) === false) die('Could not find original image source!');
$original_image_src .= $image_ext;
$small_image_src .= $image_ext;
$final_image_location .= $image_ext;
//Get the width and height of both the original and small image
list($original_image_width, $original_image_height) = getimagesize($original_image_src);
list($small_image_width, $small_image_height) = getimagesize($small_image_src);
//Converts string location of image into php resource
//This function helps determine the type of image and create the resource
$src_image = createImage($original_image_src);
//This is the area where I am having trouble
//I need to scale up the users input x,y,w,h because they are from small image and need to match to original
//These are the vars to go into all the final fields
$src_x = $user_input_x;
$src_y = $user_input_y;
$src_w = 0;
$src_h = 0;
$crop_x = 0;
$crop_y = 0;
$crop_w = 0;
$crop_h = 0;
$final_image = imagecreatetruecolor($crop_w, $crop_h);
if(!imagecopyresampled($final_image, $src_image, $crop_x, $crop_y, $src_x, $src_y, $crop_w, $crop_h, $src_w, $src_h)) die('Could not resmaple image!');
//Saves image to final location retains the extension and destroys the resource
if(imageSave($final_image, $final_image_location, $image_ext) === false) die('Count not save image!');
Oh and if it help any, this crop is being done by jCrop which is pretty much providing the x, y, w & h.
As far as I understand x and w, and y and h scale at the same ratio.
$crop_y = $original_image_height/$small_image_height*$user_input_y;
$crop_h = $original_image_height/$small_image_height*$user_input_h;
$crop_w = $original_image_width/$small_image_width*$user_input_w;
$crop_x = $original_image_width/$small_image_width*$user_input_x;
I drew this to try and visualise it.
http://i58.tinypic.com/32zm0it.jpg

How to resize an image like facebook cover

What basically I am trying to do is to create a cover page for my personal website, just like facebook. Basically I am after the same layout of the cover as on facebook, so that user can get the same result while using the same cover on my site as well as on facebook.
The part I am stucked at is the "Drag image to position cover" thing.
The Facebook uses some algorithm to convert the cover image size to something different during dragging thing. For example, if the original image dimensions are 920x720, the dimensions of same image while it is on facebook setting-cover page(drag image to position cover thing), the dimensions of the image are 851x638.
I just wanted to know what algorithm facebook uses to set the image dimensions(from 720 to 638)
NOTE: The cover has to be the pixel perfect
I know that the cover dimension of facebook is 851x315, so here is what I am doing:
//$x = X origin cordinate variable obtained by dragging image
//$y = Y origin cordinate variable obtained by dragging image
list($k, $l) = getimagesize($src); // $src == image source
//$w = Needs to be calculated
//$h = Needs to be calculated
$img_r = imagecreatefromjpeg($src);
$dst_r = ImageCreateTrueColor( 854,316 );
imagecopyresampled($dst_r,$img_r,0,0,$x,$y,$w,$h,$k,$l);
imagejpeg($dst_r,$src,$jpeg_quality);
$img_name = writeToImage($src, $des); //writeToImage() is just a demo function created by me to do some other things with them which do not affect this part of code
echo $img_name;
I need to figure out how facebook calculates the new dimension of the image from previous one. Is it dependent of the actual(original) size of the image or is it dependent on some other factors?
The formulas for scaling images are quite simple.
$aspect_ratio = $original_width / $original_height;
$new_width = $new_height * $aspect_ratio;
or
$new_height = $new_width / $aspect_ratio;

How to crop and image before adding an overlay? (GD) (PHP)

My code so far (it creates an overlay to a youtube thumbnail):
<?php
header("Content-type:image/png");
$background=imagecreatefromjpeg("http://img.youtube.com/vi/".$_GET['v']."/default.jpg");
$insert=imagecreatefrompng("play.png");
imagecolortransparent($insert,imagecolorat($insert,0,0));
$insert_x=imagesx($insert);
$insert_y=imagesy($insert);
imagecopymerge($background,$insert,5,57,0,0,$insert_x,$insert_y,100);
imagepng($background,NULL);
The output image is 120x90px, but i need it to have 90x90px.
Anyone knows how this is possible?
Thanks in advance!
http://www.johnconde.net/blog/cropping-an-image-with-php-and-the-gd-library/
<?php
header("Content-type:image/png");
$background = imagecreatefromjpeg("http://img.youtube.com/vi/".$_GET['v']."/default.jpg");
$insert = imagecreatefrompng("play.png");
imagecolortransparent($insert,imagecolorat($insert,0,0));
list($current_width, $current_height) = getimagesize($background);
$left = 0;
$top = 0;
$crop_width = 90;
$crop_height = 90;
$canvas = imagecreatetruecolor($crop_width, $crop_height);
$current_image = $background;
imagecopy($canvas, $current_image, 0, 0, $left, $top, $current_width, $current_height);
imagecopymerge($canvas,$insert,5,57,0,0,$current_width,$current_height,100);
imagepng($canvas);
?>
try that it should work if not comment as to otherwise.
This is taken from a function I wrote to create square thumbnails. You may find the commentary I wrote for myself helpful. Depending on your needs (i.e if you can't afford to make assumptions about the type and dimensions of incoming images) you may need to add additional checks. To avoid smashed or stretched thumbnails we take a central part of the image which is most likely to contain something distinguishable as source co-ordinates.
The basic idea is: Since imagecopyresampled or imagecopyresized also allow you to specify destination and source coordinates, you can copy only part of your original image to a new canvas and save that (or directly output to browser). To avoid smashed or stretched dimensions we take a central part of the original image which is most likely to contain distinguishable content.
//assuming you have already merged your $background image with your overlay at this point
//original dimensions
$original_width = imagesx($background);
$original_height = imagesy($background);
//new dimensions
$new_width = 90;
$new_height = 90;
//the center of the rectangular image
$center = $original_width/2, $original_height/2
//the coordinates from where to start on the original image
//assuming you want to crop the center part
$src_x = floor(($original_width/2) - ($new_width/2));
$src_y = floor(($original_height/2) - ($new_height/2));
//create a new canvas with the new desired width, height
$temp = imagecreatetruecolor(90,90);
//copy the large image to this new canvas
imagecopyresampled($temp,$background,0,0,$src_x,$src_y,$new_width,$new_height,$original_width,$original_height);
//from right to left: source image, destination image, dest x, dest y,
//source x, source y, new width, new height, original width, original height
//save the canvas as an image
imagepng($temp);
This could be improved to handle larger images by first taking a central part relative to it's size and then scaling it down to the new canvas.

Categories