当我尝试在同一个文件上使用imagefronpng()时,PHP GD会创建一个PNG文件并失败

I am using PHP GD library to proccess some images in order to create a meme generator. I've never worked with image processing before, in any language.

First I take an image uploaded trhough POST and resize it with GD, according to max width and height parameters I set. The resized image is saved to the server, and displayed in the next page to the user, with a form used to set the captions. This form contains all the caption info: caption text, font size and x-y position of every caption.

Back in the server, using the data from the caption forms I create a GD resource from the file that was resized in the previous step and add the captions.

It works like a charm with .gif and .jpg/.jpeg files, but when I use a PNG file it fails. When I resize the uploaded file it is saved correctly, but on the second step, when I try to create the GD resource using the resized file it throws this error: Message: imagecreatefrompng() [function.imagecreatefrompng]: './images/tmp/Phineas_talks_to_Perry1.png' is not a valid PNG file

I'm guessing it's related to the process of creating the file the first time (resize). It's not that the file is not there, I double check every time. And I download it back to my computer, open it with Picassa and it's fine.

I'm working on top of CodeIgniter, on an Apache Server (Go Daddy shared hosting).

Here's the code for the two functions I use, that are wrapped in a class: (Comments are in spanish, feel free to ignore them)

class Imageprocessing
{
    public function __construct()
    {
        $this->ci =& get_instance();
        $this->ci->load->helper('file');
    }


public function resize( $path, $overwrite = false, $destination = null, $name = null )
{
    $output = 0;        

    //Si están seteados los parámetros de ancho y altura máximos
    if( isset( $this->max_W ) && isset( $this->max_H ) )
    {
        //Si la ubicación que recibimos es un archivo válido
        if( is_file( $path ) )
        {
            //Si el archivo es de tipo imagen
            if( $this->is_image( $path ) )
            {                    
                $pathinfo = pathinfo( $path );
                $ext = $pathinfo['extension'];
                $file = $pathinfo['filename'];            
                $dir = $pathinfo['dirname'] . '/';

                //Creando el recurso de imagen GD, usando la función apropiada según el mime type
                if( $ext == 'jpeg' || $ext == 'jpg' )
                {
                    $src = imagecreatefromjpeg( $path );
                }
                elseif( $ext == 'png' )
                {
                    $src = imagecreatefrompng( $path );
                }
                elseif( $ext == 'gif' )
                {
                    $src = imagecreatefromgif( $path );
                }

                //determinando el ancho y alto actual de la imagen
                $W = imageSX( $src );
                $H = imageSY( $src );

                //Si alguno de los dos parámetros excede el máximo permitido, calculamos las nuevas dimensiones de la imagen
                if( $W > $this->max_W || $H > $this->max_H )
                {        
                    //Si la foto es más alta que ancha
                    if( $W < $H )
                    {

                        /*Redimensionamos la altura al máximo permitido
                        /*Calculamos la proporción en que varió la altura y disminuimos el ancho en esa misma proporción
                        */
                        $new_H = $this->max_H;                            
                        $new_W = $W * ( $this->max_H / $H );
                    }
                    elseif( $W > $H )
                    {
                        /*Redimensionamos el ancho al máximo permitido
                        /*Calculamos la proporción en que varió el ancho y disminuimos la altura en esa misma proporción
                        */
                        $new_W = $this->max_W;                            
                        $new_H = $H * ( $this->max_W / $W );
                    }
                    else
                    {
                        $new_W = $this->max_W;
                        $new_H = $this->max_W;
                    }

                    //determinando la carpeta de destino y el nombre del nuevo archivo
                    if( $overwrite )
                    {
                        $destination = $path;
                    }
                    else
                    {
                        if( ! isset( $destination ) || empty( $destination ) )
                        {
                            $destination = $dir;
                        }
                        //si $destination no es un directorio válido
                        elseif( ! is_dir( $destination ) )
                        {
                            $destination = $dir;                        
                        }

                        if( ! isset( $name ) || empty( $name ) )
                        {
                            $destination .= "{$file}_" . (int) $new_W . 'x' . (int) $new_H . ".{$ext}";
                        }
                        else
                        {
                            //filtrar para que sea un nombre de archivo válido
                            $destination .= filter_var( str_replace( ' ', '_', $name ), FILTER_SANITIZE_URL ) . ".{$ext}";
                        }
                    }                    

                    //creamos la nueva imagen, redimensionada                        
                    $dst = imagecreatetruecolor( $new_W, $new_H );
                    imagecopyresampled( $dst, $src, 0, 0, 0, 0, $new_W, $new_H, $W, $H );

                    //según el mime
                    if( $ext == 'jpg' || $ext = 'jpeg' )
                    {
                        $success = imagejpeg( $dst, $destination, 100 );
                    }
                    elseif( $ext == 'png' )
                    {
                        $success = imagepng( $dst, $destination );
                    }
                    elseif( $ext == 'gif' )
                    {
                        $success = imagegif( $dst, $destination );
                    }

                    if( $success )
                    {
                        $output = array( 'src' => $destination, 'width' => $new_W, 'height' => $new_H );
                    }

                    unset( $src, $dst );

                }
                else
                {
                    $output = -1;
                }                    
            }
            else
            {
                $error = 'Debes usar un archivo de imagen';
            }                
        }
        else
        {
            $error = 'Debes especificar una ubicación de archivo válida';
        }
    }
    else
    {
        $error = 'Para usar la función ' . __METHOD__ . ' de la clase ' . __CLASS__ . ' se deben especificar los parámetros de ancho máximo permitido ( max_W ) y altura máxima permitida ( max_H )';
    }

    if( isset( $error ) && ! empty( $error ) )
    {
        trigger_error( $error, E_USER_WARNING );
    }

    return $output;
}    

public function caption( $path, $captions, $overwrite = false, $destination = null, $name = null )
{

    $output = false;

    if( is_file( $path ) )
    {
        if( $this->is_image( $path ) )
        {
            if( is_array( $captions ) )
            {                
                $pathinfo = pathinfo( $path );
                $ext = $pathinfo['extension'];                    
                $file = $pathinfo['filename'];                    
                $dir = $pathinfo['dirname'] . '/';

                //Creando el recurso de imagen GD, usando la función apropiada según el mime type
                if( $ext == 'jpeg' || $ext == 'jpg' )
                {
                    $src = imagecreatefromjpeg( $path );
                }
                elseif( $ext == 'png' )
                {
                    $src = imagecreatefrompng( $path );
                }
                elseif( $ext == 'gif' )
                {
                    $src = imagecreatefromgif( $path );                
                }

                $color = imagecolorallocate( $src, 255, 255, 255 );

                foreach( $captions as $caption )
                {
                    imagefttext( $src, $caption['font-size'], 0, $caption['x'], $caption['y'] + $caption['font-size'], $color, './fonts/impact.ttf', $caption['text'] );
                }

                if( $overwrite )
                {
                    $destination = $path;                    
                }
                else
                {
                    if( ! isset( $destination ) || empty( $destination )  )
                    {
                        $destination = $dir;
                    }
                    elseif( ! is_dir( $destination ) )
                    {
                        $destination = $dir;
                    }

                    if( ! isset( $name ) || empty( $name )  )
                    {
                        $destination .= "{$file}_caption.{$ext}";
                    }
                    else
                    {
                        //filtrar para que sea un nombre de archivo válido
                        $destination .= filter_var( str_replace( ' ', '_', $name ), FILTER_SANITIZE_URL ) . ".{$ext}";
                    }
                }

                //según el mime
                if( $ext == 'jpg' || $ext = 'jpeg' )
                {
                    $success = imagejpeg( $src, $destination, 100 );
                }
                elseif( $ext == 'png' )
                {
                    $success = imagepng( $src, $destination );
                }
                elseif( $ext == 'gif' )
                {
                    $success = imagegif( $src, $destination );
                }

                if( $success )
                {
                    $output = array( 'src' => $destination, 'width' => (int) imageSX( $src ), 'height' => (int) imageSY( $src ) );
                }

                unset( $src );

            }
            else
            {
                $error = 'Los captions deben ingresarse como un array';
            }
        }
        else
        {
            $error = 'Se debe usar un archivo de imagen';
        }
    }
    else
    {
        $error = 'Se debe usar un archivo válido';
    }

    if( isset( $error ) && ! empty( $error ) )
    {
        trigger_error( $error, E_USER_WARNING );
    }

    return $output;        

}    

}

Do you have any thoughts on what's wrong with this?

EDIT: You can try what I have done so far in this address, again, ignore the spanish, just upload the file and try it. Thank You!

In order to have the script resize the picture it must be larger than 640x480

http://unmillondemascotas.org/meme/

The problem is definitely in the image creation proccess. I manually uploaded an image to the server and hard coded the captioning proccess and it was successful, it created a new PNG file. Then I tried to caption again that same file that and it failed. So, I must be doing something wrong when writing the new PNG file, but I have no clue on what it is.

I had the same problem with an image coming from a PhpThumb (GD) save because the "input" image could come in any format. I fixed it simply ensuring that the saved image was indeed a PNG file:

$image->save($path, "PNG");

Greetings.