Example #1
0
 public function buildContent()
 {
     $RQ = RequestArrayAdapter::inst();
     $mode = $RQ->str('mode', self::MODE_SPRITES_LIST);
     $name = $RQ->str('name');
     $navigation = AdminPageNavigation::inst();
     $sprites = CssSpritesManager::getAllDirsSptites();
     switch ($mode) {
         case self::MODE_SPRITE:
             if (!array_key_exists($name, $sprites)) {
                 $mode = self::MODE_SPRITES_LIST;
                 break;
             }
             $smartyParams['sprite'] = CssSprite::inst($name)->rebuild();
             break;
     }
     switch ($mode) {
         case self::MODE_SPRITES_LIST:
             $navigation->setCurrent('Список спрайтов');
             break;
         case self::MODE_SPRITE:
             $navigation->addPath(self::urlSpritesList(), 'Список спрайтов');
             $navigation->setCurrent($name);
             break;
     }
     $smartyParams['mode'] = $mode;
     $smartyParams['name'] = $name;
     $smartyParams['sprites'] = $sprites;
     return $this->getFoldedEntity()->fetchTpl($smartyParams);
 }
Example #2
0
 public function CreateSprite(CssSprite $sprite)
 {
     if ($sprite->exists()) {
         return;
         //--- Спрайт существует
     }
     $this->LOGGER->info("Waiting to make {$sprite}");
     PsLock::lockMethod(__CLASS__, __FUNCTION__);
     try {
         if ($sprite->exists()) {
             $this->LOGGER->info('Sprite was created in another thread, skipping');
         } else {
             $this->PROFILER->start('Sprite creation');
             $this->CssSpriteGen->CreateSprite($sprite);
             $this->LOGGER->info('Sprite was successfully created, path: ' . $sprite->getCssDi()->getAbsPath());
             $this->PROFILER->stop();
         }
     } catch (Exception $ex) {
         PsLock::unlock();
         throw $ex;
     }
     PsLock::unlock();
 }
Example #3
0
 /** @return CssSprite */
 public static function getSprite($item)
 {
     return CssSprite::inst($item);
 }
Example #4
0
 ini_set('memory_limit', '64M');
 if (!is_dir($dir)) {
     throw new Exception('Images not found - Either you didn\'t upload any or your session expired');
 }
 $padding = isset($_REQUEST['padding']) ? (int) $_REQUEST['padding'] : 3;
 $padding = min(max(0, $padding), 25);
 $type = 'png';
 if (!empty($_REQUEST['output_type']) && in_array($_REQUEST['output_type'], ['jpeg', 'gif'])) {
     $type = $_REQUEST['output_type'];
 }
 $reduceArtefacts = !empty($_REQUEST['jpeg_reduce_artefacts']) && $type == 'jpeg';
 $prefix = '.';
 if (!empty($_REQUEST['css_prefix'])) {
     $prefix .= preg_replace('/[^a-z0-9_-]/ui', '', $_REQUEST['css_prefix']);
 }
 $s = new CssSprite($padding, $reduceArtefacts, $prefix);
 $s->addDirectory($dir);
 $s->pack();
 $options = [];
 if ($type == 'jpeg' && isset($_REQUEST['jpeg_quality'])) {
     $options = [min(100, max(0, (int) $_REQUEST['jpeg_quality']))];
 } elseif ($type == 'png') {
     $options = [9, PNG_ALL_FILTERS];
 }
 $filepath = 'uploads/' . $token . '.' . $type;
 file_put_contents($filepath, $s->getImage($type, $options));
 $server = $_SERVER['HTTP_HOST'] == 'localhost:96' ? 'dev.justsayplease.co.uk:96' : $_SERVER['HTTP_HOST'];
 $response->url = 'http://' . $server . dirname($_SERVER['PHP_SELF']) . '/uploads/' . $token . '.' . $type;
 $response->css = $s->getCss();
 //$s->smush($filepath, $response->url);
 $oldSize = 0;
