Перейти к содержимому
Поиск
Php Разработка

PHP: полный мануал с примерами, функциями и ООП

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

Александр НекрасовИзменено:
Практический мануал PHP: от переменных и функций к объектной модели интернет-магазина
PHP 8.5.11468 глав6256 карточек справочника
Дерево руководства

Глава 376 · После переменных, объектов, файлов и последовательностей Imagick

Imagick: gravity текущего изображения и настоящее выравнивание карточек

Увидеть реальный append, прочитать и изменить свойство нужного кадра, отличить Draw/Wand и абсолютные координаты.

Получить понятное выравнивание двух карточек

Нужно поставить рядом две карточки разной высоты: полную карточку товара и небольшое превью. По умолчанию короткая картинка оказывается сверху; в макете её хочется выровнять по центру или снизу. Сначала посмотрите три реально собранных PNG. Справа одна и та же картинка200×160 занимает y=0,80 или160 на холсте400×320. Слева карточка200×320 остаётся на месте.

Реальный appendImages(false): короткий второй кадр сверху, по центру и снизу
Реальный appendImages(false): короткий второй кадр сверху, по центру и снизу

Gravity здесь означает правило привязки: сверху, по центру или снизу; это не сила тяжести и не готовая пара x/y. У объекта есть текущее изображение, а в последовательности текущий кадр выбирает iterator. $image — переменная с объектом; -> вызывает метод, () содержит аргументы, ; завершает инструкцию. Imagick::GRAVITY_SOUTH — именованная целочисленная константа. Getter получает значение без аргументов; setter записывает одно значение. Переменные, объекты и последовательности Imagick — связанные объяснения.

Оригинальная собственная иллюстрация400×320 явно уменьшена PHP до200×160; рамка нарисована внутри, поэтому размеры не выросли. Высокая карточка содержит эту иллюстрацию и условные графические полосы описания — это учебный макет, а не текст товара. Helper не прячет изучаемые вызовы: программа выбирает кадр, задаёт gravity и вызывает appendImages(false). false означает слева направо; возвращается новый Imagick с результатом. Затем он записывается как отдельный PNG.

Собрать карточки разной высоты и увидеть выравнивание

Три настоящих PNG показывают короткую карточку справа сверху, по центру и снизу. Растр меняет appendImages, который читает gravity каждого кадра; один setter пиксели не передвигал.

Собрать карточки разной высоты и увидеть выравниваниеПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__.'/gravity-fixture.php';
gravityRestore();
[$tall,$tile]=gravityParts();$views=[];$observed=[];
gravityView(new Imagick(__DIR__.'/source.png'),'source-preview8.png');
foreach(['north'=>Imagick::GRAVITY_NORTHWEST,'center'=>Imagick::GRAVITY_CENTER,'south'=>Imagick::GRAVITY_SOUTH] as $name=>$wanted){
    $sequence=new Imagick();$sequence->addImage($tall);$sequence->addImage($tile);
    $sequence->setFirstIterator();$sequence->setImageGravity(Imagick::GRAVITY_NORTHWEST);
    $sequence->setIteratorIndex(1);$before=gravityHash($sequence);
    $ok=$sequence->setImageGravity($wanted);$current=$sequence->getImageGravity();$same=$before===gravityHash($sequence);
    $sequence->setFirstIterator();$sequence->setImageBackgroundColor('white');
    $result=$sequence->appendImages(false); // false joins left-to-right; each frame supplies its own alignment.
    gravityView($result,$name.'-append.png');$views[]=new Imagick(__DIR__.'/'.$name.'-append.png');
    $observed[]=['name'=>$name,'requested'=>$wanted,'current'=>$current,'setter_return'=>$ok,'pixels_unchanged_by_setter'=>$same,'output'=>gravityPixels($result)];
}
$rects=gravityCompare($views,'gravity-first.png');
gravityDiagnostic('image-gravity-first',['cases'=>$observed,'panel_geometry'=>$rects,'checks'=>['three_real_alignments'=>count(array_unique(array_map('gravityHash',$views)))===3,'setter_only_keeps_pixels'=>!in_array(false,array_column($observed,'pixels_unchanged_by_setter'),true),'properties_match_request'=>array_column($observed,'current')===array_column($observed,'requested')]]);
echo "gravity-first.png\nsource-preview8.png\nnorth-append.png\ncenter-append.png\nsouth-append.png\nmetrics.json\nalignments=3 setter-keeps-pixels=1\n";

Три настоящих PNG показывают короткую карточку справа сверху, по центру и снизу. Растр меняет appendImages, который читает gravity каждого кадра; один setter пиксели не передвигал. Сохраните example.php и два дополнительных текстовых файла из архива в одной папке; запустите php example.php с Imagick/PNG и правом записи. Helper проверяет SHA и восстанавливает свой исходник, готовит компоненты карточек, сохраняет нейтральные RGB8-просмотры и metrics.json. Изучаемые getter/setter, выбор текущего кадра и операции размещения видимы в программе.

Ожидаемый вывод
gravity-first.png
source-preview8.png
north-append.png
center-append.png
south-append.png
metrics.json
alignments=3 setter-keeps-pixels=1

Разделить свойство, контекст и фактическое размещение

Свойство текущего кадра, операция-потребитель и абсолютные координаты — отдельные элементы
Свойство текущего кадра, операция-потребитель и абсолютные координаты — отдельные элементы

Знакомая модель — выравнивание картинок в строке. У короткой картинки есть правило «по нижнему краю»; компоновщик использует высоту строки, чтобы найти место. Аналогия ограничена этой задачей: Imagick не является CSS-layout, не вычисляет автоматически интервалы/переносы и не заставляет все методы читать gravity. Setter записывает предпочтение в объект; растр создаёт последующий consumer.

Где хранится правилоКак читаем/задаёмКто использует
Текущее изображение/кадрgetImageGravity / setImageGravityНапример, appendImages читает gravity каждого участвующего кадра
Контекст Wand image_infogetGravity / setGravityОтдельная настройка; не переписывает уже существующие кадры
Объект рисования ImagickDrawgetGravity / setGravity у DrawПравила текста/рисования в DrawInfo, отдельные от image->gravity
Аргумент конкретного методаcompositeImageGravity(...,$gravity)Явное значение передано в вызов; getter можно использовать как источник аргумента
Абсолютные координатыcompositeImage(...,$x,$y)Положение определяется числами x/y; imagegravity не подменяет их

