Изменение размера изображения и нехватка памяти

#php #image #memory #resize #jpeg

#php #изображение #память #изменение размера #jpeg

Вопрос:

В настоящее время я создаю модуль импорта для Prestashop. Этот модуль импортирует около 3000 продуктов, и ему необходимо изменить размер каждого изображения продукта до 5 различных форматов миниатюр. Проблема в том, что скрипт потребляет МНОГО памяти. Я говорю о максимальных 100 МБ и до 27 МБ во время процесса. Мне немного стыдно признаться, что я не очень хорошо знаком со всеми вопросами управления памятью, так что любая помощь приветствуется!

Код, который я использую, следующий. Метод resizeImg должен быть самым интересным, другие методы приведены только для иллюстрации того, как я обрабатываю задачи. Кто-нибудь знает, почему я получаю пик памяти более 100 МБ?

 public function main() {
    foreach( $products as $product ) {
        self::copyImg( $imageURL );
    }
}

static private function copyImg( $imageURL ) {
    // Copy image from $imageURL to temp folder

    foreach( $imageTypes as $type ) {
        self::resizeImg( $tempImage, $destination, $type['width'], $type['height']);
    }
}

static private function resizeImg( $sourceFile, $destFile, $destWidth, $destHeight )
{
    list( $sourceWidth, $sourceHeight, $type, $attr ) = getimagesize( $sourceFile );
    if ( is_null( $destWidth ) ) $destWidth = $sourceWidth;
    if ( is_null( $destHeight ) ) $destHeight = $sourceHeight;

    $sourceImage = imagecreatefromjpeg( $sourceFile );
    $widthDiff = $destWidth / $sourceWidth;
    $heightDiff = $destHeight / $sourceHeight;

    if ( $widthDiff > 1 amp;amp; $heightDiff > 1 ) {

        $nextWidth = $sourceWidth;
        $nextHeight = $sourceHeight;

    } else {

        if ( Configuration::get( 'PS_IMAGE_GENERATION_METHOD' ) == 2 || ( ! Configuration::get( 'PS_IMAGE_GENERATION_METHOD' ) AND $widthDiff > $heightDiff ) ) {

            $nextHeight = $destHeight;
            $nextWidth = round( $sourceWidth * $nextHeight / $sourceHeight );
            $destWidth = ( ! Configuration::get( 'PS_IMAGE_GENERATION_METHOD' ) ? $destWidth : $nextWidth );

        } else {

            $nextWidth = $destWidth;
            $nextHeight = round( $sourceHeight * $destWidth / $sourceWidth );
            $destHeight = ( ! Configuration::get( 'PS_IMAGE_GENERATION_METHOD' ) ? $destHeight : $nextHeight );

        }

    }

    $destImage = imagecreatetruecolor( $destWidth, $destHeight );
    $white = imagecolorallocate( $destImage, 255, 255, 255 );
    imagefilledrectangle( $destImage, 0, 0, $destWidth, $destHeight, $white );
    imagecopyresampled( $destImage, $sourceImage, ( ( $destWidth - $nextWidth ) / 2 ), ( ( $destHeight - $nextHeight ) / 2 ), 0, 0, $nextWidth, $nextHeight, $sourceWidth, $sourceHeight );
    imagecolortransparent( $destImage, $white );
    imagejpeg( $destImage, $destFile, 90 );

    imagedestroy( $sourceImage );
    imagedestroy( $destImage );
}
  

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

1. Вы когда-нибудь находили решение этой проблемы? Я борюсь с тем же самым в модуле Prestashop

2. Я не помню, как мы решили эту проблему. Скорее всего, мы использовали другой подход.

Ответ №1:

Насколько велики эти изображения? Помните, что как только они загружаются в GD, они распаковываются до 3 (или 4) байт на пиксель. 100 МБ при 24 битах достаточно для изображения размером 6666×5000 или около того. Вы проверили, что вычисления изменения размера работают правильно? Если они ошибочны, возможно, вы пытаетесь по ошибке создать слишком большое изображение «dest».

Я тоже не вижу, куда вы записываете изображение с измененным размером. Существует множество операций изменения размера / копирования, но нигде у вас нет imagejpeg() или imagepng() etc …, чтобы записать измененное изображение.

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

1. Привет, Марк. Все изображения имеют точный размер 500x500px. Поправьте меня, если я ошибаюсь. Я предполагаю, что это означает, что одно изображение имеет размер 250 000 пикселей. После того, как GD распакует его, 250.000 * 4 = 1 миллион байт, что составляет примерно 1 МБ. Но я постоянно очищаю эти ресурсы в своем цикле, так почему же я получаю пик в 100 МБ? P.s: модифицировал свой код для imagejpeg-метода!

2. трудно сказать. Я не могу сразу обнаружить никаких утечек ресурсов. Попробуйте выполнить несколько echo memory_get_usage(true) вызовов до / после различных вызовов, чтобы увидеть, где использование резко возрастает.

3. Использование не направлено вверх где-либо конкретно. Я замечаю, что после загрузки и изменения размера нескольких изображений резервируется еще один блок памяти объемом 256 или 512 КБ, но не более того. Проблема в том, что примерно после 10000-кратного выполнения этого фрагмента кода эти блоки по 265 КБ увеличат объем используемой памяти до ненормальных значений.