PHP: полный мануал с примерами, функциями и ООП
Практический мануал PHP: от переменных и читаемого кода до безопасных форм, интеграций, базы данных и ООП на примере магазина. Учебный маршрут, поиск функций, подробные примеры, разбор ошибок и исходники для скачивания.

Дерево руководства
Глава 427 · После первых изображений Gmagick, объектов, массивов и циклов
Gmagick: время кадров, повторы и удаление при анимации
Управлять временем показа, повтором GIF и состоянием холста после каждого кадра.
Сравнить спокойный и быстрый показ
Одинаковые картинки могут восприниматься как торопливое мигание или спокойная демонстрация. Сравним короткую и длинную паузу каждого ракурса. Задержка30 означает30/100 секунды, а не30 секунд и не30 миллисекунд.




<?php
$sequence = new Gmagick(__DIR__ . '/views.gif');
$sequence->setImageIndex(0);
do {
$sequence->setImageDelay(80);
} while ($sequence->nextImage());
$sequence->setImageIndex(0);
$sequence->writeImage(__DIR__ . '/slow.gif', true);setImageDelay изменяет активный кадр. Цикл повторяет настройку для всех изображений.80 сотых —0.8 секунды. Перед экспортом указатель снова ставится в начало. Полная программа читает getter для каждого кадра и проверяет записанный GIF, поэтому речь идёт о времени в файле, а не только о присвоении переменной.
<?php
declare(strict_types=1);
require __DIR__ . '/gm-fixture.php';
gmRestore();
$sequence=new Gmagick();
$sequence->readImageBlob(file_get_contents(__DIR__.'/views.ppm'));
$sequence->setImageIndex(0);
do{$sequence->setImageDelay(30);$sequence->setImageDispose(Gmagick::DISPOSE_NONE);$sequence->setImageIterations(0);}while($sequence->nextImage());
$sequence->setImageIndex(0);
$sequence->setImageIndex(0);
$sequence->setImageDepth(8);
$sequence->setImageFormat('PNG');
$sequence->writeImage(__DIR__.'/gm100-speed-frame.png',false);
$delays=[];
foreach([20,80] as $delay){
$sequence->setImageIndex(0);$seen=[];
do{$sequence->setImageDelay($delay);$seen[]=$sequence->getImageDelay();$sequence->setImageFormat('GIF');}while($sequence->nextImage());
$delays[$delay]=$seen;$sequence->setImageIndex(0);
$sequence->writeImage(__DIR__.'/gm100-speed'.$delay.'.gif',true);
}
gmReport('gm100-time-speed',["gmagick.construct", "gmagick.readimageblob", "gmagick.setimageindex", "gmagick.setimagedelay", "gmagick.setimagedispose", "gmagick.setimageiterations", "gmagick.nextimage", "gmagick.setimagedepth", "gmagick.setimageformat", "gmagick.writeimage", "gmagick.getimagedelay"],["gm100-speed-frame.png"],
['fast_delays'=>$delays[20]===[20,20,20],'slow_delays'=>$delays[80]===[80,80,80],'size_gm100_speed_frame'=>gmInspect('gm100-speed-frame.png')['width']===320&&gmInspect('gm100-speed-frame.png')['height']===200],
$errors ?? [], ['delays_centiseconds'=>$delays]);
echo "gm100-speed-frame.png 320x200\n";
Ожидаемый результат
gm100-speed-frame.png 320x200
Самостоятельный ZIP: php example.php с Gmagick. Окружение: PHP8.3.6 / Gmagick2.0.6RC1 / GraphicsMagick1.3.42 Q16. Собственные PPM и готовый views.gif восстанавливаются из .b64. gm-fixture.php проверяет файлы и записывает metrics.json; изучаемые операции видны в самой программе. PNG и GIF сохраняются рядом.
Вывод успешного запуска
gm100-speed-frame.png 320x200
Браузер планирует показ кадров самостоятельно, особенно для очень малых задержек и фоновых вкладок. В примерах выбраны заметные положительные интервалы; нулевая задержка не используется как обещание невидимого промежуточного кадра.
Задержать последний ракурс
Последний ракурс должен задержаться, чтобы покупатель успел рассмотреть товар. Назначим отдельное время каждому кадру: два коротких перехода и длинная финальная пауза. Никаких копий последнего кадра ради паузы не требуется.