Example #5
0
                case UPLOAD_ERR_CANT_WRITE:
                    $imageErrors[] = $name . ': Failed to write file to disk.';
                    break;
                case UPLOAD_ERR_EXTENSION:
                    $imageErrors[] = $name . ': File upload stopped by extension.';
                    break;
                default:
                    throw new Exception('Unexpected file error number "' . $_FILES['images']['error'][$i] . '"');
            }
        }
        if (empty($imageErrors)) {
            if (count($images) < 2) {
                $errors['images'] = 'Please select at least 2 image files';
            } else {
                $options = ['output_type' => empty($_POST['output_type']) ? 'png' : $_POST['output_type'], 'jpeg_quality' => !isset($_POST['jpeg_quality']) ? 75 : (int) $_POST['jpeg_quality'], 'css_prefix' => empty($_POST['css_prefix']) ? '' : $_POST['css_prefix'], 'padding' => empty($_POST['padding']) ? 0 : (int) $_POST['padding'], 'jpeg_reduce_artefacts' => !empty($_POST['jpeg_reduce_artefacts'])];
                $sprite = new CssSprite();
                try {
                    $sprite->run($images, $options);
                    $done = true;
                } catch (Exception $e) {
                    $errors['sprite'] = 'There was an error creating your sprite: ' . $e->getMessage();
                }
            }
        } else {
            $errors['images'] = implode(' ', $imageErrors);
        }
    }
}
if ($done) {
    $spriteDataUri = $sprite->getDataUri();
}
Example #6
0
 /** @return CssSprite */
 public function getSprite($ident)
 {
     return $this->isSpritable() ? CssSprite::inst($this->getFoldedEntity($ident)) : null;
 }
