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

Дерево руководства
Глава 352 · После цветовых и художественных эффектов
Imagick: цветовые ступени, соляризация и приглушённый фон
От первого оформительского PNG до понятного dithering, Quantum-порога и точной маркировки на изменённом фоне.
Получить оформительский PNG и сохранить исходник
Для каталога нужны три самостоятельных оформления: товар с ограниченными цветовыми ступенями, необычная выборочная инверсия и приглушённый фон под точную маркировку. Исходник содержит коробку, кружку и ярлык, а нижние шкалы позволяют понять изменения по числам. Это не коррекция достоверности цвета товара; оригинал сохраняется отдельно.
RGB — три численных компоненты цвета. Интенсивность — численная яркость, вычисляемая из цветовых компонентов; solarize ниже сравнивает сами компоненты, а не эту яркость. c или v — текущее значение одной RGB-компоненты, c′ — её значение после эффекта. На сохранённых PNG8 каждая имеет уровни 0..255. Q — QuantumRange, максимум внутреннего канала: в проверенной Q16-сборке 65535. T — целый порог solarize, здесь intdiv(Q,2)=32767. Levels — число ступеней каждого канала posterize; k — номер ступени от 0 до levels−1; dither — логическое true/false, с особым соответствием параметра перечислению IM7, разобранным ниже. Dithering распределяет ошибку округления между соседями, создавая пространственный узор вместо одних плоских ступеней. Factor f blueShift — безразмерное число; m/min и M/max — минимум и максимум исходного RGB. Clamp ограничивает результат допустимым диапазоном; ни Q, ни T не обозначают число пикселей.


Модель posterize: исходная компонента → ближайшая равномерная ступень; dithering распределяет ошибку по соседям. Модель solarize: сравнить каждую компоненту с T → выше заменить на Q−v → остальные оставить. Модель blueShift: найти исходные m/M → добавить общий член к четверти каждой компоненты → clamp. Ни одно правило не распознаёт смысл маркировки или «правильный» художественный цвет.

