How to crop image like with object-fit:cover by php? - php

Could you help please, I crop image for thumbnail with php code below.
But some pictures crops with black frames at top and bottom. How to do it properly?
$w = 265;
$h = 198;
if (empty($w)) {
$w = ceil($h / ($height / $width));
}
if (empty($h)) {
$h = ceil($w / ($width / $height));
}
$tmp = imageCreateTrueColor($w, $h);
$tw = ceil($h / ($height / $width));
$th = ceil($w / ($width / $height));
if ($tw < $w) {
imageCopyResampled($tmp, $img, ceil(($w - $tw) / 2), 0, 0, 0, $tw, $h, $width, $height);
} else {
imageCopyResampled($tmp, $img, 0, ceil(($h - $th) / 2), 0, 0, $w, $th, $width, $height);
}
$img = $tmp;
Links to origninal photo and with black frames:

Related

Resizing font size and padding using gd to create a dynamic bar chart

Inspired by this code, I am trying to create a simple bar chart able to dynamically create, resize both bars and texts depends on the the $data, $height and $weight:
<?php
$width = 300;
$height = 200;
$font_path = getenv('WINDIR') . DIRECTORY_SEPARATOR . "Fonts" . DIRECTORY_SEPARATOR;
$font = 'arial.ttf';
$data = ['jan'=>30,'fev'=>40,'mar'=>90,'apr'=>77,
'mai'=>33, 'jun'=>44, 'bigggggggg' => 80];
$columns = count($data);
$padding = ($width+$height)/100;
$column_width = $width / $columns;
$image = imagecreate($width, $height);
$gray = imagecolorallocate($image, 0xcc, 0xcc, 0xcc);
$black = imagecolorallocate($image, 0, 0, 0);
$gray_lite = imagecolorallocate($image, 0xee, 0xee, 0xee);
$gray_dark = imagecolorallocate($image, 0x7f, 0x7f, 0x7f);
$white = imagecolorallocate($image, 0xff, 0xff, 0xff);
imagefilledrectangle($image, 0, 0, $width, $height, $white);
$maxv = max($data);
$array_values = array_values($data);
$array_keys = array_keys($data);
for ($i = 0; $i < $columns; $i++) {
$font_size = ($height / 100) * $padding;
$column_height = ($height / 100) * (( $array_values[$i] / $maxv) * 100);
$string = $array_keys[$i];
$x1 = $i * $column_width;
$y1 = $height - $column_height;
$x2 = (($i + 1) * $column_width) - $padding;
$y2 = $height - ($padding*4);
$maxChars = ($font_size * 2) / $padding;
if (strlen($string) > ($maxChars)) {
$string = substr($string, 0, $maxChars) . '...';
}
imagefilledrectangle($image, $x1, $y1, $x2, $y2, $gray);
imagettftext($image, $font_size, 0, $x1, $y2+$font_size+$padding, $black, $font_path.$font,
$string);
imageline($image, $x1, $y1, $x1, $y2, $gray_lite);
imageline($image, $x1, $y2, $x2, $y2, $gray_lite);
imageline($image, $x2, $y1, $x2, $y2, $gray_dark);
}
header("Content-type: image/png");
imagepng($image);
imagedestroy($image);
Using 300x200 its okay:
But using 600x400:
What Can I do to fix that?
There is only Font Size Calculations Which can be fixed earlier code:
$font_size = ($height / 100) * $padding; //Changing this line
$column_height = ($height / 100) * (( $array_values[$i] / $maxv) * 100);
$string = $array_keys[$i];
$x1 = $i * $column_width;
$y1 = $height - $column_height;
$x2 = (($i + 1) * $column_width) - $padding;
$y2 = $height - ($padding*4);
$maxChars = ($font_size * 2) / $padding;
after changing it dynamic it would be as under:
$column_height = ($height / 100) * (( $array_values[$i] / $maxv) * 100);
$string = $array_keys[$i];
$x1 = $i * $column_width;
$y1 = $height - $column_height;
$x2 = (($i + 1) * $column_width) - $padding;
$y2 = $height - ($padding*4);
$font_size = ($x2 - $x1) / 4; //Changed line and location
$maxChars = ($font_size * 2) / $padding;
Except this change nothing is required.
You create the $font_size base on $padding, the $font_size will grow fast in the case size of chart grow
Instead of it, make the $font_size depend on the $height and Y position of the bars, it should work fine, please try this script instead
<?php
$width = 600;
$height = 400;
$font_path = getenv('WINDIR') . DIRECTORY_SEPARATOR . "Fonts" . DIRECTORY_SEPARATOR;
$font = 'arial.ttf';
$data = ['jan'=>30,'fev'=>40,'mar'=>90,'apr'=>77,
'mai'=>33, 'jun'=>44, 'bigggggggg' => 80];
$columns = count($data);
$padding = ($width+$height)/100;
$column_width = $width / $columns;
$image = imagecreate($width, $height);
$gray = imagecolorallocate($image, 0xcc, 0xcc, 0xcc);
$black = imagecolorallocate($image, 0, 0, 0);
$gray_lite = imagecolorallocate($image, 0xee, 0xee, 0xee);
$gray_dark = imagecolorallocate($image, 0x7f, 0x7f, 0x7f);
$white = imagecolorallocate($image, 0xff, 0xff, 0xff);
imagefilledrectangle($image, 0, 0, $width, $height, $white);
$maxv = max($data);
$array_values = array_values($data);
$array_keys = array_keys($data);
for ($i = 0; $i < $columns; $i++) {
$column_height = ($height / 100) * (( $array_values[$i] / $maxv) * 100);
$string = $array_keys[$i];
$x1 = $i * $column_width;
$y1 = $height - $column_height;
$x2 = (($i + 1) * $column_width) - $padding;
$y2 = $height - ($padding*4);
$maxChars = ($font_size * 2) / $padding;
if (strlen($string) > ($maxChars)) {
$string = substr($string, 0, $maxChars) . '...';
}
$font_size = ($height - $y2) / 2.5;
imagefilledrectangle($image, $x1, $y1, $x2, $y2, $gray);
imagettftext($image, $font_size, 0, $x1, $y2+$font_size+$padding, $black, $font_path.$font,
$string);
imageline($image, $x1, $y1, $x1, $y2, $gray_lite);
imageline($image, $x1, $y2, $x2, $y2, $gray_lite);
imageline($image, $x2, $y1, $x2, $y2, $gray_dark);
}
header("Content-type: image/png");
imagepng($image);
imagedestroy($image);
Just small change on $font_size = ($height - $y2) / 2.5;
Try if this works.
Basically your font size was height/100 which was working when height was 200, but when you have doubled the height, we need to change the font size to match it as well.
See if this is the desired result MaxInfo.Tech
<?php
$width = 600;
$height = 400;
$font_path = getenv('WINDIR') . DIRECTORY_SEPARATOR . "Fonts" . DIRECTORY_SEPARATOR;
$font = 'arial.ttf';
$data = ['jan'=>30,'fev'=>40,'mar'=>90,'apr'=>77,
'mai'=>33, 'jun'=>44, 'bigggggggg' => 80];
$columns = count($data);
$padding = ($width+$height)/100;
$column_width = $width / $columns;
$image = imagecreate($width, $height);
$gray = imagecolorallocate($image, 0xcc, 0xcc, 0xcc);
$black = imagecolorallocate($image, 0, 0, 0);
$gray_lite = imagecolorallocate($image, 0xee, 0xee, 0xee);
$gray_dark = imagecolorallocate($image, 0x7f, 0x7f, 0x7f);
$white = imagecolorallocate($image, 0xff, 0xff, 0xff);
imagefilledrectangle($image, 0, 0, $width, $height, $white);
$maxv = max($data);
$array_values = array_values($data);
$array_keys = array_keys($data);
for ($i = 0; $i < $columns; $i++) {
$font_size = ($height / 200) * $padding;
$column_height = ($height / 100) * (( $array_values[$i] / $maxv) * 100);
$string = $array_keys[$i];
$x1 = $i * $column_width;
$y1 = $height - $column_height;
$x2 = (($i + 1) * $column_width) - $padding;
$y2 = $height - ($padding*4);
$maxChars = ($font_size * 2) / $padding;
if (strlen($string) > ($maxChars)) {
$string = substr($string, 0, $maxChars) . '...';
}
imagefilledrectangle($image, $x1, $y1, $x2, $y2, $gray);
imagettftext($image, $font_size, 0, $x1, $y2+$font_size+$padding, $black, $font_path.$font,
$string);
imageline($image, $x1, $y1, $x1, $y2, $gray_lite);
imageline($image, $x1, $y2, $x2, $y2, $gray_lite);
imageline($image, $x2, $y1, $x2, $y2, $gray_dark);
}
header("Content-type: image/png");
imagepng($image);
imagedestroy($image);
Also Please note to format it better you can change other variables also which are based on height or width, to something more dynamic than a static divider of 100.