<?php
$sequence = new Gmagick(__DIR__ . '/views.gif');
foreach ([20, 20, 120] as $index => $delay) {
$sequence->setImageIndex($index);
$sequence->setImageDelay($delay);
}
$sequence->setImageIndex(0);
$sequence->writeImage(__DIR__ . '/pause.gif', true);Массив содержит три задержки. foreach выдаёт индекс и значение; стрелка => внутри foreach связывает ключ с переменной, это другая запись, чем объектная ->.120 сотых —1.2 секунды. Полная программа читает getImageDelay обратно и показывает последний кадр отдельным PNG.
<?php
declare(strict_types=1);
require __DIR__ . '/gm-fixture.php';
gmRestore();
$sequence=new Gmagick();
$sequence->readImageBlob(file_get_contents(__DIR__.'/views.ppm'));
$sequence->setImageIndex(0);
do{$sequence->setImageDelay(30);$sequence->setImageDispose(Gmagick::DISPOSE_NONE);$sequence->setImageIterations(0);}while($sequence->nextImage());
$sequence->setImageIndex(0);
$seen=[];
foreach([20,20,120] as $i=>$delay){$sequence->setImageIndex($i);$sequence->setImageDelay($delay);$seen[]=$sequence->getImageDelay();}
$sequence->setImageIndex(2);
$sequence->setImageDepth(8);
$sequence->setImageFormat('PNG');
$sequence->writeImage(__DIR__.'/gm100-pause-last.png',false);
$sequence->setImageIndex(0);
do{$sequence->setImageFormat('GIF');}while($sequence->nextImage());
$sequence->setImageIndex(0);$sequence->writeImage(__DIR__.'/gm100-pause.gif',true);
gmReport('gm100-time-pauses',["gmagick.construct", "gmagick.readimageblob", "gmagick.setimageindex", "gmagick.setimagedelay", "gmagick.setimagedispose", "gmagick.setimageiterations", "gmagick.nextimage", "gmagick.getimagedelay", "gmagick.setimagedepth", "gmagick.setimageformat", "gmagick.writeimage"],["gm100-pause-last.png"],
['delays'=>$seen===[20,20,120],'size_gm100_pause_last'=>gmInspect('gm100-pause-last.png')['width']===320&&gmInspect('gm100-pause-last.png')['height']===200],
$errors ?? [], ['delays_centiseconds'=>$seen,'cycle_duration_seconds'=>1.6]);
echo "gm100-pause-last.png 320x200\n";
Ожидаемый результат
gm100-pause-last.png 320x200
Самостоятельный ZIP: php example.php с Gmagick. Окружение: PHP8.3.6 / Gmagick2.0.6RC1 / GraphicsMagick1.3.42 Q16. Собственные PPM и готовый views.gif восстанавливаются из .b64. gm-fixture.php проверяет файлы и записывает metrics.json; изучаемые операции видны в самой программе. PNG и GIF сохраняются рядом.
Вывод успешного запуска
gm100-pause-last.png 320x200
Длина массива должна совпадать с числом кадров. Если последовательность была сокращена removeImage, старый набор задержек надо пересчитать: индекс теперь относится к новому списку.
Сравнить непрерывный цикл и конечный повтор
Для короткого объявления достаточно конечного числа повторов, для демонстрации ракурсов нужен непрерывный цикл. Сравним две настройки iterations на одинаковых изображениях. Время кадра оставим одинаковым, чтобы не спутать скорость с количеством проходов.