Самая маленькая запись
В $image уже находится загруженная копия. 4 — int уровней каждого канала, true — bool; в проверенной IM7-обёртке это NoDither. Стрелка -> вызывает метод объекта; скобки содержат аргументы, запятая отделяет их, ; завершает команду.
$image->posterizeImage(4, true);$image = clone $source; создаёт независимую копию, простое присваивание объект не копирует. Метод изменяет текущую картинку и возвращает bool: нельзя записывать этот bool обратно вместо изображения. В полном коде if с ! проверяет false, throw new RuntimeException останавливает отказавшую цепочку; clear освобождает native-ресурсы после сохранения. Подготовка: объекты и методы, clone, исключения.
Распакуйте весь ZIP рядом: example.php — программа, stylization-fixture.php — показанный помощник, source.png.b64 — текстовые Base64-байты точного PNG. Require подключает файл относительно __DIR__, папки программы. LoadStylizationSource декодирует данные, проверяет SHA256, восстанавливает source.png и возвращает Imagick. SaveStylizationComparison сохраняет отдельное RGB PNG8 со сравниваемыми панелями и печатает имя; сам файл открывают просмотрщиком. Это полезный оформительский результат вместе с исходником, не только набор числовых контрольных плашек.
<?php
declare(strict_types=1);
require __DIR__ . '/stylization-fixture.php';
$source = loadStylizationSource();
$image = clone $source;
if (!$image->posterizeImage(4, true)) {
throw new RuntimeException('Не удалось применить posterizeImage');
}
saveStylizationComparison([$source, $image], 'style-first.png');
$source->clear();
$image->clear();
Результат: Исходник и готовый posterize(4,true) 400×320; основной файл сравнения 800×320. В сохранённом PNG контрольная плашка RGB(120, 80, 40) стала (85, 85, 0), а серая 128 стала 170. Крупные цветовые переходы стали ступенями; четыре уровня на канал не равны палитре из четырёх цветов. Архив содержит example.php, stylization-fixture.php и source.png.b64. Распакуйте все три рядом и выполните php example.php в папке с правом записи и PHP/Imagick. Помощник проверит SHA256 и восстановит точный source.png без интернета и шрифтов при запуске. Выходной PNG откройте просмотрщиком; stdout содержит его фиксированное имя. Сравнение 800×320: исходник, далее варианты в указанном порядке, каждая панель 400×320 без resize. Надписи входного растра не пересчитываются эффектом.
Ожидаемый вывод
style-first.png
Полный переносимый помощник stylization-fixture.php
<?php
declare(strict_types=1);
function loadStylizationSource(): Imagick
{
$encoded = file_get_contents(__DIR__ . '/source.png.b64');
if ($encoded === false) {
throw new RuntimeException('Не найден source.png.b64: распакуйте весь архив');
}
$bytes = base64_decode($encoded, true);
if ($bytes === false || hash('sha256', $bytes) !== '453b22e19273f2fdd54ec6a7f0cd9e96a7b08c70cc4cc854838d1428fea207c6') {
throw new RuntimeException('Повреждён исходный PNG');
}
$path = __DIR__ . '/source.png';
if (file_put_contents($path, $bytes) !== strlen($bytes)) {
throw new RuntimeException('Не удалось восстановить source.png');
}
return new Imagick($path);
}
function saveStylizationComparison(array $panels, string $filename): void
{
if ($panels === []) {
throw new InvalidArgumentException('Нужна хотя бы одна панель');
}
$output = new Imagick();
$output->newImage(400 * count($panels), 320, 'white');
$output->setImageFormat('png');
foreach ($panels as $index => $panel) {
if (!$panel instanceof Imagick || $panel->getImageWidth() !== 400 || $panel->getImageHeight() !== 320) {
throw new InvalidArgumentException('Панель должна быть Imagick 400 на 320 пикселей');
}
if (!$output->compositeImage($panel, Imagick::COMPOSITE_OVER, 400 * $index, 0)) {
throw new RuntimeException('Не удалось собрать сравнение');
}
}
$output->setImageDepth(8);
$output->setOption('png:color-type', '2');
if (!$output->writeImage(__DIR__ . '/' . $filename)) {
throw new RuntimeException('Не удалось записать результат');
}
$output->clear();
echo $filename, "\n";
}
Function объявляет функцию, тип после двоеточия описывает результат: Imagick у загрузчика, void у сохранения. Array $panels — список, foreach перебирает объекты/индексы, count считает панели. Base64_decode с true отвергает повреждённый текст; hash сравнивает байты по SHA256. ===/!== строго различают false и данные, strlen считает записанные байты. Composite собирает непрозрачные панели без resize; depth 8 и color-type 2 задают сохранённый RGB PNG8. Это открытая инфраструктура переносимого примера. Подготовка: функции, массивы, foreach, файлы.
Проследить значение канала и пространственную ошибку
При levels 4 прямые RGB-ступени соответствуют PNG8 уровням 0, 85, 170, 255. У dithering соседние значения выбираются так, чтобы пространственный узор передавал промежуточный тон; это дополнительная фактура, а не новые произвольные уровни палитры. Для заданного дизайнером списка цветов нужен другой инструмент, например remap, а не изменение смысла levels.
У solarize единицы внутренние: Q = 65535,T = 32767. На точном Quantum-контроле 32766 и 32767 остались прежними, 32768 превратился в 32767. Смешанный RGB(40000, 10000, 50000) стал (25535, 10000, 15535): зелёная компонента ниже порога не изменилась. В сохранённом PNG8 серые уровни 127 и 128 оба стали 127; светлая плашка 230 стала 25. Предыдущие значения 32766 и выше — реальные внутренние значения до PNG8, а не обещание увидеть 65535 в восьмибитном просмотрщике.
У blueShift при значении по умолчанию 1.5 на RGB(120, 80, 40) минимум m = 40 и максимум M = 120, общий член равен 105: четверти компонентов 30, 20, 10 дают 135, 125, 115. Эти же значения получены в сохранённом PNG8; серая плашка 128 стала 176, а 230 ограничилась белым 255. Равные RGB остаются равными, но серый может стать светлее, а clamp уничтожает различия светлых значений. Factor 1 не выключает цветовое смешивание.
Перед полной программой: переменные ниже — независимые clone исходника. 4 — уровни, true — фактический NoDither этой сборки. В solarize нужен int: статический вызов Imagick::getQuantumRange() возвращает массив, ['quantumRangeLong'] читает его именованный элемент; :: со скобками вызывает статический метод, не читает константу. Intdiv(Q,2) делит нацело и даёт 32767. BlueShift без аргумента использует 1.5.
$image->posterizeImage(4, true);
$quantum = Imagick::getQuantumRange()['quantumRangeLong'];
$threshold = intdiv($quantum, 2);
$solar->solarizeImage($threshold);
$blue->blueShiftImage();<?php
declare(strict_types=1);
require __DIR__ . '/stylization-fixture.php';
$source = loadStylizationSource();
$image = clone $source;
if (!$image->posterizeImage(4, true)) {
throw new RuntimeException('Не удалось применить posterizeImage');
}
$solar = clone $source;
$quantum = Imagick::getQuantumRange()['quantumRangeLong'];
$threshold = intdiv($quantum, 2);
if (!$solar->solarizeImage($threshold)) {
throw new RuntimeException('Не удалось применить solarizeImage');
}
$blue = clone $source;
if (!$blue->blueShiftImage()) {
throw new RuntimeException('Не удалось применить blueShiftImage');
}
saveStylizationComparison([$source, $image, $solar, $blue], 'style-controls.png');
$source->clear();
$image->clear();
$solar->clear();
$blue->clear();
Результат: Панели: исходник, posterize(4,true), solarize(T = 32767), blueShift() со значением по умолчанию 1.5. Цветные и серые элементы показывают разные правила, а не три силы одного фильтра. Архив содержит example.php, stylization-fixture.php и source.png.b64. Распакуйте все три рядом и выполните php example.php в папке с правом записи и PHP/Imagick. Помощник проверит SHA256 и восстановит точный source.png без интернета и шрифтов при запуске. Выходной PNG откройте просмотрщиком; stdout содержит его фиксированное имя. Сравнение 1600×320: исходник, далее варианты в указанном порядке, каждая панель 400×320 без resize. Надписи входного растра не пересчитываются эффектом.
Ожидаемый вывод
style-controls.png
Разобрать обязательность, единицы и версионные ограничения
RGB — три численных компоненты цвета. Интенсивность — численная яркость, вычисляемая из цветовых компонентов; solarize ниже сравнивает сами компоненты, а не эту яркость. c или v — текущее значение одной RGB-компоненты, c′ — её значение после эффекта. На сохранённых PNG8 каждая имеет уровни 0..255. Q — QuantumRange, максимум внутреннего канала: в проверенной Q16-сборке 65535. T — целый порог solarize, здесь intdiv(Q,2)=32767. Levels — число ступеней каждого канала posterize; k — номер ступени от 0 до levels−1; dither — логическое true/false, с особым соответствием параметра перечислению IM7, разобранным ниже. Dithering распределяет ошибку округления между соседями, создавая пространственный узор вместо одних плоских ступеней. Factor f blueShift — безразмерное число; m/min и M/max — минимум и максимум исходного RGB. Clamp ограничивает результат допустимым диапазоном; ни Q, ни T не обозначают число пикселей.
| API | Что меняется | Чего число не обещает |
|---|---|---|
| posterizeImage(4,true) | Поканальные ступени, в этой IM7 NoDither | Не ровно 4 цвета и не выбор Riemersma enum. |
| posterizeImage(4,false) | При 4 уровнях диффузия Floyd–Steinberg | Не универсальный смысл false на любой версии. |
| solarizeImage(T) | Только обновляемые компоненты v > T | Не бинаризация и не доля площади кадра. |
| blueShiftImage() | Значение по умолчанию 1.5, min/max-смешивание RGB | Не отдельный синий канал и не автоматическая ночная фотография. |
Эти три метода не принимают channel. У posterize два обязательных аргумента, у solarize один обязательный int, у blueShift один необязательный float со значением по умолчанию 1.5. Способность объекта иметь alpha не означает её сохранность: контроль DirectClass в установленной сборке показал изменения alpha у posterize/solarize, тогда как blueShift её скопировал. Основные программы намеренно используют непрозрачный RGB.
На другом сервере сверяйте версии/сигнатуры, а не только название API. Малые уровни 2..16 выбраны для понятного опыта; большие значения могут почти не менять картинку и требуют другого разбора Core-ветви. Сравнительная скорость и экономия размера файла здесь не измерены. Глубина 16 бит не восстанавливает детали цвета, ранее утраченные при уменьшении уровней.
Выбрать фактуру ступеней и защитить служебные данные