В точном Core AppendImages цикл вызывает GravityAdjustGeometry с next->gravity каждого кадра. Первый кадр также задаёт фон результирующего холста. До append здесь вызывается setFirstIterator, потому что операция начинает с текущего изображения и идёт к концу. setImageGravity влияет только на выбранный кадр; один вызов не является рассылкой всем кадрам.

Прочитать именно выбранное изображение и применить значение

Прочитать int текущего изображения, затем явно использовать значения двух кадров для размещения
Прочитать int текущего изображения, затем явно использовать значения двух кадров для размещения

Gravity здесь означает правило привязки: сверху, по центру или снизу; это не сила тяжести и не готовая пара x/y. У объекта есть текущее изображение, а в последовательности текущий кадр выбирает iterator. $image — переменная с объектом; -> вызывает метод, () содержит аргументы, ; завершает инструкцию. Imagick::GRAVITY_SOUTH — именованная целочисленная константа. Getter получает значение без аргументов; setter записывает одно значение. Переменные, объекты и последовательности Imagick — связанные объяснения.

Минимальная запись и полный официальный контракт

Imagick::getImageGravity(): int
$gravity = $image->getImageGravity();

Параметров нет; возвращается int — gravity текущего изображения, одна из констант семейства GRAVITY_*. Официальная запись отличает метод от getGravity и говорит о текущей последовательности. Exact C уточняет: читается image->gravity именно текущего кадра, не общий результат всех кадров. Если выбрать другой кадр, число может измениться. У этого известного собственного исходника наблюдается незаданное Core-значение0; не трактуйте0 как координату или универсальный код ошибки.

Доступность: PECL imagick 2 >= 2.3.0, PECL imagick 3; оба метода требуют сборку с ImageMagick6.4.4 или новее. В исходных официальных записях нет примеров кода и отдельного раздела ошибок. Текущий PHP wrapper проверяет непустой Imagick: без изображения оба метода дают ImagickException; неверный путь может завершиться исключением ещё в new Imagick, до getter/setter. Неверный PHP-тип/число аргументов обрабатывает PHP binding. Это уточнение фактического поведения, а не выдуманный текст официальной страницы.

Именованные положения

СлеваПо центруСправа
GRAVITY_NORTHWESTGRAVITY_NORTHGRAVITY_NORTHEAST
GRAVITY_WESTGRAVITY_CENTERGRAVITY_EAST
GRAVITY_SOUTHWESTGRAVITY_SOUTHGRAVITY_SOUTHEAST

Названия задают ориентир, но конкретное использование и допустимые смещения определяет операция. В горизонтальном append одинаковая ширина не меняет смысл, а разная высота делает вертикальное выравнивание видимым. Примеры используют имена; числа1/5/8 в stdout — наблюдения установленной версии, а не рекомендация запоминать номера.

Полный официальный XML без сокращений
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<refentry xmlns="http://docbook.org/ns/docbook" xml:id="imagick.getimagegravity">
 <refnamediv>
  <refname>Imagick::getImageGravity</refname>
  <refpurpose>Gets the image gravity</refpurpose>
 </refnamediv>

 <refsect1 role="description">
  &reftitle.description;
  <methodsynopsis>
   <modifier>public</modifier> <type>int</type><methodname>Imagick::getImageGravity</methodname>
   <void />
  </methodsynopsis>

  <para>
   Gets the current gravity value of the
   image. Unlike <function>Imagick::getGravity</function>, this method
   returns the gravity defined for the current image sequence.
   &imagick.method.available.0x644;
  </para>
 </refsect1>

 <refsect1 role="parameters">
  &reftitle.parameters;
  &no.function.parameters;
 </refsect1>

 <refsect1 role="returnvalues">
  &reftitle.returnvalues;
  <para>
   Returns the images gravity property. Refer to the list of 
   <link linkend="imagick.constants.gravity">gravity constants</link>.
  </para>
 </refsect1>

</refentry>

<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->

Прочитать свойство текущего изображения

У собственного исходника прочитан int0 — наблюдаемое незаданное Core-значение этого известного исходника. Это значение свойства, не координата и не код неудачи чтения. Само чтение не меняет рисунок.

Прочитать свойство текущего изображенияПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__.'/gravity-fixture.php';
gravityRestore();
$image=new Imagick(__DIR__.'/source.png');
$value=$image->getImageGravity();
$undefined=$value===0; // Observed unset Core value of this known own source.
printf("gravity=%d type=%s undefined=%d\n",$value,get_debug_type($value),(int)$undefined);
gravityView($image,'gravity-get-minimal.png');
gravityDiagnostic('image-gravity-getimagegravity-minimal',['value'=>$value,'value_type'=>get_debug_type($value),'undefined'=>$undefined,'pixels'=>gravityPixels($image),'checks'=>['getter_is_int'=>is_int($value),'known_own_source_is_undefined'=>$undefined]]);
echo "gravity-get-minimal.png\nmetrics.json\n";

У собственного исходника прочитан int0 — наблюдаемое незаданное Core-значение этого известного исходника. Это значение свойства, не координата и не код неудачи чтения. Само чтение не меняет рисунок. Сохраните example.php и два дополнительных текстовых файла из архива в одной папке; запустите php example.php с Imagick/PNG и правом записи. Helper проверяет SHA и восстанавливает свой исходник, готовит компоненты карточек, сохраняет нейтральные RGB8-просмотры и metrics.json. Изучаемые getter/setter, выбор текущего кадра и операции размещения видимы в программе.

Ожидаемый вывод
gravity=0 type=int undefined=1
gravity-get-minimal.png
metrics.json

Практическая задача getter — проверить настройки выбранного кадра, когда входом служит последовательность. В следующем примере два холста имеют разные imagegravity, а общий Wand-option равен Center. setIteratorIndex выбирает0 или1; getImage извлекает только текущий кадр. Значение getter явно передаётся compositeImageGravity третьим аргументом. Этот метод не доказательство автоматического чтения свойства: связь видна в самом выражении.

Прочитать разные кадры и явно передать положение операции

Getter читает выбранный кадр последовательности. Его значение явно передано compositeImageGravity, поэтому получены две разные позиции. getGravity контекста остаётся Center и не заменяет настройки кадров.

