Index: /trunk/admin/derivatives_build.php
===================================================================
--- /trunk/admin/derivatives_build.php	(revision 12865)
+++ /trunk/admin/derivatives_build.php	(revision 12865)
@@ -0,0 +1,30 @@
+<?php
+// +-----------------------------------------------------------------------+
+// | Piwigo - a PHP based photo gallery                                    |
+// +-----------------------------------------------------------------------+
+// | Copyright(C) 2008-2011 Piwigo Team                  http://piwigo.org |
+// | Copyright(C) 2003-2008 PhpWebGallery Team    http://phpwebgallery.net |
+// | Copyright(C) 2002-2003 Pierrick LE GALL   http://le-gall.net/pierrick |
+// +-----------------------------------------------------------------------+
+// | This program is free software; you can redistribute it and/or modify  |
+// | it under the terms of the GNU General Public License as published by  |
+// | the Free Software Foundation                                          |
+// |                                                                       |
+// | This program is distributed in the hope that it will be useful, but   |
+// | WITHOUT ANY WARRANTY; without even the implied warranty of            |
+// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      |
+// | General Public License for more details.                              |
+// |                                                                       |
+// | You should have received a copy of the GNU General Public License     |
+// | along with this program; if not, write to the Free Software           |
+// | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
+// | USA.                                                                  |
+// +-----------------------------------------------------------------------+
+
+defined('PHPWG_ROOT_PATH') or trigger_error('Hacking attempt!', E_USER_ERROR);
+
+$template->assign('derivatives', array_keys(ImageStdParams::get_defined_type_map()));
+
+$template->set_filename('derivatives', 'derivatives_build.tpl');
+$template->assign_var_from_handle('ADMIN_CONTENT', 'derivatives');
+?>
Index: /trunk/admin/include/functions.php
===================================================================
--- /trunk/admin/include/functions.php	(revision 12864)
+++ /trunk/admin/include/functions.php	(revision 12865)
@@ -201,9 +201,6 @@
     $files[] = get_element_path($row);
 
-   
     if (!empty($row['representative_ext']))
     {
-      $pi = pathinfo($row['path']);
-      $file_wo_ext = get_filename_wo_extension($pi['basename']);
       $files[] = original_to_representative( $files[0], $row['representative_ext']);
     }
Index: /trunk/admin/include/image.class.php
===================================================================
--- /trunk/admin/include/image.class.php	(revision 12864)
+++ /trunk/admin/include/image.class.php	(revision 12865)
@@ -705,4 +705,5 @@
 		imagecopy($cut, $ioverlay, 0, 0, 0, 0, $ow, $oh);
 		imagecopymerge($this->image, $cut, $x, $y, 0, 0, $ow, $oh, $opacity);
+    imagedestroy($cut);
     return true;
   }
Index: /trunk/admin/themes/default/template/derivatives.tpl
===================================================================
--- /trunk/admin/themes/default/template/derivatives.tpl	(revision 12864)
+++ /trunk/admin/themes/default/template/derivatives.tpl	(revision 12865)
@@ -23,4 +23,5 @@
 {/literal}{/html_head}
 
+<p><a href="admin.php?page=derivatives_build">Build missing derivatives</a></p>
 <form method="post" id="derviativesForm">
 <fieldset>
