Ресайз картинок на лету (для Битрикса и не только)

Битрикс - хорошая (отличной не назовёшь) система управления сайтами. И всё в ней хорошо, даже API есть, если не хватает компонентов (а мне, последнее время, попадаются как-раз специфические задачи, которые компонентами не решить).

Так вот, неоднократно мне понадобилось обжимать картинки на Битрикс-сайтах.
Встроенный CFile::ShowImage() всего-навсего задаёт width и height у картинок, что, в большинстве случаев, неприемлемо. Так и был придуман этот незаурядный способ ресайза картинок на лету.

Итак, по порядку:
  1. Создаём папку resized в корневой директории сайта (mkdir resized)
  2. Создаём resize.php в корне, со следующим содержимым:
    1. <?php
    2. if ( $_GET['f'] && ($_GET['x'] && $_GET['x'] <= 1440) ) {
    3. createThumb( '.' . base64_decode( $_GET['f'] ), ('./resized/' . $_GET['f'] . '>' .$_GET['x']), $_GET['x'] );
    4. }
    5. function createThumb($resource, $dest, $x_scale) {
    6. $check = GetImageSize ( $resource );
    7. $y_scale = floor ( $x_scale / ( $check [0] / $check [1] ) );
    8. $im_dest = imagecreatetruecolor ( $x_scale, $y_scale );
    9. if ($check [2] == IMAGETYPE_JPEG) {
    10. $im_src = ImageCreateFromJPEG ( $resource );
    11. } elseif ($check [2] == IMAGETYPE_GIF) {
    12. $im_src = ImageCreateFromGIF ( $resource );
    13. } elseif ($check [2] == IMAGETYPE_PNG) {
    14. $im_src = imagecreatefrompng ( $resource );
    15. }
    16. if ($im_src && ImageCopyResampled ( $im_dest, $im_src, 0, 0, 0, 0, $x_scale, $y_scale, $check [0], $check [1] )) {
    17. if ($check [2] == IMAGETYPE_JPEG) {
    18. header('Content-type: image/jpeg');
    19. return ImageJPEG ( $im_dest, $dest, 99 ) && ImageJPEG ( $im_dest, null, 99 );
    20. } elseif ($check [2] == IMAGETYPE_GIF) {
    21. header('Content-type: image/gif');
    22. return ImageGIF ( $im_dest, $dest, 99 ) && ImageGIF ( $im_dest, null, 99 );
    23. } elseif ($check [2] == IMAGETYPE_PNG) {
    24. header('Content-type: image/png');
    25. return imagepng ( $im_dest, $dest, 99 ) && imagepng ( $im_dest, null, 99 );
    26. }
    27. }
    28. return 0;
    29. }
    30. ?>
  3. Редактируем .htaccess (или создаём, если его нет):
    1. <IfModule mod_rewrite.c>
    2. RewriteEngine On
    3. RewriteCond %{REQUEST_FILENAME} !-f
    4. RewriteRule ^resized/([a-zA-Z0-9=]+)>([0-9]{1,3})$ /resize.php?f=$1&x=$2 [QSA,L]
    5. </IfModule>
  4. Добавляем хелпер в /bitrix/header.php (или другой файл, который инклудится везде):
    1. <?php
    2. // Bitrix line
    3. require_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog.php");
    4. // Our helper
    5. function resizeHelper( $path, $x, $addi = '' ) {
    6. $path = '/resized/'
    7. . base64_encode(
    8. ((string)(float)$path === (string)$path)
    9. ? CFile::GetPath( $path )
    10. : $path
    11. )
    12. . '>' . $x;
    13. return '<img src="' . $path .'" width="' . $x . '"' . $addi . '/>';
    14. }
    15. ?>
  5. Вот и всё :)

Параметры resizeHelper():
  1. $path - путь к картинке или её Битрикс ID (что обычно и возвращается из инфоблока);
  2. $x - необходимая ширина картинки (высота вычисляется автоматически, пропорционально ширине);
  3. $addi - дополнительные параметры тега <img/>, которые будут просто вставлены (например, style="border:1px solid #666;padding:2px;margin-right:15px").

В папке /resized сохраняются картинки с новыми размерами (для каждого размера картинки - отдельный файл) - при повторном запросе, будет возвращена уже уменьшенная картинка (для этого-то мы и редактировали .htaccess).

Пример использования:
  1. <?php
  2. CModule::IncludeModule("iblock");
  3. // Bitrix API GetList()
  4. $x = CIBlockElement::GetList(
  5. array(
  6. 'RAND' => 'ASC',
  7. ),
  8. array(
  9. 'IBLOCK_ID'=> 8,
  10. '>=DATE_ACTIVE_TO' => ConvertTimeStamp(
  11. mktime(
  12. 0, 0, 0,
  13. date( 'n' ),
  14. date( 'j' )
  15. ),
  16. 'FULL'
  17. ),
  18. '!PROPERTY_IMAGE_LEFT_VALUE' => 'false',
  19. //'ID' => 69
  20. ),
  21. false,
  22. array(
  23. //'nTopCount' => 1
  24. ),
  25. array(
  26. 'IBLOCK_ID',
  27. 'PROPERTY_image_left',
  28. 'NAME',
  29. 'PREVIEW_TEXT',
  30. 'DETAIL_PAGE_URL',
  31. 'PREVIEW_PICTURE'
  32. )
  33. );
  34. // Iterate over it
  35. while ( $x && ($s = $x->GetNext()) ) {
  36. if ( ($i = $s['PROPERTY_IMAGE_LEFT_VALUE']) or ($i = $s['PREVIEW_PICTURE']) ) {
  37. // Below is out helper: put image $i (int or str), 330px wide, with border-styling (style="")
  38. ?>
  39. <div><a href="<?=$s['DETAIL_PAGE_URL']?>"><?=resizeHelper($i, 330, 'style="border: 5px solid #fff;"')?></a></div>
  40. <div class="info">
  41. <h2><?=$s['NAME']?></h2>
  42. <p>
  43. <?=$s['PREVIEW_TEXT']?> <br><br>
  44. <a class="more_1" href="<?=$s['DETAIL_PAGE_URL']?>">подробнее</a>
  45. </p>
  46. </div>
  47. <?
  48. break;
  49. } else {
  50. continue;
  51. }
  52. }
  53. ?>

Комментариев нет:

Отправить комментарий