Прочитать разные кадры и явно передать положение операцииПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__.'/gravity-fixture.php';
gravityRestore();
[, $tile]=gravityParts();$sequence=new Imagick();
foreach([Imagick::GRAVITY_NORTHWEST,Imagick::GRAVITY_SOUTH] as $value){$canvas=new Imagick();$canvas->newImage(400,320,'white');$canvas->setImageGravity($value);$sequence->addImage($canvas);}
$sequence->setGravity(Imagick::GRAVITY_CENTER); // A different setting: this does not rewrite existing frames.
$views=[];$observed=[];
foreach(['north','south'] as $index=>$name){
    $sequence->setIteratorIndex($index);$frameGravity=$sequence->getImageGravity();$wandGravity=$sequence->getGravity();
    $canvas=$sequence->getImage(); // Extract the current image, not a clone of the whole sequence.
    $ok=$canvas->compositeImageGravity($tile,Imagick::COMPOSITE_OVER,$frameGravity); // Explicit argument bridges the getter to this operation.
    gravityView($canvas,$name.'-bridge.png');$views[]=new Imagick(__DIR__.'/'.$name.'-bridge.png');
    $observed[]=['index'=>$index,'image_gravity'=>$frameGravity,'wand_gravity'=>$wandGravity,'composite_return'=>$ok];
}
$sequence->setFirstIterator();$rects=gravityCompare($views,'gravity-get-workflow.png');
gravityDiagnostic('image-gravity-getimagegravity-workflow',['frames'=>$observed,'panel_geometry'=>$rects,'checks'=>['current_frames_have_distinct_gravity'=>array_column($observed,'image_gravity')===[Imagick::GRAVITY_NORTHWEST,Imagick::GRAVITY_SOUTH],'wand_option_is_separate'=>array_column($observed,'wand_gravity')===[Imagick::GRAVITY_CENTER,Imagick::GRAVITY_CENTER],'explicit_placements_differ'=>gravityHash($views[0])!==gravityHash($views[1]),'bridge_succeeded'=>!in_array(false,array_column($observed,'composite_return'),true)]]);
echo "gravity-get-workflow.png\nnorth-bridge.png\nsouth-bridge.png\nmetrics.json\nframes=2 distinct-image-gravity=1 wand-option-is-separate=1\n";

Getter читает выбранный кадр последовательности. Его значение явно передано compositeImageGravity, поэтому получены две разные позиции. getGravity контекста остаётся Center и не заменяет настройки кадров. Сохраните example.php и два дополнительных текстовых файла из архива в одной папке; запустите php example.php с Imagick/PNG и правом записи. Helper проверяет SHA и восстанавливает свой исходник, готовит компоненты карточек, сохраняет нейтральные RGB8-просмотры и metrics.json. Изучаемые getter/setter, выбор текущего кадра и операции размещения видимы в программе.

Ожидаемый вывод
gravity-get-workflow.png
north-bridge.png
south-bridge.png
metrics.json
frames=2 distinct-image-gravity=1 wand-option-is-separate=1

Задать правило нужному кадру, затем вызвать настоящий consumer

Свойство само не двигает рисунок; правильный кадр меняет append, а одинаковые абсолютные x/y дают одинаковый результат
Свойство само не двигает рисунок; правильный кадр меняет append, а одинаковые абсолютные x/y дают одинаковый результат

Gravity здесь означает правило привязки: сверху, по центру или снизу; это не сила тяжести и не готовая пара x/y. У объекта есть текущее изображение, а в последовательности текущий кадр выбирает iterator. $image — переменная с объектом; -> вызывает метод, () содержит аргументы, ; завершает инструкцию. Imagick::GRAVITY_SOUTH — именованная целочисленная константа. Getter получает значение без аргументов; setter записывает одно значение. Переменные, объекты и последовательности Imagick — связанные объяснения.

Минимальная запись и полный официальный контракт

Imagick::setImageGravity(int $gravity): bool
$ok = $image->setImageGravity(Imagick::GRAVITY_SOUTH);
Аргумент/результатСмысл
$gravity:int, обязательныйИменованная константа положения текущего изображения. Не x/y и не номер кадра.
booltrueФактический статус успешной записи свойства в PHP binding.
ПикселиSetter сам не изменяет размеры, компоненты и положение рисунка.

В полном официальном XML и текущей странице есть неточность: synopsis обещает bool, а абзац Return Values говорит, что значение не возвращается. Текущий stub и PHP wrapper возвращают true; оригинальный абзац ниже сохранён. Exact Wand просто присваивает image->gravity и не проверяет принадлежность int перечислению. В приложении разрешайте именованные варианты по своей таблице, не произвольные номера. Успех setter не означает, что следующая произвольная операция читает это свойство.

Доступность: PECL imagick 2 >= 2.3.0, PECL imagick 3; оба метода требуют сборку с ImageMagick6.4.4 или новее. В исходных официальных записях нет примеров кода и отдельного раздела ошибок. Текущий PHP wrapper проверяет непустой Imagick: без изображения оба метода дают ImagickException; неверный путь может завершиться исключением ещё в new Imagick, до getter/setter. Неверный PHP-тип/число аргументов обрабатывает PHP binding. Это уточнение фактического поведения, а не выдуманный текст официальной страницы.

Именованные положения

СлеваПо центруСправа
GRAVITY_NORTHWESTGRAVITY_NORTHGRAVITY_NORTHEAST
GRAVITY_WESTGRAVITY_CENTERGRAVITY_EAST
GRAVITY_SOUTHWESTGRAVITY_SOUTHGRAVITY_SOUTHEAST

Названия задают ориентир, но конкретное использование и допустимые смещения определяет операция. В горизонтальном append одинаковая ширина не меняет смысл, а разная высота делает вертикальное выравнивание видимым. Примеры используют имена; числа1/5/8 в stdout — наблюдения установленной версии, а не рекомендация запоминать номера.

Полный официальный XML без сокращений
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<refentry xmlns="http://docbook.org/ns/docbook" xml:id="imagick.setimagegravity">
 <refnamediv>
  <refname>Imagick::setImageGravity</refname>
  <refpurpose>Sets the image gravity</refpurpose>
 </refnamediv>

 <refsect1 role="description">
  &reftitle.description;
  <methodsynopsis>
   <modifier>public</modifier> <type>bool</type><methodname>Imagick::setImageGravity</methodname>
   <methodparam><type>int</type><parameter>gravity</parameter></methodparam>
  </methodsynopsis>

  <para>
   Sets the gravity property for the current image. This method can be used 
   to set the gravity property for a single image sequence.
   &imagick.method.available.0x644;
  </para>
 </refsect1>

 <refsect1 role="parameters">
  &reftitle.parameters;
  <para>
   <variablelist>
    <varlistentry>
     <term><parameter>gravity</parameter></term>
     <listitem>
      <para>
       The gravity property. Refer to the list of 
       <link linkend="imagick.constants.gravity">gravity constants</link>.
      </para>
     </listitem>
    </varlistentry>
   </variablelist>
  </para>

 </refsect1>
 <refsect1 role="returnvalues">
  &reftitle.returnvalues;
  <para>
   &return.void;
  </para>
 </refsect1>