Плавная шкала содержит все 256 исходных уровней; поэтому на ней видна разница округления и диффузии. Ровная ступень не обязана сохранять средний тон промежуточного участка, а dithering добавляет узор. Нельзя судить о качестве только по числу уникальных цветов или считать levels 4 четырьмя произвольными красками дизайнера.
Для защищённого макета операция ограничена x=24..375,y=88..219. Заголовок, SKU и нижние шкалы находятся снаружи и остаются точными. Жёсткая граница ROI — сознательная часть подготовленного учебного макета; для естественного силуэта нужна отдельная осмысленная маска смешивания, а не увеличение levels.
Не спутать порог, интенсивность и направление цвета


Цветной solarize может изменить оттенок: одни компоненты выше T, другие ниже. После явной grayscale-подготовки уровни равны и меняются одинаково. Это отличается от определения «светлого объекта» по интенсивности. Q — 65535 внутри проверенной сборки; сохранённые PNG8 показывают 0..255 с квантизацией.
BlueShift применяет одинаковый общий член ко всем RGB, поэтому порядок компонент до clamp сохраняется, а расстояние между ними уменьшается. Серый при значении по умолчанию 1.5 светлеет; высокие уровни могут стать одинаковым белым. Это предел полезности такого фона: проверяйте потерю бликов и читаемость. Восстановленная SKU в двух вариантах точна потому, что она возвращена отдельным слоем из исходника.
Проверить ошибки, alpha и цену потери цвета
Восемь программ успешно выполнены в PHP 8.5.11, Imagick 3.8.1, ImageMagick 7.1.1-46 Q16. Сравнения — непрозрачные RGB PNG8; размеры 400×320 на панель. Контроли проверяют поканальные уровни, отличие dithering, строгий порог, нейтральную подготовку, min/max-плашки и точную защищённую область. Возвращаемое true и одинаковые размеры сами по себе не доказывают пользу для каталога.
Малый alpha-контроль подтвердил: posterize/solarize могут менять alpha, blueShift в этом пути скопировал её точно. Основной непрозрачный источник не доказывает поведение любых ICC/CMYK/HDR/нескольких кадров. Палитровая PseudoClass и DirectClass имеют отдельные ветви; не переносите RGB-формулу на произвольные канальные пространства без проверки.
До обработки ограничьте внешний файл по формату, площади и числу кадров, а пользовательские параметры — по конечности и ресурсам. Копии и dithering используют память нативной библиотеки; время и размер файла зависят от данных. Проверяйте чтение, эффект и запись отдельно; в веб-ошибках не раскрывайте внутренние пути. Не обещаем экономию байтов или CPU без измерения.
Выбрать инструмент и оформить свой макет

- Нужны равномерные ступени на канал: posterize, с версионной проверкой bool→enum.
- Нужна инверсия только высоких компонент: solarize с целым T в Quantum-единицах.
- Нужно приглушить цветовые различия: blueShift с осмысленным factor и контролем clamp.
- Нужны точные фирменные цвета: заданная палитра/remap; число levels не заменяет список цветов.
Упражнение: оформить только товарный прямоугольник 352×132, сохранив SKU и шкалы. Решение: clone; cropImage(352,132,24,88); setImagePage(0,0,0,0); posterizeImage(4,true) в нашей сборке; COMPOSITE_OVER в (24, 88). Полная программа — защищённый posterize. Затем объясните, почему нельзя заменить true целочисленной DITHERMETHOD_RIEMERSMA, ожидая выбрать алгоритм.
Продолжение: тонирование и инверсия, тональный диапазон, художественные фактуры, координатные преобразования. Следующий оформительский вариант начинайте с назначения и данных, которые должны остаться точными.
Функции и методы этой темы
Откройте карточку, чтобы увидеть договор функции, примеры, ограничения и связанные инструменты.
Imagick::posterizeImageОформить товар цветовыми ступенями, осознанно выбрать фактуру и защитить SKU.
PECL imagick 2, PECL imagick 3 · imagick
Imagick::posterizeImage(int $levels, bool $dither): boolОформить товар цветовыми ступенями, осознанно выбрать фактуру и защитить SKU.
RGB — три численных компоненты цвета. Интенсивность — численная яркость, вычисляемая из цветовых компонентов; solarize ниже сравнивает сами компоненты, а не эту яркость. c или v — текущее значение одной RGB-компоненты, c′ — её значение после эффекта. На сохранённых PNG8 каждая имеет уровни 0..255. Q — QuantumRange, максимум внутреннего канала: в проверенной Q16-сборке 65535. T — целый порог solarize, здесь intdiv(Q,2)=32767. Levels — число ступеней каждого канала posterize; k — номер ступени от 0 до levels−1; dither — логическое true/false, с особым соответствием параметра перечислению IM7, разобранным ниже. Dithering распределяет ошибку округления между соседями, создавая пространственный узор вместо одних плоских ступеней. Factor f blueShift — безразмерное число; m/min и M/max — минимум и максимум исходного RGB. Clamp ограничивает результат допустимым диапазоном; ни Q, ни T не обозначают число пикселей.
Уменьшает число уровней обновляемых каналов. Без dithering компонента округляется к равномерной ступени Q×k/(levels−1), затем выполняется квантование. При малых уровнях 2..16 диффузионная ветвь использует карту комбинаций уровней. На непрозрачном RGB четыре уровня допускают до 4³=64 комбинаций, но не требуют, чтобы все они встретились.

