Source of file api.pixelcraft.php
Size: 26,001 Bytes - Last Modified: 2024-04-27T15:26:05+03:00
/tmp/current_snapshot/api/libs/api.pixelcraft.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879 | <?php /** * PixelCraft is a lightweight PHP library designed for easy image processing using the GD lib. * With PixelCraft, you can perform basic image operations such as resizing, cropping, drawing of watermarks, and format conversion. * The library is characterized by its user-friendly interface and minimal code footprint, * allowing for quick and efficient image processing in PHP projects. * * @package PixelCraft * @author Rostyslav Haitkulov <info@ubilling.net.ua> * @see https://github.com/nightflyza/PixelCraft * @license MIT */ class PixelCraft { /** * Contains image copy to perform some magic on it * * @var GDimage */ protected $image = ''; /** * Contains image rendering quality * * @var int */ protected $quality = -1; /** * Contains loaded image mime type * * @var string */ protected $imageType = ''; /** * Contains loaded image original width * * @var int */ protected $imageWidth = 0; /** * Contains loaded image original height * * @var int */ protected $imageHeight = 0; /** * Contains array of custom RGB colors palette as name=>color * * @var array */ protected $colorPalette = array(); /** * Contains already allocated image colors as name=>colorInt * * @var array */ protected $colorsAllocated = array(); /** * TTF font path * * @var string */ protected $font = 'skins/OpenSans-Regular.ttf'; /** * Font size in pt. * * @var int */ protected $fontSize = 10; /** * Drawing line width in px * * @var int */ protected $lineWidth = 1; /** * Contains watermark image copy * * @var GDimage */ protected $watermark = ''; /** * Schweigen im wald */ public function __construct() { $this->setDefaultColors(); } /** * Sets few default colors to palette * * @return void */ protected function setDefaultColors() { $this->addColor('white', 255, 255, 255); $this->addColor('black', 0, 0, 0); $this->addColor('red', 255, 0, 0); $this->addColor('green', 0, 255, 0); $this->addColor('blue', 0, 0, 255); $this->addColor('yellow', 255, 255, 0); $this->addColor('grey', 85, 85, 85); } /** * Sets current instance image save/render quality * * @param int $quality Deafult -1 means IJG quality value for jpeg or default zlib for png * * @return void */ public function setQuality($quality) { if (is_int($quality)) { $this->quality = $quality; } } /** * Set TTF font path * * @param string $font TTF font path * * @return void */ public function setFont($font) { $this->font = $font; } /** * Set font size in pt. * * @param int $fontSize Font size in pt. * * @return void */ public function setFontSize($fontSize) { $this->fontSize = $fontSize; } /** * Returns current image width * * @return int */ public function getImageWidth() { return ($this->imageWidth); } /** * Returns current image height * * @return int */ public function getImageHeight() { return ($this->imageHeight); } /** * Returns loaded image type * * @return string */ public function getImageType() { return ($this->imageType); } /** * Returns specified image * * @param string $filePath * * @return array */ protected function getImageParams($filePath) { return (@getimagesize($filePath)); } /** * Creates or replaces RGB color in palette * * @param string $colorName * @param int $r * @param int $g * @param int $b * * @return void */ public function addColor($colorName, $r, $g, $b) { $this->colorPalette[$colorName] = array('r' => $r, 'g' => $g, 'b' => $b); } /** * Checks is some image valid? * * @param string $filePath * @param array $imageParams * * @return bool */ public function isImageValid($filePath = '', $imageParams = array()) { $result = false; if (empty($imageParams) and !empty($filePath)) { $imageParams = $this->getImageParams($filePath); } if (is_array($imageParams)) { if (isset($imageParams['mime'])) { if (strpos($imageParams['mime'], 'image/') !== false) { $result = true; } } } return ($result); } /** * Returns image type name * * @param string $filePath * @param array $imageParams * * @return string */ protected function detectImageType($filePath = '', $imageParams = array()) { $result = ''; if ($this->isImageValid($filePath, $imageParams)) { if (empty($imageParams) and !empty($filePath)) { $imageParams = $this->getImageParams($filePath); } if (is_array($imageParams)) { $imageType = $imageParams['mime']; $imageType = str_replace('image/', '', $imageType); $result = $imageType; } } return ($result); } /** * Loads some image into protected property from file * * @param string $fileName readable image file path * @return bool */ protected function loadImageFile($filePath, $propertyName = 'image') { $result = false; $imageParams = $this->getImageParams($filePath); $imageType = $this->detectImageType('', $imageParams); if (!empty($imageType)) { $loaderFunctionName = 'imagecreatefrom' . $imageType; if (function_exists($loaderFunctionName)) { $this->$propertyName = $loaderFunctionName($filePath); //setting loaded image base props if ($this->$propertyName != false) { if ($propertyName == 'image') { $this->imageWidth = $imageParams[0]; $this->imageHeight = $imageParams[1]; $this->imageType = $imageType; } $result = true; } } else { throw new Exception('EX_NOT_SUPPORTED_FILETYPE:' . $imageType); } } return ($result); } /** * Loads some image into protected property from file * * @param string $fileName readable image file path * @return bool */ public function loadImage($filePath) { $result = $this->loadImageFile($filePath, 'image'); return ($result); } /** * Loads a instance image from an base64 encoded image string. * * @param string $encodedImage The encoded image string. * @param string $propertyName The name of the property to store the image in. Default is 'image'. * * @return bool Returns true if the base image is successfully loaded, false otherwise. */ public function loadBaseImage($encodedImage, $propertyName = 'image') { $result = false; if (!empty($encodedImage)) { $decodedImage = base64_decode($encodedImage); if ($decodedImage) { $imageParams = getimagesizefromstring($decodedImage); $imageType = $this->detectImageType('', $imageParams); if (!empty($imageType)) { $this->$propertyName = imagecreatefromstring($decodedImage); if ($this->$propertyName != false) { if ($propertyName == 'image') { $this->imageWidth = $imageParams[0]; $this->imageHeight = $imageParams[1]; $this->imageType = $imageType; } $result = true; } } } } return ($result); } /** * Loads some watermark image into protected property from file * * @param string $fileName readable image file path * @return bool */ public function loadWatermark($filePath) { $result = $this->loadImageFile($filePath, 'watermark'); if ($result) { imagealphablending($this->watermark, false); } return ($result); } /** * Renders current instance image into browser or specified file path * * @param string $fileName writable file path with name or null to browser rendering * @param string $type image type to save, like jpeg, png, gif... * * @return bool */ public function saveImage($fileName = null, $type) { $result = false; if ($this->image) { $saveFunctionName = 'image' . $type; if (function_exists($saveFunctionName)) { //custom header on browser output if (!$fileName) { header('Content-Type: image/' . $type); } if ($type == 'jpeg' or $type == 'png') { if ($type == 'png') { imagesavealpha($this->image, true); } $result = $saveFunctionName($this->image, $fileName, $this->quality); } else { $result = $saveFunctionName($this->image, $fileName); } //memory free imagedestroy($this->image); //droppin image props $this->imageWidth = 0; $this->imageHeight = 0; $this->imageType = ''; //nothing else matters if ($fileName === false) { die(); } } else { throw new Exception('EX_NOT_SUPPORTED_FILETYPE:' . $type); } } else { throw new Exception('EX_VOID_IMAGE'); } return ($result); } /** * Returns current instance image as base64 encoded text * * @param string $type image mime type * @param bool $htmlData data ready to embed as img src HTML base64 data (data URI scheme) * * @return void */ public function getImageBase($type = 'png', $htmlData = false) { $result = ''; if ($this->image) { $saveFunctionName = 'image' . $type; if (function_exists($saveFunctionName)) { ob_start(); if ($type == 'jpeg' or $type == 'png') { if ($type == 'png') { imagesavealpha($this->image, true); } } $result = $saveFunctionName($this->image, null, $this->quality); //memory free imagedestroy($this->image); //droppin image props $this->imageWidth = 0; $this->imageHeight = 0; $this->imageType = ''; $imageBody = ob_get_contents(); ob_end_clean(); if (!empty($imageBody)) { $result = base64_encode($imageBody); // print($imageBody); } //optional html embed data if ($htmlData) { $result = 'data:image/' . $type . ';charset=utf-8;base64,' . $result; } } else { throw new Exception('EX_NOT_SUPPORTED_FILETYPE:' . $type); } } else { throw new Exception('EX_VOID_IMAGE'); } return ($result); } /** * Renders current instance image into browser * * @param string $type * * @return void */ public function renderImage($type = 'png') { $this->saveImage(null, $type); } /** * Creates new empty true-color image * * @return void */ public function createImage($width, $height) { $this->image = imagecreatetruecolor($width, $height); $this->imageWidth = $width; $this->imageHeight = $height; } /** * Scales image to some scale * * @param float $scale something like 0.5 for 50% or 2 for 2x scale * * @return void */ public function scale($scale) { if ($this->imageWidth and $this->imageHeight) { if ($scale != 1) { $nWidth = $this->imageWidth * $scale; $nHeight = $this->imageHeight * $scale; $imageCopy = imagecreatetruecolor($nWidth, $nHeight); imagealphablending($imageCopy, false); imagesavealpha($imageCopy, true); imagecopyresized($imageCopy, $this->image, 0, 0, 0, 0, $nWidth, $nHeight, $this->imageWidth, $this->imageHeight); $this->image = $imageCopy; $this->imageWidth = $nWidth; $this->imageHeight = $nHeight; } } } /** * Resizes image to some new dimensions * * @param int $width * @param int $height * * @return void */ public function resize($width, $height) { if ($this->imageWidth and $this->imageHeight) { $imageResized = imagescale($this->image, $width, $height); $this->image = $imageResized; $this->imageWidth = $width; $this->imageHeight = $height; } } /** * Crops image to new dimensions starting from 0x0 * * @return void */ public function crop($width, $height) { if ($this->imageWidth and $this->imageHeight) { $imageCropped = imagecrop($this->image, array('x' => 0, 'y' => 0, 'width' => $width, 'height' => $height)); $this->image = $imageCropped; $this->imageWidth = $width; $this->imageHeight = $height; } } /** * Crops image to selected region by coords * * @return void */ public function cropRegion($x1, $y1, $x2, $y2) { if ($this->imageWidth and $this->imageHeight) { $imageCropped = imagecrop($this->image, array('x' => $x1, 'y' => $y1, 'width' => $x2, 'height' => $y2)); $this->image = $imageCropped; $this->imageWidth = $x2; $this->imageHeight = $y2; } } /** * Allocates and returns some image color by its name * * @param string $colorName * * @return int */ protected function allocateColor($colorName) { $result = 0; if (isset($this->colorPalette[$colorName])) { $colorData = $this->colorPalette[$colorName]; if (isset($this->colorsAllocated[$colorName])) { $result = $this->colorsAllocated[$colorName]; } else { $result = imagecolorallocate($this->image, $colorData['r'], $colorData['g'], $colorData['b']); $this->colorsAllocated[$colorName] = $result; } } else { throw new Exception('EX_COLOR_NOT_EXISTS:' . $colorName); } return ($result); } /** * Fills image with some color from palette * * @param string $colorName * * @return void */ public function fill($colorName) { imagefill($this->image, 0, 0, $this->allocateColor($colorName)); } /** * Draws pixel on X/Y coords with some color from palette * * @param int y * @param int x * @param string $colorName * * @return void */ public function drawPixel($x, $y, $colorName) { imagesetpixel($this->image, $x, $y, $this->allocateColor($colorName)); } /** * Prints some text string at specified X/Y coords with default font * * @param int $x * @param int $y * @param string $text * @param string $colorName * @param int $size=1 * @param bool $vertical * * @return void */ public function drawString($x, $y, $text, $colorName, $size = 1, $vertical = false) { if (!empty($text)) { if ($vertical) { imagestringup($this->image, $size, $x, $y, $text, $this->allocateColor($colorName)); } else { imagestring($this->image, $size, $x, $y, $text, $this->allocateColor($colorName)); } } } /** * Write text to the image using TrueType fonts * * @param int $x * @param int $y * @param string $text * @param string $colorName * * @return void */ public function drawText($x, $y, $text, $colorName) { if (!empty($text)) { imagettftext($this->image, $this->fontSize, 0, $x, $y, $this->allocateColor($colorName), $this->font, $text); } } /** * Returns font size that fits into image width * * @param int $fontSize font size that required to fit text * @param string $text text data that required to fit * @param int $padding text padding in px * * @return int */ protected function guessFontSize($fontSize, $text, $padding) { $box = imageftbbox($fontSize, 0, $this->font, $text); $boxWidth = $box[4] - $box[6]; $imageWidth = $this->imageWidth - ($padding * 2); if ($boxWidth > $imageWidth) { $fontSize = $fontSize - 1; return $this->guessFontSize($fontSize, $text, $padding); } return ($fontSize); } /** * Write single text to the image using TrueType font with auto size selection * * @param int $y * @param int $padding * @param string $text * @param string $colorName * @param string $outlineColor * * @return void */ public function drawTextAutoSize($y, $padding = 10, $text, $colorName, $outlineColor = '') { if (!empty($text)) { $defaultFontSize = 40; $border = 1; $x = $padding; //guessing font size $fontSize = $this->guessFontSize($defaultFontSize, $text, $padding); //drawing outline if required if ($outlineColor) { for ($c1 = ($x - abs($border)); $c1 <= ($x + abs($border)); $c1++) { for ($c2 = ($y - abs($border)); $c2 <= ($y + abs($border)); $c2++) { imagettftext($this->image, $fontSize, 0, $c1, $c2, $this->allocateColor($outlineColor), $this->font, $text); } } } //and text with selected color imagettftext($this->image, $fontSize, 0, $x, $y, $this->allocateColor($colorName), $this->font, $text); } } /** * Set the thickness for line drawing in px * * @param int $lineWidth * * @return void */ public function setLineWidth($lineWidth) { $this->lineWidth = $lineWidth; imagesetthickness($this->image, $this->lineWidth); } /** * Draws filled rectangle * * @param int $x1 * @param int $y1 * @param int $x2 * @param int $y2 * @param string $colorName * * @return void */ public function drawRectangle($x1, $y1, $x2, $y2, $colorName) { if (isset($this->colorPalette[$colorName])) { $colorData = $this->colorPalette[$colorName]; if (isset($this->colorsAllocated[$colorName])) { $drawingColor = $this->colorsAllocated[$colorName]; } else { $drawingColor = imagecolorallocate($this->image, $colorData['r'], $colorData['g'], $colorData['b']); $this->colorsAllocated[$colorName] = $drawingColor; } imagefilledrectangle($this->image, $x1, $y1, $x2, $y2, $drawingColor); } else { throw new Exception('EX_COLOR_NOT_EXISTS:' . $colorName); } } /** * Draws a line * * @param int $x1 * @param int $y1 * @param int $x2 * @param int $y2 * @param string $colorName * * @return void */ public function drawLine($x1, $y1, $x2, $y2, $colorName) { imageline($this->image, $x1, $y1, $x2, $y2, $this->allocateColor($colorName)); } /** * Puts preloaded watermark on base image * * @param int $stretch=true * @param int $x=0 * @param int $y=0 * * @return void */ public function drawWatermark($stretch = true, $x = 0, $y = 0) { imagealphablending($this->watermark, false); $watermarkWidth = imagesx($this->watermark); $watermarkHeight = imagesy($this->watermark); if ($stretch) { imagecopyresampled($this->image, $this->watermark, $x, $y, 0, 0, $this->imageWidth, $this->imageHeight, $watermarkWidth, $watermarkHeight); } else { imagecopy($this->image, $this->watermark, $x, $y, 0, 0, $watermarkWidth, $watermarkHeight); } } /** * Applies pixelation filter * * @param int $blockSize * @param bool $smooth * * @return void */ public function pixelate($blockSize, $smooth = true) { imagefilter($this->image, IMG_FILTER_PIXELATE, $blockSize, $smooth); } /** * Applies image filters set to current instance base image * * @param array|int $filterSet must contains array of filters as index=>(IMAGE_FILTER=>argsArray) * * @return void */ public function imageFilters($filterSet = array()) { if (!empty($filterSet)) { foreach ($filterSet as $eachFilterIdx => $eachFilterData) { if (is_array($eachFilterData)) { foreach ($eachFilterData as $eachFilter => $eachFilterArgs/* */) { if (is_array($eachFilterArgs)) { $filterArgsTmp = array(); $filterArgsTmp[] = $this->image; $filterArgsTmp[] = $eachFilter; foreach ($eachFilterArgs as $io => $each) { $filterArgsTmp[] = $each; } //not using just "..." arg unpack operator here due PHP <5.6 compat call_user_func_array('imagefilter', $filterArgsTmp); } else { imagefilter($this->image, $eachFilter, $eachFilterArgs); } } } } } } /** * Returns RGB values for some specified image pixel as r/g/b/a(lpha) * * @return array */ public function getPixelColor($x, $y) { $result = array(); $rgb = imagecolorat($this->image, $x, $y); $components = imagecolorsforindex($this->image, $rgb); $result['r'] = $components['red']; $result['g'] = $components['green']; $result['b'] = $components['blue']; $result['a'] = $components['alpha']; return ($result); } /** * Converts RGB components array into hex string * * @param array $rgb RGB/RGBa components array * * @return string */ public function rgbToHex($rgb) { $result = ''; if (!empty($rgb)) { $result = sprintf("#%02x%02x%02x", $rgb['r'], $rgb['g'], $rgb['b']); } return ($result); } /** * Converts hex color string to RGB components array * * @param string $hex hex string as RRGGBB * * @return array */ public function hexToRgb($hex) { $result = ''; if (!empty($hex)) { $hex = str_replace('#', '', $hex); $r = hexdec(substr($hex, 0, 2)); $g = hexdec(substr($hex, 2, 2)); $b = hexdec(substr($hex, 4, 2)); $result = array('r' => $r, 'g' => $g, 'b' => $b); } return ($result); } /** * Calculates the brightness value of an RGB color. * * @param array $rgb The RGB color values as an associative array with keys 'r', 'g', and 'b'. * * @return int The brightness value of the RGB color. */ public function rgbToBrightness($rgb) { $result = round(($rgb['r'] + $rgb['g'] + $rgb['b']) / 3); return ($result); } /** * Returns color map for current intance image as array(y,x)=>color * * @param bool $hex returns map values as rrggbb hex values or raw rgba components * * @return array */ public function getColorMap($hex = true) { $result = array(); for ($x = 0; $x < $this->imageWidth; $x++) { for ($y = 0; $y < $this->imageHeight; $y++) { $rgb = $this->getPixelColor($x, $y); if ($hex) { $result[$y][$x] = $this->rgbToHex($rgb); } else { $result[$y][$x] = $rgb; } } } return ($result); } /** * Calculates the brightness of a pixel at the specified coordinates. * * @param int $x The x-coordinate of the pixel. * @param int $y The y-coordinate of the pixel. * * @return int The brightness value of the pixel. */ public function getPixelBrightness($x, $y) { $result = false; $pixelColor = $this->getPixelColor($x, $y); $result = $this->rgbToBrightness($pixelColor); return ($result); } } |