<?php
$sequence = new Gmagick(__DIR__ . '/views.gif');
$sequence->setImageIndex(0);
$sequence->setImageIterations(2);
$iterations = $sequence->getImageIterations();
$sequence->setImageFormat('GIF');
$sequence->writeImage(__DIR__ . '/limited.gif', true);Здесь значение2 относится к циклу, а не к сотым секунды. Настройка задаётся на первом кадре перед экспортом. Для бесконечного варианта используется0. Полная программа отдельно фиксирует getter Gmagick и фактически записанное поле повтора GIF; эти числа не следует автоматически считать одинаково определёнными во всех инструментах.
<?php
declare(strict_types=1);
require __DIR__ . '/gm-fixture.php';
gmRestore();
$sequence=new Gmagick();
$sequence->readImageBlob(file_get_contents(__DIR__.'/views.ppm'));
$sequence->setImageIndex(0);
do{$sequence->setImageDelay(30);$sequence->setImageDispose(Gmagick::DISPOSE_NONE);$sequence->setImageIterations(0);}while($sequence->nextImage());
$sequence->setImageIndex(0);
$iterations=[];
foreach([0,2] as $loops){
$sequence->setImageIndex(0);$sequence->setImageIterations($loops);$iterations[]=$sequence->getImageIterations();
do{$sequence->setImageFormat('GIF');}while($sequence->nextImage());$sequence->setImageIndex(0);
$sequence->writeImage(__DIR__.'/gm100-loops'.$loops.'.gif',true);
}
$sequence->setImageIndex(2);
$sequence->setImageDepth(8);
$sequence->setImageFormat('PNG');
$sequence->writeImage(__DIR__.'/gm100-loops-last.png',false);
$read=new Gmagick(__DIR__.'/gm100-loops2.gif');$read->setImageIndex(0);$readIterations=$read->getImageIterations();
gmReport('gm100-time-loops',["gmagick.construct", "gmagick.readimageblob", "gmagick.setimageindex", "gmagick.setimagedelay", "gmagick.setimagedispose", "gmagick.setimageiterations", "gmagick.nextimage", "gmagick.getimageiterations", "gmagick.setimageformat", "gmagick.writeimage", "gmagick.setimagedepth"],["gm100-loops-last.png"],
['iterations'=>$iterations===[0,2],'readback_first'=>$readIterations===2,'size_gm100_loops_last'=>gmInspect('gm100-loops-last.png')['width']===320&&gmInspect('gm100-loops-last.png')['height']===200],
$errors ?? [], ['configured_iterations'=>$iterations,'readback_first_iterations'=>$readIterations,'raw_netscape_loop'=>2]);
echo "gm100-loops-last.png 320x200\n";
Ожидаемый результат
gm100-loops-last.png 320x200
Самостоятельный ZIP: php example.php с Gmagick. Окружение: PHP8.3.6 / Gmagick2.0.6RC1 / GraphicsMagick1.3.42 Q16. Собственные PPM и готовый views.gif восстанавливаются из .b64. gm-fixture.php проверяет файлы и записывает metrics.json; изучаемые операции видны в самой программе. PNG и GIF сохраняются рядом.
Вывод успешного запуска
gm100-loops-last.png 320x200
Конечная анимация со временем останавливается, поэтому рядом оставлен статический итоговый кадр. Для повторного просмотра можно открыть сам GIF заново. Текст PHP.net о задержке в параметре iterations ошибочен; единицы времени принадлежат setImageDelay.
В сохранённом примере iterations2 прочиталось Gmagick как2, а расширение NETSCAPE GIF содержит поле loop2. Это поле счётчика повторов, и его нельзя без уточнения трактовать как ровно два полных показа во всех просмотрщиках. Значение0 означает бесконечный цикл. Для iterations1 исследованный кодер вообще не записал расширение повтора. Последующие кадры при чтении GIF имеют собственное значение iterations1; параметр цикла контролируем по первому кадру.
Сравнить удаление на полных кадрах
После показа кадра просмотрщик должен решить, что оставить на холсте. Сначала возьмём полные непрозрачные изображения320×200: следующий кадр закрывает весь предыдущий, поэтому разные способы удаления могут дать одинаковую видимую последовательность.




