Rotate and crop image batch - php

EDIT: please forget about this question! I made a stupid error in the original code.
The example code works as expected!
I'm trying to rotate AND crop images.
I have this so far:
$w = 100;
$h = 400;
$img1 = imagecreatefromjpeg('image1.jpg');
$img2 = imagecreatefromjpeg('image2.jpg');
for ($i = 0; $i < 2; $i++) {
${'img'.$i + 3} = imagecreatetruecolor($h, $h);
imagecopy(${'img'.$i + 3}, ${'img'.$i + 1}, 0, 0, 0, 0, $w, $h);
${'img'.$i + 3} = imagerotate(${'img'.$i + 3}, 90, 0);
${'img'.$i + 3} = imagecrop(${'img'.$i + 3}, array(0, 0, $h, $w));
imagejpeg(${'img'.$i + 3});
imagedestroy(${'img'.$i + 3});
imagedestroy(${'img'.$i + 1});
}
So what I essentially do is open some JPGs, create new images, copy the JPGs into the new images and then crop the images.
Alas this results in empty images ...
What am I doing wrong?

No idea if this will make any difference to the lack of output - but what do $img1 & $img2 do - they don't get used as far as i can see?
#error_reporting( E_ALL );
$w = 100;
$h = 400;
$img1 = imagecreatefromjpeg('image1.jpg');
$img2 = imagecreatefromjpeg('image2.jpg');
for ($i = 0; $i < 3; $i++) {
$new=${'img'.$i + 3};
$src=${'img'.$i + 1};
$new = imagecreatetruecolor($h, $h);
imagecopy( $new, $src, 0, 0, 0, 0, $w, $h);
$new = imagerotate($new, 90, 0);
$new = imagecrop($new, array(0, 0, $h, $w));
imagejpeg($new);
imagedestroy($new);
imagedestroy($src);
break;/* just to see if it gets this far*/
}

Firstly, you should consider using image copy resampled for a better quality of result from the process.
Then, you need to correctly use the imagejpeg function, currently you are simply loading the JPGs and outputting them directly, which may be what you want but you're in a loop and you can't loop load multiple images directly to the same file. It also means that the image you're seeing (or not) is the final image in the set.
Your Problem is that your for loop runs THREE times but your only have data associated with the first two instances, but the third instance is empty, and as this is the most recent this is the only instance output to the browser.
So:
1) Save the images you have generated with imagejpeg($data,$filename);. You can define a filename as $filename = $img+3.".jpg"; or similar.
2) It would also be much easier to debug and read your code if you used arrays instead of numerically incremented variables, that's a very messy way of writing code!
3) If you do want to output the image directly to the browser you need PHP to supply a header such as header('Content-Type: image/jpeg'); before outputting the contents of imagejpeg.
A Rehash of your code:
$w = 100;
$h = 400;
$img[1] = imagecreatefromjpeg('image1.jpg');
$img[2] = imagecreatefromjpeg('image2.jpg');
for ($i = 3; $i < 5; $i++) {
$img[$i] = imagecreatetruecolor($h, $h);
$j = $i -2;
imagecopyresampled($img[$i], $img[$j], 0, 0, 0, 0, $h, $h, $w, $h,);
// this function also contains destination width and destination
// height, which are equal to the size of the destination image so
// are set as $h, $h in the function above.
$img[$i] = imagerotate($img[$i], 90, 0);
$img[$i] = imagecrop($img[$i], array(0, 0, $h, $w));
$filename = "image-".$i.".jpg";
imagejpeg($img[$i], $filename);
imagedestroy($img[$i]);
imagedestroy($img[$j]);
}

Related

Laravel 5 imagepng not working

