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

Дерево руководства
Глава 375 · После переменных, объектов, файлов и RGB
Imagick: gamma-свойство, PNG gAMA и проверка настоящего экспорта
Понятная разница между меткой и коррекцией пикселей; известные входы, настоящий getter, setter и обнаружение потерянного gAMA.
Увидеть метку и настоящую коррекцию как разные действия
После обработки PNG цветовая метка может пропасть, хотя изображение выглядит знакомо и запись файла прошла успешно. Нужно различить две задачи: прочитать/изменить описание gamma и действительно изменить RGB-компоненты. Первый результат показывает эту разницу на собственной иллюстрации: setter оставляет рисунок прежним, отдельный gammaImage меняет пиксели.

Пиксель хранит компоненты цвета; метаданные описывают, как эти компоненты следует понимать. Gamma в свойстве Imagick — число, а не измеренная яркость фотографии. В PNG отдельный chunk gAMA может хранить это описание. $image — переменная с объектом, -> вызывает метод, () содержит аргументы, ; завершает инструкцию. У getter скобки пустые; setter получает float0.7 с точкой. Переменные, объекты и цветовое пространство — связанные темы.
Здесь0.7 — новая метка,1.8 — коэффициент другого метода. Их нельзя сравнивать как одинаковые настройки. gammaImage применяет степенное преобразование значений с показателем1/коэффициент и в этой реализации также меняет существующее gamma-свойство. Маска RED|GREEN|BLUE ограничивает контекстный вызов цветными каналами; | объединяет флаги. Мы работаем на явном непрозрачном OVERwhite-входе. Это не утверждение о сохранении alpha при любом default-вызове gammaImage.
Увидеть разницу между меткой и изменёнными пикселями
Три настоящих просмотра показывают исходник, неизменённые пиксели после setter и отдельно изменённые RGB после gammaImage. Метка не является фильтром осветления.
<?php
declare(strict_types=1);
require __DIR__.'/gamma-fixture.php';
gammaRestore();
$source=new Imagick(__DIR__.'/source.png');$working=gammaOpaque($source);
$before=gammaPixels($working);$beforeGamma=$working->getImageGamma();
$tagged=clone $working;$setOK=$tagged->setImageGamma(0.7);$liveGamma=$tagged->getImageGamma();
$corrected=clone $working;$rgb=Imagick::CHANNEL_RED|Imagick::CHANNEL_GREEN|Imagick::CHANNEL_BLUE;
$correctOK=$corrected->gammaImage(1.8,$rgb);$correctedGamma=$corrected->getImageGamma();
gammaView($working,'source-preview8.png');gammaView($tagged,'metadata-preview.png');gammaView($corrected,'corrected-preview.png');
$rects=gammaCompare([new Imagick(__DIR__.'/source-preview8.png'),new Imagick(__DIR__.'/metadata-preview.png'),new Imagick(__DIR__.'/corrected-preview.png')],'gamma-first.png');
$same=$before['RGBA8_hash']===gammaPixelHash($tagged);$changed=$before['RGBA8_hash']!==gammaPixelHash($corrected);
gammaDiagnostic('gamma-metadata-first',['before_gamma'=>$beforeGamma,'live_gamma'=>$liveGamma,'corrected_gamma'=>$correctedGamma,'correction_factor'=>1.8,'before_pixels'=>$before,'tagged_pixels'=>gammaPixels($tagged),'corrected_pixels'=>gammaPixels($corrected),'panel_geometry'=>$rects,'checks'=>['setter_true'=>$setOK===true,'correction_true'=>$correctOK===true,'setter_keeps_pixels'=>$same,'correction_changes_pixels'=>$changed]]);
echo "gamma-first.png\nsource-preview8.png\nmetadata-preview.png\ncorrected-preview.png\nmetrics.json\nmetadata-keeps-pixels=1 correction-changes-pixels=1\n";
Три настоящих просмотра показывают исходник, неизменённые пиксели после setter и отдельно изменённые RGB после gammaImage. Метка не является фильтром осветления. Сохраните example.php и четыре дополнительных текстовых файла из архива в одной папке; запустите php example.php с Imagick и PNG, имея право записи. Helper восстанавливает три собственных входа по SHA, сохраняет нейтральные RGB8-превью, разбирает PNG chunks/CRC и пишет metrics.json. Изучаемые getter/setter и отдельный gammaImage вызываются явно в программе. Подготовленные входные метки не сертифицируют правильность цветового кодирования изображения.
Ожидаемый вывод
gamma-first.png
source-preview8.png
metadata-preview.png
corrected-preview.png
metrics.json
metadata-keeps-pixels=1 correction-changes-pixels=1
Понять, откуда берётся число и где хранится метка

Представьте этикетку на коробке: её замена не перекрашивает содержимое. Аналогия относится только к отделению данных от описания. Для корректного цвета этикетка должна соответствовать данным, а не выбираться на глаз. Подготовленные здесь входы с метками45455/70000 имеют одинаковые IDAT-компоненты и служат контролями чтения, а не образцами правильной gamma-кодировки.
| Что проверяем | Надёжное наблюдение | Чего оно не доказывает |
|---|---|---|
| Native свойство | getImageGamma текущего объекта | Наличие gAMA в файле |
| Растр | Компоненты/контрольная сумма названного RGBA8-представления | Цветовую правильность ICC/монитора |
| PNG gAMA | Chunk присутствует, CRC верен, uint32 прочитан | Одинаковое отображение всеми клиентами |
| Результат экспорта | Повторное чтение реального файла и его chunks | Что true у setter заранее удостоверил запись метки |
По PNG3 gAMA хранит gamma×100000 в четырёх байтах:45455 соответствует примерно1/2.2,70000 —0.7. Это не указание displaygamma2.2 и не полная кусочная функция sRGB. Декодер учитывает приоритет понимаемых им цветовых chunks; поддерживаемые cICP/iCCP/sRGB имеют приоритет над gAMA. Gamma-декодирование цвета не является gamma-коррекцией alpha. Нейтральные превью данной главы созданы из фактических компонентов одним способом и исключают цветовые chunks: они не эмулируют обработку gAMA браузером.
Прочитать известную метку и обнаружить её потерю