Cropping images in PHP leaves black space

This is likely a duplicate, but every solution I have looked at seems to not work for me, so not sure what I am doing differently.
I don't understand too much about image manipulation yet, but cropping images seems to add lots of black space around the right/bottom of the image when using imagecopyresampled to place it over another. They are all JPEGs.
This is my crop function:
function thumbImage($thumb_img,$img_size,$shape){
$width = 250;
$height = 250;
list($w, $h) = $img_size;
if($w > $h) {
$new_height = $height;
$new_width = floor($w * ($new_height / $h));
$crop_x = ceil(($w - $h) / 2);
$crop_y = 0;
} else {
$new_width = $width;
$new_height = floor( $h * ( $new_width / $w ));
$crop_x = 0;
$crop_y = ceil(($h - $w) / 2);
}
$tmp_img = imagecreatetruecolor($width,$height);
imagecopyresampled($tmp_img, $thumb_img, 0, 0, $crop_x, $crop_y, $new_width, $new_height, $w, $h);
return $tmp_img;
}
Any solutions with an explanation of how it works would be greatly appreciated.
Try this:
function thumbImage($source_img,$max_size){
list($w, $h) = getimagesize($source_img);
if($w>$h){
$width = ($max_size/$h)*$w;
$height = $max_size;
}else{
$width = $max_size;
$height = ($max_size/$w)*$h;
}
$x = ($max_size-$width)/2;
$y = ($max_size-$height)/2;
$thumb_img = imagecreatetruecolor($max_size,$max_size);
imagecopyresampled($thumb_img, $source_img, $x, $y, 0, 0, $width, $height, $w, $h);
return $thumb_img;
}

