cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1 | #!/usr/bin/perl |
| 2 | # |
| 3 | # Demonstration of some of the fancier Image Composition Methods |
| 4 | # including the 'rotate' parameter specific to PerlMagick Composite() |
| 5 | # |
| 6 | # NOTE: versions of IM older than IM v6.5.3-4 will need to rename the |
| 7 | # parameter "args=>" to the mis-named "blend=>" parameter. |
| 8 | # |
| 9 | # Also not that "composite -watermark" is actually known as the compose |
| 10 | # method "Modulate". |
| 11 | # |
| 12 | # Essentually each image is equivelent to |
| 13 | # convert logo: -crop 80x80+140+60 +repage \ |
| 14 | # -size 60x60 gradient:black-white \ |
| 15 | # -alpha set miff:- |\ |
| 16 | # composite - -geometry +10+10 -virtual-pixel gray \ |
| 17 | # -dissolve 70x30 show: |
| 18 | # for various composition methods. |
| 19 | # |
| 20 | use strict; |
| 21 | use Image::Magick; |
| 22 | |
| 23 | # Background or Destination image |
| 24 | my $dest=Image::Magick->new(); |
| 25 | $dest->Read('logo:'); |
| 26 | $dest->Crop('100x100+400+100'); # wizards hat |
| 27 | $dest->Set(page=>'0x0+0+0'); |
| 28 | $dest->Set(alpha=>'Set'); |
| 29 | |
| 30 | # Source, Composite or Overlay image |
| 31 | my $src=Image::Magick->new(); |
| 32 | $src->Set(size=>'80x80'); |
| 33 | $src->Read('gradient:black-white'); |
| 34 | $src->Set(alpha=>'Set'); |
| 35 | |
| 36 | my $offset="+10+10"; |
| 37 | |
| 38 | # Circle Mask Image (same size as Destination) |
| 39 | my $circle=Image::Magick->new(); |
| 40 | $circle->Set(size=>'100x100'); |
| 41 | $circle->Read('xc:black'); |
| 42 | $circle->Draw(fill=>'white',primitive=>'circle',points=>'49.5,49.5 10,49.5'); |
| 43 | |
| 44 | my $texture=Image::Magick->new(); |
| 45 | $texture->Read('pattern:checkerboard'); |
| 46 | |
| 47 | # List of images generated |
| 48 | my $results=Image::Magick->new(); |
| 49 | |
| 50 | # Working copy of Destination Image |
| 51 | my $clone; |
| 52 | |
| 53 | # ---------------------------------------- |
| 54 | # Normal Composition Methods |
| 55 | |
| 56 | $clone=$dest->Clone(); |
| 57 | $clone->Label('Over\n(normal compose)'); |
| 58 | $clone->Composite( |
| 59 | image=>$src, |
| 60 | compose=>'over', |
| 61 | geometry=>$offset, |
| 62 | ); |
| 63 | push(@$results, $clone); |
| 64 | |
| 65 | $clone=$dest->Clone(); |
| 66 | $clone->Label('Multiply\n(add black)'); |
| 67 | $clone->Composite( |
| 68 | image=>$src, |
| 69 | compose=>'multiply', |
| 70 | geometry=>$offset, |
| 71 | ); |
| 72 | push(@$results, $clone); |
| 73 | |
| 74 | $clone=$dest->Clone(); |
| 75 | $clone->Label('Screen\n(add white)'); |
| 76 | $clone->Composite( |
| 77 | image=>$src, |
| 78 | compose=>'screen', |
| 79 | geometry=>$offset, |
| 80 | ); |
| 81 | push(@$results, $clone); |
| 82 | |
| 83 | $clone=$dest->Clone(); |
| 84 | $clone->Label('HardLight\n(light effects)'); |
| 85 | $clone->Composite( |
| 86 | image=>$src, |
| 87 | compose=>'hardlight', |
| 88 | geometry=>$offset, |
| 89 | ); |
| 90 | push(@$results, $clone); |
| 91 | |
| 92 | # --------------- |
| 93 | # Masked and Blending Demonstartion |
| 94 | |
| 95 | $clone=$dest->Clone(); |
| 96 | $clone->Label('Circle Masked\n(three image)'); |
| 97 | $clone->Composite( |
| 98 | image=>$src, |
| 99 | mask=>$circle, |
| 100 | compose=>'over', |
| 101 | geometry=>$offset, |
| 102 | ); |
| 103 | push(@$results, $clone); |
| 104 | |
| 105 | $clone=$dest->Clone(); |
| 106 | $clone->Label('Blend 50x50\n(50% plus 50%)'); |
| 107 | $clone->Composite( |
| 108 | image=>$src, |
| 109 | compose=>'blend', |
| 110 | args=>'50x50', |
| 111 | geometry=>$offset, |
| 112 | ); |
| 113 | push(@$results, $clone); |
| 114 | |
| 115 | $clone=$dest->Clone(); |
| 116 | $clone->Label('Dissolve 50x50\n(50% over 50%)'); |
| 117 | $clone->Composite( |
| 118 | image=>$src, |
| 119 | compose=>'dissolve', |
| 120 | args=>'50x50', |
| 121 | geometry=>$offset, |
| 122 | ); |
| 123 | push(@$results, $clone); |
| 124 | |
| 125 | $clone=$dest->Clone(); |
| 126 | $clone->Label('Dissolve 50\n(50% over 100%)'); |
| 127 | $clone->Composite( |
| 128 | image=>$src, |
| 129 | compose=>'dissolve', |
| 130 | args=>'50', |
| 131 | geometry=>$offset, |
| 132 | ); |
| 133 | push(@$results, $clone); |
| 134 | |
| 135 | # --------------- |
| 136 | # Displacement Demonstartion |
| 137 | |
| 138 | $clone=$dest->Clone(); |
| 139 | $clone->Label('Displace 50x0\n(displace horiz)'); |
| 140 | $clone->Set('virtual-pixel'=>'gray'); |
| 141 | $clone->Composite( |
| 142 | image=>$src, |
| 143 | compose=>'displace', |
| 144 | args=>'50x0', |
| 145 | geometry=>$offset, |
| 146 | ); |
| 147 | push(@$results, $clone); |
| 148 | |
| 149 | $clone=$dest->Clone(); |
| 150 | $clone->Label('Displace 0x50\n(compress vert)'); |
| 151 | $clone->Set('virtual-pixel'=>'gray'); |
| 152 | $clone->Composite( |
| 153 | image=>$src, |
| 154 | compose=>'displace', |
| 155 | args=>'0x50', |
| 156 | geometry=>$offset, |
| 157 | ); |
| 158 | push(@$results, $clone); |
| 159 | |
| 160 | $clone=$dest->Clone(); |
| 161 | $clone->Label('Displace 50x50\n(diagonal)'); |
| 162 | $clone->Set('virtual-pixel'=>'gray'); |
| 163 | $clone->Composite( |
| 164 | image=>$src, |
| 165 | compose=>'displace', |
| 166 | args=>'50x50', |
| 167 | geometry=>$offset, |
| 168 | ); |
| 169 | push(@$results, $clone); |
| 170 | |
| 171 | $clone=$dest->Clone(); |
| 172 | $clone->Label('Displace 0,-80\n(displace flip)'); |
| 173 | $clone->Set('virtual-pixel'=>'gray'); |
| 174 | $clone->Composite( |
| 175 | image=>$src, |
| 176 | compose=>'displace', |
| 177 | args=>'0,-80', |
| 178 | geometry=>$offset, |
| 179 | ); |
| 180 | push(@$results, $clone); |
| 181 | |
| 182 | # --------------- |
| 183 | # Demonstrate rotation |
| 184 | # note that offset is automatically adjusted to keep rotated image |
| 185 | # centered relative to its '0' rotation position |
| 186 | |
| 187 | $clone=$dest->Clone(); |
| 188 | $clone->Label('Rotate 0\n'); |
| 189 | $clone->Composite( |
| 190 | image=>$src, |
| 191 | compose=>'over', |
| 192 | rotate=>0, |
| 193 | background=>'none', |
| 194 | geometry=>$offset, |
| 195 | ); |
| 196 | push(@$results, $clone); |
| 197 | |
| 198 | $clone=$dest->Clone(); |
| 199 | $clone->Label('Rotate 10\n'); |
| 200 | $clone->Composite( |
| 201 | image=>$src, |
| 202 | compose=>'over', |
| 203 | rotate=>10, |
| 204 | background=>'none', |
| 205 | geometry=>$offset, |
| 206 | ); |
| 207 | push(@$results, $clone); |
| 208 | |
| 209 | $clone=$dest->Clone(); |
| 210 | $clone->Label('Rotate 45\n'); |
| 211 | $clone->Composite( |
| 212 | image=>$src, |
| 213 | compose=>'over', |
| 214 | rotate=>45, |
| 215 | background=>'none', |
| 216 | geometry=>$offset, |
| 217 | ); |
| 218 | push(@$results, $clone); |
| 219 | |
| 220 | $clone=$dest->Clone(); |
| 221 | $clone->Label('Rotate 90\n'); |
| 222 | $clone->Composite( |
| 223 | image=>$src, |
| 224 | compose=>'over', |
| 225 | rotate=>90, |
| 226 | background=>'none', |
| 227 | geometry=>$offset, |
| 228 | ); |
| 229 | push(@$results, $clone); |
| 230 | |
| 231 | # ---------------------------------------- |
| 232 | # Output the changed pixels |
| 233 | |
| 234 | # to every image underlay a checkboard pattern |
| 235 | # so as to show if any transparency is present |
| 236 | for my $image ( @$results ) { |
| 237 | $image->Composite( |
| 238 | image=>$texture, |
| 239 | tile=>'True', |
| 240 | compose=>'DstOver', |
| 241 | ); |
| 242 | } |
| 243 | |
| 244 | my $montage=$results->Montage( |
| 245 | geometry=>'+10+10', |
| 246 | tile=>'4x', |
| 247 | frame=>'6x6+2+2', |
| 248 | shadow=>'True', |
| 249 | ); |
| 250 | $montage->Write('show:'); |
| 251 | $montage->Write('compose_specials.jpg'); |
| 252 | |