I'm trying to create a script that takes a certain part of an image but when i use imagepng, it returns me this:
Here's my code
$name = $path;
header("Content-type: image/png");
if (strpos($name, '..') !== false) {
exit(); // name in path with '..' in it would allow for directory
traversal.
}
$size = $face_size > 0 ? $face_size : 100;
//Grab the skin
$src = imagecreatefrompng("./skins/" . $name . ".png");
//If no path was given or no image can be found, then create from default
if (!$src) {
$src = imagecreatefrompng("./skins/default.png");
}
//Start creating the image
list($w, $h) = getimagesize("./skins/" . $name . ".png");
$w = $w / 8;
$dest = imagecreatetruecolor($w, $w);
imagecopy($dest, $src, 0, 0, $w, $w, $w, $w); // copy the face
// Check to see if the helm is not all same color
$bg_color = imagecolorat($src, 0, 0);
$no_helm = true;
// Check if there's any helm
for ($i = 1; $i <= $w; $i++) {
for ($j = 1; $j <= 4; $j++) {
// scanning helm area
if (imagecolorat($src, 40 + $i, 7 + $j) != $bg_color) {
$no_helm = false;
}
}
if (!$no_helm)
break;
}
// copy the helm
if (!$no_helm) {
imagecopy($dest, $src, 0, -1, 40, 7, $w, 4);
}
//prepare to finish the image
$final = imagecreatetruecolor($size, $size);
imagecopyresized($final, $dest, 0, 0, 0, 0, $size, $size, $w, $w);
//if its not, just show image on screen
imagepng($final);
//Finally some cleanup
imagedestroy($dest);
imagedestroy($final);
I used this code previously without any framework and it worked just fine, I don't know where it comes from.
Laravel and other frameworks use Middlewares, so when your controller method is done the application isn't ready to send the response yet. You can solve the problem by storing the output of the imagepng function in an internal buffer and send it properly(I think there isn't another solution if you want to use GD), also you have to use Laravel's function to set the HTTP headers instead of the header function.
Here is a simple example:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class AppController extends Controller
{
//Generates an image with GD and sends it to the client.
public function image(){
$im = imagecreatetruecolor(800, 420);
$orange = imagecolorallocate($im, 220, 210, 60);
imagestring($im, 3, 10, 9, 'Example image', $orange);
//Turn on output buffering
ob_start();
imagepng($im);
//Store the contents of the output buffer
$buffer = ob_get_contents();
// Clean the output buffer and turn off output buffering
ob_end_clean();
imagedestroy($im);
return response($buffer, 200)->header('Content-type', 'image/png');
}
}
You can look at this, I hope it will help you.
Although it works, it isn't the best method, I recommend you to use Imagick(if you can) instead of GD.

Merging transparent images on PHP

I'm trying to merge of this images:
https://imgur.com/aURQax9 -- Base
https://imgur.com/a/cpiSc -- Marking
the result should look like this:
https://imgur.com/a/ri3zw
I'm getting an image that is removing all of the black color, but I'm unsure how to do this.
$numberOfImages = 2;
$x = 600;
$y = 600;
$background = imagecreatetruecolor($x, $y);
$black = imagecolorallocate($background, 0, 0, 0);
imagecolortransparent($background, $black);
$firstUrl = 'Images/Horses/First horses/Red Breeds/Paint/Adult/Overo/1/BayOvero1AD.png';
$secondUrl = 'Images/Horses/First horses/Red Breeds/Paint/Markings/PaintBlazeAD.png';
$outputImage = $background;
$first = imagecreatefrompng($firstUrl);
$second = imagecreatefrompng($secondUrl);
imagecopymerge($outputImage,$first,0,0,0,0, $x, $y,100);
imagecopymerge($outputImage,$second,0,$y,0,0, $x, $y,100);
imagepng($outputImage, './Images/BayOvero1AD.PaintBlazeAD.png');
imagedestroy($outputImage);
How can I update this so that the color isn't removed and that it merges very similarly to the finished image above?
I have just wrote this for you. One of the images posted was a jpg not a PNG, however that could be to do with imgur, therefore I had to resize it and remove some of the white. Which is why my result didn't look quite right when testing. But it should be fine with your original files:
As you can see, it added the second image above the first, and kept it in the correct posistion.
The code I used for this was:
<?php
$x = 600;
$y = 600;
$firstUrl = 'Images/Horses/First horses/Red Breeds/Paint/Adult/Overo/1/BayOvero1AD.png';
$secondUrl = 'Images/Horses/First horses/Red Breeds/Paint/Markings/PaintBlazeAD.png';
$Image1 = imagecreatefrompng($firstUrl);
$Image2 = imagecreatefrompng($secondUrl);
imagealphablending($Image1, true);
imagesavealpha($Image1, true);
imagecopy($Image1, $Image2, 0, 0, 0, 0, $x, $y);
imagepng($Image1, './Images/BayOvero1AD.PaintBlazeAD.png');
?>

