Forum Moderators: coopster

Message Too Old, No Replies

Uploading big images turn to black!

resize image URGENT!

         

smagdy

10:19 pm on Sep 25, 2006 (gmt 0)

10+ Year Member



Hello,

First of all i've VDS Server so i can change any settings in PHP or Apache so all comments are welcomed...

I am running a web site where users can upload images and its been online for 4 months and going well, but suddenly i discoverd that when uploading a picture that is about 1 MB 800x530 pixels or other which is 464 KB 1600x1200 pixels, then my script cant read their height and width then i get invalid dimensions and the image dont get resized at all and stays at their original width & height which breaks the page design!

and this is when i was using:

imagesx();
imagesy();

but i got the dimensions using "getimagesize()" and it was resized correctly but both images turned black!

So where could be the fail!

Please help me urgently because i think am losing users, i dono how come i didnt test big images b4 going live :(

Here is the part where the fail & warnings come!

if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile))
{
$info = getimagesize($uploadfile);
$width = $info[0];
$height = $info[1];
$type = $info[2];
$attr = $info[3];

$image = "$uploadfile";
$newimage = "$uploadfile";
$image_quality = 75;
$addborder = 0;
$max_height = 480;
$max_width = 640;

// Main code

switch( $info['mime'] ){
case 'image/jpeg': $src_img = @imagecreatefromjpeg($image); break;
case 'image/gif' : $src_img = @imagecreatefromgif($image);
}

$orig_x = $width;
$orig_y = @imagesy($src_img);

if($width > 640 ¦¦ $height > 480)
{
$new_y = $max_height;
$new_x = $orig_x/($orig_y/$max_height);

if ($new_x > $max_width) {
$new_x = $max_width;
$new_y = $orig_y/($orig_x/$max_width);
}

$dst_img = @imagecreatetruecolor($new_x,$new_y);
@imagecopyresampled($dst_img, $src_img, 0, 0, 0, 0, $new_x, $new_y, $orig_x, $orig_y);

}
else
{
$dst_img = @imagecreatetruecolor($width,$height);
@imagecopyresampled($dst_img, $src_img, 0, 0, 0, 0, $width, $height, $orig_x, $orig_y);
}

@imagejpeg($dst_img, $newimage, $image_quality);
@imagedestroy($src_img);
@imagedestroy($dst_img);

$_SESSION["img"] = "$uploadfile";
$formVars["userfile"] = "$uploadfile";
$img = "$uploadfile";
if($width > 640 ¦¦ $height > 480)
{
$_SESSION["x"]="$new_x";
$_SESSION["y"]="$new_y";
}
else
{
$_SESSION["x"]="$width";
$_SESSION["y"]="$height";
}
}

Thanks in advance

Birdman

1:54 am on Sep 26, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



The problem could be here:

$orig_x = $width;
$orig_y = @imagesy($src_img);

Why not just:

$orig_x = $width;
$orig_y = $height;

smagdy

8:47 am on Sep 26, 2006 (gmt 0)

10+ Year Member



Hello,

i am really sorry...

it is already

$orig_x = $width;
$orig_y = $height;

i just pasted old part... so what now?

thanks again

Birdman

10:28 am on Sep 26, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



It's hard to say when we're not looking at the real code. Let's start with the exact code you are using. Maybe we can spot something in it.

smagdy

10:36 am on Sep 26, 2006 (gmt 0)

10+ Year Member



Thanks there you go.....

