container = $container; $this->warehouse = $warehouse; } /** * @param FileItem $fileItem * @return bool * @throws Exception */ public function generate(FileItem $fileItem){ if($fileItem == null) return false; switch($fileItem->getMainMime()){ case 'image': $ret = $this->generateFromImage($fileItem); break; case 'video': $ret = $this->generateVideo($fileItem); break; case 'pdf': $ret = $this->generateFromPdf($fileItem); break; case 'text': // $this->generateFromText($preview,$args);//used to be "text" but till we find some magic cmd line no preview // break; default: $ret = true; //general image } if($ret === false) return false; return true; } /** * @param FileItem $fileItem * @return bool */ public function generateFromImage(FileItem $fileItem):bool{ return $this->mogrify($fileItem,300,300); } /** * @param FileItem $fileItem * @return string */ private function getThumbnailDirectoryForFileItem(FileItem $fileItem){ $directory_storage = substr($fileItem->getGuid(),0,32); if(!is_dir($this->warehouse.DIRECTORY_SEPARATOR.$directory_storage)) mkdir($this->warehouse.DIRECTORY_SEPARATOR.$directory_storage); return $this->warehouse.DIRECTORY_SEPARATOR.$directory_storage; } /** * @param FileItem $fileItem * @return string */ private function getThumbnailFileForFileItem(FileItem $fileItem){ $directory = $this->getThumbnailDirectoryForFileItem($fileItem); return $directory.DIRECTORY_SEPARATOR.$fileItem->getGuid(); } /** * @param FileItem $fileItem * @return string * @throws Exception */ private function getThumbnailTempFile(FileItem $fileItem){ if(!is_dir($this->warehouse.DIRECTORY_SEPARATOR.'tmp')) mkdir($this->warehouse.DIRECTORY_SEPARATOR.'tmp'); return $this->warehouse.DIRECTORY_SEPARATOR.'tmp'.DIRECTORY_SEPARATOR.$fileItem->getGuid(); } /** * @param FileItem $fileItem * @param $width * @param $height * @param int $quality * @param string $otherOriginal * @return bool */ private function mogrify(FileItem $fileItem, $width,$height, $quality = 82, string $otherOriginal = ''):bool { $originalPath = $fileItem->getDownloadPath(); if($otherOriginal != ''){ $originalPath = $otherOriginal; } $destination = $this->getThumbnailDirectoryForFileItem($fileItem); $commandLine = ['mogrify','-path',$destination,'-filter','Triangle','-define','filter:support=2','-thumbnail',$width.'x'.$height,'-unsharp','0.25x0.25+8+0.065','-dither','None','-posterize',136,'-quality',$quality,'-define','jpeg:fancy-upsampling=off','-define','png:compression-filter=5','-define','png:compression-level=9','-define','png:compression-strategy=1','-define','png:exclude-chunk=all','-interlace','none','-colorspace','sRGB','-strip',$originalPath]; $process = new Process($commandLine); $process->run(); $process->wait(); if (!$process->isSuccessful()) { return false; } $fileItem->setThumbnail($this->getThumbnailFileForFileItem($fileItem)); return $this->container->get('net15.file.item.manager')->quickUpdate($fileItem); } /** * @param FileItem $fileItem * @return bool */ public function generateFromPdf(FileItem $fileItem){ return $this->getPdfScreen(0,$fileItem->getPath(),$this->getThumbDirectory(). $this->generateOutputName($fileItem)); } /** * @param FileItem $fileItem * @return bool * @throws Exception */ public function generateVideo(FileItem $fileItem){ $infos = $this->container->get('net15.files.info.details')->getMediaFileInfo($fileItem->getDownloadPath()); $duration = $infos['media']['track'][0]['Duration']*1000; $durationMax = $duration*0.85; $step = $durationMax/2; $time = $this->container->get('net15.files.info.details')->convertMsToTimecode($step); $ret = $this->screenVideoAt($fileItem, $time); return $ret; } /** * @param FileItem $fileItem * @param string $timecode * @return bool * @throws Exception */ public function screenVideoAt(FileItem $fileItem, string $timecode ){ $tempFile = $this->getThumbnailTempFile($fileItem).'.jpg'; $process = new Process(['ffmpeg','-i',$fileItem->getDownloadPath(),'-vframes',1,'-ss',$timecode,$tempFile]); $process->run(); if (!$process->isSuccessful()) { return false; } $fileDestination = str_replace('.jpg','',$tempFile); rename($tempFile, $fileDestination); return $this->mogrify($fileItem,300,300,82, $fileDestination); } /** * generate screen from pdf * * @param $page * @param $file * @param $fileOutput * @return bool */ public function getPdfScreen($page,$file,$fileOutput){ $process = new Process('convert -alpha remove -strip '.$file.'['.$page.'] '.$fileOutput); $process->run(); if (!$process->isSuccessful()) { return false; } return $fileOutput; } /** * @param $file * @param $fileOutput * @return bool */ public function getTextScreen($file,$fileOutput){ $process = new Process('convert -size 1980x1080 xc:white -font "FreeMono" -pointsize 12 -fill black -annotate +15+15 "@'.$file.'" -trim -bordercolor "#FFF" -border 10 +repage '.$fileOutput); $process->run(); if (!$process->isSuccessful()) { return false; } return $fileOutput; } /** * ImageMagick * * @param $fileInput * @param $width * @param $fileOutput * @return bool */ public function resizeImage($fileInput,$width,$fileOutput){ $process = new Process('convert -alpha on "'.$fileInput.'" -quality 75% -resize '.$width.'x1080 "'.$fileOutput.'"'); $process->run(); if (!$process->isSuccessful()) { return false; } return $fileOutput; } /** * rsvg-convert * * @param $fileInput * @param $fileOutput * @return bool */ public function rasterizeSvg($fileInput,$fileOutput){ $process = new Process('rsvg-convert "'.$fileInput.'" -o "'.$fileOutput.'"'); $process->run(); if (!$process->isSuccessful()) { return false; } return $fileOutput; } public function generateOutputName(FileItem $fileItem){ try { return $fileItem->getGuid() . '_' . $this->generateHumanHash(5) . '.jpg'; } catch (Exception $e) { return null; } } /** * @param int $length * @return bool|string * @throws Exception */ private function generateHumanHash($length = 64){ $hash = ""; while(strlen($hash) < $length){ $hash .= hash('sha512', random_bytes($length)); } return substr($hash, 0,$length); } /** * return wich function to use for this content * * @param $mime * @return string */ public function extractMode($mime){ $ret = "default"; if(preg_match('@^video/(.+){1,}$@', $mime)) return "video"; elseif(preg_match('@vnd.adobe.photoshop@i', $mime)) return "default"; elseif(preg_match('@^image/(.+){1,}$@', $mime)) return "image"; elseif(preg_match('@(javascript|xhtml|xml|json|html|plain)@', $mime)) return "text"; elseif ($mime == "application/pdf") return "pdf"; return $ret; } public function generateFromText(FilePreview $filePreview, $args) { if(empty($args)){ $args = array('1080','640','128'); } $p = $filePreview->getMainFile(); $k = $filePreview->createNewKey(); $filePreview->setSelected($k); $filePreview->setThumbContainer($this->getThumbDirectory()); $ext = '.jpg'; $retIn = $this->getTextScreen($p,$this->getThumbDirectory(). $this->generateOutputName().$ext); foreach($args as $q){ $fileOutput = $this->generateOutputName().$ext; $retImMag = $this->resizeImage($retIn,$q,$this->getThumbDirectory().$fileOutput); if(is_string($retImMag)) $filePreview->addInFile($k,$q,$fileOutput); } try { if(!$this->em->contains($filePreview)) $this->em->persist($filePreview); $this->em->flush(); } catch (OptimisticLockException $e) { return false; } catch (ORMException $e) { return false; } return true; } }