Битрикс - хорошая (отличной не назовёшь) система управления сайтами. И всё в ней хорошо, даже API есть, если не хватает компонентов (а мне, последнее время, попадаются как-раз специфические задачи, которые компонентами не решить).
Так вот, неоднократно мне понадобилось обжимать картинки на Битрикс-сайтах.
Встроенный CFile::ShowImage() всего-навсего задаёт width и height у картинок, что, в большинстве случаев, неприемлемо. Так и был придуман этот незаурядный способ ресайза картинок на лету.
Итак, по порядку:
- Создаём папку resized в корневой директории сайта (mkdir resized)
- Создаём resize.php в корне, со следующим содержимым:
<?php
if ( $_GET['f'] && ($_GET['x'] && $_GET['x'] <= 1440) ) {
createThumb( '.' . base64_decode( $_GET['f'] ), ('./resized/' . $_GET['f'] . '>' .$_GET['x']), $_GET['x'] );
}
function createThumb($resource, $dest, $x_scale) {
$check = GetImageSize ( $resource );
$y_scale = floor ( $x_scale / ( $check [0] / $check [1] ) );
$im_dest = imagecreatetruecolor ( $x_scale, $y_scale );
if ($check [2] == IMAGETYPE_JPEG) {
$im_src = ImageCreateFromJPEG ( $resource );
} elseif ($check [2] == IMAGETYPE_GIF) {
$im_src = ImageCreateFromGIF ( $resource );
} elseif ($check [2] == IMAGETYPE_PNG) {
$im_src = imagecreatefrompng ( $resource );
}
if ($im_src && ImageCopyResampled ( $im_dest, $im_src, 0, 0, 0, 0, $x_scale, $y_scale, $check [0], $check [1] )) {
if ($check [2] == IMAGETYPE_JPEG) {
header('Content-type: image/jpeg');
return ImageJPEG ( $im_dest, $dest, 99 ) && ImageJPEG ( $im_dest, null, 99 );
} elseif ($check [2] == IMAGETYPE_GIF) {
header('Content-type: image/gif');
return ImageGIF ( $im_dest, $dest, 99 ) && ImageGIF ( $im_dest, null, 99 );
} elseif ($check [2] == IMAGETYPE_PNG) {
header('Content-type: image/png');
return imagepng ( $im_dest, $dest, 99 ) && imagepng ( $im_dest, null, 99 );
}
}
return 0;
}
?>
- Редактируем .htaccess (или создаём, если его нет):
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^resized/([a-zA-Z0-9=]+)>([0-9]{1,3})$ /resize.php?f=$1&x=$2 [QSA,L]
</IfModule>
- Добавляем хелпер в /bitrix/header.php (или другой файл, который инклудится везде):
<?php
// Bitrix line
require_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog.php");
// Our helper
function resizeHelper( $path, $x, $addi = '' ) {
$path = '/resized/'
. base64_encode(
((string)(float)$path === (string)$path)
? CFile::GetPath( $path )
: $path
)
. '>' . $x;
return '<img src="' . $path .'" width="' . $x . '"' . $addi . '/>';
}
?>
- Вот и всё :)
Параметры resizeHelper():
- $path - путь к картинке или её Битрикс ID (что обычно и возвращается из инфоблока);
- $x - необходимая ширина картинки (высота вычисляется автоматически, пропорционально ширине);
- $addi - дополнительные параметры тега <img/>, которые будут просто вставлены (например, style="border:1px solid #666;padding:2px;margin-right:15px").
В папке /resized сохраняются картинки с новыми размерами (для каждого размера картинки - отдельный файл) - при повторном запросе, будет возвращена уже уменьшенная картинка (для этого-то мы и редактировали .htaccess).
Пример использования:
<?php
CModule::IncludeModule("iblock");
// Bitrix API GetList()
$x = CIBlockElement::GetList(
array(
'RAND' => 'ASC',
),
array(
'IBLOCK_ID'=> 8,
'>=DATE_ACTIVE_TO' => ConvertTimeStamp(
mktime(
0, 0, 0,
date( 'n' ),
date( 'j' )
),
'FULL'
),
'!PROPERTY_IMAGE_LEFT_VALUE' => 'false',
//'ID' => 69
),
false,
array(
//'nTopCount' => 1
),
array(
'IBLOCK_ID',
'PROPERTY_image_left',
'NAME',
'PREVIEW_TEXT',
'DETAIL_PAGE_URL',
'PREVIEW_PICTURE'
)
);
// Iterate over it
while ( $x && ($s = $x->GetNext()) ) {
if ( ($i = $s['PROPERTY_IMAGE_LEFT_VALUE']) or ($i = $s['PREVIEW_PICTURE']) ) {
// Below is out helper: put image $i (int or str), 330px wide, with border-styling (style="")
?>
<div><a href="<?=$s['DETAIL_PAGE_URL']?>"><?=resizeHelper($i, 330, 'style="border: 5px solid #fff;"')?></a></div>
<div class="info">
<h2><?=$s['NAME']?></h2>
<p>
<?=$s['PREVIEW_TEXT']?> <br><br>
<a class="more_1" href="<?=$s['DETAIL_PAGE_URL']?>">подробнее</a>
</p>
</div>
<?
break;
} else {
continue;
}
}
?>