PHP Captcha Image can not be displayed because of errors

This is my static function in class 'image_utils.php'
public static function getCaptcha()
{
try {
$width = 200;
$height = 30;
$font = 'fonts/arial.ttf';
//
if (!file_exists($font)) {
throw new Exception('Error Font not found');
}
//
$image = imagecreatetruecolor($width, $height);
$white = imagecolorallocate($image, 255, 255, 255);
$grey = imagecolorallocate($image, 180, 180, 180);
$black = imagecolorallocate($image, 0, 0, 0);
//
for ($sq = 1; $sq <= 10; $sq++) {
$cx = (int)rand(0, $width / 2);
$cy = (int)rand(0, $height);
$h = $cy + (int)rand(0, $height / 5);
$w = $cx + (int)rand($width / 3, $width);
if (!imagefilledrectangle($image, $cx, $cy, $w, $h, $white)) {
throw new Exception('Error in White Fill');
}
}
//
$ellipse_count = 5;
for ($i = 0; $i < $ellipse_count; $i++) {
$cx = (int)rand(-1 * ($width / 2), $width + ($width / 2));
$cy = (int)rand(-1 * ($height / 2), $height + ($height / 2));
$h = (int)rand($height / 2, 2 * $height);
$w = (int)rand($width / 2, 2 * $width);
if (!imageellipse($image, $cx, $cy, $w, $h, $grey)) {
throw new Exception('Error in Grey Fill');
}
}
//
imagefttext($image, 20, 0, 10, 20, $black, $font, 'Captcha');
header('Content-type: image/png');
if (!imagepng($image)) {
throw new Exception('Error in ImagePng');
}
} catch (Exception $ex) {
echo $ex->getMessage();
}
}
Calling it in 'log.php' in img tag:
<img src='<?php image_utils::getCaptcha() ?>'/>
Gives an error 'The image cannot be displayed because it contains errors'. I have create a check for font file as shown in code so the font file is in inclusion. Please throw some light.
Thanks in Advance.

How to crop a verticaly and horizontaly centered version of an image?

