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

Дерево руководства
Глава 359 · После alpha и математики каналов
Imagick: зерно, случайные соседи и печатная фактура
Умеренная фактура, самостоятельный RGBA-слой и печатная иллюстрация с защищённым SKU.
Сохранить умеренную фактуру каталога
Нужна скачиваемая карточка с лёгким зерном или печатной иллюстрацией, а не стерильно ровная заливка. Сначала сохраним умеренную фактуру каталога; затем сравним сильный шум, случайный выбор соседа и двухцветные точки. Такие эффекты — художественный выбор: они могут ухудшить текст и точность цвета, поэтому исходник сохраняем отдельно.
RGB — красная, зелёная и синяя компоненты цвета. RGBA добавляет alpha: 0 означает прозрачный пиксель, 1 — непрозрачный. Используем собственный RGB-каталог и отдельный RGBA-слой с прозрачным отверстием; это точные копии прежних авторских входов, не результаты новых фильтров.


Напечатанные RGB-числа, названия цветов, шкала и надпись на отметке — часть исходного растра. Шум и смещение не переписывают текст; старые надписи не измеряют новые пиксели. Выходные числа берём из сохранённого PNG. Повторный запуск может дать другой случайный рисунок; на странице показан конкретный реально сохранённый результат.
| Обозначение до схемы | Смысл |
|---|---|
| c и Q | c — значение одной компоненты; Q=QuantumRange — внутренний максимум. В проверенной Q16-сборке Q=65535. Файл RGB/RGBA сохраняется с 8 битами на компоненту, то есть 0..255; это другая шкала. |
| u и T | u — случайное число от 0 до 1. T=Q×u — случайный порог по всему диапазону. Это математические обозначения схемы, не новые PHP-переменные. |
| x, y и W | x/y — координаты выходного пикселя, начало слева сверху, x вправо, y вниз. W — ширина области выбора соседа. В проверенной точке spreadImage(5.0) W=11; это не обещание исправного произвольного radius. |
| alpha и OVER | Сначала получаем сильную Gaussian-копию, затем явно задаём её вклад 0.12 и накладываем OVER поверх исходника. Это уменьшает вклад слоя, не меняет силу самого шумового метода. RGB-mаска отделяет цвет от alpha. |