</refentry>

<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->

Записать свойство и проверить, что пиксели ещё прежние

Успешный setter возвращает booltrue, getter читает South (8 в этой сборке), а RGBA8-компоненты до и после совпадают. Нужна следующая операция, которая использует это свойство.

Записать свойство и проверить, что пиксели ещё прежниеПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__.'/gravity-fixture.php';
gravityRestore();
$image=new Imagick(__DIR__.'/source.png');$before=gravityHash($image);
$ok=$image->setImageGravity(Imagick::GRAVITY_SOUTH);
$value=$image->getImageGravity();$same=$before===gravityHash($image);
printf("set=%s gravity=%d pixels_unchanged=%d\n",$ok?'true':'false',$value,(int)$same);
gravityView($image,'gravity-set-minimal.png');
gravityDiagnostic('image-gravity-setimagegravity-minimal',['return_value'=>$ok,'return_type'=>get_debug_type($ok),'value'=>$value,'before_hash'=>$before,'after_hash'=>gravityHash($image),'checks'=>['setter_true'=>$ok===true,'property_is_south'=>$value===Imagick::GRAVITY_SOUTH,'pixels_unchanged'=>$same]]);
echo "gravity-set-minimal.png\nmetrics.json\n";

Успешный setter возвращает booltrue, getter читает South (8 в этой сборке), а RGBA8-компоненты до и после совпадают. Нужна следующая операция, которая использует это свойство. Сохраните example.php и два дополнительных текстовых файла из архива в одной папке; запустите php example.php с Imagick/PNG и правом записи. Helper проверяет SHA и восстанавливает свой исходник, готовит компоненты карточек, сохраняет нейтральные RGB8-просмотры и metrics.json. Изучаемые getter/setter, выбор текущего кадра и операции размещения видимы в программе.

Ожидаемый вывод
set=true gravity=8 pixels_unchanged=1
gravity-set-minimal.png
metrics.json

При росте требования макет получает строковую настройку top/middle/bottom. Нельзя считать произвольный int от посетителя безопасной поддерживаемой константой: таблица приложения разрешает три понятных варианта. Сначала показана типичная ошибка — setGravity у Wand и ожидание изменения кадров. Затем политика применяется к конкретному короткому кадру. Последние две панели объясняют ещё одну частую ошибку: compositeImage получает явные10,20 и при разных imagegravity рисует в том же месте.

Применить настройку карточки к нужному кадру

Строковая настройка bottom проверена по разрешённым значениям и применена к короткому кадру. Append теперь ставит его снизу. Два отдельных compositeImage с одинаковыми x/y совпадают: координатный метод не превращается в gravity-операцию от одного setter.

Применить настройку карточки к нужному кадруПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__.'/gravity-fixture.php';
gravityRestore();
[$tall,$tile]=gravityParts();$policy='bottom';
$allowed=['top'=>Imagick::GRAVITY_NORTHWEST,'middle'=>Imagick::GRAVITY_CENTER,'bottom'=>Imagick::GRAVITY_SOUTH];
if(!array_key_exists($policy,$allowed)){throw new InvalidArgumentException('Unknown card alignment');}$wanted=$allowed[$policy];
$wrong=new Imagick();$wrong->setGravity($wanted);$wrong->addImage($tall);$wrong->addImage($tile);$wrong->setFirstIterator();$wrong->setImageBackgroundColor('white');
$wrong->setIteratorIndex(1);$wrongFrame=$wrong->getImageGravity();$wrong->setFirstIterator();$wrongResult=$wrong->appendImages(false);gravityView($wrongResult,'wand-option-only.png');
$correct=new Imagick();$correct->addImage($tall);$correct->addImage($tile);$correct->setFirstIterator();$correct->setImageGravity(Imagick::GRAVITY_NORTHWEST);
$correct->setIteratorIndex(1);$before=gravityHash($correct);$ok=$correct->setImageGravity($wanted);$selected=$correct->getImageGravity();$same=$before===gravityHash($correct);
$correct->setFirstIterator();$correct->setImageBackgroundColor('white');$result=$correct->appendImages(false);gravityView($result,'frame-policy-applied.png');
$views=[new Imagick(__DIR__.'/wand-option-only.png'),new Imagick(__DIR__.'/frame-policy-applied.png')];$xy=[];
foreach(['north'=>Imagick::GRAVITY_NORTHWEST,'south'=>Imagick::GRAVITY_SOUTH] as $name=>$value){
    $canvas=new Imagick();$canvas->newImage(400,320,'white');$canvas->setImageGravity($value);
    $canvas->compositeImage($tile,Imagick::COMPOSITE_OVER,10,20); // Absolute x/y: no image-gravity lookup here.
    gravityView($canvas,'xy-'.$name.'.png');$xy[]=new Imagick(__DIR__.'/xy-'.$name.'.png');$views[]=end($xy);
}
$rects=gravityCompare($views,'gravity-set-workflow.png');$appendChanged=gravityHash($views[0])!==gravityHash($views[1]);$xySame=gravityHash($xy[0])===gravityHash($xy[1]);
gravityDiagnostic('image-gravity-setimagegravity-workflow',['policy'=>$policy,'wanted'=>$wanted,'wrong_wand_gravity'=>$wrong->getGravity(),'wrong_frame_gravity'=>$wrongFrame,'selected_frame_gravity'=>$selected,'setter_return'=>$ok,'setter_pixels_unchanged'=>$same,'append_changed'=>$appendChanged,'absolute_xy_unchanged'=>$xySame,'xy'=>['x'=>10,'y'=>20],'panel_geometry'=>$rects,'checks'=>['named_policy_matches_frame'=>$selected===$wanted,'wand_option_did_not_rewrite_frame'=>$wrongFrame!==$wanted,'absolute_xy_is_unchanged_by_image_gravity'=>$xySame,'setter_true_and_pixels_unchanged'=>$ok===true&&$same]]);
echo "gravity-set-workflow.png\nwand-option-only.png\nframe-policy-applied.png\nxy-north.png\nxy-south.png\nmetrics.json\n";
printf("policy=%s append-changes=%d absolute-xy-unchanged=%d\n",$policy,(int)$appendChanged,(int)$xySame);

Строковая настройка bottom проверена по разрешённым значениям и применена к короткому кадру. Append теперь ставит его снизу. Два отдельных compositeImage с одинаковыми x/y совпадают: координатный метод не превращается в gravity-операцию от одного setter. Сохраните example.php и два дополнительных текстовых файла из архива в одной папке; запустите php example.php с Imagick/PNG и правом записи. Helper проверяет SHA и восстанавливает свой исходник, готовит компоненты карточек, сохраняет нейтральные RGB8-просмотры и metrics.json. Изучаемые getter/setter, выбор текущего кадра и операции размещения видимы в программе.