Самая маленькая запись
В $image уже находится загруженная копия. 4 — int уровней каждого канала, true — bool; в проверенной IM7-обёртке это NoDither. Стрелка -> вызывает метод объекта; скобки содержат аргументы, запятая отделяет их, ; завершает команду.
$image->posterizeImage(4, true);$image = clone $source; создаёт независимую копию, простое присваивание объект не копирует. Метод изменяет текущую картинку и возвращает bool: нельзя записывать этот bool обратно вместо изображения. В полном коде if с ! проверяет false, throw new RuntimeException останавливает отказавшую цепочку; clear освобождает native-ресурсы после сохранения. Подготовка: объекты и методы, clone, исключения.
Сигнатура и все параметры
Imagick::posterizeImage(int $levels, bool $dither): boolУменьшает число уровней обновляемых каналов. Без dithering компонента округляется к равномерной ступени Q×k/(levels−1), затем выполняется квантование. При малых уровнях 2..16 диффузионная ветвь использует карту комбинаций уровней. На непрозрачном RGB четыре уровня допускают до 4³=64 комбинаций, но не требуют, чтобы все они встретились.
| Аргумент | Смысл, обязательность и единицы |
|---|---|
| $levels | Обязательный int, число уровней на канал. В этих программах фиксировано 4. Для внешних параметров можно отдельно реализовать ограничение 2..16 ради показанной ветви и ресурсов; это не полный диапазон API и не уже реализованная проверка. Это не общий размер пользовательской палитры. |
| $dither | Обязательный bool. В Imagick 3.8.1/IM7 передаётся напрямую как enum: false=0=Undefined, true=1=NoDither. При четырёх уровнях false попадает в Floyd–Steinberg, true — в прямые ступени. Не переносите это молча на другую версию связки PHP и ImageMagick. |
Возврат true при успехе; текущий объект изменяется, новый Imagick не возвращается. Channel-аргумента в этих сигнатурах нет. Пустой объект в проверенной сборке вызывает ImagickException; отказ ImageMagick также преобразуется в исключение. Пустая секция errors в raw XML не гарантирует отсутствие ошибок. Чтение, обработка и запись могут отказать независимо. Доступность PHP Manual: PECL imagick 2, PECL imagick 3. Raw changelog не содержит дополнительных записей.
В этих программах значения фиксированы: четыре уровня, целый T в диапазоне 0..Q и умеренные конечные factor. Проверки внешних параметров здесь не реализованы. Если значения приходят от пользователя, нужна отдельная валидация: например, уровни 2..16 для изученной ветви, целый T в диапазоне 0..Q и конечный factor с разумным ограничением ресурсов; это политика приложения, а не полный диапазон API. Внешний файл дополнительно ограничивают по формату, площади и кадрам. Для отказов полезны исключения и проверки файловых операций.
Полный официальный XML без изменения raw-контракта
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<refentry xmlns="http://docbook.org/ns/docbook" xml:id="imagick.posterizeimage">
<refnamediv>
<refname>Imagick::posterizeImage</refname>
<refpurpose>Reduces the image to a limited number of color level</refpurpose>
</refnamediv>
<refsect1 role="description">
&reftitle.description;
<methodsynopsis>
<modifier>public</modifier> <type>bool</type><methodname>Imagick::posterizeImage</methodname>
<methodparam><type>int</type><parameter>levels</parameter></methodparam>
<methodparam><type>bool</type><parameter>dither</parameter></methodparam>
</methodsynopsis>
<para>
Reduces the image to a limited number of color level.
</para>
</refsect1>
<refsect1 role="parameters">
&reftitle.parameters;
<para>
<variablelist>
<varlistentry>
<term><parameter>levels</parameter></term>
<listitem>
<para>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><parameter>dither</parameter></term>
<listitem>
<para>
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</refsect1>
<refsect1 role="returnvalues">
&reftitle.returnvalues;
<para>
&imagick.return.success;
</para>
</refsect1>
<refsect1 role="examples">
&reftitle.examples;
<para>
<example>
<title> <function>Imagick::posterizeImage</function></title>
<programlisting role="php">
<![CDATA[
<?php
function posterizeImage($imagePath, $posterizeType, $numberLevels) {
$imagick = new \Imagick(realpath($imagePath));
$imagick->posterizeImage($numberLevels, $posterizeType);
$imagick->setImageFormat('png');
header("Content-Type: image/png");
echo $imagick->getImageBlob();
}
posterizeImage($imagePath, \Imagick::DITHERMETHOD_RIEMERSMA, 8);
?>
]]>
</programlisting>
</example>
</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
-->
Официальный пример оформлен функцией: new Imagick(realpath(path)) читает файл, эффект меняет объект, header задаёт Content-Type, getImageBlob возвращает двоичные данные для echo. Это веб-ответ без постороннего вывода. Наши восемь программ — самостоятельные локальные PNG, а не тест HTTP. Полный исходный пример сохранён выше; функции и чтение/запись разбираются отдельно.

