Skip to content

Commit d15b579

Browse files
committed
insertImage может вставлять изображение с прозрачностью
1 parent b69e6fd commit d15b579

File tree

1 file changed

+86
-29
lines changed

1 file changed

+86
-29
lines changed

src/Image.php

Lines changed: 86 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,9 @@ public function __construct( $bitmap, $isTransparent = false )
7373

7474
// Работаем только с True Color
7575
if ( !imageistruecolor( $this->bitmap ) ) {
76-
$bitmap = $this->toResource();
77-
@imagedestroy( $this->bitmap );
78-
$this->bitmap = $bitmap;
76+
$bitmap = $this->toResource();
77+
@imagedestroy( $this->bitmap );
78+
$this->bitmap = $bitmap;
7979
}
8080

8181
@imagealphablending( $this->bitmap, true );
@@ -271,7 +271,7 @@ function write(
271271
$x -= $width * $alignHor;
272272
$color = static::allocateColor( $this->bitmap, $color );
273273
$bitmap = $this->toResource();
274-
@imagealphablending( $bitmap, true );
274+
@imagealphablending( $bitmap, true );
275275

276276
$result = @imagettftext( $bitmap, $fontSize, $angle, $x, $y, $color, $font, $text );
277277
if ( !$result )
@@ -293,10 +293,12 @@ function write(
293293
* @param self $image Вставляемое изображение
294294
* @param int $dstX Координата X на текущем изображении, куда вставить новое. По умолчанию, 0.
295295
* @param int $dstY Координата Y на текущем изображении, куда вставить новое. По умолчанию, 0.
296-
* @param int $srcX Координата X вставляемой области вставляемого изображения. По умолчанию, 0.
297-
* @param int $srcY Координата Y вставляемой области вставляемого изображения. По умолчанию, 0.
298296
* @param int|null $dstWidth Новая ширина вставляемой области. Если null, то такая же как $srcWidth.
299297
* @param int|null $dstHeight Новая Высота вставляемой области. Если null, то такая же как $srcHeight.
298+
* @param float $opacity Уровень непрозрачности вставляемого изображения (от 0 – полностью прозрачное, до 1 – без
299+
* прозрачности)
300+
* @param int $srcX Координата X вставляемой области вставляемого изображения. По умолчанию, 0.
301+
* @param int $srcY Координата Y вставляемой области вставляемого изображения. По умолчанию, 0.
300302
* @param int|null $srcWidth Ширина вставляемой области вставляемого изображения. Если null, то вся ширина изображения.
301303
* @param int|null $srcHeight Высота вставляемой области вставляемого изображения. Если null, то вся высота изображения.
302304
* @return static Текущее изображение с вставленным
@@ -306,24 +308,49 @@ function insertImage(
306308
self $image,
307309
$dstX = 0,
308310
$dstY = 0,
309-
$srcX = 0,
310-
$srcY = 0,
311311
$dstWidth = null,
312312
$dstHeight = null,
313+
$opacity = 1.0,
314+
$srcX = 0,
315+
$srcY = 0,
313316
$srcWidth = null,
314317
$srcHeight = null
315318
) {
316319
if( !isset( $image->bitmap ) )
317320
throw new \Exception( 'В объекте вставляемого изображения нет данных изображения.' );
318321

319-
if( !is_numeric( $dstX ) ) $dstX = 0;
320-
if( !is_numeric( $dstY ) ) $dstY = 0;
321-
if( !is_numeric( $srcX ) ) $srcX = 0;
322-
if( !is_numeric( $srcY ) ) $srcY = 0;
323-
if( !is_numeric( $srcWidth ) ) $srcWidth = $image->getWidth() - $srcX;
324-
if( !is_numeric( $srcHeight ) ) $srcHeight = $image->getHeight() - $srcY;
325-
if( !is_numeric( $dstWidth ) ) $dstWidth = $srcWidth;
326-
if( !is_numeric( $dstHeight ) ) $dstHeight = $srcHeight;
322+
if ( !is_numeric( $dstX ) ) $dstX = 0;
323+
if ( !is_numeric( $dstY ) ) $dstY = 0;
324+
if ( !is_numeric( $srcX ) ) $srcX = 0;
325+
if ( !is_numeric( $srcY ) ) $srcY = 0;
326+
if ( !is_numeric( $srcWidth ) ) $srcWidth = $image->getWidth() - $srcX;
327+
if ( !is_numeric( $srcHeight ) ) $srcHeight = $image->getHeight() - $srcY;
328+
if ( !is_numeric( $dstWidth ) ) $dstWidth = $srcWidth;
329+
if ( !is_numeric( $dstHeight ) ) $dstHeight = $srcHeight;
330+
$opacity = is_numeric( $opacity ) ? min( 1, max( 0, $opacity ) ) : 1;
331+
332+
if ( $opacity == 0 )
333+
return clone $this;
334+
335+
if ( $opacity < 1 ) {
336+
if (
337+
$srcX !== 0 || $srcY !== 0 ||
338+
$srcWidth !== $image->getWidth() || $srcHeight !== $image->getHeight()
339+
) {
340+
$image = $image->crop( $srcX, $srcY, $srcWidth, $srcHeight );
341+
$srcX = 0;
342+
$srcY = 0;
343+
}
344+
345+
// Когда меньше пикселей: до или после изменения размера?
346+
if ( $srcWidth * $srcHeight > $dstWidth * $dstHeight ) {
347+
$image = $image->resize( $dstWidth, $dstHeight, true, static::SIZING_EXEC );
348+
$srcWidth = $dstWidth;
349+
$srcHeight = $dstHeight;
350+
}
351+
352+
$image = $image->setOpacity( $opacity );
353+
}
327354

328355
$bitmap = $this->toResource();
329356
@imagealphablending( $bitmap, true );
@@ -356,6 +383,36 @@ function insertImage(
356383
}
357384

358385

386+
/**
387+
* Обрезает изображение. Возвращается копия, текущий объект не модифицируется.
388+
*
389+
* @param int $x Координата X откуда начинается обрезка. По умолчанию, 0.
390+
* @param int $y Координата Y откуда начинается обрезка. По умолчанию, 0.
391+
* @param int|null $width Ширина вырезаемой области. Если null, то вся ширина.
392+
* @param int|null $height Новая Высота вырезаемой области. Если null, вся высота.
393+
* @return static Обрезанное изображение
394+
* @throws \Exception В случае непредвиденной ошибки
395+
*/
396+
function crop( $x = 0, $y = 0, $width = null, $height = null )
397+
{
398+
if ( !is_numeric( $x ) ) $x = 0;
399+
if ( !is_numeric( $y ) ) $y = 0;
400+
if ( !is_numeric( $width ) ) $width = $this->getWidth() - $x;
401+
if ( !is_numeric( $height ) ) $height = $this->getHeight() - $y;
402+
403+
$bitmap = @imagecreatetruecolor( $width, $height );
404+
@imagealphablending( $bitmap, false );
405+
$result = @imagecopy( $bitmap, $this->bitmap, 0, 0, $x, $y, $width, $height );
406+
407+
if ( !$bitmap || !$result )
408+
throw new \Exception( 'Не удалось обрезать изображение по неизвестной причине.' );
409+
410+
$newImage = static::construct( $bitmap );
411+
$newImage->isTransparent = $this->isTransparent;
412+
return $newImage;
413+
}
414+
415+
359416
/**
360417
* Вращает изображение. Возвращается копия, текущий объект не модифицируется.
361418
*
@@ -385,29 +442,29 @@ function rotate( $angle, Array $underlay = null )
385442
* @return static Изображение, к которому применена указанная прозрачность
386443
* @throws \InvalidArgumentException Если указанная прозрачность не является числом
387444
*/
388-
function setOpaque( $opacity )
445+
function setOpacity( $opacity )
389446
{
390447
if ( !is_numeric( $opacity ) )
391448
throw new \InvalidArgumentException( 'Opacity must be number, ' . gettype( $opacity ) . ' given.' );
392449

393-
if ( $opacity >= 1 )
394-
return clone $this;
395-
396450
$opacity = min( 1, max( 0, $opacity ) );
397451

452+
if ( $opacity == 1 )
453+
return clone $this;
454+
398455
$width = $this->getWidth();
399456
$height = $this->getHeight();
400457
$bitmap = $this->toResource();
401458

402459
for ( $x = 0; $x < $width; ++$x )
403-
for ( $y = 0; $y < $height; ++$y ) {
404-
$color = imagecolorat( $bitmap, $x, $y );
405-
$alpha = 127 - ( ( $color >> 24 ) & 0xFF );
406-
if ( $alpha > 0 ) {
407-
$color = ( $color & 0xFFFFFF ) | ( (int)round( 127 - $alpha * $opacity ) << 24 );
408-
imagesetpixel( $bitmap, $x, $y, $color );
409-
}
410-
}
460+
for ( $y = 0; $y < $height; ++$y ) {
461+
$color = imagecolorat( $bitmap, $x, $y );
462+
$alpha = 127 - ( ( $color >> 24 ) & 0xFF );
463+
if ( $alpha > 0 ) {
464+
$color = ( $color & 0xFFFFFF ) | ( (int)round( 127 - $alpha * $opacity ) << 24 );
465+
imagesetpixel( $bitmap, $x, $y, $color );
466+
}
467+
}
411468

412469
$newImage = static::construct( $bitmap );
413470
$newImage->isTransparent = true;
@@ -684,7 +741,7 @@ public function toResource()
684741
@imagealphablending( $bitmap, false );
685742

686743
if ( !imageistruecolor( $this->bitmap ) )
687-
@imagefill( $bitmap, 0, 0, @imagecolortransparent( $bitmap ) );
744+
@imagefill( $bitmap, 0, 0, @imagecolortransparent( $bitmap ) );
688745

689746
$result = @imagecopy( $bitmap, $this->bitmap, 0, 0, 0, 0, $width, $height );
690747

0 commit comments

Comments
 (0)