I am currently resizing an image to a custom with keeping aspect ratio:
class ImgResizer {
var $originalFile = '$newName';
function ImgResizer($originalFile = '$newName') {
$this -> originalFile = $originalFile;
}
function resize($newWidth, $targetFile) {
if (empty($newWidth) || empty($targetFile)) {
return false;
}
$src = imagecreatefromjpeg($this -> originalFile);
list($width, $height) = getimagesize($this -> originalFile);
$newHeight = ($height / $width) * $newWidth;
$tmp = imagecreatetruecolor($newWidth, $newHeight);
imagecopyresampled($tmp, $src, 0, 0, 0, 0, $newWidth, $newHeight, $width, $height);
if (file_exists($targetFile)) {
unlink($targetFile);
}
imagejpeg($tmp, $targetFile, 95);
}
}
Usage:
$work = new ImgResizer($path);
$work -> resize(200, $path);
But i would like to get a 200x200px version o the image. And it should be vertically amd horizontally centered ( basically get the main 200px of the image)
is that possible?
-EDIT-
function resize($newWidth, $targetFile) {
if (empty($newWidth) || empty($targetFile)) {
return false;
}
$src = imagecreatefromjpeg($this -> originalFile);
list($width, $height) = getimagesize($this -> originalFile);
$newHeight = $newWidth;
if ($width > $newWidth){
$srcx = $width/2 - $newWidth/2;
$destx = 0;
}
else{
$srcx = 0;
$destx = $newWidth/2 - $width/2;
}
if ($height > $newHeight){
$srcy = $height/2 - $newHeight/2;
$desty = 0;
}
else{
$srcy = 0;
$desty = $newHeight/2 - $height/2;
}
$tmp = imagecreatetruecolor($newWidth, $newHeight);
imagecopyresampled($tmp, $src, $destx, $desty, $srcx, $srcy, $newWidth, $newHeight, $width, $height);
if (file_exists($targetFile)) {
unlink($targetFile);
}
imagejpeg($tmp, $targetFile, 95);
}
Would create something unexpected: HTTP://209.51.221.243/integracion/files/uploads/1_050.JPG
Try
if ($width > $newWidth){
$srcx = $width/2 - $newWidth/2;
$destx = 0;
$w = $newWidth;
}
else{
$srcx = 0;
$destx = $newWidth/2 - $width/2;
$w = $width;
}
if ($height > $newHeight){
$srcy = $height/2 - $newHeight/2;
$desty = 0;
$h = $newHeight;
}
else{
$srcy = 0;
$desty = $newHeight/2 - $height/2;
$h = $keight;
}
imagecopyresampled($tmp, $src, $destx, $desty, $srcx, $srcy, $w, $h, $w, $h);

Image resize with php [duplicate]