<?php
declare(strict_types=1);
require __DIR__ . '/stylization-fixture.php';
$source = loadStylizationSource();
$image = clone $source;
if (!$image->posterizeImage(4, true)) {
throw new RuntimeException('Не удалось применить posterizeImage');
}
$dithered = clone $source;
if (!$dithered->posterizeImage(4, false)) {
throw new RuntimeException('Не удалось применить posterizeImage');
}
saveStylizationComparison([$source, $image, $dithered], 'style-posterize-basic.png');
$source->clear();
$image->clear();
$dithered->clear();
Результат: Панели: исходник, posterize(4,true) без диффузии ошибки округления в этой IM7-сборке, posterize(4,false) с диффузией Floyd–Steinberg для четырёх уровней. 4 означает уровни каждой RGB-компоненты, а не ровно четыре цвета всего PNG. Фактура dithering и плоские ступени решают разные оформительские задачи. Архив содержит example.php, stylization-fixture.php и source.png.b64. Распакуйте все три рядом и выполните php example.php в папке с правом записи и PHP/Imagick. Помощник проверит SHA256 и восстановит точный source.png без интернета и шрифтов при запуске. Выходной PNG откройте просмотрщиком; stdout содержит его фиксированное имя. Сравнение 1200×320: исходник, далее варианты в указанном порядке, каждая панель 400×320 без resize. Надписи входного растра не пересчитываются эффектом.
Ожидаемый вывод
style-posterize-basic.png
Когда меняется требование
Для карточки каталога нужен ступенчатый рисунок товара, но заголовок, артикул и контрольные шкалы должны остаться точными. Ограничим обработку известным прямоугольником 352×132 в (24,88).
CropImage(width,height,x,y) вырезает известный прямоугольник, setImagePage(0,0,0,0) сбрасывает виртуальное смещение. CompositeImage(...,COMPOSITE_OVER,x,y) возвращает непрозрачный слой на копию макета. У posterize защищается всё вне области оформления; у blueShift, наоборот, после изменения фона восстанавливается только исходная SKU. Это разные правила сохранения данных, не распознавание объекта.

<?php
declare(strict_types=1);
require __DIR__ . '/stylization-fixture.php';
$source = loadStylizationSource();
$image = clone $source;
$region = clone $source;
$region->cropImage(352, 132, 24, 88);
$region->setImagePage(0, 0, 0, 0);
if (!$region->posterizeImage(4, true)) {
throw new RuntimeException('Не удалось применить posterizeImage');
}
if (!$image->compositeImage($region, Imagick::COMPOSITE_OVER, 24, 88)) {
throw new RuntimeException('Не удалось вернуть оформленную область');
}
$region->clear();
saveStylizationComparison([$source, $image], 'style-posterize-protected.png');
$source->clear();
$image->clear();
Результат: Справа только x=24..375,y=88..219 обработаны posterize(4,true). Вне прямоугольника каждый пиксель совпадает с исходником, включая SKU. Это подготовленный макет с явной областью, не автоматическая сегментация товара и не мягкая маска его силуэта. Архив содержит example.php, stylization-fixture.php и source.png.b64. Распакуйте все три рядом и выполните php example.php в папке с правом записи и PHP/Imagick. Помощник проверит SHA256 и восстановит точный source.png без интернета и шрифтов при запуске. Выходной PNG откройте просмотрщиком; stdout содержит его фиксированное имя. Сравнение 800×320: исходник, далее варианты в указанном порядке, каждая панель 400×320 без resize. Надписи входного растра не пересчитываются эффектом.
Ожидаемый вывод
style-posterize-protected.png
Проверка и следующий выбор
Смотрите результат в размере публикации: мелкие буквы, градиент, цвет и светлые детали. Сохраняйте исходник; это намеренная стилизация с потерей информации. Для заданной палитры нужен remap/квантование, для бинарной маски — пороговые методы, для общей инверсии или тонирования — negate/colorize/tint/sepia.
Соседние оформления: solarizeImage · blueShiftImage.
Imagick::solarizeImageПолучить цветную или нейтральную афишу с выборочной инверсией компонент.
PECL imagick 2, PECL imagick 3 · imagick
Imagick::solarizeImage(int $threshold): boolПолучить цветную или нейтральную афишу с выборочной инверсией компонент.
RGB — три численных компоненты цвета. Интенсивность — численная яркость, вычисляемая из цветовых компонентов; solarize ниже сравнивает сами компоненты, а не эту яркость. c или v — текущее значение одной RGB-компоненты, c′ — её значение после эффекта. На сохранённых PNG8 каждая имеет уровни 0..255. Q — QuantumRange, максимум внутреннего канала: в проверенной Q16-сборке 65535. T — целый порог solarize, здесь intdiv(Q,2)=32767. Levels — число ступеней каждого канала posterize; k — номер ступени от 0 до levels−1; dither — логическое true/false, с особым соответствием параметра перечислению IM7, разобранным ниже. Dithering распределяет ошибку округления между соседями, создавая пространственный узор вместо одних плоских ступеней. Factor f blueShift — безразмерное число; m/min и M/max — минимум и максимум исходного RGB. Clamp ограничивает результат допустимым диапазоном; ни Q, ни T не обозначают число пикселей.
Для каждой обновляемой компоненты v проверяет v>T; только тогда записывает Q−v. Равная порогу и меньшая остаются. Это покомпонентное правило, а не сравнение общей интенсивности пикселя. В DirectClass затрагиваются UpdatePixelTrait-каналы, включая возможную alpha; отдельная PseudoClass-ветвь меняет RGB палитры.

