/** * Paving entry point * Используется для запуска механизма замащивания * @param int $accuracy * @param float|int $partOpacity * @return bool */ public function paving($accuracy = 32, $partOpacity = 1) { if (count($this->segments) == 0) { echo "Segmentation map is empty!\n"; return false; } if (!$this->partRepo) { echo "PartRepo is not defined!\n"; return false; } $segmentsCount = count($this->segments); echo "Paving for " . $segmentsCount . " segments...\n"; $counter = 1; foreach ($this->segments as $segment) { /** @var Segment $segment */ $part = $this->partRepo->findOneWithColorLike($segment->getAvgColor(), $accuracy); if (!$part) { continue; } echo "Found image for {$segment} ({$counter} / {$segmentsCount})\n"; $segment->setPart($part); $tile = new ImagickExt($this->webDir . $part->getPath()); $tile->resizeImage($segment->getEndX() - $segment->getStartX(), $segment->getEndY() - $segment->getStartY(), \Imagick::FILTER_LANCZOS, 1); $tile->setImageOpacity($partOpacity); $this->imagick->compositeImage($tile, \Imagick::COMPOSITE_OVER, $segment->getStartX(), $segment->getStartY()); $counter++; } return true; }
/** * @param InputInterface $input * @param OutputInterface $output * @return int|null|void */ protected function execute(InputInterface $input, OutputInterface $output) { // php app/console gfb:mosaic:create --file="4.jpg" --size=32 --level=2 --accuracy=16 --opacity=0.6 $this->webDir = $this->getContainer()->get("kernel")->getRootDir() . "/../web/"; $this->originsPath = $this->getContainer()->getParameter("gfb_mosaic.origins_dir"); $this->resultsPath = $this->getContainer()->getParameter("gfb_mosaic.results_dir"); $this->basePath = $this->getContainer()->getParameter("gfb_mosaic.base_dir"); $this->output = $output; if (!extension_loaded('imagick')) { $output->writeln("Error: Imagick not found! You should install it!"); return -1; } $mosaicFullPath = $this->webDir . $this->resultsPath; if (!file_exists($mosaicFullPath)) { mkdir($mosaicFullPath, 0777); } if (!is_writable($mosaicFullPath)) { chmod($mosaicFullPath, 0777); } $imagick = new ImagickExt(); $needleFormats = array("JPG", "JPEG", "PNG", "GIF"); $formatsAll = $imagick->queryFormats(); if (count(array_intersect($needleFormats, $formatsAll)) != count($needleFormats)) { $output->writeln("Error: not all the required formats are supported!"); exit; } $name = $input->getOption('file'); $partSize = $input->getOption('size'); $segmentationLevel = $input->getOption("level"); $accuracy = $input->getOption('accuracy'); $partOpacity = $input->getOption("opacity"); $imagick->readImage($this->webDir . $this->originsPath . $name); // Do some magic! try { $processor = new MosaicProcessor($imagick, $this->webDir); $processor->setPartRepo($this->getContainer()->get("doctrine")->getEntityManager()->getRepository("GFBMosaicBundle:Part")); $processor->segmentation($partSize, $segmentationLevel); $processor->paving($accuracy, $partOpacity); $imagick->writeImage($mosaicFullPath . "R" . $name); $markupGen = new MarkupGenerator($this->webDir, $this->basePath); $markupGen->generate($imagick, $this->resultsPath . "R" . $name, $processor->getSegments()); } catch (\Exception $ex) { echo $ex->getMessage() . "\n"; } // Finish some magic! return 0; }
/** * Run markup file generation * Запустить генерацию файла с версткой * @param ImagickExt $imagick * @param string $filePath * @param Segment[] $segments */ public function generate($imagick, $filePath, $segments) { $markup = "\n<style>\n .mosaic_canvas {\n width: 960px;\n margin: 0 auto;\n background-image: url(/{$filePath});\n background-size: 100% auto;\n position: relative;\n }\n\n .mosaic_canvas img {\n width: 100%;\n }\n\n .mosaic_part:hover {\n background: rgba(95, 158, 160, 0.5);\n }\n\n .mosaic_popup {\n margin-left: -210px;\n width: 420px;\n background: #808080;\n padding: 24px;\n display: none;\n position: absolute;\n left: 50%;\n top: 25%;\n }\n\n .mosaic_popup img {\n width: 100%;\n }\n</style>\n "; $markup .= "<div class=\"mosaic_canvas\">"; $markup .= " <img src='/{$filePath}' style='visibility:hidden;'/>"; $cW = $imagick->getWidth(); $cH = $imagick->getHeight(); echo "\nCanvas size : {$cW}x{$cH}\n"; foreach ($segments as $segment) { $markup .= $this->itemCode($cW, $cH, $segment); } $markup .= "</div>"; $markup .= ' <div class="mosaic_popup"> <img src="#"></div> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script> <script> if (window.jQuery != undefined) { $(function() { var $popup = $(".mosaic_popup"); $(".mosaic_canvas .mosaic_part").click(function(event) { event.stopPropagation(); $popup.find("img").attr("src", $(this).data("orig")); $popup.show(); }); $("body").click(function() { $popup.hide(); }); }); } </script> '; file_put_contents($this->webDir . $filePath . ".html", $markup); }
/** * @param array $results * @param string $color */ private function processResults($results, $color) { $em = $this->getEm(); /** @var PartRepo $partRepo */ $partRepo = $em->getRepository("GFBMosaicBundle:Part"); foreach ($results as $imgData) { $code = md5($imgData["imageId"] . $imgData["url"]); $this->output->write(" >>> " . $imgData["url"]); $imagick = new ImagickExt(); try { $imagick->readImage($imgData["url"]); } catch (\Exception $ex) { $this->output->writeln(" [FAIL] "); continue; } $this->output->writeln(" [OK] "); $imagick->cutToSquare(); $imagick->setFormat("png"); $filename = $code . ".png"; $imagick->writeImage($this->webDir . $this->basePath . $filename); $part = $partRepo->findOneByCode($code); if (!$part) { $part = new Part(); } $part->setAvgColor($imagick->getAvgColor())->setCode($code)->setPath($filename)->setWidth($imagick->getWidth())->setHeight($imagick->getHeight())->setColor($color); if ($part->getId() > 0) { $em->merge($part); } else { $em->persist($part); } $em->flush(); } }