Title
<?php
// Файл: crop_all_product_images_fixed.php
define('BX_BUFFER_USED', true);
define('NO_KEEP_STATISTIC', true);
define('NOT_CHECK_PERMISSIONS', true);
define('BX_NO_ACCELERATOR_RESET', true);
require($_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_before.php');
use Bitrix\Main\Loader;
use Bitrix\Iblock\ElementTable;
use Bitrix\Iblock\IblockTable;
// 1. Подключаем модули
if (!Loader::includeModule('iblock') || !Loader::includeModule('catalog')) {
die('Не удалось подключить модули инфоблоков и каталога');
}
// 2. Настройки
$targetWidth = 1600;
$targetHeight = 1200;
$quality = 85;
// 3. Получаем ID ВСЕХ инфоблоков, которые содержат товары
// Ищем инфоблоки с типом "Каталог товаров" (1C)
$catalogIblockIds = [];
// Способ 1: через CatalogIblockTable
$catalogs = \Bitrix\Catalog\CatalogIblockTable::getList([
'select' => ['IBLOCK_ID', 'PRODUCT_IBLOCK_ID'],
'filter' => []
])->fetchAll();
foreach ($catalogs as $catalog) {
if ($catalog['IBLOCK_ID']) {
$catalogIblockIds[] = $catalog['IBLOCK_ID'];
}
if ($catalog['PRODUCT_IBLOCK_ID']) {
$catalogIblockIds[] = $catalog['PRODUCT_IBLOCK_ID'];
}
}
// Способ 2: если не нашли, ищем инфоблоки с типом "catalog" или "1c_catalog"
if (empty($catalogIblockIds)) {
$iblocks = IblockTable::getList([
'select' => ['ID', 'NAME', 'IBLOCK_TYPE_ID'],
'filter' => [
'IBLOCK_TYPE_ID' => ['catalog', '1c_catalog', 'catalog_offers']
]
])->fetchAll();
foreach ($iblocks as $iblock) {
$catalogIblockIds[] = $iblock['ID'];
}
}
// Способ 3: добавим вручную, если знаете ID инфоблока (можно указать здесь)
// $catalogIblockIds[] = 1; // ID вашего инфоблока "Товары 1с"
$catalogIblockIds = array_unique($catalogIblockIds);
$catalogIblockIds = [363, 342, 329, 321, 318];
if (empty($catalogIblockIds)) {
echo "Не найдены инфоблоки каталога товаров.\n";
echo "Пожалуйста, укажите ID инфоблока вручную в скрипте.\n";
echo "Для этого найдите ID инфоблока в админке Битрикса и добавьте строку:\n";
echo "\$catalogIblockIds[] = ID_вашего_инфоблока;\n";
exit;
}
echo "Найдено инфоблоков с товарами: " . count($catalogIblockIds) . "\n";
echo "ID инфоблоков: " . implode(', ', $catalogIblockIds) . "\n\n";
// 4. Получаем ВСЕ элементы (товары) из этих инфоблоков
$elements = ElementTable::getList([
'select' => ['ID', 'NAME', 'IBLOCK_ID', 'PREVIEW_PICTURE', 'DETAIL_PICTURE'],
'filter' => ['IBLOCK_ID' => $catalogIblockIds],
'order' => ['ID' => 'ASC']
])->fetchAll();
echo "Найдено товаров: " . count($elements) . "\n\n";
$processed = 0;
$errors = 0;
$skipped = 0;
foreach ($elements as $element) {
$elementId = $element['ID'];
$elementName = $element['NAME'];
// Проверяем PREVIEW_PICTURE и DETAIL_PICTURE
$pictures = [];
if ($element['PREVIEW_PICTURE']) {
$pictures[] = ['id' => $element['PREVIEW_PICTURE'], 'type' => 'PREVIEW'];
}
if ($element['DETAIL_PICTURE']) {
$pictures[] = ['id' => $element['DETAIL_PICTURE'], 'type' => 'DETAIL'];
}
if (empty($pictures)) {
$skipped++;
continue;
}
echo "Обработка товара #{$elementId} '{$elementName}':\n";
foreach ($pictures as $pictureData) {
$pictureId = $pictureData['id'];
$pictureType = $pictureData['type'];
// Получаем информацию о файле
$file = \CFile::GetByID($pictureId)->Fetch();
if (!$file) {
echo " [ОШИБКА] Не найден файл для картинки ID {$pictureId}\n";
$errors++;
continue;
}
// Проверяем формат
$allowedTypes = ['image/jpeg', 'image/jpg', 'image/png'];
if (!in_array($file['CONTENT_TYPE'], $allowedTypes)) {
echo " [ПРОПУСК] Картинка ID {$pictureId} - неподдерживаемый формат ({$file['CONTENT_TYPE']})\n";
$skipped++;
continue;
}
// Полный путь к файлу
$filePath = $_SERVER['DOCUMENT_ROOT'] . \CFile::GetPath($pictureId);
if (!file_exists($filePath)) {
echo " [ОШИБКА] Файл не найден: {$filePath}\n";
$errors++;
continue;
}
// Определяем размеры исходного файла
$originalSize = getimagesize($filePath);
if (!$originalSize) {
echo " [ОШИБКА] Не удалось определить размер файла\n";
$errors++;
continue;
}
$origWidth = $originalSize[0];
$origHeight = $originalSize[1];
echo " {$pictureType}: исходный размер {$origWidth}x{$origHeight}";
// Если изображение уже точно 1600x1200 или больше с правильными пропорциями, пропускаем
if ($origWidth == $targetWidth && $origHeight == $targetHeight) {
echo " - уже нужного размера [ПРОПУСК]\n";
$skipped++;
continue;
}
// Если изображение меньше 1600x1200, масштабируем вверх (с потерями качества)
// Но лучше не увеличивать маленькие картинки, просто пропускаем
if ($origWidth < 1600 && $origHeight < 1200) {
echo " - меньше целевого размера [ПРОПУСК]\n";
$skipped++;
continue;
}
// Создаем ресурс изображения
$imageResource = null;
$isPng = false;
switch ($file['CONTENT_TYPE']) {
case 'image/jpeg':
case 'image/jpg':
$imageResource = imagecreatefromjpeg($filePath);
break;
case 'image/png':
$imageResource = imagecreatefrompng($filePath);
$isPng = true;
break;
}
if (!$imageResource) {
echo " [ОШИБКА] Не удалось создать ресурс изображения\n";
$errors++;
continue;
}
// === ОБРЕЗАНИЕ (CROP) до 1600x1200 ===
$ratioOrig = $origWidth / $origHeight;
$ratioTarget = $targetWidth / $targetHeight;
if ($ratioOrig > $ratioTarget) {
// Исходное шире - обрезаем по ширине (центр)
$cropWidth = (int)($origHeight * $ratioTarget);
$cropHeight = $origHeight;
$srcX = (int)(($origWidth - $cropWidth) / 2);
$srcY = 0;
} else {
// Исходное выше - обрезаем по высоте (центр)
$cropWidth = $origWidth;
$cropHeight = (int)($origWidth / $ratioTarget);
$srcX = 0;
$srcY = (int)(($origHeight - $cropHeight) / 2);
}
// Создаем новое изображение
$newImage = imagecreatetruecolor($targetWidth, $targetHeight);
// Для PNG сохраняем прозрачность
if ($isPng) {
imagealphablending($newImage, false);
imagesavealpha($newImage, true);
$transparent = imagecolorallocatealpha($newImage, 0, 0, 0, 127);
imagefilledrectangle($newImage, 0, 0, $targetWidth, $targetHeight, $transparent);
}
// Копируем с обрезанием
imagecopyresampled(
$newImage,
$imageResource,
0, 0, $srcX, $srcY,
$targetWidth, $targetHeight,
$cropWidth, $cropHeight
);
// Сохраняем бэкап
$backupPath = $filePath . '.backup_' . date('Ymd_His');
if (!copy($filePath, $backupPath)) {
echo " [ОШИБКА] Не удалось создать бэкап\n";
$errors++;
imagedestroy($imageResource);
imagedestroy($newImage);
continue;
}
// Сохраняем новый файл
$saveResult = false;
switch ($file['CONTENT_TYPE']) {
case 'image/jpeg':
case 'image/jpg':
$saveResult = imagejpeg($newImage, $filePath, $quality);
break;
case 'image/png':
$saveResult = imagepng($newImage, $filePath, 9);
break;
}
imagedestroy($imageResource);
imagedestroy($newImage);
if (!$saveResult) {
echo " [ОШИБКА] Не удалось сохранить файл\n";
if (file_exists($backupPath)) {
copy($backupPath, $filePath);
unlink($backupPath);
}
$errors++;
continue;
}
// Обновляем информацию о файле в БД
$arFile = \CFile::MakeFileArray($filePath);
$arFile['MODULE_ID'] = 'iblock';
$newFileId = \CFile::SaveFile($arFile, 'iblock');
if ($newFileId) {
$arUpdate = [];
if ($pictureType == 'PREVIEW') {
$arUpdate['PREVIEW_PICTURE'] = $newFileId;
} else {
$arUpdate['DETAIL_PICTURE'] = $newFileId;
}
$el = new \CIBlockElement();
$el->Update($elementId, $arUpdate);
}
// Удаляем бэкап
if (file_exists($backupPath)) {
unlink($backupPath);
}
echo " -> обрезано до {$targetWidth}x{$targetHeight} [ГОТОВО]\n";
$processed++;
}
echo "\n";
}
echo "\n========================================\n";
echo "ОБРАБОТКА ЗАВЕРШЕНА!\n";
echo "Обработано файлов: {$processed}\n";
echo "Пропущено: {$skipped}\n";
echo "Ошибок: {$errors}\n";
echo "========================================\n";
require($_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/epilog_after.php');
// Файл: crop_all_product_images_fixed.php
define('BX_BUFFER_USED', true);
define('NO_KEEP_STATISTIC', true);
define('NOT_CHECK_PERMISSIONS', true);
define('BX_NO_ACCELERATOR_RESET', true);
require($_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_before.php');
use Bitrix\Main\Loader;
use Bitrix\Iblock\ElementTable;
use Bitrix\Iblock\IblockTable;
// 1. Подключаем модули
if (!Loader::includeModule('iblock') || !Loader::includeModule('catalog')) {
die('Не удалось подключить модули инфоблоков и каталога');
}
// 2. Настройки
$targetWidth = 1600;
$targetHeight = 1200;
$quality = 85;
// 3. Получаем ID ВСЕХ инфоблоков, которые содержат товары
// Ищем инфоблоки с типом "Каталог товаров" (1C)
$catalogIblockIds = [];
// Способ 1: через CatalogIblockTable
$catalogs = \Bitrix\Catalog\CatalogIblockTable::getList([
'select' => ['IBLOCK_ID', 'PRODUCT_IBLOCK_ID'],
'filter' => []
])->fetchAll();
foreach ($catalogs as $catalog) {
if ($catalog['IBLOCK_ID']) {
$catalogIblockIds[] = $catalog['IBLOCK_ID'];
}
if ($catalog['PRODUCT_IBLOCK_ID']) {
$catalogIblockIds[] = $catalog['PRODUCT_IBLOCK_ID'];
}
}
// Способ 2: если не нашли, ищем инфоблоки с типом "catalog" или "1c_catalog"
if (empty($catalogIblockIds)) {
$iblocks = IblockTable::getList([
'select' => ['ID', 'NAME', 'IBLOCK_TYPE_ID'],
'filter' => [
'IBLOCK_TYPE_ID' => ['catalog', '1c_catalog', 'catalog_offers']
]
])->fetchAll();
foreach ($iblocks as $iblock) {
$catalogIblockIds[] = $iblock['ID'];
}
}
// Способ 3: добавим вручную, если знаете ID инфоблока (можно указать здесь)
// $catalogIblockIds[] = 1; // ID вашего инфоблока "Товары 1с"
$catalogIblockIds = array_unique($catalogIblockIds);
$catalogIblockIds = [363, 342, 329, 321, 318];
if (empty($catalogIblockIds)) {
echo "Не найдены инфоблоки каталога товаров.\n";
echo "Пожалуйста, укажите ID инфоблока вручную в скрипте.\n";
echo "Для этого найдите ID инфоблока в админке Битрикса и добавьте строку:\n";
echo "\$catalogIblockIds[] = ID_вашего_инфоблока;\n";
exit;
}
echo "Найдено инфоблоков с товарами: " . count($catalogIblockIds) . "\n";
echo "ID инфоблоков: " . implode(', ', $catalogIblockIds) . "\n\n";
// 4. Получаем ВСЕ элементы (товары) из этих инфоблоков
$elements = ElementTable::getList([
'select' => ['ID', 'NAME', 'IBLOCK_ID', 'PREVIEW_PICTURE', 'DETAIL_PICTURE'],
'filter' => ['IBLOCK_ID' => $catalogIblockIds],
'order' => ['ID' => 'ASC']
])->fetchAll();
echo "Найдено товаров: " . count($elements) . "\n\n";
$processed = 0;
$errors = 0;
$skipped = 0;
foreach ($elements as $element) {
$elementId = $element['ID'];
$elementName = $element['NAME'];
// Проверяем PREVIEW_PICTURE и DETAIL_PICTURE
$pictures = [];
if ($element['PREVIEW_PICTURE']) {
$pictures[] = ['id' => $element['PREVIEW_PICTURE'], 'type' => 'PREVIEW'];
}
if ($element['DETAIL_PICTURE']) {
$pictures[] = ['id' => $element['DETAIL_PICTURE'], 'type' => 'DETAIL'];
}
if (empty($pictures)) {
$skipped++;
continue;
}
echo "Обработка товара #{$elementId} '{$elementName}':\n";
foreach ($pictures as $pictureData) {
$pictureId = $pictureData['id'];
$pictureType = $pictureData['type'];
// Получаем информацию о файле
$file = \CFile::GetByID($pictureId)->Fetch();
if (!$file) {
echo " [ОШИБКА] Не найден файл для картинки ID {$pictureId}\n";
$errors++;
continue;
}
// Проверяем формат
$allowedTypes = ['image/jpeg', 'image/jpg', 'image/png'];
if (!in_array($file['CONTENT_TYPE'], $allowedTypes)) {
echo " [ПРОПУСК] Картинка ID {$pictureId} - неподдерживаемый формат ({$file['CONTENT_TYPE']})\n";
$skipped++;
continue;
}
// Полный путь к файлу
$filePath = $_SERVER['DOCUMENT_ROOT'] . \CFile::GetPath($pictureId);
if (!file_exists($filePath)) {
echo " [ОШИБКА] Файл не найден: {$filePath}\n";
$errors++;
continue;
}
// Определяем размеры исходного файла
$originalSize = getimagesize($filePath);
if (!$originalSize) {
echo " [ОШИБКА] Не удалось определить размер файла\n";
$errors++;
continue;
}
$origWidth = $originalSize[0];
$origHeight = $originalSize[1];
echo " {$pictureType}: исходный размер {$origWidth}x{$origHeight}";
// Если изображение уже точно 1600x1200 или больше с правильными пропорциями, пропускаем
if ($origWidth == $targetWidth && $origHeight == $targetHeight) {
echo " - уже нужного размера [ПРОПУСК]\n";
$skipped++;
continue;
}
// Если изображение меньше 1600x1200, масштабируем вверх (с потерями качества)
// Но лучше не увеличивать маленькие картинки, просто пропускаем
if ($origWidth < 1600 && $origHeight < 1200) {
echo " - меньше целевого размера [ПРОПУСК]\n";
$skipped++;
continue;
}
// Создаем ресурс изображения
$imageResource = null;
$isPng = false;
switch ($file['CONTENT_TYPE']) {
case 'image/jpeg':
case 'image/jpg':
$imageResource = imagecreatefromjpeg($filePath);
break;
case 'image/png':
$imageResource = imagecreatefrompng($filePath);
$isPng = true;
break;
}
if (!$imageResource) {
echo " [ОШИБКА] Не удалось создать ресурс изображения\n";
$errors++;
continue;
}
// === ОБРЕЗАНИЕ (CROP) до 1600x1200 ===
$ratioOrig = $origWidth / $origHeight;
$ratioTarget = $targetWidth / $targetHeight;
if ($ratioOrig > $ratioTarget) {
// Исходное шире - обрезаем по ширине (центр)
$cropWidth = (int)($origHeight * $ratioTarget);
$cropHeight = $origHeight;
$srcX = (int)(($origWidth - $cropWidth) / 2);
$srcY = 0;
} else {
// Исходное выше - обрезаем по высоте (центр)
$cropWidth = $origWidth;
$cropHeight = (int)($origWidth / $ratioTarget);
$srcX = 0;
$srcY = (int)(($origHeight - $cropHeight) / 2);
}
// Создаем новое изображение
$newImage = imagecreatetruecolor($targetWidth, $targetHeight);
// Для PNG сохраняем прозрачность
if ($isPng) {
imagealphablending($newImage, false);
imagesavealpha($newImage, true);
$transparent = imagecolorallocatealpha($newImage, 0, 0, 0, 127);
imagefilledrectangle($newImage, 0, 0, $targetWidth, $targetHeight, $transparent);
}
// Копируем с обрезанием
imagecopyresampled(
$newImage,
$imageResource,
0, 0, $srcX, $srcY,
$targetWidth, $targetHeight,
$cropWidth, $cropHeight
);
// Сохраняем бэкап
$backupPath = $filePath . '.backup_' . date('Ymd_His');
if (!copy($filePath, $backupPath)) {
echo " [ОШИБКА] Не удалось создать бэкап\n";
$errors++;
imagedestroy($imageResource);
imagedestroy($newImage);
continue;
}
// Сохраняем новый файл
$saveResult = false;
switch ($file['CONTENT_TYPE']) {
case 'image/jpeg':
case 'image/jpg':
$saveResult = imagejpeg($newImage, $filePath, $quality);
break;
case 'image/png':
$saveResult = imagepng($newImage, $filePath, 9);
break;
}
imagedestroy($imageResource);
imagedestroy($newImage);
if (!$saveResult) {
echo " [ОШИБКА] Не удалось сохранить файл\n";
if (file_exists($backupPath)) {
copy($backupPath, $filePath);
unlink($backupPath);
}
$errors++;
continue;
}
// Обновляем информацию о файле в БД
$arFile = \CFile::MakeFileArray($filePath);
$arFile['MODULE_ID'] = 'iblock';
$newFileId = \CFile::SaveFile($arFile, 'iblock');
if ($newFileId) {
$arUpdate = [];
if ($pictureType == 'PREVIEW') {
$arUpdate['PREVIEW_PICTURE'] = $newFileId;
} else {
$arUpdate['DETAIL_PICTURE'] = $newFileId;
}
$el = new \CIBlockElement();
$el->Update($elementId, $arUpdate);
}
// Удаляем бэкап
if (file_exists($backupPath)) {
unlink($backupPath);
}
echo " -> обрезано до {$targetWidth}x{$targetHeight} [ГОТОВО]\n";
$processed++;
}
echo "\n";
}
echo "\n========================================\n";
echo "ОБРАБОТКА ЗАВЕРШЕНА!\n";
echo "Обработано файлов: {$processed}\n";
echo "Пропущено: {$skipped}\n";
echo "Ошибок: {$errors}\n";
echo "========================================\n";
require($_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/epilog_after.php');