Самая маленькая запись
В $image уже находится загруженная копия. 32767 — целый порог в Quantum-единицах нашей Q16-сборки; ниже полный код вычисляет его из реального Q. Стрелка -> вызывает метод объекта; скобки содержат аргументы, запятая отделяет их, ; завершает команду.
$image->solarizeImage(32767);$image = clone $source; создаёт независимую копию, простое присваивание объект не копирует. Метод изменяет текущую картинку и возвращает bool: нельзя записывать этот bool обратно вместо изображения. В полном коде if с ! проверяет false, throw new RuntimeException останавливает отказавшую цепочку; clear освобождает native-ресурсы после сохранения. Подготовка: объекты и методы, clone, исключения.
Сигнатура и все параметры
Imagick::solarizeImage(int $threshold): boolДля каждой обновляемой компоненты v проверяет v>T; только тогда записывает Q−v. Равная порогу и меньшая остаются. Это покомпонентное правило, а не сравнение общей интенсивности пикселя. В DirectClass затрагиваются UpdatePixelTrait-каналы, включая возможную alpha; отдельная PseudoClass-ветвь меняет RGB палитры.
| Аргумент | Смысл, обязательность и единицы |
|---|---|
| $threshold | Единственный обязательный int. Внутренние единицы QuantumRange, без масштабирования wrapper: диапазон описания 0..Q. Здесь Q = 65535, T = 32767. В strict_types не передавайте дробное 0.5×Q прямо: intdiv(Q,2) возвращает целое. T — уровень канала, не доля числа пикселей и не процент площади. |
Возврат true при успехе; текущий объект изменяется, новый Imagick не возвращается. Channel-аргумента в этих сигнатурах нет. Пустой объект в проверенной сборке вызывает ImagickException; отказ ImageMagick также преобразуется в исключение. Пустая секция errors в raw XML не гарантирует отсутствие ошибок. Чтение, обработка и запись могут отказать независимо. Доступность PHP Manual: PECL imagick 2, PECL imagick 3. Raw changelog не содержит дополнительных записей.
В этих программах значения фиксированы: четыре уровня, целый T в диапазоне 0..Q и умеренные конечные factor. Проверки внешних параметров здесь не реализованы. Если значения приходят от пользователя, нужна отдельная валидация: например, уровни 2..16 для изученной ветви, целый T в диапазоне 0..Q и конечный factor с разумным ограничением ресурсов; это политика приложения, а не полный диапазон API. Внешний файл дополнительно ограничивают по формату, площади и кадрам. Для отказов полезны исключения и проверки файловых операций.
Полный официальный XML без изменения raw-контракта
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<refentry xmlns="http://docbook.org/ns/docbook" xml:id="imagick.solarizeimage">
<refnamediv>
<refname>Imagick::solarizeImage</refname>
<refpurpose>Applies a solarizing effect to the image</refpurpose>
</refnamediv>
<refsect1 role="description">
&reftitle.description;
<methodsynopsis>
<modifier>public</modifier> <type>bool</type><methodname>Imagick::solarizeImage</methodname>
<methodparam><type>int</type><parameter>threshold</parameter></methodparam>
</methodsynopsis>
<para>
Applies a special effect to the image, similar to the effect achieved in
a photo darkroom by selectively exposing areas of photo sensitive paper
to light. Threshold ranges from 0 to QuantumRange and is a measure of the
extent of the solarization.
</para>
</refsect1>
<refsect1 role="parameters">
&reftitle.parameters;
<para>
<variablelist>
<varlistentry>
<term><parameter>threshold</parameter></term>
<listitem>
<para>
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</refsect1>
<refsect1 role="returnvalues">
&reftitle.returnvalues;
<para>
&imagick.return.success;
</para>
</refsect1>
<refsect1 role="examples">
&reftitle.examples;
<para>
<example>
<title> <function>Imagick::solarizeImage</function></title>
<programlisting role="php">
<![CDATA[
<?php
function solarizeImage($imagePath, $solarizeThreshold) {
$imagick = new \Imagick(realpath($imagePath));
$imagick->solarizeImage($solarizeThreshold * \Imagick::getQuantum());
header("Content-Type: image/jpg");
echo $imagick->getImageBlob();
}
?>
]]>
</programlisting>
</example>
</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
-->
Официальный пример оформлен функцией: new Imagick(realpath(path)) читает файл, эффект меняет объект, header задаёт Content-Type, getImageBlob возвращает двоичные данные для echo. Это веб-ответ без постороннего вывода. Наши восемь программ — самостоятельные локальные PNG, а не тест HTTP. Полный исходный пример сохранён выше; функции и чтение/запись разбираются отдельно.

<?php
declare(strict_types=1);
require __DIR__ . '/stylization-fixture.php';
$source = loadStylizationSource();
$image = clone $source;
$quantum = Imagick::getQuantumRange()['quantumRangeLong'];
$threshold = intdiv($quantum, 2);
if (!$image->solarizeImage($threshold)) {
throw new RuntimeException('Не удалось применить solarizeImage');
}
saveStylizationComparison([$source, $image], 'style-solarize-basic.png');
$source->clear();
$image->clear();
Результат: Справа solarize при целом T = intdiv(Q, 2) = 32767, где Q = 65535. Только компоненты строго выше T инвертируются. В одном пикселе R может измениться, а G остаться прежним; это не бинарная маска и не инверсия только светлых объектов по распознаванию. Архив содержит example.php, stylization-fixture.php и source.png.b64. Распакуйте все три рядом и выполните php example.php в папке с правом записи и PHP/Imagick. Помощник проверит SHA256 и восстановит точный source.png без интернета и шрифтов при запуске. Выходной PNG откройте просмотрщиком; stdout содержит его фиксированное имя. Сравнение 800×320: исходник, далее варианты в указанном порядке, каждая панель 400×320 без resize. Надписи входного растра не пересчитываются эффектом.
Ожидаемый вывод
style-solarize-basic.png
Когда меняется требование
Требуется выбрать между необычным цветом и нейтральным тональным рисунком. Вторая независимая копия сначала действительно преобразуется в серый, затем получает тот же порог T. Подготовка меняет значения каналов до solarize.
TransformImageColorspace(Imagick::COLORSPACE_GRAY) преобразует значения цвета в серый. :: без скобок читает именованную константу пространства; это не простая смена метки файла. Затем применяется тот же int T. Исходная цветная копия и серая подготовка независимы; мы сравниваем два маршрута оформления, а не выдаём второй за тот же цветовой вход.
<?php
declare(strict_types=1);
require __DIR__ . '/stylization-fixture.php';
$source = loadStylizationSource();
$image = clone $source;
$quantum = Imagick::getQuantumRange()['quantumRangeLong'];
$threshold = intdiv($quantum, 2);
if (!$image->solarizeImage($threshold)) {
throw new RuntimeException('Не удалось применить solarizeImage');
}
$gray = clone $source;
if (!$gray->transformImageColorspace(Imagick::COLORSPACE_GRAY)) {
throw new RuntimeException('Не удалось применить transformImageColorspace');
}
if (!$gray->solarizeImage($threshold)) {
throw new RuntimeException('Не удалось применить solarizeImage');
}
saveStylizationComparison([$source, $image, $gray], 'style-solarize-gray.png');
$source->clear();
$image->clear();
$gray->clear();
Результат: Панели: исходник, RGB solarize(T), явный GRAY→solarize(T). У серой подготовки каналы нейтральны; цветной вариант инвертирует компоненты независимо. Это сравнение двух производственных маршрутов, а не смена одного channel-аргумента: у solarizeImage его нет. Архив содержит example.php, stylization-fixture.php и source.png.b64. Распакуйте все три рядом и выполните php example.php в папке с правом записи и PHP/Imagick. Помощник проверит SHA256 и восстановит точный source.png без интернета и шрифтов при запуске. Выходной PNG откройте просмотрщиком; stdout содержит его фиксированное имя. Сравнение 1200×320: исходник, далее варианты в указанном порядке, каждая панель 400×320 без resize. Надписи входного растра не пересчитываются эффектом.
Ожидаемый вывод
style-solarize-gray.png
Проверка и следующий выбор
Смотрите результат в размере публикации: мелкие буквы, градиент, цвет и светлые детали. Сохраняйте исходник; это намеренная стилизация с потерей информации. Для заданной палитры нужен remap/квантование, для бинарной маски — пороговые методы, для общей инверсии или тонирования — negate/colorize/tint/sepia.
Соседние оформления: posterizeImage · blueShiftImage.
Imagick::blueShiftImageПриглушить цветовые различия фона и сохранить исходную маркировку.
PECL imagick 3 >= 3.3.0 · imagick
Imagick::blueShiftImage(float $factor = 1.5): boolПриглушить цветовые различия фона и сохранить исходную маркировку.
RGB — три численных компоненты цвета. Интенсивность — численная яркость, вычисляемая из цветовых компонентов; solarize ниже сравнивает сами компоненты, а не эту яркость. c или v — текущее значение одной RGB-компоненты, c′ — её значение после эффекта. На сохранённых PNG8 каждая имеет уровни 0..255. Q — QuantumRange, максимум внутреннего канала: в проверенной Q16-сборке 65535. T — целый порог solarize, здесь intdiv(Q,2)=32767. Levels — число ступеней каждого канала posterize; k — номер ступени от 0 до levels−1; dither — логическое true/false, с особым соответствием параметра перечислению IM7, разобранным ниже. Dithering распределяет ошибку округления между соседями, создавая пространственный узор вместо одних плоских ступеней. Factor f blueShift — безразмерное число; m/min и M/max — минимум и максимум исходного RGB. Clamp ограничивает результат допустимым диапазоном; ни Q, ни T не обозначают число пикселей.
Для каждого RGB-пикселя берёт исходные минимум m и максимум M компонентов и выполняет два смешивания. До clamp формула c′=0.25c+0.25f×m+0.5f×M одинакова для R,G,B. Разброс компонентов уменьшается до четверти при отсутствии clamp; общий добавленный член не выбирает синий специально. Размер и расположение пикселей не меняются.

