5
5
namespace Intervention \Image \Drivers \Imagick \Modifiers ;
6
6
7
7
use Imagick ;
8
- use Intervention \ Image \ Drivers \ Imagick \ Driver ;
8
+ use ImagickPixel ;
9
9
use Intervention \Image \Interfaces \ImageInterface ;
10
10
use Intervention \Image \Interfaces \SpecializedInterface ;
11
11
use Intervention \Image \Modifiers \CropModifier as GenericCropModifier ;
@@ -14,20 +14,30 @@ class CropModifier extends GenericCropModifier implements SpecializedInterface
14
14
{
15
15
public function apply (ImageInterface $ image ): ImageInterface
16
16
{
17
- $ crop = $ this -> crop ( $ image );
17
+ // decode background color
18
18
$ background = $ this ->driver ()->colorProcessor ($ image ->colorspace ())->colorToNative (
19
19
$ this ->driver ()->handleInput ($ this ->background )
20
20
);
21
21
22
22
// create empty container imagick to rebuild core
23
23
$ imagick = new Imagick ();
24
+
25
+ // save resolution to add it later
24
26
$ resolution = $ image ->resolution ()->perInch ();
25
27
28
+ // define position of the image on the new canvas
29
+ $ crop = $ this ->crop ($ image );
30
+ $ position = [
31
+ ($ crop ->pivot ()->x () + $ this ->offset_x ) * -1 ,
32
+ ($ crop ->pivot ()->y () + $ this ->offset_y ) * -1 ,
33
+ ];
34
+
26
35
foreach ($ image as $ frame ) {
27
36
// create new frame canvas with modifiers background
28
37
$ canvas = new Imagick ();
29
38
$ canvas ->newImage ($ crop ->width (), $ crop ->height (), $ background , 'png ' );
30
39
$ canvas ->setImageResolution ($ resolution ->x (), $ resolution ->y ());
40
+ $ canvas ->setImageAlphaChannel (Imagick::ALPHACHANNEL_SET ); // or ALPHACHANNEL_ACTIVATE?
31
41
32
42
// set animation details
33
43
if ($ image ->isAnimated ()) {
@@ -36,31 +46,28 @@ public function apply(ImageInterface $image): ImageInterface
36
46
$ canvas ->setImageDispose ($ frame ->native ()->getImageDispose ());
37
47
}
38
48
39
- // place original frame content onto the empty colored frame canvas
40
- $ canvas ->compositeImage (
41
- $ frame ->native (),
42
- Imagick::COMPOSITE_DEFAULT ,
43
- ($ crop ->pivot ()->x () + $ this ->offset_x ) * -1 ,
44
- ($ crop ->pivot ()->y () + $ this ->offset_y ) * -1 ,
49
+ // make the rectangular position of the original image transparent
50
+ // so that we can later place the original on top. this preserves
51
+ // the transparency of the original and shows the background color
52
+ // of the modifier in the other areas. if the original image has no
53
+ // transparent area the rectangular transparency will be covered by
54
+ // the original.
55
+ $ clearer = new Imagick ();
56
+ $ clearer ->newImage (
57
+ $ frame ->native ()->getImageWidth (),
58
+ $ frame ->native ()->getImageHeight (),
59
+ new ImagickPixel ('black ' ),
45
60
);
61
+ $ canvas ->compositeImage ($ clearer , Imagick::COMPOSITE_DSTOUT , ...$ position );
46
62
47
- // copy alpha channel if available
48
- if ($ frame ->native ()->getImageAlphaChannel ()) {
49
- $ canvas ->compositeImage (
50
- $ frame ->native (),
51
- version_compare (Driver::version (), '7.0.0 ' , '>= ' ) ?
52
- Imagick::COMPOSITE_COPYOPACITY :
53
- Imagick::COMPOSITE_DSTIN ,
54
- ($ crop ->pivot ()->x () + $ this ->offset_x ) * -1 ,
55
- ($ crop ->pivot ()->y () + $ this ->offset_y ) * -1 ,
56
- );
57
- }
63
+ // place original frame content onto prepared frame canvas
64
+ $ canvas ->compositeImage ($ frame ->native (), Imagick::COMPOSITE_DEFAULT , ...$ position );
58
65
59
66
// add newly built frame to container imagick
60
67
$ imagick ->addImage ($ canvas );
61
68
}
62
69
63
- // replace imagick
70
+ // replace imagick in the original image
64
71
$ image ->core ()->setNative ($ imagick );
65
72
66
73
return $ image ;
0 commit comments