I have made a PHP script which dynamically creates a photo gallery (on http://benxd.me/art/) using all the images in a directory. It generates thumbnails for each image, and watermarks a high quality image for use in a lightbox.
However, I have a problem: both the watermarking script and the thumbnail script rotate one image (http://benxd.me/assets/img/art/Advance.jpg) 90 degrees counterclockwise.
I have other images uploaded to the directory, so is there a problem with this image that causes it to be rotated by the PHP? Or would it be caused by my scripts?
Here are my scripts for reference:
engine.php - the script which generates the thumbnails and the HTML displayed on the gallery page
<?php
/*========================================
http://www.techrepublic.com/article/create-a-dynamic-photo-gallery-with-php-in-three-steps/
http://stackoverflow.com/questions/38963849/php-exif-data-not-working
https://davidwalsh.name/generate-photo-gallery
========================================*/
/* function: generates thumbnail */
function make_thumb($src,$dest,$desired_width) {
/* read the source image */
$source_image = imagecreatefromjpeg($src);
$width = imagesx($source_image);
$height = imagesy($source_image);
/* find the "desired height" of this thumbnail, relative to the desired width */
$desired_height = floor($height*($desired_width/$width));
/* create a new, "virtual" image */
$virtual_image = imagecreatetruecolor($desired_width,$desired_height);
/* copy source image at a resized size */
imagecopyresized($virtual_image,$source_image,0,0,0,0,$desired_width,$desired_height,$width,$height);
/* create the physical thumbnail image to its destination */
imagejpeg($virtual_image,$dest);
}
/* function: returns files from dir */
function get_files($images_dir,$exts = array('jpg')) {
$files = array();
if($handle = opendir($images_dir)) {
while(false !== ($file = readdir($handle))) {
$extension = strtolower(get_file_extension($file));
if($extension && in_array($extension,$exts)) {
$files[] = $file;
}
}
closedir($handle);
}
return $files;
}
/* function: returns a file's extension */
function get_file_extension($file_name) {
return substr(strrchr($file_name,'.'),1);
}
include("settings.php");
/** generate photo gallery **/
$image_files = get_files($images_dir);
if(count($image_files)) {
$index = 0;
foreach($image_files as $index=>$file) {
$index++;
$thumbnail_image = $thumbs_dir.$file;
if(!file_exists($thumbnail_image)) {
$extension = get_file_extension($thumbnail_image);
if($extension) {
make_thumb($images_dir.$file,$thumbnail_image,$thumbs_width);
}
}
// read EXIF headers
$exif = exif_read_data("$images_dir/$file", "FILE,COMPUTED,ANY_TAG,IFD0,THUMBNAIL,COMMENT,EXIF", true);
//generate HTML
echo '<li class="borderless img"><img src="',$thumbnail_image,'" /></li>';
}
}
?>
image.php - watermarks the high-quality image for use by the lightbox
<?php
/*========================================
http://gazelleincorporated.com/dynamically-adding-a-watermark-to-an-image-using-php
========================================*/
include("settings.php");
//Let's say you sent the filename via the url, i.e. watermark.php?filename=myimage.jpg
$filename=$_REQUEST['n'];
//get the full path to the image:
$imgpath = $images_dir.$filename;
//OK cool, let's start the process of outputting the image with a watermark...
header('content-type: image/jpeg'); //HTTP header - assumes your images in the gallery are JPGs
//$watermarkfile is the filepath for your watermark image as a PNG-24 Transparent (ex: your logo)
$watermarkfile="../assets/img/copyright-trans.png";
//Get the attributes of the watermark file so you can manipulate it
$watermark = imagecreatefrompng($watermarkfile);
//Get the width and height of your watermark - we will use this to calculate where to put it on the image
list($watermark_width,$watermark_height) = getimagesize($watermarkfile);
//Now get the main gallery image (at $imgpath) so we can maniuplate it
$image = imagecreatefromjpeg($imgpath);
//Get the width and height of your image - we will use this to calculate where the watermark goes
$size = getimagesize($imgpath);
//Calculate where the watermark is positioned
//In this example, it is positioned in the lower right corner, 15px away from the bottom & right edges
$dest_x = ($size[0] - $watermark_width) / 2;
$dest_y = ($size[1] - $watermark_height) / 2;
//I used to use imagecopymerge to apply the watermark to the image
//However it does not preserve the transparency and quality of the watermark
//imagecopymerge($image, $watermark, $dest_x, $dest_y, 0, 0, $watermark_width, $watermark_height, 70);
//So I now use this function which works beautifully:
//Refer here for documentation: http://www.php.net/manual/en/function.imagecopy.php
imagecopy($image, $watermark, $dest_x, $dest_y, 0, 0, $watermark_width, $watermark_height);
//Finalize the image:
imagejpeg($image);
//Destroy the image and the watermark handles
imagedestroy($image);
imagedestroy($watermark);
?>
settings.php
<?php
$images_dir = '../assets/img/art/';
$thumbs_dir = '../assets/img/art/thumb/';
$thumbs_width = 325;
?>
Thanks #MarkSetchell , the problem was caused by the image's exif orientation tag. I wasn't even aware such a thing existed! I was able to use JPEG Autorotate to remove the exif orientation tag. My script now displays the image in the correct orientation.
Related
I have a partially working function for making thumbnails but 10% of the images doesn't get created as thumbnails, and they're the same exact 10%. The other 90% works. I'm not sure why though. Please take a look at my code:
<?php
$image = "511photo.jpg";
if ($image) {
make_thumb("uploads", "thumbnails", $image, 500);
}
function make_thumb($imageFrom, $imageTo, $image, $thumbWidth) {
/* read the source image */
$getFrom = $imageFrom."/".$image;
$source_image = imagecreatefromjpeg($getFrom);
$width = imagesx($source_image);
$height = imagesy($source_image);
/* find the "desired height" of this thumbnail, relative to the desired width */
$thumbHeight = floor($height * ($thumbWidth / $width));
/* create a new, "virtual" image */
$virtual_image = imagecreatetruecolor($thumbWidth, $thumbHeight);
/* copy source image at a resized size */
imagecopyresampled($virtual_image, $source_image, 0, 0, 0, 0, $thumbWidth, $thumbHeight, $width, $height);
/* create the physical thumbnail image to its destination */
$dest = $imageTo."/".$image;
imagejpeg($virtual_image, $dest);
} //end of function make_thumb($imageFrom, $imageTo, $image, $thumbWidth)
?>
Note: Here's a couple of other $image that doesn't work:
"434cute-anime-couple-drawing-on-tumblr.png"
"503anime_head_vectorized_by_cona_cru-d784ls0.png"
Note: Yes, I am sure that they are all in the uploads folder - I've checked and double checked so honestly, right now I'm so confuse...
It's because you are using imagecreatefromjpeg() for png image. You need to use imagecreatefrompng() for these images.
$source_image = imagecreatefrompng($getFrom);
For checking image type you can use exif_imagetype() function :
$imageType = exif_imagetype($getFrom);
if($imageType == IMAGETYPE_PNG) {
//It's PNG
} elseif($imageType == IMAGETYPE_JPEG) {
//It's JPEG
} //You can check more types here.
check file type and add this code with imagejpeg function in a condition its an example add your variables and values
if($fileType=="image/png"){
$im=ImageCreateFromPNG($add);
$width=ImageSx($im); // Original picture width is stored
$height=ImageSy($im); // Original picture height is stored
$newimage=imagecreatetruecolor($n_width,$n_height);
imageCopyResized($newimage,$im,0,0,0,0,$n_width,$n_height,$width,$height);
ImagePng($newimage,$tsrc);
chmod("$tsrc",0777);
}
I am building a thumbnail system, but my code outputs a bunch or random icons. It apparently should work, but it doesn't.
Code:
<?php
// The file
$filename = 'post/imgres/posts/1.jpg';
// Set a maximum height and width
$width = 200;
$height = 200;
// Content type
header('Content-Type: image/jepg');
// Get new dimensions
list($width_orig, $height_orig) = getimagesize($filename);
$ratio_orig = $width_orig/$height_orig;
if ($width/$height > $ratio_orig) {
$width = $height*$ratio_orig;
} else {
$height = $width/$ratio_orig;
}
// Resample
$image_p = imagecreatetruecolor($width, $height);
$image = imagecreatefromjpeg($filename);
imagecopyresampled($image_p, $image, 0, 0, 0, 0, $width, $height, $width_orig, $height_orig);
// Output
imagejpeg($image_p, null, 100);
?>
I found a class called simpleimage by claviska. and my code is now done. it all looks like this.
The code that takes care of the thumbnails:
function isThumb($thumbnail)
{
if (file_exists($thumbnail))
{
return true;
}
return false;
}
function makeThumb($original, $destination)
{
$img = new abeautifulsite\SimpleImage($original);
$img->fit_to_width(256);
$img->save($destination);
}
?>
The code that loads the images:
<?php
//Image loader
//Folder containing images.
$filedir = "imgres/posts/";
//Retrieve the images in the folder.
$images = glob($filedir."*.{jpg,JPG,png,PNG,gif,GIF}",GLOB_BRACE);
//Make sure the image array is not empty, or null.
if (!empty($images))
{
//Load the images into the website.
foreach ($images as $image)
{
if (pathinfo($image,PATINFO_EXTENSION) == "gif" || pathinfo($image, PATHINFO_EXTENSION)=="GIF")
{
echo '<img src="'.$image.'"/>';
}
else
{
echo '<img src="'.getThumb($image).'"/>';
}
}
}
else
{
//Write out an error message to warn the user.
echo "<p>No images were found in the server. This is most likely an error in the PHP code, incompatibility, or something went wrong with our storage solution. Contact admin! Information needed: Browser, OS, and has the site worked before?</p>";
}
?>
PHP Image thumbnailing is a common task and there are plenty of solid image thumbnailing examples and sources are out there. I'm not sure what your script is doing but here is a barebone basic script which always works and its straight forward.
You should cover and support all image types png's and gif's. But since you're doing jpegs, let use that for now. Adding support for other image types shouldn't be that difficult.
/* read the source image */
$source_image = imagecreatefromjpeg($src);
$width = imagesx($source_image);
$height = imagesy($source_image);
/* find the "desired height" of this thumbnail, relative to the desired width */
$desired_height = floor($height * ($desired_width / $width));
/* create a new, "virtual" image */
$virtual_image = imagecreatetruecolor($desired_width, $desired_height);
/* copy source image at a resized size */
imagecopyresampled($virtual_image, $source_image, 0, 0, 0, 0, $desired_width, $desired_height, $width, $height);
// Content type, you need this line of code to
// display image to browser or for testing it on the UI
header('Content-Type: image/jepg');
/* create the physical thumbnail image to its destination */
imagejpeg($virtual_image, $dest);
I'm using the code, that first checks filenames in folder and then creates url. In the url find it the special line where is an imagefile. It displays correctly image and address, but if images are too big, takes it so long time. Is it possible to create thumbnail and display this instead of image? Thank You!
require_once('simple_html_dom.php');
$files = scandir('files/');
foreach($files as $file) {
if($file == '.' || $file == '..') continue;
$file = basename($file, ".html");
$url = 'http://address.com/test/'.$file;
$html = file_get_html($url);
foreach($html->find('img') as $element) {
if (strpos($element,'address.com') !== false) {
$url = $element->src;
echo $url.'</br>';
echo '<IMG SRC="',$url, '" WIDTH="128" HEIGHT="96" BORDER="0" ALT="" /><br/>';
}
}
}
You want to use CSS clip:rect(50px 218px 155px 82px);
Setting width and height does not decress the ACTUAL image size, so load time will still take just as long. See this article on step by step div creation and css coding.
http://www.seifi.org/css/creating-thumbnails-using-the-css-clip-property.html
Also as a side note, nothing beats ACTUALLY MAKING TUMBNAILS! There are serve side thumbnail generators, but this is the best you'll get with out actually making tumbnails.
I wrote a blog post on How to proportionally resize uploaded images, you should be able to adjust the code from the sample I wrote to do what you want.
Pasting the code below in case my site dies in the future.
<?php
// *snip* Removed form stuff
$image = imagecreatefromjpeg($pathToImage);
// Target dimensions
$max_width = 240;
$max_height = 180;
// Calculate new dimensions
$old_width = imagesx($image);
$old_height = imagesy($image);
$scale = min($max_width/$old_width, $max_height/$old_height);
$new_width = ceil($scale*$old_width);
$new_height = ceil($scale*$old_height);
// Create new empty image
$new = imagecreatetruecolor($new_width, $new_height);
// Resample old into new
imagecopyresampled($new, $image,
0, 0, 0, 0,
$new_width, $new_height, $old_width, $old_height);
// Catch the image data
ob_start();
imagejpeg($new, NULL, 90);
$data = ob_get_clean();
// Destroy resources
imagedestroy($image);
imagedestroy($new);
// Output image data
header("Content-type: image/jpeg", true, 200);
echo $data;
You'd probably want to stick this in a function and change it output to a file. Then generate the thumbnail in your foreach loop and link to the thumbnail instead of the original. You should also check if you have already created a thumbnail for an image so you don't do it more than once for each image.
I want to display the thumbnail of image while displaying time,but dont want to save the image.
I have tried some notorious ;) script but its not working :(. Please have look and let me know do you have any idea
<?php
function print_thumb($src, $desired_width = 100){
/* read the source image */
$source_image = imagecreatefromjpeg($src);
$width = imagesx($source_image);
$height = imagesy($source_image);
/* find the "desired height" of this thumbnail, relative to the desired width */
$desired_height = floor($height * ($desired_width / $width));
/* create a new, "virtual" image */
$virtual_image = imagecreatetruecolor($desired_width, $desired_height);
/* copy source image at a resized size */
imagecopyresampled($virtual_image, $source_image, 0, 0, 0, 0, $desired_width, $desired_height, $width, $height);
// Set the content type header - in this case image/jpeg
header('Content-Type: image/jpeg');
// Output the image
imagejpeg($virtual_image);
}
?>
<img src="<?php print_thumb("s1.jpg"); ?>" />
I saved this file as thumbs.php (single file) while accessing it via localhost it displaying like
<img src="http://localhost/test/thumbs.php">
Its working fine if I write both in separate file.
like file.html with
<img src="thumb.php?img=s1.jpg" />
and
thumb.php
<?php
function print_thumb($src, $desired_width = 100){
/* read the source image */
$source_image = imagecreatefromjpeg($src);
$width = imagesx($source_image);
$height = imagesy($source_image);
/* find the "desired height" of this thumbnail, relative to the desired width */
$desired_height = floor($height * ($desired_width / $width));
/* create a new, "virtual" image */
$virtual_image = imagecreatetruecolor($desired_width, $desired_height);
/* copy source image at a resized size */
imagecopyresampled($virtual_image, $source_image, 0, 0, 0, 0, $desired_width, $desired_height, $width, $height);
// Set the content type header - in this case image/jpeg
header('Content-Type: image/jpeg');
// Output the image
imagejpeg($virtual_image);
}
print_thumb($_REQUEST['img']);
?>
You need 2 separate scripts.
1 to output the image image/jpg and one to output the HTML. You appear to be trying to render the image directly to the src attribute.
HTML Page:
<html>
<body>
<img src="http://localhost/test/thumbs.php?img=s1.jpg">
</body>
</html>
PHP Page:
<?php
function print_thumb($src, $desired_width = 100){
// your function as is
}
// you should probably sanitize this input
print_thumb($_REQUEST['img']);
?>
Try using "TimThumb" (CLICK HERE), it makes things like this very easy indeed.
If <img src="<?php print_thumb("s1.jpg"); ?>" /> is part of thumbs.php as in your shown code, then you have to remove it. I also suggest removing ?> from thumbs.php
Inside 'thumb.php'
<?php
function print_thumb($src, $desired_width = 100){
if( !file_exists($src) )
return false;
/* read the source image */
$source_image = imagecreatefromjpeg($src);
$width = imagesx($source_image);
$height = imagesy($source_image);
/* find the "desired height" of this thumbnail, relative to the desired width */
$desired_height = floor($height * ($desired_width / $width));
/* create a new, "virtual" image */
$virtual_image = imagecreatetruecolor($desired_width, $desired_height);
/* copy source image at a resized size */
imagecopyresampled($virtual_image, $source_image, 0, 0, 0, 0, $desired_width, $desired_height, $width, $height);
// Set the content type header - in this case image/jpeg
header('Content-Type: image/jpeg');
// Output the image
imagejpeg($virtual_image);
return true;
}
if( isset( $_GET['file'] ) && !empty( $_GET['file'] ) ){
if( !print_thumb( $_GET['file'] ) ){
echo 'Failed to create thumb for "'.$_GET['file'].'"';
}else{
// The Thumb would have been returned
}
}else{
echo 'No File specified';
}
?>
Inside any page displaying the thumbnails
<img src="thumb.php?file=s1.jpg" />
The problem you have with your existing code is that you are putting the wrong code in the wrong file. The thumb.php file is meant to do nothing but look at the parameters it is being sent (the file it is meant to turn into a thumbnail) and return the image.
So putting the <img.... markup at the end of that file is where your problem is.
Instead, you have to look at where you are trying to make the images appear. And you have to pass that image filename into the markup, so the thumbs.php file know what you want it to thumbnail and return.
As another respondant noted, there are libraries which will do this for you alot easier than writing it up yourself.
How can I take a 500x500 (or any sized) image that has been uploaded to the server and generate a new image from defined specific x,y coordinates? For example (0,0) to (50,0); (0,50) to (50,50). Rather than resizing an image down to 50x50px, I want to grab the top left part of an image and in a sense "crop" it to use as a thumbnail.
How can I go about doing this in PHP?
You want to use imagecopy. First create an image with the dimensions you want and then use imagecopy to a portion of the source image into the new image:
// use whatever mechanism you prefer to load your source image into $image
$width = 50;
$height = 50;
// Define your starting coordinates in the source image.
$source_x = 20;
$source_y = 100;
$new_image = imagecreatetruecolor($width, $height);
imagecopy($new_image, $image, 0, 0, $source_x, $source_y, $width, $height);
// Now $new_image has the portion cropped from the source and you can output or save it.
imagejpeg($new_image);
http://www.php.net/manual/en/function.imagick-cropthumbnailimage.php#81547
$image = new Imagick($path."test1.jpg");
$image->cropThumbnailImage(160,120); // Crop image and thumb
$image->writeImage($path."test1.jpg");
I've seen a few ways to do this. If you want to generate the thumbs on the fly you could use:
function make_thumb($src,$dest,$desired_width)
{
/* read the source image */
$source_image = imagecreatefromjpeg($src);
$width = imagesx($source_image);
$height = imagesy($source_image);
/* find the "desired height" of this thumbnail, relative to the desired width */
$desired_height = floor($height*($desired_width/$width));
/* create a new, "virtual" image */
$virtual_image = imagecreatetruecolor($desired_width,$desired_height);
/* copy source image at a resized size */
imagecopyresized($virtual_image,$source_image,0,0,0,0,$desired_width,$desired_height,$width,$height);
/* create the physical thumbnail image to its destination */
imagejpeg($virtual_image,$dest);
}
You can also set the quality parameter in the imagejpeg function.
Or if you want to save the image thumb to a directory I would look at:
http://bgallz.org/270/php-create-thumbnail-images/
or
http://www.imagemagick.org/script/index.php