1

I have a function created which processes images in different ways based on the parameters. I have comments in the function to explain a bit.

Everything works with exception to when I take a jpg image and save it as a png. I just checked, even if I use imagepng() but save it with the extension .jpg, the image displays while properly resized, but with a .jpg extension. However, if I upload the same .jpg image, use imagepng() and save it with a .png extension, I get an image of the expected width and height after the resize, in a png format, with a .png extension. While the whole image is 100% transparent I have a 1px by 1px black pixel in the top left corner.

I would appreciate it if anyone can look at this and see if they see something I am missing. I believe the 1px X 1px is coming from the point I use for the imagefill(), but I don't understand why; it should be filling all transparent as with the rest of the image.

Here is my function:

if(!function_exists("upload")){
    //$image = $image file name
    //$width = intended width of resized image, if 0 it will proportion to height, overrides proportion
    //$height = intended width of resized image, if 0 it will proportion to width, overrides proportion
    //$proportion = 2,1,0;
    //------ 2 = Preserve proportions while adding a border to fill width and height  
    //------ 1 = retain proportion to fit within both given width and height
    //------ 0 = disregard proportions and resize to the exact width and height
    function upload($image, $width, $height, $proportion){
        // IS GD HERE?

        $gdv = get_gd_info();

        if (!$gdv){ 
            return FALSE;
        }

        // GET AN IMAGE THING

        $ext = trim(strtolower(end(explode('.', $image))));

        list($imageX, $imageY, $type) = getimagesize($image);   //gets information about new server image

        // GET THE LESSER OF THE RATIO OF THUMBNAIL H OR W DIMENSIONS
        $ratio_w = ($width / $imageX);
        $ratio_h = ($height / $imageY);
        $ratio   = ($ratio_w < $ratio_h) ? $ratio_w : $ratio_h;     

        if($width == 0){

            if($imageY > $height){
                $newHeight = $height;
                $newWidth = ($height/$imageY) * $imageX;    
            }else{
                $newHeight = $imageY;
                $newWidth = $imageX;    
            }

            $width = $newWidth;
            $height = $newHeight;

            // COMPUTE THUMBNAIL IMAGE CENTERING OFFSETS
            $fromMidX = 0;
            $fromMidY = 0;

        }elseif($height == 0){

            if ($imageX > $width){
                $newWidth = $width;
                $newHeight = ($width/$imageX) * $imageY;
            }else{
                $newHeight = $imageY;
                $newWidth = $imageX;    
            }

            $width = $newWidth;
            $height = $newHeight;

            // COMPUTE THUMBNAIL IMAGE CENTERING OFFSETS
            $fromMidX = 0;
            $fromMidY = 0;

        }elseif($proportion == 2){

            // COMPUTE THUMBNAIL IMAGE DIMENSIONS
            $newWidth = $imageX * $ratio;
            $newHeight = $imageY * $ratio;

            // COMPUTE THUMBNAIL IMAGE CENTERING OFFSETS
            $fromMidX = ($width - $newWidth) / 2.0;
            $fromMidY = ($height - $newHeight) / 2.0;

        }elseif($proportion == 1){

            if ($imageX > $width){
                $newHeight = ($width/$imageX) * $imageY;
                $newWidth = $width;
            }
            if ($imageY > $height){
                $newHeight = $height;
                $newWidth = ($height/$imageY) * $imageX;
            }

            $fromMidY = 0;
            $fromMidX = 0;

        }elseif($proportion == 0){

            $newWidth = $width;
            $newHeight = $height;

            $fromMidY = 0;
            $fromMidX = 0;          
        }

        switch(strtoupper($ext))
        {
            case 'JPG' :
            case 'JPEG' :
                $source = imagecreatefromjpeg($image);
                break;

            case 'PNG' :
                $source = imagecreatefrompng($image);

                break;

            default : die("UNKNOWN IMAGE TYPE: $image");
        }

        // WHICH FUNCTIONS CAN RESIZE / RESAMPLE THE IMAGE?
        if ($gdv >= 2)
        {

            // IF GD IS AT LEVEL 2 OR ABOVE
            $target = imagecreatetruecolor($width, $height);
            $color = imagecolorallocatealpha($target, 0, 0, 0, 127); 

            imagefill($target, 0, 0, $color);

            imagesavealpha($target, TRUE);


            imagecopyresampled ($target, $source, $fromMidX, $fromMidY, 0, 0, $newWidth, $newHeight, $imageX, $imageY);

        }
        else
        {
            // IF GD IS AT A LOWER REVISION LEVEL
            $target = imagecreate($width, $height);
            imagesavealpha($target, TRUE);
                $empty = imagecolorallocatealpha($thumb,0x00,0x00,0x00,127);
                imagefill($target, 0, 0, $empty);
            imagecopyresized($target, $source, $fromMidX, $fromMidY, 0, 0, $newWidth, $newHeight, $imageX, $imageY);
        }

        // SHARPEN THE PIC
        $sharpenMatrix = array
        ( array( -1.2, -1, -1.2 )
        , array( -1,   20, -1 )
        , array( -1.2, -1, -1.2 )
        )
        ;
        $divisor = array_sum(array_map('array_sum', $sharpenMatrix));
        $offset  = 0;
        imageconvolution($target, $sharpenMatrix, $divisor, $offset);

        if(imagepng($target, $image,9)){

            imagedestroy($target);
        }else{

        }

        return $image;  
    }
}