function smarty_function_linkup_sprite($params, Smarty_Internal_Template &$smarty)
{
    echo PsHtml::linkCss(CssSprite::inst($params['name'])->getCssDi());
}
Example #8
0
 public function CreateSprite(CssSprite $sprite)
 {
     $images = $sprite->getImages();
     if (empty($images)) {
         return;
         //---
     }
     $name = $sprite->getName();
     $this->aFormValues['class-prefix'] = "sprite-{$name}-";
     $DM = CssSprite::autogenWs(array($name, '.temp'));
     $DM->clearDir();
     //Временная директория, в которой должны содержаться картинки, добавляемые в спрайт
     $sFolderMD5 = ensure_dir_endswith_dir_separator($DM->absDirPath());
     /** @var $img DirItem */
     foreach ($images as $img) {
         $img->copyTo($sFolderMD5 . $img->getName());
     }
     // set up variable defaults used when calculating offsets etc
     $aFilesInfo = array();
     $aFilesMD5 = array();
     $bResize = false;
     if ($this->aFormValues['build-direction'] == 'horizontal') {
         $iRowCount = 1;
         $iTotalWidth = 0;
         $iTotalHeight = 0;
         $aMaxRowHeight = array();
         $iMaxVOffset = 0;
     } else {
         $iColumnCount = 1;
         $iTotalWidth = 0;
         $iTotalHeight = 0;
         $aMaxColumnWidth = array();
         $iMaxHOffset = 0;
     }
     $iMaxWidth = 0;
     $iMaxHeight = 0;
     $i = 0;
     $bValidImages = false;
     $sOutputFormat = strtolower($this->aFormValues['image-output']);
     // read the contents of the directory passed
     $oDir = dir($sFolderMD5);
     /*         * **************************************** */
     /* this section calculates all offsets etc */
     /*         * **************************************** */
     // loop through directory (files will be processed in whatever the OS's default file ordering scheme is)
     // save to array so we can sort alphabetically
     $aFiles = array();
     while (false !== ($sFile = $oDir->read())) {
         $aFiles[] = $sFile;
     }
     sort($aFiles);
     foreach ($aFiles as $sFile) {
         // do we want to scale down the source images
         // scaling up isn't supported as that would result in poorer quality images
         $bResize = $this->aFormValues['width-resize'] != 100 && $this->aFormValues['height-resize'] != 100;
         // grab path information
         $sFilePath = $sFolderMD5 . $sFile;
         $aPathParts = pathinfo($sFilePath);
         // are we matching filenames against a regular expression
         // if so it's likely not all images from the ZIP file will end up in the generated sprite image
         if (!empty($this->aFormValues['file-regex'])) {
             // forward slashes should be escaped - it's likely not doing this might be a security risk also
             // one might be able to break out and change the modifiers (to for example run PHP code)
             $this->aFormValues['file-regex'] = str_replace('/', '\\/', $this->aFormValues['file-regex']);
             // if the regular expression matches grab the first match and store for use as the class name
             if (preg_match('/^' . $this->aFormValues['file-regex'] . '$/i', $sFile, $aMatches)) {
                 $sFileClass = $aMatches[1];
             } else {
                 $sFileClass = '';
             }
         } else {
             // not using regular expressions - set the class name to the base part of the filename (excluding extension)
             $sFileClass = $aPathParts['basename'];
         }
         // format the class name - it should only contain certain characters
         // this strips out any which aren't
         $sFileClass = $this->FormatClassName($sFileClass);
         //$iImageType = exif_imagetype($sFilePath);
         // if we've got an empty class name then the file wasn't valid and shouldn't be included in the sprite image
         // the file also isn't valid if its extension doesn't match one of the image formats supported by the tool
         if (!empty($sFileClass) && isset($aPathParts['extension']) && in_array(strtoupper($aPathParts['extension']), $this->aImageTypes) && substr($sFile, 0, 1) != '.') {
             // grab the file extension
             $sExtension = $aPathParts['extension'];
             // get MD5 of file (this can be used to compare if a file's content is exactly the same as another's)
             $sFileMD5 = md5(file_get_contents($sFilePath));
             // check if this file's MD5 already exists in array of MD5s recorded so far
             // if so it's a duplicate of another file in the ZIP
             if (($sKey = array_search($sFileMD5, $aFilesMD5)) !== false) {
                 // do we want to drop duplicate files and merge CSS rules
                 // if so CSS will end up like .filename1, .filename2 { }
                 if ($this->aFormValues['ignore-duplicates'] == 'merge') {
                     if (isset($aFilesInfo[$sKey]['class'])) {
                         $aFilesInfo[$sKey]['class'] = $aFilesInfo[$sKey]['class'] . $this->aFormValues['selector-suffix'] . ', ' . $this->aFormValues['selector-prefix'] . '.' . $this->aFormValues['class-prefix'] . $sFileClass;
                         continue;
                     }
                 }
             }
             // add MD5 to array to check future files against
             $aFilesMD5[$i] = $sFileMD5;
             // store generated class selector details
             $aFilesInfo[$i]['class'] = ".{$this->aFormValues['class-prefix']}{$sFileClass}";
             // store file path information and extension
             $aFilesInfo[$i]['path'] = $sFilePath;
             $aFilesInfo[$i]['ext'] = $sExtension;
             // get dimensions of image
             $aImageInfo = getimagesize($sFilePath);
             $iWidth = $aImageInfo[0];
             $iHeight = $aImageInfo[1];
             if ($this->aFormValues['build-direction'] == 'horizontal') {
                 // get the current width of the sprite image - after images processed so far
                 $iCurrentWidth = $iTotalWidth + $this->aFormValues['horizontal-offset'] + $iWidth;
                 // store the maximum width reached so far
                 // if we're on a new column current height might be less than the maximum
                 if ($iMaxWidth < $iCurrentWidth) {
                     $iMaxWidth = $iCurrentWidth;
                 }
             } else {
                 // get the current height of the sprite image - after images processed so far
                 $iCurrentHeight = $iTotalHeight + $this->aFormValues['vertical-offset'] + $iHeight;
                 // store the maximum height reached so far
                 // if we're on a new column current height might be less than the maximum
                 if ($iMaxHeight < $iCurrentHeight) {
                     $iMaxHeight = $iCurrentHeight;
                 }
             }
             // store the original width and height of the image
             // we'll need this later if the image is to be resized
             $aFilesInfo[$i]['original-width'] = $iWidth;
             $aFilesInfo[$i]['original-height'] = $iHeight;
             // store the width and height of the image
             // if we're resizing they'll be less than the original
             $aFilesInfo[$i]['width'] = $bResize ? round($iWidth / 100 * $this->aFormValues['width-resize']) : $iWidth;
             $aFilesInfo[$i]['height'] = $bResize ? round($iHeight / 100 * $this->aFormValues['height-resize']) : $iHeight;
             if ($this->aFormValues['build-direction'] == 'horizontal') {
                 // opera (9.0 and below) has a bug which prevents it recognising  offsets of less than -2042px
                 // all subsequent values are treated as -2042px
                 // if we've hit 2000 pixels and we care about this (as set in the interface) then wrap to a new row
                 // increment row count and reset current height
                 if ($iTotalWidth + $this->aFormValues['horizontal-offset'] >= 2000 && !empty($this->aFormValues['wrap-columns'])) {
                     $iRowCount++;
                     $iTotalWidth = 0;
                 }
                 // if the current image is higher than any other in the current row then set the maximum height to that
                 // it will be used to set the height of the current row
                 if ($aFilesInfo[$i]['height'] > $iMaxHeight) {
                     $iMaxHeight = $aFilesInfo[$i]['height'];
                 }
                 // keep track of the height of rows added so far
                 $aMaxRowHeight[$iRowCount] = $iMaxHeight;
                 // calculate the current maximum vertical offset so far
                 $iMaxVOffset = $this->aFormValues['vertical-offset'] * ($iRowCount - 1);
                 // get the x position of current image in overall sprite
                 $aFilesInfo[$i]['x'] = $iTotalWidth;
                 $iTotalWidth += $aFilesInfo[$i]['width'] + $this->aFormValues['horizontal-offset'];
                 // get the y position of current image in overall sprite
                 if ($iRowCount == 1) {
                     $aFilesInfo[$i]['y'] = 0;
                 } else {
                     $aFilesInfo[$i]['y'] = $this->aFormValues['vertical-offset'] * ($iRowCount - 1) + (array_sum($aMaxRowHeight) - $aMaxRowHeight[$iRowCount]);
                 }
                 $aFilesInfo[$i]['currentCombinedWidth'] = $iTotalWidth;
                 $aFilesInfo[$i]['rowNumber'] = $iRowCount;
             } else {
                 if ($iTotalHeight + $this->aFormValues['vertical-offset'] >= 2000 && !empty($this->aFormValues['wrap-columns'])) {
                     $iColumnCount++;
                     $iTotalHeight = 0;
                 }
                 // if the current image is wider than any other in the current column then set the maximum width to that
                 // it will be used to set the width of the current column
                 if ($aFilesInfo[$i]['width'] > $iMaxWidth) {
                     $iMaxWidth = $aFilesInfo[$i]['width'];
                 }
                 // keep track of the width of columns added so far
                 $aMaxColumnWidth[$iColumnCount] = $iMaxWidth;
                 // calculate the current maximum horizontal offset so far
                 $iMaxHOffset = $this->aFormValues['horizontal-offset'] * ($iColumnCount - 1);
                 // get the y position of current image in overall sprite
                 $aFilesInfo[$i]['y'] = $iTotalHeight;
                 $iTotalHeight += $aFilesInfo[$i]['height'] + $this->aFormValues['vertical-offset'];
                 // get the x position of current image in overall sprite
                 if ($iColumnCount == 1) {
                     $aFilesInfo[$i]['x'] = 0;
                 } else {
                     $aFilesInfo[$i]['x'] = $this->aFormValues['horizontal-offset'] * ($iColumnCount - 1) + (array_sum($aMaxColumnWidth) - $aMaxColumnWidth[$iColumnCount]);
                 }
                 $aFilesInfo[$i]['currentCombinedHeight'] = $iTotalHeight;
                 $aFilesInfo[$i]['columnNumber'] = $iColumnCount;
             }
             $i++;
         }
     }
     // close the dir handle
     $oDir->close();
     /*         * **************************************** */
     /* this section generates the sprite image */
     /* and CSS rules                           */
     /*         * **************************************** */
     // if $i is greater than 1 then we managed to generate enough info to create a sprite
     if ($i > 1) {
         // if Imagick throws an exception we want the script to terminate cleanly so that
         // temporary files are cleaned up
         try {
             // get the sprite width and height
             if ($this->aFormValues['build-direction'] == 'horizontal') {
                 $iSpriteWidth = $iMaxWidth - $this->aFormValues['horizontal-offset'];
                 $iSpriteHeight = array_sum($aMaxRowHeight) + $iMaxVOffset;
             } else {
                 $iSpriteHeight = $iMaxHeight - $this->aFormValues['vertical-offset'];
                 $iSpriteWidth = array_sum($aMaxColumnWidth) + $iMaxHOffset;
             }
             // get background colour - remove # if added
             $sBgColour = str_replace('#', '', $this->aFormValues['background']);
             // convert 3 digit hex values to 6 digit equivalent
             if (strlen($sBgColour) == 3) {
                 $sBgColour = substr($sBgColour, 0, 1) . substr($sBgColour, 0, 1) . substr($sBgColour, 1, 1) . substr($sBgColour, 1, 1) . substr($sBgColour, 2, 1) . substr($sBgColour, 2, 1);
             }
             // should the image be transparent
             $this->bTransparent = !empty($this->aFormValues['use-transparency']) && in_array($this->aFormValues['image-output'], array('GIF', 'PNG'));
             // if using Imagick library create new instance of library class
             if ($this->sImageLibrary == 'imagick') {
                 $oSprite = new Imagick();
                 // create a new image - set background according to transparency
                 if (!empty($this->aFormValues['background'])) {
                     $oSprite->newImage($iSpriteWidth, $iSpriteHeight, new ImagickPixel("#{$sBgColour}"), $sOutputFormat);
                 } else {
                     if ($this->bTransparent) {
                         $oSprite->newImage($iSpriteWidth, $iSpriteHeight, new ImagickPixel('#000000'), $sOutputFormat);
                     } else {
                         $oSprite->newImage($iSpriteWidth, $iSpriteHeight, new ImagickPixel('#ffffff'), $sOutputFormat);
                     }
                 }
             } else {
                 // using GD - do the same thing
                 if ($this->bTransparent && !empty($this->aFormValues['background'])) {
                     $oSprite = imagecreate($iSpriteWidth, $iSpriteHeight);
                 } else {
                     $oSprite = imagecreatetruecolor($iSpriteWidth, $iSpriteHeight);
                 }
             }
             // check for transparency option
             if ($this->bTransparent) {
                 if ($this->sImageLibrary == 'imagick') {
                     // set background colour to transparent
                     // if no background colour use black
                     if (!empty($this->aFormValues['background'])) {
                         $oSprite->paintTransparentImage(new ImagickPixel("#{$sBgColour}"), 0.0, 0);
                     } else {
                         $oSprite->paintTransparentImage(new ImagickPixel("#000000"), 0.0, 0);
                     }
                 } else {
                     // using GD - do the same thing
                     if (!empty($this->aFormValues['background'])) {
                         $iBgColour = hexdec($sBgColour);
                         $iBgColour = imagecolorallocate($oSprite, 0xff & $iBgColour >> 0x10, 0xff & $iBgColour >> 0x8, 0xff & $iBgColour);
                         imagecolortransparent($oSprite, $iBgColour);
                     } else {
                         imagealphablending($oSprite, false);
                         imagesavealpha($oSprite, true);
                         $col = imagecolorallocatealpha($oSprite, 255, 255, 255, 127);
                         imagefill($oSprite, 0, 0, $col);
                     }
                 }
             } else {
                 // set background colour if not using transparency and using GD
                 if ($this->sImageLibrary != 'imagick') {
                     if (empty($sBgColour)) {
                         $sBgColour = 'ffffff';
                     }
                     $iBgColour = hexdec($sBgColour);
                     $iBgColour = imagecolorallocate($oSprite, 0xff & $iBgColour >> 0x10, 0xff & $iBgColour >> 0x8, 0xff & $iBgColour);
                     imagefill($oSprite, 0, 0, $iBgColour);
                 }
             }
             // initalise variable to store CSS rules
             $this->sCss = ".sprite-{$name} {background-image: url({$name}.{$sOutputFormat});}\n";
             // loop through file info for valid images
             for ($i = 0; $i < count($aFilesInfo); $i++) {
                 // create a new image object for current file
                 if (!($oCurrentImage = $this->CreateImage($aFilesInfo[$i]['path'], $aFilesInfo[$i]['ext']))) {
                     // if we've got here then a valid but corrupt image was found
                     // at this stage we've already allocated space for the image so create
                     // a blank one to fill the space instead
                     // this should happen very rarely
                     $oCurrentImage = new Imagick();
                     $oCurrentImage->newImage($aFilesInfo[$i]['original-width'], $aFilesInfo[$i]['original-height'], new ImagickPixel('#ffffff'));
                 }
                 // if resizing get image width and height and resample to new dimensions (percentage of original)
                 // and copy to sprite image
                 if ($bResize) {
                     if ($this->sImageLibrary == 'imagick') {
                         // resample image should work but doesn't seem to - using thumbnailImage instead
                         // which achieves the same effect
                         $oCurrentImage->thumbnailImage($aFilesInfo[$i]['width'], $aFilesInfo[$i]['height']);
                     } else {
                         imagecopyresampled($oSprite, $oCurrentImage, $aFilesInfo[$i]['x'], $aFilesInfo[$i]['y'], 0, 0, $aFilesInfo[$i]['width'], $aFilesInfo[$i]['height'], $aFilesInfo[$i]['original-width'], $aFilesInfo['original-height']);
                     }
                 }
                 // copy image to sprite
                 if ($this->sImageLibrary == 'imagick') {
                     $oSprite->compositeImage($oCurrentImage, $oCurrentImage->getImageCompose(), $aFilesInfo[$i]['x'], $aFilesInfo[$i]['y']);
                 } else {
                     // if using GD and already resized the image will have been copied as part of the resize
                     if (!$bResize) {
                         imagecopy($oSprite, $oCurrentImage, $aFilesInfo[$i]['x'], $aFilesInfo[$i]['y'], 0, 0, $aFilesInfo[$i]['width'], $aFilesInfo[$i]['height']);
                     }
                 }
                 // get CSS x & y values
                 $iX = $aFilesInfo[$i]['x'] != 0 ? '-' . $aFilesInfo[$i]['x'] . 'px' : '0';
                 $iY = $aFilesInfo[$i]['y'] != 0 ? '-' . $aFilesInfo[$i]['y'] . 'px' : '0';
                 // create CSS rules and append to overall CSS rules
                 $this->sCss .= "{$this->aFormValues['selector-prefix']}{$aFilesInfo[$i]['class']} {$this->aFormValues['selector-suffix']}{background-position: {$iX} {$iY}; ";
                 // If add widths and heights the sprite image width and height are added to the CSS
                 if ($this->aFormValues['add-width-height-to-css'] == 'on') {
                     $this->sCss .= "width: {$aFilesInfo[$i]['width']}px; height: {$aFilesInfo[$i]['height']}px;";
                 }
                 $this->sCss .= "} \n";
                 // destroy object created for current image to save memory
                 if ($this->sImageLibrary == 'imagick') {
                     $oCurrentImage->destroy();
                 } else {
                     imagedestroy($oCurrentImage);
                 }
             }
             // path to sprite img
             $imgDestPath = $sprite->getImgDi()->getAbsPath();
             // write image to file (deleted by cron script after a limited time period)
             $this->WriteImage($oSprite, $sOutputFormat, $imgDestPath);
             // destroy object created for sprite image to save memory
             if ($this->sImageLibrary == 'imagick') {
                 $oSprite->destroy();
             } else {
                 imagedestroy($oSprite);
             }
             // set flag to indicate valid images created
             $this->bValidImages = true;
             //Сохраним .css
             $sprite->getCssDi()->writeToFile($this->sCss, true);
         } catch (ImagickException $e) {
             error_log($e->getMessage());
         }
     }
     //Очистим временную директорию
     $DM->clearDir(null, true);
 }