Making non square image render as square image without stretching - php

I have a PHP function that uses Imagick. I am trying to pull a non-square image from a URL and size it up to 500x500px where it doesn't stretch but fits inside this area. Additionally, I am using the Laravel framework and this function is in a controller that is rendered via route.
function myFunction()
{
function createGrid()
{
$placeholder = "https://placeholdit.imgix.net/~text?txtsize=33&txt=&w=500&h=500";
$im = new imagick("http://www.masters.com/images/pics/large/h_2015041243595.jpg");
$image = $im->resizeImage(500, 500, 0, 0, true);
// $target = new Imagick($placeholder);
// $target->setImageVirtualPixelMethod(Imagick::VIRTUALPIXELMETHOD_TRANSPARENT);
// $target->compositeImage($image, imagick::COMPOSITE_COPY, 0, 0);
header("Content-Type: image/png");
echo $image->getImageBlob();
}
}
I am getting an it rendered as:
How is $Image not an instance of imagick when it's defined as:
$im->resizeImage(500, 500, 0, 0, true);
What am I doing wrong and how do I fix it?

Alternative is cropping the image.
For Imagick this function: http://php.net/manual/en/imagick.cropimage.php
Imagick::cropImage — Extracts a region of the image
Steps:
Resize to format so width and height are minimal 500px
Crop with size of 500px

Related

Cannot display JPEG image in PHP Laravel project

Does anybody know what can call these files properly?
I'm trying to put text on a JPEG image, and apparently the way I'm calling those 2 files is not working
It is a PHP 7.4 Laravel 8 project and the script is located in a blade view.
<?php
// C:\xampp\htdocs\solidcadclass\public\storage\resources\arial.ttf
// C:\xampp\htdocs\solidcadclass\public\storage\resources\template.jpeg
$img = imagecreatefromjpeg('C:\xampp\htdocs\solidcadclass\public\storage\resources\template.jpeg');
$black = imagecolorallocate($img, 0, 0, 0); // OBJ, RGB
$txt = Auth::user()->name;
$font = 'C:\xampp\htdocs\solidcadclass\public\storage\resources\arial.ttf';
imagettftext(
$img, // Image object
24, // Font Size
0, // Angle
5, 24, // x,y
$black, // Color
$font, // Font to use
$txt // Text to write
);
// OUTPUT IMAGE
header("Content-type: image/jpeg");
imagejpeg($img);
I am getting bunch of weird symbols like:
����JFIF ...
Any advice on how to call files in functions like these would be really useful!
You can use Laravel response function with passing image in response parameter.
return response($img)->header('Content-type','image/jpeg');

Php GD adds black background around cropped source image