<?php
$sequence = new Gmagick(__DIR__ . '/views.gif');
$sequence->setImageIndex(0);
do {
$sequence->setImageDispose(Gmagick::DISPOSE_BACKGROUND);
} while ($sequence->nextImage());
$sequence->setImageIndex(0);
$sequence->writeImage(__DIR__ . '/background.gif', true);DISPOSE_BACKGROUND — именованная константа со значением2. Она просит восстановить фон занятой кадром области после его показа. DISPOSE_NONE со значением1 оставляет изображение на месте. Getter getImageDispose читает настройку текущего кадра; список кадров от этой настройки не сокращается.
<?php
declare(strict_types=1);
require __DIR__ . '/gm-fixture.php';
gmRestore();
$sequence=new Gmagick();
$sequence->readImageBlob(file_get_contents(__DIR__.'/views.ppm'));
$sequence->setImageIndex(0);
do{$sequence->setImageDelay(30);$sequence->setImageDispose(Gmagick::DISPOSE_NONE);$sequence->setImageIterations(0);}while($sequence->nextImage());
$sequence->setImageIndex(0);
$settings=[];
foreach([Gmagick::DISPOSE_NONE,Gmagick::DISPOSE_BACKGROUND] as $dispose){
$sequence->setImageIndex(0);$seen=[];
do{$sequence->setImageDispose($dispose);$seen[]=$sequence->getImageDispose();$sequence->setImageFormat('GIF');}while($sequence->nextImage());
$settings[$dispose]=$seen;$sequence->setImageIndex(0);
$sequence->writeImage(__DIR__.'/gm100-full-dispose'.$dispose.'.gif',true);
}
$sequence->setImageIndex(2);
$sequence->setImageDepth(8);
$sequence->setImageFormat('PNG');
$sequence->writeImage(__DIR__.'/gm100-full-last.png',false);
gmReport('gm100-time-full-dispose',["gmagick.construct", "gmagick.readimageblob", "gmagick.setimageindex", "gmagick.setimagedelay", "gmagick.setimagedispose", "gmagick.setimageiterations", "gmagick.nextimage", "gmagick.getimagedispose", "gmagick.setimageformat", "gmagick.writeimage", "gmagick.setimagedepth"],["gm100-full-last.png"],
['none_codes'=>$settings[1]===[1,1,1],'background_codes'=>$settings[2]===[2,2,2],'size_gm100_full_last'=>gmInspect('gm100-full-last.png')['width']===320&&gmInspect('gm100-full-last.png')['height']===200],
$errors ?? [], ['disposals'=>$settings]);
echo "gm100-full-last.png 320x200\n";
Ожидаемый результат
gm100-full-last.png 320x200
Самостоятельный ZIP: php example.php с Gmagick. Окружение: PHP8.3.6 / Gmagick2.0.6RC1 / GraphicsMagick1.3.42 Q16. Собственные PPM и готовый views.gif восстанавливаются из .b64. gm-fixture.php проверяет файлы и записывает metrics.json; изучаемые операции видны в самой программе. PNG и GIF сохраняются рядом.
Вывод успешного запуска
gm100-full-last.png 320x200
Одинаковая картинка в этом сравнении не означает, что dispose не работает. Полноразмерные непрозрачные кадры скрывают разницу. Следующий пример использует частичные области, где предыдущее состояние холста становится существенным.
Увидеть влияние удаления на частичные кадры
У компактной анимации последующие кадры могут содержать только изменившуюся область. Для такого файла уже важно, что произошло с остальной частью холста после предыдущего кадра. Сравним оставление, фон и восстановление прежнего содержимого.