Самая маленькая запись
В $image уже есть независимая копия исходника. $ начинает имя переменной, -> вызывает метод, аргументы разделены запятыми внутри скобок, ; завершает команду. Imagick::ИМЯ — константа класса, :: соединяет класс с её именем. Меняет численные значения выбранных компонент по выбранному случайному распределению. Это добавление фактуры, а не удаление шума.
Операция | объединяет маски RED, GREEN и BLUE; это не сложение чисел пикселей. В формулах ниже c — исходное значение одной компоненты, c′ — результат, Q=QuantumRange — внутренний максимум (65535 в нашей Q16-сборке), u — случайное число 0..1.
$rgbChannels = Imagick::CHANNEL_RED | Imagick::CHANNEL_GREEN | Imagick::CHANNEL_BLUE;
$image->addNoiseImage(Imagick::NOISE_GAUSSIAN, $rgbChannels);Здесь Gaussian выбирает распределение, RGB-маска — изменяемые компоненты. В IM7-переходнике этого метода attenuation фиксирован 1.0. Не передавайте вторым аргументом 0.2 как силу: это позиция int-маски каналов.
Все три целевых метода меняют текущий $image и возвращают bool true, не новый bitmap. Clone создаёт независимую копию; обычное присваивание объекта даёт ещё одно имя тому же объекту. If с ! проверяет отказ, throw new RuntimeException прерывает цепочку. Связи: объект и метод, клонирование, исключения.
Для умеренного первого результата после вызова отдельно активируем непрозрачную alpha у Gaussian-копии, умножаем её на 0.12 и собираем OVER. Методы alpha/evaluate разобраны в арифметике каналов, композиция — в сборке прозрачных слоёв. Imagick::getQuantumRange() — статический вызов метода класса, возвращающий массив; ['quantumRangeLong'] читает его элемент по ключу, = присваивает максимум переменной $Q. Require подключает noise-fixture.php из __DIR__, папки программы; обе load-функции восстанавливают точные PNG. [] создаёт массив панелей, saveNoiseComparison сохраняет их целиком и печатает имя. <?php начинает PHP, declare(strict_types=1) включает строгую передачу типов.
<?php
declare(strict_types=1);
require __DIR__ . '/noise-fixture.php';
$source = loadNoiseSource();
$overlay = loadNoiseOverlay();
$Q = Imagick::getQuantumRange()['quantumRangeLong'];
$rgbChannels = Imagick::CHANNEL_RED | Imagick::CHANNEL_GREEN | Imagick::CHANNEL_BLUE;
$grain = clone $source;
if (!$grain->addNoiseImage(Imagick::NOISE_GAUSSIAN, $rgbChannels)) {
throw new RuntimeException('Не выполнен addNoiseImage');
}
$grain->setImageAlphaChannel(Imagick::ALPHACHANNEL_OPAQUE);
if (!$grain->evaluateImage(Imagick::EVALUATE_MULTIPLY, 0.12, Imagick::CHANNEL_ALPHA)) {
throw new RuntimeException('Не выполнен evaluateImage');
}
$grain->setImageFormat('png');
$grain->setImageDepth(8);
$grain->setOption('png:color-type', '6');
if (!$grain->writeImage(__DIR__ . '/grain-layer.png')) {
throw new RuntimeException('Не записан grain-layer.png');
}
$image = noisePreview($source, $grain);
saveNoiseComparison([$source, $image], 'noise-first.png');
$source->clear();
$image->clear();
$overlay->clear();
$grain->clear();
Результат: Исходник и Gaussian-копия с вкладом 0.12 поверх исходника. Сильный шум смешан с нетронутым каталогом; это отдельная композиция, не параметр силы addNoiseImage. grain-layer.png — сам RGBA-слой без фона просмотра. Для запуска нужны example.php, noise-fixture.php, source.png.b64 и overlay.png.b64 в одной папке. Распакуйте архив целиком и выполните php example.php с расширением Imagick и правом записи. Помощник восстанавливает оба точных PNG по Base64/SHA256, не использует сеть или шрифты. Stdout — noise-first.png и перевод строки. Сравнение содержит полные панели 400×320 слева направо. При новом запуске случайный рисунок может отличаться; имя файла и смысловые свойства остаются договорённостью.
Ожидаемый вывод
noise-first.png
Полный noise-fixture.php из каждого ZIP
<?php
declare(strict_types=1);
function loadNoiseSource(): 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 loadNoiseOverlay(): Imagick
{
$encoded = file_get_contents(__DIR__ . '/overlay.png.b64');
if ($encoded === false) {
throw new RuntimeException('Не найден overlay.png.b64: распакуйте весь архив');
}
$bytes = base64_decode($encoded, true);
if ($bytes === false || hash('sha256', $bytes) !== 'ba7be41405eec777d3d0fc97f45aafb80637d90b0c883b1d4cfc684d26527866') {
throw new RuntimeException('Повреждён исходный PNG');
}
$path = __DIR__ . '/overlay.png';
if (file_put_contents($path, $bytes) !== strlen($bytes)) {
throw new RuntimeException('Не удалось восстановить overlay.png');
}
return new Imagick($path);
}
function saveNoiseComparison(array $panels, string $filename): void
{
if ($panels === []) {
throw new InvalidArgumentException('Нужна хотя бы одна панель');
}
$width = 0;
$height = 0;
foreach ($panels as $panel) {
if (!$panel instanceof Imagick) {
throw new InvalidArgumentException('Панель должна быть объектом Imagick');
}
$width += $panel->getImageWidth();
$height = max($height, $panel->getImageHeight());
}
$output = new Imagick();
$output->newImage($width, $height, 'white');
$output->setImageFormat('png');
$left = 0;
foreach ($panels as $panel) {
$top = intdiv($height - $panel->getImageHeight(), 2);
if (!$output->compositeImage($panel, Imagick::COMPOSITE_OVER, $left, $top)) {
throw new RuntimeException('Не удалось собрать полное сравнение');
}
$left += $panel->getImageWidth();
}
$output->setImageDepth(8);
$output->setOption('png:color-type', '2');
if (!$output->writeImage(__DIR__ . '/' . $filename)) {
throw new RuntimeException('Не удалось записать результат');
}
$output->clear();
echo $filename, "\n";
}
function noisePreview(Imagick $source, Imagick $overlay): Imagick
{
$preview = clone $source;
if (!$preview->compositeImage($overlay, Imagick::COMPOSITE_OVER, 0, 0)) {
throw new RuntimeException('Не удалось собрать preview');
}
return $preview;
}
Function объявляет функцию, : Imagick задаёт тип изображения, return возвращает значение. Base64_decode восстанавливает байты, hash проверяет SHA256, file_put_contents записывает вход. Foreach перебирает панели, складывает ширины и помещает их без уменьшения на общий холст. NoisePreview клонирует каталог и накладывает уже готовый слой. Помощник не вызывает три изучаемых метода, не ищет шрифты и не обращается к сети; полная обработка видна в example.php.
Различить значения, соседей и печатные точки
Шум меняет числа выбранных компонент, spread выбирает другую координату источника, случайный порог выбрасывает промежуточные уровни и оставляет 0/Q. Для Uniform добавка мала и ограничена; RANDOM может заменить весь рисунок. Ни один из этих методов не восстанавливает пропавшие детали и не распознаёт товар или текст.
До следующей полной программы: $grain, $spread и $print — независимые clone исходника; $rgbChannels объединяет RED/GREEN/BLUE. В нашей версии используем только проверенное spread 5.0. Для печатного рисунка явно GRAY, порог RED и separateRED:
$grain->addNoiseImage(Imagick::NOISE_GAUSSIAN, $rgbChannels);
$spread->spreadImage(5.0);
$print->transformImageColorspace(Imagick::COLORSPACE_GRAY);
$print->randomThresholdImage(0.2 * $Q, 0.8 * $Q, Imagick::CHANNEL_RED);
$print->separateImageChannel(Imagick::CHANNEL_RED);<?php
declare(strict_types=1);
require __DIR__ . '/noise-fixture.php';
$source = loadNoiseSource();
$overlay = loadNoiseOverlay();
$Q = Imagick::getQuantumRange()['quantumRangeLong'];
$rgbChannels = Imagick::CHANNEL_RED | Imagick::CHANNEL_GREEN | Imagick::CHANNEL_BLUE;
$grain = clone $source;
if (!$grain->addNoiseImage(Imagick::NOISE_GAUSSIAN, $rgbChannels)) {
throw new RuntimeException('Не выполнен addNoiseImage');
}
$spread = clone $source;
$spread->setImageVirtualPixelMethod(Imagick::VIRTUALPIXELMETHOD_EDGE);
if (!$spread->spreadImage(5.0)) {
throw new RuntimeException('Не выполнен spreadImage');
}
$print = clone $source;
$print->transformImageColorspace(Imagick::COLORSPACE_GRAY);
if (!$print->randomThresholdImage(0.2 * $Q, 0.8 * $Q, Imagick::CHANNEL_RED)) {
throw new RuntimeException('Не выполнен randomThresholdImage');
}
if (!$print->separateImageChannel(Imagick::CHANNEL_RED)) {
throw new RuntimeException('Не выполнен separateImageChannel');
}
saveNoiseComparison([$source, $grain, $spread, $print], 'noise-controls.png');
$source->clear();
$grain->clear();
$spread->clear();
$print->clear();
$overlay->clear();
Результат: Исходник; сильный Gaussian RGB; spreadImage(5.0); серый случайный печатный вариант 0.2Q..0.8Q. Это независимые случайные реализации, не повторение тех же байтов из других программ. Для запуска нужны example.php, noise-fixture.php, source.png.b64 и overlay.png.b64 в одной папке. Распакуйте архив целиком и выполните php example.php с расширением Imagick и правом записи. Помощник восстанавливает оба точных PNG по Base64/SHA256, не использует сеть или шрифты. Stdout — noise-controls.png и перевод строки. Сравнение содержит полные панели 400×320 слева направо. При новом запуске случайный рисунок может отличаться; имя файла и смысловые свойства остаются договорённостью.
Ожидаемый вывод
noise-controls.png
Выбрать зерно и сохранить alpha отметки
Небольшое Uniform-зерно и сильный Gaussian — разные распределения. В минимальной практике видны оба полных результата. Uniform при фиксированной attenuation 1 меняет компоненту лишь примерно на два уровня файла; увеличение контраста просмотрщиком для сравнения не выполняется.