I’m creating an uploader that can upload jpg, giff and png images. Then converts them all too transparent PNG’s and then crops the image based on crop parameters send from client side. The crop can even supply negative axis coordinates, meaning the image is being cropped beyond image dimensions.
To ensure all supported formats can have transparency I first recreate the image into a transparent png, and this is working well.
//GET WIDTH AND HIEGHT OF UPLOADED JPG
list($imageWidth,$imageHeight)= getimagesize($originalDirectory.$file_name);
$image = imagecreatefromjpeg($originalDirectory.$file_name);
//CREATE NEW IMAGE BASED ON WIDTH AND HEIGHT OF SROUCE IMAGE
$bg = imagecreatetruecolor($imageWidth, $imageHeight);
//TRANSPARENCY SETTINGS FOR BOTH DESTINATION AND SOURCE IMAGES
$transparent2 = imagecolorallocatealpha($bg, 0, 0, 0, 127);
$transparent = imagecolorallocatealpha($image, 0,128,255,50); //ONLY TO ENSURE TRANSPARENCY IS WORKING
//SAVE TRANSPARENCY AMD FILL DESTINATION IMAGE
imagealphablending( $bg, false );
imagesavealpha($bg, true);
imagefill($bg, 0, 0, $transparent2);
//SAVE TRANSPARENCY AMD FILL SOURCE IMAGE
imagealphablending( $image, false );
imagesavealpha($image, true);
imagefill($image, 0, 0, $transparent); //ONLY TO ENSURE TRANSPARENCY IS WORKING
//CREATE AND SAVE AS PNG FILE WITH TRANSPARENCY
imagecopy($bg, $image, 0, 0, 0, 0, $imageWidth,$imageHeight);
header('Content-type: image/png');
imagepng($bg, $originalDirectory.$jpgFile);
imagedestroy($bg);
After the new png is created I use it to then only crop the image according to the parameters passed through from the client side scripting.
//GET NEWLY CREATED PNG
$src = imagecreatefrompng($originalSRC);
// NOT SURE IF NECESSARY BUT HAS NO EFFECT ON FINAL RESULT REGGARDLESS OF ANY SETTINGS DONE
imagealphablending( $image, false );
imagesavealpha($image, true);
//DEFINE DESTINATION CROPPED FILE
$thumbHighFilename = $thumbHighDirectory.'test.png';
//CREATE NEW IMAGE BASED ON FINAL CROP SIZE
$tmp = imagecreatetruecolor($cropWidth, $cropHeight);
//ENSURE DESTINATION HAS TRANSPARENT BACKGROUND
$transparent2 = imagecolorallocatealpha($tmp, 0, 0, 0, 127);
imagealphablending( $tmp, false );
imagesavealpha($tmp, true);
imagefill($tmp, 0, 0, $transparent2);
/* -------------------------------------------------
PROBLEM HERE
When I try to merge the two with the crop paramaters
send from client side. All transparencies work, except
where crop X and Y axis exceeds source image paramaters.
Currently 50px offset on destination image is to verify
transparency works.
The source coordinates are based on image not crop area.
Tried with both imagecopyresized & imagecopyresampled
-------------------------------------------------*/
imagecopyresized($tmp, $src, -50,-50, $xAxis,$yAxis,$cropWidth, $cropHeight, $pW, $pH);
//SAVE FINAL IMAGE
header('Content-type: image/png');
imagepng($tmp, $thumbHighFilename);
imagedestroy($tmp);
This is where the source and destination images still has there transparency; however the negative coordinates creates a black background around the source image. How can I get that to be transparent?
While I found a lot about transparencies, nothing has been a proper solution. For example imagefill afterwards will not work as source could use 100% black around the edges and will make that also transparent then, which it shouldn’t.
CLIENT SIDE CROP EXAMPLE WITH INDICATIONS
CURRENT FINAL IMAGE RESULT WITH ADDED INDICATIONS
From what I could find it seems that there is no way for the GD imagecopyresized and imagecopyresampled to inherit the default backgrounds of the images it is cropping. Thus it keeps adding the default black background to the source image.
The biggest problem I’ve had was actually the crop container being responsive, thus very difficult to determine crop parameters.
To get around the problem I asked my frontend developer to send me more parameters from the crop. Below are all parameters now being passed to php, and the variables in php that are linked to the parameters received:
$xAxisCropper & $yAxisCropper – The variables get the X and Y
coordinates of the container not the image being cropped.
$pW & $pH – Defines the width and height of the crop box.
$containerWidth & $containerheight – As the container is responsive
getting the height and width helps understand what size the
coordinates where calculated on.
$imResizeHeight & $imResizeWidth – Since the images in the container
are always set to be contained within the container, it was important
to get the width and height into which the image is being resized by
the CSS. Giving understanding of what is happening with the image
within the responsive container.
$originalWidth & $originalHeight – Defines the original size of the
image and could either be passed to php or retrieved from the
original image uploaded to the server.
With these parameters I could now recreate the container with the image in the centre, and crop the newly created image. Before I crop it’s important to get the right scaling of the image for the crop, in order to ensure the best quality image is cropped and not compressed before cropping.
To do this I started by determining if the image in the container is being scaled up or down within the container. If scaled up image needs to be scaled to container size, if scaled down the container needs to be increased to have the image fit in the container. Below is the code that currently determines this, and changes the necessary parameters accordingly:
//IF CSS CONTAIN RESIZES HEIGHT EQUAL TO CROP CONTAINER HEIGHT
if($imResizeHeight == $containerheight){
//IF IMAGE SIZE WAS INCREASED
if($imResizeHeight>$originalHeight){
//DEFINE NEW IMAGE SIZE TO SCALE TO CONTAINER
$new_height = $imResizeHeight;
$new_width = $originalWidth * ($new_height / $originalHeight);
$scale = 'image'; //DEFINE WHAT IS BEING INCREASED
//ESLSE INCREASE CONTAINER TO IMAGE HEIGHT DIMENSIONS
}else{
//RECALCULATE WIDTH & HEIGHT OF CONTAINER
$newContainerWidth = $containerWidth * ($originalHeight / $containerheight);
$newContainerheight = $originalHeight;
$scale = 'container'; //DEFINE WHAT IS BEING INCREASED
}
//IF CSS CONTAIN RESIZES WIDTH EQUAL TO CROP CONTAINER WIDTH
}elseif($imResizeWidth == $containerWidth) {
//IF IMAGE SIZE WAS INCREASED
if($imResizeWidth>$originalWidth){
//DEFINE NEW IMAGE SIZE TO SCALE TO CONTAINER
$new_width = $imResizeWidth;
$new_height = $originalHeight * ($new_width / $originalWidth);
$scale = 'image'; //DEFINE WHAT IS BEING INCREASED
//ESLSE INCREASE CONTAINER TO IMAGE WIDTH DIMENSIONS
}else{
//RECALCULATE WIDTH & HEIGHT OF CONTAINER
$newContainerheight = $containerheight * ($originalWidth / $containerWidth);
$newContainerWidth = $originalWidth;
$scale = 'container'; //DEFINE WHAT IS BEING INCREASED
}
}
//IF IMAGE WAS INCREASED
if($scale=='image'){
//SCALE IMAGE
$src = imagescale ( $src , $new_width , $new_height, IMG_BILINEAR_FIXED);
imagepng($src,$originalSRC,0);
//ADD CHANGES TO VARIABLES USED IN CROP
$pH = $pH * ($new_height / $originalHeight);
$pW = max(0, round($pW * ($new_width / $originalWidth)));
$originalWidth = $new_width;
$originalHeight = $new_height;
$newContainerWidth = $containerWidth;
$newContainerheight = $containerheight;
//ELSE CONTAINER WAS INCREASED
}else {
//RECALCULATE COORDINATES OF CONTAINER
$yAxisCropper = max(0, round($yAxisCropper * ($newContainerheight / $containerheight)));
$xAxisCropper = max(0, round($xAxisCropper * ($newContainerWidth / $containerWidth)));
}
Once the parameters have been redefined according to the scaling, I then create the transparent background according to the container size and add the image in the centre. Thus creating a proper version of the crop container as an image, below the code for creating the new image:
//CALCULATE CENTRE OF NEW CONTAINER
$centreX = max(0, round(($newContainerWidth-$originalWidth)/2));
$centreY = max(0, round(($newContainerheight-$originalHeight)/2));
//CREATE NEW IMAGE BASED ON WIDTH AND HEIGHT OF SROUCE IMAGE
$bg = imagecreatetruecolor($newContainerWidth, $newContainerheight);
//SAVE TRANSPARENCY AMD FILL DESTINATION IMAGE
$transparent = imagecolorallocatealpha($bg, 0,0,0,127);
imagealphablending( $bg, false);
imagesavealpha($bg, true);
imagefill($bg, 0, 0, $transparent);
//CREATE AND SAVE AS PNG FILE WITH TRANSPARENCY
imagecopy($bg, $src, $centreX, $centreY, 0, 0, $originalWidth,$originalHeight);
header('Content-type: image/png');
imagepng($bg, $originalSRC, 0);
imagedestroy($bg);
The result till thus far:
It is only at this point that I send the new image to be cropped according to the specified width and height. Code below:
$src = imagecreatefrompng($originalSRC);
$thumbHighFilename = $thumbHighDirectory.$new_image;
$tmp = imagecreatetruecolor($cropWidth, $cropHeight);
$transparent2 = imagecolorallocatealpha($tmp, 0, 0, 0, 127);
imagealphablending( $tmp, false );
imagesavealpha($tmp, true);
imagefill($tmp, 0, 0, $transparent2);
imagealphablending( $tmp, false );
imagesavealpha($tmp, true);
imagecopyresampled($tmp, $src, 0,0, $xAxisCropper,$yAxisCropper,$cropWidth, $cropHeight, $pW, $pH);
header('Content-type: image/png');
imagepng($tmp, $thumbHighFilename, 2);
Final result cropped 400x300
This has been the only way so far that I’ve managed to solve the problem. Code could probably still be optimised, but if someone has a more optimal solution please share.
I also wish to thank my frontend developer Salem for helping me to solve this irritating issue.
I also did have this annoying black Background Problem with png Files and the imagecropauto Function.
After "some" Tests, i have found a Solution as it seems. At least it works for me.
Here is my mofified Code:
$im=imagecreatefrompng("yourpicture.png");
$cropped=imagecropauto($im, IMG_CROP_SIDES);
imagesavealpha($cropped,true);
if($cropped !==false) {
imagedestroy($im);
$im=$cropped;
}
imagepng($im, "yourpicturecropped.png");
imagedestroy($im);

