<?php namespace services\info; use services\CommonService; use services\users\UserService; use setasign\Fpdi\Fpdi; use yii\db\Exception; use yii\helpers\FileHelper; /** * PDF文件处理服务类 * Class Pdf2PicService * @package services\info * @author: luwc * @Time: 2022/2/7 10:45 */ class Pdf2PicService { /** * 将pdf每页转化为图并增加水印(优化版) * @param $pdf_file * @param string $warter_text * @param int $quality * @param string $picExtension * @return string * @throws Exception * @throws \ImagickException * @throws \setasign\Fpdi\PdfParser\CrossReference\CrossReferenceException * @throws \setasign\Fpdi\PdfParser\Filter\FilterException * @throws \setasign\Fpdi\PdfParser\PdfParserException * @throws \setasign\Fpdi\PdfParser\Type\PdfTypeException * @throws \setasign\Fpdi\PdfReader\PdfReaderException * @throws \yii\base\Exception * @author: luwc * @Time: 2022/2/7 9:31 */ public static function pdf2PngAllWarterAndOss( $pdf_file , $warter_text = 'xxxxxxx资料' , $quality = 100, $picExtension = 'png' ) { $path = PROJECT_PATH . "/data/pdftmp/pic/" ; FileHelper::createDirectory(PROJECT_PATH . "/data/pdftmp/" ); FileHelper::createDirectory( $path ); $pdf = new Fpdi(); //获取页数 $pageCount = $pdf ->setSourceFile( $pdf_file ); @ ini_set ( 'memory_limit' , '1024M' ); $ossPath = []; //遍历所有页面 for ( $pageNo = 1; $pageNo <= $pageCount ; $pageNo ++) { //导入页面 $templateId = $pdf ->importPage( $pageNo ); //获取导入页面的大小 $size = $pdf ->getTemplateSize( $templateId ); //创建页面(横向或纵向取决于导入的页面大小) if ( $size [ 'width' ] > $size [ 'height' ]) { $pdf ->AddPage( 'L' , array ( $size [ 'width' ], $size [ 'height' ])); } else { $pdf ->AddPage( 'P' , array ( $size [ 'width' ], $size [ 'height' ])); } echo '第' . $pageNo . '页' . PHP_EOL; $pic = self::pdf2png( $pdf_file , PROJECT_PATH . "/data/pdftmp/pic/" , ( $pageNo - 1), $quality , $picExtension ); if (! empty ( $warter_text )) { $canvas = new \Imagick( $pic ); $width = $canvas ->getImageWidth(); $height = $canvas ->getImageHeight(); $fontsize = 26; $imagickPixel = new \ImagickPixel( 'rgba(204, 204, 204, 0.5)' ); $font = VENDOR_PATH . '/../common/services/font/simsun.ttc' ; for ( $i = 0; $i < ceil ( $height / 96); $i ++) { $x = max([rand(0, $width / 2), rand(0, $width / 2)]) - 48; $y = $i * 200 + 96; $draw = new \ImagickDraw(); $draw ->setFont( $font ); $draw ->setFontSize( $fontsize ); $draw ->setFillColor( $imagickPixel ); $canvas ->annotateImage( $draw , $x , $y , -22, $warter_text ); } $canvas ->writeImage( $pic ); } $fileInfo = pathinfo ( $pic ); $ossPath [] = CommonService::uploadFile( $pic , $fileInfo [ 'basename' ]); } FileHelper::removeDirectory(PROJECT_PATH . "/data/pdftmp/pic/" ); @unlink( $pdf_file ); unset( $pdf ); return $ossPath ; } /** * 处理PDF文件 * 将PDF内容生成图片并将图片传OSS(质量差) * @param $pdf_file * @param string $warter_text * @param int $type * @return array * @throws \Exception * @author: luwc * @Time: 2022/2/7 15:46 */ public static function pdfWarter2PicAndOss( $pdf_file , $warter_text = 'xxxxxx资料' , $type = 2) { try { FileHelper::createDirectory(PROJECT_PATH . "/data/pdftmp/" ); FileHelper::createDirectory(PROJECT_PATH . "/data/pdftmp/pic/" ); $pdf = new Fpdi(); $pdf_new = new Fpdi(); //获取页数 $pageCount = $pdf ->setSourceFile( $pdf_file ); $flag = false; @ ini_set ( 'memory_limit' , '1024M' ); //遍历所有页面 for ( $pageNo = 1; $pageNo <= $pageCount ; $pageNo ++) { //导入页面 $templateId = $pdf ->importPage( $pageNo ); //获取导入页面的大小 $size = $pdf ->getTemplateSize( $templateId ); //创建页面(横向或纵向取决于导入的页面大小) if ( $size [ 'width' ] > $size [ 'height' ]) { $pdf ->AddPage( 'L' , array ( $size [ 'width' ], $size [ 'height' ])); $pdf_new ->AddPage( 'L' , array ( $size [ 'width' ], $size [ 'height' ])); } else { $pdf ->AddPage( 'P' , array ( $size [ 'width' ], $size [ 'height' ])); $pdf_new ->AddPage( 'P' , array ( $size [ 'width' ], $size [ 'height' ])); } echo '第' . $pageNo . '页' . PHP_EOL; $pic = self::pdf2png( $pdf_file , PROJECT_PATH . "/data/pdftmp/pic/" , ( $pageNo - 1), 50); $pdf_new ->Image( $pic , 0, 0, $size [ 'width' ]); if ( $flag === false) { self::pngThumb( $warter_text , $size [ 'width' ] * 25, $size [ 'height' ] * 25); } $flag = true; //使用导入的页面 $pdf ->useTemplate( $templateId ); /*// Set font $pdf->SetFont('Arial', 'B', 16); // Move to 8 cm to the right $pdf->Cell(80); // Centered text in a framed 20*10 mm cell and line break $pdf->Cell(20, 10, 'Title', 1, 1, 'C');*/ if ( $type == 1) { //文字水印 //不能调整角色,放弃它了 //设置字体 //$pdf->SetFont('Arial','B','24'); $family = [ 'courier' , 'helvetica' , 'times' , 'symbol' , 'zapfdingbats' ]; $pdf_new ->SetFont( 'helvetica' , 'U' , '50' ); //设置位置 - 加在中间位置 $center_x = $size [ 'width' ] / 2; $center_y = $size [ 'height' ] / 2; $pdf_new ->SetXY( $center_x - 200, $center_y + 50); //写入水印 - 中文会乱码 建议使用中文图片 $pdf_new ->Write(7, 'ROOT_ICO' ); } else { //图片水印 // $center_x = $size['width'] / 2 - 40; // $center_y = $size['height'] / 2; // $pdf->image(PROJECT_PATH."/public/warter.png", $center_x, $center_y, 80);//中间水印 $pdf_new ->image(PROJECT_PATH . "/data/pdftmp/warter.png" , 0, 0, $size [ 'width' ]); //全屏背景水印 } } unset( $pdf ); // I输出output,D下载download,F保存file_put_contents,S返回return // $pdf->Output('I','测试水印',true); $info = pathinfo ( $pdf_file ); $newFile = $info [ 'dirname' ] . '/1_' . $info [ 'basename' ]; @unlink( $newFile ); $pdf_new ->Output( 'F' , $newFile , true); unset( $pdf_new ); $pdf = new Fpdi(); //获取页数 $pageCount = $pdf ->setSourceFile( $newFile ); @ ini_set ( 'memory_limit' , '1024M' ); //遍历所有页面生成图片地址 $ossPath = []; for ( $pageNo = 1; $pageNo <= $pageCount ; $pageNo ++) { //导入页面 $templateId = $pdf ->importPage( $pageNo ); //获取导入页面的大小 $size = $pdf ->getTemplateSize( $templateId ); //创建页面(横向或纵向取决于导入的页面大小) if ( $size [ 'width' ] > $size [ 'height' ]) { $pdf ->AddPage( 'L' , array ( $size [ 'width' ], $size [ 'height' ])); } else { $pdf ->AddPage( 'P' , array ( $size [ 'width' ], $size [ 'height' ])); } echo '第2-' . $pageNo . '页' . PHP_EOL; $localUrl = self::pdf2png( $newFile , PROJECT_PATH . "/data/pdftmp/pic/" , ( $pageNo - 1), 50); $fileInfo = pathinfo ( $localUrl ); $ossPath [] = CommonService::uploadFile( $localUrl , $fileInfo [ 'basename' ]); } // FileHelper::removeDirectory(PROJECT_PATH . "/data/pdftmp/pic/" ); @unlink(PROJECT_PATH . "/data/pdftmp/warter.png" ); @unlink( $newFile ); @unlink( $pdf_file ); unset( $pdf ); echo '完成' . PHP_EOL; return $ossPath ; } catch (\Exception $e ) { throw new \Exception( $e ->getMessage()); } } /** * 处理PDF文件 * 将PDF内容生成图片并生成新的加密 * @param $pdf_file * @param string $warter_text * @param int $type * @return string * @throws \Exception * @author: luwc * @Time: 2022/2/7 15:46 */ public static function pdfWarter2Pic( $pdf_file , $warter_text = 'xxxxxxx资料' , $type = 2) { try { FileHelper::createDirectory(PROJECT_PATH . "/data/pdftmp/" ); FileHelper::createDirectory(PROJECT_PATH . "/data/pdftmp/pic/" ); $pdf = new Fpdi(); $pdf_new = new Fpdi(); //获取页数 $pageCount = $pdf ->setSourceFile( $pdf_file ); $flag = false; @ ini_set ( 'memory_limit' , '1024M' ); //遍历所有页面 for ( $pageNo = 1; $pageNo <= $pageCount ; $pageNo ++) { //导入页面 $templateId = $pdf ->importPage( $pageNo ); //获取导入页面的大小 $size = $pdf ->getTemplateSize( $templateId ); //创建页面(横向或纵向取决于导入的页面大小) if ( $size [ 'width' ] > $size [ 'height' ]) { $pdf ->AddPage( 'L' , array ( $size [ 'width' ], $size [ 'height' ])); $pdf_new ->AddPage( 'L' , array ( $size [ 'width' ], $size [ 'height' ])); } else { $pdf ->AddPage( 'P' , array ( $size [ 'width' ], $size [ 'height' ])); $pdf_new ->AddPage( 'P' , array ( $size [ 'width' ], $size [ 'height' ])); } echo '第' . $pageNo . '页' . PHP_EOL; $pic = self::pdf2png( $pdf_file , PROJECT_PATH . "/data/pdftmp/pic/" , ( $pageNo - 1), 50); $pdf_new ->Image( $pic , 0, 0, $size [ 'width' ]); if ( $flag === false) { self::pngThumb( $warter_text , $size [ 'width' ] * 25, $size [ 'height' ] * 25); } $flag = true; //使用导入的页面 $pdf ->useTemplate( $templateId ); /*// Set font $pdf->SetFont('Arial', 'B', 16); // Move to 8 cm to the right $pdf->Cell(80); // Centered text in a framed 20*10 mm cell and line break $pdf->Cell(20, 10, 'Title', 1, 1, 'C');*/ if ( $type == 1) { //文字水印 //不能调整角色,放弃它了 //设置字体 //$pdf->SetFont('Arial','B','24'); $family = [ 'courier' , 'helvetica' , 'times' , 'symbol' , 'zapfdingbats' ]; $pdf_new ->SetFont( 'helvetica' , 'U' , '50' ); //设置位置 - 加在中间位置 $center_x = $size [ 'width' ] / 2; $center_y = $size [ 'height' ] / 2; $pdf_new ->SetXY( $center_x - 200, $center_y + 50); //写入水印 - 中文会乱码 建议使用中文图片 $pdf_new ->Write(7, 'ROOT_ICO' ); } else { //图片水印 // $center_x = $size['width'] / 2 - 40; // $center_y = $size['height'] / 2; // $pdf->image(PROJECT_PATH."/public/warter.png", $center_x, $center_y, 80);//中间水印 $pdf_new ->image(PROJECT_PATH . "/data/pdftmp/warter.png" , 0, 0, $size [ 'width' ]); //全屏背景水印 } } unset( $pdf ); // I输出output,D下载download,F保存file_put_contents,S返回return // $pdf->Output('I','测试水印',true); $info = pathinfo ( $pdf_file ); $newFile = $info [ 'dirname' ] . '/1_' . $info [ 'basename' ]; @unlink( $newFile ); $pdf_new ->Output( 'F' , $newFile , true); unset( $pdf_new ); // 安全处理 $pdf_new = new \setasign\Fpdi\Tcpdf\Fpdi(); $pdf_new ->SetAuthor( 'xxxx' , true); $pdf_new ->SetCreator( 'xxx' , true); $pdf_new ->SetSubject( 'xxx' , true); $pdf_new ->SetKeywords( 'xxx' , true); $pdf_new ->SetTitle( $warter_text , true); $pdf_new ->SetCompression(true); $pdf_new ->setSourceFile( $newFile ); $pdf_new ->SetProtection([ 'print' , 'modify' , 'copy' , 'annot-forms' , 'fill-forms' , 'extract' , 'assemble' , 'print-high' ], '' , 'xxxx' ); //遍历所有页面 for ( $pageNo = 1; $pageNo <= $pageCount ; $pageNo ++) { //导入页面 $templateId = $pdf_new ->importPage( $pageNo ); //获取导入页面的大小 $size = $pdf_new ->getTemplateSize( $templateId ); //创建页面(横向或纵向取决于导入的页面大小) if ( $size [ 'width' ] > $size [ 'height' ]) { $pdf_new ->AddPage( 'L' , array ( $size [ 'width' ], $size [ 'height' ])); } else { $pdf_new ->AddPage( 'P' , array ( $size [ 'width' ], $size [ 'height' ])); } //使用导入的页面 $pdf_new ->useTemplate( $templateId ); } $newFile2 = $info [ 'dirname' ] . '/2_' . $info [ 'basename' ]; $pdf_new ->Output( $newFile2 , 'F' ); // FileHelper::removeDirectory(PROJECT_PATH . "/data/pdftmp/pic/" ); @unlink(PROJECT_PATH . "/data/pdftmp/warter.png" ); @unlink( $newFile ); unset( $pdf_new ); // echo '完成' . PHP_EOL; return $newFile2 ; } catch (\Exception $e ) { throw new \Exception( $e ->getMessage()); } } /** * 将某页PDF文件转成图片 * @param $pdf PDF文件绝对路径 * @param $path 图片临时目录 * @param int $page pdf页 * @param int $quality 质量默认100 * @param string $picExtension 图片文件扩展名 * @return array|string * @throws Exception * @throws \ImagickException * @author: luwc * @Time: 2022/1/24 13:18 */ public static function pdf2png( $pdf , $path , $page = 0, $quality = 100, $picExtension = 'jpg' ) { try { $im = new \Imagick(); $im ->setResolution(120, 120); //设置图像分辨率 $im ->setCompressionQuality( $quality ); //压缩比 $im ->readImage( $pdf . "[" . $page . "]" ); //设置读取pdf的第一页 //$im->thumbnailImage(200, 100, true);//改变图像的大小 //$im->scaleImage(200,100,true);//缩放大小图像 $filename = $path . "/" . md5(time()) . '-' . $page . '.' . $picExtension ; if ( $im ->writeImage( $filename ) == true) { $Return = $filename ; } return $Return ; } catch (PDOException $e ) { throw new Exception( '数据处理失败' . $e ->getMessage()); } } /** * 暂没用 * 将pdf转化为一个大长图 * @param $pdf pdf所在路径 (/www/pdf/abc.pdf pdf所在的绝对路径) * @param $path 新生成图片所在路径 (/www/pngs/) * @param int $quality * @param string $picExtension * @return string * @throws \ImagickException * @author: luwc * @Time: 2022/2/7 9:31 */ public static function pdf2PngAll( $pdf , $path , $quality = 100, $picExtension = 'jpg' ) { $im = new \Imagick(); $im ->setCompressionQuality( $quality ); $im ->setResolution(120, 120); //设置分辨率 值越大分辨率越高 $im ->readImage( $pdf ); $canvas = new \Imagick(); $imgNum = $im ->getNumberImages(); foreach ( $im as $k => $sub ) { $sub ->setImageFormat( $picExtension ); //$sub->setResolution(120, 120); $sub ->stripImage(); $sub ->trimImage(0); $width = $sub ->getImageWidth() + 10; $height = $sub ->getImageHeight() + 10; if ( $k + 1 == $imgNum ) { $height += 10; } //最后添加10的height $canvas ->newImage( $width , $height , new \ImagickPixel( 'white' )); $canvas ->compositeImage( $sub , \Imagick::COMPOSITE_DEFAULT, 5, 5); } $canvas ->resetIterator(); $picPath = sprintf( '%s%s.%s' , $path , self::getRandStr(), $picExtension ); $canvas ->appendImages(true)->writeImage( $picPath ); return $picPath ; } /** * 暂没用 * @return false|string * @author: luwc * @Time: 2022/2/7 10:59 */ public static function getRandStr() { $str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890' ; $randStr = str_shuffle ( $str ); //打乱字符串 $rands = substr ( $randStr , 0, 6); return $rands ; } /** * 水印图片 * @param string $warter_text * @param $width * @param $heigh * @author: luwc * @Time: 2022/1/24 12:40 */ public static function pngThumb( $warter_text = 'xxxxx' , $width , $heigh ) { $fontsize = 140; $font = VENDOR_PATH . '/../common/services/font/simsun.ttc' ; $warter = imagecreatetruecolor( $width , $heigh ); $src_white = imagecolorallocatealpha( $warter , 255, 255, 255, 127); imagefill( $warter , 0, 0, $src_white ); //替换成白色 imagecolortransparent( $warter , $src_white ); //将原图颜色替换为透明色 imagealphablending( $warter , false); //这里很重要,意思是不合并颜色,直接用$img图像颜色替换,包括透明色; imagesavealpha( $warter , true); //这里很重要,意思是不要丢了$thumb图像的透明色; $fontcolor = imagecolorallocate( $warter , 204, 204, 204); for ( $i = 0; $i < ceil ( $heigh / 1200); $i ++) { $x = max([rand(0, $width / 2), rand(0, $width / 2)]) - 400; $y = $i * 1200 + 400; imagettftext( $warter , $fontsize , 22, $x , $y , $fontcolor , $font , mb_convert_encoding( $warter_text , 'HTML-ENTITIES' , 'UTF-8' )); } imagepng( $warter , PROJECT_PATH . '/data/pdftmp/warter.png' ); imagedestroy( $warter ); } } |