123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394 |
- <?php
- namespace Gregwar\Image\Adapter;
- abstract class Common extends Adapter
- {
- /**
- * {@inheritdoc}
- */
- public function zoomCrop($width, $height, $background = 'transparent', $xPosLetter = 'center', $yPosLetter = 'center')
- {
- // Calculate the different ratios
- $originalRatio = $this->width() / $this->height();
- $newRatio = $width / $height;
- // Compare ratios
- if ($originalRatio > $newRatio) {
- // Original image is wider
- $newHeight = $height;
- $newWidth = (int) $height * $originalRatio;
- } else {
- // Equal width or smaller
- $newHeight = (int) $width / $originalRatio;
- $newWidth = $width;
- }
- // Perform resize
- $this->resize($newWidth, $newHeight, $background, true);
- // Define x position
- switch ($xPosLetter) {
- case 'L':
- case 'left':
- $xPos = 0;
- break;
- case 'R':
- case 'right':
- $xPos = (int) $newWidth - $width;
- break;
- default:
- $xPos = (int) ($newWidth - $width) / 2;
- }
- // Define y position
- switch ($yPosLetter) {
- case 'T':
- case 'top':
- $yPos = 0;
- break;
- case 'B':
- case 'bottom':
- $yPos = (int) $newHeight - $height;
- break;
- default:
- $yPos = (int) ($newHeight - $height) / 2;
- }
- // Crop image to reach desired size
- $this->crop($xPos, $yPos, $width, $height);
- return $this;
- }
- /**
- * Resizes the image forcing the destination to have exactly the
- * given width and the height.
- *
- * @param int $w the width
- * @param int $h the height
- * @param int $bg the background
- */
- public function forceResize($width = null, $height = null, $background = 'transparent')
- {
- return $this->resize($width, $height, $background, true);
- }
- /**
- * {@inheritdoc}
- */
- public function scaleResize($width = null, $height = null, $background = 'transparent', $crop = false)
- {
- return $this->resize($width, $height, $background, false, true, $crop);
- }
- /**
- * {@inheritdoc}
- */
- public function cropResize($width = null, $height = null, $background = 'transparent')
- {
- return $this->resize($width, $height, $background, false, false, true);
- }
- /**
- * Read exif rotation from file and apply it.
- */
- public function fixOrientation()
- {
- if (!in_array(exif_imagetype($this->source->getInfos()), array(
- IMAGETYPE_JPEG,
- IMAGETYPE_TIFF_II,
- IMAGETYPE_TIFF_MM,
- ))) {
- return $this;
- }
- if (!extension_loaded('exif')) {
- throw new \RuntimeException('You need to EXIF PHP Extension to use this function');
- }
- $exif = @exif_read_data($this->source->getInfos());
- if ($exif === false || !array_key_exists('Orientation', $exif)) {
- return $this;
- }
- return $this->applyExifOrientation($exif['Orientation']);
- }
- /**
- * Apply orientation using Exif orientation value.
- */
- public function applyExifOrientation($exif_orienation)
- {
- switch ($exif_orienation) {
- case 1:
- break;
- case 2:
- $this->flip(false, true);
- break;
- case 3: // 180 rotate left
- $this->rotate(180);
- break;
- case 4: // vertical flip
- $this->flip(true, false);
- break;
- case 5: // vertical flip + 90 rotate right
- $this->flip(true, false);
- $this->rotate(-90);
- break;
- case 6: // 90 rotate right
- $this->rotate(-90);
- break;
- case 7: // horizontal flip + 90 rotate right
- $this->flip(false, true);
- $this->rotate(-90);
- break;
- case 8: // 90 rotate left
- $this->rotate(90);
- break;
- }
- return $this;
- }
- /**
- * Opens the image.
- */
- abstract protected function openGif($file);
- abstract protected function openJpeg($file);
- abstract protected function openPng($file);
- abstract protected function openWebp($file);
- /**
- * Creates an image.
- */
- abstract protected function createImage($width, $height);
- /**
- * Creating an image using $data.
- */
- abstract protected function createImageFromData($data);
- /**
- * Loading image from $resource.
- */
- protected function loadResource($resource)
- {
- $this->resource = $resource;
- }
- protected function loadFile($file, $type)
- {
- if (!$this->supports($type)) {
- throw new \RuntimeException('Type '.$type.' is not supported by GD');
- }
- if ($type == 'jpeg') {
- $this->openJpeg($file);
- }
- if ($type == 'gif') {
- $this->openGif($file);
- }
- if ($type == 'png') {
- $this->openPng($file);
- }
- if ($type == 'webp') {
- $this->openWebp($file);
- }
- if (false === $this->resource) {
- throw new \UnexpectedValueException('Unable to open file ('.$file.')');
- } else {
- $this->convertToTrueColor();
- }
- }
- /**
- * {@inheritdoc}
- */
- public function init()
- {
- $source = $this->source;
- if ($source instanceof \Gregwar\Image\Source\File) {
- $this->loadFile($source->getFile(), $source->guessType());
- } elseif ($source instanceof \Gregwar\Image\Source\Create) {
- $this->createImage($source->getWidth(), $source->getHeight());
- } elseif ($source instanceof \Gregwar\Image\Source\Data) {
- $this->createImageFromData($source->getData());
- } elseif ($source instanceof \Gregwar\Image\Source\Resource) {
- $this->loadResource($source->getResource());
- } else {
- throw new \Exception('Unsupported image source type '.get_class($source));
- }
- return $this;
- }
-
- /**
- * {@inheritdoc}
- */
- public function deinit()
- {
- $this->resource = null;
- }
- /**
- * {@inheritdoc}
- */
- public function resize($width = null, $height = null, $background = 'transparent', $force = false, $rescale = false, $crop = false)
- {
- $current_width = $this->width();
- $current_height = $this->height();
- $new_width = 0;
- $new_height = 0;
- $scale = 1.0;
- if ($height === null && preg_match('#^(.+)%$#mUsi', $width, $matches)) {
- $width = round($current_width * ((float) $matches[1] / 100.0));
- $height = round($current_height * ((float) $matches[1] / 100.0));
- }
- if (!$rescale && (!$force || $crop)) {
- if ($width != null && $current_width > $width) {
- $scale = $current_width / $width;
- }
- if ($height != null && $current_height > $height) {
- if ($current_height / $height > $scale) {
- $scale = $current_height / $height;
- }
- }
- } else {
- if ($width != null) {
- $scale = $current_width / $width;
- $new_width = $width;
- }
- if ($height != null) {
- if ($width != null && $rescale) {
- $scale = max($scale, $current_height / $height);
- } else {
- $scale = $current_height / $height;
- }
- $new_height = $height;
- }
- }
- if (!$force || $width == null || $rescale) {
- $new_width = round($current_width / $scale);
- }
- if (!$force || $height == null || $rescale) {
- $new_height = round($current_height / $scale);
- }
- if ($width == null || $crop) {
- $width = $new_width;
- }
- if ($height == null || $crop) {
- $height = $new_height;
- }
- $this->doResize($background, $width, $height, $new_width, $new_height);
- }
- /**
- * Trim background color arround the image.
- *
- * @param int $bg the background
- */
- protected function _trimColor($background = 'transparent')
- {
- $width = $this->width();
- $height = $this->height();
- $b_top = 0;
- $b_lft = 0;
- $b_btm = $height - 1;
- $b_rt = $width - 1;
- //top
- for (; $b_top < $height; ++$b_top) {
- for ($x = 0; $x < $width; ++$x) {
- if ($this->getColor($x, $b_top) != $background) {
- break 2;
- }
- }
- }
- // bottom
- for (; $b_btm >= 0; --$b_btm) {
- for ($x = 0; $x < $width; ++$x) {
- if ($this->getColor($x, $b_btm) != $background) {
- break 2;
- }
- }
- }
- // left
- for (; $b_lft < $width; ++$b_lft) {
- for ($y = $b_top; $y <= $b_btm; ++$y) {
- if ($this->getColor($b_lft, $y) != $background) {
- break 2;
- }
- }
- }
- // right
- for (; $b_rt >= 0; --$b_rt) {
- for ($y = $b_top; $y <= $b_btm; ++$y) {
- if ($this->getColor($b_rt, $y) != $background) {
- break 2;
- }
- }
- }
- ++$b_btm;
- ++$b_rt;
- $this->crop($b_lft, $b_top, $b_rt - $b_lft, $b_btm - $b_top);
- }
- /**
- * Resizes the image to an image having size of $target_width, $target_height, using
- * $new_width and $new_height and padding with $bg color.
- */
- abstract protected function doResize($bg, $target_width, $target_height, $new_width, $new_height);
- /**
- * Gets the color of the $x, $y pixel.
- */
- abstract protected function getColor($x, $y);
- /**
- * {@inheritdoc}
- */
- public function enableProgressive()
- {
- throw new \Exception('The Adapter '.$this->getName().' does not support Progressive Image loading');
- }
- /**
- * This does nothing, but can be used to tag a ressource for instance (having a final image hash
- * for the cache different depending on the tag)
- */
- public function tag($tag)
- {
- }
- }
|