Ожидаемый вывод
gravity-set-workflow.png
wand-option-only.png
frame-policy-applied.png
xy-north.png
xy-south.png
metrics.json
policy=bottom append-changes=1 absolute-xy-unchanged=1

Выбрать операцию и проверить границы поведения

Названия gravity общие, а путь применения зависит от API. Командная строка magick может разобрать -gravity вместе с -extent/-geometry до Core-вызова; нельзя механически переносить это поведение в PHP. В проверенной Imagick3.8.1/ImageMagick7.1.1-46 extentImage(w,h,x,y) использует явные -x/-y в Core и не читает imagegravity: NW и South при одинаковых0,0 дали один растр. Для собственного расширенного холста рассчитывайте нужные смещения по контракту extentImage либо создайте canvas и явно передайте gravity в compositeImageGravity. Не обещаем одно поведение всех версий и всех методов.

ПотребностьПодход
Выстроить карточки разной высоты рядомЗадать imagegravity нужным кадрам, выбрать начало и вызвать appendImages(false)
Поставить одно превью по якорю на холстЯвно передать константу или результат getter в compositeImageGravity
Поставить watermark на точные координатыВычислить x/y и передать в compositeImage; gravity не добавляет отступы сам
Позиционировать текстНастроить ImagickDraw и его gravity; учитывать метрики шрифта и baseline
Обработать всю последовательностьЯвно пройти/выбрать кадры; текущий кадр и текущая последовательность не взаимозаменяемы
Сохранить прозрачность или цветПроверять отдельный контракт alpha/цвета; gravity не является преобразованием ICC и не гарантирует alpha-политику

Упражнение: измените $policy с bottom на уже разрешённый вариант middle и убедитесь, что короткая картинка располагается на y=80, а setter по-прежнему не меняет её компоненты. Решение — связать middle с GRAVITY_CENTER, задать это второму кадру, вернуть iterator к началу и выполнить append. При одинаковой высоте кадров различия top/middle/bottom могут стать невидимыми: это геометрия задачи, не доказательство поломки setter. Измерять скорость в этих примерах мы не пытаемся; стоимость чтения свойства и создания нового растрового холста — разные виды работы.

Полный helper подготовки и просмотра

<?php
declare(strict_types=1);
function gravityRestore():void {$raw=base64_decode((string)file_get_contents(__DIR__.'/source.png.b64'),true);if($raw===false||hash('sha256',$raw)!=='f51e5780445e0f5130a7f23112b2a00618035afd5545b8e3042c7ccff09b617c'||file_put_contents(__DIR__.'/source.png',$raw)===false){throw new RuntimeException('Own source missing or changed');}}
function gravityHash(Imagick $image):string {return hash('sha256',json_encode($image->exportImagePixels(0,0,$image->getImageWidth(),$image->getImageHeight(),'RGBA',Imagick::PIXEL_CHAR),JSON_THROW_ON_ERROR));}
function gravityPixels(Imagick $image):array {return ['width'=>$image->getImageWidth(),'height'=>$image->getImageHeight(),'RGBA8_hash'=>gravityHash($image)];}
function gravityOpaque(Imagick $image):Imagick {$view=new Imagick();$view->newImage($image->getImageWidth(),$image->getImageHeight(),'white');$view->compositeImage($image,Imagick::COMPOSITE_OVER,0,0);$view->setImageType(Imagick::IMGTYPE_TRUECOLOR);return $view;}
function gravityView(Imagick $image,string $filename):void {$view=gravityOpaque($image);$view->setImageFormat('png');$view->setImageDepth(8);$view->setOption('png:bit-depth','8');$view->setOption('png:color-type','2');$view->setOption('png:exclude-chunk','all');if(!$view->writeImage(__DIR__.'/'.$filename)){throw new RuntimeException('PNG preview write failed');}}
function gravityParts():array {
 $source=new Imagick(__DIR__.'/source.png');$tile=new Imagick();$tile->newImage(400,320,'white');$tile->compositeImage($source,Imagick::COMPOSITE_OVER,0,0);$tile->resizeImage(200,160,Imagick::FILTER_LANCZOS,1);$tile->setImagePage(0,0,0,0);
 $d=new ImagickDraw();$d->setFillColor('none');$d->setStrokeColor('#c66d32');$d->setStrokeWidth(1);$d->rectangle(0,0,199,159);$tile->drawImage($d);
 $tall=new Imagick();$tall->newImage(200,320,'#e2f1ed');$tall->compositeImage($tile,Imagick::COMPOSITE_OVER,0,0);
 $d=new ImagickDraw();$d->setStrokeColor('none');$d->setFillColor('#195b63');$d->roundRectangle(16,186,184,212,5,5);$d->setFillColor('#6b9093');$d->rectangle(16,230,160,240);$d->rectangle(16,250,130,260);$d->setFillColor('#d09443');$d->roundRectangle(16,278,100,304,4,4);$tall->drawImage($d);
 return [$tall,$tile];
}
function gravityCompare(array $images,string $filename):array {$board=new Imagick();$board->newImage(400*count($images),320,'white');$rects=[];foreach($images as $i=>$image){if($image->getImageWidth()!==400||$image->getImageHeight()!==320){throw new RuntimeException('Expected a complete 400x320 panel');}$board->compositeImage($image,Imagick::COMPOSITE_OVER,400*$i,0);$rects[]=['x'=>400*$i,'y'=>0,'width'=>400,'height'=>320];}gravityView($board,$filename);return $rects;}
function gravityDiagnostic(string $id,array $data):void {$doc=['schema'=>'aen-image-gravity-program-diagnostics-v1','example_id'=>$id]+$data;if(file_put_contents(__DIR__.'/metrics.json',json_encode($doc,JSON_PRETTY_PRINT|JSON_PRESERVE_ZERO_FRACTION|JSON_THROW_ON_ERROR)."\n")===false){throw new RuntimeException('Diagnostic write failed');}}

gravityParts готовит только собственный макет; target getter/setter и append/bridge вызываются в программах. Нейтральные RGB8-превью показаны OVERwhite, поэтому они не сертифицируют сохранение прозрачности исходного RGBA во всех форматах. В веб-проекте отдавайте созданный PNG отдельным ответом с Content-Type:image/png, без echo диагностики перед бинарными байтами. Следующие шаги: кадры и iterator, композиция, текст и Draw gravity, работа с файлами.

