Grafika.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. <?php
  2. namespace Grafika;
  3. use Grafika\Gd\DrawingObject\CubicBezier as GdCubicBezier;
  4. use Grafika\Gd\DrawingObject\Ellipse as GdEllipse;
  5. use Grafika\Gd\DrawingObject\Line as GdLine;
  6. use Grafika\Gd\DrawingObject\Polygon as GdPolygon;
  7. use Grafika\Gd\DrawingObject\QuadraticBezier as GdQuadraticBezier;
  8. use Grafika\Gd\DrawingObject\Rectangle as GdRectangle;
  9. use Grafika\Gd\Editor as GdEditor;
  10. use Grafika\Gd\Filter\Dither as GdDither;
  11. use Grafika\Gd\Filter\Blur as GdBlur;
  12. use Grafika\Gd\Filter\Brightness as GdBrightness;
  13. use Grafika\Gd\Filter\Colorize as GdColorize;
  14. use Grafika\Gd\Filter\Contrast as GdContrast;
  15. use Grafika\Gd\Filter\Gamma as GdGamma;
  16. use Grafika\Gd\Filter\Grayscale as GdGrayscale;
  17. use Grafika\Gd\Filter\Invert as GdInvert;
  18. use Grafika\Gd\Filter\Pixelate as GdPixelate;
  19. use Grafika\Gd\Filter\Sharpen as GdSharpen;
  20. use Grafika\Gd\Filter\Sobel as GdSobel;
  21. use Grafika\Gd\Image as GdImage;
  22. use Grafika\Imagick\DrawingObject\CubicBezier as ImagickCubicBezier;
  23. use Grafika\Imagick\DrawingObject\Ellipse as ImagickEllipse;
  24. use Grafika\Imagick\DrawingObject\Line as ImagickLine;
  25. use Grafika\Imagick\DrawingObject\Polygon as ImagickPolygon;
  26. use Grafika\Imagick\DrawingObject\QuadraticBezier as ImagickQuadraticBezier;
  27. use Grafika\Imagick\DrawingObject\Rectangle as ImagickRectangle;
  28. use Grafika\Imagick\Editor as ImagickEditor;
  29. use Grafika\Imagick\Filter\Blur as ImagickBlur;
  30. use Grafika\Imagick\Filter\Brightness as ImagickBrightness;
  31. use Grafika\Imagick\Filter\Colorize as ImagickColorize;
  32. use Grafika\Imagick\Filter\Contrast as ImagickContrast;
  33. use Grafika\Imagick\Filter\Gamma as ImagickGamma;
  34. use Grafika\Imagick\Filter\Dither as ImagickDither;
  35. use Grafika\Imagick\Filter\Grayscale as ImagickGrayscale;
  36. use Grafika\Imagick\Filter\Invert as ImagickInvert;
  37. use Grafika\Imagick\Filter\Pixelate as ImagickPixelate;
  38. use Grafika\Imagick\Filter\Sharpen as ImagickSharpen;
  39. use Grafika\Imagick\Filter\Sobel as ImagickSobel;
  40. use Grafika\Imagick\Image as ImagickImage;
  41. /**
  42. * Contains factory methods for detecting editors, creating editors and images.
  43. * @package Grafika
  44. */
  45. class Grafika
  46. {
  47. /**
  48. * Grafika root directory
  49. */
  50. const DIR = __DIR__;
  51. /**
  52. * @var array $editorList List of editors to evaluate.
  53. */
  54. private static $editorList = array('Imagick', 'Gd');
  55. /**
  56. * Return path to directory containing fonts used in text operations.
  57. *
  58. * @return string
  59. */
  60. public static function fontsDir()
  61. {
  62. $ds = DIRECTORY_SEPARATOR;
  63. return realpath(self::DIR . $ds . '..' . $ds . '..') . $ds . 'fonts';
  64. }
  65. /**
  66. * Change the editor list order of evaluation globally.
  67. *
  68. * @param array $editorList
  69. *
  70. * @throws \Exception
  71. */
  72. public static function setEditorList($editorList){
  73. if(!is_array($editorList)){
  74. throw new \Exception('$editorList must be an array.');
  75. }
  76. self::$editorList = $editorList;
  77. }
  78. /**
  79. * Detects and return the name of the first supported editor which can either be "Imagick" or "Gd".
  80. *
  81. * @param array $editorList Array of editor list names. Use this to change the order of evaluation for editors for this function call only. Default order of evaluation is Imagick then GD.
  82. *
  83. * @return string Name of available editor.
  84. * @throws \Exception Throws exception if there are no supported editors.
  85. */
  86. public static function detectAvailableEditor($editorList = null)
  87. {
  88. if(null === $editorList){
  89. $editorList = self::$editorList;
  90. }
  91. /* Get first supported editor instance. Order of editorList matter. */
  92. foreach ($editorList as $editorName) {
  93. if ('Imagick' === $editorName) {
  94. $editorInstance = new ImagickEditor();
  95. } else {
  96. $editorInstance = new GdEditor();
  97. }
  98. /** @var EditorInterface $editorInstance */
  99. if (true === $editorInstance->isAvailable()) {
  100. return $editorName;
  101. }
  102. }
  103. throw new \Exception('No supported editor.');
  104. }
  105. /**
  106. * Creates the first available editor.
  107. *
  108. * @param array $editorList Array of editor list names. Use this to change the order of evaluation for editors. Default order of evaluation is Imagick then GD.
  109. *
  110. * @return EditorInterface
  111. * @throws \Exception
  112. */
  113. public static function createEditor($editorList = array('Imagick', 'Gd'))
  114. {
  115. $editorName = self::detectAvailableEditor($editorList);
  116. if ('Imagick' === $editorName) {
  117. return new ImagickEditor();
  118. } else {
  119. return new GdEditor();
  120. }
  121. }
  122. /**
  123. * Create an image.
  124. * @param string $imageFile Path to image file.
  125. *
  126. * @return ImageInterface
  127. * @throws \Exception
  128. */
  129. public static function createImage($imageFile)
  130. {
  131. $editorName = self::detectAvailableEditor();
  132. if ('Imagick' === $editorName) {
  133. return ImagickImage::createFromFile($imageFile);
  134. } else {
  135. return GdImage::createFromFile($imageFile);
  136. }
  137. }
  138. /**
  139. * Create a blank image.
  140. *
  141. * @param int $width Width of image in pixels.
  142. * @param int $height Height of image in pixels.
  143. *
  144. * @return ImageInterface
  145. * @throws \Exception
  146. */
  147. public static function createBlankImage($width = 1, $height = 1)
  148. {
  149. $editorName = self::detectAvailableEditor();
  150. if ('Imagick' === $editorName) {
  151. return ImagickImage::createBlank($width, $height);
  152. } else {
  153. return GdImage::createBlank($width, $height);
  154. }
  155. }
  156. /**
  157. * Create a filter. Detects available editor to use.
  158. *
  159. * @param string $filterName The name of the filter.
  160. *
  161. * @return FilterInterface
  162. * @throws \Exception
  163. */
  164. public static function createFilter($filterName)
  165. {
  166. $editorName = self::detectAvailableEditor();
  167. $p = func_get_args();
  168. if ('Imagick' === $editorName) {
  169. switch ($filterName){
  170. case 'Blur':
  171. return new ImagickBlur(
  172. (array_key_exists(1,$p) ? $p[1] : 1)
  173. );
  174. case 'Brightness':
  175. return new ImagickBrightness(
  176. $p[1]
  177. );
  178. case 'Colorize':
  179. return new ImagickColorize(
  180. $p[1], $p[2], $p[3]
  181. );
  182. case 'Contrast':
  183. return new ImagickContrast(
  184. $p[1]
  185. );
  186. case 'Dither':
  187. return new ImagickDither(
  188. $p[1]
  189. );
  190. case 'Gamma':
  191. return new ImagickGamma(
  192. $p[1]
  193. );
  194. case 'Grayscale':
  195. return new ImagickGrayscale();
  196. case 'Invert':
  197. return new ImagickInvert();
  198. case 'Pixelate':
  199. return new ImagickPixelate(
  200. $p[1]
  201. );
  202. case 'Sharpen':
  203. return new ImagickSharpen(
  204. $p[1]
  205. );
  206. case 'Sobel':
  207. return new ImagickSobel();
  208. }
  209. throw new \Exception('Invalid filter name.');
  210. } else {
  211. switch ($filterName){
  212. case 'Blur':
  213. return new GdBlur(
  214. (array_key_exists(1,$p) ? $p[1] : 1)
  215. );
  216. case 'Brightness':
  217. return new GdBrightness(
  218. $p[1]
  219. );
  220. case 'Colorize':
  221. return new GdColorize(
  222. $p[1], $p[2], $p[3]
  223. );
  224. case 'Contrast':
  225. return new GdContrast(
  226. $p[1]
  227. );
  228. case 'Dither':
  229. return new GdDither(
  230. $p[1]
  231. );
  232. case 'Gamma':
  233. return new GdGamma(
  234. $p[1]
  235. );
  236. case 'Grayscale':
  237. return new GdGrayscale();
  238. case 'Invert':
  239. return new GdInvert();
  240. case 'Pixelate':
  241. return new GdPixelate(
  242. $p[1]
  243. );
  244. case 'Sharpen':
  245. return new GdSharpen(
  246. $p[1]
  247. );
  248. case 'Sobel':
  249. return new GdSobel();
  250. }
  251. throw new \Exception('Invalid filter name.');
  252. }
  253. }
  254. /**
  255. * Draws an object. Detects available editor to use.
  256. *
  257. * @param string $drawingObjectName The name of the DrawingObject.
  258. *
  259. * @return DrawingObjectInterface
  260. * @throws \Exception
  261. *
  262. * We use array_key_exist() instead of isset() to be able to detect a parameter with a NULL value.
  263. */
  264. public static function createDrawingObject($drawingObjectName)
  265. {
  266. $editorName = self::detectAvailableEditor();
  267. $p = func_get_args();
  268. if ('Imagick' === $editorName) {
  269. switch ($drawingObjectName){
  270. case 'CubicBezier':
  271. return new ImagickCubicBezier(
  272. $p[1],
  273. $p[2],
  274. $p[3],
  275. $p[4],
  276. (array_key_exists(5,$p) ? $p[5] : '#000000')
  277. );
  278. case 'Ellipse':
  279. return new ImagickEllipse(
  280. $p[1],
  281. $p[2],
  282. (array_key_exists(3,$p) ? $p[3] : array(0,0)),
  283. (array_key_exists(4,$p) ? $p[4] : 1),
  284. (array_key_exists(5,$p) ? $p[5] : '#000000'),
  285. (array_key_exists(6,$p) ? $p[6] : '#FFFFFF')
  286. );
  287. case 'Line':
  288. return new ImagickLine(
  289. $p[1],
  290. $p[2],
  291. (array_key_exists(3,$p) ? $p[3] : 1),
  292. (array_key_exists(4,$p) ? $p[4] : '#000000')
  293. );
  294. case 'Polygon':
  295. return new ImagickPolygon(
  296. $p[1],
  297. (array_key_exists(2,$p) ? $p[2] : 1),
  298. (array_key_exists(3,$p) ? $p[3] : '#000000'),
  299. (array_key_exists(4,$p) ? $p[4] : '#FFFFFF')
  300. );
  301. case 'Rectangle':
  302. return new ImagickRectangle(
  303. $p[1],
  304. $p[2],
  305. (array_key_exists(3,$p) ? $p[3] : array(0,0)),
  306. (array_key_exists(4,$p) ? $p[4] : 1),
  307. (array_key_exists(5,$p) ? $p[5] : '#000000'),
  308. (array_key_exists(6,$p) ? $p[6] : '#FFFFFF')
  309. );
  310. case 'QuadraticBezier':
  311. return new ImagickQuadraticBezier(
  312. $p[1],
  313. $p[2],
  314. $p[3],
  315. (array_key_exists(4,$p) ? $p[4] : '#000000')
  316. );
  317. }
  318. throw new \Exception('Invalid drawing object name.');
  319. } else {
  320. switch ($drawingObjectName) {
  321. case 'CubicBezier':
  322. return new GdCubicBezier(
  323. $p[1],
  324. $p[2],
  325. $p[3],
  326. $p[4],
  327. (array_key_exists(5,$p) ? $p[5] : '#000000')
  328. );
  329. case 'Ellipse':
  330. return new GdEllipse(
  331. $p[1],
  332. $p[2],
  333. (array_key_exists(3,$p) ? $p[3] : array(0,0)),
  334. (array_key_exists(4,$p) ? $p[4] : 1),
  335. (array_key_exists(5,$p) ? $p[5] : '#000000'),
  336. (array_key_exists(6,$p) ? $p[6] : '#FFFFFF')
  337. );
  338. case 'Line':
  339. return new GdLine(
  340. $p[1],
  341. $p[2],
  342. (array_key_exists(3,$p) ? $p[3] : 1),
  343. (array_key_exists(4,$p) ? $p[4] : '#000000')
  344. );
  345. case 'Polygon':
  346. return new GdPolygon(
  347. $p[1],
  348. (array_key_exists(2,$p) ? $p[2] : 1),
  349. (array_key_exists(3,$p) ? $p[3] : '#000000'),
  350. (array_key_exists(4,$p) ? $p[4] : '#FFFFFF')
  351. );
  352. case 'Rectangle':
  353. return new GdRectangle(
  354. $p[1],
  355. $p[2],
  356. (array_key_exists(3,$p) ? $p[3] : array(0,0)),
  357. (array_key_exists(4,$p) ? $p[4] : 1),
  358. (array_key_exists(5,$p) ? $p[5] : '#000000'),
  359. (array_key_exists(6,$p) ? $p[6] : '#FFFFFF')
  360. );
  361. case 'QuadraticBezier':
  362. return new GdQuadraticBezier(
  363. $p[1],
  364. $p[2],
  365. $p[3],
  366. (array_key_exists(4,$p) ? $p[4] : '#000000')
  367. );
  368. }
  369. throw new \Exception('Invalid drawing object name.');
  370. }
  371. }
  372. }