PHP: embed text in image when uploading it

I followed this example to embed text in image while uploading it but it's not working.
This is my code:
header('Content-type: image/jpeg');
$img = $_FILES['mainImage']['name'];
list($txt, $ext) = explode(".", $img);
$imgName = "ac_".time().".".$ext;
$tmp = $_FILES['mainImage']['tmp_name'];
$textToImage = imagecreatefromjpeg($tmp);
// Allocate A Color For The Text
$white = imagecolorallocate($textToImage, 255, 255, 255);
// Set Path to Font File
$font_path = '../assets/fonts/font.ttf';
// Set Text to Be Printed On Image
$text = "Test text";
// Print Text On Image
imagettftext($textToImage, 25, 0, 75, 300, $white, $font_path, $text);
$imageUploaded = move_uploaded_file($tmp, 'images_path/'.$imgName);
if(!$imageUploaded){
die('Error upload image!');
}
The image is uploaded but wihout text in it !
For this we are working with GD library.
"PHP is not limited to creating just HTML output. It can also be used
to create and manipulate image files in a variety of different image
formats, including GIF, PNG, JPEG, WBMP, and XPM. Even more
convenient, PHP can output image streams directly to a browser. You
will need to compile PHP with the GD library of image functions for
this to work. GD and PHP may also require other libraries, depending
on which image formats you want to work with."
You can use the image functions in PHP to get the size of JPEG, GIF, PNG, SWF, TIFF and JPEG2000 images.
The following code sample demonstrates the use of GD library to watermark images on the fly. The method demonstrated here to watermark an uploaded image is to overlay the original image with another image, preferably a transparent PNG image.
PHP provides a rich set of functions to create and alter images on the fly. These functions require the GD library, which is bundled with PHP since version 4.3.
The HTML form needs a file upload element: <input type="file">. You must also specify the correct encoding type: enctype="multipart/form-data" for the form.
/ link to the font file no the server
$fontname = 'font/Capriola-Regular.ttf';
// controls the spacing between text
$i=30;
//JPG image quality 0-100
$quality = 85;
function create_image($user){
global $fontname;
global $quality;
$file = "covers/".md5($user[0]['name'].$user[1]['name'].$user[2]['name']).".jpg";
// if the file already exists dont create it again just serve up the original
if (!file_exists($file)) {
// define the base image that we lay our text on
$im = imagecreatefromjpeg("pass.jpg");
// setup the text colours
$color['grey'] = imagecolorallocate($im, 54, 56, 60);
$color['green'] = imagecolorallocate($im, 55, 189, 102);
// this defines the starting height for the text block
$y = imagesy($im) - $height - 365;
// loop through the array and write the text
foreach ($user as $value){
// center the text in our image - returns the x value
$x = center_text($value['name'], $value['font-size']);
imagettftext($im, $value['font-size'], 0, $x, $y+$i, $color[$value['color']], $fontname,$value['name']);
// add 32px to the line height for the next text block
$i = $i+32;
}
// create the image
imagejpeg($im, $file, $quality);
}
return $file;
}
function center_text($string, $font_size){
global $fontname;
$image_width = 800;
$dimensions = imagettfbbox($font_size, 0, $fontname, $string);
return ceil(($image_width - $dimensions[4]) / 2);
}
$user = array(
array(
'name'=> 'Slimen Tunis',
'font-size'=>'25',
'color'=>'black'),
array(
'name'=> 'Web developer',
'font-size'=>'16',
'color'=>'grey'),
array(
'name'=> 'SlimenTunis#webdeveloper.com',
'font-size'=>'13',
'color'=>'green'
)
);
// run the script to create the image
$filename = create_image($user);
here we have two functions to make it as simple as possible. To run the code simply pass the $user array data to the function and it’ll save the new image in the folder ‘covers’ on your server. The function returns the file url so you just need to echo it into an image tag as shown below. Check out the demo where you can create your own.
$filename = create_image($user);
<img src="<?=$filename;?>" width="800" height="600"/>
You can try using the Intervention library. I use it for doing what you're asking about. It is quite simple to understand and the documentation is is well-written.

