Четверг , 28 Март 2024
ДомойПубликацииКак отразить изображение в php

Как отразить изображение в php

Сегодня расскажу о забавной фиче, про которую не упоминается в мане. Почти все, кто работал с изображениями, знакомы с функцией imagecopyresampled(), которая предназначена для копирования изображения с изменением его размеров (включая непропорциональное масштабирование). Если по существу, то можно взять произвольную часть с одного изображения и нанести её на произвольный участок другого.

Примечательно, что для поворота картинки на произвольный угол функция имеется — imagerotate(). Однако, чтобы отразить изображение по горизонтали/вертикали, можно произвести небольшой финт ушами. Для начала, вспомним функцию substr(), точнее — второй и третий параметры. Соль в том, что их можно задать отрицательными, в этом случае, значения будут отсчитываться не от начала строки, а от её конца. Этот же способ вполне себе отлично работает и в данном случае. Задавая отрицательные ширину/высоту, мы показываем, что следует брать отрицательное смещение. Но в этом случае, в качестве точки старта (координаты x и y, от которой отсчитывается ширина/высота), необходимо указать крайнюю часть изображения для масштабирования (при этом не забываем, что начало координат имеет точку [0,0], и поэтому если необходимо отразить картинку, шириной 30 пикселей, значение x будет 29).
Чтобы стало чуть понятнее, вот увеличенная картинка, изначальным размером 30×16 точек.

Жёлтые точки (прошу прощения, что они выстроены немного криво) условно показывают реальные пикселы. Можно посчитать их и убедится, что количество по горизонтали составит 30 штук, по вертикали — 16 (изображение, как помним, имеет размер 30×16 пикселей). Но, если начать считать с нуля (т. е. первый кружок считаем как ноль, следующий — один и т. д.), получим, что размеры «уменьшатся» на 1 пиксел (в действительности, конечно же, физические размеры не меняются, и вам, возможно, проще будет провести аналогию с температурой по Кельвину и Цельсию, где 273 К соответствует 0 C, в то время, как на деле это одно и то же).

Теперь вспомним функцию копирования изображения с ресемплированием:

imagecopyresampled($dimg, $simg, $dx, $dy, $sx, $sy, $dw, $dh, $sx, $sh)

где:
$dimg — изображение, на которое копируется (акцептор);
$simg — изображение, с которого копируется (донор);
$dx, dy — координаты x и y на акцепторе, начиная с которых будет записываться новое изображение;
$sx, $sy — координаты x и y на доноре, начиная с которых будет копироваться старое изображение;
$dw, $dh — ширина и высота части на акцепторе, в которое отмасштабируется изображение;
$sw, $sh — ширина и высота части донора, которая будет скопирована.

Другими словами: функция берёт часть изображения с $simg, начиная с координат $sx и $sy, шириной/высотой — $sw/$sh, и «умещает» их на изображении $dimg, начиная с координат $dx и $dy, шириной/высотой — $dw/$dh (при этом, $dw/$dh могут быть как больше $sw/$sh, так и меньше их).

Пусть требуется отразить изображение по горизонтали. Ширина исходной области равна ширине всей картинки, т. е. 30 точек. Но для отражения (для копирования задом наперёд) нужна отрицательная ширина, что составит: 0 — 30 = -30 (минус тридцать) пикселей. При этом, началом точки копирования необходимо установить крайнюю правую точку, что соответствует значению ширина — 1 = 30 — 1 = 29 (как помним, начало координат отсчитывается с нуля, это точки изображения будут как бы отставать на 1 пиксел).

Для отражения по вертикали используется тот же фокус, только с высотой и координатой y: $sh и $sy, получаем, что высота равняется 0 — 16 = -16, а точка начала копирования — $sy — 1 = 16 — 1 = 15.

Теперь, т. к. размеры изображения остаются неизменны, получим, что $dw = $sw, $dh = $sh. для простоты, обозначим ширину и высоту как $w и $h соответственно. размеры изображений $dimg и $simg будут $w x $h точек.

Т. к. изображение копируется целиком, началом точки, в которую копируется картинки, примем за нули: $dx = 0, $sx = 0.

В итоге, для горизонтального отражения получим:

imagecopyresampled($dimg, $simg, 0, 0, $w - 1, 0, $w, $h, - $w, $h);

Для вертикального отражения:

imagecopyresampled($dimg, $simg, 0, 0, 0, $h - 1, $w, $h, $w, - $h);

Для отражения сразу по горизонтали и вертикали нужно сделать объединённый вариант:

imagecopyresampled($dimg, $simg, 0, 0, $w - 1, $h - 1, $w, $h, - $w, - $h);

Рейтинг: 0

Автор публикации

2 070
не в сети 11 месяцев

x64 (aka andi)

Комментарии: 2893Публикации: 405Регистрация: 02-04-2009
Так себеНеплохоХорошоЗамечательноСупер! (2 голосов, в среднем: 5,00 из 5)
Загрузка...

2 комментария

  1. Хотелось бы также отметить, что с функцией imagecopyresized сей баг не работает.

    Рейтинг: 0
    • Здравствуйте.
      Скорее, это не баг, а фича. Такая вот недокументированная особенность функции.
      Когда писал статью, думал, что это особенность распространяется на поведение обоих функций. Но тесты показали, что всё не так. Поэтому упоминание о imagecopyresized() было выпилено.
      Спасибо, что напомнили!

      Рейтинг: 0

Оставить комментарий

Политика конфиденциальности

Наш сайт использует файлы cookies, чтобы улучшить работу и повысить эффективность сайта. Продолжая работу с сайтом, вы соглашаетесь с использованием нами cookies и политикой конфиденциальности.

Принять