if($_FILES['userfile']['name']!= '')
{
if($_FILES['userfile']['size'] > 7)
{
ob_start();
$directory = "upload/"; //directory name, where all the images upload

//show the upload file form
$uploaddir = $directory;
$trim = str_replace(" ", "",basename($_FILES['userfile']['name']));
$name = strtolower($trim);
srand((double)microtime()*1000000);
if(substr($name, -5, 5) == '.jpeg' ¦¦ substr($name, -5, 5) == '.JPEG' ¦¦ substr($name, -5, 5) == '.tiff' ¦¦ substr($name, -5, 5) == '.TIFF')
{
$number2 = rand(0,100000000) . substr($name, -5, 5);
}
else
{
$number2 = rand(0,100000000) . substr($name, -4, 4);
}
$uploadfile = $uploaddir . $number2;

if(substr($name, -5, 5) == '.jpeg' ¦¦ substr($name, -4, 4) == '.gif' ¦¦ substr($name, -4, 4) == '.jpg' ¦¦ substr($name, -5, 5) == '.JPEG' ¦¦ substr($name, -4, 4) == '.GIF' ¦¦ substr($name, -4, 4) == '.JPG')
{

if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile))
{
$info = getimagesize($uploadfile);
$width = $info[0];
$height = $info[1];
$type = $info[2];
$attr = $info[3];

$image = "$uploadfile";
$newimage = "$uploadfile";
$image_quality = 75;
$addborder = 0;
$max_height = 480;
$max_width = 640;

// Main code

switch( $info['mime'] ){
case 'image/jpeg': $src_img = @imagecreatefromjpeg($image); break;
case 'image/gif' : $src_img = @imagecreatefromgif($image);
}
$orig_x = $width;
$orig_y = $height;

if($width > 640 ¦¦ $height > 480)
{

$new_y = $max_height;
$new_x = $orig_x/($orig_y/$max_height);

if ($new_x > $max_width) {
$new_x = $max_width;
$new_y = $orig_y/($orig_x/$max_width);
}
$dst_img = @imagecreatetruecolor($new_x,$new_y);
@imagecopyresampled($dst_img, $src_img, 0, 0, 0, 0, $new_x, $new_y, $orig_x, $orig_y);

}
else
{
$dst_img = @imagecreatetruecolor($width,$height);
@imagecopyresampled($dst_img, $src_img, 0, 0, 0, 0, $width, $height, $orig_x, $orig_y);
}

@imagejpeg($dst_img, $newimage, $image_quality);
@imagedestroy($src_img);
@imagedestroy($dst_img);

$_SESSION["img"] = "$uploadfile";
$formVars["userfile"] = "$uploadfile";
$img = "$uploadfile";
if($width > 640 ¦¦ $height > 480)
{
$_SESSION["x"]="$new_x";
$_SESSION["y"]="$new_y";
}
else
{
$_SESSION["x"]="$width";
$_SESSION["y"]="$height";
}
}
else
{
$errors["userfile"]="Din bild skcsikade inte, försok igen!";
$jer1.= "k";
}
}
else
{
$errors["userfile"]="Bilden måste vara en JPEG, JPG eller GIF";
$jer1.= "k";
}
}

else
{
$errors["userfile"]="Din bild existera inte";
$jer1.= "k";
}
}
else
{
if(isset($_POST["myimg"]))
{
$_SESSION["img"] = $_POST["myimg"];
}
}

}

smagdy

4:51 pm on Sep 26, 2006 (gmt 0)

10+ Year Member



Please anyone!

whoisgregg

1:11 pm on Sep 27, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Nothing jumps out at me as being the cause of your current problem. However, I can offer some advice for how to troubleshoot this.

First, remove all the "@" signs in front of your function calls. That character suppresses error messages -- error messages that might be useful to you when you must troubleshoot your script.

Next, at the top of your script, add error_reporting (you can later comment these lines out for when the code goes live):

ini_set("display_errors", "on");
error_reporting(E_ALL);

If that reveals any PHP error reporting, work through those issues and post back with any questions. :)

Added: Also, please add this line so you can see what values the script is working with.

$info = getimagesize($uploadfile); 
[red][b]print_r($info);[/b][/red]

smagdy

1:20 pm on Sep 27, 2006 (gmt 0)

10+ Year Member



Well thanks, but i still couldnt solve it..

Here are the errors:

Warning: imagecopyresampled(): supplied argument is not a valid Image resource in /sitename/public_html/filename.php on line 383

Warning: imagedestroy(): supplied argument is not a valid Image resource in /sitename/public_html/filename.php on line 393

thanks in advance

smagdy

1:49 pm on Sep 27, 2006 (gmt 0)

10+ Year Member



I tried to upload 3 images now and of course rezising them with same script..

so first 2 get resized but turns to black but the third works normally.

Both who turn to black are large in sizes and dimensions or at least bigger than width="640" height="480"

Turns to BLACK - 1.21 MB
Array ( [0] => 800 [1] => 530 [2] => 6 [3] => width="800" height="530" [bits] => 24 [mime] => image/bmp )

Turns to BLACK - 464 KB
Array ( [0] => 1600 [1] => 1200 [2] => 2 [3] => width="1600" height="1200" [bits] => 8 [channels] => 3 [mime] => image/jpeg )

Works fine - 85 KB
Array ( [0] => 640 [1] => 480 [2] => 2 [3] => width="640" height="480" [bits] => 8 [channels] => 3 [mime] => image/jpeg )

whoisgregg

6:48 pm on Sep 27, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Which imagedestroy is on line 393? The "$src_img" or the "$dst_img?"

Do those errors only show up when the image ends up turning to black?

