I want to be able to trim images, many of which are very long vertically...anywhere from 2000 to 4000px, always at 800. So only getting the top part of the image. I then want to output this to a page/report with PHP, without storring the resultant trimmed image.
Is $imagepng->trim the best way to do this?
You'd do something like this:
$srcName = 'source.png';
$info = getimageinfo($srcName);
$src = imagecreatefrompng($srcName);
// Create a new image up to 800px tall
$dest = imagecreate($info[0], min($info[1], 800));
imagecopy($dest, $src, 0, 0, 0, 0, $info[0], min($info[1], 800));
// Output
header('Content-type: image/png');
imagepng($dest);
GD is what imagepng uses and it's the most widely-supported way of doing image manipulation in PHP, so it's a pretty safe bet, especially if you are looking to deploy your code on servers you don't control.
An alternative would be to look at ImageMagick, though I find GD is a little faster in most cases.
Related
While reading up on the issues merging transparent images in PHP, it seems that everyone is in the "it works" or "it doesn't work" camps. I have found a way to demonstrate each case.
I wish to take a PNG, cut an ALPHA hole in it and then merge it on top of another image. In this case, I cut a hole in an image from google maps, and paste it over a red block. I have two images from google maps. One is of Manhattan and one is of my house. One works, and one does not. The only difference is one was "saved" via a browser.
If you run the code below, you will see the difference in outputs. Does anyone know why the same code would treat two PNG files completely differently? It must be the difference in the PNG files themselves, but then what would it be?
<?php
sometimesworks("https://maps.googleapis.com/maps/api/staticmap?center=40.714728,-73.998672&zoom=12&size=400x400&maptype=hybrid", "google");
sometimesworks("https://lh4.googleusercontent.com/UQvV_dpBa3_rVf25pvLXKD3OwzF4FtPnHBHkzdWqjCQ5mlFqcFfId9echIgDMv_xYRRYzLaKEXphw7g=w2447-h1106", "myhouse");
function sometimesworks($p_image, $p_prefix)
{
$image_top =imagecreatefrompng($p_image);
$brush = imagecolorallocate($image_top, 0, 0, 0); //create a black brush
imagefilledpolygon($image_top, explode(",", "10,10, 120,22, 80,280, 200, 191"), 4, $brush); //fill a polygon
imagecolortransparent($image_top, $brush); //turn the black to be transparent
imagepng($image_top, './'.$p_prefix.'.transparent.png'); //save the file to confirm that it is working.
//create a big red square
$image_bottom = imagecreatetruecolor(imagesx($image_top), imagesy($image_top));
$red = imagecolorallocate($image_bottom, 255, 0, 0);
imagefill($image_bottom, 0, 0, $red);
imagepng($image_bottom, './'.$p_prefix.'.red.png');
//merge the top onto the bottom.
$out = imagecreatetruecolor(imagesx($image_top), imagesy($image_top));
imagecopy($out, $image_bottom, 0, 0, 0, 0, imagesx($image_top), imagesy($image_top));
imagecopy($out, $image_top, 0, 0, 0, 0, imagesx($image_top), imagesy($image_top));
imagepng($out, './'.$p_prefix.'.out.png');
}
The issue with the above code is that the PNG files were of different type. One was a truecolor image and the other was a palette. The code to merge files differs depending on what is being done.
This is a good reference for the merging of "palette" based PNG files with transparency.
I am creating a poster using PHP and I want to add figures on the poster.
I use the following code to add them:
$src1 = imagecreatefrompng("m2.png");
$widthsrc=0;
$heightsrc=0;
list($widthsrc, $heightsrc, $typesrc, $attrsrc) = getimagesize("m2.png");
$background = imagecolorallocate($src1, 0, 0, 0);
imagecolortransparent($src1, $background);
imagealphablending($src1, false);
imagesavealpha($src1, true);
imagecopyresampled($my_img,$src1,$line2X1+100*$resize,$line2Y1,0,0,1000*$resize,1000*$resize,$widthsrc,$heightsrc);
The problem is that the places that the figures should be transparent, they are black.
I have already looked at the following posts:
imagecreatefrompng-makes-a-black-background-instead-of-transparent
hp-resizing-png-images-generate-black-background
png-has-black-background
But I haven't been able to create a solution that works for me.
Well that was easy XD Converting comment to answer:
Your mistake was in defining the background colour. You should use this:
$background = imagecolorallocatealpha($src,0,0,0,127);
However, it is probably a good idea to be safe, and avoid using a "transparent" colour that already exists on your image. The "traditional" transparent colour from old sprite-based games is magenta, since it is very unlikely that you'll have straight magenta on your image!
$background = imagecolorallocatealpha($src,255,0,255,127);
Not sure why it looks so bad, but when I copy an image over another image, it looks extremely terrible, like it lost almost all its colors for some reason.
$img = imagecreate(240, 140);
$wall = imagecreatefrompng($src);
imagecopyresampled($img, $wall, 0, 0, 40, 340, 240, 140, 240, 140);
I've been trying to find a solution myself but I can't seem to find one, anybody really good with GD that can help? I can't use imagemagick.
You need to create your canvas image with imagecreatetruecolor() rather than imagecreate() as the former creates a palette based canvas with limited colour support.
I presume you are then using imagepng() to save our output the image. The third argument accepted by this function defines the quality of the image, or the compression level (0-9)
I am making a site where people can upload their own background images. One of the things users really having a problem understanding is image sizes and resolution. If I say 'Make sure your background is at least 1080x1920 pixels (Full HiDef)' I am guessing a good 70% of people will not know what this means or how to do it.
So what I would like to do is enlarge small images in a nicer way than just making them blurry. What I would like to do is something like this:-
http://nanotux.com/plugins/fullscreenr/index.html
where basically every other dot is a black pixel, that way small images will be twice the size when they are stretched to 1080x1920 and generally look better.
Does anyone know of a way to do this with PHP's image functions?
(as an aside does anyone know what this type of effect should be called? Moire? would that be accurate?)
Thanks in advance
If I understood you well, you want to set every second pixel in x and y dimensions to black on the stretched image?
This should do the trick (not tested, I relied on PHP documentation).
$initialImage = ... // handle to the image
$srcWidth = imagesx($initialImage);
$srcHeight = imagesy($initialImage);
$maxX = 1920;
$maxY = 1080;
$newImage = imagecreatetruecolor($max_x, $max_y);
imagecopyresampled ($newImage, $initialImage, 0,0,0,0, $maxX, $maxY, $srcWidth, $srcHeight);
$BLACK = imagecolorallocate($newImage, 0, 0, 0);
for($x=0; $x+=2; $x<$max_x){
for($y=0; $y+=2; $y<$max_y){
imagesetpixel($newImage, $x, $y, $BLACK);
}
}
Documentation: imagesetpixel, imagecolorallocate, imagecopyresampled,
imagecreatetruecolor.
Read PHP documentation and examples there. Remember to use imagecopyresampled instead of imagecopyresized to have better quality.
The most optimal way would be to create a transparent raster (.png) "by hand" (i.e. create it programmatically as in jakub.gieryluk's solution), and overlay that, multiple times if needed, via imagecopy().
Drawing pixel by pixel is painfully slow.
$im = ImageCreateFromString(file_get_contents($source_file));
ImageFilter($im, IMG_FILTER_GRAYSCALE);
any idea what i could do, to properly grayscale gifs and pngs with transperancy? This snippet actually works good, it transforms jpgs and pngs to grayscale. However gifs are a little bit "buggy" - they don't always work, it depends on the image. Sometimes there are a few pale colors left in them. Moreover this snippet doesn't work with alpha-channels. If i convert a gif or a png with transparancy the transparent parts always get blackened.
Of course im querying the image-type and after "grayscaling" it, i'll set the proper type again.
Have you any ideas?
This code should preserve the alpha, but it's slower than imagefilter:
$im = ImageCreateFromString(file_get_contents($source_file));
$width=imagesx();
$height=imagesy();
for($x=0;$x<$width;$x++)
for($y=0;$y<$height;$y++)
{
$rgb=imagecolorsforindex($im,imagecolorat($im,$x,$y));
$average=ceil(($rgb["red"]+$rgb["green"]+$rgb["blue"])/3);
imagesetpixel($im,$x,$y,imagecolorallocatealpha($im,$average,$average,$average,$rgb['alpha']));
}
If you still have problems try to write this after the image creation (before the $width=..):
imagesavealpha($im,true);
For pngs a simple call to imagesavealpha() solves the problem of black pixels on the alpha channel, complete code:
$im = ImageCreateFromString(file_get_contents($source))
imagefilter($im, IMG_FILTER_GRAYSCALE);
imagesavealpha($im,true);
imagepng( $im, $output );