Index: /trunk/admin/include/functions.php
===================================================================
--- /trunk/admin/include/functions.php	(revision 12796)
+++ /trunk/admin/include/functions.php	(revision 12797)
@@ -2247,3 +2247,82 @@
   return array_from_query($query, 'user_id');
 }
+
+function clear_derivative_cache($type='all')
+{
+  $pattern='#.*-';
+  if ($type == 'all')
+  {
+    $type_urls = array();
+    foreach(ImageStdParams::get_all_types() as $dtype)
+    {
+      $type_urls[] = derivative_to_url($dtype);
+    }
+    $type_urls[] = derivative_to_url(IMG_CUSTOM);
+    $pattern .= '(' . implode('|',$type_urls) . ')';
+  }
+  else
+  {
+    $pattern .= derivative_to_url($type);
+  }
+  $pattern.='(_[a-zA-Z0-9]+)*\.[a-zA-Z0-9]{3,4}$#';
+  if ($contents = opendir(PHPWG_ROOT_PATH.PWG_DERIVATIVE_DIR))
+  {
+    while (($node = readdir($contents)) !== false)
+    {
+      if ($node != '.'
+          and $node != '..'
+          and is_dir(PHPWG_ROOT_PATH.PWG_DERIVATIVE_DIR.$node))
+      {
+        clear_derivative_cache_rec(PHPWG_ROOT_PATH.PWG_DERIVATIVE_DIR.$node, $pattern);
+      }
+    }
+    closedir($contents);
+  }
+}
+
+function clear_derivative_cache_rec($path, $pattern)
+{
+  $rmdir = true;
+  $rm_index = false;
+
+  if ($contents = opendir($path))
+  {
+    while (($node = readdir($contents)) !== false)
+    {
+      if ($node == '.' or $node == '..')
+        continue;
+      if (is_dir($path.'/'.$node))
+      {
+        $rmdir &= clear_derivative_cache_rec($path.'/'.$node, $pattern);
+      }
+      else
+      {
+        if (preg_match($pattern, $node))
+        {
+          unlink($path.'/'.$node);
+        }
+        elseif ($node=='index.htm')
+        {
+          $rm_index = true;
+        }
+        else
+        {
+          $rmdir = false;
+        }
+      }
+    }
+    closedir($contents);
+    
+    if ($rmdir)
+    {
+      if ($rm_index)
+      {
+        unlink($path.'/index.htm');
+      }
+      clearstatcache();
+      rmdir($path);
+    }
+    return $rmdir;
+  }
+}
 ?>
Index: /trunk/admin/maintenance.php
===================================================================
--- /trunk/admin/maintenance.php	(revision 12796)
+++ /trunk/admin/maintenance.php	(revision 12797)
@@ -122,8 +122,13 @@
     break;
   }
-  case 'compiled-templates' :
+  case 'compiled-templates':
   {
     $template->delete_compiled_templates();
     FileCombiner::clear_combined_files();
+    break;
+  }
+  case 'derivatives':
+  {
+    clear_derivative_cache();
     break;
   }
@@ -155,4 +160,5 @@
     'U_MAINT_SEARCH' => sprintf($url_format, 'search'),
     'U_MAINT_COMPILED_TEMPLATES' => sprintf($url_format, 'compiled-templates'),
+    'U_MAINT_DERIVATIVES' => sprintf($url_format, 'derivatives'),
     'U_HELP' => get_root_url().'admin/popuphelp.php?page=maintenance',
     )
Index: /trunk/admin/rating.php
===================================================================
--- /trunk/admin/rating.php	(revision 12796)
+++ /trunk/admin/rating.php	(revision 12797)
@@ -173,5 +173,5 @@
     i.path,
     i.file,
-    i.tn_ext,
+    i.representative_ext,
     i.rating_score       AS score,
     MAX(r.date)          AS recently_rated,