Функции и методы этой темы

Откройте карточку, чтобы увидеть договор функции, примеры, ограничения и связанные инструменты.

Imagick::getImageGravityGravity текущего кадра: чтение

PECL imagick 2 >= 2.3.0, PECL imagick 3 · imagick

Imagick::getImageGravity(): int

Gravity здесь означает правило привязки: сверху, по центру или снизу; это не сила тяжести и не готовая пара x/y. У объекта есть текущее изображение, а в последовательности текущий кадр выбирает iterator. $image — переменная с объектом; -> вызывает метод, () содержит аргументы, ; завершает инструкцию. Imagick::GRAVITY_SOUTH — именованная целочисленная константа. Getter получает значение без аргументов; setter записывает одно значение. Переменные, объекты и последовательности Imagick — связанные объяснения.

Минимальная запись и полный официальный контракт

Imagick::getImageGravity(): int
$gravity = $image->getImageGravity();

Параметров нет; возвращается int — gravity текущего изображения, одна из констант семейства GRAVITY_*. Официальная запись отличает метод от getGravity и говорит о текущей последовательности. Exact C уточняет: читается image->gravity именно текущего кадра, не общий результат всех кадров. Если выбрать другой кадр, число может измениться. У этого известного собственного исходника наблюдается незаданное Core-значение0; не трактуйте0 как координату или универсальный код ошибки.

Доступность: PECL imagick 2 >= 2.3.0, PECL imagick 3; оба метода требуют сборку с ImageMagick6.4.4 или новее. В исходных официальных записях нет примеров кода и отдельного раздела ошибок. Текущий PHP wrapper проверяет непустой Imagick: без изображения оба метода дают ImagickException; неверный путь может завершиться исключением ещё в new Imagick, до getter/setter. Неверный PHP-тип/число аргументов обрабатывает PHP binding. Это уточнение фактического поведения, а не выдуманный текст официальной страницы.

Именованные положения

СлеваПо центруСправа
GRAVITY_NORTHWESTGRAVITY_NORTHGRAVITY_NORTHEAST
GRAVITY_WESTGRAVITY_CENTERGRAVITY_EAST
GRAVITY_SOUTHWESTGRAVITY_SOUTHGRAVITY_SOUTHEAST

Названия задают ориентир, но конкретное использование и допустимые смещения определяет операция. В горизонтальном append одинаковая ширина не меняет смысл, а разная высота делает вертикальное выравнивание видимым. Примеры используют имена; числа1/5/8 в stdout — наблюдения установленной версии, а не рекомендация запоминать номера.

Полный официальный XML без сокращений
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<refentry xmlns="http://docbook.org/ns/docbook" xml:id="imagick.getimagegravity">
 <refnamediv>
  <refname>Imagick::getImageGravity</refname>
  <refpurpose>Gets the image gravity</refpurpose>
 </refnamediv>

 <refsect1 role="description">
  &reftitle.description;
  <methodsynopsis>
   <modifier>public</modifier> <type>int</type><methodname>Imagick::getImageGravity</methodname>
   <void />
  </methodsynopsis>

  <para>
   Gets the current gravity value of the
   image. Unlike <function>Imagick::getGravity</function>, this method
   returns the gravity defined for the current image sequence.
   &imagick.method.available.0x644;
  </para>
 </refsect1>

 <refsect1 role="parameters">
  &reftitle.parameters;
  &no.function.parameters;
 </refsect1>

 <refsect1 role="returnvalues">
  &reftitle.returnvalues;
  <para>
   Returns the images gravity property. Refer to the list of 
   <link linkend="imagick.constants.gravity">gravity constants</link>.
  </para>
 </refsect1>

</refentry>

<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->

Прочитать свойство текущего изображения

У собственного исходника прочитан int0 — наблюдаемое незаданное Core-значение этого известного исходника. Это значение свойства, не координата и не код неудачи чтения. Само чтение не меняет рисунок.

Прочитать свойство текущего изображенияПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__.'/gravity-fixture.php';
gravityRestore();
$image=new Imagick(__DIR__.'/source.png');
$value=$image->getImageGravity();
$undefined=$value===0; // Observed unset Core value of this known own source.
printf("gravity=%d type=%s undefined=%d\n",$value,get_debug_type($value),(int)$undefined);
gravityView($image,'gravity-get-minimal.png');
gravityDiagnostic('image-gravity-getimagegravity-minimal',['value'=>$value,'value_type'=>get_debug_type($value),'undefined'=>$undefined,'pixels'=>gravityPixels($image),'checks'=>['getter_is_int'=>is_int($value),'known_own_source_is_undefined'=>$undefined]]);
echo "gravity-get-minimal.png\nmetrics.json\n";

У собственного исходника прочитан int0 — наблюдаемое незаданное Core-значение этого известного исходника. Это значение свойства, не координата и не код неудачи чтения. Само чтение не меняет рисунок. Сохраните example.php и два дополнительных текстовых файла из архива в одной папке; запустите php example.php с Imagick/PNG и правом записи. Helper проверяет SHA и восстанавливает свой исходник, готовит компоненты карточек, сохраняет нейтральные RGB8-просмотры и metrics.json. Изучаемые getter/setter, выбор текущего кадра и операции размещения видимы в программе.

Ожидаемый вывод
gravity=0 type=int undefined=1
gravity-get-minimal.png
metrics.json

Прочитать разные кадры и явно передать положение операции

Getter читает выбранный кадр последовательности. Его значение явно передано compositeImageGravity, поэтому получены две разные позиции. getGravity контекста остаётся Center и не заменяет настройки кадров.