Пиксель хранит компоненты цвета; метаданные описывают, как эти компоненты следует понимать. Gamma в свойстве Imagick — число, а не измеренная яркость фотографии. В PNG отдельный chunk gAMA может хранить это описание. $image — переменная с объектом, -> вызывает метод, () содержит аргументы, ; завершает инструкцию. У getter скобки пустые; setter получает float0.7 с точкой. Переменные, объекты и цветовое пространство — связанные темы.
Минимальная запись и полный базовый контракт
Imagick::getImageGamma(): float$gamma = $image->getImageGamma();Параметров нет. Возвращается float gamma текущего изображения; официально при ошибке ImagickException. В текущем PHP binding пустой объект проверяется до Wand-вызова. Возвращаемое число не измеряет среднюю яркость и само по себе не доказывает наличие gAMA в исходном файле. Значение0 тоже не является универсальным признаком исключения: смотрите источник/формат и состояние объекта.
Официальная доступность: PECL imagick 2, PECL imagick 3. В PHP/Imagick источник различает методы: getImageGamma():float и setImageGamma(float $gamma):bool. В обеих исходных официальных записях нет собственного примера кода; здесь добавлены минимальное применение и реальный сценарий. Полный исходник сохранён без сокращений:
Полный официальный XML
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<refentry xmlns="http://docbook.org/ns/docbook" xml:id="imagick.getimagegamma">
<refnamediv>
<refname>Imagick::getImageGamma</refname>
<refpurpose>Gets the image gamma</refpurpose>
</refnamediv>
<refsect1 role="description">
&reftitle.description;
<methodsynopsis>
<modifier>public</modifier> <type>float</type><methodname>Imagick::getImageGamma</methodname>
<void/>
</methodsynopsis>
<para>
Gets the image gamma.
</para>
</refsect1>
<refsect1 role="parameters">
&reftitle.parameters;
&no.function.parameters;
</refsect1>
<refsect1 role="returnvalues">
&reftitle.returnvalues;
<para>
Returns the image gamma on success.
</para>
</refsect1>
<refsect1 role="errors">
&reftitle.errors;
<para>
&imagick.imagick.throws;
</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
-->
Прочитать gamma заранее подготовленного PNG
Getter возвращает float0.7 из собственного входа с известным gAMA70000. Этот PNG подготовлен как тестовый вход; он не выдан за результат Imagick setter.
<?php
declare(strict_types=1);
require __DIR__.'/gamma-fixture.php';
gammaRestore();
$image=new Imagick(__DIR__.'/gamma-070000.png');
$gamma=$image->getImageGamma();
gammaView($image,'gamma-get-minimal.png');
gammaDiagnostic('gamma-metadata-getimagegamma-minimal',['input'=>'gamma-070000.png','value'=>$gamma,'value_type'=>get_debug_type($gamma),'png'=>gammaPNG('gamma-070000.png'),'checks'=>['known_input_gamma'=>abs($gamma-0.7)<1e-12,'return_float'=>is_float($gamma)]]);
printf("gamma=%.5f type=%s\n",$gamma,get_debug_type($gamma));
echo "gamma-get-minimal.png\nmetrics.json\n";
Getter возвращает float0.7 из собственного входа с известным gAMA70000. Этот PNG подготовлен как тестовый вход; он не выдан за результат Imagick setter. Сохраните example.php и четыре дополнительных текстовых файла из архива в одной папке; запустите php example.php с Imagick и PNG, имея право записи. Helper восстанавливает три собственных входа по SHA, сохраняет нейтральные RGB8-превью, разбирает PNG chunks/CRC и пишет metrics.json. Изучаемые getter/setter и отдельный gammaImage вызываются явно в программе. Подготовленные входные метки не сертифицируют правильность цветового кодирования изображения.
Ожидаемый вывод
gamma=0.70000 type=float
gamma-get-minimal.png
metrics.json
Практическая ошибка — использовать getter как датчик яркости или считать число около0.45455 доказательством gAMA. В этой сборке файл без метки даёт значение по умолчанию около0.45454545; подготовленный chunk45455 читается как0.45455. Близость чисел не заменяет проверку присутствия chunk. Следующий сценарий читает все три входа, затем реально экспортирует помеченный файл и обнаруживает потерю метки. Никакие байты выхода Imagick после записи не исправляются.
Найти отсутствующую метку и потерю при экспорте
Одинаковые пиксели не означают одинаковые метки. Сравниваются три известных входа и реальный повторный экспорт: getter без метки может вернуть значение по умолчанию, поэтому наличие gAMA проверяется отдельно.
<?php
declare(strict_types=1);
require __DIR__.'/gamma-fixture.php';
gammaRestore();
$rows=[];$panels=[];
foreach(['source.png','gamma-045455.png','gamma-070000.png'] as $i=>$filename){$image=new Imagick(__DIR__.'/'.$filename);$value=$image->getImageGamma();$view='input-'.$i.'-preview.png';gammaView($image,$view);$panels[]=new Imagick(__DIR__.'/'.$view);$rows[]=['input'=>$filename,'getter'=>$value,'getter_type'=>get_debug_type($value),'pixels'=>gammaPixels($image),'png'=>gammaPNG($filename)];}
$copy=new Imagick(__DIR__.'/gamma-070000.png');$copy->setImageFormat('png');$copy->setImageDepth(8);$copy->setOption('png:color-type','6');$copy->writeImage(__DIR__.'/roundtrip.png');
$reread=new Imagick(__DIR__.'/roundtrip.png');$roundtripGamma=$reread->getImageGamma();$roundtripHeader=gammaPNG('roundtrip.png');
gammaView($reread,'roundtrip-preview.png');$panels[]=new Imagick(__DIR__.'/roundtrip-preview.png');$rects=gammaCompare($panels,'gamma-read-workflow.png');
$lost=$rows[2]['png']['gAMA_present']&&!$roundtripHeader['gAMA_present'];
gammaDiagnostic('gamma-metadata-getimagegamma-workflow',['inputs'=>$rows,'roundtrip'=>['getter'=>$roundtripGamma,'png'=>$roundtripHeader,'pixels'=>gammaPixels($reread)],'lost_label'=>$lost,'panel_geometry'=>$rects,'checks'=>['known_inputs_differ_only_by_label'=>count(array_unique(array_column(array_column($rows,'pixels'),'RGBA8_hash')))===1,'known_labels_explicit'=>$rows[0]['png']['gAMA_integer']===null&&$rows[1]['png']['gAMA_integer']===45455&&$rows[2]['png']['gAMA_integer']===70000]]);
echo "gamma-read-workflow.png\ninput-0-preview.png\ninput-1-preview.png\ninput-2-preview.png\nroundtrip.png\nroundtrip-preview.png\nmetrics.json\n";
printf("inputs=%d lost-label-detected=%d\n",count($rows),(int)$lost);
Одинаковые пиксели не означают одинаковые метки. Сравниваются три известных входа и реальный повторный экспорт: getter без метки может вернуть значение по умолчанию, поэтому наличие gAMA проверяется отдельно. Сохраните example.php и четыре дополнительных текстовых файла из архива в одной папке; запустите php example.php с Imagick и PNG, имея право записи. Helper восстанавливает три собственных входа по SHA, сохраняет нейтральные RGB8-превью, разбирает PNG chunks/CRC и пишет metrics.json. Изучаемые getter/setter и отдельный gammaImage вызываются явно в программе. Подготовленные входные метки не сертифицируют правильность цветового кодирования изображения.
Ожидаемый вывод
gamma-read-workflow.png
input-0-preview.png
input-1-preview.png
input-2-preview.png
roundtrip.png
roundtrip-preview.png
metrics.json
inputs=3 lost-label-detected=1
Задать native свойство и не пропустить неправильный экспорт