Index: /trunk/admin/themes/default/template/maintenance.tpl
===================================================================
--- /trunk/admin/themes/default/template/maintenance.tpl	(revision 12796)
+++ /trunk/admin/themes/default/template/maintenance.tpl	(revision 12797)
@@ -30,3 +30,4 @@
 	<li><a href="{$U_MAINT_SEARCH}"onclick="return confirm('{'Purge search history'|@translate|@escape:'javascript'}');">{'Purge search history'|@translate}</a></li>
 	<li><a href="{$U_MAINT_COMPILED_TEMPLATES}">{'Purge compiled templates'|@translate}</a></li>
+	<li><a href="{$U_MAINT_DERIVATIVES}">{'Purge derivative image cache'|@translate}</a></li>
 </ul>
Index: /trunk/i.php
===================================================================
--- /trunk/i.php	(revision 12796)
+++ /trunk/i.php	(revision 12797)
@@ -136,5 +136,5 @@
   foreach (ImageStdParams::get_defined_type_map() as $type => $params)
   {
-    if (substr($type,0,2) == $deriv[0])
+    if ( derivative_to_url($type) == $deriv[0])
     {
       $page['derivative_type'] = $type;
@@ -146,5 +146,5 @@
   if (!isset($page['derivative_type']))
   {
-    if (substr(IMG_CUSTOM,0,2) == $deriv[0])
+    if (derivative_to_url(IMG_CUSTOM) == $deriv[0])
     {
       $page['derivative_type'] = IMG_CUSTOM;
@@ -289,4 +289,4 @@
 
 fpassthru($fp);
-exit;
+fclose($fp);
 ?>
Index: /trunk/include/derivative.inc.php
===================================================================
--- /trunk/include/derivative.inc.php	(revision 12796)
+++ /trunk/include/derivative.inc.php	(revision 12797)
@@ -22,8 +22,12 @@
 final class SrcImage
 {
+  const IS_ORIGINAL = 0x01;
+  const IS_MIMETYPE = 0x02;
+
   public $rel_path;
-  
+
   public $coi=null;
   private $size=null;
+  private $flags=0;
 
   function __construct($infos)
@@ -35,4 +39,5 @@
     {
       $this->rel_path = $infos['path'];
+      $this->flags |= self::IS_ORIGINAL;
     }
     elseif (!empty($infos['representative_ext']))
@@ -45,12 +50,35 @@
     else
     {
-      $this->rel_path = get_themeconf('mime_icon_dir').strtolower($ext).'.png';
+      $ext = strtolower($ext);
+      $this->rel_path = trigger_event('get_mimetype_location', get_themeconf('mime_icon_dir').$ext.'.png', $ext );
+      $this->flags |= self::IS_MIMETYPE;
+      $this->size = @getimagesize(PHPWG_ROOT_PATH.$this->rel_path);
     }
 
     $this->coi = @$infos['coi'];
-    if (isset($infos['width']) && isset($infos['height']))
+    if (!$this->size && isset($infos['width']) && isset($infos['height']))
     {
       $this->size = array($infos['width'], $infos['height']);
     }
+  }
+
+  function is_original()
+  {
+    return $this->flags & self::IS_ORIGINAL;
+  }
+
+  function is_mimetype()
+  {
+    return $this->flags & self::IS_MIMETYPE;
+  }
+
+  function get_path()
+  {
+    return PHPWG_ROOT_PATH.$this->rel_path;
+  }
+
+  function get_url()
+  {
+    return get_root_url().$this->rel_path;
   }
 
@@ -127,5 +155,5 @@
       $ret[$type] = $ret[$type2];
     }
-    
+
     return $ret;
   }
@@ -145,5 +173,5 @@
     $tokens[] = substr($params->type,0,2);
 
-    if (!empty($src->coi))
+    if ($params->sizing->max_crop != 0 and !empty($src->coi))
     {
       $tokens[] = 'ci'.$src->coi;
@@ -207,4 +235,11 @@
 
 
+  function get_type()
+  {
+    if ($this->flags & self::SAME_AS_SRC)
+      return 'original';
+    return $this->params->type;
+  }
+
   /* returns the size of the derivative image*/
   function get_size()
Index: /trunk/include/derivative_params.inc.php
===================================================================
--- /trunk/include/derivative_params.inc.php	(revision 12796)
+++ /trunk/include/derivative_params.inc.php	(revision 12797)
@@ -20,4 +20,9 @@
 // +-----------------------------------------------------------------------+
 
+function derivative_to_url($t)
+{
+  return substr($t, 0, 2);
+}
+
 function size_to_url($s)
 {
Index: /trunk/include/picture_metadata.inc.php
===================================================================
--- /trunk/include/picture_metadata.inc.php	(revision 12796)
+++ /trunk/include/picture_metadata.inc.php	(revision 12797)
@@ -37,5 +37,5 @@
   }
 
-  $exif = get_exif_data($picture['current']['image_path'], $exif_mapping);
+  $exif = get_exif_data($picture['current']['src_image']->get_path(), $exif_mapping);
   
   if (count($exif) > 0)
@@ -80,5 +80,5 @@
 if ($conf['show_iptc'])
 {
-  $iptc = get_iptc_data($picture['current']['image_path'], $conf['show_iptc_mapping']);
+  $iptc = get_iptc_data($picture['current']['src_image']->get_path(), $conf['show_iptc_mapping']);
 
   if (count($iptc) > 0)
Index: /trunk/picture.php
===================================================================
--- /trunk/picture.php	(revision 12796)
+++ /trunk/picture.php	(revision 12797)
@@ -475,13 +475,13 @@
     $i = 'previous';
   }
-  else if (isset($page['next_item']) and $row['id'] == $page['next_item'])
+  elseif (isset($page['next_item']) and $row['id'] == $page['next_item'])
   {
     $i = 'next';
   }
-  else if (isset($page['first_item']) and $row['id'] == $page['first_item'])
+  elseif (isset($page['first_item']) and $row['id'] == $page['first_item'])
   {
     $i = 'first';
   }
-  else if (isset($page['last_item']) and $row['id'] == $page['last_item'])
+  elseif (isset($page['last_item']) and $row['id'] == $page['last_item'])
   {
     $i = 'last';
@@ -492,56 +492,29 @@
   }
 
-  $picture[$i] = $row;
-
-  $picture[$i]['is_picture'] = false;
-  if (in_array(get_extension($row['file']), $conf['picture_ext']))
-  {
-    $picture[$i]['is_picture'] = true;
-  }
-
-  $picture[$i]['derivatives'] = DerivativeImage::get_all($row);
-  $picture[$i]['src_image'] = $picture[$i]['derivatives'][IMG_THUMB]->src_image;
-  $picture[$i]['thumbnail'] = $picture[$i]['derivatives'][IMG_THUMB]->get_url();
+
+
+  $row['derivatives'] = DerivativeImage::get_all($row);
+  $row['src_image'] = $row['derivatives'][IMG_THUMB]->src_image;
   
   // ------ build element_path and element_url
-  $picture[$i]['element_path'] = get_element_path($picture[$i]);
-  $picture[$i]['element_url'] = get_element_url($picture[$i]);
-
-  // ------ build image_path and image_url
-  if ($i=='current' or $i=='next')
-  {
-    $picture[$i]['image_path'] = get_image_path( $picture[$i] );
-    $picture[$i]['image_url'] = get_image_url( $picture[$i] );
-  }
+  $row['element_path'] = get_element_path($row);
+  $row['element_url'] = get_element_url($row);
 
   if ($i=='current')
   {
-    if ( $picture[$i]['is_picture'] )
+    if ( $row['src_image']->is_original() )
     {
       if ( $user['enabled_high']=='true' )
       {
-        $picture[$i]['download_url'] = get_download_url('e',$picture[$i]);
+        $row['download_url'] = get_download_url('e',$row);
       }
     }
     else
     { // not a pic - need download link
-      $picture[$i]['download_url'] = get_download_url('e',$picture[$i]);
-    }
-  }
-
-
-  if ( !empty( $row['name'] ) )
-  {
-    $picture[$i]['name'] = $row['name'];
-  }
-  else
-  {
-    $file_wo_ext = get_filename_wo_extension($row['file']);
-    $picture[$i]['name'] = str_replace('_', ' ', $file_wo_ext);
-  }
-
-  $picture[$i]['name'] = trigger_event('render_element_description', $picture[$i]['name']);
-
-  $picture[$i]['url'] = duplicate_picture_url(
+      $row['download_url'] = $row['element_url'];
+    }
+  }
+
+  $row['url'] = duplicate_picture_url(
     array(
       'image_id' => $row['id'],
@@ -553,4 +526,18 @@
     );
 
+  $picture[$i] = $row;
+
+  if ( !empty( $row['name'] ) )
+  {
+    $picture[$i]['name'] = $row['name'];
+  }
+  else
+  {
+    $file_wo_ext = get_filename_wo_extension($row['file']);
+    $picture[$i]['name'] = str_replace('_', ' ', $file_wo_ext);
+  }
+
+  $picture[$i]['name'] = trigger_event('render_element_description', $picture[$i]['name']);
+
   if ('previous'==$i and $page['previous_item']==$page['first_item'])
   {
@@ -560,15 +547,4 @@
   {
     $picture['last'] = $picture[$i];
-  }
-}
-
-// calculation of width and height for the current picture
-if (empty($picture['current']['width']))
-{
-  $taille_image = @getimagesize($picture['current']['image_path']);
-  if ($taille_image!==false)
-  {
-    $picture['current']['width'] = $taille_image[0];
-    $picture['current']['height']= $taille_image[1];
   }
 }
@@ -638,7 +614,7 @@
   (
     ($conf['show_exif'] or $conf['show_iptc'])
-    and isset($picture['current']['image_path'])
+    and !$picture['current']['src_image']->is_mimetype()
     ),
-  $picture['current']['path']
+  $picture['current']
   );
 
@@ -653,12 +629,4 @@
 // allow plugins to change what we computed before passing data to template
 $picture = trigger_event('picture_pictures_data', $picture);
-
-
-if (isset($picture['next']['image_url'])
-    and $picture['next']['is_picture']
-    and strpos($_SERVER['HTTP_USER_AGENT'], 'Chrome/') === false)
-{
-  $template->assign('U_PREFETCH', $picture['next']['image_url'] );
-}
 
 //------------------------------------------------------- navigation management
@@ -673,5 +641,5 @@
         array(
           'TITLE' => $picture[$which_image]['name'],
-          'THUMB_SRC' => $picture[$which_image]['thumbnail'],
+          'THUMB_SRC' => $picture[$which_image]['derivatives'][IMG_THUMB]->get_url(),
           // Params slideshow was transmit to navigation buttons
           'U_IMG' =>
@@ -889,5 +857,5 @@
 
 // size in pixels
-if ($picture['current']['is_picture'] and isset($picture['current']['width']) )
+if ($picture['current']['src_image']->is_original() and isset($picture['current']['width']) )
 {
   $infos['INFO_DIMENSIONS'] =
@@ -981,4 +949,12 @@
 $template->assign( 'ELEMENT_CONTENT', $element_content );
 
+if (isset($picture['next'])
+    and $picture['next']['src_image']->is_original()
+    and strpos($_SERVER['HTTP_USER_AGENT'], 'Chrome/') === false)
+{
+  $template->assign('U_PREFETCH', $picture['next']['derivatives'][pwg_get_session_var('picture_deriv', IMG_LARGE)]->get_url() );
+}
+
+
 // +-----------------------------------------------------------------------+
 // |                               sub pages                               |
Index: /trunk/themes/clear/theme.css
===================================================================
--- /trunk/themes/clear/theme.css	(revision 12796)
+++ /trunk/themes/clear/theme.css	(revision 12797)
@@ -15,10 +15,10 @@
 }
 
-#menubar DL, .content, #imageToolBar, .header_notes {
+#menubar DL, .content, #imageToolBar, #derivativeSwitchLink, #derivativeSwitchBox, .header_notes {
   background-color: #eeeeee;
 }
 
 /* borders */
-#menubar DL, .content, #imageToolBar {
+#menubar DL, .content, #imageToolBar, #derivativeSwitchLink, #derivativeSwitchBox {
   border: 1px solid #d3d3d3;
 }
Index: /trunk/themes/dark/theme.css
===================================================================
--- /trunk/themes/dark/theme.css	(revision 12796)
+++ /trunk/themes/dark/theme.css	(revision 12797)
@@ -17,5 +17,5 @@
 }
 
