PageRenderTime 65ms CodeModel.GetById 35ms RepoModel.GetById 1ms app.codeStats 0ms

/libs/system/Image.php

https://github.com/monkeycraps/swoole_framework
PHP | 546 lines | 390 code | 29 blank | 127 comment | 58 complexity | 1b67df208dcaf8558320d00a7ad4394c MD5 | raw file
  1. <?php
  2. /**
  3. * 图像处理类
  4. * @author Tianfeng.Han
  5. * @package SwooleSystem
  6. * @subpackage Image
  7. * @link http://code.google.com/p/swoole/
  8. */
  9. class Image
  10. {
  11. /**
  12. * 裁切图片
  13. * @param $pic 源图像
  14. * @param $dst_pic 目标图像
  15. * @param $width 宽度
  16. * @param $height 高度
  17. * @param $qulitity 质量
  18. * @return unknown_type
  19. */
  20. static function cut($pic,$dst_pic,$width,$height=null,$qulitity=100)
  21. {
  22. $im = imagecreatefromjpeg($pic);
  23. if(imagesx($im)>$width)
  24. {
  25. $old_w = imagesx($im);
  26. $old_h = imagesy($im);
  27. if($height==null)
  28. {
  29. $w_h = $old_w/$old_h;
  30. $height = $width*$w_h;
  31. }
  32. $newim = imagecreatetruecolor($width, $height);
  33. imagecopyresampled($newim, $im, 0, 0, 0, 0, $width,$height,$old_w,$old_h);
  34. imagejpeg($newim, $dst_pic,$qulitity);
  35. imagedestroy($im);
  36. return true;
  37. }
  38. elseif($pic!=$dst_pic) copy($pic,$dst_pic);
  39. }
  40. /**
  41. * 压缩图像尺寸
  42. * @param $pic 源图像
  43. * @param $dst_pic 目标图像
  44. * @param $width 宽度
  45. * @param $height 高度
  46. * @param $qulitity 质量
  47. * @return unknown_type
  48. */
  49. static function thumbnail($pic,$dst_pic,$max_width,$max_height=null,$qulitity=100, $copy=true)
  50. {
  51. $im = self::readfile($pic);
  52. $old_w = imagesx($im);
  53. $old_h = imagesy($im);
  54. if($max_height==null) $max_height=$max_width;
  55. if($old_w>$max_width or $old_h>$max_height)
  56. {
  57. $w_h = $old_w / $old_h;
  58. $h_w = $old_h / $old_w;
  59. if($w_h>$h_w)
  60. {
  61. $width = $max_width;
  62. $height = $width*$h_w;
  63. }
  64. else
  65. {
  66. $height = $max_height;
  67. $width = $height*$w_h;
  68. }
  69. $newim = imagecreatetruecolor($width, $height);
  70. imagecopyresampled($newim, $im, 0, 0, 0, 0, $width,$height,$old_w,$old_h);
  71. imagejpeg($newim, $dst_pic, $qulitity);
  72. imagedestroy($im);
  73. }
  74. elseif($pic!=$dst_pic and $copy) copy($pic, $dst_pic);
  75. }
  76. /**
  77. * 读取图像
  78. * @param $pic
  79. * @return unknown_type
  80. */
  81. static function readfile($pic)
  82. {
  83. $image_info = getimagesize($pic);
  84. if($image_info["mime"]=="image/jpeg" || $image_info["mime"]=="image/gif" || $image_info["mime"]=="image/png")
  85. {
  86. switch($image_info["mime"])
  87. {
  88. case "image/jpeg":
  89. $im = imagecreatefromjpeg($pic);
  90. break;
  91. case "image/gif":
  92. $im = imagecreatefromgif($pic);
  93. break;
  94. case "image/png":
  95. $im = imagecreatefrompng($pic);
  96. break;
  97. }
  98. return $im;
  99. }
  100. return false;
  101. }
  102. /**
  103. * 加给图片加水印
  104. *
  105. * @param strimg $groundImage 要加水印地址
  106. * @param int $waterPos 水印位置
  107. * @param string $waterImage 水印图片地址
  108. * @param string $waterText 文本文字
  109. * @param int $textFont 文字大小
  110. * @param string $textColor 文字颜色
  111. * @param int $minWidth 小于此值不加水印
  112. * @param int $minHeight 小于此值不加水印
  113. * @param float $alpha 透明度
  114. * @return FALSE
  115. */
  116. public static function waterMark($groundImage , $waterPos = 0 , $waterImage = "" , $waterText = "" , $textFont = 15 , $textColor = "#FF0000",$minWidth='100',$minHeight='100',$alpha=0.9)
  117. {
  118. $isWaterImg = FALSE;
  119. $bg_h = $bg_w = $water_h = $water_w = 0;
  120. //获取背景图的高,宽
  121. if(is_file($groundImage) && !empty($groundImage)){
  122. $bg = new Imagick();
  123. $bg ->readImage($groundImage);
  124. $bg_h = $bg->getImageHeight();
  125. $bg_w = $bg->getImageWidth();
  126. }
  127. //获取水印图的高,宽
  128. if(is_file($waterImage) && !empty($waterImage)){
  129. $water = new Imagick($waterImage);
  130. $water_h = $water->getImageHeight();
  131. $water_w = $water->getImageWidth();
  132. }
  133. //如果背景图的高宽小于水印图的高宽或指定的高和宽则不加水印
  134. if($bg_h < $minHeight || $bg_w < $minWidth || $bg_h < $water_h || $bg_w < $water_w ) {
  135. return ;
  136. }else {
  137. $isWaterImg = TRUE;
  138. }
  139. //加水印
  140. if($isWaterImg){
  141. $dw = new ImagickDraw();
  142. //加图片水印
  143. if(is_file($waterImage)){
  144. $water->setImageOpacity($alpha);
  145. $dw -> setGravity($waterPos);
  146. $dw -> composite($water->getImageCompose(),0,0,50,0,$water);
  147. $bg -> drawImage($dw);
  148. if(!$bg -> writeImage($groundImage)){
  149. return FALSE;
  150. }
  151. }else{
  152. //加文字水印
  153. $dw -> setFontSize($textFont);
  154. $dw -> setFillColor($textColor);
  155. $dw -> setGravity($waterPos);
  156. $dw -> setFillAlpha($alpha);
  157. $dw -> annotation(0,0,$waterText);
  158. $bg -> drawImage($dw);
  159. if(!$bg -> writeImage($groundImage)){
  160. return FALSE;
  161. }
  162. }
  163. }
  164. }
  165. /**
  166. * PHP图片水印 (水印支持图片或文字)
  167. * 注意:Support GD 2.0,Support FreeType、GIF Read、GIF Create、JPG 、PNG
  168. * $waterImage 和 $waterText 最好不要同时使用,选其中之一即可,优先使用 $waterImage。
  169. * 当$waterImage有效时,参数$waterString、$stringFont、$stringColor均不生效。
  170. * 加水印后的图片的文件名和 $groundImage 一样。
  171. * @param $groundImage 背景图片,即需要加水印的图片,暂只支持GIF,JPG,PNG格式;
  172. * @param $waterPos 水印位置,有10种状态,0为随机位置;1为顶端居左,2为顶端居中,3为顶端居右;4为中部居左,5为中部居中,6为中部居右;7为底端居左,8为底端居中,9为底端居右;
  173. * @param $waterImage 图片水印,即作为水印的图片,暂只支持GIF,JPG,PNG格式;
  174. * @param $waterText 文字水印,即把文字作为为水印,支持ASCII码,不支持中文;
  175. * @param $textFont 文字大小
  176. * @param $textColor 文字颜色,值为十六进制颜色值,默认为#FF0000(红色);
  177. * @param $minwidth
  178. * @param $minheight
  179. * @return unknown_type
  180. */
  181. public static function waterMark2($groundImage , $waterPos = 0 , $waterImage = "" , $waterText = "" , $textFont = 5 , $textColor = "#FF0000",$minwidth,$minheight)
  182. {
  183. $isWaterImage = FALSE ;
  184. //$waterImage = SYSROOTPATH . $waterImage;
  185. $formatMsg = "暂不支持该文件格式,请用图片处理软件将图片转换为GIF、JPG、PNG格式。" ;
  186. //读取水印文件
  187. if(!empty( $waterImage ) && file_exists ( $waterImage )) {
  188. $isWaterImage = TRUE ;
  189. $water_info = getimagesize ( $waterImage );
  190. $water_w = $water_info [ 0 ]; //取得水印图片的宽
  191. $water_h = $water_info [ 1 ]; //取得水印图片的高
  192. switch( $water_info [ 2 ]) //取得水印图片的格式
  193. {
  194. case 1 : $water_im = imagecreatefromgif ( $waterImage );break;
  195. case 2 : $water_im = imagecreatefromjpeg ( $waterImage );break;
  196. case 3 : $water_im = imagecreatefrompng ( $waterImage );break;
  197. default:die( $formatMsg );
  198. }
  199. }
  200. //读取背景图片
  201. if(!empty( $groundImage ) && file_exists ( $groundImage )) {
  202. $ground_info = getimagesize ( $groundImage );
  203. $ground_w = $ground_info [ 0 ]; //取得背景图片的宽
  204. $ground_h = $ground_info [ 1 ]; //取得背景图片的高
  205. switch( $ground_info [ 2 ]) //取得背景图片的格式
  206. {
  207. case 1 : $ground_im = imagecreatefromgif ( $groundImage );break;
  208. case 2 : $ground_im = imagecreatefromjpeg ( $groundImage );break;
  209. case 3 : $ground_im = imagecreatefrompng ( $groundImage );break;
  210. default:die( $formatMsg );
  211. }
  212. } else {
  213. die( "需要加水印的图片不存在!" );
  214. }
  215. //水印位置
  216. if( $isWaterImage ) //图片水印
  217. {
  218. $w = $water_w ;
  219. $h = $water_h ;
  220. $label = "图片的" ;
  221. }
  222. else //文字水印
  223. {
  224. $temp = imagettfbbox ( ceil ( $textFont * 2.5 ), 0 , SYSROOTPATH."images/watermark/ant1.ttf" , $waterText ); //取得使用 TrueType 字体的文本的范围
  225. $w = $temp [ 2 ] - $temp [ 6 ];
  226. $h = $temp [ 3 ] - $temp [ 7 ];
  227. unset( $temp );
  228. $label = "文字区域" ;
  229. }
  230. // add
  231. if( ( $ground_w < $w ) || ( $ground_h < $h ) || ( $ground_w < $minwidth ) || ( $ground_h < $minheight ) ){
  232. echo "需要加水印的图片的长度或宽度比水印" . $label . "还小,无法生成水印!" ;
  233. return;
  234. }
  235. switch( $waterPos ) {
  236. case 0 : //随机
  237. $posX = rand ( 0 ,( $ground_w - $w ));
  238. $posY = rand ( 0 ,( $ground_h - $h ));
  239. break;
  240. case 1 : //1为顶端居左
  241. $posX = 0 ;
  242. $posY = 0 ;
  243. break;
  244. case 2 : //2为顶端居中
  245. $posX = ( $ground_w - $w ) / 2 ;
  246. $posY = 0 ;
  247. break;
  248. case 3 : //3为顶端居右
  249. $posX = $ground_w - $w ;
  250. $posY = 0 ;
  251. break;
  252. case 4 : //4为中部居左
  253. $posX = 0 ;
  254. $posY = ( $ground_h - $h ) / 2 ;
  255. break;
  256. case 5 : //5为中部居中
  257. $posX = ( $ground_w - $w ) / 2 ;
  258. $posY = ( $ground_h - $h ) / 2 ;
  259. break;
  260. case 6 : //6为中部居右
  261. $posX = $ground_w - $w ;
  262. $posY = ( $ground_h - $h ) / 2 ;
  263. break;
  264. case 7 : //7为底端居左
  265. $posX = 0 ;
  266. $posY = $ground_h - $h ;
  267. break;
  268. case 8 : //8为底端居中
  269. $posX = ( $ground_w - $w ) / 2 ;
  270. $posY = $ground_h - $h ;
  271. break;
  272. case 9 : //9为底端居右
  273. $posX = $ground_w - $w ;
  274. $posY = $ground_h - $h ;
  275. break;
  276. default: //随机
  277. $posX = rand ( 0 ,( $ground_w - $w ));
  278. $posY = rand ( 0 ,( $ground_h - $h ));
  279. break;
  280. }
  281. //设定图像的混色模式
  282. imagealphablending ( $ground_im , true );
  283. if( $isWaterImage ) //图片水印
  284. {
  285. imagecopy ( $ground_im , $water_im , $posX , $posY , 0 , 0 , $water_w , $water_h ); //拷贝水印到目标文件
  286. }
  287. else //文字水印
  288. {
  289. if( !empty( $textColor ) && ( strlen ( $textColor )== 7 ) )
  290. {
  291. $R = hexdec ( substr ( $textColor , 1 , 2 ));
  292. $G = hexdec ( substr ( $textColor , 3 , 2 ));
  293. $B = hexdec ( substr ( $textColor , 5 ));
  294. }
  295. else
  296. {
  297. die( "水印文字颜色格式不正确!" );
  298. }
  299. imagestring ( $ground_im , $textFont , $posX , $posY , $waterText , imagecolorallocate ( $ground_im , $R , $G , $B ));
  300. }
  301. //生成水印后的图片
  302. @unlink ( $groundImage );
  303. switch( $ground_info [ 2 ]) //取得背景图片的格式
  304. {
  305. case 1 : imagegif ( $ground_im , $groundImage );break;
  306. case 2 : imagejpeg ( $ground_im , $groundImage );break;
  307. case 3 : imagepng ( $ground_im , $groundImage );break;
  308. default:die( $errorMsg );
  309. }
  310. //释放内存
  311. if(isset( $water_info )) unset( $water_info );
  312. if(isset( $water_im )) imagedestroy ( $water_im );
  313. unset( $ground_info );
  314. imagedestroy ( $ground_im );
  315. }
  316. /**
  317. * 生成验证码使用GD
  318. * @param $img_width
  319. * @param $img_height
  320. * @return unknown_type
  321. */
  322. static function authcode_gd($img_width=80,$img_height=30)
  323. {
  324. session_start();
  325. $authnum = '';
  326. srand(microtime() * 100000);
  327. for($Tmpa=0;$Tmpa<4;$Tmpa++)
  328. {
  329. $authnum.=dechex(rand(0,15));
  330. }
  331. $authnum = strtoupper($authnum);;
  332. $_SESSION['authcode'] = $authnum;
  333. $aimg = imageCreate($img_width,$img_height); //生成图片
  334. ImageColorAllocate($aimg, 255,255,255); //图片底色,ImageColorAllocate第1次定义颜色PHP就认为是底色了
  335. //下面该生成雪花背景了,其实就是在图片上生成一些符号
  336. for($i=1; $i<=128; $i++)
  337. {
  338. imageString($aimg,1,mt_rand(1,$img_width),mt_rand(1,$img_height),"*",imageColorAllocate($aimg,mt_rand(200,255),mt_rand(200,255),mt_rand(200,255)));
  339. //其实也不是雪花,就是生成*号而已。为了使它们看起来"杂乱无章、5颜6色",就得在1个1个生成它们的时候,让它们的位置、颜色,甚至大小都用随机数,rand()或mt_rand都可以完成。
  340. }
  341. for($i=0;$i<strlen($_SESSION['authcode']);$i++)
  342. {
  343. imageString($aimg, mt_rand(8,12),$i*$img_width/4+mt_rand(1,8),mt_rand(1,$img_height/4), $_SESSION['authcode'][$i],imageColorAllocate($aimg,mt_rand(0,100),mt_rand(0,150),mt_rand(0,200)));
  344. }
  345. header("Content-type: image/png"); //告诉浏览器,下面的数据是图片
  346. ImagePng($aimg); //生成png格式
  347. ImageDestroy($aimg);
  348. }
  349. static function authcode_im()
  350. {
  351. if(empty($_SESSION)) session_start();
  352. $authnum = '';
  353. srand((double)microtime()*1000000);
  354. $_SESSION['authcode']="";
  355. /* imagick对象 *
  356. $Imagick = new Imagick();
  357. /* 背景对象 */
  358. $bg = new ImagickPixel();
  359. /* Set the pixel color to white */
  360. $bg->setColor('rgb(235,235,235)');
  361. /* 画刷 *
  362. $ImagickDraw = new ImagickDraw();
  363. /* Set font and font size. You can also specify /path/to/font.ttf */
  364. $ImagickDraw->setFont(LIBPATH.'/../static/fonts/CONSOLA.TTF');
  365. $ImagickDraw->setFontSize( 24 );
  366. $ImagickDraw->setFillColor('black');
  367. //生成数字和字母混合的验证码方法
  368. $ychar="0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z";
  369. $list=explode(",",$ychar);
  370. for($i=0;$i<4;$i++)
  371. {
  372. $randnum=rand(0,35);
  373. $authnum.=$list[$randnum];
  374. }
  375. $authnum = strtoupper($authnum);;
  376. $_SESSION['authcode'] = $authnum;
  377. /* Create new empty image */
  378. $Imagick->newImage( 60, 24, $bg );
  379. /* Write the text on the image */
  380. $Imagick->annotateImage( $ImagickDraw, 4, 20, 0, $authnum );
  381. /* 变形 *
  382. //$Imagick->swirlImage( 10 );
  383. /* 随即线条 */
  384. /*$ImagickDraw->line( rand( 0, 70 ), rand( 0, 30 ), rand( 0, 70 ), rand( 0, 30 ) );
  385. $ImagickDraw->line( rand( 0, 70 ), rand( 0, 30 ), rand( 0, 70 ), rand( 0, 30 ) );
  386. $ImagickDraw->line( rand( 0, 70 ), rand( 0, 30 ), rand( 0, 70 ), rand( 0, 30 ) );
  387. $ImagickDraw->line( rand( 0, 70 ), rand( 0, 30 ), rand( 0, 70 ), rand( 0, 30 ) );
  388. $ImagickDraw->line( rand( 0, 70 ), rand( 0, 30 ), rand( 0, 70 ), rand( 0, 30 ) );*/
  389. /* Draw the ImagickDraw object contents to the image. */
  390. $Imagick->drawImage( $ImagickDraw );
  391. /* Give the image a format */
  392. $Imagick->setImageFormat( 'png' );
  393. /* Send headers and output the image */
  394. //header( "Content-Type: image/{$Imagick->getImageFormat()}" );
  395. echo $Imagick->getImageBlob( );
  396. }
  397. /**
  398. * 生成验证码,使用TTF字体
  399. * @param $font
  400. * @param $img_width
  401. * @param $img_height
  402. * @return unknown_type
  403. */
  404. static function authcode_ttf($font,$width=180,$height=130)
  405. {
  406. if(empty($_SESSION)) session_start();
  407. $length = 4;
  408. $code = getRandNumChineseString(4);
  409. $width = ($length * 45) > $width ? $length * 45 : $width;
  410. $_SESSION['authcode'] = md5($code);
  411. $im = imagecreatetruecolor($width, $height);
  412. $borderColor = imagecolorallocate($im, 100, 100, 100); //边框色
  413. $bkcolor = imagecolorallocate($im, 250, 250, 250);
  414. imagefill($im, 0, 0, $bkcolor);
  415. imagerectangle($im, 0, 0, $width - 1, $height - 1, $borderColor);
  416. // 干扰
  417. for ($i = 0; $i < 15; $i++) {
  418. $fontcolor = imagecolorallocate($im, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255));
  419. imagearc($im, mt_rand(-10, $width), mt_rand(-10, $height), mt_rand(30, 300), mt_rand(20, 200), 55, 44, $fontcolor);
  420. }
  421. for ($i = 0; $i < 255; $i++) {
  422. $fontcolor = imagecolorallocate($im, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255));
  423. imagesetpixel($im, mt_rand(0, $width), mt_rand(0, $height), $fontcolor);
  424. }
  425. for ($i = 0; $i < $length; $i++) {
  426. $fontcolor = imagecolorallocate($im, mt_rand(0, 120), mt_rand(0, 120), mt_rand(0, 120)); //这样保证随机出来的颜色较深。
  427. $codex = msubstr($code, $i, 1);
  428. imagettftext($im, mt_rand(16, 20), mt_rand(-60, 60), 40 * $i + 20, mt_rand(30, 35), $fontcolor, $font, $codex);
  429. }
  430. Header("Content-type: image/png"); //告诉浏览器,下面的数据是图片
  431. ImagePng($im); //生成png格式
  432. ImageDestroy($im);
  433. }
  434. static function thumb_name($file_name,$insert='thumb')
  435. {
  436. $dirname = dirname($file_name);
  437. $file_name = basename($file_name);
  438. $extend =explode("." , $file_name);
  439. return $dirname.'/'.$extend[0].'_'.$insert.'.'.$extend[count($extend)-1];
  440. }
  441. /**
  442. * 裁切图片,制作头像
  443. * @param $image 图片相对网站根目录的地址
  444. * @param $params 参数,高度height=100,宽度width=116,精度qulitity=80,新图片的地址newfile,原图的真实宽度abs_width
  445. * @param $original_size 原始的尺寸
  446. * @param $crop_size 裁切的参数,高度,宽度,四点坐标
  447. * @return true/false
  448. */
  449. static function cropImage($image,$params,$original_size,$crop_size)
  450. {
  451. $qulitity = isset($params['qulitity'])?$params['qulitity']:100;
  452. $dst_width = isset($params['width'])?$params['width']:90;
  453. $dst_height = isset($params['height'])?$params['height']:105;
  454. $image = WEBPATH.$image;
  455. if(!file_exists($image))
  456. return '错误,图片不存在!';
  457. $image_info = getimagesize($image);
  458. if($image_info["mime"]=="image/jpeg" || $image_info["mime"]=="image/gif" || $image_info["mime"]=="image/png")
  459. {
  460. /**
  461. * 计算实际裁剪区域,图片是否被缩放,如果不是真实大小,需要计算
  462. */
  463. if(isset($params['abs_width']))
  464. {
  465. $tmp_rate = $params['abs_width'] / $original['width'];
  466. $crop_size['left'] = $crop_size['left'] * $tmp_rate;
  467. $crop_size['top'] = $crop_size['top'] * $tmp_rate;
  468. $crop_size['width'] = $crop_size['width'] * $tmp_rate;
  469. $crop_size['height'] = $crop_size['height'] * $tmp_rate;
  470. }
  471. //裁剪
  472. $image_new = imagecreatetruecolor($dst_width, $dst_height);
  473. switch($image_info["mime"]){
  474. case "image/jpeg":
  475. $bin_ori = imagecreatefromjpeg($image);
  476. break;
  477. case "image/gif":
  478. $bin_ori = imagecreatefromgif($image);
  479. break;
  480. case "image/png":
  481. $bin_ori = imagecreatefrompng($image);
  482. break;
  483. }
  484. imagecopyresampled($image_new, $bin_ori, 0, 0, $crop_size['left'], $crop_size['top'], $dst_width, $dst_height, $crop_size['width'], $crop_size['height']);
  485. $file_new = WEBPATH.$params['newfile'];
  486. if(!file_exists(dirname($file_new))) mkdir(dirname($file_new),0777,true);
  487. return imagejpeg($image_new, $file_new , $qulitity);
  488. }
  489. }
  490. }
  491. function msubstr($str, $start=0, $length, $charset="utf-8", $suffix=true)
  492. {
  493. if(function_exists("mb_substr")){
  494. if ($suffix && strlen($str)>$length)
  495. return mb_substr($str, $start, $length, $charset)."...";
  496. else
  497. return mb_substr($str, $start, $length, $charset);
  498. }
  499. elseif(function_exists('iconv_substr')) {
  500. if ($suffix && strlen($str)>$length)
  501. return iconv_substr($str,$start,$length,$charset)."...";
  502. else
  503. return iconv_substr($str,$start,$length,$charset);
  504. }
  505. $re['utf-8'] = "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xff][\x80-\xbf]{3}/";
  506. $re['gb2312'] = "/[\x01-\x7f]|[\xb0-\xf7][\xa0-\xfe]/";
  507. $re['gbk'] = "/[\x01-\x7f]|[\x81-\xfe][\x40-\xfe]/";
  508. $re['big5'] = "/[\x01-\x7f]|[\x81-\xfe]([\x40-\x7e]|\xa1-\xfe])/";
  509. preg_match_all($re[$charset], $str, $match);
  510. $slice = join("",array_slice($match[0], $start, $length));
  511. if($suffix) return $slice."…";
  512. return $slice;
  513. }
  514. ?>