This question already has answers here:
Resize image in PHP
(13 answers)
Closed 6 years ago.
function resize($originalImage){
list($width, $height) = getimagesize($originalImage);
$newName=basename($originalImage);
$imageResized = imagecreatetruecolor(128, 128);
$imageTmp = imagecreatefromjpeg ($originalImage);
imagecopyresampled($imageResized, $imageTmp, 0, 0, 0, 0, 128, 128, $width, $height);
imagejpeg($imageResized, "resizedImg/$newName",100);
imageDestroy($imageResized);
}
The script returns the image with the correct name but it's just black? Any ideas?
If you have trouble with image resizing use this code for it. Do the modifications as you need it.
function resizeImage($file){
define ('MAX_WIDTH', 1500);//max image width
define ('MAX_HEIGHT', 1500);//max image height
define ('MAX_FILE_SIZE', 10485760);
//iamge save path
$path = 'storeResize/';
//size of the resize image
$new_width = 128;
$new_height = 128;
//name of the new image
$nameOfFile = 'resize_'.$new_width.'x'.$new_height.'_'.basename($file['name']);
$image_type = $file['type'];
$image_size = $file['size'];
$image_error = $file['error'];
$image_file = $file['tmp_name'];
$image_name = $file['name'];
$image_info = getimagesize($image_file);
//check image type
if ($image_info['mime'] == 'image/jpeg' or $image_info['mime'] == 'image/jpg'){
}
else if ($image_info['mime'] == 'image/png'){
}
else if ($image_info['mime'] == 'image/gif'){
}
else{
//set error invalid file type
}
if ($image_error){
//set error image upload error
}
if ( $image_size > MAX_FILE_SIZE ){
//set error image size invalid
}
switch ($image_info['mime']) {
case 'image/jpg': //This isn't a valid mime type so we should probably remove it
case 'image/jpeg':
$image = imagecreatefromjpeg ($image_file);
break;
case 'image/png':
$image = imagecreatefrompng ($image_file);
break;
case 'image/gif':
$image = imagecreatefromgif ($image_file);
break;
}
if ($new_width == 0 && $new_height == 0) {
$new_width = 100;
$new_height = 100;
}
// ensure size limits can not be abused
$new_width = min ($new_width, MAX_WIDTH);
$new_height = min ($new_height, MAX_HEIGHT);
//get original image h/w
$width = imagesx ($image);
$height = imagesy ($image);
//$align = 'b';
$zoom_crop = 1;
$origin_x = 0;
$origin_y = 0;
//TODO setting Memory
// generate new w/h if not provided
if ($new_width && !$new_height) {
$new_height = floor ($height * ($new_width / $width));
} else if ($new_height && !$new_width) {
$new_width = floor ($width * ($new_height / $height));
}
// scale down and add borders
if ($zoom_crop == 3) {
$final_height = $height * ($new_width / $width);
if ($final_height > $new_height) {
$new_width = $width * ($new_height / $height);
} else {
$new_height = $final_height;
}
}
// create a new true color image
$canvas = imagecreatetruecolor ($new_width, $new_height);
imagealphablending ($canvas, false);
if (strlen ($canvas_color) < 6) {
$canvas_color = 'ffffff';
}
$canvas_color_R = hexdec (substr ($canvas_color, 0, 2));
$canvas_color_G = hexdec (substr ($canvas_color, 2, 2));
$canvas_color_B = hexdec (substr ($canvas_color, 2, 2));
// Create a new transparent color for image
$color = imagecolorallocatealpha ($canvas, $canvas_color_R, $canvas_color_G, $canvas_color_B, 127);
// Completely fill the background of the new image with allocated color.
imagefill ($canvas, 0, 0, $color);
// scale down and add borders
if ($zoom_crop == 2) {
$final_height = $height * ($new_width / $width);
if ($final_height > $new_height) {
$origin_x = $new_width / 2;
$new_width = $width * ($new_height / $height);
$origin_x = round ($origin_x - ($new_width / 2));
} else {
$origin_y = $new_height / 2;
$new_height = $final_height;
$origin_y = round ($origin_y - ($new_height / 2));
}
}
// Restore transparency blending
imagesavealpha ($canvas, true);
if ($zoom_crop > 0) {
$src_x = $src_y = 0;
$src_w = $width;
$src_h = $height;
$cmp_x = $width / $new_width;
$cmp_y = $height / $new_height;
// calculate x or y coordinate and width or height of source
if ($cmp_x > $cmp_y) {
$src_w = round ($width / $cmp_x * $cmp_y);
$src_x = round (($width - ($width / $cmp_x * $cmp_y)) / 2);
} else if ($cmp_y > $cmp_x) {
$src_h = round ($height / $cmp_y * $cmp_x);
$src_y = round (($height - ($height / $cmp_y * $cmp_x)) / 2);
}
// positional cropping!
if ($align) {
if (strpos ($align, 't') !== false) {
$src_y = 0;
}
if (strpos ($align, 'b') !== false) {
$src_y = $height - $src_h;
}
if (strpos ($align, 'l') !== false) {
$src_x = 0;
}
if (strpos ($align, 'r') !== false) {
$src_x = $width - $src_w;
}
}
// positional cropping!
imagecopyresampled ($canvas, $image, $origin_x, $origin_y, $src_x, $src_y, $new_width, $new_height, $src_w, $src_h);
} else {
imagecopyresampled ($canvas, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
}
//Straight from Wordpress core code. Reduces filesize by up to 70% for PNG's
if ( (IMAGETYPE_PNG == $image_info[2] || IMAGETYPE_GIF == $image_info[2]) && function_exists('imageistruecolor') && !imageistruecolor( $image ) && imagecolortransparent( $image ) > 0 ){
imagetruecolortopalette( $canvas, false, imagecolorstotal( $image ) );
}
$quality = 100;
$nameOfFile = 'resize_'.$new_width.'x'.$new_height.'_'.basename($file['name']);
if (preg_match('/^image\/(?:jpg|jpeg)$/i', $image_info['mime'])){
imagejpeg($canvas, $path.$nameOfFile, $quality);
} else if (preg_match('/^image\/png$/i', $image_info['mime'])){
imagepng($canvas, $path.$nameOfFile, floor($quality * 0.09));
} else if (preg_match('/^image\/gif$/i', $image_info['mime'])){
imagegif($canvas, $path.$nameOfFile);
}
}

Categories