-#menubar DL, .content, #imageToolBar, #imageHeaderBar, .header_notes {
+#menubar DL, .content, #imageToolBar, #imageHeaderBar, #derivativeSwitchLink, #derivativeSwitchBox, .header_notes {
 	background-color: #505050;
 }
@@ -35,5 +35,5 @@
 
 /* borders */
-#menubar DL, .content{
+#menubar DL, .content, #derivativeSwitchLink, #derivativeSwitchBox{
 	border: 1px solid #000;
 }
Index: /trunk/themes/default/template/picture_content.tpl
===================================================================
--- /trunk/themes/default/template/picture_content.tpl	(revision 12796)
+++ /trunk/themes/default/template/picture_content.tpl	(revision 12797)
@@ -5,5 +5,5 @@
 {if count($current.available_derivative_types)>1}
 {footer_script}{literal}
-function changeImgSrc(url,type)
+function changeImgSrc(url,type,display)
 {
 	var theImg = document.getElementById("theMainImage");
@@ -12,12 +12,30 @@
 		theImg.removeAttribute("width");theImg.removeAttribute("height");
 		theImg.src = url;
+		var elt = document.getElementById("derivativeSwitchLink");
+		if (elt) elt.innerHTML = display;
 	}
 	document.cookie = 'picture_deriv=' + type;
 }