Change color of non-transparent parts of png in PHP

I want to fill the png non transparent part with any color or image using php.
Following is the base image
Following is the target image
I have used following code of php to fill non transparent part of the png.
$im = imagecreatefrompng(dirname(__FILE__) . '/images/cat_1.png');
$red = imagecolorallocate($im, 255, 0, 0);
imagefill($im, 0, 0, $red);
header('Content-type: image/png');
imagepng($im);
imagedestroy($im);
But it gives me following output.
please help me to complete my task.
Thanks in advance.
Save this version of the base image:
This image has been saved as an indexed-PNG format, making it perfect for colour substitution. In this case, index 0 is the cat's colour, and index 1 is the background (not ideal, but that's what GIMP gave me)
In this case:
$img = imagecreatefrompng("cat_1.png");
imagecolorset($img,0, 255,0,0);
imagepng($img); // output red cat
Image editing in general is made much easier if you have a base image that lends itself to easy editing in this way ;)
This line imagefill($im, 0, 0, $red); fills the image with the color red, at the coordinate (0,0), which is topleft. So it starts filling at the top left and fills everything like when you use the paintbucket in MSPaint. You could use imagefill($im, 150, 150, $red); for example (if 150,150 is the center).
use this function, it returns a base64 image <img src="output">
public static function colorImage($url, $hex = null, $r = null, $g = null, $b = null)
{
if ($hex != null) {
$hex = str_replace("#", "", $hex);
$r = hexdec(substr($hex, 0, 2));
$g = hexdec(substr($hex, 2, 2));
$b = hexdec(substr($hex, 4, 2));
}
$im = imagecreatefrompng($url);
imageAlphaBlending($im, true);
imageSaveAlpha($im, true);
if (imageistruecolor($im)) {
$sx = imagesx($im);
$sy = imagesy($im);
for ($x = 0; $x < $sx; $x++) {
for ($y = 0; $y < $sy; $y++) {
$c = imagecolorat($im, $x, $y);
$a = $c & 0xFF000000;
$newColor = $a | $r << 16 | $g << 8 | $b;
imagesetpixel($im, $x, $y, $newColor);
}
}
}
ob_start();
imagepng($im);
imagedestroy($im);
$image_data = ob_get_contents();
ob_end_clean();
$image_data_base64 = "data:image/png;base64," . base64_encode($image_data);
return $image_data_base64;
}

Image resize in PHP