Index: /trunk/admin/themes/default/template/derivatives_build.tpl
===================================================================
--- /trunk/admin/themes/default/template/derivatives_build.tpl	(revision 12865)
+++ /trunk/admin/themes/default/template/derivatives_build.tpl	(revision 12865)
@@ -0,0 +1,152 @@
+{html_head}{literal}
+<style type="text/css">
+TABLE {
+	font-size: larger;
+}
+</style>
+{/literal}{/html_head}
+
+<p>
+	<select id="types" name="types[]" multiple="multiple">
+	{foreach from=$derivatives item=type}
+	<option value="{$type}" selected="selected">{$type|@translate}</option>
+	{/foreach}
+	</select>
+	<input id="startLink" value="{'Start'|@translate}" onclick="start()" type="button">
+	<input id="pauseLink" value="{'Pause'|@translate}" onclick="pause()" type="button" disabled="disbled">
+	<input id="stopLink" value="{'Stop'|@translate}" onclick="stop()" type="button" disabled="disbled">
+</p>
+<hr/>
+<p>
+<table>
+	<tr>
+		<td>Errors</td>
+		<td id="errors">0</td>
+	</tr>
+	<tr>
+		<td>Loaded</td>
+		<td id="loaded">0</td>
+	</tr>
+	<tr>
+		<td>Remaining</td>
+		<td id="remaining">0</td>
+	</tr>
+</table>
+<div id="feedbackWrap" style="height:320px; min-height:320px;">
+<img id="feedbackImg">
+</div>
+</p>
+
+<div id="errorList">
+</div>
+
+{combine_script id='iloader' load='footer' path='themes/default/js/image.loader.js'}
+
+{footer_script require='jquery.effects.slide'}{literal}
+
+var loader = new ImageLoader( {onChanged: loaderChanged} )
+	, pending_next_page = null
+	, last_image_show_time = 0
+	, allDoneDfd, urlDfd;
+
+function start() {
+	allDoneDfd = jQuery.Deferred();
+	urlDfd = jQuery.Deferred();
+
+	allDoneDfd.always( function() {
+			jQuery("#startLink").attr('disabled', false).css("opacity", 1);
+			jQuery("#pauseLink,#stopLink").attr('disabled', true).css("opacity", 0.5);
+		} );
+
+	urlDfd.always( function() {
+		if (loader.remaining()==0)
+			allDoneDfd.resolve();
+		} );
+
+	jQuery("#startLink").attr('disabled', true).css("opacity", 0.5);
+	jQuery("#pauseLink,#stopLink").attr('disabled', false).css("opacity", 1);
+
+	loader.pause(false);
+	updateStats();
+	getUrls();
+}
+
+function pause() {
+	loader.pause( !loader.pause() );
+}
+
+function stop() {
+	loader.clear();
+	urlDfd.resolve();
+}
+
+function getUrls(page_token) {
+	data = {max_urls: 500, types: []};
+	jQuery.each(jQuery("#types").serializeArray(), function(i, t) {
+			data.types.push( t.value );
+		} );
+
+	if (page_token)
+		data['prev_page'] = page_token;
+	jQuery.post( '{/literal}{$ROOT_URL}{literal}ws.php?format=json&method=pwg.getMissingDerivatives',
+		data, wsData, "json").fail( wsError );
+}
+
+function wsData(data) {
+	if (!data.stat || data.stat != "ok") {
+		wsError();
+		return;
+	}
+	loader.add( data.result.urls );
+	if (data.result.next_page) {
+		if (loader.pause() || loader.remaining() > 100) {
+			pending_next_page = data.result.next_page;
+		}
+		else {
+			getUrls(data.result.next_page);
+		}
+	}
+}
+
+function wsError() {
+	urlDfd.reject();
+}
+
+function updateStats() {
+	jQuery("#loaded").text( loader.loaded );
+	jQuery("#errors").text( loader.errors );
+	jQuery("#remaining").text( loader.remaining() );
+}
+
+function loaderChanged(type, img) {
+	updateStats();
+	if (img) {
+		if (type==="load") {
+			var now = jQuery.now();
+			if (now - last_image_show_time > 3000) {
+				last_image_show_time = now;
+				var h=img.height, url=img.src;
+				jQuery("#feedbackWrap").hide("slide", {direction:'down'}, function() {
+					last_image_show_time = jQuery.now();
+					if (h > 300 )
+						jQuery("#feedbackImg").attr("height", 300);
+					else
+						jQuery("#feedbackImg").removeAttr("height");
+					jQuery("#feedbackImg").attr("src", url);
+					jQuery("#feedbackWrap").show("slide", {direction:'up'} );
+					} );
+			}
+		}
+		else {
+			jQuery("#errorList").prepend( '<a href="'+img.src+'">'+img.src+'</a>' + "<br>");
+		}
+	}
+	if (pending_next_page && 100 > loader.remaining() )	{
+		getUrls(pending_next_page);
+		pending_next_page = null;
+	}
+	else if (loader.remaining() == 0 && (urlDfd.isResolved() || urlDfd.isRejected()))	{
+		allDoneDfd.resolve();
+	}
+}
+{/literal}{/footer_script}
Index: /trunk/i.php
===================================================================
--- /trunk/i.php	(revision 12864)
+++ /trunk/i.php	(revision 12865)
@@ -109,4 +109,8 @@
   {
     $req = $_SERVER["QUERY_STRING"];
+    if ($pos=strpos($req, '&'))
+    {
+      $req = substr($req, 0, $pos);
+    }
     /*foreach (array_keys($_GET) as $keynum => $key)
     {
@@ -168,9 +172,17 @@
     try
     {
-      $page['derivative_params'] = DerivativeParams::from_url_tokens($deriv);
+      $params = $page['derivative_params'] = DerivativeParams::from_url_tokens($deriv);
     }
     catch (Exception $e)
     {
       ierror($e->getMessage(), 400);
+    }
+    if ($params->sizing->ideal_size[0] < 20 or $params->sizing->ideal_size[1] < 20)
+    {
+      ierror('Invalid size', 400);
+    }
+    if ($params->sizing->max_crop < 0 or $params->sizing->max_crop > 1)
+    {
+      ierror('Invalid crop', 400);
     }
   }
@@ -225,12 +237,4 @@
 
 $params = $page['derivative_params'];
-if ($params->sizing->ideal_size[0] < 20 or $params->sizing->ideal_size[1] < 20)
-{
-  ierror('Invalid size', 400);
-}
-if ($params->sizing->max_crop < 0 or $params->sizing->max_crop > 1)
-{
-  ierror('Invalid crop', 400);
-}
 
 $src_mtime = @filemtime($page['src_path']);
@@ -251,5 +255,10 @@
 $expires=false;
 $now = time();
-if ( $now > (max($src_mtime, $params->last_mod_time) + 24*3600) )
+if ( isset($_GET['b']) )
+{
+  $expires = $now + 100;
+  header("Cache-control: no-store, max-age=100");
+}
+elseif ( $now > (max($src_mtime, $params->last_mod_time) + 24*3600) )
 {// somehow arbitrary - if derivative params or src didn't change for the last 24 hours, we send an expire header for several days
   $expires = $now + 10*24*3600;
@@ -268,4 +277,8 @@
 }
 
+if (!mkgetdir(dirname($page['derivative_path'])))
+{
+  ierror("dir create error", 500);
+}
 
 include_once(PHPWG_ROOT_PATH . 'admin/include/image.class.php');
@@ -275,9 +288,4 @@
 
 $image = new pwg_image($page['src_path']);
-
-if (!mkgetdir(dirname($page['derivative_path'])))
-{
-  ierror("dir create error", 500);
-}
 
 $changes = 0;
@@ -326,4 +334,13 @@
     {
       // todo
+      $pad = $wm_size[0] + max(30, round($wm_size[0]/4));
+      for($i=-$wm->xrepeat; $i<=$wm->xrepeat; $i++)
+      {
+        if (!$i) continue;
+        $x2 = $x + $i * $pad;
+        if ($x2>=0 && $x2+$wm_size[0]<$d_size[0])
+          if (!$image->compose($wm_image, $x2, $y, $wm->opacity))
+            break;
+      }
     }
   }
Index: /trunk/include/derivative.inc.php
===================================================================
--- /trunk/include/derivative.inc.php	(revision 12864)
+++ /trunk/include/derivative.inc.php	(revision 12865)
@@ -220,4 +220,9 @@
   }
 
+  function get_path()
+  {
+    return PHPWG_ROOT_PATH.$this->rel_path;
+  }
+
   function get_url()
   {
Index: /trunk/include/ws_functions.inc.php
===================================================================
--- /trunk/include/ws_functions.inc.php	(revision 12864)
+++ /trunk/include/ws_functions.inc.php	(revision 12865)
@@ -93,7 +93,7 @@
     $clauses[] = $tbl_name.'width/'.$tbl_name.'height<='.$params['f_max_ratio'];
   }
-  if ( $params['f_with_thumbnail'] )
-  {
-    $clauses[] = $tbl_name.'tn_ext IS NOT NULL';
+  if (is_numeric($params['f_max_level']) )
+  {
+    $clauses[] = $tbl_name.'level <= '.$params['f_max_level'];
   }
   return $clauses;
@@ -148,5 +148,5 @@
 {
   $ret = array();
-  
+
   $src_image = new SrcImage($image_row);
 
@@ -156,5 +156,5 @@
     $ret['element_url'] = get_element_url($image_row);
   }
-  
+
   $derivatives = DerivativeImage::get_all($src_image);
   $derivatives_arr = array();
@@ -178,4 +178,90 @@
     'id','element_url', 'file','width','height','hit','date_available','date_creation'
     );
+}
+
+function ws_getMissingDerivatives($params, &$service)
+{
+  if (!is_admin())
+  {
+    return new PwgError(403, 'Forbidden');
+  }
+
+  if ( empty($params['types']) )
+  {
+    $types = array_keys(ImageStdParams::get_defined_type_map());
+  }
+  else
+  {
+    $types = array_intersect(array_keys(ImageStdParams::get_defined_type_map()), $params['types']);
+    if (count($types)==0)
+    {
+      return new PwgError(WS_ERR_INVALID_PARAM, "Invalid types");
+    }
+  }
+
+  if ( ($max_urls = intval($params['max_urls'])) <= 0)
+  {
+    return new PwgError(WS_ERR_INVALID_PARAM, "Invalid max_urls");
+  }
+
+  list($max_id, $image_count) = pwg_db_fetch_row( pwg_query('SELECT MAX(id)+1, COUNT(*) FROM '.IMAGES_TABLE) );
+  $start_id = intval($params['prev_page']);
+  if ($start_id<=0)
+  {
+    $start_id = $max_id;
+  }
+
+  $uid = '&b='.time();
+  global $conf;
+  $conf['question_mark_in_urls'] = $conf['php_extension_in_urls'] = true;
+  $conf['derivative_url_style']=2; //script
+
+  $qlimit = min(5000, ceil(max($image_count/500, $max_urls/count($types))));
+  $where_clauses = ws_std_image_sql_filter( $params, '' );
+  $where_clauses[] = 'id<start_id';
+
+  $query_model = 'SELECT id, path, representative_ext, width, height
+  FROM '.IMAGES_TABLE.'
+  WHERE '.implode(' AND ', $where_clauses).'
+  ORDER BY id DESC
+  LIMIT '.$qlimit;
+
+  $urls=array();
+  do
+  {
+    $result = pwg_query( str_replace('start_id', $start_id, $query_model));
+    $is_last = pwg_db_num_rows($result) < $qlimit;
+    while ($row=pwg_db_fetch_assoc($result))
+    {
+      $start_id = $row['id'];
+      $src_image = new SrcImage($row);
+      if ($src_image->is_mimetype())
+        continue;
+      foreach($types as $type)
+      {
+        $derivative = new DerivativeImage($type, $src_image);
+        if ($type != $derivative->get_type())
+          continue;
+        if (@filemtime($derivative->get_path())===false)
+        {
+          $urls[] = $derivative->get_url().$uid;
+        }
+      }
+      if (count($urls)>=$max_urls && !$is_last)
+        break;
+    }
+    if ($is_last)
+    {
+      $start_id = 0;
+    }
+  }while (count($urls)<$max_urls && $start_id);
+
+  $ret = array();
+  if ($start_id)
+  {
+    $ret['next_page']=$start_id;
+  }
+  $ret['urls']=$urls;
+  return $ret;
 }
 
@@ -515,5 +601,5 @@
   $user_representative_updates_for = array();
   // management of the album thumbnail -- stops here
-  
+
   $cats = array();
   while ($row = pwg_db_fetch_assoc($result))
@@ -553,5 +639,5 @@
 
     // management of the album thumbnail -- starts here
-    // 
+    //
     // on branch 2.3, the algorithm is duplicated from
     // include/category_cats, but we should use a common code for Piwigo 2.4
@@ -604,5 +690,5 @@
       }
     }
-    
+
     if (isset($image_id))
     {
@@ -611,5 +697,5 @@
         $user_representative_updates_for[ $user['id'].'#'.$row['id'] ] = $image_id;
       }
-    
+
       $row['representative_picture_id'] = $image_id;
       array_push($image_ids, $image_id);
@@ -651,5 +737,5 @@
         // * register it at user_representative_picture_id
         // * set it as the representative_picture_id for the category
-        
+
         foreach ($categories as &$category)
         {
@@ -658,15 +744,15 @@
             // searching a random representant among elements in sub-categories
             $image_id = get_random_image_in_category($category);
-            
+
             if (isset($image_id) and !in_array($image_id, $image_ids))
             {
               array_push($new_image_ids, $image_id);
             }
-            
+
             if ($conf['representative_cache_on_level'])
             {
               $user_representative_updates_for[ $user['id'].'#'.$category['id'] ] = $image_id;
             }
-            
+
             $category['representative_picture_id'] = $image_id;
           }
@@ -675,5 +761,5 @@
       }
     }
-    
+
     if (count($new_image_ids) > 0)
     {
@@ -697,9 +783,9 @@
   {
     $updates = array();
-  
+
     foreach ($user_representative_updates_for as $user_cat => $image_id)
     {
       list($user_id, $cat_id) = explode('#', $user_cat);
-    
+
       array_push(
         $updates,
@@ -736,5 +822,5 @@
     unset($cat['count_categories']);
   }
-  unset($cat);  
+  unset($cat);
   // management of the album thumbnail -- stops here
 
@@ -1531,5 +1617,5 @@
   // check dumped thumbnail md5
   $dumped_md5 = md5_file($file_path);
-  if ($dumped_md5 != $file_sum) 
+  if ($dumped_md5 != $file_sum)
   {
     return new PwgError(500, '[add_file] '.$type.' transfer failed');
@@ -1666,14 +1752,14 @@
   {
     ws_logfile('[pwg.images.add] resize activated');
-    
+
     // temporary file path
     $type = 'file';
     $file_path = $conf['upload_dir'].'/buffer/'.$params['original_sum'].'-'.$type;
-    
+
     merge_chunks($file_path, $params['original_sum'], $type);
     chmod($file_path, 0644);
 
     include_once(PHPWG_ROOT_PATH.'admin/include/functions_upload.inc.php');
-    
+
     $image_id = add_uploaded_file(
       $file_path,
@@ -1704,9 +1790,9 @@
     $filename_wo_ext = $date_string.'-'.$random_string;
     $file_path = $upload_dir.'/'.$filename_wo_ext.'.jpg';
-    
+
     // add files
     $file_infos  = add_file($file_path, 'file',  $params['original_sum'], $params['file_sum']);
     $thumb_infos = add_file($file_path, 'thumb', $params['original_sum'], $params['thumbnail_sum']);
-    
+
     if (isset($params['high_sum']))
     {
@@ -1763,5 +1849,5 @@
     }
   }
-  
+
   if (count(array_keys($update)) > 0)
   {
@@ -1774,5 +1860,5 @@
 
   $url_params = array('image_id' => $image_id);
-  
+
   // let's add links between the image and the categories
   if (isset($params['categories']))
@@ -1782,5 +1868,5 @@
     if (preg_match('/^\d+/', $params['categories'], $matches)) {
       $category_id = $matches[0];
-    
+
       $query = '
 SELECT id, name, permalink
@@ -1790,5 +1876,5 @@
       $result = pwg_query($query);
       $category = pwg_db_fetch_assoc($result);
-      
+
       $url_params['section'] = 'categories';
       $url_params['category'] = $category;
@@ -1958,14 +2044,14 @@
     return new PwgError(WS_ERR_INVALID_PARAM, 'Invalid user_id');
   }
-  
+
   $query = '
 DELETE FROM '.RATE_TABLE.'
   WHERE user_id='.$user_id;
-  
+
   if (!empty($params['anonymous_id']))
   {
     $query .= ' AND anonymous_id=\''.$params['anonymous_id'].'\'';
   }
-  
+
   $changes = pwg_db_changes(pwg_query($query));
   if ($changes)
@@ -3275,5 +3361,5 @@
     return new PwgError(403, "image can't be resized");
   }
-  
+
   $hd_path = get_high_path($image);
 
@@ -3285,5 +3371,5 @@
       $hd_dir = dirname($hd_path);
       prepare_directory($hd_dir);
-      
+
       rename($image_path, $hd_path);
       $hd_infos = pwg_image_infos($hd_path);
Index: /trunk/themes/default/js/image.loader.js
===================================================================
--- /trunk/themes/default/js/image.loader.js	(revision 12865)
+++ /trunk/themes/default/js/image.loader.js	(revision 12865)
@@ -0,0 +1,84 @@
+
+function ImageLoader(opts) {
+	this.opts = jQuery.extend( {
+			maxRequests: 6,
+			onChanged: jQuery.noop
+		}, opts||{} );
+}
+
+ImageLoader.prototype = {
+	loaded: 0,
+	errors: 0,
+	errorEma: 0,
+
+	pause: false,
+
+	current: [],
+	queue: [],
+	pool: [],
+
+	remaining: function() {
+		return this.current.length + this.queue.length;
+	},
+
+	add: function(urls) {
+		this.queue = this.queue.concat( urls );
+		this._fireChanged("add");
+		this._checkQueue();
+	},
+
+	clear: function() {
+		this.queue.length = 0;
+		while (this.current.length)
+			jQuery( this.current.pop() ).unbind();
+		this.loaded = this.errors = this.errorEma = 0;
+	},
+
+	pause: function(val) {
+		if (val !== undefined)
+		{
+			this.paused = val;
+			this._checkQueue();
+		}
+		return this.paused;
+	},
+
+	_checkQueue: function() {
+		while (!this.paused
+			&& this.queue.length
+			&& this.current.length < this.opts.maxRequests)
+		{
+			this._processOne( this.queue.shift() );
+		}
+	},
+
+	_processOne: function(url) {
+		var img = this.pool.shift() || new Image;
+		this.current.push(img);
+		var that = this;
+		jQuery(img).bind( "load error abort", function(e) {
+		//img.onload = function(e) {
+			jQuery(img).unbind();
+			img.onload=null;
+			that.current.splice(jQuery.inArray(img, that.current), 1);
+			if (e.type==="load") {
+				that.loaded++;
+				that.errorEma *= 0.9;
+			}
+			else {
+				that.errors++;
+				that.errorEma++;
+				if (that.errorEma>=20 && that.errorEma<21)
+					that.paused = true;
+			}
+			that._fireChanged(e.type, img);
+			that._checkQueue();
+			that.pool.push(img);
+		} );
+		img.src = url;
+	},
+
+	_fireChanged: function(type, img) {
+		this.opts.onChanged(type, img);
+	}
+}
Index: /trunk/themes/default/template/picture_content.tpl
===================================================================
--- /trunk/themes/default/template/picture_content.tpl	(revision 12864)
+++ /trunk/themes/default/template/picture_content.tpl	(revision 12865)
@@ -33,5 +33,5 @@
 }
 {/literal}{/footer_script}
-<a id="derivativeSwitchLink" onclick="toggleDerivativeSwitchBox()" style="cursor:pointer">{$current.selected_derivative->get_type()|@translate}</a>
+<a id="derivativeSwitchLink" href="javascript:toggleDerivativeSwitchBox()">{$current.selected_derivative->get_type()|@translate}</a>
 <div id="derivativeSwitchBox" onclick="toggleDerivativeSwitchBox()" style="display:none">
 {foreach from=$current.unique_derivatives item=derivative key=derivative_type}
@@ -39,5 +39,5 @@
 {/foreach}
 {if isset($U_ORIGINAL)}
-<a  href="javascript:phpWGOpenWindow('{$U_ORIGINAL}','xxx','scrollbars=yes,toolbar=no,status=no,resizable=yes')" title="{'Click on the photo to see it in high definition'|@translate}">{'original'|@translate}</a>
+<a href="javascript:phpWGOpenWindow('{$U_ORIGINAL}','xxx','scrollbars=yes,toolbar=no,status=no,resizable=yes')" title="{'Click on the photo to see it in high definition'|@translate}">{'original'|@translate}</a>
 {/if}
 </div>
Index: /trunk/ws.php
===================================================================
--- /trunk/ws.php	(revision 12864)
+++ /trunk/ws.php	(revision 12865)
@@ -70,5 +70,5 @@
         'f_min_ratio' => array( 'default'=> null ),
         'f_max_ratio' => array( 'default'=> null ),
-        'f_with_thumbnail' => array( 'default'=> false ),
+        'f_max_level' => array( 'default'=> null ),
       ),
       'Returns elements for the corresponding categories.
@@ -86,4 +86,23 @@
       ),
       'retrieves a list of categories (tree_output option only compatible with json/php output format' );
+
+  $service->addMethod('pwg.getMissingDerivatives', 'ws_getMissingDerivatives',
+      array(
+        'types' => array( 'default'=>array(), 'flags'=>WS_PARAM_FORCE_ARRAY),
+        'max_urls' => array( 'default' => 200 ),
+        'prev_page' => array( 'default'=> null),
+        'f_min_rate' => array( 'default'=> null ),
+        'f_max_rate' => array( 'default'=> null ),
+        'f_min_hit' => array( 'default'=> null ),
+        'f_max_hit' => array( 'default'=> null ),
+        'f_min_date_available' => array( 'default'=> null ),
+        'f_max_date_available' => array( 'default'=> null ),
+        'f_min_date_created' => array( 'default'=> null ),
+        'f_max_date_created' => array( 'default'=> null ),
+        'f_min_ratio' => array( 'default'=> null ),
+        'f_max_ratio' => array( 'default'=> null ),
+        'f_max_level' => array( 'default'=> null ),
+      ),
+      'retrieves a list of derivatives to build' );
 
   $service->addMethod('pwg.images.addComment', 'ws_images_addComment',
@@ -130,5 +149,5 @@
         'f_min_ratio' => array( 'default'=> null ),
         'f_max_ratio' => array( 'default'=> null ),
-        'f_with_thumbnail' => array( 'default'=> false ),
+        'f_max_level' => array( 'default'=> null ),
       ),
       'Returns elements for the corresponding query search.'
@@ -193,5 +212,5 @@
         'f_min_ratio' => array( 'default'=> null ),
         'f_max_ratio' => array( 'default'=> null ),
-        'f_with_thumbnail' => array( 'default'=> false ),
+        'f_max_level' => array( 'default'=> null ),
       ),
       'Returns elements for the corresponding tags. Note that tag_id, tag_url_name, tag_name an be arrays. Fill at least one of them. '