<?php
$sequence = new Gmagick(__DIR__ . '/views.gif');
$patches = $sequence->deconstructImages();
$patches->setImageIndex(0);
do {
$patches->setImageDispose(Gmagick::DISPOSE_NONE);
} while ($patches->nextImage());
$patches->setImageIndex(0); $patches->writeImage(__DIR__ . '/patches.gif', true);deconstructImages возвращает новый список областей отличий. Каждая область имеет размеры и положение на общем холсте. DISPOSE_PREVIOUS со значением3 возвращает содержимое области, бывшее до её показа. Полная программа сохраняет анимации и отдельные собранные кадры, чтобы различие было видно без угадывания момента.
<?php
declare(strict_types=1);
require __DIR__ . '/gm-fixture.php';
gmRestore();
$sequence=new Gmagick();
$sequence->readImageBlob(file_get_contents(__DIR__.'/views.ppm'));
$sequence->setImageIndex(0);
do{$sequence->setImageDelay(30);$sequence->setImageDispose(Gmagick::DISPOSE_NONE);$sequence->setImageIterations(0);}while($sequence->nextImage());
$sequence->setImageIndex(0);
$settings=[];
foreach([Gmagick::DISPOSE_NONE,Gmagick::DISPOSE_BACKGROUND,Gmagick::DISPOSE_PREVIOUS] as $dispose){
$patches=$sequence->deconstructImages();$patches->setImageIndex(0);$seen=[];
do{$patches->setImageDispose($dispose);$seen[]=$patches->getImageDispose();$patches->setImageFormat('GIF');}while($patches->nextImage());
$settings[$dispose]=$seen;$patches->setImageIndex(0);$name='gm100-patch-dispose'.$dispose;
$patches->writeImage(__DIR__.'/'.$name.'.gif',true);
$read=new Gmagick(__DIR__.'/'.$name.'.gif');$display=$read->coalesceImages();$display->setImageIndex(2);
$display->setImageDepth(8);$display->setImageFormat('PNG');$display->writeImage(__DIR__.'/'.$name.'.png',false);
}
gmReport('gm100-time-patch-dispose',["gmagick.construct", "gmagick.readimageblob", "gmagick.setimageindex", "gmagick.setimagedelay", "gmagick.setimagedispose", "gmagick.setimageiterations", "gmagick.nextimage", "gmagick.deconstructimages", "gmagick.getimagedispose", "gmagick.setimageformat", "gmagick.writeimage", "gmagick.coalesceimages", "gmagick.setimagedepth"],["gm100-patch-dispose1.png", "gm100-patch-dispose2.png", "gm100-patch-dispose3.png"],
['none_codes'=>$settings[1]===[1,1,1],'background_codes'=>$settings[2]===[2,2,2],'previous_codes'=>$settings[3]===[3,3,3],'size_gm100_patch_dispose1'=>gmInspect('gm100-patch-dispose1.png')['width']===320&&gmInspect('gm100-patch-dispose1.png')['height']===200,'size_gm100_patch_dispose2'=>gmInspect('gm100-patch-dispose2.png')['width']===320&&gmInspect('gm100-patch-dispose2.png')['height']===200,'size_gm100_patch_dispose3'=>gmInspect('gm100-patch-dispose3.png')['width']===320&&gmInspect('gm100-patch-dispose3.png')['height']===200],
$errors ?? [], ['disposals'=>$settings,'pngs'=>'native coalesce of the saved GIF, final frame']);
echo "gm100-patch-dispose1.png 320x200 gm100-patch-dispose2.png 320x200 gm100-patch-dispose3.png 320x200\n";
Ожидаемый результат
gm100-patch-dispose1.png 320x200 gm100-patch-dispose2.png 320x200 gm100-patch-dispose3.png 320x200
Самостоятельный ZIP: php example.php с Gmagick. Окружение: PHP8.3.6 / Gmagick2.0.6RC1 / GraphicsMagick1.3.42 Q16. Собственные PPM и готовый views.gif восстанавливаются из .b64. gm-fixture.php проверяет файлы и записывает metrics.json; изучаемые операции видны в самой программе. PNG и GIF сохраняются рядом.
Вывод успешного запуска
gm100-patch-dispose1.png 320x200 gm100-patch-dispose2.png 320x200 gm100-patch-dispose3.png 320x200
Нельзя считать обрезанный фрагмент самостоятельным полноразмерным кадром. Нельзя также произвольно менять dispose после сокращения областей и обещать прежнюю анимацию: геометрия, предыдущий холст и удаление образуют единый порядок действий.
Здесь отдельные PNG получены самой библиотекой: coalesceImages собирает отображаемые полные кадры из записанного GIF с учётом областей и dispose. Для NONE полка остаётся; для BACKGROUND она пропадает; для PREVIOUS слева сохраняется старая коробка. Это намеренно разные результаты одного набора фрагментов. GIF89a также определяет0 как неуказанный способ, а4…7 резервирует. Формулировка «удаление кадра» здесь относится к холсту после показа; removeImage удаляет элемент списка и решает другую задачу.
Настроить показ функцией каталога
Объединим настройку демонстрации в функцию: кадры, массив задержек, число повторов и способ удаления. Функция принимает проверяемые значения и оставляет вызывающему коду явный файл результата. На странице виден готовый цикл с длинной финальной паузой.



