重建缩略图时保留GIF tansparencies

时间:2010-09-28 17:59:40

标签: php transparency transparent gif thumbnails

在上传图像时,代码会创建几个不同的缩略图。在某些情况下,缩略图可能比原始图像大,在这种情况下应用填充。在JPEG的情况下,填充是白色的,一切都很好。对于GIF和PNG,填充应该是透明的。它是。或不。这很奇怪。

如果我得到一个完全黑色或透明的填充,我会知道问题所在,但我得到的填充物在某些地方是透明的而在其他地方是黑色的,这没有任何意义。

http://filedump.xn--es-zka.info/broken_thumbs/处拍摄PNG和GIF图像(在令人震惊的粉红色背景色上,以便您可以看到白色和透明之间的差异)。

alt text

有什么好主意吗?

class Image {

    public static function exec($path) {
        // This function receives the path to an image.
        // Logic here skipped: For each thumbnail, check whether Crop is set. If it is, call self::crop(). Otherwise, call self::resize().
        return true;
    }

    public static function resize($file, $class, $width='-', $height='-', $fit=0) {
        $a = getimagesize($file);
        switch ($a[2]) {
        case 1:
            $tag = 'gif';
            break;
        case 2:
             $tag = 'jpeg';
             break;
        case 3:
             $tag = 'png';
             break;
        default:
            return;
        }
        $w = $a[0];
        $h = $a[1];

        if ($width == 0) {
            $fw = 0;
            $fh = $h / $height;
        } elseif ($height == 0) {
            $fw = $w / $width;
            $fh = 0;
        } else {
            $fw = $w / $width;
            $fh = $h / $height;
        }
        if (($fw == 1) and ($fh == 1)) {
            $file2 = dirname($file) . '/' . $class . basename($file);
            copy($file, $file2);
            return true;
        } elseif (($fw >= 1) and ($fh >= 1)) {
            if ($fw > $fh) {
                $w = $width;
                $h = floor($h / $fw);
            } else {
                $h = $height;
                $w = floor($w / $fh);
            }
        } elseif ($fh == 0) {
            if ($fw > 1) {
                $fit = 0;
                $w = $width;
                $h = floor($h / $fw);
            } else {
                if ($fit) {
                    $height = $h;
                }
            }
        } elseif ($fw == 0) {
            if ($fh > 1) {
                $fit = 0;
                $w = floor($w / $fh);
                $h = $height;
            } else {
                if ($fit) {
                    $width = $w;
                }
            }
        } elseif (($fw < 1) and ($fh < 1)) {
            //
        } elseif ($fw > $fh) {
            if ($fw >= 1) {
                $w = $width;
                $h = floor($h / $fw);
            }
        } elseif ($fh > $fw) {
            if ($fh >= 1) {
                $w = floor($w / $fh);
                $h = $height;
            }
        }

        if ($fit) {
            $x = ($width  - $w) / 2;
            $y = ($height - $h) / 2;
            $cw = $width;
            $ch = $height;
        } else {
            $x = 0;
            $y = 0;
            $cw = $w;
            $ch = $h;
        }

        $file2 = dirname($file) . '/' . $class . basename($file);
        $f1    = 'imagecreatefrom' . $tag;
        $src   = $f1($file);
        $new   = imagecreatetruecolor($cw, $ch);
        return self::create($new, $src, $file2, $x, $y, $w, $h, $a);
    }

    public static function crop($file, $class, $width='-', $height='-', $fit=0) {
        if (!$class) return trigger_error('ExecImage: Original image can not be overwritten.');
        $small = 0;
        $a = getimagesize($file);

        switch ($a[2]) {
        case 1:
            $tag = 'gif';
            break;
        case 2:
             $tag = 'jpeg';
             break;
        case 3:
             $tag = 'png';
             break;
        default:
            return;
        }

        $w = $a[0];
        $h = $a[1];
        if ($height == 0) {
            //resize by width -- height will follow
            $fh = 0;
            $fw = $w / $width;
        } elseif ($width == 0) {
            //resize by height -- width will follow
            $fw = 0;
            $fh = $h / $height;
        } else {
            $fw = $w / $width;
            $fh = $h / $height;
        }

        if (($fw <= 1) and ($fh <= 1)) {
            $small = 1;
            //don't resize
        } else {
            $fit = 1;
            //chop by the smallest
            if ($fh < $fw) {
                //Crop By Height
                $h = $height;
                $w = floor($w / $fh);
                //$w = $width;
                //$h = floor($h /$fw);
                //$w = $width;
            } else {
                //Crop By Width
                $w = $width;
                $h = floor($h /$fw);
                //$h = $height;
                //$w = floor($w / $fh);
            }
        }

        $file2 = dirname($file) . '/' . $class . basename($file);
        $f1 = 'imagecreatefrom' . $tag;
        $src = $f1($file);

        if ($small) {
            if ($fit) {
                //image must be padded
                $x = ($width  - $w) / 2;
                $y = ($height - $h) / 2;
            } else {
                //image goes as is -- shrinked
                $x = 0;
                $y = 0;
            }
        } else {
            //image must be centered -- this should be a square from js
            $x = ($width  - $w) / 2;
            $y = ($height - $h) / 2;
        }

        if ($small) {
            if ($fit) {
                //create with the full size
                $new = imagecreatetruecolor($width, $height);
            } else {
                //nah, just with the original size
                $new = imagecreatetruecolor($w, $h);
            }
        } else {
            if ($fit) {
                $new = imagecreatetruecolor($width, $height);
            } else {
                $new = imagecreatetruecolor($w, $h);
            }
        }
        return self::create($new, $src, $file2, $x, $y, $w, $h, $a);
    }