I am very new to Resize image in php.Basically i wanted to make thumbnail image using uploaded image. i have used below code but its not working, can anybody help me?..
Thanks in Advance...
$source_image = $path.$row->photosfolder;
$size = getimagesize($source_image);
$w = $size[0];
$h = $size[1];
$simg = imagecreatefromjpeg($source_image);
$dimg = imagecreatetruecolor(150, 225);
$wm = $w / 150;
$hm = $h / 225;
$h_height = 225 / 2;
$w_height = 150 / 2;
if ($w > $h) {
$temp = imagecopyresampled($dimg, $simg, 0, 0, 0, 0, 150, 225, $w, $h);
}
elseif (($w < $h) || ($w == $h)) {
$temp = imagecopyresampled($dimg, $simg, 0, 0, 0, 0, 150, 225, $w, $h);
}
else {
$temp = imagecopyresampled($dimg, $simg, 0, 0, 0, 0, 150, 225, $w, $h);
}
$thumb_image = imagejpeg($dimg, $simg, 100);
check timthumb.php is easy to use and you can find the code full educational
If you want to resize an image, you should do it on client side because PHP image manipulation takes a lot of memory and CPU time, and it doesn't have to be done on server side (there are no access to db, no access to session, etc).
If you still want to do it on PHP, you can use that functions to get the right sizes :
list($realW, $realH) = getimagesize($source_image);
$realR = $realW / $realH;
$thumbR = $thumbW / $thumbH;
// If you want your resize image to fit inside the max thumb size :
if($realR > $thumbR) // Real image if flatter than thumb
{
$newW = $thumbW;
$newH = $newW / $realR;
}
else
{
$newH = $thumbH;
$newW = $newH * $realR;
}
// Or if you want your resize image to be as small as possible but
// not smaller than your thumb. This can be helpful in some cases.
if($realR < $thumbR)
{
// Same code
}
And then use copy resampled as you did (read php manual if you can't get it to work, there are examples below the synopsis of the function).
If you want to resize an image using javascript, you can use the <canvas> :
var canvas = document.createElement('canvas');
var image = document.getElementById('image');
var context = canvas.getContext('2d');
context.save();
context.drawImage(image, /* Here you put the right values using the algorithms above */);
context.restore();
var thumb = document.createElement('image');
thumb.src = canvas.toDataUrl();
Or something like that. You may change a few things depending on your specific case.
Please try with below code, It will resize image and create new thumbnail. New size is defined 100 X 100. This example will also keep aspected ratio of image.
Note:
1.Image path will be directory path if want to set full path.
2. In example we consider for jpg file, you can use for PGN & GIF file with imagecreatefrompng, imagecreatefromgif.
3.This will create PNG file.
$_imagePath = 'somefile.jpg';
$im = imagecreatefromjpeg($_imagePath);
imagealphablending($im, true);
$_orgWidth = imagesx($im);
$_orgHeight = imagesy($im);
$_newWidth = 100;
$_newHeight = 100;
$_finalHeight = $_orgHeight * ( $_newWidth/ $_orgWidth);
if($_finalHeight > $_newHeight){
$_newWidth = $_orgWidth * ($_newHeight / $_orgHeight);
}else{
$_newHeight = $_finalHeight ;
}
$_thumb = imagecreatetruecolor($_newWidth, $_newHeight);
imagealphablending($_thumb, true);
imagesavealpha($_thumb, true);
imagecopyresampled($_thumb, $im, 0, 0, 0, 0, $_newWidth, $_newHeight, $_orgWidth , $_orgHeight );
imagepng($_thumb, 'newname.png');
imagedestroy($_thumb);

Image as isosceles trapezoid PHP GD

i have this function that transforms image to trapezoid using PHP GD:
function perspective($i,$gradient=0.9,$rightdown=true,$background=0xFFFFFF) {
$mult=3;
$w=imagesx($i);
$h=imagesy($i);
$image=imagecreatetruecolor($w*$mult,$h*$mult);
imagecopyresized($image,$i,0,0,0,0,$w*$mult,$h*$mult,$w,$h);
imagedestroy($i);
$w*=$mult;
$h*=$mult;
$im=imagecreatetruecolor($w,$h);
$background=imagecolorallocate($im,($background>>16)&0xFF,($background>>8)&0xFF,$background&0xFF);
imagefill($im,0,0,$background);
imageantialias($im,true);
$nh=$h-($h*$gradient);
for ($x=0; $x<$w; $x++) {
$ni=(($rightdown) ? $x : $w-$x);
$p=intval($h-(($ni/$w)*$nh));
if (($p%2)<>0)
$p-=1;
$nx=intval(($p-$h)/2);
imagecopyresampled($im,$image,$x,0,$x,$nx,1,$p,1,$h-1);
imageline($im,$x,$h-1,$x,$h+$nx,$background);
imageline($im,$x,0,$x,-$nx-1,$background);
}
imagedestroy($image);
imagefilter($im,IMG_FILTER_SMOOTH,10);
$i=imagecreatetruecolor($w/$mult,$h/$mult);
imageantialias($i,true);
imagecopyresampled($i,$im,0,0,0,0,$w,$h,$w*$mult,$h*$mult);
imagedestroy($im);
return $i;
}
But i cant modify it to produce isosceles trapezoid, i think there needs just one small modification, but i cant figure it outh (i tried lot of things).
Can someone help?
Right, basically that code should generate the right values, but due to a bug has a lot of cludges in place to get a trapezium shape. The bug is that the copy of each line has the destination-y and the source-y values transposed. The source-y should always be 0, the destination-y should change.
There were also a few other small numerical bugs and double rounding at unnecessary points throwing off the results.
Also, the variable naming was atrocious, so I have rewritten it so that the entire function is clear.
Try the following:
function makeTrapeziumImage($image, $gradient, $rightToLeft = false, $background = 0xFFFFFF, $supersampleScale = 3) {
$originalWidth = imagesx($image);
$originalHeight = imagesy($image);
$supersampledWidth = $originalWidth * $supersampleScale;
$supersampledHeight = $originalHeight * $supersampleScale;
$supersampledImage = imagecreatetruecolor($supersampledWidth, $supersampledHeight);
imagecopyresized($supersampledImage, $image,
0, 0, 0, 0,
$supersampledWidth, $supersampledHeight, $originalWidth, $originalHeight);
$workingImage = imagecreatetruecolor($supersampledWidth, $supersampledHeight);
$backgroundColour = imagecolorallocate($workingImage, ($background >> 16) & 0xFF, ($background >> 8) & 0xFF, $background & 0xFF);
imagefill($workingImage, 0, 0, $backgroundColour);
imageantialias($workingImage,true);
$endHeight = $supersampledHeight - ($supersampledHeight * $gradient);
for ($x = 0; $x < $supersampledWidth; $x++) {
$cX = ($rightToLeft ? $supersampledWidth - $x : $x);
$dstHeight = $supersampledHeight - ((($cX + 1) / $supersampledWidth) * $endHeight);
$dstY = intval(($supersampledHeight - $dstHeight) / 2) - 1; // -1 required as zero-indexed
$dstY = ($dstY < 0 ? 0 : $dstY); // Rounding can make $dstY = -1
$dstHeight = intval($dstHeight); // Round the height after calculating $dstY
imagecopyresampled($workingImage, $supersampledImage,
$cX, $dstY, $cX, 0,
1, $dstHeight, 1, $supersampledHeight);
}
imagedestroy($supersampledImage);
imagefilter($workingImage, IMG_FILTER_SMOOTH, 10);
$resizedImage = imagecreatetruecolor($originalWidth, $originalHeight);
imageantialias($resizedImage, true);
imagecopyresampled($resizedImage, $workingImage,
0, 0, 0, 0,
$originalWidth, $originalHeight, $supersampledWidth, $supersampledHeight);
imagedestroy($workingImage);
return $resizedImage;
}
The essential mechanism of the inner loop, as before, is to take each column of pixels, along the x-axis and resize them over a gradient. It naturally creates an isosceles trapezium. In order to create a non-isosceles trapezoid, another gradient would have to be specified. Alternatively, a set of start and end y-values could be specified and the gradients calculated from them.
Whilst this example works along the x-axis, in either direction as before, it could just as easily work along the y-axis (or the image could be rotated 90 degrees, processed, then rotated back).

Categories