Другая задача — фактура готовой полупрозрачной отметки. Меняем только RGB и сохраняем исходную alpha, включая отверстие и промежуточные значения. Сравнение OVER показывает её на каталоге, а overlay-grain.png хранит отдельный слой без белого фона просмотрщика.

Эта программа не обещает монохромное зерно: RGB-компоненты получают независимые решения. Для умеренной общей фактуры подходит композиция первого примера, для отдельной цветной отметки — второй маршрут. Программы: два применения addNoiseImage.
Оставить случайное смещение внутри иллюстрации
Нужен рассыпчатый живописный вариант иллюстрации. Полный spread показывает и цену эффекта: мелкий текст разрушается вместе с краями рисунка. Практическая версия обрабатывает только заранее известный прямоугольник иллюстрации 352×132 в (24,88), защищая SKU и служебные поля.

CropImage принимает ширину, высоту, x, y; setImagePage(0,0,0,0) сбрасывает виртуальную позицию вырезки. EDGE продолжает её собственный край. После обработки compositeImage помещает область OVER в прежние (24,88). Это выбор автора макета, не автоматическое распознавание текста. Программы и подробная версионная оговорка: spread и защищённая область.
Не превращаем обнаруженную перестановку аргументов в учебный регулятор: выбранное 5.0 — проверенная рабочая точка, где замысел radius 5 и фактические позиции совпадают. Для другой версии или другого значения сначала нужно проверить её обёртку и результат. Случайное смещение не является геометрически обратимым; интерполяция смешивает соседние значения.
Сохранить печатную иллюстрацию в цветном макете
Печатная фактура передаёт серый тон долей белых точек, а не множеством промежуточных цветов. У low=0.2Q и high=0.8Q тёмная часть становится чёрной, светлая белой; в середине вероятность белого c/Q. Границы включены в случайную ветвь. Это не требование получить ровно c/Q белых в каждом маленьком фрагменте.

Первая программа сохраняет полный нейтральный рисунок. Вторая выбирает более узкий случайный интервал 0.35Q..0.65Q и вставляет только печатную иллюстрацию в цветную карточку. Это одновременно другая задача и другие границы; не приписываем всю визуальную разность одному параметру. Не обещаем сохранения тонких линий или качество для OCR. Программы: случайный порог и печатная вставка.
Увидеть потери и проверить реальную случайную реализацию
| Ситуация | Проверка |
|---|---|
| Стало слишком шумно | Исходник сохранён отдельно. У текущего addNoiseImage нет scalar strength; первый пример уменьшает вклад готового слоя через явную композицию. |
| Прозрачный фон испорчен | Default может менять alpha. Для цветной фактуры явно RGB-маска; у spread возможна другая alpha из выбранной области. RGBA проверяют по каналу, не белому фону просмотрщика. |
| Вместо двух цветов цветные точки | Независимые RGB-решения не равны одному серому решению. В коде есть подготовка GRAY и извлечение RED. |
| Мелкий текст стал рваным | Это реальная потеря. Ограничьте обработку известной ROI или используйте другой стиль; случайный эффект не является очисткой/векторизацией. |
| Радиус0 не отключил spread | В этой версии есть описанная перестановка аргументов; даже обычный Core auto-radius не обязан быть identity. Не увеличивайте числа вслепую. |
| Повторный PNG отличается | Сохраните утверждённый файл и используйте его байты. Локальные одинаковые seed дали одинаковые результаты только в нашей малой проверке; переносимую byte identity не обещаем. |
Один bounded preflight проверил все доступные семь noise enums, RGB/alpha/default, spread 0/2/2.9/4/5/5.9, EDGE/TILE, Quantum-пороги/GRAY, endpoints и ошибки типов. В конкретном EDGE/TILE-контроле пиксели совпали; это не доказательство отсутствия влияния virtual pixels вообще. Непрозрачные главные сравнения и два отдельных RGBA-слоя не означают универсального сохранения alpha. Статистические свойства случайной реализации проверяем по сохранённым PNG, а не подгоняем выдуманный ожидаемый растр.
Исторический orderedPosterizeImage, deprecated с PECL 3.4.4 и доступный в этой обёртке только при IM < 7, остаётся отдельным будущим узлом полного руководства. AddNoiseImageWithAttenuate и spreadImageWithMethod также отдельные API. Здесь не исключаем их из общего объёма и не выдаём за optional-параметры трёх текущих методов. Проверены локальные PNG, не HTTP, печать, скорость, размер файла или безопасность обезличивания.
Выбрать эффект и сохранить удачный файл

