/src/UNL/ENews/File/Image.php

https://github.com/unl/UNL_ENews · PHP · 197 lines · 139 code · 27 blank · 31 comment · 12 complexity · f0ce562d0383724a31b3929c65b7f36e MD5 · raw file

  1. <?php
  2. class UNL_ENews_File_Image extends UNL_ENews_File
  3. {
  4. const THUMB_WIDTH = 256;
  5. const THUMB_HEIGHT = 192;
  6. const FULL_AD_WIDTH = 536;
  7. const FULL_AD_HEIGHT = 96;
  8. const HALF_AD_WIDTH = 253;
  9. const HALF_AD_HEIGHT = 96;
  10. const MAX_WIDTH = 556;
  11. const HALF_WIDTH = 273;
  12. const GRID2_WIDTH = 140;
  13. const GRID3_WIDTH = 222;
  14. const GRID4_WIDTH = 304;
  15. const GRID5_WIDTH = 386;
  16. const GRID6_WIDTH = 468;
  17. const GRID7_WIDTH = 550;
  18. const GRID8_WIDTH = 632;
  19. const GRID9_WIDTH = 714;
  20. const GRID10_WIDTH = 796;
  21. const GRID11_WIDTH = 878;
  22. const GRID12_WIDTH = 960;
  23. // Max image size displayed to the user
  24. const THUMBNAIL_SELECTION_WIDTH = 410;
  25. /**
  26. * Save a thumbnail and return the object
  27. *
  28. * Sample:
  29. * ------------------------------
  30. * | |
  31. * | y1---------- |
  32. * | | | |
  33. * | | | |
  34. * | x1,y2--------x2 |
  35. * |-----------------------------
  36. *
  37. * @param int $x1 X coordinate offset start
  38. * @param int $x2 X coordinate offset end
  39. * @param int $y1 Y coordinate offset start
  40. * @param int $y2 Y coordinate offset end
  41. * @param int $width Final image width
  42. * @param int $height Final image height
  43. *
  44. * @return UNL_ENews_File_Image
  45. */
  46. function saveThumbnail($x1=0, $x2=0, $y1=0, $y2=0)
  47. {
  48. // Determine orientation
  49. if ($x2 - $x1 > $y2 - $y1) {
  50. $width=self::THUMB_WIDTH;
  51. $height=self::THUMB_HEIGHT;
  52. } else {
  53. $width=self::THUMB_HEIGHT;
  54. $height=self::THUMB_WIDTH;
  55. }
  56. // Crop the image ***************************************************************
  57. // Get dimensions of the original image
  58. list($current_width, $current_height) = $this->getSize();
  59. if ($x1 < 0) {
  60. // User did not select a cropping area
  61. $x1 = 0;
  62. $y1 = 0;
  63. $x2 = $current_width;
  64. $y2 = $current_width*($height/$width);
  65. } else {
  66. // Needs to be adjusted to account for the scaled down 410px-width size that's displayed to the user
  67. if ($current_width > self::THUMBNAIL_SELECTION_WIDTH) {
  68. $x1 = ($current_width/self::THUMBNAIL_SELECTION_WIDTH)*$x1;
  69. $y1 = ($current_height/(self::THUMBNAIL_SELECTION_WIDTH*$current_height/$current_width))*$y1;
  70. $x2 = ($current_width/self::THUMBNAIL_SELECTION_WIDTH)*$x2;
  71. $y2 = ($current_height/(self::THUMBNAIL_SELECTION_WIDTH*$current_height/$current_width))*$y2;
  72. }
  73. }
  74. if ($thumb = $this->resizeImage($x1, $x2, $y1, $y2, $width, $height)) {
  75. $thumb->use_for = 'thumbnail';
  76. $thumb->save();
  77. return $thumb;
  78. }
  79. return false;
  80. }
  81. function saveMaxWidth()
  82. {
  83. return $this->saveVarWidth(self::MAX_WIDTH);
  84. }
  85. function saveHalfWidth()
  86. {
  87. return $this->saveVarWidth(self::HALF_WIDTH);
  88. }
  89. function __call($method, $args)
  90. {
  91. if (preg_match('/save([\w]+)Width/', $method, $matches)) {
  92. $reflection = new ReflectionClass(__CLASS__);
  93. $valid_sizes = $reflection->getConstants();
  94. if (array_key_exists(strtoupper($matches[1].'_WIDTH'), $valid_sizes)) {
  95. return $this->saveVarWidth($valid_sizes[strtoupper($matches[1].'_WIDTH')]);
  96. }
  97. $size = array_search($matches[1], $valid_sizes);
  98. if (false !== strpos($size, '_WIDTH')) {
  99. return $this->saveVarWidth($matches[1]);
  100. }
  101. throw new InvalidArgumentException('I cannot create that size image for you', 400);
  102. }
  103. throw new RuntimeException('Invalid method call', 500);
  104. }
  105. protected function saveVarWidth($width)
  106. {
  107. list($current_width, $current_height) = $this->getSize();
  108. $new_height = $width/$current_width * $current_height;
  109. if ($thumb = $this->resizeImage(0, $current_width, 0, $current_height, $width, $new_height)) {
  110. $thumb->use_for = $width.'_wide';
  111. $thumb->save();
  112. return $thumb;
  113. }
  114. return false;
  115. }
  116. function resizeImage($x1=0, $x2=0, $y1=0, $y2=0, $width, $height)
  117. {
  118. $file = 'data://'.$this->type.';base64,' . base64_encode($this->data);
  119. list($current_width, $current_height) = getimagesize($file);
  120. // This will be the final size of the cropped image
  121. $crop_width = $x2-$x1;
  122. $crop_height = $y2-$y1;
  123. // Resample the image
  124. $croppedimage = imagecreatetruecolor($crop_width, $crop_height);
  125. switch ($this->type) {
  126. case 'image/jpeg':
  127. case 'image/pjpeg':
  128. $create_method = 'imagecreatefromjpeg';
  129. $output_method = 'imagejpeg';
  130. break;
  131. case 'image/png':
  132. case 'image/x-png':
  133. $create_method = 'imagecreatefrompng';
  134. $output_method = 'imagepng';
  135. break;
  136. case 'image/gif':
  137. $create_method = 'imagecreatefromgif';
  138. $output_method = 'imagegif';
  139. break;
  140. default:
  141. throw new Exception('I do not know how to resize a file of that content type: '.$this->type, 501);
  142. }
  143. $current_image = $create_method($file);
  144. imagecopy($croppedimage, $current_image, 0, 0, $x1, $y1, $current_width, $current_height);
  145. // Resize the image ************************************************************
  146. $current_width = $crop_width;
  147. $current_height = $crop_height;
  148. $canvas = imagecreatetruecolor($width, $height);
  149. imagecopyresampled($canvas, $croppedimage, 0, 0, 0, 0, $width, $height, $current_width, $current_height);
  150. ob_start();
  151. $output_method($canvas);
  152. imagedestroy($canvas);
  153. $resized = new self();
  154. $resized->name = $this->name;
  155. $resized->type = $this->type;
  156. $resized->description = $this->description;
  157. $resized->size = ob_get_length();
  158. $resized->data = ob_get_clean();
  159. // Save the thumbnail **********************************************************
  160. if ($resized->save()) {
  161. return $resized;
  162. }
  163. return false;
  164. }
  165. function getSize()
  166. {
  167. $file = 'data://'.$this->type.';base64,' . base64_encode($this->data);
  168. return getimagesize($file);
  169. }
  170. }