How can I merge two images in PHP without GD?
PHP doesn't have the built in support to do what your asking. You'll need to
Execute another command line script/program that can
Install one of the many image manipulation libs and work with that
Possibly find a 3rd party API that you can send a request and get a response of the merged images?
Do as Emil suggested (Requires install: http://bg.php.net/manual/en/imagick.setup.php)
You can use Imagick.
You can't do image processing in PHP without some library like GD or ImageMagick.
i used this block of codes in my project to merge various images into one:
<?php
/* example invocation: http://www.yourserver.com/combine.php?dir=/images/ */
set_time_limit(5*60);
function sanitize($input) {
$input=strip_tags($input);
$input=str_replace("<","<",$input);
$input=str_replace(">",">",$input);
$input=str_replace("#","%23",$input);
$input=str_replace("'","`",$input);
$input=str_replace(";","%3B",$input);
$input=str_replace("script","",$input);
$input=str_replace("%3c","",$input);
$input=str_replace("%3e","",$input);
$input=trim($input);
return $input;
}
//accept path to images via http param dir (e.g. '/templates/corporate/images/okb/' -- include trailing slash)
$rel = '';
if (array_key_exists("dir", $_REQUEST)) $rel = sanitize($_REQUEST["dir"]);
if ($rel=='') die();
$rt = $_SERVER['DOCUMENT_ROOT'] . $rel;
$i = 0;
$imgBuf = array ();
$maxW=0; $maxH=0;
$imagesperline = 5;
$curlineW = 0;
$curlineMaxH = 0;
$imagespacing=5;
$dir = opendir ($rt);
while (false !== ($link = readdir($dir)))
{
$len = strlen($link);
$off = $len - 3;
$ext = substr($link, $off, 3);
$file = $rt . $link;
switch($ext)
{
case 'png':
$iTmp = imagecreatefrompng($file);
break;
case 'gif':
$iTmp = imagecreatefromgif($file);
break;
case 'jpeg':
case 'jpg':
$iTmp = imagecreatefromjpeg($file);
break;
default:
continue;
}
array_push ($imgBuf,$iTmp);
$i++;
if ($i == $imagesperline + 1)
{
$i = 0;
$maxW=($maxW>$curlineW)?$maxW:$curlineW;
$curlineW = 0;
$maxH+=$curlineMaxH+$imagespacing;
$curlineMaxH=0;
}
else
{
$ix = imagesx($iTmp);
$iy = imagesy($iTmp);
$curlineW+=$ix+$imagespacing;
$curlineMaxH=($iy>$curlineMaxH)?$iy:$curlineMaxH;
}
}
$iOut = imagecreate ($maxW,$maxH) ;
$i=1;
$curxpos = 0;
$curypos = 0;
$curlineMaxH=0;
foreach ($imgBuf as $img)
{
if ($i <= $imagesperline)
{
$ix = imagesx($img);
$iy = imagesy($img);
imagecopy ($iOut,$img,$curxpos,$curypos,0,0,$ix,$iy);
$curxpos+=$ix + $imagespacing;
$curlineMaxH=($iy>$curlineMaxH)?$iy:$curlineMaxH;
}
else
{
$i = 0;
$curxpos = 0;
$curypos += $curlineMaxH + $imagespacing;
$curlineMaxH = 0;
imagecopy ($iOut,$img,$curxpos,$curypos,0,0,$ix,$iy);
}
imagedestroy ($img);
$i++;
}
imagegif($iOut);
closedir ($dir);
?>
Related
I have a short PHP code to help me display random images from a specific folder. But now it seems to select any image in any size. I want those selected images are between 100-500 kb. If it's less than 100 kb or over 500 kb, the function won't select and display it.
Could you please tell me how to modify this code? Probably need to add some function.
<?php $randomdir = dir('images/random');
$count = 1;
$pattern="/(gif|jpg|jpeg|png)/";
while($file = $randomdir->read()) {
$ext = pathinfo($file, PATHINFO_EXTENSION);
if (preg_match($pattern, $ext)) {
$imagearray[$count] = $file;
$count++;
}
}
$random = mt_rand(1, $count - 1);
echo '<img src="images/random/'.$imagearray[$random].'" alt />';
?>
Try this one We have to set 2 conditions
$min = 100; //KB
$max = 500; //KB
if($_FILES['myfile']['size'] < $min * 1024 || $_FILES['myfile']['size'] > $max * 1024){
echo 'error';
}
Try now
<?php
$dir_name = 'images/random/';
$pattern="/(gif|jpg|jpeg|png)/";
$min = 100;
$max = 500;
$imagearray = array();
$scanned_directory = array_diff(scandir($dir_name), array('..', '.'));
$count = count($scanned_directory);
$ids = array_keys($scanned_directory);
$s = TRUE;
$stop = $count;
while( ($s === TRUE) && ($stop >=0))
{
$random = mt_rand(0, $count - 1);
$full_path_to_file = $dir_name.$scanned_directory[$ids[$random]];
$ext = pathinfo($full_path_to_file, PATHINFO_EXTENSION);
$file_size_kb = round(filesize($full_path_to_file)/1024);
if (preg_match($pattern, $ext) && ($file_size_kb>=$min && $file_size_kb<=$max))
{
$s = FALSE;
echo '<img src="'.$full_path_to_file.'" alt />';
}
$stop--;
}
?>
I want to validate my upload files is it an images or not. after searching i found two way that i think is a good way to do it. the first code is:
$whitelist_type = array('image/jpeg', 'image/png','image/gif');
$fileinfo = finfo_open(FILEINFO_MIME_TYPE);
if (!in_array(finfo_file($fileinfo, $file['tmp_name']), $whitelist_type)) {
$error[] = "Uploaded file is not a valid image";
}
and the second code:
if (!getimagesize($_FILES['photo']['tmp_name'])) {
$error[] = "Uploaded file is not a valid image";
}
which code is more reliable to check that it's an images and why? or is it any better way than this? thanks.
finfo_* library would be good but it will work with >= 5.3.0 versions,
AND getimagesize() GD library function that is return image info WxH and size
if image invalid then getimagesize() show warning so better to use to validate image using finfo_* function,
you can also do for cross version code, see below sample code
<?php
$file = $_FILES['photo'];
$whitelist_type = array('image/jpeg', 'image/png','image/gif');
$error = null;
if(function_exists('finfo_open')){ //(PHP >= 5.3.0, PECL fileinfo >= 0.1.0)
$fileinfo = finfo_open(FILEINFO_MIME_TYPE);
if (!in_array(finfo_file($fileinfo, $file['tmp_name']), $whitelist_type)) {
$error[] = "Uploaded file is not a valid image";
}
}else if(function_exists('mime_content_type')){ //supported (PHP 4 >= 4.3.0, PHP 5)
if (!in_array(mime_content_type($file['tmp_name']), $whitelist_type)) {
$error[] = "Uploaded file is not a valid image";
}
}else{
if (!#getimagesize($file['tmp_name'])) { //# - for hide warning when image not valid
$error[] = "Uploaded file is not a valid image";
}
}
Why not use exif_imagetype:
if (exif_imagetype($file['tmp_name']) != (IMAGETYPE_JPEG || IMAGETYPE_GIF || IMAGETYPE_PNG)) {
$error[] = "Uploaded file is not a valid image";
}
It's probably going to be faster than any of the others. (PHP 4 >= 4.3.0, PHP 5)
From a security standpoint, you might be better off converting an uploaded file presumed to be an image, see if it succeeds, and keep and serve the converted result from there on.
You could use one of those imagecreatefrom...() functions from the GD library, based on the MIME type you detected, e.g. from the $_FILES array, and/or from exif_imagetype(), finfo_file() etc.
The issue is that there are some exploits out there that pretend to be valid images (and in some cases are valid images) but are also valid JavaScript, Flash or other code containers that may be run by the client's browser under certain circumstances.
See also e.g. https://www.defcon.org/images/defcon-15/dc15-presentations/dc-15-schrenk.pdf
The fastest way I use is custom PHP function which reads specific bytes from file. It works much faster than getimagesize when check file is very large (movies, iso images etc.).
fastImageGet('image.jpg'); // returns size and image type in array or false if not image
fastImageGet('image.jpg', 'type'); // returns image type only
fastImageGet('image.jpg', 'size'); // returns image size only
function fastImageGet($file, $what=null) {
if (!in_array($what, ['size', 'type']))
$what = null;
// INIT
$pos = 0; $str = null;
if (is_resource($file))
$fp = $file;
elseif (!#filesize($file))
return false;
else
try {
$fp = fopen($file, 'r', false);
} catch (\Exception $e) {
return false;
}
// HELPER FUNCTIONS
$getChars = function($n) use (&$fp, &$pos, &$str) {
$response = null;
if (($pos + $n - 1) >= strlen($str)) {
$end = $pos + $n;
while ((strlen($str) < $end) && ($response !== false)) {
$need = $end - ftell($fp);
if (false !== ($response = fread($fp, $need)))
$str .= $response;
else
return false;
}
}
$result = substr($str, $pos, $n);
$pos += $n;
return $result;
};
$getByte = function() use ($getChars) {
$c = $getChars(1);
$b = unpack('C', $c);
return reset($b);
};
$readInt = function ($str) {
$size = unpack('C*', $str);
return ($size[1] << 8) + $size[2];
};
// GET TYPE
$t2 = $getChars(2);
if ($t2 === 'BM')
$type = 'bmp';
elseif ($t2 === 'GI')
$type = 'gif';
elseif ($t2 === chr(0xFF) . chr(0xd8))
$type = 'jpeg';
elseif ($t2 === chr(0x89) . 'P')
$type = 'png';
else
$type = false;
if (($type === false) || ($what === 'type')) {
fclose($fp);
return $type;
}
// GET SIZE
$pos = 0;
if ($type === 'bmp') {
$chars = $getChars(29);
$chars = substr($chars, 14, 14);
$ctype = unpack('C', $chars);
$size = (reset($ctype) == 40)
? unpack('L*', substr($chars, 4))
: unpack('L*', substr($chars, 4, 8));
} elseif ($type === 'gif') {
$chars = $getChars(11);
$size = unpack('S*', substr($chars, 6, 4));
} elseif ($type === 'jpeg') {
$state = null;
while (true) {
switch ($state) {
default:
$getChars(2);
$state = 'started';
break;
case 'started':
$b = $getByte();
if ($b === false) {
$size = false;
break 2;
}
$state = $b == 0xFF ? 'sof' : 'started';
break;
case 'sof':
$b = $getByte();
if (in_array($b, range(0xE0, 0xEF)))
$state = 'skipframe';
elseif (in_array($b, array_merge(range(0xC0, 0xC3), range(0xC5, 0xC7), range(0xC9, 0xCB), range(0xCD, 0xCF))))
$state = 'readsize';
elseif ($b == 0xFF)
$state = 'sof';
else
$state = 'skipframe';
break;
case 'skipframe':
$skip = $readInt($getChars(2)) - 2;
$state = 'doskip';
break;
case 'doskip':
$getChars($skip);
$state = 'started';
break;
case 'readsize':
$c = $getChars(7);
$size = [$readInt(substr($c, 5, 2)), $readInt(substr($c, 3, 2))];
break 2;
}
}
} elseif ($type === 'png') {
$chars = $getChars(25);
$size = unpack('N*', substr($chars, 16, 8));
}
// COMPLETE
fclose($fp);
if (is_array($size))
$size = array_values($size);
return ($what === 'size') ? $size : [$type, $size];
}
I'm trying to crop an image when it has been uploaded. So far I've only managed to resize it but if an image is a rectangular shape then the image is squashed which doesn't look nice. I'm trying to get coding that I can use with the function that I currently have to resize. The ones that I'm seeing I have to change my function and I'm hoping not to do that.
Here is my function
function createThumbnail($filename) {
global $_SITE_FOLDER;
//require 'config.php';
$final_width_of_image = 82;
$height = 85;
$path_to_image_directory = $_SITE_FOLDER.'portfolio_images/';
$path_to_thumbs_directory = $_SITE_FOLDER.'portfolio_images/thumbs/';
if(preg_match('/[.](jpg)$/', $filename)) {
$im = imagecreatefromjpeg($path_to_image_directory . $filename);
} else if (preg_match('/[.](gif)$/', $filename)) {
$im = imagecreatefromgif($path_to_image_directory . $filename);
} else if (preg_match('/[.](png)$/', $filename)) {
$im = imagecreatefrompng($path_to_image_directory . $filename);
}
$ox = imagesx($im);
$oy = imagesy($im);
$nx = $final_width_of_image;
$ny = floor($oy * ($final_width_of_image / $ox));
//$ny = $height;
$nm = imagecreatetruecolor($nx, $ny);
imagecopyresized($nm, $im, 0,0,0,0,$nx,$ny,$ox,$oy);
if(!file_exists($path_to_thumbs_directory)) {
if(!mkdir($path_to_thumbs_directory)) {
die("There was a problem. Please try again!");
}
}
imagejpeg($nm, $path_to_thumbs_directory . $filename);
$tn = '<img src="' . $path_to_thumbs_directory . $filename . '" alt="image" />';
$tn .= '<br />Congratulations. Your file has been successfully uploaded, and a thumbnail has been created.';
echo $tn;
}
Here is my function.
<?php
function crop($file_input, $file_output, $crop = 'square',$percent = false) {
list($w_i, $h_i, $type) = getimagesize($file_input);
if (!$w_i || !$h_i) {
echo 'Unable to get the length and width of the image';
return;
}
$types = array('','gif','jpeg','png');
$ext = $types[$type];
if ($ext) {
$func = 'imagecreatefrom'.$ext;
$img = $func($file_input);
} else {
echo 'Incorrect file format';
return;
}
if ($crop == 'square') {
$min = $w_i;
if ($w_i > $h_i) $min = $h_i;
$w_o = $h_o = $min;
} else {
list($x_o, $y_o, $w_o, $h_o) = $crop;
if ($percent) {
$w_o *= $w_i / 100;
$h_o *= $h_i / 100;
$x_o *= $w_i / 100;
$y_o *= $h_i / 100;
}
if ($w_o < 0) $w_o += $w_i;
$w_o -= $x_o;
if ($h_o < 0) $h_o += $h_i;
$h_o -= $y_o;
}
$img_o = imagecreatetruecolor($w_o, $h_o);
imagecopy($img_o, $img, 0, 0, $x_o, $y_o, $w_o, $h_o);
if ($type == 2) {
return imagejpeg($img_o,$file_output,100);
} else {
$func = 'image'.$ext;
return $func($img_o,$file_output);
}
}
?>
And you can call like this
crop($file_input, $file_output, $crop = 'square',$percent = false);
And also resize function if you need.
<?php
function resize($file_input, $file_output, $w_o, $h_o, $percent = false) {
list($w_i, $h_i, $type) = getimagesize($file_input);
if (!$w_i || !$h_i) {
return;
}
$types = array('','gif','jpeg','png');
$ext = $types[$type];
if ($ext) {
$func = 'imagecreatefrom'.$ext;
$img = $func($file_input);
} else {
return;
}
if ($percent) {
$w_o *= $w_i / 100;
$h_o *= $h_i / 100;
}
if (!$h_o) $h_o = $w_o/($w_i/$h_i);
if (!$w_o) $w_o = $h_o/($h_i/$w_i);
$img_o = imagecreatetruecolor($w_o, $h_o);
imagecopyresampled($img_o, $img, 0, 0, 0, 0, $w_o, $h_o, $w_i, $h_i);
if ($type == 2) {
return imagejpeg($img_o,$file_output,100);
} else {
$func = 'image'.$ext;
return $func($img_o,$file_output);
}
}
?>
resize($file_input, $file_output, $w_o, $h_o, $percent = false);
You can use SimpleImage class found here SimpleImage
[edit] Updated version with many more features here SimleImage Updated
I use this when resizing various images to a smaller thumbnail size while maintaining aspect ratio and exact image size output. I fill the blank area with a colour that suits the background for where the image will be placed, this class supports cropping. Explore the methods cutFromCenter and maxareafill.
For example in your code you would not need to imagecreatefromjpeg() you would simply;
Include the class include('SimpleImage.php');
then;
$im = new SimpleImage();
$im->load($path_to_image_directory . $filename);
$im->maxareafill($output_width,$output_height, 0,0,0); // rgb
$im->save($path_to_image_directory . $filename);
I use this class daily and find it very versatile.
Only one of the thumbnail images saves to the folder of this script even though several images are uploading. I'm thinking it must be something related to the iteration of the foreach loop. This is only the resizing script posted below. Does anyone have a quick fix? Thanks
define('THUMBS_DIR', 'C: /inetpub / wwwroot / mysite / images / thumbs / ');
define('MAX_WIDTH', 90);
define('MAX_HEIGHT', 100);
if (array_key_exists('upload', $_POST))
{
$original = $_FILES['image']['tmp_name'];
foreach ($original as $number => $tmp_file)
{
$original = ($tmp_file);
}
if (!$original)
{
echo 'NoImageSelected';
}
} else {
list($width, $height, $type) = getimagesize($original);
if ($width <= MAX_WIDTH && $height <= MAX_HEIGHT)
{
$ratio = 1;
} elseif ($width > $height) {
$ratio = MAX_WIDTH/$width;
} else {
$ratio = MAX_HEIGHT/$height;
}
$imagetypes = array(' / . gif$ / ',' / . jpg$ / ',' / . jpeg$ / ',' / . png$ / ');
$name = preg_replace($imagetypes, '', basename($file[$location]));
$moved = # move_uploaded_file($original[$location], THUMBS_DIR.$file);
if ($moved)
{
$result[] = $_FILES['image']['name'].'succesfullyuploaded';
$original = $ext.$file[$location];
}else{
$result = 'Problemuploading'.$_FILES['image']['name'];
}
if ($type == 1)
{
$source = imagecreatefromgif($original);
} elseif ($type == 2) {
$source = imagecreatefromjpeg($original);
} elseif ($type == 3) {
$source = imagecreatefrompng($original);
} else {
$result = 'Cannotidentifythefiletype';
}
}
Could you be more descriptive about what you want the script to do. I think your problem could be in :
$original = ($tmp_file);
You are overwriting the variable that you use in your foreach loop.
<?
$start = $_GET[start] ? $_GET[start] : 0 ;
$sortby = $_COOKIE[sortby] ? $_COOKIE[sortby] : "name" ;
if($_GET[sortby]){
$sortby = $_GET[sortby];
setcookie("sortby", $_GET[sortby], time()+86400 );
header("location: index.php");
}
$od = opendir("./");
while($file = readdir($od)){
if( eregi("\.(gif|jpe?g|png)$", $file) ){
$file2 = rawurlencode($file);
$img_arr[$file2] = $file;
$img_arr_filesize[$file2] = filesize($file);
$img_arr_filemtime[$file2] = filemtime($file);
list($imagex, $imagey, $type, $attr) = getimagesize($file);
$img_arr_sizexy[$file2] = $imagex."x".$imagey;
}
}
asort($img_arr);
asort($img_arr_filesize);
asort($img_arr_filemtime);
switch($sortby){
case "time":
$img_arr_final = $img_arr_filemtime;
break;
case "size":
$img_arr_final = $img_arr_filesize;
break;
case "name":
$img_arr_final = $img_arr;
break;
}
$total_images = count($img_arr_final);
foreach($img_arr_final as $k=>$v){
$i++;
if($i < $start+1) continue;
if($i > $start + $pp) break;
$img_name = strlen($img_arr[$k]) > 18 ? substr($img_arr[$k],0,16)."..." :$img_arr[$k];
$alt = $img_arr[$k] . " -|- Last modified: " . date("Y-m-d H:i:s", $img_arr_filemtime[$k]) . " ";
$imgl .= "<div class=\"img_thumb\"><img src=\"index.php?thumb=$k\" alt=\"$alt\" title=\"$alt\" /><p title=\"".$img_arr[$k]."\"><strong>".$img_name. "</strong><br /><span class=\"mini\">".$img_arr_sizexy[$k].", ".round(($img_arr_filesize[$k]/1024))." KB</span></p></div>";
}
for($p=0; $p*$pp < $total_images ; $p++){
$active = ($p*$pp) == $start ? "active" : "" ;
$page_htmo .= "".($p+1)." ";
}
$arr_sortby = array("name"=>"Name", "size"=>"Size", "time"=>"Time");
foreach($arr_sortby as $k=>$v){
if($sortby == $k){
$sortby_html[] = "<strong>$v</strong>";
} else {
$sortby_html[] = "$v";
}
}
$sortby_htmo = implode(" | ", $sortby_html);
function make_thumbnail($updir, $img){
global $thumb_width, $thumb_height;
$thumbnail_width = $thumb_width ? $thumb_width : 120;
$thumbnail_height = $thumb_height ? $thumb_height : 80;
$arr_image_details = GetImageSize("$updir"."$img");
$original_width = $arr_image_details[0];
$original_height = $arr_image_details[1];
if( $original_width > $original_height ){
$new_width = $thumbnail_width;
$new_height = intval($original_height*$new_width/$original_width);
} else {
$new_height = $thumbnail_height;
$new_width = intval($original_width*$new_height/$original_height);
}
$dest_x = intval(($thumbnail_width - $new_width) / 2);
$dest_y = intval(($thumbnail_height - $new_height) / 2);
if($arr_image_details[2]==1) { $imgt = "ImageGIF"; $imgcreatefrom = "ImageCreateFromGIF"; $imgx = "gif"; }
if($arr_image_details[2]==2) { $imgt = "ImageJPEG"; $imgcreatefrom = "ImageCreateFromJPEG"; $imgx = "jpeg"; }
if($arr_image_details[2]==3) { $imgt = "ImagePNG"; $imgcreatefrom = "ImageCreateFromPNG"; $imgx = "png"; }
if( $imgt ) {
$old_image = $imgcreatefrom("$updir"."$img");
$new_image = ImageCreateTrueColor($thumbnail_width, $thumbnail_height);
imageCopyResized($new_image,$old_image,$dest_x,
$dest_y,0,0,$new_width,$new_height,$original_width,$original_height);
header("Content-Type: image/jpeg"); imagejpeg($new_image, NULL, 80);
}
}
if($_GET['thumb']) {
if( in_array($_GET['thumb'], $img_arr) ) make_thumbnail("./", $_GET['thumb']); // against file inclusion
exit();
}
?>
This is a gallery generator script, but it only shows me the pics when they are in the same directory as the script is in, how could I modify it to allow other scripts.
I've tried many tweaks but, nothing works.
It's almost certainly a file permissions issue as you're trying to open the root directory.
$od = opendir("./");
It will work for the directory that the script is in as the script will have permissions to access that directory.
I don't recommend giving PHP permission to access the root folder (even only in read mode) as it is a huge security risk, as theoretically someone could read your passwords file.
Instead you should use a non-root directory to hold the images you want to generate a gallery for and only give read permission to that, i.e.
mkdir /var/images
chmod a+r /var/images