/** * 在保持图像长宽比的情况下将图像裁减到指定大小 * * crop() 在缩放图像时,可以保持图像的长宽比,从而保证图像不会拉高或压扁。 * * crop() 默认情况下会按照 $width 和 $height 参数计算出最大缩放比例, * 保持裁减后的图像能够最大程度的充满图片。 * * 例如源图的大小是 800 x 600,而指定的 $width 和 $height 是 200 和 100。 * 那么源图会被首先缩小为 200 x 150 尺寸,然后裁减掉多余的 50 像素高度。 * * 用法: * @code php * $image->crop($width, $height); * @endcode * * 如果希望最终生成图片始终包含完整图像内容,那么应该指定 $options 参数。 * 该参数可用值有: * * - fullimage: 是否保持完整图像 * - pos: 缩放时的对齐方式 * - bgcolor: 缩放时多余部分的背景色 * - enlarge: 是否允许放大 * - reduce: 是否允许缩小 * * 其中 $options['pos'] 参数的可用值有: * * - left: 左对齐 * - right: 右对齐 * - center: 中心对齐 * - top: 顶部对齐 * - bottom: 底部对齐 * - top-left, left-top: 左上角对齐 * - top-right, right-top: 右上角对齐 * - bottom-left, left-bottom: 左下角对齐 * - bottom-right, right-bottom: 右下角对齐 * * 如果指定了无效的 $pos 参数,则等同于指定 center。 * * $options 中的每一个选项都可以单独指定,例如在允许裁减的情况下将图像放到新图片的右下角。 * * @code php * $image->crop($width, $height, array('pos' => 'right-bottom')); * @endcode * * @param int $width 新的宽度 * @param int $height 新的高度 * @param array $options 裁减选项 * * @return Helper_ImageGD 返回 Helper_ImageGD 对象本身,实现连贯接口 */ function crop($width, $height, $options = array()) { if (is_null($this->_handle)) { return $this; } $default_options = array('fullimage' => false, 'pos' => 'center', 'bgcolor' => '0xfff', 'enlarge' => false, 'reduce' => true); $options = array_merge($default_options, $options); // 创建目标图像 $dest = imagecreatetruecolor($width, $height); // 填充背景色 list($r, $g, $b) = Helper_Image::hex2rgb($options['bgcolor'], '0xffffff'); $bgcolor = imagecolorallocate($dest, $r, $g, $b); imagefilledrectangle($dest, 0, 0, $width, $height, $bgcolor); imagecolordeallocate($dest, $bgcolor); // 根据源图计算长宽比 $full_w = imagesx($this->_handle); $full_h = imagesy($this->_handle); $ratio_w = doubleval($width) / doubleval($full_w); $ratio_h = doubleval($height) / doubleval($full_h); if ($options['fullimage']) { // 如果要保持完整图像,则选择最小的比率 $ratio = $ratio_w < $ratio_h ? $ratio_w : $ratio_h; } else { // 否则选择最大的比率 $ratio = $ratio_w > $ratio_h ? $ratio_w : $ratio_h; } if (!$options['enlarge'] && $ratio > 1) { $ratio = 1; } if (!$options['reduce'] && $ratio < 1) { $ratio = 1; } // 计算目标区域的宽高、位置 $dst_w = $full_w * $ratio; $dst_h = $full_h * $ratio; // 根据 pos 属性来决定如何定位 switch (strtolower($options['pos'])) { case 'left': $dst_x = 0; $dst_y = ($height - $dst_h) / 2; break; case 'right': $dst_x = $width - $dst_w; $dst_y = ($height - $dst_h) / 2; break; case 'top': $dst_x = ($width - $dst_w) / 2; $dst_y = 0; break; case 'bottom': $dst_x = ($width - $dst_w) / 2; $dst_y = $height - $dst_h; break; case 'top-left': case 'left-top': $dst_x = $dst_y = 0; break; case 'top-right': case 'right-top': $dst_x = $width - $dst_w; $dst_y = 0; break; case 'bottom-left': case 'left-bottom': $dst_x = 0; $dst_y = $height - $dst_h; break; case 'bottom-right': case 'right-bottom': $dst_x = $width - $dst_w; $dst_y = $height - $dst_h; break; case 'center': default: $dst_x = ($width - $dst_w) / 2; $dst_y = ($height - $dst_h) / 2; } imagecopyresampled($dest, $this->_handle, $dst_x, $dst_y, 0, 0, $dst_w, $dst_h, $full_w, $full_h); imagedestroy($this->_handle); $this->_handle = $dest; return $this; }
/** * 在保持图像长宽比的情况下将图像裁减到指定大小 * * @param int $width * @param int $height * @param boolean $highQuality * @param array $nocut */ function crop($width, $height, $highQuality = true, $nocut = null) { if (is_null($this->_handle)) { return; } $dest = imagecreatetruecolor($width, $height); $sx = imagesx($this->_handle); $sy = imagesy($this->_handle); $ratio = doubleval($width) / doubleval($sx); if (!is_array($nocut)) { if ($nocut) { $nocut = array('enabled' => true, 'pos' => 'center', 'bgcolor' => '0xffffff'); } else { $nocut = array('enabled' => false); } } else { $nocut['enabled'] = isset($nocut['enabled']) ? $nocut['enabled'] : true; $nocut['pos'] = isset($nocut['pos']) ? $nocut['pos'] : 'center'; $nocut['bgcolor'] = isset($nocut['bgcolor']) ? $nocut['bgcolor'] : '0xffffff'; } if ($nocut['enabled']) { // 求缩放后的最大宽度和高度 if ($sy * $ratio > $height) { $ratio = doubleval($height) / doubleval($sy); } $dx = $sx * $ratio; $dy = $sy * $ratio; // 根据 pos 属性来决定如何定位原始图片 switch (strtolower($nocut['pos'])) { case 'left': $ox = 0; $oy = ($height - $sy * $ratio) / 2; break; case 'right': $ox = $width - $sx * $ratio; $oy = ($height - $sy * $ratio) / 2; break; case 'top': $ox = ($width - $sx * $ratio) / 2; $oy = 0; break; case 'bottom': $ox = ($width - $sx * $ratio) / 2; $oy = $height - $sy * $ratio; break; case 'top-left': $ox = $oy = 0; break; case 'top-right': $ox = $width - $sx * $ratio; $oy = 0; break; case 'bottom-left': $ox = 0; $oy = $height - $sy * $ratio; break; case 'bottom-right': $ox = $width - $sx * $ratio; $oy = $height - $sy * $ratio; break; default: $ox = ($width - $sx * $ratio) / 2; $oy = ($height - $sy * $ratio) / 2; } list($r, $g, $b) = Helper_Image::hex2rgb($nocut['bgcolor'], '0xffffff'); $bgcolor = imagecolorallocate($dest, $r, $g, $b); imagefilledrectangle($dest, 0, 0, $width, $height, $bgcolor); imagecolordeallocate($dest, $bgcolor); $args = array($dest, $this->_handle, $ox, $oy, 0, 0, $dx, $dy, $sx, $sy); } else { // 允许图像溢出 if ($sy * $ratio < $height) { // 当按照比例缩放后的图像高度小于要求的高度时,只有放弃原始图像右边的部分内容 $ratio = doubleval($sy) / doubleval($height); $sx = $width * $ratio; } elseif ($sy * $ratio > $height) { // 当按照比例缩放后的图像高度大于要求的高度时,只有放弃原始图像底部的部分内容 $ratio = doubleval($sx) / doubleval($width); $sy = $height * $ratio; } $args = array($dest, $this->_handle, 0, 0, 0, 0, $width, $height, $sx, $sy); } if ($highQuality) { call_user_func_array('imagecopyresampled', $args); } else { call_user_func_array('imagecopyresized', $args); } imagedestroy($this->_handle); $this->_handle = $dest; }