When i submit a new image to database which is extracted from pdf,it should be cropped image of original image. If the image already exists in database, than image should not be inserted and if its not inserted,i have to generate an identification value for that.
The identification value will also be inserted to the same table as of image.
There are keys involved. table page have the following identies
pid,qid,pidentifierval,image
$record = array('pid' => "NULL",
'qid' => $qid,
'pidentifierval' => $pid,
'image' => $crop,
'rotation' => 0);
function newquestionnaire($filename,$desc = "",$type="pngmono"){
global $db;
if ($desc == "") $desc = $filename;
//generate temp file
$tmp = tempnam(TEMPORARY_DIRECTORY, "FORM");
//print "Creating PNG files<br/>";
//use ghostscript to convert to PNG
exec(GS_BIN . " -sDEVICE=$type -r300 -sOutputFile=\"$tmp\"%d.png -dNOPAUSE -dBATCH \"$filename\"");
//add to questionnaire table
//
//create form entry in DB
//
$db->StartTrans();
$sql = "INSERT INTO questionnaires (qid,description,sheets)
VALUES (NULL,'$desc',0)";
$db->Execute($sql);
$qid = $db->Insert_Id();
//Number of imported pages
$pages = 0;
//read pages from 1 to n - stop when n does not exist
$n = 1;
$file = $tmp . $n . ".png";
while (file_exists($file))
{
$data = file_get_contents($file);
$images = split_scanning($data);
unset($image);
unset($data);
foreach($images as $data)
{
//header Cropped Function
// Original image
$filename = $data;
// Get dimensions of the original image
list($current_width, $current_height) = getimagesize($filename);
// The x and y coordinates on the original image where we
// will begin cropping the image
$left = 50;
$top = 50;
// This will be the final size of the image (e.g. how many pixels
// left and down we will be going)
$crop_width = 200;
$crop_height = 200;
// Resample the image
$canvas = imagecreatetruecolor($crop_width, $crop_height);
$current_image = imagecreatefromjpeg($filename);
imagecopy($canvas, $current_image, 0, 0, $left, $top, $current_width, $current_height);
$crop = imagepng($canvas, $filename, 100);
//check for header Cropped Image
what function should i made here ?
$pid = $pid.$pages;
if ($pid)
{
$pages++;
$record = defaultpage($qid,$pid,$crop);
$db->AutoExecute('pages',$record,'INSERT');
}
else
print T_("INVALID - IGNORING BLANK PAGE");
unset($data);
unset($crop);
i am confused here,that how should i check and compare if the image exists in the database or not. Please help
For cropping the image
i have found a solution
$data = '1.png';
list($current_width, $current_height) = getimagesize($data);
// The x and y co-ordinates on the original image where we will begin cropping the image
$left = 1100;
$top = 30;
// final size of image
$crop_width = 200;
$crop_height = 200;
//Resample the Image
$canvas = imagecreatefromtruecolor($crop_width, $crop_height);
$current_image = imagecreatefrompng($data);
imagecopy($canvas, $current_image, 0, 0, $left, $top, $current_width, $current_height);
imagepng($canvas, $data, 100);
For comparing two images
array image_compare(mixed $image1, mixed $image2, int $RTolerance, int $GTolerance, int $BTolerance, int $WarningTolerance, int $ErrorTolerance)
Parameters
image1
- A string containing the path to the image, or a resource of an image already created by GD Library. This is the first image to be compared.
image2
- A string containing the path to the second image, or a resource of the second image already created by GD Library. This will be the second image to be compared.
RTolerance, GTolerance, BTolerance (0-255)
- Specifies the maximum deviation for the red, green, or blue (respectively) channel before throwing a flag.
WarningTolerance (0-100)
- Percentage of channel differences before warning returned.
ErrorTolerance (0-100)
- Percentage of channel differences before error (flag) returned.
Return Values
An array will be returned with the following information:
PixelsByColors
- Pixel quantity * 3 (for each of R,G, and B channels).
PixelsOutOfSpec
- (If a pixel varies outside of xTolerance, for each red, green, and blue. Where x = R/G/B) If any channel exceeds the threshhold, this number is incremented.
PercentDifference
- The percentage of difference comparing PixelsOutOfSpec to PixelsByColors
WarningLevel and ErrorLevel
- If the percentage was large enough to trigger either the specified warning, or error level.
For comparison i have to work, i am thinking to use array.Using Select query for
getting images from the database,using while loop and fetching the result in array,calling array keys for the image to be stored in variable and using if else condition in the compare function above will work i think. What you people think ?
For image comparision, No Scanned image can be 100 percent accurate, so image comparision is not so easy. It is quite hectic task.
After a Lot of Research and work, I came to a point that if it is 100 percent necessary to do image comparision. I will have to use Php-OpenCV Library. If i have to allow some sort of error tolerance, the above class can work properly. My work can was achieved using Php-tesseract. I have simply used tesseract-OCR. I used ghostscript for converting the PDF into png, cropped the image, convert that particular part of image into text using Php-tesseract OCR Library that is placed on google Code website. Called that text into variable,using regexpression i was able to check that whether a particular text exists in the variable or not and used it in the condition as requried for me.
Consider this as end of my problem.
For convenience of the visitors i am pasting my Code Snippet so that it can be used.
// Cropping the image
// Get dimensions of the original image
list($current_width, $current_height) = getimagesize($file);
// The x and y co-ordinates on the original image where we will begin cropping the image
$left = 1100;
$top = 30;
// final size of image
$crop_width = 700;
$crop_height = 200;
//Resample the Image
$canvas = imagecreatetruecolor($crop_width,$crop_height);
$current_image = imagecreatefrompng($file);
imagecopy($canvas, $current_image, 0, 0, $left, $top, $current_width, $current_height);
imagepng($canvas, $file, 1);
// Note you will have to install Php tesseract Library before making the API Call.
$api= new TessBaseAPI;
$api->Init(".","eng",$mode_or_oem=OEM_DEFAULT);
$api->SetPageSegMode(PSM_AUTO);
$mImgFile = $file;
$handle=fopen($mImgFile,"rb");
$mBuffer=fread($handle,filesize($mImgFile));
//print strlen($mBuffer);
$result=ProcessPagesBuffer($mBuffer,strlen($mBuffer)*4,$api);
//print $result;
$result = ProcessPagesFileStream($mImgFile,$api);
//print "result(ProcessPagesFileStream)=";
print $result;
$txtchk = 'FORM';
if(preg_match("/$txtchk/i", $result)) {
echo true;
}
I hope it will be helpful for lot of people.
Related
I have my own PHP function allowing users to update their profile image.
It all works fine, however, I am having a problem where users can upload any size image they want; i.e: 564 x 346.
I do not want this to happen. I would like the image that they select to upload to be cropped to a 1:1 ratio and centred; i.e: it goes from 564 x 346 to 346 x 346 and centres to the middle of the image.
None of the scripts that I have found seem to work for my site (at least the way I want them to).
This is the code I am currently using to update their avatar. It consists of checking if they have a correct file extension & if the image is less than 256kb in size:
$ext = array('jpg', 'jpeg', 'png');
$file = $_FILES['avatar']['name'];
$fileext = strtolower(end(explode('.', $file)));
$filetmp = $_FILES['avatar']['tmp_name'];
if(!in_array($fileext, $ext)){
$errors[] = 'Please select a valid file type. (JPG, JPEG or PNG)'; }
if($_FILES['avatar']['size'] > 256000){
$errors[] = 'Avatars cannot exceed a 256kb file size.';
}
if(empty($errors)){
updateAvatar($conn, $username, $filetmp, $fileext);
} else if(!empty($errors)){
echo output_errors($errors);
}
if(isset($_SESSION['updateAvat'])){
flash('You have successfully updated your avatar.');
unset($_SESSION['updateAvat']);
}
This is the updateAvatar() function that I have made and is called on line 13:
function updateAvatar($conn, $username, $filetmp, $fileext){
$file = md5(microtime() . $filetmp) . '.' . $fileext;
$filepth = './data/user_data/img/udid/prof/' . $file;
move_uploaded_file($filetmp, $filepth);
if(mysqli_query($conn, "UPDATE users SET profile = '$file' WHERE username = '$username'")){
$_SESSION['updateAvat'] = md5(microtime() . $filetmp);
} else {
$errors[] = 'There was a problem updating your avatar. Please try again.';
}
}
However, this is not enough and does not allow my users profile page to work or look the way it should, I am going for something along the lines of how Google or Twitter do their avatar's.
All help is appreciated.
Cheers.
There is imagecrop() function in php:
$tmpfile = $_FILES['avatar']['tmp_name'];
switch ($fileext) {
case 'jpg':
case 'jpeg':
$image = imagecreatefromjpeg($tmpfile);
break;
case 'png':
$image = imagecreatefrompng($tmpfile);
break;
default:
die("wtf is this extension??");
}
list($w, $h) = getimagesize($imgfile);
// get width $w and height $h for the image
if ($w < $h) // then keep the width and scale the height
$image = imagecrop($image, array(
"x" => 0,
"y" => ($h - $w) / 2,
"width" => $w,
"height" => $w
));
else if ($h < $w) // then keep the height and scale the width
$image = imagecrop($image, array(
"x" => ($w - $h) / 2,
"y" => 0,
"width" => $h,
"height" => $h
));
I haven't tried this code but I'm quite sure it's right. Try it and tell me if it doesn't work.
UPDATE:
Then you can save the resource $image with imagejpeg() or imagepng() to save the images with the same extensions so you won't have problems with the database:
imagejpeg($image, "/path/to/your/image.jpg");
This is an explanation of how the process works, this is not a copy
and paste code but a description of the logic processes you need to
understand to resize images in PHP
You want to be using PHP imagecopyresampled to take the original image and then work out mathematically the margins to make it a square and then resize that square.
Process:
Uploaded image is checked is a genuine image and genuine filetype.
Using imagecreatefromjpeg (or similar ones for PNG etc.) you can import the uploaded image file resource.
Using getimagesize you can find the dimensions, you can then find the aspect ratio of the image.
If the aspect ratio is > 1 then width is larger than height so you then need to assume a square the same size as height (as it's the smaller value). For example:
.
Width: 450
Height: 300
Ratio = 450/300 = 3/2 = 1.5 = >1
If the aspect ratio is <1 then the height is larger than the width.
So you want a square that is 300x300 so you need to cut off the excess 150 from the width. This is called the Margin, and to centre the image you need to cut off half of the margin from each side so:
.
$fullMargin = (width- height)
$margin = $fullMargin/2
Just before resizing and saving the new image, a new image resource should be generated:
.
$max_width = $max_height = 256;
$smallestDimensionValue = $originalHeight //(in this example);
$newImage = imagecreatetruecolor($max_width,$max_height);
$sourceHeight = $originalHeight;
$sourceWidth = $originalWidth - $fullMargin;
Finally, Image copy and resample and the output should be as intended:
.
imagecopyresampled($nwImage, $sourceImage, 0,0,$margin,0,$max_width,$max_height,$sourceWidth,$sourceHeight);
PHP scales the image in the imagecopyresampled automatically, but to understand it, Once you've established the Margin size for the full size image you then have to multiply the margin by the same value as the width and the height to scale the overall image to the appropriate size.
Say for example you want the avatar to have a maximum size of 256px then:
maximum_allowed_width / original_width = scale_factor.
So for the example above this is:
256 / 450 = 0.56888888
This is the value the margin value defined above, as well as the height and width of the destination image, is multiplied by.
A couple of years ago I authored a PHP (ZEND) module that I still use today in some of my projects. This module was built with a fairly rudimentary (i.e. copypasta) understanding of PHP image manipulation but works beautiful except in one case.
The module pulls blob data from a table, parses it into an image, uses imagcopyresampled() to resize it, and then sends the resulting .jpg to the browser, it is called as a standard controller action.
It seems to work in all cases except when the original image was saved by a user from facebook (i.e. right click on the facebook image viewer and download to desktop and then upload to client site). I've tested this a number of times myself and been able to replicate it. I've also been able to upload the same image when re-saved via photoshop without encountering the problem.
I suspect the facebook image display adds some sort of additional metadata inside the file that causes my system to break.
Is there a solution for this?
The code for the PHP image module is as follows:
private function _buildImage($mode) {
//Prepare the output image
//Currently CROP and RESIZE are using different output onstruction calls
//So $finalImage is initialized prior to entering the mode blocks.
$finalImage = imagecreatetruecolor($this->_width, $this->_height);
$backgroundFillColor = imagecolorallocate($finalImage, RED, BLUE, GREEN);
imageFill($finalImage, 0, 0, $backgroundFillColor);
$this->_table = $this->_getTable($mode);
$image = $this->_request->image;
$this->_imageData = $this->_table->fetchEntryAsRow($image);
//Set top and left to 0 to capture the top/left corner of the orignal image.
$top = 0;
$left = 0;
$inputImage = imagecreatefromstring( $this->_imageData->image);
list($inputWidth, $inputHeight) = $this->_getImageSize($this->_imageData->image);
//Ratio is the target ratio of $this->_width divided by $this->_height, as set in actions.
//For index thumbnails this ratio is .7
//For index large images this ratio is 2
$ratio = $this->_width / $this->_height;
//define offset width and offset height as being equal to input image width and height
$offsetWidth = $inputWidth;
$offsetHeight = $inputHeight;
//Define Original Ratio as found in the image in the table.
$inputRatio = $inputWidth / $inputHeight;
//Rendering maths for RESIZE and CROP modes.
//RESIZE forces the whole input image to appear within the frame of the output image.
//CROP forces the output image to contain only the relevantly sized piece of the input image, measured from the middle.
if($this->_mode == CROP) {
if($inputRatio > $ratio) {
//Original image is too wide, use $height as is. Modify $width;
//define $scale: input is scaled to output along height.
$scale = $inputHeight / $this->_height;
//Calculate $left: an integer calculated based on 1/2 of the input width * half of the difference in the rations.
$left = round(($inputWidth/2)*(($inputRatio-$ratio)/2), 0);
$inputWidth = round(($inputWidth - ($left*2)), 0);
$offset = $offsetWidth - $inputWidth;
} else {
//Original image is too high, use $width as is. Modify $height;
$scale = $inputWidth / $this->_width;
$inputHeight = round(($this->_height * $scale),0);
$offset = $offsetHeight - $inputHeight;
$top = $offset / 2;
}
imagecopyresampled($finalImage, //Destination Image
$inputImage, //Original Image
0, 0, //Destination top left Coord
$left, $top, //Source top left coord
$this->_width, $this->_height, //Final location Bottom Right Coord
$inputWidth, $inputHeight //Source bottom right coord.
);
} else {
if($inputRatio < $ratio) {
//Original image is too wide, use $height as is. Modify $width;
$scale = $inputHeight / $this->_height;
$calculatedWidth = round(($inputWidth / $scale), 0);
$calculatedHeight = $this->_height;
$offset = $this->_width - $calculatedWidth;
$left = round(($offset / 2), 0);
$top = 0;
} else {
//Original image is too high, use $width as is. Modify $height;
$scale = $inputWidth / $this->_width;
$calculatedHeight = round(($inputHeight / $scale),0);
$calculatedWidth = $this->_width;
$offset = $this->_height - $calculatedHeight;
$top = round(($offset / 2), 2);
}
imagecopyresampled($finalImage, //Destination Image
$inputImage, //Original Image
$left, $top, //Destination top left Coord
0, 0, //Source top left coord
$calculatedWidth, $calculatedHeight, //Final location Bottom Right Coord
$inputWidth, $inputHeight //Source bottom right coord.
);
}
imagejpeg($finalImage, null, 100);
imagedestroy($inputImage);
imagedestroy($finalImage);
}
I suspect that the problem may actually lay with the implementation of _getImageSize.
private function _getImageSize($data)
{
$soi = unpack('nmagic/nmarker', $data);
if ($soi['magic'] != 0xFFD8) return false;
$marker = $soi['marker'];
$data = substr($data, 4);
$done = false;
while(1) {
if (strlen($data) === 0) return false;
switch($marker) {
case 0xFFC0:
$info = unpack('nlength/Cprecision/nY/nX', $data);
return array($info['X'], $info['Y']);
break;
default:
$info = unpack('nlength', $data);
$data = substr($data, $info['length']);
$info = unpack('nmarker', $data);
$marker = $info['marker'];
$data = substr($data, 2);
break;
}
}
}
You can see another example of this problem at http://www.angelaryan.com/gallery/Image/22 which displays a blue square, rather than the image stored in the database.
Try automatically "re-saving" the image after the upload with
imagejpeg(imagecreatefromjpeg($filename),$filename,9);
This should re-create any malformed or unrecognised headers from the original Facebook image.
I think you should use the getimagesizefromstring function instead of parsing the raw data yourself:
list($width, $height, $type) = getimagesizefromstring($data);
Resaving the image will only degrade image quality.
Using the following script I´m getting over-compressed images on the front end. They appear fine on the server, but the imagesize.php seems to be destroying the end result. Here is a visual of the issue (ignore the slight difference in size on this image, that's my bad alignment) http://puu.sh/38VaP.png. Any ideas? Here is the script...
<?php
// Get the File path for the image
$imagedir = '../../imgs';
$imagename = $_GET["file"];
$sImagePath = "$imagedir/$imagename";
// If you want exact dimensions, you
// will pass 'width' and 'height'
$iThumbnailWidth = (int)$_GET['width'];
$iThumbnailHeight = (int)$_GET['height'];
// If you want proportional thumbnails,
// you will pass 'maxw' and 'maxh'
$iMaxWidth = (int)$_GET["maxw"];
$iMaxHeight = (int)$_GET["maxh"];
// Based on the above we can tell which
// type of resizing our script must do
if ($iMaxWidth && $iMaxHeight) $sType = 'scale';
else if ($iThumbnailWidth && $iThumbnailHeight) $sType = 'exact';
// The 'scale' type will make the image
// smaller but keep the same dimensions
// The 'exact' type will make the thumbnail
// exactly the width and height you choose
// To start off, we will create a copy
// of our original image in $img
$img = NULL;
// At this point, we need to know the
// format of the image
// Based on that, we can create a new
// image using these functions:
// - imagecreatefromjpeg
// - imagecreatefrompng
// - imagecreatefromgif
//$sExtension = strtolower(end(explode('.', $sImagePath)));
$explodedImagePath = explode('.',$sImagePath);
$sExtension = strtolower(end($explodedImagePath));
if ($sExtension == 'jpg' || $sExtension == 'jpeg') {
$img = #imagecreatefromjpeg($sImagePath)
or die("Cannot create new JPEG image");
} else if ($sExtension == 'png') {
$img = #imagecreatefrompng($sImagePath)
or die("Cannot create new PNG image");
} else if ($sExtension == 'gif') {
$img = #imagecreatefromgif($sImagePath)
or die("Cannot create new GIF image");
}
// If the image has been created, we may proceed
// to the next step
if ($img) {
// We now need to decide how to resize the image
// If we chose to scale down the image, we will
// need to get the original image propertions
$iOrigWidth = imagesx($img);
$iOrigHeight = imagesy($img);
if ($sType == 'scale') {
// Get scale ratio
$fScale = min($iMaxWidth/$iOrigWidth,
$iMaxHeight/$iOrigHeight);
// To explain how this works, say the original
// dimensions were 200x100 and our max width
// and height for a thumbnail is 50 pixels.
// We would do $iMaxWidth/$iOrigWidth
// (50/200) = 0.25
// And $iMaxHeight/$iOrigHeight
// (50/100) = 0.5
// We then use the min() function
// to find the lowest value.
// In this case, 0.25 is the lowest so that
// is our scale. The thumbnail must be
// 1/4th (0.25) of the original image
if ($fScale < 1) {
// We must only run the code below
// if the scale is lower than 1
// If it isn't, this means that
// the thumbnail we want is actually
// bigger than the original image
// Calculate the new height and width
// based on the scale
$iNewWidth = floor($fScale*$iOrigWidth);
$iNewHeight = floor($fScale*$iOrigHeight);
// Create a new temporary image using the
// imagecreatetruecolor function
$tmpimg = imagecreatetruecolor($iNewWidth,
$iNewHeight);
// The function below copies the original
// image and re-samples it into the new one
// using the new width and height
imagecopyresampled($tmpimg, $img, 0, 0, 0, 0,
$iNewWidth, $iNewHeight, $iOrigWidth, $iOrigHeight);
// Finally, we simply destroy the $img file
// which contained our original image
// so we can replace with the new thumbnail
imagedestroy($img);
$img = $tmpimg;
}
} else if ($sType == "exact") {
// Get scale ratio
$fScale = max($iThumbnailWidth/$iOrigWidth,
$iThumbnailHeight/$iOrigHeight);
// This works similarly to other one but
// rather than the lowest value, we need
// the highest. For example, if the
// dimensions were 200x100 and our thumbnail
// had to be 50x50, we would calculate:
// $iThumbnailWidth/$iOrigWidth
// (50/200) = 0.25
// And $iThumbnailHeight/$iOrigHeight
// (50/100) = 0.5
// We then use the max() function
// to find the highest value.
// In this case, 0.5 is the highest so that
// is our scale. This is the first step of
// the image manipulation. Once we scale
// the image down to 0.5, it will have the
// dimensions of 100x50. At this point,
// we will need to crop the image, leaving
// the height identical but halving
// the width to 50
if ($fScale < 1) {
// Calculate the new height and width
// based on the scale
$iNewWidth = floor($fScale*$iOrigWidth);
$iNewHeight = floor($fScale*$iOrigHeight);
// Create a new temporary image using the
// imagecreatetruecolor function
$tmpimg = imagecreatetruecolor($iNewWidth,
$iNewHeight);
$tmp2img = imagecreatetruecolor($iThumbnailWidth,
$iThumbnailHeight);
// The function below copies the original
// image and re-samples it into the new one
// using the new width and height
imagecopyresampled($tmpimg, $img, 0, 0, 0, 0,
$iNewWidth, $iNewHeight, $iOrigWidth, $iOrigHeight);
// Our $tmpimg will now have the scaled down
// image. The next step is cropping the picture to
// make sure it's exactly the size of the thumbnail
// The following logic choose how the image
// will be cropped. Using the previous example, it
// needs to take a 50x50 block from the original
// image and copy it over to the new thumbnail
// Since we want to copy the exact center of the
// scaled down image, we need to find out the x
// axis and y axis. To do so, say the scaled down
// image now has a width of 100px but we want it
// to be only 50px
// Somehow, we need to select between the 25th and
// 75th pixel to copy the middle.
// To find this value we do:
// ($iNewWidth/2)-($iThumbnailWidth/2)
// ( 100px / 2 ) - (50px / 2)
// ( 50px ) - ( 25px )
// = 25px
if ($iNewWidth == $iThumbnailWidth) {
$yAxis = ($iNewHeight/2)-
($iThumbnailHeight/2);
$xAxis = 0;
} else if ($iNewHeight == $iThumbnailHeight) {
$yAxis = 0;
$xAxis = ($iNewWidth/2)-
($iThumbnailWidth/2);
}
// We now have to resample the new image using the
// new dimensions are axis values.
imagecopyresampled($tmp2img, $tmpimg, 0, 0,
$xAxis, $yAxis,
$iThumbnailWidth,
$iThumbnailHeight,
$iThumbnailWidth,
$iThumbnailHeight);
imagedestroy($img);
imagedestroy($tmpimg);
$img = $tmp2img;
}
}
// Display the image using the header function to specify
// the type of output our page is giving
header("Content-type: image/jpeg");
imagejpeg($img);
}
?>
You can adjust the compression level using the third parameter to imagejpeg. For top quality (but biggest file size) use:
imagejpeg($img, NULL, 100);
A quality value of 90 will probably give you a reasonable balance between quality and file size.
Then again, the kind of image you have in the example may be best saved as PNG, with imagepng. The JPEG format is best used for photographic images.
Looks like you're destroying the image yourself:
imagedestroy($tmpimg);
$img = $tmp2img;
... snip ...
imagejpeg($tmpimg);
You cannot imagedestroy() until AFTER you have completely finished using the GD image handle, which includes outputting it via imagejpeg. once it's destroyed, the image is GONE from memory and the handle variable becomes invalid.
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);
I am working on a script to crop images. It's working on jpgs. But is there a way to make it apply to various file types (bmp, png, gif) without going through various if clauses?
//create the crop
// Original image
$filename = 'uploads/'.$image_name;
$endname = 'uploads/thumbnails/'.$image_name;
// Get dimensions of the original image
list($current_width, $current_height) = getimagesize($filename);
// The x and y coordinates on the original image where we
// will begin cropping the image
$left = 0;
$top = 0;
// This will be the final size of the image (e.g. how many pixels
// left and down we will be going)
$crop_width = 200;
$crop_height = 200;
// Resample the image
$canvas = imagecreatetruecolor($crop_width, $crop_height);
$current_image = imagecreatefromjpeg($filename);
imagecopy($canvas, $current_image, 0, 0, $left, $top, $crop_width, $crop_height);
imagejpeg($canvas, $endname, 100);
I tried replacing imcreatefromjpeg with imagecreate but that didn't work.
imagecreatefromstring automatically detects filetype, but it requires image data as a string, but you could always do
$current_image = imagecreatefromstring(file_get_contents($filename));
scr - for your source files
dest - for resulting files
$size = getimagesize($src);
// Detect file format from MIME-information, detected by getimagesize() function
// And select proper imagecreatefrom()-function.
$format = strtolower(substr($size['mime'], strpos($size['mime'], '/')+1));
$icfunc = "imagecreatefrom" . $format;
if (!function_exists($icfunc)){
echo "Function $icfunc doesn't exists!");
}
//Here is the magic: We call function, which name is value of variable
$isrc = $icfunc($src);
// Create new img
$idest = imagecreatetruecolor($width_dest, $height_dest);
// Copy src img to dest img with resizing
imagecopyresampled(
$idest, $isrc, // dest & src img ident
0,0, // dest img (x,y) top left corner
0,0, // src img (x,y) top left corner
$width_dest, $height_dest,
$width_src, $height_src
);