PHP - 如何在不在本地保存图像的情况下调整远程图像的大小?
PHP - How to resize remote image without saving image locally?
我需要做的是抓取远程缩略图并将它们临时调整为 300x200 像素。我想用像 phpthumb 这样的脚本来完成这个(无法让它工作)。
所以我希望能够做的是:
<img src="my_script.php?http://google.com/image.jpg&w=300&h=200" />
我有一个 class 用于此,但它有一些依赖项,所以我将粘贴相关位,以帮助您入门。抱歉,重做我的 HD 后我没有安装 GIT,因此例如缺少异常 class 依赖项。我相信您可以解决其中的一些问题,而且我已经有大约 2 年没有使用它了。所以我不能保证一切正常。
<?php
namespace Lib\Image;
/**
* @author ArtisiticPhoenix
* @package Lib
* @subpackage Image
*
*/
Class LibImage{
const MODE_CROP = 'crop';
const MODE_STRETCH = 'stretch';
const MODE_SHRINK = 'shirnk';
const MODE_FILL = 'fill';
const POS_TOP = 1;
const POS_BOTTOM = 2;
const POS_LEFT = 4;
const POS_RIGHT = 8;
public $img_src = '';
public $image = null;
public $image_type = null;
/**
*
* @param string $src
*/
public function __construct($file_src=null, $string_src=null){
if(!is_null($file_src)){
$this->setImage($file_src);
}
}
/**
* is the image loaded
* @return boolean
*/
public function isLoaded(){
return !is_null($this->image);
}
/**
* load an image file
* @param filepath $file_src
* @throws ImageException
*/
public function setImage($file_src){
if(!is_null($file_src)){
if(!is_file($file_src)){
throw new ImageException('[ '.$file_src.' ]', ImageException::ER_NO_FILE);
}
$this->img_src = $file_src;
$this->image_type = exif_imagetype($this->img_src);
switch($this->image_type)
{
case IMAGETYPE_GIF:
$this->image = imagecreatefromgif($file_src);
break;
case IMAGETYPE_JPEG:
$this->image = imagecreatefromjpeg($file_src);
break;
case IMAGETYPE_PNG:
$this->image = imagecreatefrompng($file_src);
imagealphablending($this->image, true); // setting alpha blending on
imagesavealpha($this->image, true); // save alphablending setting (important)
break;
case IMAGETYPE_WBMP:
$this->image = imagecreatefromwbmp($file_src);
break;
default:
throw new ImageException('', ImageException::ER_MIME);
}
}
}
/**
* get the image height - y
* @return number
*/
public function height(){
return imagesy($this->image);
}
/**
* get the image width - x
* @return number
*/
public function width(){
return imagesx($this->image);
}
/**
* get the aspect of image
* @return number
*/
public function getAspect(){
return $this->width() / $this->height();
}
/**
* get the image info
* @return array:
*/
public function getInfo(){
return $this->image_info;
}
//@todo
public function calc_offset($src_width, $src_height, $dest_width, $dest_height, $location=0){
if($location & self::POS_TOP){ //bitwise &
}else if($location & self::POS_BOTTOM){
}else{
$centreY = round($dest_height / 2);
$y = $centreY - $src_height / 2;
}
if($location & self::POS_LEFT){
}else if($location & self::POS_RIGHT){
}else{
$centreX = round($dest_width / 2);
$x = $centreX - $src_width / 2;
}
return array('x'=>$x, 'y'=>$y);
}
/**
* get the greatest dimension
* @return string
*/
public function greaterDim(){
if($this->width() > $this->height()){
return 'width';
}else if($this->width() < $this->height()){
return 'height';
}else{
return 'equal';
}
}
/**
* get the image orientation
* @return string
*/
public function getOrientation(){
$dim = $this->GreaterDim();
if($dim == 'height'){
return 'portrait';
}else if($dim == 'width'){
return 'landscape';
}else{
return 'equal';
}
}
///transforms//////
/**
* fit the image in a box
* @param number $width
* @param number $height
* @param string $mode
*/
public function fitBox($width, $height, $mode=false, $position=32){
switch ($mode){
case self::MODE_CROP:
//shrink the shortest dim to fit in the box - then center crop the exess
if($this->width() <= $this->height() && $this->width() > $width){
$this->resizeToWidth($width);
}else if($this->width() > $this->height() && $this->height() > $height){
$this->resizeToHeight($height);
}else{
print_rr('TODO');
}
$this->cropTo($width, $height);
break;
case self::MODE_FILL:
$this->fitBox($width, $height, self::MODE_SHRINK);
$this->expandCanvaseTo($width, $height);
break;
case self::MODE_SHRINK:
$this->resizeToHeight($height);
//shrink to fit in the box bounds
if($this->width() > $width){
$this->resizeToWidth($width);
}
break;
case self::MODE_STRETCH:
default:
//stretch the image to fit in the box bounds
$this->resize($width, $height);
break;
}
}
/**
* scale image by percent (eg. 100 - full size)
* @param int $scale
*/
function scale($scale) {
$width = $this->width() * $scale / 100;
$height = $this->height() * $scale / 100;
$this->resize($width, $height);
}
/**
* resize image to height
* @param number $height
*/
function resizeToHeight($height) {
$ratio = $height / $this->height();
$width = $this->width() * $ratio;
$this->resize($width, $height);
}
/**
* resize image to width
* @param number $width
*/
function resizeToWidth($width) {
$ratio = $width / $this->width();
$height = $this->height() * $ratio;
$this->resize($width, $height);
}
/**
* resize image by width and height (stretch)
* @param number $width
* @param number $height
*/
function resize($width,$height) {
$new_image = $this->createCanvas($width, $height);
imagecopyresampled($new_image, $this->image, 0, 0, 0, 0, $width, $height, $this->width(), $this->height());
$this->image = $new_image;
}
/**
*
* @param number $width
* @param unknown $height
* @return resource
*/
function createCanvas($width, $height){
$new_image = imagecreatetruecolor($width, $height);
if($this->image_type==IMAGETYPE_PNG || $this->image_type==IMAGETYPE_GIF){
imagealphablending($new_image, false);
imagesavealpha($new_image, true);
if($this->image_type==IMAGETYPE_GIF){
$new_image = imagecreate($width, $height);
}
}
$white = imagecolorallocate($new_image, 255, 255, 255);
imagefill( $new_image, 0, 0, $white );
return $new_image;
}
/**
*
* @param int $dst_x - x-coordinate of destination point.
* @param int $dst_y - y-coordinate of destination point.
* @param int $src_x - x-coordinate of source point.
* @param int $src_y - y-coordinate of source point.
* @param number $width - Source width.
* @param number $height - Source height.
*/
function crop($dst_x, $dst_y, $src_x, $src_y, $width, $height){
$new_image = $this->createCanvas($width, $height);
imagecopy ( $new_image, $this->image, $dst_x, $dst_y, $src_x, $src_y, $width, $height );
$this->image = $new_image;
}
/**
*
* @param number $width
* @param number $height
* @param int $position - @todo
*/
function cropTo($width, $height, $position=32){
$centreX = round($this->width() / 2);
$centreY = round($this->height() / 2);
$x = $centreX - $width / 2;
$y = $centreY - $height / 2;
if ($x < 0) $x = 0;
if ($y < 0) $y = 0;
$this->crop(0, 0, $x, $y, $width, $height);
}
function expandCanvaseTo($width, $height, $position=32){
$centreX = round($width / 2);
$x = $centreX - $this->width() / 2;
$centreY = round($height / 2);
$y = $centreY - $this->height() / 2;
if ($x < 0) $x = 0;
if ($y < 0) $y = 0;
$new_image = $this->createCanvas($width, $height);
imagecopy ( $new_image, $this->image, $x, $y, 0, 0, $this->width(), $this->height() );
$this->image = $new_image;
}
/**
* //@todo test and update this
* @param unknown $degrees
* @param number $bg
*/
function rotate($degrees, $bg=0){
$this->image = imagerotate($this->image, $degrees, $bg);
//imagecolortransparent($this->image, imagecolorallocate($this->image, 0, 0, 0));
}
/**
*
* @param string $watermark_src - path to watermark image
*/
function watermarkImage($watermark_src) {
$WaterMark = new self($watermark_src);
//make sure the watermark will always fit in the image confines
if($this->width() < $WaterMark->width() || $this->height() < $WaterMark->height()){
$WaterMark->fitBox($this->width(), $this->height(), self::MODE_SHRINK);
}
// Set the tile
imagesettile($this->image, $WaterMark->image);
// Make the image repeat
imagefilledrectangle($this->image, 0, 0, $this->width(), $this->height(), IMG_COLOR_TILED);
}
//@todo http://us2.php.net/manual/en/function.imageflip.php
/////////output////////////
/**
* update old image file
* @param number $res
*/
function save($res=90){
$this->Create($this->img_src, $res);
}
/**
* save image with filename dest - or save over file
* @param string $dest
* @param number $res
* @throws ImageException
*/
function create($dest, $res=90){
switch($this->image_type){
case IMAGETYPE_GIF:
imagegif($this->image, $dest, $res);
break;
case IMAGETYPE_JPEG:
imagejpeg($this->image, $dest, $res);
break;
case IMAGETYPE_PNG:
$res = ceil($res*0.1); //convert from 0-100 to 1-10
imagepng($this->image, $dest, $res);
break;
case IMAGETYPE_WBMP:
imagewbmp($this->image, $dest, $res);
break;
default:
throw new ImageException('', ImageException::ER_MIME);
}
}
/**
* render to browser
* @param number $res
* @throws ImageException
*/
function render($res=90){
switch($this->image_type){
case IMAGETYPE_GIF:
header('Content-Type: image/gif');
imagegif($this->image, null, $res);
break;
case IMAGETYPE_JPEG:
header('Content-Type: image/jpg');
imagejpeg($this->image, null, $res);
break;
case IMAGETYPE_PNG:
header('Content-Type: image/png');
$res = ceil($res*0.1); //convert from 0-100 to 1-10
imagepng($this->image, null, $res);
break;
case IMAGETYPE_WBMP:
header('Content-Type: image/bmp');
imagewbmp($this->image, null, $res);
break;
default:
throw new ImageException('', ImageException::ER_MIME);
}
}
/**
* close image resorce
*/
function __distruct(){
imagedestroy($this->image);
}
}
你会想做类似的事情,
$Image = new \Lib\Image\LibImage( 'image.jpg' );
$Image->fitBox(300, 200, \Lib\Image\LibImage::MODE_CROP );
$Image->save();
您可以使用 ImageMagick ( http://php.net/manual/en/book.imagick.php ),前提是您已经安装了它。
解决方案:
function crop( $url, $width, $height, $x = 0, $y = 0 )
{
$file = file_get_contents( $url );
$imagick = new Imagick;
$imagick->readImageBlob( $file );
$imagick->cropImage( $width, $height, $x, $y );
$base64 = base64_encode( $imagick->getImageBlob() );
return "data:image/jpeg;base64," . $base64;
}
这需要 URL、'crop area' 的宽度和高度以及 x y 参数,以设置 'crop area' 左上角的位置。
data:image/jpeg;指定输出格式
我需要做的是抓取远程缩略图并将它们临时调整为 300x200 像素。我想用像 phpthumb 这样的脚本来完成这个(无法让它工作)。
所以我希望能够做的是:
<img src="my_script.php?http://google.com/image.jpg&w=300&h=200" />
我有一个 class 用于此,但它有一些依赖项,所以我将粘贴相关位,以帮助您入门。抱歉,重做我的 HD 后我没有安装 GIT,因此例如缺少异常 class 依赖项。我相信您可以解决其中的一些问题,而且我已经有大约 2 年没有使用它了。所以我不能保证一切正常。
<?php
namespace Lib\Image;
/**
* @author ArtisiticPhoenix
* @package Lib
* @subpackage Image
*
*/
Class LibImage{
const MODE_CROP = 'crop';
const MODE_STRETCH = 'stretch';
const MODE_SHRINK = 'shirnk';
const MODE_FILL = 'fill';
const POS_TOP = 1;
const POS_BOTTOM = 2;
const POS_LEFT = 4;
const POS_RIGHT = 8;
public $img_src = '';
public $image = null;
public $image_type = null;
/**
*
* @param string $src
*/
public function __construct($file_src=null, $string_src=null){
if(!is_null($file_src)){
$this->setImage($file_src);
}
}
/**
* is the image loaded
* @return boolean
*/
public function isLoaded(){
return !is_null($this->image);
}
/**
* load an image file
* @param filepath $file_src
* @throws ImageException
*/
public function setImage($file_src){
if(!is_null($file_src)){
if(!is_file($file_src)){
throw new ImageException('[ '.$file_src.' ]', ImageException::ER_NO_FILE);
}
$this->img_src = $file_src;
$this->image_type = exif_imagetype($this->img_src);
switch($this->image_type)
{
case IMAGETYPE_GIF:
$this->image = imagecreatefromgif($file_src);
break;
case IMAGETYPE_JPEG:
$this->image = imagecreatefromjpeg($file_src);
break;
case IMAGETYPE_PNG:
$this->image = imagecreatefrompng($file_src);
imagealphablending($this->image, true); // setting alpha blending on
imagesavealpha($this->image, true); // save alphablending setting (important)
break;
case IMAGETYPE_WBMP:
$this->image = imagecreatefromwbmp($file_src);
break;
default:
throw new ImageException('', ImageException::ER_MIME);
}
}
}
/**
* get the image height - y
* @return number
*/
public function height(){
return imagesy($this->image);
}
/**
* get the image width - x
* @return number
*/
public function width(){
return imagesx($this->image);
}
/**
* get the aspect of image
* @return number
*/
public function getAspect(){
return $this->width() / $this->height();
}
/**
* get the image info
* @return array:
*/
public function getInfo(){
return $this->image_info;
}
//@todo
public function calc_offset($src_width, $src_height, $dest_width, $dest_height, $location=0){
if($location & self::POS_TOP){ //bitwise &
}else if($location & self::POS_BOTTOM){
}else{
$centreY = round($dest_height / 2);
$y = $centreY - $src_height / 2;
}
if($location & self::POS_LEFT){
}else if($location & self::POS_RIGHT){
}else{
$centreX = round($dest_width / 2);
$x = $centreX - $src_width / 2;
}
return array('x'=>$x, 'y'=>$y);
}
/**
* get the greatest dimension
* @return string
*/
public function greaterDim(){
if($this->width() > $this->height()){
return 'width';
}else if($this->width() < $this->height()){
return 'height';
}else{
return 'equal';
}
}
/**
* get the image orientation
* @return string
*/
public function getOrientation(){
$dim = $this->GreaterDim();
if($dim == 'height'){
return 'portrait';
}else if($dim == 'width'){
return 'landscape';
}else{
return 'equal';
}
}
///transforms//////
/**
* fit the image in a box
* @param number $width
* @param number $height
* @param string $mode
*/
public function fitBox($width, $height, $mode=false, $position=32){
switch ($mode){
case self::MODE_CROP:
//shrink the shortest dim to fit in the box - then center crop the exess
if($this->width() <= $this->height() && $this->width() > $width){
$this->resizeToWidth($width);
}else if($this->width() > $this->height() && $this->height() > $height){
$this->resizeToHeight($height);
}else{
print_rr('TODO');
}
$this->cropTo($width, $height);
break;
case self::MODE_FILL:
$this->fitBox($width, $height, self::MODE_SHRINK);
$this->expandCanvaseTo($width, $height);
break;
case self::MODE_SHRINK:
$this->resizeToHeight($height);
//shrink to fit in the box bounds
if($this->width() > $width){
$this->resizeToWidth($width);
}
break;
case self::MODE_STRETCH:
default:
//stretch the image to fit in the box bounds
$this->resize($width, $height);
break;
}
}
/**
* scale image by percent (eg. 100 - full size)
* @param int $scale
*/
function scale($scale) {
$width = $this->width() * $scale / 100;
$height = $this->height() * $scale / 100;
$this->resize($width, $height);
}
/**
* resize image to height
* @param number $height
*/
function resizeToHeight($height) {
$ratio = $height / $this->height();
$width = $this->width() * $ratio;
$this->resize($width, $height);
}
/**
* resize image to width
* @param number $width
*/
function resizeToWidth($width) {
$ratio = $width / $this->width();
$height = $this->height() * $ratio;
$this->resize($width, $height);
}
/**
* resize image by width and height (stretch)
* @param number $width
* @param number $height
*/
function resize($width,$height) {
$new_image = $this->createCanvas($width, $height);
imagecopyresampled($new_image, $this->image, 0, 0, 0, 0, $width, $height, $this->width(), $this->height());
$this->image = $new_image;
}
/**
*
* @param number $width
* @param unknown $height
* @return resource
*/
function createCanvas($width, $height){
$new_image = imagecreatetruecolor($width, $height);
if($this->image_type==IMAGETYPE_PNG || $this->image_type==IMAGETYPE_GIF){
imagealphablending($new_image, false);
imagesavealpha($new_image, true);
if($this->image_type==IMAGETYPE_GIF){
$new_image = imagecreate($width, $height);
}
}
$white = imagecolorallocate($new_image, 255, 255, 255);
imagefill( $new_image, 0, 0, $white );
return $new_image;
}
/**
*
* @param int $dst_x - x-coordinate of destination point.
* @param int $dst_y - y-coordinate of destination point.
* @param int $src_x - x-coordinate of source point.
* @param int $src_y - y-coordinate of source point.
* @param number $width - Source width.
* @param number $height - Source height.
*/
function crop($dst_x, $dst_y, $src_x, $src_y, $width, $height){
$new_image = $this->createCanvas($width, $height);
imagecopy ( $new_image, $this->image, $dst_x, $dst_y, $src_x, $src_y, $width, $height );
$this->image = $new_image;
}
/**
*
* @param number $width
* @param number $height
* @param int $position - @todo
*/
function cropTo($width, $height, $position=32){
$centreX = round($this->width() / 2);
$centreY = round($this->height() / 2);
$x = $centreX - $width / 2;
$y = $centreY - $height / 2;
if ($x < 0) $x = 0;
if ($y < 0) $y = 0;
$this->crop(0, 0, $x, $y, $width, $height);
}
function expandCanvaseTo($width, $height, $position=32){
$centreX = round($width / 2);
$x = $centreX - $this->width() / 2;
$centreY = round($height / 2);
$y = $centreY - $this->height() / 2;
if ($x < 0) $x = 0;
if ($y < 0) $y = 0;
$new_image = $this->createCanvas($width, $height);
imagecopy ( $new_image, $this->image, $x, $y, 0, 0, $this->width(), $this->height() );
$this->image = $new_image;
}
/**
* //@todo test and update this
* @param unknown $degrees
* @param number $bg
*/
function rotate($degrees, $bg=0){
$this->image = imagerotate($this->image, $degrees, $bg);
//imagecolortransparent($this->image, imagecolorallocate($this->image, 0, 0, 0));
}
/**
*
* @param string $watermark_src - path to watermark image
*/
function watermarkImage($watermark_src) {
$WaterMark = new self($watermark_src);
//make sure the watermark will always fit in the image confines
if($this->width() < $WaterMark->width() || $this->height() < $WaterMark->height()){
$WaterMark->fitBox($this->width(), $this->height(), self::MODE_SHRINK);
}
// Set the tile
imagesettile($this->image, $WaterMark->image);
// Make the image repeat
imagefilledrectangle($this->image, 0, 0, $this->width(), $this->height(), IMG_COLOR_TILED);
}
//@todo http://us2.php.net/manual/en/function.imageflip.php
/////////output////////////
/**
* update old image file
* @param number $res
*/
function save($res=90){
$this->Create($this->img_src, $res);
}
/**
* save image with filename dest - or save over file
* @param string $dest
* @param number $res
* @throws ImageException
*/
function create($dest, $res=90){
switch($this->image_type){
case IMAGETYPE_GIF:
imagegif($this->image, $dest, $res);
break;
case IMAGETYPE_JPEG:
imagejpeg($this->image, $dest, $res);
break;
case IMAGETYPE_PNG:
$res = ceil($res*0.1); //convert from 0-100 to 1-10
imagepng($this->image, $dest, $res);
break;
case IMAGETYPE_WBMP:
imagewbmp($this->image, $dest, $res);
break;
default:
throw new ImageException('', ImageException::ER_MIME);
}
}
/**
* render to browser
* @param number $res
* @throws ImageException
*/
function render($res=90){
switch($this->image_type){
case IMAGETYPE_GIF:
header('Content-Type: image/gif');
imagegif($this->image, null, $res);
break;
case IMAGETYPE_JPEG:
header('Content-Type: image/jpg');
imagejpeg($this->image, null, $res);
break;
case IMAGETYPE_PNG:
header('Content-Type: image/png');
$res = ceil($res*0.1); //convert from 0-100 to 1-10
imagepng($this->image, null, $res);
break;
case IMAGETYPE_WBMP:
header('Content-Type: image/bmp');
imagewbmp($this->image, null, $res);
break;
default:
throw new ImageException('', ImageException::ER_MIME);
}
}
/**
* close image resorce
*/
function __distruct(){
imagedestroy($this->image);
}
}
你会想做类似的事情,
$Image = new \Lib\Image\LibImage( 'image.jpg' );
$Image->fitBox(300, 200, \Lib\Image\LibImage::MODE_CROP );
$Image->save();
您可以使用 ImageMagick ( http://php.net/manual/en/book.imagick.php ),前提是您已经安装了它。
解决方案:
function crop( $url, $width, $height, $x = 0, $y = 0 )
{
$file = file_get_contents( $url );
$imagick = new Imagick;
$imagick->readImageBlob( $file );
$imagick->cropImage( $width, $height, $x, $y );
$base64 = base64_encode( $imagick->getImageBlob() );
return "data:image/jpeg;base64," . $base64;
}
这需要 URL、'crop area' 的宽度和高度以及 x y 参数,以设置 'crop area' 左上角的位置。
data:image/jpeg;指定输出格式