PHP imagecopy with transparent background

I use this code to create an image from another png image, the background is black by default. My question is how to set a transparent background?
$input = imagecreatefrompng('image.png');
$output = imagecreatetruecolor(50, 50);
imagecopy($output, $input, 4,0, 8,8, 8,8);
imagecopy... etc.
header('Content-Type: image/png');
imagepng($output);
Is there a easy way of doing this? Thanks
Sets the transparent color in the given image.
int imagecolortransparent ( resource $image [, int $color ] )
Here's the link
Since the PHP function imagecopymerge doesn't work with the Alpha channel, you'll want to use the function from the first comment on this page imagecopymerge_alpha:
http://php.net/manual/en/function.imagecopymerge.php
Just have the transparent image as the base and merge it together with the image you need.
I've tried it out and it works fine for a project of mine.
None of the solutions worked for me, it would always convert transparent pixels on the source image to black on the destination image. What worked was changing imagecopy/imagecopymerge/imagecopymerge_alpha to imagecopyresampled and just passing the same width and height twice.
//Create destination image.
$png = imagecreatetruecolor(1024, 1024);
imagealphablending($png, false);
imagesavealpha($png, true);
//Make destination image be all transparent.
$color = imagecolorallocatealpha($png, 0, 0, 0, 127); //127 means completely transparent.
imagefill($png, 0, 0, $color);
//Load source image.
$png2 = imagecreatefrompng($sourceurl);
imagealphablending($png2, false);
imagesavealpha($png2, true);
$sizex = imagesx($png2);
$sizey = imagesy($png2);
//Copy to destination and save to file.
imagecopyresampled( $png, $png2,
0, 0,
0, 0,
$sizex, $sizey,
$sizex, $sizey);
imagepng($png, "result.png");
imagealphablending($input, true);
imagesavealpha($input, true);
imagealphablending($output, true);
imagesavealpha($output, true);
Or propably
int imagesavealpha($img,true);
http://www.php.net/manual/en/function.imagesavealpha.php
Full credit goes to:
http://consistentcoder.com/combine-a-transparent-png-image-on-top-of-another-image-with-php
The following code will overlay the foreground image onto the background image while preserving the transparency of the overlay:
//set the source image (foreground)
$sourceImage = 'table.png';
//set the destination image (background)
$destImage = 'create-a-surreal-head-of-tree-photo-manipulation.jpg';
//get the size of the source image, needed for imagecopy()
list($srcWidth, $srcHeight) = getimagesize($sourceImage);
//create a new image from the source image
$src = imagecreatefrompng($sourceImage);
//create a new image from the destination image
$dest = imagecreatefromjpeg($destImage);
//set the x and y positions of the source image on top of the destination image
$src_xPosition = 75; //75 pixels from the left
$src_yPosition = 50; //50 pixels from the top
//set the x and y positions of the source image to be copied to the destination image
$src_cropXposition = 0; //do not crop at the side
$src_cropYposition = 0; //do not crop on the top
//merge the source and destination images
imagecopy($dest,$src,$src_xPosition,$src_yPosition,
$src_cropXposition,$src_cropYposition,
$srcWidth,$srcHeight);
//output the merged images to a file
/*
* '100' is an optional parameter,
* it represents the quality of the image to be created,
* if not set, the default is about '75'
*/
imagejpeg($dest,
'combine-a-transparent-png-image-on-top-of-another-image-with-php-01.jpg',
100);
//destroy the source image
imagedestroy($src);
//destroy the destination image
imagedestroy($dest);