Самая маленькая запись
В $image уже находится загруженная копия. Аргументы не указаны: применяется factor = 1.5 по умолчанию. Пустые скобки всё равно обозначают вызов метода. Стрелка -> вызывает метод объекта; скобки содержат аргументы, запятая отделяет их, ; завершает команду.
$image->blueShiftImage();$image = clone $source; создаёт независимую копию, простое присваивание объект не копирует. Метод изменяет текущую картинку и возвращает bool: нельзя записывать этот bool обратно вместо изображения. В полном коде if с ! проверяет false, throw new RuntimeException останавливает отказавшую цепочку; clear освобождает native-ресурсы после сохранения. Подготовка: объекты и методы, clone, исключения.
Сигнатура и все параметры
Imagick::blueShiftImage(float $factor = 1.5): boolДля каждого RGB-пикселя берёт исходные минимум m и максимум M компонентов и выполняет два смешивания. До clamp формула c′=0.25c+0.25f×m+0.5f×M одинакова для R,G,B. Разброс компонентов уменьшается до четверти при отсутствии clamp; общий добавленный член не выбирает синий специально. Размер и расположение пикселей не меняются.
| Аргумент | Смысл, обязательность и единицы |
|---|---|
| $factor | Необязательный float со значением по умолчанию 1.5. Это безразмерный множитель, не проценты и не угол оттенка. На нейтральном v результат до clamp=(0.25+0.75f)×v: при значении по умолчанию 1.5 получается 1.375×v. Factor 0 не выключает эффект, factor 1 не тождественен для цветного пикселя. В примерах сравниваются умеренные 0.8 и 1.5. |
Возврат true при успехе; текущий объект изменяется, новый Imagick не возвращается. Channel-аргумента в этих сигнатурах нет. Пустой объект в проверенной сборке вызывает ImagickException; отказ ImageMagick также преобразуется в исключение. Пустая секция errors в raw XML не гарантирует отсутствие ошибок. Чтение, обработка и запись могут отказать независимо. Доступность PHP Manual: PECL imagick 3 >= 3.3.0. Raw changelog не содержит дополнительных записей.
В этих программах значения фиксированы: четыре уровня, целый T в диапазоне 0..Q и умеренные конечные factor. Проверки внешних параметров здесь не реализованы. Если значения приходят от пользователя, нужна отдельная валидация: например, уровни 2..16 для изученной ветви, целый T в диапазоне 0..Q и конечный factor с разумным ограничением ресурсов; это политика приложения, а не полный диапазон API. Внешний файл дополнительно ограничивают по формату, площади и кадрам. Для отказов полезны исключения и проверки файловых операций.
Полный официальный XML без изменения raw-контракта
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<refentry xml:id="imagick.blueshiftimage" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
<refnamediv>
<refname>Imagick::blueShiftImage</refname>
<refpurpose>Mutes the colors of the image</refpurpose>
</refnamediv>
<refsect1 role="description">
&reftitle.description;
<methodsynopsis>
<modifier>public</modifier> <type>bool</type><methodname>Imagick::blueShiftImage</methodname>
<methodparam choice="opt"><type>float</type><parameter>factor</parameter><initializer>1.5</initializer></methodparam>
</methodsynopsis>
<para>
Mutes the colors of the image to simulate a scene at nighttime in the moonlight.
</para>
</refsect1>
<refsect1 role="parameters">
&reftitle.parameters;
<variablelist>
<varlistentry>
<term><parameter>factor</parameter></term>
<listitem>
<para>
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1 role="returnvalues">
&reftitle.returnvalues;
<para>
&imagick.return.success;
</para>
</refsect1>
<refsect1 role="examples">
&reftitle.examples;
<para>
<example>
<title> <function>Imagick::blueShiftImage</function></title>
<programlisting role="php">
<![CDATA[
<?php
function blueShiftImage($imagePath, $blueShift) {
$imagick = new \Imagick(realpath($imagePath));
$imagick->blueShiftImage($blueShift);
header("Content-Type: image/jpg");
echo $imagick->getImageBlob();
}
?>
]]>
</programlisting>
</example>
</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
-->
Официальный пример оформлен функцией: new Imagick(realpath(path)) читает файл, эффект меняет объект, header задаёт Content-Type, getImageBlob возвращает двоичные данные для echo. Это веб-ответ без постороннего вывода. Наши восемь программ — самостоятельные локальные PNG, а не тест HTTP. Полный исходный пример сохранён выше; функции и чтение/запись разбираются отдельно.