Прочитать разные кадры и явно передать положение операцииПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__.'/gravity-fixture.php';
gravityRestore();
[, $tile]=gravityParts();$sequence=new Imagick();
foreach([Imagick::GRAVITY_NORTHWEST,Imagick::GRAVITY_SOUTH] as $value){$canvas=new Imagick();$canvas->newImage(400,320,'white');$canvas->setImageGravity($value);$sequence->addImage($canvas);}
$sequence->setGravity(Imagick::GRAVITY_CENTER); // A different setting: this does not rewrite existing frames.
$views=[];$observed=[];
foreach(['north','south'] as $index=>$name){
    $sequence->setIteratorIndex($index);$frameGravity=$sequence->getImageGravity();$wandGravity=$sequence->getGravity();
    $canvas=$sequence->getImage(); // Extract the current image, not a clone of the whole sequence.
    $ok=$canvas->compositeImageGravity($tile,Imagick::COMPOSITE_OVER,$frameGravity); // Explicit argument bridges the getter to this operation.
    gravityView($canvas,$name.'-bridge.png');$views[]=new Imagick(__DIR__.'/'.$name.'-bridge.png');
    $observed[]=['index'=>$index,'image_gravity'=>$frameGravity,'wand_gravity'=>$wandGravity,'composite_return'=>$ok];
}
$sequence->setFirstIterator();$rects=gravityCompare($views,'gravity-get-workflow.png');
gravityDiagnostic('image-gravity-getimagegravity-workflow',['frames'=>$observed,'panel_geometry'=>$rects,'checks'=>['current_frames_have_distinct_gravity'=>array_column($observed,'image_gravity')===[Imagick::GRAVITY_NORTHWEST,Imagick::GRAVITY_SOUTH],'wand_option_is_separate'=>array_column($observed,'wand_gravity')===[Imagick::GRAVITY_CENTER,Imagick::GRAVITY_CENTER],'explicit_placements_differ'=>gravityHash($views[0])!==gravityHash($views[1]),'bridge_succeeded'=>!in_array(false,array_column($observed,'composite_return'),true)]]);
echo "gravity-get-workflow.png\nnorth-bridge.png\nsouth-bridge.png\nmetrics.json\nframes=2 distinct-image-gravity=1 wand-option-is-separate=1\n";

Getter читает выбранный кадр последовательности. Его значение явно передано compositeImageGravity, поэтому получены две разные позиции. getGravity контекста остаётся Center и не заменяет настройки кадров. Сохраните example.php и два дополнительных текстовых файла из архива в одной папке; запустите php example.php с Imagick/PNG и правом записи. Helper проверяет SHA и восстанавливает свой исходник, готовит компоненты карточек, сохраняет нейтральные RGB8-просмотры и metrics.json. Изучаемые getter/setter, выбор текущего кадра и операции размещения видимы в программе.

Ожидаемый вывод
gravity-get-workflow.png
north-bridge.png
south-bridge.png
metrics.json
frames=2 distinct-image-gravity=1 wand-option-is-separate=1
Imagick::setImageGravityGravity текущего кадра: запись

PECL imagick 2 >= 2.3.0, PECL imagick 3 · imagick

Imagick::setImageGravity(int $gravity): bool

Gravity здесь означает правило привязки: сверху, по центру или снизу; это не сила тяжести и не готовая пара x/y. У объекта есть текущее изображение, а в последовательности текущий кадр выбирает iterator. $image — переменная с объектом; -> вызывает метод, () содержит аргументы, ; завершает инструкцию. Imagick::GRAVITY_SOUTH — именованная целочисленная константа. Getter получает значение без аргументов; setter записывает одно значение. Переменные, объекты и последовательности Imagick — связанные объяснения.

Минимальная запись и полный официальный контракт

Imagick::setImageGravity(int $gravity): bool
$ok = $image->setImageGravity(Imagick::GRAVITY_SOUTH);
Аргумент/результатСмысл
$gravity:int, обязательныйИменованная константа положения текущего изображения. Не x/y и не номер кадра.
booltrueФактический статус успешной записи свойства в PHP binding.
ПикселиSetter сам не изменяет размеры, компоненты и положение рисунка.

В полном официальном XML и текущей странице есть неточность: synopsis обещает bool, а абзац Return Values говорит, что значение не возвращается. Текущий stub и PHP wrapper возвращают true; оригинальный абзац ниже сохранён. Exact Wand просто присваивает image->gravity и не проверяет принадлежность int перечислению. В приложении разрешайте именованные варианты по своей таблице, не произвольные номера. Успех setter не означает, что следующая произвольная операция читает это свойство.

Доступность: PECL imagick 2 >= 2.3.0, PECL imagick 3; оба метода требуют сборку с ImageMagick6.4.4 или новее. В исходных официальных записях нет примеров кода и отдельного раздела ошибок. Текущий PHP wrapper проверяет непустой Imagick: без изображения оба метода дают ImagickException; неверный путь может завершиться исключением ещё в new Imagick, до getter/setter. Неверный PHP-тип/число аргументов обрабатывает PHP binding. Это уточнение фактического поведения, а не выдуманный текст официальной страницы.

Именованные положения

СлеваПо центруСправа
GRAVITY_NORTHWESTGRAVITY_NORTHGRAVITY_NORTHEAST
GRAVITY_WESTGRAVITY_CENTERGRAVITY_EAST
GRAVITY_SOUTHWESTGRAVITY_SOUTHGRAVITY_SOUTHEAST

Названия задают ориентир, но конкретное использование и допустимые смещения определяет операция. В горизонтальном append одинаковая ширина не меняет смысл, а разная высота делает вертикальное выравнивание видимым. Примеры используют имена; числа1/5/8 в stdout — наблюдения установленной версии, а не рекомендация запоминать номера.

Полный официальный XML без сокращений
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<refentry xmlns="http://docbook.org/ns/docbook" xml:id="imagick.setimagegravity">
 <refnamediv>
  <refname>Imagick::setImageGravity</refname>
  <refpurpose>Sets the image gravity</refpurpose>
 </refnamediv>

 <refsect1 role="description">
  &reftitle.description;
  <methodsynopsis>
   <modifier>public</modifier> <type>bool</type><methodname>Imagick::setImageGravity</methodname>
   <methodparam><type>int</type><parameter>gravity</parameter></methodparam>
  </methodsynopsis>

  <para>
   Sets the gravity property for the current image. This method can be used 
   to set the gravity property for a single image sequence.
   &imagick.method.available.0x644;
  </para>
 </refsect1>

 <refsect1 role="parameters">
  &reftitle.parameters;
  <para>
   <variablelist>
    <varlistentry>
     <term><parameter>gravity</parameter></term>
     <listitem>
      <para>
       The gravity property. Refer to the list of 
       <link linkend="imagick.constants.gravity">gravity constants</link>.
      </para>
     </listitem>
    </varlistentry>
   </variablelist>
  </para>

 </refsect1>
 <refsect1 role="returnvalues">
  &reftitle.returnvalues;
  <para>
   &return.void;
  </para>
 </refsect1>

</refentry>

<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->

Записать свойство и проверить, что пиксели ещё прежние

Успешный setter возвращает booltrue, getter читает South (8 в этой сборке), а RGBA8-компоненты до и после совпадают. Нужна следующая операция, которая использует это свойство.

