On a PWA, full legacy/handmade PHP/JS (jquery), i'm trying to avoid all the bug and problems with picture.
I've solved the famous bug where picture are 90° rotate
I've dicreased the weight with the "quality" parameter in imagejpeg
And i'm trying to resize it with no less than 800px for width and no more less 600px for height. Like, 810x750 it's okay for me, 1500x620 too, but no 500x450.
1 and 2 work fine. The third point is bit complicated it "crop" my picture with false position and there is this famous black bar on right.
I've read a lot of articles on it with sometimes solutions, but they are always "isolated" scripts, intended for the black bar. I want to solve my problem by keeping this big function which makes resize/rotate/decrease weight.
I don't want a copy/thumbnail, just the original with correct size.
Here's my code
function compressImage($source, $destination, $quality) {
error_log('====================');
error_log('Source : '.$source);
error_log('Destination : '.$destination);
error_log('Qualité : '.$quality);
$imgInfo = getimagesize($source);
$mime = $imgInfo['mime'];
// EXTRACT INFO
$newPic = imagecreatefromstring(file_get_contents($source));
$exif = exif_read_data($source);
$rotation = 0;
if(!empty($exif['Orientation'])) {
error_log('Orientation : '.$exif['Orientation']);
// CHECK IF PHP DID WRONG ROTATION
switch($exif['Orientation']) {
case 8:
$newPic = imagerotate($newPic, 90, 0);
break;
case 3:
$newPic = imagerotate($newPic, 180, 0);
break;
case 6:
$newPic = imagerotate($newPic, -90 ,0);
break;
}
$rotation = 1;
time_nanosleep(0, 500000000);
}
$w = 800;
$h = 600;
list($width, $height) = $imgInfo;
error_log('Actual width : '.$width);
error_log('Actual height : '.$height);
$r = $width / $height;
if($w/$h > $r) {
$newWidth = $h*$r;
$newHeight = $h;
} else {
$newHeight = $w/$r;
$newWidth = $w;
}
// CALCULATE NEW SIZE (MAYBE HERE FOR MISTAKE ?)
error_log('New width : '.$newWidth);
error_log('New height : '.$newHeight);
$thumb = imagecreatetruecolor($newWidth, $newHeight);
if($rotation == 1) {
error_log('2nd MIME : '.$mime);
switch($mime) {
case 'jpg':
error_log('JPG');
$newPic = imagejpeg($image, $destination, $quality);
break;
case 'jpeg':
error_log('JPEG');
$newPic = imagejpeg($image, $destination, $quality);
break;
}
time_nanosleep(0, 500000000);
}
imagecopyresized($thumb, $newPic, 0, 0, 0, 0, $newWidth, $newHeight, $width, $height);
$newPic = imagejpeg($thumb, $destination, $quality);
move_uploaded_file($newPic, $destination);
}
Here's a complete example :
Randomly wanted 9000x12000 to be 800x600 but for example if someone sends a picture of 1685x1235 (random) i want 819x600. (if we took the width as a reference in this specific case instead it would not be good because we would have 800x586 (and therefore 586 < 600)
Edit : after two weeks of tests i can't afford what i want, thanks to everyone who have solution to resize, prevent rotate bug and crop in one script.
I'm new to php, and I found a tutorial about cropping image, with a strange instruction I never see. I don't know how to search about it.
$src_img = $image_create($source_file);
Here it is the full code of the tutorial
//resize and crop image by center
function resize_crop_image($max_width, $max_height, $source_file, $dst_dir, $quality = 80){
$imgsize = getimagesize($source_file);
$width = $imgsize[0];
$height = $imgsize[1];
$mime = $imgsize['mime'];
switch($mime){
case 'image/gif':
$image_create = "imagecreatefromgif";
$image = "imagegif";
break;
case 'image/png':
$image_create = "imagecreatefrompng";
$image = "imagepng";
$quality = 7;
break;
case 'image/jpeg':
$image_create = "imagecreatefromjpeg";
$image = "imagejpeg";
$quality = 80;
break;
default:
return false;
break;
}
$dst_img = imagecreatetruecolor($max_width, $max_height);
$src_img = $image_create($source_file);
$width_new = $height * $max_width / $max_height;
$height_new = $width * $max_height / $max_width;
//if the new width is greater than the actual width of the image, then the height is too large and the rest cut off, or vice versa
if($width_new > $width){
//cut point by height
$h_point = (($height - $height_new) / 2);
//copy image
imagecopyresampled($dst_img, $src_img, 0, 0, 0, $h_point, $max_width, $max_height, $width, $height_new);
}else{
//cut point by width
$w_point = (($width - $width_new) / 2);
imagecopyresampled($dst_img, $src_img, 0, 0, $w_point, 0, $max_width, $max_height, $width_new, $height);
}
$image($dst_img, $dst_dir, $quality);
if($dst_img)imagedestroy($dst_img);
if($src_img)imagedestroy($src_img);
}
//usage example
resize_crop_image(100, 100, "test.jpg", "test.jpg");
$image_create returns a string.
This sting is a dynamic function (whose name is decided run time)
Reference:
http://php.net/manual/en/functions.variable-functions.php
Instead of adding 3 if statements for choosing three functions:
imagecreatefromgif(), imagecreatefrompng() and imagecreatefromjpeg(),
a variable is taken which will switch the function variable (name) and that will be used.
Which is easier to use.
First up: I don't know what tutorial you're following, but it doesn't look to be a particularly good one. The code, to my eye, looks very messy and a bit dated. It also doesn't follow the coding standards at all... I'd steer clear.
To answer your question, though:
$image_create = 'imagecreatefromjpeg';
Is assigning a string to the variable, at first glance, but that string happens to be a function name, too. Basically, read this:
$src_img = $image_create($source_file);
as either one of three calls:
$src_img = imagecreatefromjpeg($source_file);
//or
$src_img = imagecreatefrompng($source_file);
//or
$src_img = imagecreatefromgif($source_file);
Depending on the value of $image_create...
It is calling a function via a variable that contains the function's name.
Note that $image_create is set depending on what type of image the code is trying to create. This allows the rest of the code that doesn't care about the image type to be consolidated, which is a good practice.
In other words...
src_img = imagecreatefromjpeg($source_file);
is-the-same-as...
$image_create = 'imagecreatefromjpeg';
src_img = $image_create($source_file);
I am uploading image with uploadify V2.1.4. After uploading image I am trying to create thumbnails of size 60x60 and 80x80 in uploadify.php file. Thumbnails are get created for jpg, png, gif file type. But it is not created when file type is jpeg.
$imgsize = getimagesize($targetFile);
switch(strtolower(substr($targetFile, -3)))
{
case "jpeg":
case "jpg":
$image = imagecreatefromjpeg($targetFile);
break;
case "png":
$image = imagecreatefrompng($targetFile);
break;
case "gif":
$image = imagecreatefromgif($targetFile);
break;
default:
exit;
break;
}
$width = 60; //New width of image
$height=60;
$src_w = $imgsize[0];
$src_h = $imgsize[1];
$picture = imagecreatetruecolor($width, $height);
imagealphablending($picture, false);
imagesavealpha($picture, true);
$bool = imagecopyresampled($picture, $image, 0, 0, 0, 0, $width, $height, $src_w, $src_h);
$image_name='';
if($bool)
{
$image_name=$newf_name;
$parts=explode('.',$newf_name);
$newf_name=$parts[0]."_90X90.".$parts[1];
switch(strtolower(substr($targetFile, -3)))
{
case "jpeg":
case "jpg":
header("Content-Type: image/jpeg");
$bool2 = imagejpeg($picture,$path."thumb/".$newf_name,80);
break;
case "png":
header("Content-Type: image/png");
imagepng($picture,$path."thumb/".$newf_name);
break;
case "gif":
header("Content-Type: image/gif");
imagegif($picture,$path."thumb/".$newf_name);
break;
}
}
The the operation system of the computer where you uploading your images from is absolutely irrelevant.
Instead of posting the code here you have to debug it yourself.
There is very little sense in posting code here. You will get but some wild guesses, mostly irrelevant to your case.
So, you have to make your code to tell you what is going wrong. this is called debugging and being the most important programmer's skill.
First of all you have to be sure, that you will be informed of all errors occurred.
add these lines at hthe top of your code
ini_set('display_errors',1);
error_reporting(E_ALL);
and see if if it says something.
if not - trace your program step by step.
add some exit's in your code along with printing relevant variables contents to check if they have desired value.
If you're using codeigniter (as it's been tagged) why not use codeigniter's image manipulation class?
http://codeigniter.com/user_guide/libraries/image_lib.html
It's really simple and theres plenty of documentaion to upload images and create thumbs!
Oddly enough, I can't find any info on this topic: user profile pictures.
Is there a PHP solution for the following?
Allows users to upload a pic from their hard drive for storage on our server
Shrinks the image if it's too big; expands it if it's too small (height/width)
Is this easy to build yourself? Or is there already a library for it?
To upload and store the image, I would recommend generating a random filename for the picture, instead of keeping the original file name. This will prevent conflicts and also add a measure of security. I would suggest a pretty long name; just random numbers and letters.
Then, store the random file name in the database record along with your user info. This way, you won't have to worry about file names and user names getting out of sync, and, as I said earlier, someone won't be able to guess that Joe Schmoe's profile picture is stored as JoeSchmoe.jpg.
For when you get to the image-resizing part, use this function below I modified (from the PHP user comments). In your case, "images/smallerpicture.jpeg" would probably be replaced by "images/<some random name here>.jpeg".
Example:
scaleImage("images/bigpicture.jpeg", 100, 100, "images/smallerpicture.jpeg");
Function:
function scaleImage($source, $max_width, $max_height, $destination) {
list($width, $height) = getimagesize($source);
if ($width > 150 || $height > 150) {
$ratioh = $max_height / $height;
$ratiow = $max_width / $width;
$ratio = min($ratioh, $ratiow);
// New dimensions
$newwidth = intval($ratio * $width);
$newheight = intval($ratio * $height);
$newImage = imagecreatetruecolor($newwidth, $newheight);
$exts = array("gif", "jpg", "jpeg", "png");
$pathInfo = pathinfo($source);
$ext = trim(strtolower($pathInfo["extension"]));
$sourceImage = null;
// Generate source image depending on file type
switch ($ext) {
case "jpg":
case "jpeg":
$sourceImage = imagecreatefromjpeg($source);
break;
case "gif":
$sourceImage = imagecreatefromgif($source);
break;
case "png":
$sourceImage = imagecreatefrompng($source);
break;
}
imagecopyresampled($newImage, $sourceImage, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
// Output file depending on type
switch ($ext) {
case "jpg":
case "jpeg":
imagejpeg($newImage, $destination);
break;
case "gif":
imagegif($newImage, $destination);
break;
case "png":
imagepng($newImage, $destination);
break;
}
}
}
It supports gifs, jpgs, and pngs.
Maybe this basic tut can hep you:
Building your own Tutorial CMS
To manipulate images with php, it is very easy with:
PHP: GD
1
Good luck
It's hard to answer this because "easy" is very relative term. For an experiences php coder it's easy, for a beginner it's not so easy. Yes, there are libraries for image resizing. You probably will have to handle processing of upload yourself, it's really easy
For resizing you can take a look at pear library here
What's the most efficient way to resize large images in PHP?
I'm currently using the GD function imagecopyresampled to take high resolution images, and cleanly resize them down to a size for web viewing (roughly 700 pixels wide by 700 pixels tall).
This works great on small (under 2 MB) photos and the entire resize operation takes less than a second on the server. However, the site will eventually service photographers who may be uploading images up to 10 MB in size (or images up to 5000x4000 pixels in size).
Doing this kind of resize operation with large images tends to increase the memory usage by a very large margin (larger images can spike the memory usage for the script past 80 MB). Is there any way to make this resize operation more efficient? Should I be using an alternate image library such as ImageMagick?
Right now, the resize code looks something like this
function makeThumbnail($sourcefile, $endfile, $thumbwidth, $thumbheight, $quality) {
// Takes the sourcefile (path/to/image.jpg) and makes a thumbnail from it
// and places it at endfile (path/to/thumb.jpg).
// Load image and get image size.
$img = imagecreatefromjpeg($sourcefile);
$width = imagesx( $img );
$height = imagesy( $img );
if ($width > $height) {
$newwidth = $thumbwidth;
$divisor = $width / $thumbwidth;
$newheight = floor( $height / $divisor);
} else {
$newheight = $thumbheight;
$divisor = $height / $thumbheight;
$newwidth = floor( $width / $divisor );
}
// Create a new temporary image.
$tmpimg = imagecreatetruecolor( $newwidth, $newheight );
// Copy and resize old image into new image.
imagecopyresampled( $tmpimg, $img, 0, 0, 0, 0, $newwidth, $newheight, $width, $height );
// Save thumbnail into a file.
imagejpeg( $tmpimg, $endfile, $quality);
// release the memory
imagedestroy($tmpimg);
imagedestroy($img);
People say that ImageMagick is much faster. At best just compare both libraries and measure that.
Prepare 1000 typical images.
Write two scripts -- one for GD, one
for ImageMagick.
Run both of them a few times.
Compare results (total execution
time, CPU and I/O usage, result
image quality).
Something which the best everyone else, could not be the best for you.
Also, in my opinion, ImageMagick has much better API interface.
Here's a snippet from the php.net docs that I've used in a project and works fine:
<?
function fastimagecopyresampled (&$dst_image, $src_image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h, $quality = 3) {
// Plug-and-Play fastimagecopyresampled function replaces much slower imagecopyresampled.
// Just include this function and change all "imagecopyresampled" references to "fastimagecopyresampled".
// Typically from 30 to 60 times faster when reducing high resolution images down to thumbnail size using the default quality setting.
// Author: Tim Eckel - Date: 09/07/07 - Version: 1.1 - Project: FreeRingers.net - Freely distributable - These comments must remain.
//
// Optional "quality" parameter (defaults is 3). Fractional values are allowed, for example 1.5. Must be greater than zero.
// Between 0 and 1 = Fast, but mosaic results, closer to 0 increases the mosaic effect.
// 1 = Up to 350 times faster. Poor results, looks very similar to imagecopyresized.
// 2 = Up to 95 times faster. Images appear a little sharp, some prefer this over a quality of 3.
// 3 = Up to 60 times faster. Will give high quality smooth results very close to imagecopyresampled, just faster.
// 4 = Up to 25 times faster. Almost identical to imagecopyresampled for most images.
// 5 = No speedup. Just uses imagecopyresampled, no advantage over imagecopyresampled.
if (empty($src_image) || empty($dst_image) || $quality <= 0) { return false; }
if ($quality < 5 && (($dst_w * $quality) < $src_w || ($dst_h * $quality) < $src_h)) {
$temp = imagecreatetruecolor ($dst_w * $quality + 1, $dst_h * $quality + 1);
imagecopyresized ($temp, $src_image, 0, 0, $src_x, $src_y, $dst_w * $quality + 1, $dst_h * $quality + 1, $src_w, $src_h);
imagecopyresampled ($dst_image, $temp, $dst_x, $dst_y, 0, 0, $dst_w, $dst_h, $dst_w * $quality, $dst_h * $quality);
imagedestroy ($temp);
} else imagecopyresampled ($dst_image, $src_image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h);
return true;
}
?>
http://us.php.net/manual/en/function.imagecopyresampled.php#77679
phpThumb uses ImageMagick whenever possible for speed (falling back to GD if necessary) and seems to cache pretty well to reduce the load on the server. It's pretty lightweight to try out (to resize an image, just call phpThumb.php with a GET query that includes the graphic filename and output dimensions), so you might give it a shot to see if it meets your needs.
For larger images use libjpeg to resize on image load in ImageMagick and thereby significantly reducing memory usage and improving performance, it is not possible with GD.
$im = new Imagick();
try {
$im->pingImage($file_name);
} catch (ImagickException $e) {
throw new Exception(_('Invalid or corrupted image file, please try uploading another image.'));
}
$width = $im->getImageWidth();
$height = $im->getImageHeight();
if ($width > $config['width_threshold'] || $height > $config['height_threshold'])
{
try {
/* send thumbnail parameters to Imagick so that libjpeg can resize images
* as they are loaded instead of consuming additional resources to pass back
* to PHP.
*/
$fitbyWidth = ($config['width_threshold'] / $width) > ($config['height_threshold'] / $height);
$aspectRatio = $height / $width;
if ($fitbyWidth) {
$im->setSize($config['width_threshold'], abs($width * $aspectRatio));
} else {
$im->setSize(abs($height / $aspectRatio), $config['height_threshold']);
}
$im->readImage($file_name);
/* Imagick::thumbnailImage(fit = true) has a bug that it does fit both dimensions
*/
// $im->thumbnailImage($config['width_threshold'], $config['height_threshold'], true);
// workaround:
if ($fitbyWidth) {
$im->thumbnailImage($config['width_threshold'], 0, false);
} else {
$im->thumbnailImage(0, $config['height_threshold'], false);
}
$im->setImageFileName($thumbnail_name);
$im->writeImage();
}
catch (ImagickException $e)
{
header('HTTP/1.1 500 Internal Server Error');
throw new Exception(_('An error occured reszing the image.'));
}
}
/* cleanup Imagick
*/
$im->destroy();
From you quesion, it seems you are kinda new to GD, I will share some experence of mine,
maybe this is a bit off topic, but I think it will be helpful to someone new to GD like you:
Step 1, validate file. Use the following function to check if the $_FILES['image']['tmp_name'] file is valid file:
function getContentsFromImage($image) {
if (#is_file($image) == true) {
return file_get_contents($image);
} else {
throw new \Exception('Invalid image');
}
}
$contents = getContentsFromImage($_FILES['image']['tmp_name']);
Step 2, get file format Try the following function with finfo extension to check file format of the file(contents). You would say why don't you just use $_FILES["image"]["type"] to check file format? Because it ONLY check file extension not file contents, if someone rename a file originally called world.png to world.jpg, $_FILES["image"]["type"] will return jpeg not png, so $_FILES["image"]["type"] may return wrong result.
function getFormatFromContents($contents) {
$finfo = new \finfo();
$mimetype = $finfo->buffer($contents, FILEINFO_MIME_TYPE);
switch ($mimetype) {
case 'image/jpeg':
return 'jpeg';
break;
case 'image/png':
return 'png';
break;
case 'image/gif':
return 'gif';
break;
default:
throw new \Exception('Unknown or unsupported image format');
}
}
$format = getFormatFromContents($contents);
Step.3, Get GD resource Get GD resource from contents we have before:
function getGDResourceFromContents($contents) {
$resource = #imagecreatefromstring($contents);
if ($resource == false) {
throw new \Exception('Cannot process image');
}
return $resource;
}
$resource = getGDResourceFromContents($contents);
Step 4, get image dimension Now you can get image dimension with the following simple code:
$width = imagesx($resource);
$height = imagesy($resource);
Now, Let's see what variable we got from the original image then:
$contents, $format, $resource, $width, $height
OK, lets move on
Step 5, calculate resized image arguments This step is related to your question, the purpose of the following function is to get resize arguments for GD function imagecopyresampled(), the code is kinda long, but it works great, it even has three options: stretch, shrink, and fill.
stretch: output image's dimension is the same as the new dimension you set. Won't keep height/width ratio.
shrink: output image's dimension won't exceed the new dimension you give, and keep image height/width ratio.
fill: output image's dimension will be the same as new dimension you give, it will crop & resize image if needed, and keep image height/width ratio. This option is what you need in your question.
function getResizeArgs($width, $height, $newwidth, $newheight, $option) {
if ($option === 'stretch') {
if ($width === $newwidth && $height === $newheight) {
return false;
}
$dst_w = $newwidth;
$dst_h = $newheight;
$src_w = $width;
$src_h = $height;
$src_x = 0;
$src_y = 0;
} else if ($option === 'shrink') {
if ($width <= $newwidth && $height <= $newheight) {
return false;
} else if ($width / $height >= $newwidth / $newheight) {
$dst_w = $newwidth;
$dst_h = (int) round(($newwidth * $height) / $width);
} else {
$dst_w = (int) round(($newheight * $width) / $height);
$dst_h = $newheight;
}
$src_x = 0;
$src_y = 0;
$src_w = $width;
$src_h = $height;
} else if ($option === 'fill') {
if ($width === $newwidth && $height === $newheight) {
return false;
}
if ($width / $height >= $newwidth / $newheight) {
$src_w = (int) round(($newwidth * $height) / $newheight);
$src_h = $height;
$src_x = (int) round(($width - $src_w) / 2);
$src_y = 0;
} else {
$src_w = $width;
$src_h = (int) round(($width * $newheight) / $newwidth);
$src_x = 0;
$src_y = (int) round(($height - $src_h) / 2);
}
$dst_w = $newwidth;
$dst_h = $newheight;
}
if ($src_w < 1 || $src_h < 1) {
throw new \Exception('Image width or height is too small');
}
return array(
'dst_x' => 0,
'dst_y' => 0,
'src_x' => $src_x,
'src_y' => $src_y,
'dst_w' => $dst_w,
'dst_h' => $dst_h,
'src_w' => $src_w,
'src_h' => $src_h
);
}
$args = getResizeArgs($width, $height, 150, 170, 'fill');
Step 6, resize image Use $args, $width, $height, $format and $resource we got from above into the following function and get the new resource of the resized image:
function runResize($width, $height, $format, $resource, $args) {
if ($args === false) {
return; //if $args equal to false, this means no resize occurs;
}
$newimage = imagecreatetruecolor($args['dst_w'], $args['dst_h']);
if ($format === 'png') {
imagealphablending($newimage, false);
imagesavealpha($newimage, true);
$transparentindex = imagecolorallocatealpha($newimage, 255, 255, 255, 127);
imagefill($newimage, 0, 0, $transparentindex);
} else if ($format === 'gif') {
$transparentindex = imagecolorallocatealpha($newimage, 255, 255, 255, 127);
imagefill($newimage, 0, 0, $transparentindex);
imagecolortransparent($newimage, $transparentindex);
}
imagecopyresampled($newimage, $resource, $args['dst_x'], $args['dst_y'], $args['src_x'], $args['src_y'], $args['dst_w'], $args['dst_h'], $args['src_w'], $args['src_h']);
imagedestroy($resource);
return $newimage;
}
$newresource = runResize($width, $height, $format, $resource, $args);
Step 7, get new contents, Use the following function to get contents from the new GD resource:
function getContentsFromGDResource($resource, $format) {
ob_start();
switch ($format) {
case 'gif':
imagegif($resource);
break;
case 'jpeg':
imagejpeg($resource, NULL, 100);
break;
case 'png':
imagepng($resource, NULL, 9);
}
$contents = ob_get_contents();
ob_end_clean();
return $contents;
}
$newcontents = getContentsFromGDResource($newresource, $format);
Step 8 get extension, Use the following function to get extension of from image format(note, image format is not equal to image extension):
function getExtensionFromFormat($format) {
switch ($format) {
case 'gif':
return 'gif';
break;
case 'jpeg':
return 'jpg';
break;
case 'png':
return 'png';
}
}
$extension = getExtensionFromFormat($format);
Step 9 save image If we have a user named mike, you can do the following, it will save to the same folder as this php script:
$user_name = 'mike';
$filename = $user_name . '.' . $extension;
file_put_contents($filename, $newcontents);
Step 10 destroy resource Don't forget destroy GD resource!
imagedestroy($newresource);
or you can write all your code into a class, and simply use the following:
public function __destruct() {
#imagedestroy($this->resource);
}
TIPS
I recommend not to convert file format that user upload, you will meet many problems.
I suggest that you work something along these lines:
Perform a getimagesize( ) on the uploaded file to check image type and size
Save any uploaded JPEG image smaller than 700x700px in to the destination folder "as-is"
Use GD library for medium size images (see this article for code sample: Resize Images Using PHP and GD Library)
Use ImageMagick for large images. You can use ImageMagick in background if you prefer.
To use ImageMagick in background, move the uploaded files to a temporary folder and schedule a CRON job that "convert"s all files to jpeg and resizes them accordingly. See command syntax at: imagemagick-command line processing
You can prompt the user that file is uploaded and scheduled to be processed. The CRON job could be scheduled to run daily at a specific interval. The source image could be deleted after processing to assure that an image is not processed twice.
I've heard big things about the Imagick library, unfortunately I couldn't install it at my work computer and neither at home (and trust me, I spent hours and hours on all kinds of forums).
Afterwords, I've decided to try this PHP class:
http://www.verot.net/php_class_upload.htm
It's pretty cool and I can resize all kinds of images (I can convert them to JPG also).
ImageMagick is multithreaded, so it appears to be faster, but actually uses a lot more resources than GD. If you ran several PHP scripts in parallel all using GD then they'd beat ImageMagick in speed for simple operations. ExactImage is less powerful than ImageMagick but a lot faster, though not available through PHP, you'll have to install it on the server and run it through exec.
For larger images use phpThumb(). Here is how to use it: http://abcoder.com/php/problem-with-resizing-corrupted-images-using-php-image-functions/. It also works for large corrupted images.