Combine 2 png-24 transparent Images using Php

Hello I am trying to combine two transparent png-24 images, both size 400width, 150height.
A background: ["http://www.fenixflame.net/Background-Zanaris-24.png"][1]
And the image I want to overlay adobe the background:
["http://www.fenixflame.net/Bandos-Slayer-24.png"][2]
I've tryed overlaying transparent images using php but only png-8 images. Can't use png-8 beacause the images just don't render correctly.
Edit: Code I've tryed:
$image = imagecreatefrompng("http://www.fenixflame.net/Background-Zanaris-24.png");
$frame = imagecreatefrompng("http://www.fenixflame.net/Bandos-Slayer-24.png");
//
//imagealphablending($frame,true);
//
$insert_x = imagesx($frame);
$insert_y = imagesy($frame);
imagecopymerge($image,$frame,0,0,0,0,$insert_x,$insert_y,100);
//
//# Save the image to a file imagepng($image, '/path/to/save/image.png');
imagepng($image, "/home1/fenixfla/public_html/Images/Signatures/NewImageBG.png");
//
//# Output straight to the browser.
imagepng($image);
//
I have write a small example to merge two transparent image in this link scitam.com
try this code it works fine.
$width = 200;
$height = 200;
$base_image = imagecreatefromjpeg("base.jpg");
$top_image = imagecreatefrompng("top.png");
$merged_image = "merged.png";
imagesavealpha($top_image, true);
imagealphablending($top_image, true);
imagecopy($base_image, $top_image, 0, 0, 0, 0, $width, $height);
imagepng($base_image, $merged_image);
Use GD Library to render the image and output it in php.
http://www.php.net/manual/en/ref.image.php
It gets pretty hairy after that. You have to use start doing things like
imagealphablending($image, false);
imagesavealpha($image, true);
and so on to make sure transparency is correct.
you can see an example of what I did for a client way back on their front page here. It was super tedious and a huge pain. Have fun
How about using lib ImageMagick composite (http://www.imagemagick.org/script/composite.php)
function composite() {
$command = "/usr/local/bin/composite [... your properties...]";
exec($command, $output, $result);
return ($result == 0 && $output[0] == "");
}
You might want to check this out: http://php.net/manual/en/function.imagecopymerge.php
The imagecopymerge function is part of the PHP GD library.

Categories