Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

We've moved the forum!

Please use forum.silverstripe.org for any new questions (announcement).
The forum archive will stick around, but will be read only.

You can also use our Slack channel or StackOverflow to ask for help.
Check out our community overview for more options to contribute.

General Questions /

General questions about getting started with SilverStripe that don't fit in any of the categories above.

Moderators: martimiz, Sean, Ed, biapar, Willr, Ingo, swaiba

3.1.10 rotate image / update problem / cache ?


Go to End


5 Posts   1770 Views

Avatar
timo

Community Member, 47 Posts

3 May 2015 at 6:56pm

Edited: 03/05/2015 7:25pm

When uploading images from ipad, it happens that some of the images are displayed in landscape format but should be portrait.
So i try to manually rotate this image after upload.
The rotate - function is working; but it needs a flush=all in cms and also on the page to take effect.
any ideas?
thanks.timo.

class MyImageDecorator extends DataExtension{
	
	function getCustomFields(){
		
		$selectionGroup = new OptionsetField(
					   $name = "Rotate",
					   $title = "Rotate",
					   $source = array(
						  "1" => "Rotate CW",
						  "2" => "Rotate CCW"
					   ),
					   $value = ""
					);
					
		$fields = new FieldList();
		$fields->push(new TextField('Title', 'Title'));
		$fields->push($selectionGroup);
		return $fields;
    }
	
	
	function onAfterWrite(){
		if(isset($_POST['Rotate'])){
			$this->Rotate($_POST['Rotate']);
		}	
	 }
	 
	 
	public function Rotate($rotation){
		 
		$angle = $rotation == 1 ? 270 : 90;
		$extension = strtolower($this->owner->getExtension());
		$original = $this->owner->getFullPath();
		$resampled = $original . '.tmp.' . $extension;
		$gd = new GD($original);
		$image_loaded = (method_exists('GD', 'hasImageResource')) ? $gd->hasImageResource() : $gd->hasGD();
		
		if($image_loaded){

			$transformed = $gd;
			$transformed = $transformed->rotate($angle);
			
			if($transformed){
				$transformed->writeTo($resampled);
				unlink($original);
				rename($resampled, $original);
			}
		}
	}

Avatar
Pyromanik

Community Member, 419 Posts

5 May 2015 at 9:40pm

Edited: 05/05/2015 9:43pm

Since you've named the resampled image the same as the original, this seems more like a browser cache issue than a silverstripe problem.
Try ctrl+F5 after making a rotation instead of flushing (although this will be difficult on an ipad - I don't know if it has an equivalent).

Unless you're talking about the wee preview image - this is because it's a separate image all together. You'll need to clear out all cached resamples somehow. I'm not sure there is a native method to do this.
There is a flush generated image task that may provide some insights for you though: http://api.silverstripe.org/3.1/class-FlushGeneratedImagesTask.html
It's probably not advisable to run this every time thoguh, as I believe it will flush ALL generated images, not just the affected one.

Avatar
timo

Community Member, 47 Posts

6 May 2015 at 10:25pm

Edited: 06/05/2015 10:32pm

Hi Pyromanik!
whats the "wee preview image" ?

i modyfied https://github.com/axllent/silverstripe-scaled-uploads/blob/master/code/ScaledUploads.php
and changed the switch - function in exifRotation
now all images are handled correct from ipad.
Another issue is that i can only access the ipad camera from wee preview and not from gridfield -bulk - upload.
also the cache problem is solved with a dirty rename action.
Its not updating imediatly but when clicking the second save-button on bottom.

class MyImageDecorator extends DataExtension{
	
	public static $max_width = 1200;
	public static $max_height = 1000;
	public static $exif_rotation = true;
	
	
	public function getMaxWidth() {
		$w = Config::inst()->get('MyImageDecorator', 'max-width');
		return ($w) ? $w : self::$max_width;
	}
	public function getMaxHeight() {
		$h = Config::inst()->get('MyImageDecorator', 'max-height');
		return ($h) ? $h : self::$max_height;
	}
	public function getAutoRotate() {
		$r = Config::inst()->get('MyImageDecorator', 'auto-rotate');
		if ($r === 0 || $r == 'false') return false;
		return self::$exif_rotation;
	}
	
	function getCustomFields(){
		
		$selectionGroup = new OptionsetField(
					   $name = "Rotate",
					   $title = "Rotate",
					   $source = array(
						  "1" => "90º CW",
						  "2" => "90º CCW",
						  "3" => "180º"
					   ),
					   $value = ""
					);
					
		$fields = new FieldList();
		$fields->push($selectionGroup);
		return $fields;
    }
	
	
	function onAfterWrite(){
		if(isset($_POST['Rotate'])){
			$this->ManualRotate($_POST['Rotate']);
		}else{
			$this->ExifRotate();
		}
	}
	 
	 
	public function ManualRotate($rotation){
		
		switch($rotation) {
			case 1: // 90 rotate CW
				$angle =  270;
				break;
			case 2: // 90 rotate CCW
				$angle =  90;
				break;
			case 3: // image upside down
				$angle =  180;
				break;
		}
		$extension = strtolower($this->owner->getExtension());
		$original = $this->owner->getFullPath();
		$name = $this->owner->Name;
		$filename = $this->owner->Filename;
		$image = Image::get()->byID($this->owner->ID);
		$resampled = $original . '.tmp.' . $extension;
		$gd = new GD($original);
		$image_loaded = (method_exists('GD', 'hasImageResource')) ? $gd->hasImageResource() : $gd->hasGD();
		
		if($image_loaded){

			$transformed = $gd;
			$transformed = $transformed->rotate($angle);
			
			if($transformed){
				$time = time();
				$transformed->writeTo($resampled);
				unlink($original);
				$this->owner->deleteFormattedImages();
				//rename($resampled, $original);
				$original = preg_replace('/\\.[^.\\s]{3,4}$/', '', $original); // remove Extention
				$orig_Filename = preg_replace('/\\.[^.\\s]{3,4}$/', '', $filename);
				$original = preg_replace('/--.*/', '', $original);
				$orig_Filename = preg_replace('/--.*/', '', $orig_Filename);
				$name = preg_replace('/\\.[^.\\s]{3,4}$/', '', $name);
				$name = preg_replace('/--.*/', '', $name);
				rename($resampled, $original.'--'.$time.'.'.$extension);
				
			
				DB::query("UPDATE File SET Filename='".$orig_Filename.'--'.$time.'.'.$extension."', Name='".$name.'--'.$time.'.'.$extension."' WHERE ID = ".$this->owner->ID."");
				
			}
		}
		
	}
	
	
	
	
	public function ExifRotate() {
		$extension = strtolower($this->owner->getExtension());
		if($this->owner->getHeight() > $this->getMaxHeight() || $this->owner->getWidth() > $this->getMaxWidth()) {
			$original = $this->owner->getFullPath();
			$resampled = $original . '.tmp.' . $extension;
			$gd = new GD($original);
			/* Backwards compatibility with SilverStripe 3.0 */
			$image_loaded = (method_exists('GD', 'hasImageResource')) ? $gd->hasImageResource() : $gd->hasGD();
			if ($image_loaded) {
				
				/* Clone original */
				$transformed = $gd;
				/* If rotation allowed & JPG, test to see if orientation needs switching */
				if ($this->getAutoRotate() && preg_match('/jpe?g/i', $extension)) {
					$switchorientation = $this->exifRotation($original);
					if ($switchorientation) {
						$transformed = $transformed->rotate($switchorientation);
					}
				}
				/* Resize to max values */
				if ($transformed) {
					$transformed = $transformed->resizeRatio($this->getMaxWidth(), $this->getMaxHeight());
				}
				/* Overwrite original upload with resampled */
				if ($transformed) {
					$transformed->writeTo($resampled);
					unlink($original);
					rename($resampled, $original);
				}
			}
		}
	}
	
	public function exifRotation($file) {
		
		$exif = @exif_read_data($file);
		if (!$exif) return false;
		$ort = @$exif['IFD0']['Orientation'];
		if (!$ort) $ort = @$exif['Orientation'];
		switch($ort) {
			case 1:
				return false;
				break;
			case 2:
				return '180';
				break;					
			case 3:
				return '180';
				break;		
			case 4:
				return '180';
				break;	
			case 5:
				return '-90';
				break;	
			case 6:
				return '-90';
				break;	
			case 7:
				return '-90';
				break;	
			case 8:
				return '90';
				break;
			default:
				return false;
		}
	}
	 
	 

Avatar
Pyromanik

Community Member, 419 Posts

8 May 2015 at 12:54am

Edited: 08/05/2015 12:57am

> whats the "wee preview image" ?
eg. assets/Uploads/_resampled/*

'wee' is English slang for 'small'.

Avatar
micschk

Community Member, 22 Posts

16 February 2016 at 3:34am

A bit late maybe, but I think you could call
```
$this->owner->deleteFormattedImages();
```
to refresh the cache of only this specific image after rotating. Then you don't have to rename it etc.

Also found a module which should prevent images from rotating wrongly upon upload altogether; https://github.com/thisisbd/silverstripe-fixjpeg-orientation