ChapterToImage.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: tandunzhao
  5. * Date: 2018/1/19
  6. * Time: 上午9:47
  7. */
  8. namespace App\Libs;
  9. use App\Modules\Book\Services\ChapterImageService;
  10. use App\Modules\Book\Services\ChapterService;
  11. use Log;
  12. use Hashids;
  13. class ChapterToImage
  14. {
  15. public static function createChapterImage($bookId, $style = 0,$chapters) {
  16. //$chapters = ChapterService::getTopFiveChapter($bookId);
  17. foreach ($chapters as $chapter) {
  18. //画标题
  19. if(ChapterImageService::getChapterImage($chapter['bid'],[$chapter['id']])->count()){
  20. }else{
  21. self::drawTxt(self::to_unicode($chapter['name']), $chapter['bid'], $chapter['sequence'], $chapter['id'], -1, $style);
  22. $content = str_replace($chapter['name'],'',$chapter['content']);
  23. self::createChapterContentToImage(self::to_unicode($content), $chapter['bid'], $chapter['sequence'], $chapter['id'], $style);
  24. }
  25. }
  26. $imagePath = public_path("chapter");
  27. self::del_dir($imagePath);
  28. }
  29. private static function createChapterContentToImage($inputString, $bookId, $sequence, $chapterId, $style = 0) {
  30. if(!$inputString || empty($inputString)) {
  31. $inputString = "";
  32. }
  33. $inputStrings = explode("\n", $inputString);
  34. $imageIndex = 1;
  35. if(sizeof($inputStrings) < 5) {
  36. self::drawTxt($inputString, $bookId, $sequence, $chapterId, $imageIndex, $style);
  37. } else {
  38. $imageTextString = "";
  39. $index = 1;
  40. foreach ($inputStrings as $strTmp) {
  41. $strTmp = self::trimAllSpace($strTmp);
  42. if($strTmp && !empty($strTmp)) {
  43. $imageTextString .= $strTmp."\n";
  44. if($index % 4 == 0) {
  45. self::drawTxt($imageTextString, $bookId, $sequence, $chapterId, $imageIndex, $style);
  46. $imageIndex++;
  47. $imageTextString = "";
  48. $index = 0;
  49. }
  50. $index++;
  51. } else {
  52. }
  53. }
  54. if(!empty($imageTextString)) {
  55. self::drawTxt($imageTextString, $bookId, $sequence, $chapterId, $imageIndex, $style);
  56. }
  57. }
  58. }
  59. private static function drawTxt($inputString, $bookId, $sequence, $chapterId, $index, $style = 0) {
  60. if(!$inputString || empty($inputString)) {
  61. $inputString = "";
  62. }
  63. $width = 640;
  64. $temp = array("color" => array(1, 1, 1), "font-size" =>32, "width" => $width, "left" => 0, "top" => 15 ,"hang-size" => 35, "duan-size" => 10);
  65. $bg = imagecreatetruecolor($width, 90); // 创建画布
  66. $str_height = self::drawTxtToImage($bg, $temp, $inputString, false);
  67. imagedestroy($bg);
  68. $im = ImageCreate($width, $str_height);
  69. $bgA = imagecolorallocate($im, 255, 255, 255);
  70. $str_h = self::drawTxtToImage($im, $temp, $inputString, true);
  71. $imagePath = public_path("chapter/".$bookId."/".$sequence."/");
  72. $dir = iconv("UTF-8", "UTF-8", $imagePath);
  73. if (!file_exists($dir)){
  74. mkdir ($dir,0777,true);
  75. }
  76. $imagePath .= $index."_".$style."_".time().".jpg";
  77. imagepng($im, $imagePath);
  78. imagedestroy($im);
  79. Log::info($imagePath);
  80. // Log::info("书ID[".$bookId."]章节ID[".$chapterId."] ".$imagePath." ".date("y-m-d H:i:s"."\n"));
  81. $ossPath = "book_chapter_image_new/" . Hashids::encode($bookId) . "/" . $sequence . "/" . $index."_".$style."_".time(). ".jpg";
  82. if(env('PAYMENT_AUTO_PAY_TEST') != 2) {
  83. $ossPath = "book_chapter_image_test/" . Hashids::encode($bookId) . "/" . $sequence . "/" . $index."_".$style."_".time() . ".jpg";
  84. }
  85. $imageUrl = AliOSS::uploadImg($ossPath, $imagePath);
  86. // Log::info("".$imageUrl." ".date("y-m-d H:i:s"."\n"));
  87. $imageUrl = str_ireplace('zhuishuyun.oss-cn-hangzhou.aliyuncs.com','cdn-novel.iycdm.com',$imageUrl);
  88. ChapterImageService::save($bookId, $chapterId, $sequence, $index, $imageUrl);
  89. }
  90. private static function drawTxtToImage($card, $pos, $inputString, $isWrite) {
  91. if(!$inputString || empty($inputString)) {
  92. $inputString = "";
  93. }
  94. $width = $pos["width"];
  95. $fontSize = $pos["font-size"];
  96. $fontFile = self::getFontFile();
  97. $fontColor = imagecolorallocate($card, $pos["color"][0], $pos["color"][1], $pos["color"][2]);
  98. $textOneWidth = self::getTextOneWidth($pos);
  99. $textOneWidthAndPace = self::getTextOneWidthAndPace($pos);
  100. $marginLeft = $pos["left"] + $textOneWidth * 0.5;
  101. $width = $width - $pos["left"] - $textOneWidth;
  102. $duanSize = $pos["duan-size"];
  103. $hangSize = $pos["hang-size"];
  104. $lineTextHeight = self::getTextLineHeight($pos);
  105. $_str_h = $lineTextHeight * 0.8 + $pos["top"];
  106. $textHeight = $pos["top"];
  107. // $textHeight += $hangSize;
  108. // $textHeight += $lineTextHeight;
  109. $inputStrings = explode("\n", $inputString);
  110. foreach ($inputStrings as $strTmp) {
  111. $strTmp = self::trimAllSpace($strTmp);
  112. if(empty($strTmp)) {
  113. continue;
  114. }
  115. //CentOS 服务器上生成图片,一个空格 算一个汉字的长度,暂时测试是这样的
  116. $strTmp = " ".$strTmp;
  117. $drawTextStr = "";
  118. $letter = [];
  119. for ($i=0;$i<mb_strlen($strTmp);$i++) {
  120. $letter[] = mb_substr($strTmp, $i, 1);
  121. }
  122. $ttfText = imagettftext($card, $fontSize, 0, 0, -$lineTextHeight, $fontColor, $fontFile, $strTmp);
  123. // dd($ttfText);
  124. // Log::info("".$ttfText[2]." === ".$strTmp);
  125. if($ttfText[2] <= $width) {
  126. $textHeight += $hangSize;
  127. $textHeight += $lineTextHeight;
  128. $drawTextStr = $strTmp;
  129. } else {
  130. $lineNum = 0;
  131. $content = "";
  132. for ($i=0; $i<sizeof($letter); $i++) {
  133. $content .= $letter[$i];
  134. $ttfText = imagettftext($card, $fontSize, 0, $marginLeft, -$lineTextHeight, $fontColor, $fontFile, $content);
  135. // if(strpos($drawTextStr,"记忆里还有几道模糊的影,") !== false){
  136. // Log::error("图片高度 01 === ".$drawTextStr ." === ". $content . " ".$ttfText[2]." width= ".$width);
  137. // }
  138. // if(strpos($drawTextStr,"心里清楚厉墨风回来过了") !== false){
  139. // Log::error("图片高度 1 === ".$drawTextStr ." === ". $content . " ".$ttfText[2]." width= ".$width);
  140. // Log::error("图片高度 2 === lineNum = ".$lineNum. " (sizeof(letter) = ". sizeof($letter) . " (i + 1) = " .($i + 1). " ".((sizeof($letter) == ($i + 1)) && $lineNum > 0));
  141. // }
  142. if($ttfText[2] > $width) {
  143. // dd($width);
  144. // dd($content);
  145. // dd($ttfText);
  146. $drawTextStr.="\\n";
  147. $textHeight += $hangSize;
  148. $textHeight += $lineTextHeight;
  149. $content = "";
  150. $lineNum++;
  151. if((sizeof($letter) == ($i + 1)) && $lineNum > 0) {
  152. $textHeight += $hangSize;
  153. $textHeight += $lineTextHeight;
  154. $lineNum++;
  155. }
  156. } else {
  157. if((sizeof($letter) == ($i + 1)) && $lineNum > 0) {
  158. $textHeight += $hangSize;
  159. $textHeight += $lineTextHeight;
  160. $lineNum++;
  161. }
  162. }
  163. $drawTextStr .= ($letter[$i]."");
  164. }
  165. }
  166. if ($isWrite) {
  167. $drawTextStrs = explode("\\n", $drawTextStr);
  168. $lineIndex = 0;
  169. foreach ($drawTextStrs as $lee) {
  170. $ttfText = imagettftext($card, $fontSize, 0, $marginLeft, $_str_h, $fontColor, $fontFile, $lee);
  171. $_str_h += $lineTextHeight;
  172. $_str_h += $hangSize;
  173. $lineIndex++;
  174. }
  175. $_str_h += $duanSize;
  176. }
  177. $textHeight += $duanSize;
  178. }
  179. return $textHeight;
  180. }
  181. private static function getTextLineHeight($pos) {
  182. $fontSize = $pos["font-size"];
  183. $fontFile = self::getFontFile();
  184. $ttfBoxTemp = imagettfbbox($fontSize, 0, $fontFile, self::to_unicode("啊"));
  185. $textHeight = $height = ($ttfBoxTemp[3] - $ttfBoxTemp[5]);
  186. return $textHeight;
  187. }
  188. private static function getTextOneWidth($pos) {
  189. $fontSize = $pos["font-size"];
  190. $fontFile = self::getFontFile();
  191. $ttfBoxTemp = imagettfbbox($fontSize, 0, $fontFile, self::to_unicode("啊"));
  192. $textWidth = $width = ($ttfBoxTemp[4] - $ttfBoxTemp[6]);
  193. $textWidth = $textWidth;
  194. return $textWidth;
  195. }
  196. private static function to_unicode($string)
  197. {
  198. // $str = mb_convert_encoding($string, 'UCS-2', 'UTF-8');
  199. // $arrstr = str_split($str, 2);
  200. // $unistr = '';
  201. // foreach ($arrstr as $n) {
  202. // $dec = hexdec(bin2hex($n));
  203. // $unistr .= '&#' . $dec . ';';
  204. // }
  205. // return $unistr;
  206. // $arr = mb_convert_encoding($string, "html-entities","utf-8");
  207. // return $arr;
  208. return $string;
  209. }
  210. private static function getTextOneWidthAndPace($pos) {
  211. $textWidth = self::getTextOneWidth($pos);
  212. $textWidth = $textWidth + $textWidth / 9;
  213. return $textWidth;
  214. }
  215. private static function getFontFile() {
  216. return public_path('fonts/jdytj.TTF');
  217. }
  218. private static function trimAllSpace($str) {
  219. $str = trim($str);
  220. $str = str_replace(" ","",$str);
  221. $str = str_replace(" ","",$str);
  222. $str = str_replace(" ","",$str);
  223. $str = str_replace(" ","",$str);
  224. $str = str_replace(" ","",$str);
  225. $str = str_replace("\t","",$str);
  226. $str = str_replace("\n","",$str);
  227. $str = str_replace(" ","",$str);
  228. $str = preg_replace("/\t/","", $str);
  229. $str = preg_replace("/\r/","",$str);
  230. $str = preg_replace("/\n/","",$str);
  231. $str = preg_replace("/\r\n/","",$str);
  232. $str = preg_replace("/ /","",$str);
  233. $str = preg_replace("/ /","",$str);
  234. $str = preg_replace('/($s*$)|(^s*^)/m', '',$str);
  235. $str = preg_replace("/,/",",", $str);
  236. return trim($str); //返回字符串
  237. }
  238. private static function del_dir($dir) {
  239. //TODO 重要操作,仔细检测
  240. if(strpos($dir, "zhuishuyun/public/chapter") !== false) {
  241. if(strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') {
  242. $str = "rmdir /s/q " . $dir;
  243. } else {
  244. $str = "rm -Rf " . $dir;
  245. }
  246. exec($str);
  247. }
  248. }
  249. }