Упражнение: получить ещё менее заметную фактуру первого каталога. Решение: заменить только множитель alpha 0.12 на 0.06, оставив Gaussian и RGB-маску. Это уменьшает вклад того же типа слоя, не восстанавливает детали и не задаёт attenuation. Изменённую программу нужно выполнить отдельно: сохранённые свидетельства относятся к восьми исходным определениям.
Дальше по задаче: подавление шума и границы, локальная статистика, палитра и таблица цветов, арифметика каналов. Художественные точки и чистый скан требуют разных критериев результата.
Функции и методы этой темы
Откройте карточку, чтобы увидеть договор функции, примеры, ограничения и связанные инструменты.
Imagick::addNoiseImageМеняет численные значения выбранных компонент по выбранному случайному распределению. Это добавление фактуры, а не удаление шума.
PECL imagick 2, PECL imagick 3 · imagick
Imagick::addNoiseImage(int $noise_type, int $channel = Imagick::CHANNEL_DEFAULT): boolСамая маленькая запись
В $image уже есть независимая копия исходника. $ начинает имя переменной, -> вызывает метод, аргументы разделены запятыми внутри скобок, ; завершает команду. Imagick::ИМЯ — константа класса, :: соединяет класс с её именем. Меняет численные значения выбранных компонент по выбранному случайному распределению. Это добавление фактуры, а не удаление шума.
Операция | объединяет маски RED, GREEN и BLUE; это не сложение чисел пикселей. В формулах ниже c — исходное значение одной компоненты, c′ — результат, Q=QuantumRange — внутренний максимум (65535 в нашей Q16-сборке), u — случайное число 0..1.
$rgbChannels = Imagick::CHANNEL_RED | Imagick::CHANNEL_GREEN | Imagick::CHANNEL_BLUE;
$image->addNoiseImage(Imagick::NOISE_GAUSSIAN, $rgbChannels);Здесь Gaussian выбирает распределение, RGB-маска — изменяемые компоненты. В IM7-переходнике этого метода attenuation фиксирован 1.0. Не передавайте вторым аргументом 0.2 как силу: это позиция int-маски каналов.
Все три целевых метода меняют текущий $image и возвращают bool true, не новый bitmap. Clone создаёт независимую копию; обычное присваивание объекта даёт ещё одно имя тому же объекту. If с ! проверяет отказ, throw new RuntimeException прерывает цепочку. Связи: объект и метод, клонирование, исключения.
Полная официальная сигнатура
Imagick::addNoiseImage(int $noise_type, int $channel = Imagick::CHANNEL_DEFAULT): bool| Аргумент | Смысл и единицы |
|---|---|
| $noise_type | Обязательная int-константа NOISE_*. В Reflection проверенной 3.8.1 параметр называется noise, в raw XML noise_type; примеры используют позиционные аргументы. |
| $channel | Необязательная int-маска CHANNEL_DEFAULT. Явная RED | GREEN | BLUE меняет RGB и сохраняет alpha в наших контролях. Default может изменить alpha и заполнить часть прозрачных мест. | объединяет маски, а не значения пикселей. |
Официальная доступность: PECL imagick 2, PECL imagick 3. Официальный результат: Returns true on success. Пустой объект и отказ библиотеки в проверенной обёртке приводят к ImagickException; неверный PHP-тип может вызвать TypeError. Возвращаемое true подтверждает выполнение вызова, но не качество изображения. Геометрия наших входов сохраняется; свойства alpha зависят от метода и маски.
| Шум | Что меняется при attenuation 1 |
|---|---|
| UNIFORM | Небольшая равномерная добавка: c′=c+Q×(u−0.5)/64, затем ограничение диапазона; u — случайное число 0..1. Это примерно ±2 уровня 8-битного файла. |
| GAUSSIAN | Другая, заметная гауссова модель, в том числе зависимая от исходного значения. Не обещаем одну универсальную добавку/дисперсию для всех типов. |
| MULTIPLICATIVEGAUSSIAN | Изменение связано с исходным значением компоненты; чёрный может вести себя иначе, чем у аддитивного зерна. |
| IMPULSE | При attenuation 1 около 5% решений дают 0, около 5% дают Q, остальные сохраняют вход; это вероятности, не гарантированная точная доля конечного кадра. |
| LAPLACIAN / POISSON | Другие распределения; выбирайте по задаче и проверяйте сохранённый результат. Название не является регулятором силы. |
| RANDOM | Заменяет компоненту Q×u; не просто добавляет мелкое зерно. Может полностью разрушить исходное изображение. |
Channel учитывается при IM > 6.2.8; для более ранней ветви wrapper вызывает метод без channel. Отдельный addNoiseImageWithAttenuate не является необязательным третьим параметром текущего API. Неизвестный noise enum в Core может попасть в Uniform, а не вызвать ошибку; внешние входы нужно проверять отдельно.
Наши числа фиксированы. Для внешних параметров отдельно ограничивайте разрешённые noise enums, конечные числа и размеры; для порогов разумна политика 0≤low≤high≤Q. Это политика приложения, не обещание такой проверки самим Imagick. Не используйте сильные разрушительные эффекты для скрытия секретов или гарантированного обезличивания.
Полный исходный официальный XML без сокращений
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<refentry xmlns="http://docbook.org/ns/docbook" xml:id="imagick.addnoiseimage">
<refnamediv>
<refname>Imagick::addNoiseImage</refname>
<refpurpose>Adds random noise to the image</refpurpose>
</refnamediv>
<refsect1 role="description">
&reftitle.description;
<methodsynopsis>
<modifier>public</modifier> <type>bool</type><methodname>Imagick::addNoiseImage</methodname>
<methodparam><type>int</type><parameter>noise_type</parameter></methodparam>
<methodparam choice="opt"><type>int</type><parameter>channel</parameter><initializer>Imagick::CHANNEL_DEFAULT</initializer></methodparam>
</methodsynopsis>
<para>
Adds random noise to the image.
</para>
</refsect1>
<refsect1 role="parameters">
&reftitle.parameters;
<para>
<variablelist>
<varlistentry>
<term><parameter>noise_type</parameter></term>
<listitem>
<para>
The type of the noise. Refer to this list of
<link linkend="imagick.constants.noise">noise constants</link>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><parameter>channel</parameter></term>
<listitem>
<para>
&imagick.parameter.channel;
</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::addNoiseImage</function></title>
<programlisting role="php">
<![CDATA[
<?php
function addNoiseImage($noiseType, $imagePath, $channel) {
$imagick = new \Imagick(realpath($imagePath));
$imagick->addNoiseImage($noiseType, $channel);
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
-->
<?php
declare(strict_types=1);
require __DIR__ . '/noise-fixture.php';
$source = loadNoiseSource();
$overlay = loadNoiseOverlay();
$Q = Imagick::getQuantumRange()['quantumRangeLong'];
$rgbChannels = Imagick::CHANNEL_RED | Imagick::CHANNEL_GREEN | Imagick::CHANNEL_BLUE;
$uniform = clone $source;
if (!$uniform->addNoiseImage(Imagick::NOISE_UNIFORM, $rgbChannels)) {
throw new RuntimeException('Не выполнен addNoiseImage');
}
$grain = clone $source;
if (!$grain->addNoiseImage(Imagick::NOISE_GAUSSIAN, $rgbChannels)) {
throw new RuntimeException('Не выполнен addNoiseImage');
}
saveNoiseComparison([$source, $uniform, $grain], 'noise-distributions.png');
$source->clear();
$uniform->clear();
$grain->clear();
$overlay->clear();
Результат: Исходник; Uniform RGB; Gaussian RGB. В этой обёртке attenuation равен 1.0. Uniform добавляет до примерно двух уровней файла, а Gaussian использует другое распределение; общий регулятор силы сюда не передаётся. Для запуска нужны example.php, noise-fixture.php, source.png.b64 и overlay.png.b64 в одной папке. Распакуйте архив целиком и выполните php example.php с расширением Imagick и правом записи. Помощник восстанавливает оба точных PNG по Base64/SHA256, не использует сеть или шрифты. Stdout — noise-distributions.png и перевод строки. Сравнение содержит полные панели 400×320 слева направо. При новом запуске случайный рисунок может отличаться; имя файла и смысловые свойства остаются договорённостью.
Ожидаемый вывод
noise-distributions.png
<?php
declare(strict_types=1);
require __DIR__ . '/noise-fixture.php';
$source = loadNoiseSource();
$overlay = loadNoiseOverlay();
$Q = Imagick::getQuantumRange()['quantumRangeLong'];
$rgbChannels = Imagick::CHANNEL_RED | Imagick::CHANNEL_GREEN | Imagick::CHANNEL_BLUE;
$grain = clone $overlay;
if (!$grain->addNoiseImage(Imagick::NOISE_GAUSSIAN, $rgbChannels)) {
throw new RuntimeException('Не выполнен addNoiseImage');
}
$grain->setImageFormat('png');
$grain->setImageDepth(8);
$grain->setOption('png:color-type', '6');
if (!$grain->writeImage(__DIR__ . '/overlay-grain.png')) {
throw new RuntimeException('Не записан overlay-grain.png');
}
$originalPreview = noisePreview($source, $overlay);
$grainPreview = noisePreview($source, $grain);
saveNoiseComparison([$source, $originalPreview, $grainPreview], 'noise-overlay.png');
$source->clear();
$originalPreview->clear();
$grainPreview->clear();
$overlay->clear();
$grain->clear();
Результат: Каталог; исходная RGBA-отметка поверх него; отметка с Gaussian RGB поверх того же каталога. RGB-маска оставляет исходную alpha. overlay-grain.png сохраняет самостоятельный слой и прозрачное отверстие. Для запуска нужны example.php, noise-fixture.php, source.png.b64 и overlay.png.b64 в одной папке. Распакуйте архив целиком и выполните php example.php с расширением Imagick и правом записи. Помощник восстанавливает оба точных PNG по Base64/SHA256, не использует сеть или шрифты. Stdout — noise-overlay.png и перевод строки. Сравнение содержит полные панели 400×320 слева направо. При новом запуске случайный рисунок может отличаться; имя файла и смысловые свойства остаются договорённостью.
Ожидаемый вывод
noise-overlay.png
Imagick::spreadImageДля выходного пикселя случайно выбирает ближайшую область исходника и вычисляет значение в выбранной точке. Это не перестановка, сохраняющая каждую исходную точку ровно один раз.
PECL imagick 2, PECL imagick 3 · imagick
Imagick::spreadImage(float $radius): boolСамая маленькая запись
В $image уже есть независимая копия исходника. $ начинает имя переменной, -> вызывает метод, аргументы разделены запятыми внутри скобок, ; завершает команду. Imagick::ИМЯ — константа класса, :: соединяет класс с её именем. Для выходного пикселя случайно выбирает ближайшую область исходника и вычисляет значение в выбранной точке. Это не перестановка, сохраняющая каждую исходную точку ровно один раз.
Число 5.0 — конкретная проверенная настройка этой сборки, а не обещание, что любой radius передаётся правильно. EDGE продолжает ближайший край изображения при выборке за ним; это не увеличивает холст. В модели ниже x/y — координаты выходного пикселя слева сверху, u/v — два случайных числа 0..1, W — ширина области выбора источника в пикселях.
$image->setImageVirtualPixelMethod(Imagick::VIRTUALPIXELMETHOD_EDGE);
$image->spreadImage(5.0);Все три целевых метода меняют текущий $image и возвращают bool true, не новый bitmap. Clone создаёт независимую копию; обычное присваивание объекта даёт ещё одно имя тому же объекту. If с ! проверяет отказ, throw new RuntimeException прерывает цепочку. Связи: объект и метод, клонирование, исключения.
Полная официальная сигнатура
Imagick::spreadImage(float $radius): bool| Аргумент | Смысл и единицы |
|---|---|
| $radius | Обязательный float, по официальному замыслу радиус области в пикселях. В проверенной 3.8.1 с IM7 есть перестановка аргументов между PHP и библиотекой: не считать произвольное изменение этого числа корректной шкалой силы. Ниже разобрана рабочая точка 5.0 и точная граница версии. |
Официальная доступность: PECL imagick 2, PECL imagick 3. Официальный результат: Returns true on success. Пустой объект и отказ библиотеки в проверенной обёртке приводят к ImagickException; неверный PHP-тип может вызвать TypeError. Возвращаемое true подтверждает выполнение вызова, но не качество изображения. Геометрия наших входов сохраняется; свойства alpha зависят от метода и маски.
Версионная оговорка: exact Imagick 3.8.1 вызывает MagickSpreadImage(wand, radius, Bilinear), а точная IM 7.1.1-46 объявляет (wand, method, radius). Поэтому по исходникам PHP-число становится enum метода интерполяции, а native radius получает Bilinear=5. При 5.0 обе позиции совпадают с осмысленным Bilinear/radius 5: ширина окна W=11, координата источника x+11×(u−0.5), y+11×(v−0.5). Интерполяция вычисляет значение между соседними пикселями. Это обратная выборка для каждого выхода, не гарантированная перестановка входов.
Предварительная проверка согласована с этой перестановкой: 2.0 и 2.9 дали одинаковые пиксели при одинаковом локальном seed; 0, 4, 5 и 5.9 также совпали в этой контрольной сцене и не были identity. У значения 4 в канальной реализации нет отдельной Background-ветви, оно попадает в общий Bilinear-путь. Это не доказательство одинакового поведения на всех входах. Ноль не следует использовать для отключения. SpreadImageWithMethod — отдельный API, не второй необязательный аргумент; и его порядок в этой обёртке также требует проверки. Здесь показываем одну работающую точку и ограничение, не исправляем расширение скрытно.
Наши числа фиксированы. Для внешних параметров отдельно ограничивайте разрешённые noise enums, конечные числа и размеры; для порогов разумна политика 0≤low≤high≤Q. Это политика приложения, не обещание такой проверки самим Imagick. Не используйте сильные разрушительные эффекты для скрытия секретов или гарантированного обезличивания.
Полный исходный официальный XML без сокращений
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<refentry xmlns="http://docbook.org/ns/docbook" xml:id="imagick.spreadimage">
<refnamediv>
<refname>Imagick::spreadImage</refname>
<refpurpose>Randomly displaces each pixel in a block</refpurpose>
</refnamediv>
<refsect1 role="description">
&reftitle.description;
<methodsynopsis>
<modifier>public</modifier> <type>bool</type><methodname>Imagick::spreadImage</methodname>
<methodparam><type>float</type><parameter>radius</parameter></methodparam>
</methodsynopsis>
<para>
Special effects method that randomly displaces each pixel in a block
defined by the radius parameter.
</para>
</refsect1>
<refsect1 role="parameters">
&reftitle.parameters;
<para>
<variablelist>
<varlistentry>
<term><parameter>radius</parameter></term>
<listitem>
<para>
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</refsect1>
<refsect1 role="returnvalues">
&reftitle.returnvalues;
<para>
&imagick.return.success;
</para>
</refsect1>
<refsect1 role="errors">
&reftitle.errors;
<para>
&imagick.imagick.throws;
</para>
</refsect1>
<refsect1 role="examples">
&reftitle.examples;
<para>
<example>
<title> <function>Imagick::spreadImage</function></title>
<programlisting role="php">
<![CDATA[
<?php
function spreadImage($imagePath, $radius) {
$imagick = new \Imagick(realpath($imagePath));
$imagick->spreadImage($radius);
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
-->
<?php
declare(strict_types=1);
require __DIR__ . '/noise-fixture.php';
$source = loadNoiseSource();
$overlay = loadNoiseOverlay();
$Q = Imagick::getQuantumRange()['quantumRangeLong'];
$rgbChannels = Imagick::CHANNEL_RED | Imagick::CHANNEL_GREEN | Imagick::CHANNEL_BLUE;
$spread = clone $source;
$spread->setImageVirtualPixelMethod(Imagick::VIRTUALPIXELMETHOD_EDGE);
if (!$spread->spreadImage(5.0)) {
throw new RuntimeException('Не выполнен spreadImage');
}
saveNoiseComparison([$source, $spread], 'spread-global.png');
$source->clear();
$spread->clear();
$overlay->clear();
Результат: Весь каталог до и после проверенного spreadImage(5.0). У мелкого текста и границ теряется чёткость. Для данной связки 3.8.1/IM7 это выбранная рабочая точка, а не демонстрация исправного произвольного регулятора radius. Для запуска нужны example.php, noise-fixture.php, source.png.b64 и overlay.png.b64 в одной папке. Распакуйте архив целиком и выполните php example.php с расширением Imagick и правом записи. Помощник восстанавливает оба точных PNG по Base64/SHA256, не использует сеть или шрифты. Stdout — spread-global.png и перевод строки. Сравнение содержит полные панели 400×320 слева направо. При новом запуске случайный рисунок может отличаться; имя файла и смысловые свойства остаются договорённостью.
Ожидаемый вывод
spread-global.png
<?php
declare(strict_types=1);
require __DIR__ . '/noise-fixture.php';
$source = loadNoiseSource();
$overlay = loadNoiseOverlay();
$Q = Imagick::getQuantumRange()['quantumRangeLong'];
$rgbChannels = Imagick::CHANNEL_RED | Imagick::CHANNEL_GREEN | Imagick::CHANNEL_BLUE;
$image = clone $source;
$region = clone $source;
$region->cropImage(352, 132, 24, 88);
$region->setImagePage(0, 0, 0, 0);
$region->setImageVirtualPixelMethod(Imagick::VIRTUALPIXELMETHOD_EDGE);
if (!$region->spreadImage(5.0)) {
throw new RuntimeException('Не выполнен spreadImage');
}
if (!$image->compositeImage($region, Imagick::COMPOSITE_OVER, 24, 88)) {
throw new RuntimeException('Не выполнен compositeImage');
}
saveNoiseComparison([$source, $image], 'spread-protected.png');
$source->clear();
$image->clear();
$overlay->clear();
$region->clear();
Результат: Рассыпчатая фактура только в иллюстрации 352×132 с началом (24,88). За её пределами, включая SKU, сохранены исходные пиксели. EDGE относится к собственной границе вырезки. Для запуска нужны example.php, noise-fixture.php, source.png.b64 и overlay.png.b64 в одной папке. Распакуйте архив целиком и выполните php example.php с расширением Imagick и правом записи. Помощник восстанавливает оба точных PNG по Base64/SHA256, не использует сеть или шрифты. Stdout — spread-protected.png и перевод строки. Сравнение содержит полные панели 400×320 слева направо. При новом запуске случайный рисунок может отличаться; имя файла и смысловые свойства остаются договорённостью.
Ожидаемый вывод
spread-protected.png
Imagick::randomThresholdImageВыбирает 0 или Q для каждой изменяемой компоненты. Ниже low получается 0, выше high — Q, между ними сравнивает с отдельным случайным порогом по всему диапазону 0..Q.
PECL imagick 2, PECL imagick 3 · imagick
Imagick::randomThresholdImage(float $low, float $high, int $channel = Imagick::CHANNEL_DEFAULT): boolСамая маленькая запись
В $image уже есть независимая копия исходника. $ начинает имя переменной, -> вызывает метод, аргументы разделены запятыми внутри скобок, ; завершает команду. Imagick::ИМЯ — константа класса, :: соединяет класс с её именем. Выбирает 0 или Q для каждой изменяемой компоненты. Ниже low получается 0, выше high — Q, между ними сравнивает с отдельным случайным порогом по всему диапазону 0..Q.
Q=QuantumRange — внутренний максимум. Imagick::getQuantumRange() — статический метод класса, ключ quantumRangeLong читает число из возвращённого массива. В Q16 Q=65535, поэтому 0.2Q=13107, 0.8Q=52428. Умножение * выполняет наш PHP-код, обёртка получает уже готовые числа. GRAY сначала переводит цвет в численную яркость; separateImageChannel затем делает выбранный RED самостоятельным серым изображением.
$Q = Imagick::getQuantumRange()['quantumRangeLong'];
$image->transformImageColorspace(Imagick::COLORSPACE_GRAY);
$image->randomThresholdImage(0.2 * $Q, 0.8 * $Q, Imagick::CHANNEL_RED);
$image->separateImageChannel(Imagick::CHANNEL_RED);Все три целевых метода меняют текущий $image и возвращают bool true, не новый bitmap. Clone создаёт независимую копию; обычное присваивание объекта даёт ещё одно имя тому же объекту. If с ! проверяет отказ, throw new RuntimeException прерывает цепочку. Связи: объект и метод, клонирование, исключения.
Полная официальная сигнатура
Imagick::randomThresholdImage(float $low, float $high, int $channel = Imagick::CHANNEL_DEFAULT): bool| Аргумент | Смысл и единицы |
|---|---|
| $low | Обязательный float, нижняя граница в Quantum-единицах, без пересчёта обёрткой. Для 20% передаём 0.2 * Q, а не 20 и не процент числа пикселей. |
| $high | Обязательный float, верхняя граница в той же шкале. Ровно на границах действует случайная ветвь. В ней случайный порог лежит в 0..Q, не в low..high; вероятность белого для компоненты c составляет c/Q. |
| $channel | Необязательная int-маска CHANNEL_DEFAULT. Разные RGB-компоненты могут получить разные случайные решения; цветной вход не обязан дать лишь два общих цвета. Явная подготовка серого и извлечение одной компоненты дают наш нейтральный двухцветный результат. |
Официальная доступность: PECL imagick 2, PECL imagick 3. Официальный результат: Returns true on success. Пустой объект и отказ библиотеки в проверенной обёртке приводят к ImagickException; неверный PHP-тип может вызвать TypeError. Возвращаемое true подтверждает выполнение вызова, но не качество изображения. Геометрия наших входов сохраняется; свойства alpha зависят от метода и маски.
Raw-фраза «two color» точна для нашего подготовленного нейтрального результата. Три независимых RGB-решения дают до восьми сочетаний 0/Q, alpha по default также может меняться. При настоящем одноканальном GRAY наша проверка дала два нейтральных цвета; основной код дополнительно явно извлекает RED. У значения c между границами сохраняется только вероятностная передача тона, не первоначальный оттенок. Требуется IM 6.2.9 или новее. Пример raw сам умножает нормированные доли на Quantum; PHP-wrapper ничего не масштабирует.
Наши числа фиксированы. Для внешних параметров отдельно ограничивайте разрешённые noise enums, конечные числа и размеры; для порогов разумна политика 0≤low≤high≤Q. Это политика приложения, не обещание такой проверки самим Imagick. Не используйте сильные разрушительные эффекты для скрытия секретов или гарантированного обезличивания.
Полный исходный официальный XML без сокращений
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<refentry xmlns="http://docbook.org/ns/docbook" xml:id="imagick.randomthresholdimage">
<refnamediv>
<refname>Imagick::randomThresholdImage</refname>
<refpurpose>Creates a high-contrast, two-color image</refpurpose>
</refnamediv>
<refsect1 role="description">
&reftitle.description;
<methodsynopsis>
<modifier>public</modifier> <type>bool</type><methodname>Imagick::randomThresholdImage</methodname>
<methodparam><type>float</type><parameter>low</parameter></methodparam>
<methodparam><type>float</type><parameter>high</parameter></methodparam>
<methodparam choice="opt"><type>int</type><parameter>channel</parameter><initializer>Imagick::CHANNEL_DEFAULT</initializer></methodparam>
</methodsynopsis>
<para>
Changes the value of individual pixels based on the
intensity of each pixel compared to threshold. The
result is a high-contrast, two color image. &imagick.method.available.0x629;
</para>
</refsect1>
<refsect1 role="parameters">
&reftitle.parameters;
<para>
<variablelist>
<varlistentry>
<term><parameter>low</parameter></term>
<listitem>
<para>
The low point
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><parameter>high</parameter></term>
<listitem>
<para>
The high point
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><parameter>channel</parameter></term>
<listitem>
<para>
Provide any channel constant that is valid for your channel mode. To
apply to more than one channel, combine channeltype constants using
bitwise operators. Refer to this
list of <link linkend="imagick.constants.channel">channel constants</link>.
</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::randomThresholdImage</function></title>
<programlisting role="php">
<![CDATA[
<?php
function randomThresholdimage($imagePath, $lowThreshold, $highThreshold, $channel) {
$imagick = new \Imagick(realpath($imagePath));
$imagick->randomThresholdimage(
$lowThreshold * \Imagick::getQuantum(),
$highThreshold * \Imagick::getQuantum(),
$channel
);
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
-->
<?php
declare(strict_types=1);
require __DIR__ . '/noise-fixture.php';
$source = loadNoiseSource();
$overlay = loadNoiseOverlay();
$Q = Imagick::getQuantumRange()['quantumRangeLong'];
$rgbChannels = Imagick::CHANNEL_RED | Imagick::CHANNEL_GREEN | Imagick::CHANNEL_BLUE;
$print = clone $source;
$print->transformImageColorspace(Imagick::COLORSPACE_GRAY);
if (!$print->randomThresholdImage(0.2 * $Q, 0.8 * $Q, Imagick::CHANNEL_RED)) {
throw new RuntimeException('Не выполнен randomThresholdImage');
}
if (!$print->separateImageChannel(Imagick::CHANNEL_RED)) {
throw new RuntimeException('Не выполнен separateImageChannel');
}
saveNoiseComparison([$source, $print], 'random-print.png');
$source->clear();
$print->clear();
$overlay->clear();
Результат: Полный исходник и двухцветная версия. Сначала GRAY, затем случайный порог 0.2Q..0.8Q в RED и явное извлечение RED в серое изображение. Результат имеет два цвета, но хранится RGB с 8 битами на компоненту, не автоматически как 1-bit PNG. Для запуска нужны example.php, noise-fixture.php, source.png.b64 и overlay.png.b64 в одной папке. Распакуйте архив целиком и выполните php example.php с расширением Imagick и правом записи. Помощник восстанавливает оба точных PNG по Base64/SHA256, не использует сеть или шрифты. Stdout — random-print.png и перевод строки. Сравнение содержит полные панели 400×320 слева направо. При новом запуске случайный рисунок может отличаться; имя файла и смысловые свойства остаются договорённостью.
Ожидаемый вывод
random-print.png
<?php
declare(strict_types=1);
require __DIR__ . '/noise-fixture.php';
$source = loadNoiseSource();
$overlay = loadNoiseOverlay();
$Q = Imagick::getQuantumRange()['quantumRangeLong'];
$rgbChannels = Imagick::CHANNEL_RED | Imagick::CHANNEL_GREEN | Imagick::CHANNEL_BLUE;
$image = clone $source;
$region = clone $source;
$region->cropImage(352, 132, 24, 88);
$region->setImagePage(0, 0, 0, 0);
$region->transformImageColorspace(Imagick::COLORSPACE_GRAY);
if (!$region->randomThresholdImage(0.35 * $Q, 0.65 * $Q, Imagick::CHANNEL_RED)) {
throw new RuntimeException('Не выполнен randomThresholdImage');
}
if (!$region->separateImageChannel(Imagick::CHANNEL_RED)) {
throw new RuntimeException('Не выполнен separateImageChannel');
}
$region->setImageFormat('png');
$region->setImageDepth(8);
$region->setOption('png:color-type', '2');
if (!$region->writeImage(__DIR__ . '/print-region.png')) {
throw new RuntimeException('Не записан print-region.png');
}
if (!$image->compositeImage($region, Imagick::COMPOSITE_OVER, 24, 88)) {
throw new RuntimeException('Не выполнен compositeImage');
}
saveNoiseComparison([$source, $image], 'random-protected.png');
$source->clear();
$image->clear();
$overlay->clear();
$region->clear();
Результат: Печатная область с порогами 0.35Q..0.65Q возвращена в цветной макет; остальные пиксели и SKU точны. print-region.png хранит собственную область 352×132 без уменьшения. Для запуска нужны example.php, noise-fixture.php, source.png.b64 и overlay.png.b64 в одной папке. Распакуйте архив целиком и выполните php example.php с расширением Imagick и правом записи. Помощник восстанавливает оба точных PNG по Base64/SHA256, не использует сеть или шрифты. Stdout — random-protected.png и перевод строки. Сравнение содержит полные панели 400×320 слева направо. При новом запуске случайный рисунок может отличаться; имя файла и смысловые свойства остаются договорённостью.
Ожидаемый вывод
random-protected.png
Код и руководство с собой
Скачайте самостоятельные примеры с исходными данными, инструкциями и ожидаемыми результатами. Примеры HTTP и фрагменты для проекта помечены отдельно: им нужно указанное окружение.
Код не исполняется на сайте. Скачайте нужный пример и запускайте его в своём локальном окружении.
Материалы сверены 2026-10-12. Примеры и объяснения написаны для этого руководства; источники и обсуждения доступны в каждой главе.