+
+function toggleDerivativeSwitchBox()
+{
+	var elt = document.getElementById("derivativeSwitchBox"),
+		ePos = document.getElementById("derivativeSwitchLink");
+	if (elt.style.display==="none")
+	{
+		elt.style.position = "absolute";
+		elt.style.left = (ePos.offsetLeft + 10) + "px";
+		elt.style.top = (ePos.offsetTop + ePos.offsetHeight) + "px";
+		elt.style.display="";
+	}
+	else
+		elt.style.display="none";
+}
 {/literal}{/footer_script}
-<p>
+<a id="derivativeSwitchLink" onclick="toggleDerivativeSwitchBox()" style="cursor:pointer">{$current.selected_derivative->get_type()|@translate}</a>
+<div id="derivativeSwitchBox" onclick="toggleDerivativeSwitchBox()" style="display:none">
 {foreach from=$current.available_derivative_types item=derivative_type}
-<a onclick="changeImgSrc('{$current.derivatives[$derivative_type]->get_url()|@escape:javascript}', '{$derivative_type}')" title="{$current.derivatives[$derivative_type]->get_size_hr()}">{$derivative_type}</a>
+<a onclick="changeImgSrc('{$current.derivatives[$derivative_type]->get_url()|@escape:javascript}', '{$derivative_type}', '{$derivative_type|@translate|@escape:javascript}')" style="cursor:pointer">{$derivative_type|@translate} ({$current.derivatives[$derivative_type]->get_size_hr()})</a><br>
 {/foreach}
-</p>
+</div>
 {/if}
Index: /trunk/themes/default/theme.css
===================================================================
--- /trunk/themes/default/theme.css	(revision 12796)
+++ /trunk/themes/default/theme.css	(revision 12797)
@@ -338,4 +338,17 @@
 #imageToolBar .pwg-button {width:42px;}
 
+
+#derivativeSwitchLink {
+	padding: 0.2em;
+	position: absolute;
+	left: 5px;
+	top: 100px;
+}
+
+#derivativeSwitchBox {
+	padding: 0.5em;
+	border-radius: 4px;
+	z-index: 100;
+}
 
 #theImage {