<?php
$sequence = new Gmagick(__DIR__ . '/views.gif');
$sequence->setImageIndex(2);
$sequence->setImageDelay(120);
$sequence->setImageDispose(Gmagick::DISPOSE_NONE);
$sequence->setImageIndex(0);
$sequence->setImageIterations(0);
$sequence->writeImage(__DIR__ . '/catalog.gif', true);Малый фрагмент показывает сочетание трёх настроек. Полная функция проверяет число задержек, положительное время и поддерживаемый нашей задачей dispose. Это ограничения функции каталога, не объявление всех возможностей библиотеки. Возвраты setters — Gmagick; getters дают целые значения.
<?php
declare(strict_types=1);
require __DIR__ . '/gm-fixture.php';
gmRestore();
$sequence=new Gmagick();
$sequence->readImageBlob(file_get_contents(__DIR__.'/views.ppm'));
$sequence->setImageIndex(0);
do{$sequence->setImageDelay(30);$sequence->setImageDispose(Gmagick::DISPOSE_NONE);$sequence->setImageIterations(0);}while($sequence->nextImage());
$sequence->setImageIndex(0);
function configureTimeline(Gmagick $sequence,array $delays,int $loops,int $dispose):Gmagick{
if(count($delays)!==$sequence->getNumberImages()||$loops<0||!in_array($dispose,[1,2,3],true))throw new InvalidArgumentException('Invalid timeline options');
foreach($delays as $delay)if(!is_int($delay)||$delay<1||$delay>1000)throw new InvalidArgumentException('Delay must be1..1000 centiseconds');
foreach($delays as $i=>$delay){$sequence->setImageIndex($i);$sequence->setImageDelay($delay);$sequence->setImageDispose($dispose);}
$sequence->setImageIndex(0);$sequence->setImageIterations($loops);return $sequence;
}
configureTimeline($sequence,[30,30,120],0,Gmagick::DISPOSE_NONE);
$firstIterations=$sequence->getImageIterations();$sequence->setImageIndex(2);$last=[$sequence->getImageDelay(),$sequence->getImageDispose()];
$sequence->setImageDepth(8);
$sequence->setImageFormat('PNG');
$sequence->writeImage(__DIR__.'/gm100-configured-last.png',false);
$sequence->setImageIndex(0);
do{$sequence->setImageFormat('GIF');}while($sequence->nextImage());
$sequence->setImageIndex(0);$sequence->writeImage(__DIR__.'/gm100-configured.gif',true);
$errors=['length'=>gmTry(fn()=>configureTimeline($sequence,[30],0,1)),'type'=>gmTry(fn()=>$sequence->setImageDelay([]))];
gmReport('gm100-time-function',["gmagick.construct", "gmagick.readimageblob", "gmagick.setimageindex", "gmagick.setimagedelay", "gmagick.setimagedispose", "gmagick.setimageiterations", "gmagick.nextimage", "gmagick.getnumberimages", "gmagick.getimageiterations", "gmagick.getimagedelay", "gmagick.getimagedispose", "gmagick.setimagedepth", "gmagick.setimageformat", "gmagick.writeimage"],["gm100-configured-last.png"],
['loop_forever'=>$firstIterations===0,'last_settings'=>$last===[120,1],'length_rejected'=>$errors['length']['class']==='InvalidArgumentException','type_rejected'=>$errors['type']['class']==='TypeError','size_gm100_configured_last'=>gmInspect('gm100-configured-last.png')['width']===320&&gmInspect('gm100-configured-last.png')['height']===200],
$errors ?? [], ['last_delay_dispose'=>$last,'first_iterations'=>$firstIterations]);
echo "gm100-configured-last.png 320x200\n";
Ожидаемый результат
gm100-configured-last.png 320x200
Самостоятельный ZIP: php example.php с Gmagick. Окружение: PHP8.3.6 / Gmagick2.0.6RC1 / GraphicsMagick1.3.42 Q16. Собственные PPM и готовый views.gif восстанавливаются из .b64. gm-fixture.php проверяет файлы и записывает metrics.json; изучаемые операции видны в самой программе. PNG и GIF сохраняются рядом.
Вывод успешного запуска
gm100-configured-last.png 320x200
Если в функцию передан неверный массив, полезнее остановиться до записи файла, чем выпустить наполовину настроенную последовательность. Отдельный TypeError при передаче массива вместо числа показывает границу PHP-типов.
Упражнение: delay25 — сколько миллисекунд? Ответ:250. Меняет ли setImageIterations скорость каждого кадра? Ответ:нет. Почему на полных непрозрачных кадрах dispose1 и2 выглядят одинаково? Ответ:следующий кадр закрывает весь холст. Для частичных кадров нужен учёт прежнего содержимого. Следующий шаг — общая палитра и области изменений.
Практический вопрос и наш ответ
How do remove the flickering in this ImageMagick produced animation. Ive tried exactly as documented: В начале анимации мерцает пустой прозрачный кадр, хотя ему задана нулевая задержка и следующему указан dispose previous. Мы начинаем с содержательного полного кадра, используем положительное время и показываем реальное действие dispose на частичных областях. Ноль не обещает невидимый кадр. Отдельные PNG последнего состояния позволяют увидеть пропавший фон или оставшийся предмет.
Функции и методы этой темы
Откройте карточку, чтобы увидеть договор функции, примеры, ограничения и связанные инструменты.
Gmagick::getimagedelayЧитает задержку активного кадра как целое число сотых секунды
PECL gmagick >= Unknown · gmagick
Gmagick::getimagedelay(): intЧитает задержку активного кадра как целое число сотых секунды. Фраза PHP.net о composite operator в разделе возврата ошибочна: getter вызывает MagickGetImageDelay, это время, не оператор наложения.
Gmagick::getimagedelay(): intАргументов нет. Getter или навигация относятся к текущему изображению и списку, как описано выше.
Возврат: Целое число с указанным выше смыслом.
PHP.net указывает GmagickException при ошибке. Неверный тип аргумента может быть отклонён PHP как TypeError до выполнения операции. Проверки диапазона в функциях примеров — отдельные правила приложения. Для nextImage/previousImage обычная граница обхода также выражается false.
Доступность: PECL Gmagick; нижняя граница на этих официальных страницах указана Unknown. Это не означает определённую версию PHP. Примеры привязаны к указанной Q16-сборке, ограничения которой разобраны в уроке.
Два применения: Сравнить спокойный и быстрый показ; Задержать последний ракурс.
Gmagick::getimagedisposeЧитает целый код метода удаления активного кадра после его времени показа
PECL gmagick >= Unknown · gmagick
Gmagick::getimagedispose(): intЧитает целый код метода удаления активного кадра после его времени показа. Этот getter не удаляет кадр из списка: для удаления элемента списка служит removeImage.
Gmagick::getimagedispose(): intАргументов нет. Getter или навигация относятся к текущему изображению и списку, как описано выше.
Возврат: Целое число с указанным выше смыслом.
PHP.net указывает GmagickException при ошибке. Неверный тип аргумента может быть отклонён PHP как TypeError до выполнения операции. Проверки диапазона в функциях примеров — отдельные правила приложения. Для nextImage/previousImage обычная граница обхода также выражается false.
Доступность: PECL Gmagick; нижняя граница на этих официальных страницах указана Unknown. Это не означает определённую версию PHP. Примеры привязаны к указанной Q16-сборке, ограничения которой разобраны в уроке.
Два применения: Сравнить удаление на полных кадрах; Увидеть влияние удаления на частичные кадры.
Gmagick::getimageiterationsЧитает целое значение iterations активного изображения
PECL gmagick >= Unknown · gmagick
Gmagick::getimageiterations(): intЧитает целое значение iterations активного изображения. Для итогового GIF проверяем настройку первого кадра и прочитанный файл; это другой показатель, чем длительность отдельного кадра.
Gmagick::getimageiterations(): intАргументов нет. Getter или навигация относятся к текущему изображению и списку, как описано выше.
Возврат: Целое число с указанным выше смыслом.
PHP.net указывает GmagickException при ошибке. Неверный тип аргумента может быть отклонён PHP как TypeError до выполнения операции. Проверки диапазона в функциях примеров — отдельные правила приложения. Для nextImage/previousImage обычная граница обхода также выражается false.
Доступность: PECL Gmagick; нижняя граница на этих официальных страницах указана Unknown. Это не означает определённую версию PHP. Примеры привязаны к указанной Q16-сборке, ограничения которой разобраны в уроке.
Два применения: Сравнить непрерывный цикл и конечный повтор; Настроить показ функцией каталога.
Gmagick::setimagedelayЗадаёт время показа активного кадра до перехода к следующему
PECL gmagick >= Unknown · gmagick
Gmagick::setimagedelay(int $delay): GmagickЗадаёт время показа активного кадра до перехода к следующему. Настройка относится к одному кадру, поэтому одинаковую скорость всей последовательности задают явным обходом. Для длинной паузы в конце меняют именно последний кадр.
Gmagick::setimagedelay(int $delay): Gmagick| Аргумент | Тип | Смысл |
|---|---|---|
delay | int — обязательный | Задержка текущего кадра в сотых долях секунды:30 означает0.30s, в файле GIF это300ms. Ноль не обещает мгновенного показа в браузере. |
Возврат: Изменённый Gmagick; объект можно использовать для следующей операции.
PHP.net указывает GmagickException при ошибке. Неверный тип аргумента может быть отклонён PHP как TypeError до выполнения операции. Проверки диапазона в функциях примеров — отдельные правила приложения. Для nextImage/previousImage обычная граница обхода также выражается false.
Доступность: PECL Gmagick; нижняя граница на этих официальных страницах указана Unknown. Это не означает определённую версию PHP. Примеры привязаны к указанной Q16-сборке, ограничения которой разобраны в уроке.
Два применения: Сравнить спокойный и быстрый показ; Задержать последний ракурс.
Gmagick::setimagedisposeЗадаёт действие после показа кадра: оставить область, очистить её фоном или восстановить прежнее содержимое
PECL gmagick >= Unknown · gmagick
Gmagick::setimagedispose(int $disposeType): GmagickЗадаёт действие после показа кадра: оставить область, очистить её фоном или восстановить прежнее содержимое. Для полных непрозрачных кадров разница может быть невидима; при частичных кадрах настройка влияет на собранную картинку.
Gmagick::setimagedispose(int $disposeType): Gmagick| Аргумент | Тип | Смысл |
|---|---|---|
disposeType | int — обязательный | Целое значение метода удаления:0 не определён,1 оставить,2 восстановить фон области,3 восстановить предыдущее содержимое области. В коде используем именованные DISPOSE_*;4…7 зарезервированы GIF89a. |
Возврат: Изменённый Gmagick; объект можно использовать для следующей операции.
PHP.net указывает GmagickException при ошибке. Неверный тип аргумента может быть отклонён PHP как TypeError до выполнения операции. Проверки диапазона в функциях примеров — отдельные правила приложения. Для nextImage/previousImage обычная граница обхода также выражается false.
Доступность: PECL Gmagick; нижняя граница на этих официальных страницах указана Unknown. Это не означает определённую версию PHP. Примеры привязаны к указанной Q16-сборке, ограничения которой разобраны в уроке.
Два применения: Сравнить удаление на полных кадрах; Увидеть влияние удаления на частичные кадры.
Gmagick::setimageiterationsЗадаёт iterations изображения, используемые при записи повторяющейся анимации
PECL gmagick >= Unknown · gmagick
Gmagick::setimageiterations(int $iterations): GmagickЗадаёт iterations изображения, используемые при записи повторяющейся анимации. Настройка всего цикла и задержки кадров решают разные задачи. Не используйте ошибочную единицу1/100s из описания этого параметра PHP.net.
Gmagick::setimageiterations(int $iterations): Gmagick| Аргумент | Тип | Смысл |
|---|---|---|
iterations | int — обязательный | Число повторений анимации. Ноль означает непрерывное повторение. Это не задержка кадра: строка о1/100s на странице этого параметра — ошибка документации. Хранимое расширение GIF и getter сравниваются отдельно. |
Возврат: Изменённый Gmagick; объект можно использовать для следующей операции.
PHP.net указывает GmagickException при ошибке. Неверный тип аргумента может быть отклонён PHP как TypeError до выполнения операции. Проверки диапазона в функциях примеров — отдельные правила приложения. Для nextImage/previousImage обычная граница обхода также выражается false.
Доступность: PECL Gmagick; нижняя граница на этих официальных страницах указана Unknown. Это не означает определённую версию PHP. Примеры привязаны к указанной Q16-сборке, ограничения которой разобраны в уроке.
Два применения: Сравнить непрерывный цикл и конечный повтор; Настроить показ функцией каталога.
Код и руководство с собой
Скачайте самостоятельные примеры с исходными данными, инструкциями и ожидаемыми результатами. Примеры HTTP и фрагменты для проекта помечены отдельно: им нужно указанное окружение.
Код не исполняется на сайте. Скачайте нужный пример и запускайте его в своём локальном окружении.
Материалы сверены 2026-10-12. Примеры и объяснения написаны для этого руководства; источники и обсуждения доступны в каждой главе.


