]> git.imager.perl.org - imager.git/blob - samples/drop_shadow.pl
fix some old Changes typos
[imager.git] / samples / drop_shadow.pl
1 #!perl
2 use strict;
3 use Imager;
4 use Getopt::Long;
5
6 my $bg;
7 my $shadow_size = "10%";
8 my $offset = "0x0";
9 my $shadow_color = "#404040";
10
11 GetOptions(
12            "bg=s" => \$bg,
13            "size|s=s" => \$shadow_size,
14            "o|offset=s" => \$offset,
15            "s|shadow=s" => \$shadow_color,
16            );
17
18 my $infile = shift;
19 my $outfile = shift
20   or die <<EOS;
21 Usage: $0 [options] infile outfile
22 Options can be any or all of:
23  -bg color - fill the background with a color instead of using
24              transparency, this can be a translucent color.
25  -size size - size of the shadow in pixels, or percent of min dimension
26  -offset <xsize>x<ysize> - offset of the original image within the shadow
27  -shadow color - color of the shadow
28 EOS
29
30 my $src = Imager->new(file => $infile)
31   or die "Cannot read image file '$infile': ", Imager->errstr, "\n";
32
33 # simplify things by always working in RGB rather than grey
34 $src = $src->convert(preset => "rgb");
35
36 if ($shadow_size =~ /^([0-9]+)%$/) {
37   my $dim = $src->getwidth < $src->getheight ? $src->getwidth : $src->getheight;
38
39   $shadow_size = int($1 * $dim / 100 + 0.5);
40 }
41
42 my ($x_offset, $y_offset) = $offset =~ /^([+-]?[0-9]+)x([+-]?[0-9]+)$/
43   or die "$0: invalid offset\n";
44
45 my $shc = Imager::Color->new($shadow_color)
46   or die "$0: invalid shadow color: ", Imager->errstr, "\n";
47
48 my ($red, $green, $blue) = $shc->rgba;
49
50 # First create a new image, either with an alpha channel (if you want
51 # transparency behind the shadow) or without, if you want a background
52 # colour:
53
54 my $out = Imager->new
55   (
56    xsize => $shadow_size * 2 + $src->getwidth,
57    ysize => $shadow_size * 2 + $src->getheight,
58    channels => 4,
59   );
60
61 if ($bg) {
62   # fill it with your background color, if you want one
63   my $bgc = Imager::Color->new($bg)
64     or die "$0: invalid color '$bg'\n";
65   $out->box(filled => 1, color => $bgc);
66 }
67
68 # Make a work image to render the shadow on:
69 my $shadow_work = Imager->new
70   (
71    xsize => $out->getwidth,
72    ysize => $out->getheight,
73    channels => 1,
74   );
75
76 if ($src->getchannels == 4) {
77   # Extract the alpha channel from the source image, if the image has no
78   # alpha, then a solid box then it's simpler, first the alpha version:
79   my $alpha = $src->convert(preset => "alpha");
80
81   # and draw that on the work shadow:
82   $shadow_work->paste
83     (
84      src => $alpha,
85      left => $shadow_size,
86      top => $shadow_size,
87     );
88 }
89 else {
90   # otherwise just draw a box for the non-alpha source:
91
92   $shadow_work->box
93     (
94      filled => 1,
95      color => [ 255 ],
96      xmin => $shadow_size,
97      ymin => $shadow_size,
98      xmax => $shadow_size + $src->getwidth() - 1,
99      ymax => $shadow_size + $src->getheight() - 1,
100     );
101 }
102
103 # Blur the work shadow:
104
105 $shadow_work->filter(type => "gaussian", stddev => $shadow_size);
106
107 # Convert it to an RGB image with alpha:
108
109 $shadow_work = $shadow_work->convert
110   (
111    matrix => [ [ 0, $red / 255 ],
112                 [ 0, $green / 255 ],
113                 [ 0, $blue / 255 ],
114                 [ 1 ] ]
115   ) or die $shadow_work->errstr;
116
117 # Draw that on the output image:
118
119 $out->rubthrough(src => $shadow_work);
120
121 # Draw our original image on the output image, perhaps with an offset:
122 $out->rubthrough
123   (
124    src => $src,
125    tx => $shadow_size + $x_offset,
126    ty => $shadow_size + $y_offset,
127   );
128
129 $out->write(file => $outfile)
130   or die "Cannot write to '$outfile': ", $out->errstr, "\n";
131
132