Сниппет позволяет выводить галерею в стиле Вконтакте или Яндекс.Картинок. Вот так, например:

Расскажу, как я этого добился и немного прокомментирую код сниппета.
Алгоритм ресайза изображений
Картинки по условиям обрезать нельзя, но они все равно должны быть одинаковыми по высоте и помещаться ровно в заданную ширину. Сразу скажу, что весь секрет в том, чтобы подобрать такую высоту картинок, чтобы при ресайзе до этой высоты всех картинок в строке их общая ширина была равна конкретному значению.
Давайте посмотрим, как высчитывается нужная высота картинок.
Сначала нужно узнать, сколько картинок будет в каждой строчке. Это количество мы узнаем от пользователя, который при вызове сниппета указывает параметр &lineLimit.
Дальше мы ресайзим все картинки в строке по наименьшей высоте, чтобы выровнять их. Например так:

После этого находим суммарную ширину получившихся картинок в строке:

Width = W_1 + W_2 + W_3
И находим нужную высоту умножением минимальной высоты картинок в строке на коэффициент ресайза, который равен:
&lineWidth / Widthгде &lineWidth — это требуемая ширина строки (которую задает пользователь при вызове сниппета), а Width — найденная в предыдущем шаге общая ширина.
Height = Height_Min * &lineWidth / Width
Реализация алгоритма в коде
Получаем картинки, разбитые на линии:
$i = 0; $Lines = array(); // каждый элемент этого массив - строка картинок $isItems = true; // проверяем, не кончились ли картинки while ($isItems) { $scriptProperties['outputSeparator'] = ','; $scriptProperties['limit'] = $lineLimit; $scriptProperties['offset'] = $i; // сколько всего картинок будет после текущей итерации $subTotal = $scriptProperties['offset'] + $lineLimit; // если предсказывается превышение лимита if ($limit && $subTotal > $limit) { /* изменяем лимит — например, при выводе пяти картинок по 3 в строке в последней итерации лимит должен быть равен 2, а не 3) */ $scriptProperties['limit'] = $limit - $scriptProperties['offset']; } // получаем список картинок для этой строки $result = $modx->runSnippet($snippet, $scriptProperties); // если картинки кончились, выход из цикла if (!$result) break; // превращаем список в JSON-массив $Lines[] = '{' . $result . '}'; // проверяем, все ли картинки вывелись $i = $i + $lineLimit; if ($i >= $limit) $isItems = false; }
И обрабатываем каждую строку с помощью нашего алгоритма:
foreach ($Lines as $line) { // получаем обычный массив картинок $line = $modx->fromJSON($line); $images = $w = $h = array(); // вычисляем размеры каждой картинки foreach ($line as $id => $img) { // убираем слеш в начале пути if (substr($img,0,1) == '/') $img = substr($img,1); // если указано, что нужно обрезать лишний фон, выполняем if ($crop) { // используем для этого Imagik - в MODX есть по умолчанию $im = new Imagick($img); // обрезаем фон $im->trimImage(0); // готовим новое имя картинки, чтобы сохранить ее $path_info = pathinfo($img); $cropedFile = $path_info['dirname'].'/croped-'.$lineWidth.'/'; if (!file_exists($cropedFile)) mkdir($cropedFile); $cropedFile .= $path_info['basename']; // и, собственно, сохраняем $im->writeImage($cropedFile); $img = $cropedFile; } // узнаем высоту и ширину картинки $size = getimagesize($img); $w[] = $size[0]; $h[] = $size[1]; $images[$id] = $img; } /* ресайзить картинки по наименьшей высоте не будем — вдруг, потом придется их обратно увеличивать? Просто высчитываем, какой была бы ширина отресайзенных картинок */ foreach ($w as $k => $w_old) { $w[$k] = floor($w_old * min($h) / $h[$k]); } // высчитываем требуемую высоту $lineHeight = floor(min($h) * $lineWidth / array_sum($w)); // и ресайзим картинки по этой высоте foreach ($images as $id => $image) { $ph = $tvPrefix.$processImage; $im = new Imagick($image); $im->resizeImage(0,$lineHeight,0,1); // новое имя картинки, уже отресайзеной $path_info = pathinfo($image); $image = $path_info['dirname'].'/h-'.$lineHeight.'/'; if (!file_exists($image)) mkdir($image); $image .= $path_info['basename']; // сохраняем картинку $im->writeImage($image); // и показываем пользователю $output .= $modx->getChunk($template, array($ph => $image , 'id' => $id , 'album' => $scriptProperties['album']))."\n"; } } return $output;
Результат

И еще совет напоследок — устанавливайте значение параметра &lineWidth на 10-15 пикселей меньше контейнера, чтобы между изображениями было расстояние и картинки не «слипались». G+
UPD. Pashkevich Aleksandr переработал компонент, выложил его в репозиторий MODX. Описание.
Для ms2Gallery не появлялось готового решения?
А вдруг?)))
Т.е., ну создает свои превьюшки ms2Gallery и пусть создает, можно в источнике указать минимальное количество ее собственных превьюшек.
Или это лучше делать на JavaScript?