Added: "supplied argument is not a valid Image resource" is pretty much a guaranteed failure for GD stuff. It means the image buffer handle isn't valid, so the entire operation isn't occuring. I'd guess your $dst_image is being generated properly (since imagecreatetruecolor makes a black image by default) and the $src_image is failing.

whoisgregg

6:59 pm on Sep 27, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Turns to BLACK - 1.21 MB
Array ( [0] => 800 [1] => 530 [2] => 6 [3] => width="800" height="530" [bits] => 24 [mime] => image/bmp )

This one is a good example of what I'm talking about... The mime/type is "image/bmp" and your switch statement for creating the $src_img image doesn't cover that mime type, so it will end up trying to copy a non-existent image onto a black background. BMP's will fail no matter what until you add an extra step to convert them to a GD supported format. Although this function [us2.php.net] isn't the correct one for BMP files, the comments are helpful.

As far as the JPEG failing, we're still working on that... :)

whoisgregg

7:16 pm on Sep 27, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Okay, here's my best guess. Your memory_limit is too low to process such large images.

The simple way to set memory_limit is with a line like this:

 ini_set( 'memory_limit', '32M' );

To test this theory, add that line and try a large jpeg image. Hopefully that will fix it and let us know the problem is a memory_limit problem.

However, for the actual script, setting memory_limit so high will result in a lot of wastage because some files won't need that much. There's a nice function to dynamically allocate memory based on the size and characteristics of the exact image available in the comments section of the PHP manual page for imagecreatefromjpeg [php.net]... look for the function named "setMemoryForImage" posted by a "e dot a dot schultz".

smagdy

8:15 pm on Sep 27, 2006 (gmt 0)

10+ Year Member



Thanks for the effort...

Well, i tried increasing memory up till 64 MB but same error..

Yes errors only show up when the image ends up turning to black and when they are with big dimensions..

but other than that they go in smothly...

whoisgregg

8:48 pm on Sep 27, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



And to confirm, it's the $src_img imagedestroy on line 393?

If so, the actual problem is on this line, since this line is failing to do it's job:

case 'image/jpeg': $src_img = imagecreatefromjpeg($image); break; 

If memory is sufficient to the task, the next thing to check is max_execution_time (and affect it with set_time_limit [php.net]). Here's a page on the PHP manual about Common Pitfalls for PHP File Uploads [us2.php.net] that should be of help.

smagdy

9:24 pm on Sep 27, 2006 (gmt 0)

10+ Year Member



Hmm,

I confirm that the $src_img imagedestroy on line 393

max_execution_time is set to 30seconds and I can confirm that it doesnt take anywhere more than 2 seconds to create the image resized..

smagdy

4:13 pm on Sep 28, 2006 (gmt 0)

10+ Year Member



i increased the memory and the execution time in php.ini and restarted apache and same result!

Anymore suggestions please..

Everything works perfect just when bigger dimensions it turns black.. it just sounds like memory issue but what can i do more?

DrDoc

4:21 pm on Sep 28, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



It could also be a problematic image. Try opening it in PhotoShop and just re-save it from there. That might fix it.

Have you tried other images the same size?

smagdy

4:37 pm on Sep 28, 2006 (gmt 0)

10+ Year Member



you were right!

I was trying with 3 images 2 of them didnt open with photoshop, it said invalid images..

The third opend so i saved it at highest resolution so it was 1 mega with dimensions 1600x1200 and it worked out well! ;)

Thanks

but just to end this i want usefull information!

if a user is trying to upload very big picture, i dono what is the biggest dimensions available or biggest sizes could be, but lets say 10Mega jpeg image.. how much memory would that need?

Thanks a lot

whoisgregg

8:18 pm on Sep 28, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



how much memory would that need?

I would use the function I reference a few posts back to dynamically allocate a sufficient amount based on the image characteristics. Look for the function named "setMemoryForImage" posted by a "e dot a dot schultz" on this page: [php.net...]

smagdy

8:22 pm on Sep 28, 2006 (gmt 0)

10+ Year Member



But the problem is that i didnt compile my PHP with --enable-memory-limit, so it wont work sadly!

whoisgregg

8:42 pm on Sep 28, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Ahh, well the algorithm is still helpful:

 $K64 = 65536; // number of bytes in 64K
$TWEAKFACTOR = 1.5; // Or whatever works for you
$memoryNeeded = round( ( $imageInfo[0] * $imageInfo[1]
* $imageInfo['bits']
* $imageInfo['channels'] / 8
+ $K64
) * $TWEAKFACTOR
);

Let's assume your 464 KB 1600x1200 JPEG from above is the input, the memory needed would be around 8.8 MB. So, in most cases a memory limit of 16MB to 24MB would be plenty.