123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882 |
- <?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 = 'png') {
- $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;
- $colorName = (empty($colorName)) ? 'white' : $colorName;
- $outlineColor = (empty($outlineColor)) ? 'black' : $outlineColor;
- //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);
- }
- }
|