    private static function create($new, $src, $file2, $x, $y, $w, $h, $a) {
        switch ($a[2]) {
        case 1: // GIF
        case 3: // PNG
            // http://www.akemapa.com/2008/07/10/php-gd-resize-transparent-image-png-gif/
            // http://www.mummey.org/2008/11/transparent-gifs-with-php-and-gd/
            imagealphablending($new, false);
            imagesavealpha($new, true);
            $back = imagecolorallocatealpha($new, 255, 255, 255, 127);
            imagefilledrectangle($new, 0, 0, $w, $h, $back);
            imagecolortransparent($new, $back);
            break;
        case 2: // JPEG
            $back = imagecolorallocate($new, 255, 255, 255);
            break;
        }
        imagefill($new, 0, 0, $back);
        imagecopyresampled($new, $src, $x, $y, 0, 0, $w, $h, $a[0], $a[1]);
        if (file_exists($file2)) unlink($file2);
        switch ($a[2]) {
        case 1:
            imagegif($new, $file2);
            break;
         case 2:
            imagejpeg($new, $file2, 100);
            break;
        case 3:
            imagepng($new, $file2, 0);
            break;
        }
        imagedestroy($src);
        imagedestroy($new);
        return true;
    }
}

修订/编辑以添加:

好吧,我已经解决了主要问题:添加到PNG或GIF图像的填充现在是透明的,而不是黑色。 GIF透明度变黑的问题仍然存在,但我并没有使用GIF透明度。

<?php


