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.
Related
I have created this script based on reading other posts on StackOverflow. The script creates a thumbnail from the original image and adds it to a folder. The source images are located on my local server so Glob would work however I am not sure how to adjust this script so that it will run this function on all files in a folder (Glob). I realize it may be memory intensive but I only need to do it a few times on several folders and I'll be done with it.
Just in case you are questioning the reason I have included $height2, it is a little hack I came up with where we create the thumbnail while maintaining the aspect ratio then only save the top 250px so that the thumb is 250 x 250 but not distorted (stretched). It works great.
I just need to adjust to do a batch of all images in the source folder.
Any help would be great. Please keep in mind that I am a front end developer (html and css) and not great at PHP. This script alone took me forever to make work lol.
If anyone can help me adjust it for a full folder, that would be great.
foreach(glob('SourceFolder/*.jpg', GLOB_NOSORT) as $url); {
Thumbnail ($url, "DestinationFolder/*.jpg");
function Thumbnail($url, $filename, $width = 250, $height = true, $height2 = 250) {
// download and create gd image
$image = ImageCreateFromString(file_get_contents($url));
// calculate resized ratio
// Note: if $height is set to TRUE then we automatically calculate the height based on the ratio
$height = $height === true ? (ImageSY($image) * $width / ImageSX($image)) : $height;
// create image
$output = ImageCreateTrueColor($width, $height2);
ImageCopyResampled($output, $image, 0, 0, 0, 0, $width, $height, ImageSX($image), ImageSY($image));
// save image
ImageJPEG($output, $filename, 100);
}
}
I was able to adjust the code on my own after reading the online PHP manual.
The final code:
foreach (glob("SourceFolder/*.jpg") as $url) {
$destdir = "Destination/" . basename($url, null);
$width = 250;
$height = true;
// download and create gd image
$image = ImageCreateFromString(file_get_contents($url));
// calculate resized ratio
// Note: if $height is set to TRUE then we automatically calculate the height based on the ratio
$height = $height === true ? (ImageSY($image) * $width / ImageSX($image)) : $height;
// create image
$output = ImageCreateTrueColor($width, $height);
ImageCopyResampled($output, $image, 0, 0, 0, 0, $width, $height, ImageSX($image), ImageSY($image));
// save image
ImageJPEG($output, $destdir, 100);
}
This solution uses opendir and readdir. I have found that this approach can
handle folders with more files.
// Set desired height and width
$desiredWidth = 250;
$desiredHeight = true;
// Set source and destination folders
$srcFolder = "SourceFolder";
$destFolder = "Destination";
// This is more memory efficient than using glob()
$dh = opendir($srcFolder);
if ( ! $dh ) {
die('Unable to open folder ' . $srcFolder);
}
while($filename = readdir($dh) ) {
// only process jpg files.
if ( preg_match('/.jpg$/', $filename) ) {
$inputFile = sprintf('%s/%s', $srcFolder, $filename);
$outputFile = sprintf('%s/%s', $destFolder, $filename);
echo "file: $filename\n";
echo "input: $inputFile\n";
echo "output: $outputFile\n";
$inputImage = #ImageCreateFromJpeg($inputFile);
if ( $inputImage ) {
// calculate resized ratio
// Note: if $height is set to TRUE then we automatically calculate the height based on the ratio
$height = $desiredHeight === true ? (ImageSY($inputImage) * $desiredWidth / ImageSX($inputImage)) : $desiredHeight;
// create image
$outputImage = ImageCreateTrueColor($desiredWidth, $height);
ImageCopyResampled($outputImage, $inputImage, 0, 0, 0, 0, $desiredWidth, $height, ImageSX($inputImage), ImageSY($inputImage));
// save image
ImageJPEG($outputImage, $outputFile, 100);
ImageDestroy($inputImage);
ImageDestroy($outputImage);
} else {
echo "Could not process file\n";
}
}
}
closedir($dh);
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.
I'm trying to redesign my site so that my original square, tile-based rendering of images can be more of a cutout of the image... to get rid of that grid pattern.
Here's how it looked originally...
Here's a rough mock-up of what I'm going for:
So I resaved an image thumbnail with a transparent background... I just want the dog to show, and the square is transparent which will show the site's background underneath.
Yet when I render it on the page, it has this black background.
I've checked my CSS to see if there is some sort of img class, or class for the rendered comics... or even the bootstrap to see where there may be a background-color being assigned to black (and also searched for hex code 000000), but didn't find one...
Do you know why this may be happening?
Thanks!
EDIT: I've just noticed something...
My logo at the top renders with a transparent background... and the element is a png file... therefore, its MIME type is image/png.
I'm using a thumbnailing script to make the thumbnails smaller, but now the element is of thumber.php, which puts it as MIME type image/jpeg.
So I guess it's my thumbnailing script that changing the MIME type.
So I checked it, and it's creating the file as a jpeg
//imagejpeg outputs the image
imagejpeg($img);
Is there a way to change it so that the resampled image is output as a png?
Thumbnailing script:
<?php
#Appreciation goes to digifuzz (http://www.digifuzz.net) for help on this
$image_file = $_GET['img']; //takes in full path of image
$MAX_WIDTH = $_GET['mw'];
$MAX_HEIGHT = $_GET['mh'];
global $img;
//Check for image
if(!$image_file || $image_file == "") {
die("NO FILE.");
}
//If no max width, set one
if(!$MAX_WIDTH || $MAX_WIDTH == "") {
$MAX_WIDTH="100";
}
//if no max height, set one
if(!$MAX_HEIGHT || $MAX_HEIGHT == "") {
$MAX_HEIGHT = "100";
}
$img = null;
//create image file from 'img' parameter string
$img = imagecreatefrompng($image_file);
//if image successfully loaded...
if($img) {
//get image size and scale ratio
$width = imagesx($img);
$height = imagesy($img);
//takes min value of these two
$scale = min($MAX_WIDTH/$width, $MAX_HEIGHT/$height);
//if desired new image size is less than original, output new image
if($scale < 1) {
$new_width = floor($scale * $width);
$new_height = floor($scale * $height);
$tmp_img = imagecreatetruecolor($new_width, $new_height);
//copy and resize old image to new image
imagecopyresampled($tmp_img, $img, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
imagedestroy($img);
//replace actual image with new image
$img = $tmp_img;
}
}
//set the content type header
header("Content-type: image/png");
//imagejpeg outputs the image
imagealphablending($img, false);
imagesavealpha($img, true);
imagepng($img);
imagedestroy($img);
?>
You will need to make some changes in the image generator and see if that works out for you.
The crucial changes are within the setting of the header and the method of image generation. You will be looking for these following two
header('Content-Type: image/jpeg');
change to:
header('Content-Type: image/png');
imagejpeg($im);
change to:
imagepng($im)
When dealing with png images with an alpha channel you should take a few extra steps.
Before spitting it out with imagepng(), these lines will need to be added.
imagealphablending($img, false);
imagesavealpha($img, true);
This information can be found on php.net
Edit:
Try with these alterations to this code:
if($scale < 1) {
$new_width = floor($scale * $width);
$new_height = floor($scale * $height);
$tmp_img = imagecreatetruecolor($new_width, $new_height);
imagealphablending($tmp_img,true); // add this line
//copy and resize old image to new image
imagecopyresampled($tmp_img, $img, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
$img = $tmp_img;
// remove line here
}
}
header("Content-type: image/png");
imagesavealpha($img, true);
imagepng($img);
imagedestroy($img);
imagedestroy($tmp_img); // add this line here
Basically you create new layers and put these together. For each layer you will need to set the alpha blending. I was successful in creating alpha images. Let me know what your findings are .. :-) ..
I've got a script which caches images from an external feed and stores them in a directory on my server when the image is viewed on site.
At the moment it is working great - storing the original image on my server and also creating two additional thumbnails, with their widths re-sized at 300px and 150px.
I'd like to change this slightly so that the following occurs:
Full/Original image is stored on server (as normal)
Both a square 300x300px & 150x150px .jpg thumbnail are created
However, is it possible, so that once the image width/height is resized, the additional canvas width/height is then added to make it completely square? I guess one of the issues here is determining if the image is a 'portrait' or 'landscape' first?
Also, currently I'm getting a black background with transparent PNG images. Is there any way to overcome this and fill the background with white instead?
Thank you very much for any help!! :)
Here is the code which is doing the resizing (imageCache.php):
<?php
function cacheFetch($url,$size,$age)
{
// directory in which to store cached files, must be writable by PHP
$cacheDir = "cache/";
// cache filename constructed from MD5 hash of URL
$filename = $cacheDir.md5($url);
// append size to filename if not 0
if ($size) $filename .= "_".$size;
// default to fetch the file
$fetch = true;
// but if the file exists, don't fetch if it is recent enough
if (file_exists($filename))
{
$fetch = (filemtime($filename) < (time()-$age));
}
// fetch the file if required
if ($fetch)
{
if (substr($url,0,4)=="http")
{
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
$data = curl_exec($ch);
curl_close($ch);
if (strlen($data))
{
$fp = fopen($filename,"w");
fwrite($fp,$data);
fclose($fp);
$error = false;
}
else
{
$error = true;
}
}
else
{
copy($url,$filename);
$error = false;
}
}
// return the filename only if wget did not fail
if (!$error)
{
if ($size)
{
$src = file_get_contents($filename);
$oldImage = imagecreatefromstring($src);
$oldX = imagesx($oldImage);
$oldY = imagesy($oldImage);
if ($oldX && $oldY)
{
$newX = $size;
$xFactor = ($newX / $oldX);
$newY = intval($oldY * $xFactor);
$newImage = imagecreatetruecolor($newX,$newY);
imagecopyresized($newImage, $oldImage, 0,0,0,0, $newX, $newY, $oldX, $oldY);
imagejpeg($newImage,$filename);
}
}
return $filename;
}
else
{
// as an error occured, delete the empty file so it is retried next time
unlink($filename);
// return false
return false;
}
}
require("includes/common.php");
$id = $_GET["id"];
$size = $_GET["size"];
$sql = "SELECT image_url FROM `".$config_databaseTablePrefix."products` WHERE id='".database_safe($id)."'";
if (database_querySelect($sql,$rows))
{
$src = $rows[0]["image_url"];
$src = cacheFetch($src,$size,604800);
$img = file_get_contents($src);
header("Content-Type: image");
print $img;
}
?>
and here is the .htaccess bit with sizes:
RewriteRule ^fullimage/(.*).jpg$ imageCache.php?id=$1&size=0 [L]
RewriteRule ^smallimage/(.*).jpg$ imageCache.php?id=$1&size=150 [L]
RewriteRule ^mediumimage/(.*).jpg$ imageCache.php?id=$1&size=300 [L]
EDIT: Re-worked code:
if ($size)
{
$src = file_get_contents($filename);
$oldImage = imagecreatefromstring($src);
$oldX = imagesx($oldImage);
$oldY = imagesy($oldImage);
if ($oldX && $oldY)
{
$color = imagecolorallocate($newImage, 255,255,255); //The three parameters are R,G,B
imagefilledrectangle ($newImage, 0, 0, $newX, $newY,$color);
$size = max($newX,$newY);
$newImage = imagecreatetruecolor($newX,$newY);
imagecopyresized($newImage, $oldImage, ($size-$newX)/2,($size-$newY)/2,0,0, $newX, $newY, $oldX, $oldY); //Just the coordinates was changed
imagejpeg($newImage,$filename);
Sorry, I will not add my sugestions to your code, because its is too complicated. SO just the hints.
1. How to make resised image square?
Obviously, we must create square of size of bigger dimension of original image. Here I assume the image has already been resized.
$resized = /*We hae resized image downloaded from the site [note1]*/;
$size = max(imagesx($resized), imagesy($resized)); //Make the square so the thumbnail fits in it
$thumbNail = imagecreate($size, $size); //Square.
imagecopy($thumbNail,
($size-imagesx($resized))/2, //Put the image in the middle of the square
($size-imagesy($resized))/2,
0,
0,
imagesx($resized),
imagesy($resized)
);
[note1] Alternativelly, you can just compute dimensions to make $size and copyresize image on the square. This will be faster, but is more complicated to make pseudocode for it.
2. How to change background of new images
This is no real mystery - you just draw rectangle over whole image:
$color = imagecolorallocate($thumbNail, 255,255,255);
imagefilledrectangle ($thumbNail, 0, 0, imagesx($thumbNail), imagesy($thumbNail),$color);
You can even have a transparent background:
$color = imagecolorallocatealpha($thumbNail, 255,255,255,127);
imagealphablending($thumbNail, false); //[note2]
imagefilledrectangle ($thumbNail, 0, 0, imagesx($thumbNail), imagesy($thumbNail),$color);
imagealphablending($thumbNail, true); //If you use it
[note2] Turn off blending, because transparent+black = black again
3. Code related to answer
First the resizing, copying. In the original code, we have the computed new height and width in $newX and $newY. I will use theese as of the new image sizes.
$size = max($newX,$newY);
$newImage = imagecreatetruecolor($size, $size);
imagecopyresized($newImage, $oldImage, ($size-$newX)/2,($size-$newY)/2,0,0, $newX, $newY, $oldX, $oldY); //Just the coordinates was changed
Then he background. Obviously, you should firs set the background, then copy the image. However, I'm separating theese steps so you can see what function does what.
$newImage = imagecreatetruecolor($newX,$newY);
$color = imagecolorallocate($newImage, 255,255,255); //The three parameters are R,G,B
imagefilledrectangle ($newImage, 0, 0, $newX, $newY,$color);
Let's say I uploaded an image. I can get its temp directory, then save it with move_uploaded_file() but what if I wanted to also create a thumb and save both in some folder?
I know how to save the uploaded image, but I don't know how to start manipulating an image and save it after creating a thumb.
The GD library makes this super-easy.
You will want to calculate the dimensions of your original image so that you preserve your aspect ratio, then it's just a case of resampling the image in a smaller size. Here is a good tutorial that clearly explains everything: http://www.phptoys.com/e107_plugins/content/content.php?content.46
I always use Verot PHP Upload class and always had success with it. This PHP class is really simple to implement and can manipulate a image any way you want. It can save the image also in the specified folder.
You can download it from here
To view demos and easy documentation of the Upload class visit http://www.verot.net/php_class_upload_samples.htm?PHPSESSID=5375147e959625e56e0127f3458a6385
Below is a simple sample I got from the website
//How to use it?
//Create a simple HTML file, with a form such as:
<form enctype="multipart/form-data" method="post" action="upload.php">
<input type="file" size="32" name="image_field" value="">
<input type="submit" name="Submit" value="upload">
</form>
//Create a file called upload.php:
$handle = new upload($_FILES['image_field']);
if ($handle->uploaded) {
$handle->file_new_name_body = 'image_resized';
$handle->image_resize = true;
$handle->image_x = 100;
$handle->image_ratio_y = true;
$handle->process('/home/user/files/');
if ($handle->processed) {
echo 'image resized';
$handle->clean();
} else {
echo 'error : ' . $handle->error;
}
}
//How to process local files?
//Use the class as following, the rest being the same as above:
$handle = new upload('/home/user/myfile.jpg');
you need either php gd or imagemagick. here is a quick example of resizing using gd(from the manual):
<?php
// File and new size
$filename = 'test.jpg';
$percent = 0.5;
// Content type
header('Content-type: image/jpeg');
// Get new sizes
list($width, $height) = getimagesize($filename);
$newwidth = $width * $percent;
$newheight = $height * $percent;
// Load
$thumb = imagecreatetruecolor($newwidth, $newheight);
$source = imagecreatefromjpeg($filename);
// Resize
imagecopyresized($thumb, $source, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
// Output
imagejpeg($thumb, 'thumbs/thumb1.jpg');
?>
Use Image magick.
check previous posts on stack overflow
Imagemagick thumbnail generation with php - using -crop
PHP: Creating cropped thumbnails of images, problems
Image processing class in PHP
http://www.imagemagick.org/
define('THUMB_WIDTH', 60);
define('THUMB_HEIGHT', 80);
define('MAGICK_PATH','/usr/local/bin/');
function makeThumbnail($in, $out) {
$width = THUMB_WIDTH;
$height = THUMB_HEIGHT;
list($w,$h) = getimagesize($in);
$thumbRatio = $width/$height;
$inRatio = $w/$h;
$isLandscape = $inRatio > $thumbRatio;
$size = ($isLandscape ? '1000x'.$height : $width.'x1000');
$xoff = ($isLandscape ? floor((($inRatio*$height)-$width)/2) : 0);
$command = MAGICK_PATH."convert $in -resize $size -crop {$width}x{$height}+{$xoff}+0 ".
"-colorspace RGB -strip -quality 90 $out";
exec($command);
}