<?php
declare(strict_types=1);
require __DIR__ . '/stylization-fixture.php';
$source = loadStylizationSource();
$image = clone $source;
if (!$image->blueShiftImage()) {
throw new RuntimeException('Не удалось применить blueShiftImage');
}
saveStylizationComparison([$source, $image], 'style-blueshift-basic.png');
$source->clear();
$image->clear();
Результат: Справа blueShiftImage() без аргумента, то есть factor = 1.5. Цветовые различия сжимаются, яркость тоже меняется; серые и светлые плашки показывают осветление и clamp. Название не означает простое усиление синего канала или гарантированную ночную сцену. Архив содержит example.php, stylization-fixture.php и source.png.b64. Распакуйте все три рядом и выполните php example.php в папке с правом записи и PHP/Imagick. Помощник проверит SHA256 и восстановит точный source.png без интернета и шрифтов при запуске. Выходной PNG откройте просмотрщиком; stdout содержит его фиксированное имя. Сравнение 800×320: исходник, далее варианты в указанном порядке, каждая панель 400×320 без resize. Надписи входного растра не пересчитываются эффектом.
Ожидаемый вывод
style-blueshift-basic.png
Когда меняется требование
Дизайнер сравнивает factor 0.8 и 1.5, но артикул и его штрихи должны иметь исходные значения. Сначала оформляем весь фон, затем возвращаем точную исходную вырезку SKU на обе независимые копии.
CropImage(width,height,x,y) вырезает известный прямоугольник, setImagePage(0,0,0,0) сбрасывает виртуальное смещение. CompositeImage(...,COMPOSITE_OVER,x,y) возвращает непрозрачный слой на копию макета. У posterize защищается всё вне области оформления; у blueShift, наоборот, после изменения фона восстанавливается только исходная SKU. Это разные правила сохранения данных, не распознавание объекта.
0.8 и 1.5 — два явных factor; $bright снова clone исходника. Вырезка $mark берётся из оригинала после создания вариантов и накладывается на оба. || означает «или»: отказ любой вставки прекращает цепочку. Чёрные штрихи/светлая подложка SKU сохраняют исходные значения пикселей, а фон вокруг остаётся стилизованным.
<?php
declare(strict_types=1);
require __DIR__ . '/stylization-fixture.php';
$source = loadStylizationSource();
$image = clone $source;
if (!$image->blueShiftImage(0.8)) {
throw new RuntimeException('Не удалось применить blueShiftImage');
}
$bright = clone $source;
if (!$bright->blueShiftImage(1.5)) {
throw new RuntimeException('Не удалось применить blueShiftImage');
}
$mark = clone $source;
$mark->cropImage(82, 32, 278, 48);
$mark->setImagePage(0, 0, 0, 0);
if (!$image->compositeImage($mark, Imagick::COMPOSITE_OVER, 278, 48) || !$bright->compositeImage($mark, Imagick::COMPOSITE_OVER, 278, 48)) {
throw new RuntimeException('Не удалось вернуть точную маркировку');
}
$mark->clear();
saveStylizationComparison([$source, $image, $bright], 'style-blueshift-protected.png');
$source->clear();
$image->clear();
$bright->clear();
Результат: Панели: исходник, factor 0.8 с оригинальной SKU, factor 1.5 с оригинальной SKU. Прямоугольник x=278..359,y=48..79 сохранён точно; окружающий фон изменён. Это явная компоновка слоя, а не обещание, что blueShift сам знает служебную маркировку. Сравните читаемость текста и сохранность светлых деталей. Архив содержит example.php, stylization-fixture.php и source.png.b64. Распакуйте все три рядом и выполните php example.php в папке с правом записи и PHP/Imagick. Помощник проверит SHA256 и восстановит точный source.png без интернета и шрифтов при запуске. Выходной PNG откройте просмотрщиком; stdout содержит его фиксированное имя. Сравнение 1200×320: исходник, далее варианты в указанном порядке, каждая панель 400×320 без resize. Надписи входного растра не пересчитываются эффектом.
Ожидаемый вывод
style-blueshift-protected.png
Проверка и следующий выбор
Смотрите результат в размере публикации: мелкие буквы, градиент, цвет и светлые детали. Сохраняйте исходник; это намеренная стилизация с потерей информации. Для заданной палитры нужен remap/квантование, для бинарной маски — пороговые методы, для общей инверсии или тонирования — negate/colorize/tint/sepia.
Соседние оформления: posterizeImage · solarizeImage.
Код и руководство с собой
Скачайте самостоятельные примеры с исходными данными, инструкциями и ожидаемыми результатами. Примеры HTTP и фрагменты для проекта помечены отдельно: им нужно указанное окружение.
Код не исполняется на сайте. Скачайте нужный пример и запускайте его в своём локальном окружении.
Материалы сверены 2026-10-12. Примеры и объяснения написаны для этого руководства; источники и обсуждения доступны в каждой главе.


