Index: photos_imageview.tpl.php
===================================================================
--- photos_imageview.tpl.php	(revision 491)
+++ photos_imageview.tpl.php	(working copy)
@@ -24,6 +24,11 @@
 				print $image->links['more'];
 			?>
 		</div>
+      <div class="photo-edit">
+      <?php
+         print $image->links['rotate-90'] . " " . $image->links['rotate-180'] . " " . $image->links['rotate-270'];
+      ?>
+      </div>
 	</div>
 	<div class="photo_link_pager">
     <?php if($image->links['pager']['prev_url']) { ?>
@@ -40,4 +45,4 @@
 	<div class="image-a"><?php print $image->view;?></div>
 </div>
 <?php print $image->comment['view'];?>
-<?php print $image->comment['box'];?>
\ No newline at end of file
+<?php print $image->comment['box'];?>
Index: photos.page.inc
===================================================================
--- photos.page.inc	(revision 491)
+++ photos.page.inc	(working copy)
@@ -214,7 +214,39 @@
     return $output;
 }
 
-function photos_image_pageone(){
+function photos_image_rotate($direction){
+   global $user;
+   $rotate_keys = array(
+         '90' => '90',
+         '180' => '180',
+         '270' => '270',
+         );
+   if(is_numeric(arg(2))){
+      $p = _photos_get_path(arg(2));
+      //dpm(array("PATH" => $p, "DIRECTION" => $direction));
+      if(isset($rotate_keys[$direction])) {
+         if($p){
+            foreach(array('p','p1','p2') as $image_key) {
+               $image = imageapi_image_open($p[$image_key]);
+               imageapi_image_rotate($image, $rotate_keys[$direction], $bgcolor = 0x000000);
+               imageapi_image_close($image);
+            }
+         }else{
+            return drupal_not_found();
+         }
+      }
+      else {
+         drupal_set_message("Invalid Rotation");
+      }
+   }else{
+      return drupal_not_found();
+   }
+	return photos_image_pageone($use_cache = FALSE);
+}
+
+
+
+function photos_image_pageone($use_cache = TRUE){
 	global $user;
 	if(is_numeric(arg(2))){
   	$p = _photos_get_path(arg(2));
@@ -247,7 +279,7 @@
   					if(!variable_get('photos_image_count', 0)){
   						db_query('UPDATE {x_image} SET count = count + 1 WHERE fid = %d', arg(2));
   					}
-  					$output = photos_view_image(arg(2),'');
+  					$output = photos_view_image(arg(2),'', $use_cache);
   				break;
   			}
   		}else{
@@ -949,4 +981,4 @@
 		$output = theme('table', $header, $rows,array('id'=>'photo-exif'));
 	}				
     return $output;
-}
\ No newline at end of file
+}
Index: photos.module
===================================================================
--- photos.module	(revision 491)
+++ photos.module	(working copy)
@@ -427,6 +427,14 @@
 		'type' => MENU_CALLBACK,
 		'file' => 'photos.page.inc',
 	);
+	$items['photos/image/%/rotate/%'] = array(
+		'page callback' => 'photos_image_rotate',
+      'page arguments' => array(4),
+		'access callback' => 'user_access',
+		'access arguments' => array('edit photo'),
+		'type' => MENU_CALLBACK,
+		'file' => 'photos.page.inc',
+	);
   
 	$items['photos/user/album/%user'] = array(
 		'title' => 'My albums',
@@ -505,7 +513,7 @@
 	return $t;
 }
 
-function photos_view_image($fid, $type) {
+function photos_view_image($fid, $type, $use_cache = TRUE) {
 	global $user;
 	$t = _photos_get_path($fid);
 	if($t){
@@ -567,6 +575,11 @@
 				if(_photos_access('edit',$t['uid'])){
 					$image->links['edit'] = '<a class="click-des" href="javascript:void(0)">' .t('Click to change description'). '</a>';
 				}
+				if(_photos_access('edit',$t['uid'])){
+               $image->links['rotate-90'] = l('<span>Rotate 90</span>', 'photos/image/' . arg(2) . '/rotate/90', array('html' => TRUE, 'fragment' => 'image-load', 'attributes' => array('class' => 'click-rotate-90')));
+               $image->links['rotate-180'] = l('<span>Rotate 180</span>', 'photos/image/' . arg(2) . '/rotate/180', array('html' => TRUE, 'fragment' => 'image-load','attributes' => array('class' => 'click-rotate-180')));
+               $image->links['rotate-270'] = l('<span>Rotate 270</span>', 'photos/image/' . arg(2) . '/rotate/270', array('html' => TRUE, 'fragment' => 'image-load', 'attributes' => array('class' => 'click-rotate-270')));
+            }
 				if(variable_get('photos_vote', 0)){
 					$sum = votingapi_recalculate_results('image', $fid);
 					if($sum['0']['value']){
@@ -615,7 +628,7 @@
   			}
   			$image->links['more'] = l(t('View original image'), 'photos/zoom/'.$fid, $options);
 				$image->links['pager'] = _photos_image_pager($fid, $myalbum->nid);
-				$image->view = '<img alt="'.$t['title'].'" title="'.$t['des'].'" src="'._photos_file_create_url($t['p2']).'">';
+				$image->view = '<img alt="'.$t['title'].'" title="'.$t['des'].'" src="'._photos_file_create_url($t['p2']). ($use_cache ? '' : '?' . rand(100,999)) .'">';
 				$image->comment['view'] = photos_vote_comment($fid);
 				if (variable_get('photos_comment', 0) && user_access('post comments')) {
 					$image->comment['box'] = comment_form_box(array('nid' => $myalbum->nid), t('Post new comment'));
@@ -1391,4 +1404,4 @@
 
 function _photos_file_create_url($path) {
   return $GLOBALS['base_url'] . '/'. trim($path);
-}
\ No newline at end of file
+}
Index: photos.css
===================================================================
--- photos.css	(revision 491)
+++ photos.css	(working copy)
@@ -152,3 +152,6 @@
 	
 	background: #f00;
 }
+.photo-edit {
+   text-align: center;
+}