EDIT 1: I guess I should have noted that I am uploading a .jpg image (Ex: 100px X 200px) and converting them to .png (Ex: 400px X 200px) but am retaining the proportions of the image to fit perfectly in the center of the destination .png. So I would have a 400px X 200px .png with my image in the center and 100px on the left and right which should be transparent. This way it fits nicely in a slider without a solid color as a fill. So an example of my call to my function would be upload($image, 400, 200, 2).

halfer
  • 19,824
  • 17
  • 99
  • 186
d.lanza38
  • 2,525
  • 7
  • 30
  • 52
  • One clarification comes to mind: if you upload a JPEG and convert it to a PNG, then you should have no transparent pixels. However you say the whole of your image is transparent bar the pixel in the top-left corner. What am I missing? – halfer Jan 10 '13 at 22:59
  • take a look [here](http://stackoverflow.com/questions/7610128/use-php-to-convert-jpegs-to-transparent-png) – mamdouh alramadan Jan 11 '13 at 00:01
  • @halfer I edited my question to try to help clarify why I should have transparent pixels. I guess I should have added that from the start. – d.lanza38 Jan 11 '13 at 14:07
  • Alright, thanks. Not sure myself but +1 to get some readers. – halfer Jan 11 '13 at 14:11
  • @halfer Thank you. I just figured it out, but the plus one will hopefully attract people in need of an answer. – d.lanza38 Jan 11 '13 at 15:01
  • Great, glad you figured it out. No need to add answer addendums (or references to them) in questions here on SO - people will always look elsewhere on the same page for any solutions. – halfer Jan 11 '13 at 16:19

1 Answers1

0

I figured out what the issue was. The portion of code which decides whether I should use imagecreatefromjpeg or imagecreatefrompng was incorrectly going off of the extension of the passed image and NOT by its mime type. I switched it to this:

switch($type)
        {
            case '2' :
                $source = imagecreatefromjpeg($image);
                break;
            case '3' :
                $source = imagecreatefrompng($image);
                break;
            default : die("UNKNOWN IMAGE TYPE: $image");
        }

where $type is coming from the line I had in there

list($imageX, $imageY, $type) = getimagesize($image);

So all together the function is:

if(!function_exists("upload")){
    //$image = $image file name
    //$width = intended width of resized image, if 0 it will proportion to height, overrides proportion
    //$height = intended width of resized image, if 0 it will proportion to width, overrides proportion
    //$proportion = 2,1,0;
    //------ 2 = Preserve proportions while adding a border to fill width and height  
    //------ 1 = retain proportion to fit within both given width and height
    //------ 0 = disregard proportions and resize to the exact width and height


    function upload($image, $width, $height, $proportion){
        // IS GD HERE?

        $gdv = get_gd_info();

        if (!$gdv){ 
            return FALSE;
        }

        // GET AN IMAGE THING

        $ext = trim(strtolower(end(explode('.', $image))));

        list($imageX, $imageY, $type) = getimagesize($image);   //gets information about new server image

        // GET THE LESSER OF THE RATIO OF THUMBNAIL H OR W DIMENSIONS
        $ratio_w = ($width / $imageX);
        $ratio_h = ($height / $imageY);
        $ratio   = ($ratio_w < $ratio_h) ? $ratio_w : $ratio_h;     

        if($width == 0){

            if($imageY > $height){
                $newHeight = $height;
                $newWidth = ($height/$imageY) * $imageX;    
            }else{
                $newHeight = $imageY;
                $newWidth = $imageX;    
            }

            $width = $newWidth;
            $height = $newHeight;

            // COMPUTE THUMBNAIL IMAGE CENTERING OFFSETS
            $fromMidX = 0;
            $fromMidY = 0;

        }elseif($height == 0){

            if ($imageX > $width){
                $newWidth = $width;
                $newHeight = ($width/$imageX) * $imageY;
            }else{
                $newHeight = $imageY;
                $newWidth = $imageX;    
            }

            $width = $newWidth;
            $height = $newHeight;

            // COMPUTE THUMBNAIL IMAGE CENTERING OFFSETS
            $fromMidX = 0;
            $fromMidY = 0;

        }elseif($proportion == 2){

            // COMPUTE THUMBNAIL IMAGE DIMENSIONS
            $newWidth = $imageX * $ratio;
            $newHeight = $imageY * $ratio;

            // COMPUTE THUMBNAIL IMAGE CENTERING OFFSETS
            $fromMidX = ($width - $newWidth) / 2.0;
            $fromMidY = ($height - $newHeight) / 2.0;

        }elseif($proportion == 1){

            if ($imageX > $width){
                $newHeight = ($width/$imageX) * $imageY;
                $newWidth = $width;
            }
            if ($imageY > $height){
                $newHeight = $height;
                $newWidth = ($height/$imageY) * $imageX;
            }

            $fromMidY = 0;
            $fromMidX = 0;

        }elseif($proportion == 0){

            $newWidth = $width;
            $newHeight = $height;

            $fromMidY = 0;
            $fromMidX = 0;          
        }

        switch($type)
        {
            case '2' :
                $source = imagecreatefromjpeg($image);
                break;
            case '3' :
                $source = imagecreatefrompng($image);
                break;
            default : die("UNKNOWN IMAGE TYPE: $image");
        }

        // WHICH FUNCTIONS CAN RESIZE / RESAMPLE THE IMAGE?
        if ($gdv >= 2)
        {

            // IF GD IS AT LEVEL 2 OR ABOVE
            $target = imagecreatetruecolor($width, $height);
            $color = imagecolorallocatealpha($target, 0, 0, 0, 127); 
            imagefill($target, 0, 0, $color);
            imagesavealpha($target, TRUE);
            imagecopyresampled ($target, $source, $fromMidX, $fromMidY, 0, 0, $newWidth, $newHeight, $imageX, $imageY);

        }
        else
        {
            // IF GD IS AT A LOWER REVISION LEVEL
            $target = imagecreate($width, $height);
            imagesavealpha($target, TRUE);
                $empty = imagecolorallocatealpha($thumb,0x00,0x00,0x00,127);
                imagefill($target, 0, 0, $empty);
            imagecopyresized($target, $source, $fromMidX, $fromMidY, 0, 0, $newWidth, $newHeight, $imageX, $imageY);
        }

        // SHARPEN THE PIC
        $sharpenMatrix = array
        ( array( -1.2, -1, -1.2 )
        , array( -1,   20, -1 )
        , array( -1.2, -1, -1.2 )
        )
        ;
        $divisor = array_sum(array_map('array_sum', $sharpenMatrix));
        $offset  = 0;
        imageconvolution($target, $sharpenMatrix, $divisor, $offset);

        if(imagepng($target, $image,9)){
            imagedestroy($target);
        }
        return $image;
    }
}

And an example call would be: upload("path/to/image/on/server.png", 400, 200, 2) Where the image path can be either in a jpg or png mime type. But the extension MUST be .png. I suppose I can make it smarter where you can have any extension, but with the current code which uses this function it makes more sense for me to leave it as is. I would like to eventually add the option to turn on or off the transparency and instead use a solid color such as black if it is needed. Feel free to use and modify this.

There are nice hex2rgb/rgb2hex functions which I plan on using for this here

d.lanza38
  • 2,525
  • 7
  • 30
  • 52