Пиксель хранит компоненты цвета; метаданные описывают, как эти компоненты следует понимать. Gamma в свойстве Imagick — число, а не измеренная яркость фотографии. В PNG отдельный chunk gAMA может хранить это описание. $image — переменная с объектом, -> вызывает метод, () содержит аргументы, ; завершает инструкцию. У getter скобки пустые; setter получает float0.7 с точкой. Переменные, объекты и цветовое пространство — связанные темы.
Минимальная запись и полный базовый контракт
Imagick::setImageGamma(float $gamma): bool$ok = $image->setImageGamma(0.7);| Параметр/результат | Смысл |
|---|---|
| $gamma: float, обязательный | Новое значение свойства gamma текущего изображения. Это не аргумент gammaImage и не экспозиция. |
| booltrue | Статус успешной записи свойства в объект. Он не удостоверяет конкретный chunk будущего файла. |
| ImagickException | Официальный отказ метода; пустой объект проверяется PHP binding. |
В исходном XML описание параметра пусто. Exact Wand просто присваивает image->gamma=gamma, не меняет пиксели и не проверяет положительность/конечность. Поэтому конечное положительное число для запланированного PNG — явная политика приложения, а не придуманная гарантия валидации setter. Неверный PHP-тип может дать TypeError. ICC-профиль setter не преобразует.
Официальная доступность: PECL imagick 2, PECL imagick 3. В PHP/Imagick источник различает методы: getImageGamma():float и setImageGamma(float $gamma):bool. В обеих исходных официальных записях нет собственного примера кода; здесь добавлены минимальное применение и реальный сценарий. Полный исходник сохранён без сокращений:
Полный официальный XML
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<refentry xmlns="http://docbook.org/ns/docbook" xml:id="imagick.setimagegamma">
<refnamediv>
<refname>Imagick::setImageGamma</refname>
<refpurpose>Sets the image gamma</refpurpose>
</refnamediv>
<refsect1 role="description">
&reftitle.description;
<methodsynopsis>
<modifier>public</modifier> <type>bool</type><methodname>Imagick::setImageGamma</methodname>
<methodparam><type>float</type><parameter>gamma</parameter></methodparam>
</methodsynopsis>
<para>
Sets the image gamma.
</para>
</refsect1>
<refsect1 role="parameters">
&reftitle.parameters;
<para>
<variablelist>
<varlistentry>
<term><parameter>gamma</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>
</refentry>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->
Задать свойство объекта без изменения рисунка
Setter вернул true, текущий getter прочитал0.7, RGBA-компоненты не изменились. Показанный PNG — нейтральное превью этих пикселей; сохранение gAMA проверяется отдельным сценарием.
<?php
declare(strict_types=1);
require __DIR__.'/gamma-fixture.php';
gammaRestore();
$image=new Imagick(__DIR__.'/source.png');$before=gammaPixelHash($image);
$ok=$image->setImageGamma(0.7);
$value=$image->getImageGamma();$same=$before===gammaPixelHash($image);
gammaView($image,'gamma-set-minimal.png');
gammaDiagnostic('gamma-metadata-setimagegamma-minimal',['value'=>$value,'return_value'=>$ok,'return_type'=>get_debug_type($ok),'before_hash'=>$before,'after_hash'=>gammaPixelHash($image),'checks'=>['setter_true'=>$ok===true,'requested_live_value'=>abs($value-0.7)<1e-12,'pixels_unchanged'=>$same]]);
printf("set=%s gamma=%.5f pixels_unchanged=%d\n",$ok?'true':'false',$value,(int)$same);
echo "gamma-set-minimal.png\nmetrics.json\n";
Setter вернул true, текущий getter прочитал0.7, RGBA-компоненты не изменились. Показанный PNG — нейтральное превью этих пикселей; сохранение gAMA проверяется отдельным сценарием. Сохраните example.php и четыре дополнительных текстовых файла из архива в одной папке; запустите php example.php с Imagick и PNG, имея право записи. Helper восстанавливает три собственных входа по SHA, сохраняет нейтральные RGB8-превью, разбирает PNG chunks/CRC и пишет metrics.json. Изучаемые getter/setter и отдельный gammaImage вызываются явно в программе. Подготовленные входные метки не сертифицируют правильность цветового кодирования изображения.
Ожидаемый вывод
set=true gamma=0.70000 pixels_unchanged=1
gamma-set-minimal.png
metrics.json
Полезный контракт доставки должен проверяться после записи. Приложение требует gAMA70000, задаёт живое свойство0.7, пишет candidate.png и анализирует именно этот файл. В установленной Imagick3.8.1/ImageMagick7.1.1-46 на нашем profile-free входе encoder не записал gAMA. Программа поэтому отклоняет candidate как доставку и оставляет его для диагностики. Успех сценария — обнаружение нарушения, а не ложное обещание корректного экспорта. У другого encoder/версии решение может отличаться: решает фактический chunk, не заранее выбранный текст статуса.
Отклонить экспорт, который потерял обязательный gAMA
Рабочий результат — проверка контракта и остановка неправильной доставки. Файл candidate.png реально создан, прочитан и отклонён из-за отсутствующей обязательной метки. Выход Imagick не исправляется байтовой вставкой задним числом.
<?php
declare(strict_types=1);
require __DIR__.'/gamma-fixture.php';
gammaRestore();
$source=new Imagick(__DIR__.'/source.png');$working=gammaOpaque($source);$before=gammaPixels($working);$wanted=0.7;
if(!is_finite($wanted)||$wanted<=0){throw new InvalidArgumentException('Project gamma must be finite and positive');}
$ok=$working->setImageGamma($wanted);$live=$working->getImageGamma();$afterSet=gammaPixels($working);
// A write request is not proof that a particular metadata chunk was encoded.
$working->setImageFormat('png');$working->setImageDepth(8);$working->setOption('png:color-type','2');$written=$working->writeImage(__DIR__.'/candidate.png');
$header=gammaPNG('candidate.png');$reread=new Imagick(__DIR__.'/candidate.png');$readGamma=$reread->getImageGamma();
$accepted=$header['gAMA_present']&&$header['gAMA_integer']===(int)round($wanted*100000);
if($accepted){$delivery='accepted';}else{$delivery='rejected';} // Keep candidate.png only as a diagnostic; do not publish it as the requested export.
gammaView(gammaOpaque($source),'input-preview.png');gammaView($reread,'candidate-preview.png');$rects=gammaCompare([new Imagick(__DIR__.'/input-preview.png'),new Imagick(__DIR__.'/candidate-preview.png')],'gamma-export-gate.png');
gammaDiagnostic('gamma-metadata-setimagegamma-workflow',['wanted_gamma'=>$wanted,'live_gamma'=>$live,'readback_gamma'=>$readGamma,'before_pixels'=>$before,'after_set_pixels'=>$afterSet,'saved_pixels'=>gammaPixels($reread),'png'=>$header,'delivery_accepted'=>$accepted,'delivery_status'=>$delivery,'panel_geometry'=>$rects,'checks'=>['setter_true'=>$ok===true,'write_true'=>$written===true,'live_property_matches'=>abs($live-$wanted)<1e-12,'native_pixels_unchanged'=>$before['RGBA8_hash']===$afterSet['RGBA8_hash'],'gate_matches_header'=>$accepted===($header['gAMA_present']&&$header['gAMA_integer']===(int)round($wanted*100000))]]);
echo "gamma-export-gate.png\ninput-preview.png\ncandidate.png\ncandidate-preview.png\nmetrics.json\n";
printf("contract-checked=1 delivery=%s\n",$delivery);
Рабочий результат — проверка контракта и остановка неправильной доставки. Файл candidate.png реально создан, прочитан и отклонён из-за отсутствующей обязательной метки. Выход Imagick не исправляется байтовой вставкой задним числом. Сохраните example.php и четыре дополнительных текстовых файла из архива в одной папке; запустите php example.php с Imagick и PNG, имея право записи. Helper восстанавливает три собственных входа по SHA, сохраняет нейтральные RGB8-превью, разбирает PNG chunks/CRC и пишет metrics.json. Изучаемые getter/setter и отдельный gammaImage вызываются явно в программе. Подготовленные входные метки не сертифицируют правильность цветового кодирования изображения.
Ожидаемый вывод
gamma-export-gate.png
input-preview.png
candidate.png
candidate-preview.png
metrics.json
contract-checked=1 delivery=rejected
Проверить границы и применить проверку в своём приложении
Это наблюдаемая граница конкретного PNG writer. Exact C имеет дополнительный gate: запись gAMA зависит не только от image->gamma и exclude/include-настроек, но и от ping_have_sRGB/ICC-состояния. В проверенном пути без профиля gAMA не появился даже в отдельном ограниченном контроле include-chunk. Поэтому добавление случайных include-флагов не объявлено решением, а ICC-профиль не придумывается для обхода этой границы.
| Ситуация | Действие |
|---|---|
| Две фотографии разной яркости | Не пытаться вывести яркость из getImageGamma; отдельно анализировать/изменять пиксели |
| Нужно изменить метку текущего объекта | setImageGamma с осознанным значением и проверкой собственного входа |
| Нужен обязательный gAMA в доставке | Записать candidate, проверить chunk/CRC/число; при несоответствии отклонить |
| Есть ICC/sRGB/cICP | Разбирать полноценный цветовой контракт; число gamma не заменяет профиль |
| Нет изображения или неверный путь | Обработать чтение/ImagickException на соответствующей стадии |
| Меняется вид в конкретном клиенте | Проверить chunks/профили и именно этот клиент; не обещать одинаковый вид всех браузеров |
Упражнение: измените требование70000 на45455, сохранив проверку присутствия gAMA. Не разрешайте getter-default около0.454545 автоматически пройти контракт45455, если chunk отсутствует. Решение — сначала проверять gAMA_present и точное целое, затем использовать getter как отдельное наблюдение. Подготовка известных входов находится в prepare_stage3_gamma_metadata.py; она создаёт только учебные входные данные, не патчит результаты writeImage.
Полный helper файлов и диагностики
<?php
declare(strict_types=1);
const GAMMA_INPUT_HASHES=['source.png'=>'f51e5780445e0f5130a7f23112b2a00618035afd5545b8e3042c7ccff09b617c','gamma-045455.png'=>'cfa7509b4a89b6efe6e16c08b8c4bbe66b08bbc6ec7edf510965a8fc1fb38fe5','gamma-070000.png'=>'adfb4f1e804f48f1de5456f46149b2ddbbe877efd643598952ffaee3fda2df83'];
function gammaRestore():void {
$hashes=GAMMA_INPUT_HASHES;
foreach($hashes as $name=>$wanted){$text=file_get_contents(__DIR__.'/'.$name.'.b64');$raw=$text===false?false:base64_decode($text,true);if($raw===false||hash('sha256',$raw)!==$wanted||file_put_contents(__DIR__.'/'.$name,$raw)===false){throw new RuntimeException('Input missing or changed: '.$name);}}
}
function gammaPixelHash(Imagick $image):string {return hash('sha256',json_encode($image->exportImagePixels(0,0,$image->getImageWidth(),$image->getImageHeight(),'RGBA',Imagick::PIXEL_CHAR),JSON_THROW_ON_ERROR));}
function gammaPixels(Imagick $image):array {return ['width'=>$image->getImageWidth(),'height'=>$image->getImageHeight(),'RGBA8_hash'=>gammaPixelHash($image),'colorspace'=>$image->getImageColorspace()];}
function gammaOpaque(Imagick $image):Imagick {$view=new Imagick();$view->newImage($image->getImageWidth(),$image->getImageHeight(),'white');$view->compositeImage($image,Imagick::COMPOSITE_OVER,0,0);$view->setImageType(Imagick::IMGTYPE_TRUECOLOR);return $view;}
function gammaView(Imagick $image,string $filename):void {$view=gammaOpaque($image);$view->setImageFormat('png');$view->setImageDepth(8);$view->setOption('png:bit-depth','8');$view->setOption('png:color-type','2');$view->setOption('png:exclude-chunk','all');if(!$view->writeImage(__DIR__.'/'.$filename)){throw new RuntimeException('Preview write failed');}}
function gammaPNG(string $filename):array {
$raw=file_get_contents(__DIR__.'/'.$filename);if($raw===false||substr($raw,0,8)!=="\x89PNG\r\n\x1a\n"){throw new RuntimeException('Not PNG');}
$offset=8;$chunks=[];$gama=null;$header=null;
while($offset<strlen($raw)){$length=unpack('N',substr($raw,$offset,4))[1];$type=substr($raw,$offset+4,4);$payload=substr($raw,$offset+8,$length);$crc=substr($raw,$offset+8+$length,4);if(strlen($payload)!==$length||pack('N',crc32($type.$payload))!==$crc){throw new RuntimeException('Invalid PNG chunk/CRC');}$chunks[]=$type;
if($type==='IHDR'){$header=unpack('Nwidth/Nheight/Cbit_depth/Ccolor_type/Ccompression/Cfilter/Cinterlace',$payload);}
if($type==='gAMA'){if($gama!==null||$length!==4){throw new RuntimeException('Invalid gAMA');}$gama=unpack('N',$payload)[1];}
$offset+=$length+12;if($type==='IEND'){break;}}
if($offset!==strlen($raw)||$header===null||end($chunks)!=='IEND'){throw new RuntimeException('Incomplete PNG');}
return ['filename'=>$filename,'sha256'=>hash('sha256',$raw),'bytes'=>strlen($raw),'IHDR'=>$header,'chunk_types'=>$chunks,'CRC_verified'=>true,'gAMA_present'=>$gama!==null,'gAMA_integer'=>$gama,'gAMA_value'=>$gama===null?null:$gama/100000,'sRGB_present'=>in_array('sRGB',$chunks,true),'iCCP_present'=>in_array('iCCP',$chunks,true),'cICP_present'=>in_array('cICP',$chunks,true)];
}
function gammaCompare(array $images,string $filename):array {$board=new Imagick();$board->newImage(array_sum(array_map(fn($im)=>$im->getImageWidth(),$images)),max(array_map(fn($im)=>$im->getImageHeight(),$images)),'white');$x=0;$rects=[];foreach($images as $image){$y=intdiv($board->getImageHeight()-$image->getImageHeight(),2);$board->compositeImage($image,Imagick::COMPOSITE_OVER,$x,$y);$rects[]=['x'=>$x,'y'=>$y,'width'=>$image->getImageWidth(),'height'=>$image->getImageHeight()];$x+=$image->getImageWidth();}gammaView($board,$filename);return $rects;}
function gammaDiagnostic(string $id,array $data):void {$doc=['schema'=>'aen-gamma-metadata-program-diagnostics-v1','example_id'=>$id]+$data;if(file_put_contents(__DIR__.'/metrics.json',json_encode($doc,JSON_PRETTY_PRINT|JSON_PRESERVE_ZERO_FRACTION|JSON_THROW_ON_ERROR)."\n")===false){throw new RuntimeException('Diagnostic write failed');}}
gammaRestore проверяет SHA; gammaPNG читает настоящие chunks и CRC; gammaView создаёт белое RGB8-превью без цветовых chunks. Getter/setter в helper не спрятаны. Для веб-ответа отдавайте отдельный подготовленный файл с правильным Content-Type без предыдущего echo диагностического текста. Дальше: коррекция тона, цветовое пространство, alpha и фон, файлы.
Функции и методы этой темы
Откройте карточку, чтобы увидеть договор функции, примеры, ограничения и связанные инструменты.
Imagick::getImageGammaЧтение gamma-свойства
PECL imagick 2, PECL imagick 3 · imagick
Imagick::getImageGamma(): floatПиксель хранит компоненты цвета; метаданные описывают, как эти компоненты следует понимать. Gamma в свойстве Imagick — число, а не измеренная яркость фотографии. В PNG отдельный chunk gAMA может хранить это описание. $image — переменная с объектом, -> вызывает метод, () содержит аргументы, ; завершает инструкцию. У getter скобки пустые; setter получает float0.7 с точкой. Переменные, объекты и цветовое пространство — связанные темы.
Минимальная запись и полный базовый контракт
Imagick::getImageGamma(): float$gamma = $image->getImageGamma();Параметров нет. Возвращается float gamma текущего изображения; официально при ошибке ImagickException. В текущем PHP binding пустой объект проверяется до Wand-вызова. Возвращаемое число не измеряет среднюю яркость и само по себе не доказывает наличие gAMA в исходном файле. Значение0 тоже не является универсальным признаком исключения: смотрите источник/формат и состояние объекта.
Официальная доступность: PECL imagick 2, PECL imagick 3. В PHP/Imagick источник различает методы: getImageGamma():float и setImageGamma(float $gamma):bool. В обеих исходных официальных записях нет собственного примера кода; здесь добавлены минимальное применение и реальный сценарий. Полный исходник сохранён без сокращений:
Полный официальный XML
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<refentry xmlns="http://docbook.org/ns/docbook" xml:id="imagick.getimagegamma">
<refnamediv>
<refname>Imagick::getImageGamma</refname>
<refpurpose>Gets the image gamma</refpurpose>
</refnamediv>
<refsect1 role="description">
&reftitle.description;
<methodsynopsis>
<modifier>public</modifier> <type>float</type><methodname>Imagick::getImageGamma</methodname>
<void/>
</methodsynopsis>
<para>
Gets the image gamma.
</para>
</refsect1>
<refsect1 role="parameters">
&reftitle.parameters;
&no.function.parameters;
</refsect1>
<refsect1 role="returnvalues">
&reftitle.returnvalues;
<para>
Returns the image gamma on success.
</para>
</refsect1>
<refsect1 role="errors">
&reftitle.errors;
<para>
&imagick.imagick.throws;
</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
-->
Прочитать gamma заранее подготовленного PNG
Getter возвращает float0.7 из собственного входа с известным gAMA70000. Этот PNG подготовлен как тестовый вход; он не выдан за результат Imagick setter.
<?php
declare(strict_types=1);
require __DIR__.'/gamma-fixture.php';
gammaRestore();
$image=new Imagick(__DIR__.'/gamma-070000.png');
$gamma=$image->getImageGamma();
gammaView($image,'gamma-get-minimal.png');
gammaDiagnostic('gamma-metadata-getimagegamma-minimal',['input'=>'gamma-070000.png','value'=>$gamma,'value_type'=>get_debug_type($gamma),'png'=>gammaPNG('gamma-070000.png'),'checks'=>['known_input_gamma'=>abs($gamma-0.7)<1e-12,'return_float'=>is_float($gamma)]]);
printf("gamma=%.5f type=%s\n",$gamma,get_debug_type($gamma));
echo "gamma-get-minimal.png\nmetrics.json\n";
Getter возвращает float0.7 из собственного входа с известным gAMA70000. Этот PNG подготовлен как тестовый вход; он не выдан за результат Imagick setter. Сохраните example.php и четыре дополнительных текстовых файла из архива в одной папке; запустите php example.php с Imagick и PNG, имея право записи. Helper восстанавливает три собственных входа по SHA, сохраняет нейтральные RGB8-превью, разбирает PNG chunks/CRC и пишет metrics.json. Изучаемые getter/setter и отдельный gammaImage вызываются явно в программе. Подготовленные входные метки не сертифицируют правильность цветового кодирования изображения.
Ожидаемый вывод
gamma=0.70000 type=float
gamma-get-minimal.png
metrics.json
Найти отсутствующую метку и потерю при экспорте
Одинаковые пиксели не означают одинаковые метки. Сравниваются три известных входа и реальный повторный экспорт: getter без метки может вернуть значение по умолчанию, поэтому наличие gAMA проверяется отдельно.
<?php
declare(strict_types=1);
require __DIR__.'/gamma-fixture.php';
gammaRestore();
$rows=[];$panels=[];
foreach(['source.png','gamma-045455.png','gamma-070000.png'] as $i=>$filename){$image=new Imagick(__DIR__.'/'.$filename);$value=$image->getImageGamma();$view='input-'.$i.'-preview.png';gammaView($image,$view);$panels[]=new Imagick(__DIR__.'/'.$view);$rows[]=['input'=>$filename,'getter'=>$value,'getter_type'=>get_debug_type($value),'pixels'=>gammaPixels($image),'png'=>gammaPNG($filename)];}
$copy=new Imagick(__DIR__.'/gamma-070000.png');$copy->setImageFormat('png');$copy->setImageDepth(8);$copy->setOption('png:color-type','6');$copy->writeImage(__DIR__.'/roundtrip.png');
$reread=new Imagick(__DIR__.'/roundtrip.png');$roundtripGamma=$reread->getImageGamma();$roundtripHeader=gammaPNG('roundtrip.png');
gammaView($reread,'roundtrip-preview.png');$panels[]=new Imagick(__DIR__.'/roundtrip-preview.png');$rects=gammaCompare($panels,'gamma-read-workflow.png');
$lost=$rows[2]['png']['gAMA_present']&&!$roundtripHeader['gAMA_present'];
gammaDiagnostic('gamma-metadata-getimagegamma-workflow',['inputs'=>$rows,'roundtrip'=>['getter'=>$roundtripGamma,'png'=>$roundtripHeader,'pixels'=>gammaPixels($reread)],'lost_label'=>$lost,'panel_geometry'=>$rects,'checks'=>['known_inputs_differ_only_by_label'=>count(array_unique(array_column(array_column($rows,'pixels'),'RGBA8_hash')))===1,'known_labels_explicit'=>$rows[0]['png']['gAMA_integer']===null&&$rows[1]['png']['gAMA_integer']===45455&&$rows[2]['png']['gAMA_integer']===70000]]);
echo "gamma-read-workflow.png\ninput-0-preview.png\ninput-1-preview.png\ninput-2-preview.png\nroundtrip.png\nroundtrip-preview.png\nmetrics.json\n";
printf("inputs=%d lost-label-detected=%d\n",count($rows),(int)$lost);
Одинаковые пиксели не означают одинаковые метки. Сравниваются три известных входа и реальный повторный экспорт: getter без метки может вернуть значение по умолчанию, поэтому наличие gAMA проверяется отдельно. Сохраните example.php и четыре дополнительных текстовых файла из архива в одной папке; запустите php example.php с Imagick и PNG, имея право записи. Helper восстанавливает три собственных входа по SHA, сохраняет нейтральные RGB8-превью, разбирает PNG chunks/CRC и пишет metrics.json. Изучаемые getter/setter и отдельный gammaImage вызываются явно в программе. Подготовленные входные метки не сертифицируют правильность цветового кодирования изображения.
Ожидаемый вывод
gamma-read-workflow.png
input-0-preview.png
input-1-preview.png
input-2-preview.png
roundtrip.png
roundtrip-preview.png
metrics.json
inputs=3 lost-label-detected=1
Imagick::setImageGammaИзменение gamma-свойства без коррекции пикселей
PECL imagick 2, PECL imagick 3 · imagick
Imagick::setImageGamma(float $gamma): boolПиксель хранит компоненты цвета; метаданные описывают, как эти компоненты следует понимать. Gamma в свойстве Imagick — число, а не измеренная яркость фотографии. В PNG отдельный chunk gAMA может хранить это описание. $image — переменная с объектом, -> вызывает метод, () содержит аргументы, ; завершает инструкцию. У getter скобки пустые; setter получает float0.7 с точкой. Переменные, объекты и цветовое пространство — связанные темы.
Минимальная запись и полный базовый контракт
Imagick::setImageGamma(float $gamma): bool$ok = $image->setImageGamma(0.7);| Параметр/результат | Смысл |
|---|---|
| $gamma: float, обязательный | Новое значение свойства gamma текущего изображения. Это не аргумент gammaImage и не экспозиция. |
| booltrue | Статус успешной записи свойства в объект. Он не удостоверяет конкретный chunk будущего файла. |
| ImagickException | Официальный отказ метода; пустой объект проверяется PHP binding. |
В исходном XML описание параметра пусто. Exact Wand просто присваивает image->gamma=gamma, не меняет пиксели и не проверяет положительность/конечность. Поэтому конечное положительное число для запланированного PNG — явная политика приложения, а не придуманная гарантия валидации setter. Неверный PHP-тип может дать TypeError. ICC-профиль setter не преобразует.
Официальная доступность: PECL imagick 2, PECL imagick 3. В PHP/Imagick источник различает методы: getImageGamma():float и setImageGamma(float $gamma):bool. В обеих исходных официальных записях нет собственного примера кода; здесь добавлены минимальное применение и реальный сценарий. Полный исходник сохранён без сокращений:
Полный официальный XML
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<refentry xmlns="http://docbook.org/ns/docbook" xml:id="imagick.setimagegamma">
<refnamediv>
<refname>Imagick::setImageGamma</refname>
<refpurpose>Sets the image gamma</refpurpose>
</refnamediv>
<refsect1 role="description">
&reftitle.description;
<methodsynopsis>
<modifier>public</modifier> <type>bool</type><methodname>Imagick::setImageGamma</methodname>
<methodparam><type>float</type><parameter>gamma</parameter></methodparam>
</methodsynopsis>
<para>
Sets the image gamma.
</para>
</refsect1>
<refsect1 role="parameters">
&reftitle.parameters;
<para>
<variablelist>
<varlistentry>
<term><parameter>gamma</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>
</refentry>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->
Задать свойство объекта без изменения рисунка
Setter вернул true, текущий getter прочитал0.7, RGBA-компоненты не изменились. Показанный PNG — нейтральное превью этих пикселей; сохранение gAMA проверяется отдельным сценарием.
<?php
declare(strict_types=1);
require __DIR__.'/gamma-fixture.php';
gammaRestore();
$image=new Imagick(__DIR__.'/source.png');$before=gammaPixelHash($image);
$ok=$image->setImageGamma(0.7);
$value=$image->getImageGamma();$same=$before===gammaPixelHash($image);
gammaView($image,'gamma-set-minimal.png');
gammaDiagnostic('gamma-metadata-setimagegamma-minimal',['value'=>$value,'return_value'=>$ok,'return_type'=>get_debug_type($ok),'before_hash'=>$before,'after_hash'=>gammaPixelHash($image),'checks'=>['setter_true'=>$ok===true,'requested_live_value'=>abs($value-0.7)<1e-12,'pixels_unchanged'=>$same]]);
printf("set=%s gamma=%.5f pixels_unchanged=%d\n",$ok?'true':'false',$value,(int)$same);
echo "gamma-set-minimal.png\nmetrics.json\n";
Setter вернул true, текущий getter прочитал0.7, RGBA-компоненты не изменились. Показанный PNG — нейтральное превью этих пикселей; сохранение gAMA проверяется отдельным сценарием. Сохраните example.php и четыре дополнительных текстовых файла из архива в одной папке; запустите php example.php с Imagick и PNG, имея право записи. Helper восстанавливает три собственных входа по SHA, сохраняет нейтральные RGB8-превью, разбирает PNG chunks/CRC и пишет metrics.json. Изучаемые getter/setter и отдельный gammaImage вызываются явно в программе. Подготовленные входные метки не сертифицируют правильность цветового кодирования изображения.
Ожидаемый вывод
set=true gamma=0.70000 pixels_unchanged=1
gamma-set-minimal.png
metrics.json
Отклонить экспорт, который потерял обязательный gAMA
Рабочий результат — проверка контракта и остановка неправильной доставки. Файл candidate.png реально создан, прочитан и отклонён из-за отсутствующей обязательной метки. Выход Imagick не исправляется байтовой вставкой задним числом.
<?php
declare(strict_types=1);
require __DIR__.'/gamma-fixture.php';
gammaRestore();
$source=new Imagick(__DIR__.'/source.png');$working=gammaOpaque($source);$before=gammaPixels($working);$wanted=0.7;
if(!is_finite($wanted)||$wanted<=0){throw new InvalidArgumentException('Project gamma must be finite and positive');}
$ok=$working->setImageGamma($wanted);$live=$working->getImageGamma();$afterSet=gammaPixels($working);
// A write request is not proof that a particular metadata chunk was encoded.
$working->setImageFormat('png');$working->setImageDepth(8);$working->setOption('png:color-type','2');$written=$working->writeImage(__DIR__.'/candidate.png');
$header=gammaPNG('candidate.png');$reread=new Imagick(__DIR__.'/candidate.png');$readGamma=$reread->getImageGamma();
$accepted=$header['gAMA_present']&&$header['gAMA_integer']===(int)round($wanted*100000);
if($accepted){$delivery='accepted';}else{$delivery='rejected';} // Keep candidate.png only as a diagnostic; do not publish it as the requested export.
gammaView(gammaOpaque($source),'input-preview.png');gammaView($reread,'candidate-preview.png');$rects=gammaCompare([new Imagick(__DIR__.'/input-preview.png'),new Imagick(__DIR__.'/candidate-preview.png')],'gamma-export-gate.png');
gammaDiagnostic('gamma-metadata-setimagegamma-workflow',['wanted_gamma'=>$wanted,'live_gamma'=>$live,'readback_gamma'=>$readGamma,'before_pixels'=>$before,'after_set_pixels'=>$afterSet,'saved_pixels'=>gammaPixels($reread),'png'=>$header,'delivery_accepted'=>$accepted,'delivery_status'=>$delivery,'panel_geometry'=>$rects,'checks'=>['setter_true'=>$ok===true,'write_true'=>$written===true,'live_property_matches'=>abs($live-$wanted)<1e-12,'native_pixels_unchanged'=>$before['RGBA8_hash']===$afterSet['RGBA8_hash'],'gate_matches_header'=>$accepted===($header['gAMA_present']&&$header['gAMA_integer']===(int)round($wanted*100000))]]);
echo "gamma-export-gate.png\ninput-preview.png\ncandidate.png\ncandidate-preview.png\nmetrics.json\n";
printf("contract-checked=1 delivery=%s\n",$delivery);
Рабочий результат — проверка контракта и остановка неправильной доставки. Файл candidate.png реально создан, прочитан и отклонён из-за отсутствующей обязательной метки. Выход Imagick не исправляется байтовой вставкой задним числом. Сохраните example.php и четыре дополнительных текстовых файла из архива в одной папке; запустите php example.php с Imagick и PNG, имея право записи. Helper восстанавливает три собственных входа по SHA, сохраняет нейтральные RGB8-превью, разбирает PNG chunks/CRC и пишет metrics.json. Изучаемые getter/setter и отдельный gammaImage вызываются явно в программе. Подготовленные входные метки не сертифицируют правильность цветового кодирования изображения.
Ожидаемый вывод
gamma-export-gate.png
input-preview.png
candidate.png
candidate-preview.png
metrics.json
contract-checked=1 delivery=rejected
Код и руководство с собой
Скачайте самостоятельные примеры с исходными данными, инструкциями и ожидаемыми результатами. Примеры HTTP и фрагменты для проекта помечены отдельно: им нужно указанное окружение.
Код не исполняется на сайте. Скачайте нужный пример и запускайте его в своём локальном окружении.
Материалы сверены 2026-10-12. Примеры и объяснения написаны для этого руководства; источники и обсуждения доступны в каждой главе.