class Image {

public static function exec($path) {
    $file = Nearest::file('.config.php', dirname($path) . '/', BD . '/images/');
    if (!file_exists($file)) exit('The ".config.php" file doesnt exist');
    require $file;
    foreach ($config['operations'] as $k => $v) {
        if (!isset($v['class'])) $v['class'] = '.' . $k . '.';
        if (Core::val($v, 'crop')) {
            self::crop($path, $v['class'], Core::val($v, 'width', '-'), Core::val($v, 'height', '-'), Core::val($v, 'fit', 0));
        } else {
            self::resize($path, $v['class'], Core::val($v, 'width', '-'), Core::val($v, 'height', '-'), Core::val($v, 'fit', 0));
        }
    }
    return true;
}
public static function delete($path) {
    $a = glob(dirname($path) . '/.*.' . basename($path));
    foreach ($a as $v) unlink($v);
    unlink($path);
}
public static function resize($file, $class, $width='-', $height='-', $fit=0) {
    $a = getimagesize($file);
    switch ($a[2]) {
    case 1:
        $tag = 'gif';
        break;
    case 2:
         $tag = 'jpeg';
         break;
    case 3:
         $tag = 'png';
         break;
    default:
        return;
    }
    $w = $a[0];
    $h = $a[1];

    if ($width == 0) {
        $fw = 0;
        $fh = $h / $height;
    } elseif ($height == 0) {
        $fw = $w / $width;
        $fh = 0;
    } else {
        $fw = $w / $width;
        $fh = $h / $height;
    }
    if (($fw == 1) and ($fh == 1)) {
        $file2 = dirname($file) . '/' . $class . basename($file);
        copy($file, $file2);
        return true;
    } elseif (($fw >= 1) and ($fh >= 1)) {
        if ($fw > $fh) {
            $w = $width;
            $h = floor($h / $fw);
        } else {
            $h = $height;
            $w = floor($w / $fh);
        }
    } elseif ($fh == 0) {
        if ($fw > 1) {
            $fit = 0;
            $w = $width;
            $h = floor($h / $fw);
        } else {
            if ($fit) {
                $height = $h;
            }
        }
    } elseif ($fw == 0) {
        if ($fh > 1) {
            $fit = 0;
            $w = floor($w / $fh);
            $h = $height;
        } else {
            if ($fit) {
                $width = $w;
            }
        }
    } elseif (($fw < 1) and ($fh < 1)) {
        //
    } elseif ($fw > $fh) {
        if ($fw >= 1) {
            $w = $width;
            $h = floor($h / $fw);
        }
    } elseif ($fh > $fw) {
        if ($fh >= 1) {
            $w = floor($w / $fh);
            $h = $height;
        }
    }

    if ($fit) {
        $x = ($width  - $w) / 2;
        $y = ($height - $h) / 2;
        $cw = $width;
        $ch = $height;
    } else {
        $x = 0;
        $y = 0;
        $cw = $w;
        $ch = $h;
    }

    $file2 = dirname($file) . '/' . $class . basename($file);
    $f1    = 'imagecreatefrom' . $tag;
    $src   = $f1($file);
    $new   = imagecreatetruecolor($cw, $ch);
    return self::create($new, $src, $file2, $x, $y, $w, $h, $cw, $ch, $a);
}
public static function crop($file, $class, $width='-', $height='-', $fit=0) {
    if (!$class) exit('ExecImage: Original image can not be overwrite.');
    $small = 0;
    $a = getimagesize($file);

    switch ($a[2]) {
    case 1:
        $tag = 'Gif';
        break;
    case 2:
         $tag = 'Jpeg';
         break;
    case 3:
         $tag = 'Png';
         break;
    default:
        return;
    }

    $w = $a[0];
    $h = $a[1];
    if ($height == 0) {
        //resize by width -- height will follow
        $fh = 0;
        $fw = $w / $width;
    } elseif ($width == 0) {
        //resize by height -- width will follow
        $fw = 0;
        $fh = $h / $height;
    } else {
        $fw = $w / $width;
        $fh = $h / $height;
    }

    if (($fw <= 1) and ($fh <= 1)) {
        $small = 1;
        //dont resize
    } else {
        $fit = 1;
        //chop by the smallest
        if ($fh < $fw) {
            //Crop By Height
            $h = $height;
            $w = floor($w / $fh);
            //$w = $width;
            //$h = floor($h /$fw);
            //$w = $width;
        } else {
            //Crop By Width
            $w = $width;
            $h = floor($h /$fw);
            //$h = $height;
            //$w = floor($w / $fh);
        }
    }

    $file2 = dirname($file) . '/' . $class . basename($file);
    $f1 = 'ImageCreateFrom' . $tag;
    $src = $f1($file);

    if ($small) {
        if ($fit) {
            //image must be padded
            $x = ($width  - $w) / 2;
            $y = ($height - $h) / 2;
        } else {
            //image goes as is -- shrinked
            $x = 0;
            $y = 0;
        }
    } else {
        //image must be centered -- this should be a square from js
        $x = ($width  - $w) / 2;
        $y = ($height - $h) / 2;
    }

    if ($small) {
        if ($fit) {
            //create with the full size
            $new = imagecreatetruecolor($width, $height);
            return self::create($new, $src, $file2, $x, $y, $w, $h, $width, $height, $a);
        } else {
            //nah, just with the original size
            $new = imagecreatetruecolor($w, $h);
            return self::create($new, $src, $file2, $x, $y, $w, $h, $w, $h, $a);
        }
    } else {
        if ($fit) {
            //create with the full size
            $new = imagecreatetruecolor($width, $height);
            return self::create($new, $src, $file2, $x, $y, $w, $h, $width, $height, $a);
        } else {
            //nah, just with the original size
            $new = imagecreatetruecolor($w, $h);
            return self::create($new, $src, $file2, $x, $y, $w, $h, $w, $h, $a);
        }
    }
}

private static function create($new, $src, $file2, $x, $y, $w, $h, $cw, $ch, $a) {
    switch ($a[2]) {
    case 1: // GIF
    case 3: // PNG
        // http://www.akemapa.com/2008/07/10/php-gd-resize-transparent-image-png-gif/
        // http://www.mummey.org/2008/11/transparent-gifs-with-php-and-gd/
        imagealphablending($new, false);
        imagesavealpha($new, true);
        $back = imagecolorallocatealpha($new, 255, 255, 255, 127);
        imagefilledrectangle($new, 0, 0, $cw, $ch, $back);
        imagecolortransparent($new, $back);
        break;
    case 2: // JPEG
        $back = imagecolorallocate($new, 255, 255, 255);
        break;
    }
    imagefill($new, 0, 0, $back);
    imagecopyresampled($new, $src, $x, $y, 0, 0, $w, $h, $a[0], $a[1]);
    if (file_exists($file2)) unlink($file2);
    switch ($a[2]) {
    case 1:
        imagegif($new, $file2);
        break;
     case 2:
        imagejpeg($new, $file2, 100);
        break;
    case 3:
        imagepng($new, $file2, 0);
        break;
    }
    imagedestroy($src);
    imagedestroy($new);
    return true;
}

}

那么,有关如何保持GIF透明度的任何提示吗?

1 个答案:

答案 0 :(得分:0)

您将a link与答案放在一起;)

你正在使用imageCopyResampled,它与alpha一样奇怪。请改用imageCopyResized

http://www.mummey.org/2008/11/transparent-gifs-with-php-and-gd/comment-page-1/#comment-94