Записать свойство и проверить, что пиксели ещё прежниеПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__.'/gravity-fixture.php';
gravityRestore();
$image=new Imagick(__DIR__.'/source.png');$before=gravityHash($image);
$ok=$image->setImageGravity(Imagick::GRAVITY_SOUTH);
$value=$image->getImageGravity();$same=$before===gravityHash($image);
printf("set=%s gravity=%d pixels_unchanged=%d\n",$ok?'true':'false',$value,(int)$same);
gravityView($image,'gravity-set-minimal.png');
gravityDiagnostic('image-gravity-setimagegravity-minimal',['return_value'=>$ok,'return_type'=>get_debug_type($ok),'value'=>$value,'before_hash'=>$before,'after_hash'=>gravityHash($image),'checks'=>['setter_true'=>$ok===true,'property_is_south'=>$value===Imagick::GRAVITY_SOUTH,'pixels_unchanged'=>$same]]);
echo "gravity-set-minimal.png\nmetrics.json\n";

Успешный setter возвращает booltrue, getter читает South (8 в этой сборке), а RGBA8-компоненты до и после совпадают. Нужна следующая операция, которая использует это свойство. Сохраните example.php и два дополнительных текстовых файла из архива в одной папке; запустите php example.php с Imagick/PNG и правом записи. Helper проверяет SHA и восстанавливает свой исходник, готовит компоненты карточек, сохраняет нейтральные RGB8-просмотры и metrics.json. Изучаемые getter/setter, выбор текущего кадра и операции размещения видимы в программе.

Ожидаемый вывод
set=true gravity=8 pixels_unchanged=1
gravity-set-minimal.png
metrics.json

Применить настройку карточки к нужному кадру

Строковая настройка bottom проверена по разрешённым значениям и применена к короткому кадру. Append теперь ставит его снизу. Два отдельных compositeImage с одинаковыми x/y совпадают: координатный метод не превращается в gravity-операцию от одного setter.

Применить настройку карточки к нужному кадруПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__.'/gravity-fixture.php';
gravityRestore();
[$tall,$tile]=gravityParts();$policy='bottom';
$allowed=['top'=>Imagick::GRAVITY_NORTHWEST,'middle'=>Imagick::GRAVITY_CENTER,'bottom'=>Imagick::GRAVITY_SOUTH];
if(!array_key_exists($policy,$allowed)){throw new InvalidArgumentException('Unknown card alignment');}$wanted=$allowed[$policy];
$wrong=new Imagick();$wrong->setGravity($wanted);$wrong->addImage($tall);$wrong->addImage($tile);$wrong->setFirstIterator();$wrong->setImageBackgroundColor('white');
$wrong->setIteratorIndex(1);$wrongFrame=$wrong->getImageGravity();$wrong->setFirstIterator();$wrongResult=$wrong->appendImages(false);gravityView($wrongResult,'wand-option-only.png');
$correct=new Imagick();$correct->addImage($tall);$correct->addImage($tile);$correct->setFirstIterator();$correct->setImageGravity(Imagick::GRAVITY_NORTHWEST);
$correct->setIteratorIndex(1);$before=gravityHash($correct);$ok=$correct->setImageGravity($wanted);$selected=$correct->getImageGravity();$same=$before===gravityHash($correct);
$correct->setFirstIterator();$correct->setImageBackgroundColor('white');$result=$correct->appendImages(false);gravityView($result,'frame-policy-applied.png');
$views=[new Imagick(__DIR__.'/wand-option-only.png'),new Imagick(__DIR__.'/frame-policy-applied.png')];$xy=[];
foreach(['north'=>Imagick::GRAVITY_NORTHWEST,'south'=>Imagick::GRAVITY_SOUTH] as $name=>$value){
    $canvas=new Imagick();$canvas->newImage(400,320,'white');$canvas->setImageGravity($value);
    $canvas->compositeImage($tile,Imagick::COMPOSITE_OVER,10,20); // Absolute x/y: no image-gravity lookup here.
    gravityView($canvas,'xy-'.$name.'.png');$xy[]=new Imagick(__DIR__.'/xy-'.$name.'.png');$views[]=end($xy);
}
$rects=gravityCompare($views,'gravity-set-workflow.png');$appendChanged=gravityHash($views[0])!==gravityHash($views[1]);$xySame=gravityHash($xy[0])===gravityHash($xy[1]);
gravityDiagnostic('image-gravity-setimagegravity-workflow',['policy'=>$policy,'wanted'=>$wanted,'wrong_wand_gravity'=>$wrong->getGravity(),'wrong_frame_gravity'=>$wrongFrame,'selected_frame_gravity'=>$selected,'setter_return'=>$ok,'setter_pixels_unchanged'=>$same,'append_changed'=>$appendChanged,'absolute_xy_unchanged'=>$xySame,'xy'=>['x'=>10,'y'=>20],'panel_geometry'=>$rects,'checks'=>['named_policy_matches_frame'=>$selected===$wanted,'wand_option_did_not_rewrite_frame'=>$wrongFrame!==$wanted,'absolute_xy_is_unchanged_by_image_gravity'=>$xySame,'setter_true_and_pixels_unchanged'=>$ok===true&&$same]]);
echo "gravity-set-workflow.png\nwand-option-only.png\nframe-policy-applied.png\nxy-north.png\nxy-south.png\nmetrics.json\n";
printf("policy=%s append-changes=%d absolute-xy-unchanged=%d\n",$policy,(int)$appendChanged,(int)$xySame);

Строковая настройка bottom проверена по разрешённым значениям и применена к короткому кадру. Append теперь ставит его снизу. Два отдельных compositeImage с одинаковыми x/y совпадают: координатный метод не превращается в gravity-операцию от одного setter. Сохраните example.php и два дополнительных текстовых файла из архива в одной папке; запустите php example.php с Imagick/PNG и правом записи. Helper проверяет SHA и восстанавливает свой исходник, готовит компоненты карточек, сохраняет нейтральные RGB8-просмотры и metrics.json. Изучаемые getter/setter, выбор текущего кадра и операции размещения видимы в программе.

Ожидаемый вывод
gravity-set-workflow.png
wand-option-only.png
frame-policy-applied.png
xy-north.png
xy-south.png
metrics.json
policy=bottom append-changes=1 absolute-xy-unchanged=1
Источники и обсуждения

Код и руководство с собой

Скачайте самостоятельные примеры с исходными данными, инструкциями и ожидаемыми результатами. Примеры HTTP и фрагменты для проекта помечены отдельно: им нужно указанное окружение.

Код не исполняется на сайте. Скачайте нужный пример и запускайте его в своём локальном окружении.

Материалы сверены 2026-10-12. Примеры и объяснения написаны для этого руководства; источники и обсуждения доступны в каждой главе.