| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package CAD::Drawing::Manipulate::Graphics; |
|
2
|
|
|
|
|
|
|
our $VERSION = '0.02'; |
|
3
|
|
|
|
|
|
|
|
|
4
|
2
|
|
|
2
|
|
96488
|
use CAD::Drawing; |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
use CAD::Drawing::Defined; |
|
6
|
|
|
|
|
|
|
use Image::Magick; |
|
7
|
|
|
|
|
|
|
push(@CAD::Drawing::ISA, __PACKAGE__); |
|
8
|
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
use warnings; |
|
10
|
|
|
|
|
|
|
use strict; |
|
11
|
|
|
|
|
|
|
use Carp; |
|
12
|
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
=pod |
|
14
|
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
=head1 Name |
|
16
|
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
CAD::Drawing::Manipulate::Graphics - Gimp meets CAD? |
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
=head1 AUTHOR |
|
20
|
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
Eric L. Wilhelm |
|
22
|
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
http://scratchcomputing.com |
|
24
|
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
=head1 COPYRIGHT |
|
26
|
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
This module is copyright (C) 2004-2006 by Eric L. Wilhelm. Portions |
|
28
|
|
|
|
|
|
|
copyright (C) 2003 by Eric L. Wilhelm and A. Zahner Co. |
|
29
|
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
=head1 LICENSE |
|
31
|
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
This module is distributed under the same terms as Perl. See the Perl |
|
33
|
|
|
|
|
|
|
source package for details. |
|
34
|
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
You may use this software under one of the following licenses: |
|
36
|
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
(1) GNU General Public License |
|
38
|
|
|
|
|
|
|
(found at http://www.gnu.org/copyleft/gpl.html) |
|
39
|
|
|
|
|
|
|
(2) Artistic License |
|
40
|
|
|
|
|
|
|
(found at http://www.perl.com/pub/language/misc/Artistic.html) |
|
41
|
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
=head1 NO WARRANTY |
|
43
|
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
This software is distributed with ABSOLUTELY NO WARRANTY. The author, |
|
45
|
|
|
|
|
|
|
his former employer, and any other contributors will in no way be held |
|
46
|
|
|
|
|
|
|
liable for any loss or damages resulting from its use. |
|
47
|
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
=head1 Modifications |
|
49
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
The source code of this module is made freely available and |
|
51
|
|
|
|
|
|
|
distributable under the GPL or Artistic License. Modifications to and |
|
52
|
|
|
|
|
|
|
use of this software must adhere to one of these licenses. Changes to |
|
53
|
|
|
|
|
|
|
the code should be noted as such and this notification (as well as the |
|
54
|
|
|
|
|
|
|
above copyright information) must remain intact on all copies of the |
|
55
|
|
|
|
|
|
|
code. |
|
56
|
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
Additionally, while the author is actively developing this code, |
|
58
|
|
|
|
|
|
|
notification of any intended changes or extensions would be most helpful |
|
59
|
|
|
|
|
|
|
in avoiding repeated work for all parties involved. Please contact the |
|
60
|
|
|
|
|
|
|
author with any such development plans. |
|
61
|
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
=cut |
|
63
|
|
|
|
|
|
|
######################################################################## |
|
64
|
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
=head1 Methods |
|
66
|
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
All of these are CAD::Drawing methods (I force my own inheritance:) |
|
68
|
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
=cut |
|
70
|
|
|
|
|
|
|
######################################################################## |
|
71
|
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
=head2 image_init |
|
73
|
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
Initialize the image at $addr based on the value at the fullpath key. |
|
75
|
|
|
|
|
|
|
This establishes the contained Image::Magick object and loads the image |
|
76
|
|
|
|
|
|
|
into memory in the image_handle key. |
|
77
|
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
$drw->image_init($addr); |
|
79
|
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
=cut |
|
81
|
|
|
|
|
|
|
sub image_init { |
|
82
|
|
|
|
|
|
|
my $self = shift; |
|
83
|
|
|
|
|
|
|
my ($addr) = @_; |
|
84
|
|
|
|
|
|
|
($addr->{type} eq "images") or croak("item is not an image\n"); |
|
85
|
|
|
|
|
|
|
my $obj = $self->getobj($addr); |
|
86
|
|
|
|
|
|
|
my $name = $obj->{fullpath}; |
|
87
|
|
|
|
|
|
|
(-e $name) or croak("$name does not exist\n"); |
|
88
|
|
|
|
|
|
|
# print "loading $name ...\n"; |
|
89
|
|
|
|
|
|
|
my $im = Image::Magick->new(); |
|
90
|
|
|
|
|
|
|
my $err = $im->Read($name); |
|
91
|
|
|
|
|
|
|
$err && carp("read $name gave $err\n"); |
|
92
|
|
|
|
|
|
|
$obj->{image_handle} = $im; |
|
93
|
|
|
|
|
|
|
} # end subroutine image_init definition |
|
94
|
|
|
|
|
|
|
######################################################################## |
|
95
|
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
=head2 image_crop |
|
97
|
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
Crops an image and its definition (actually, changes its insert point) |
|
99
|
|
|
|
|
|
|
according to the points given by @crop_points (which maybe had better be |
|
100
|
|
|
|
|
|
|
within the object (but I don't really sweat that.)) |
|
101
|
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
@crop_points should be in world coordinates as follows: |
|
103
|
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
@crop_points = ( |
|
105
|
|
|
|
|
|
|
[$lower_left_x , $lower_left_y ], |
|
106
|
|
|
|
|
|
|
[$upper_right_x, $upper_right_y], |
|
107
|
|
|
|
|
|
|
); |
|
108
|
|
|
|
|
|
|
# note that you can get these as |
|
109
|
|
|
|
|
|
|
# ($drw->getExtentsRec($something))[0,2] |
|
110
|
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
$drw->image_crop($addr, \@crop_points); |
|
112
|
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
=cut |
|
114
|
|
|
|
|
|
|
sub image_crop { |
|
115
|
|
|
|
|
|
|
my $dbg = 0; |
|
116
|
|
|
|
|
|
|
my $self = shift; |
|
117
|
|
|
|
|
|
|
my ($addr, $crp_pts) = @_; |
|
118
|
|
|
|
|
|
|
($addr->{type} eq "images") or croak("not an image\n"); |
|
119
|
|
|
|
|
|
|
my $obj = $self->getobj($addr); |
|
120
|
|
|
|
|
|
|
(ref($crp_pts) eq "ARRAY") or croak("$crp_pts is not array\n"); |
|
121
|
|
|
|
|
|
|
(@$crp_pts == 2) or croak("crop points should be 2\n"); |
|
122
|
|
|
|
|
|
|
# need upper left first |
|
123
|
|
|
|
|
|
|
my @crop_start = map({sprintf("%0.0f", $_)} |
|
124
|
|
|
|
|
|
|
$self->drw_to_img( |
|
125
|
|
|
|
|
|
|
[ |
|
126
|
|
|
|
|
|
|
$crp_pts->[0][0], # leftmost x |
|
127
|
|
|
|
|
|
|
$crp_pts->[1][1] # uppermost y |
|
128
|
|
|
|
|
|
|
], |
|
129
|
|
|
|
|
|
|
$addr) |
|
130
|
|
|
|
|
|
|
); |
|
131
|
|
|
|
|
|
|
my @crop_stop = map({sprintf("%0.0f", $_)} |
|
132
|
|
|
|
|
|
|
$self->drw_to_img( |
|
133
|
|
|
|
|
|
|
[ |
|
134
|
|
|
|
|
|
|
$crp_pts->[1][0], # rightmost x |
|
135
|
|
|
|
|
|
|
$crp_pts->[0][1] # lowermost y |
|
136
|
|
|
|
|
|
|
], |
|
137
|
|
|
|
|
|
|
$addr) |
|
138
|
|
|
|
|
|
|
); |
|
139
|
|
|
|
|
|
|
my @ext = map({$crop_stop[$_] - $crop_start[$_]} 0,1); |
|
140
|
|
|
|
|
|
|
my $im = $obj->{image_handle}; |
|
141
|
|
|
|
|
|
|
my @old_ext = $self->get_world_image_rectangle($addr); |
|
142
|
|
|
|
|
|
|
$dbg && print "old extents @{$obj->{size}}\n"; |
|
143
|
|
|
|
|
|
|
$dbg && print "new extents: @ext\n"; |
|
144
|
|
|
|
|
|
|
$dbg && print "start crop: @crop_start\n"; |
|
145
|
|
|
|
|
|
|
$dbg && print "stop crop: @crop_stop\n"; |
|
146
|
|
|
|
|
|
|
$im->Crop( |
|
147
|
|
|
|
|
|
|
width => $ext[0], height => $ext[1], |
|
148
|
|
|
|
|
|
|
x => $crop_start[0], y => $crop_start[1], |
|
149
|
|
|
|
|
|
|
); |
|
150
|
|
|
|
|
|
|
my @sz = $im->Get("width", "height"); |
|
151
|
|
|
|
|
|
|
$dbg && print "check: @sz\n"; |
|
152
|
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
# image processing does strange things, so we use the size reported |
|
154
|
|
|
|
|
|
|
# by Image::Magick to reset the insert point and size of the image |
|
155
|
|
|
|
|
|
|
my @new_base = ( |
|
156
|
|
|
|
|
|
|
$crop_start[0], |
|
157
|
|
|
|
|
|
|
$crop_start[1] + $sz[1], |
|
158
|
|
|
|
|
|
|
); |
|
159
|
|
|
|
|
|
|
my @new_pt = $self->img_to_drw(\@new_base, $addr); |
|
160
|
|
|
|
|
|
|
$dbg && print "old insert: @{$obj->{pt}}\n"; |
|
161
|
|
|
|
|
|
|
$dbg && print "new basepoint: @new_base at @new_pt\n"; |
|
162
|
|
|
|
|
|
|
$obj->{pt} = [@new_pt]; |
|
163
|
|
|
|
|
|
|
$obj->{size} = [@sz]; |
|
164
|
|
|
|
|
|
|
if(0) { |
|
165
|
|
|
|
|
|
|
my $check = CAD::Drawing->new(); |
|
166
|
|
|
|
|
|
|
$check->addpolygon(\@old_ext); |
|
167
|
|
|
|
|
|
|
$check->addrec($crp_pts, {color => "blue"}); |
|
168
|
|
|
|
|
|
|
$check->addpolygon( |
|
169
|
|
|
|
|
|
|
[$self->get_world_image_rectangle($addr)], {color => "red"} |
|
170
|
|
|
|
|
|
|
); |
|
171
|
|
|
|
|
|
|
$check->show(hang=>1); |
|
172
|
|
|
|
|
|
|
exit; |
|
173
|
|
|
|
|
|
|
} |
|
174
|
|
|
|
|
|
|
} # end subroutine image_crop definition |
|
175
|
|
|
|
|
|
|
######################################################################## |
|
176
|
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
=head2 image_scale |
|
178
|
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
Scales both the image and the definition by $scale, starting at |
|
180
|
|
|
|
|
|
|
@base_point. |
|
181
|
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
$drw->image_scale($addr, $scale, \@base_point); |
|
183
|
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
=cut |
|
185
|
|
|
|
|
|
|
sub image_scale { |
|
186
|
|
|
|
|
|
|
my $self = shift; |
|
187
|
|
|
|
|
|
|
my ($addr, $scale, $point) = @_; |
|
188
|
|
|
|
|
|
|
($addr->{type} eq "images") or croak("not an image\n"); |
|
189
|
|
|
|
|
|
|
# this sets only the insert: |
|
190
|
|
|
|
|
|
|
$self->Scale($addr, $scale, $point); |
|
191
|
|
|
|
|
|
|
# maybe not scale image here (punt like autoheck) |
|
192
|
|
|
|
|
|
|
my $obj = $self->getobj($addr); |
|
193
|
|
|
|
|
|
|
# really should put this in the manipulate code? |
|
194
|
|
|
|
|
|
|
$obj->{vector}[0][0] *=$scale; |
|
195
|
|
|
|
|
|
|
$obj->{vector}[1][1] *=$scale; |
|
196
|
|
|
|
|
|
|
print "vectors now $obj->{vector}[0][0], $obj->{vector}[1][1]\n"; |
|
197
|
|
|
|
|
|
|
} # end subroutine image_scale definition |
|
198
|
|
|
|
|
|
|
######################################################################## |
|
199
|
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
=head2 image_rotate |
|
201
|
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
This leaves the definition orthoganal, expands the underlying image |
|
203
|
|
|
|
|
|
|
object, and resets the insert point and size properties accordingly. |
|
204
|
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
$drw->image_rotate($addr, $angle, \@point); |
|
206
|
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
The current implementation does not handle the change to the image |
|
208
|
|
|
|
|
|
|
clipping boundary. |
|
209
|
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
=cut |
|
211
|
|
|
|
|
|
|
sub image_rotate { |
|
212
|
|
|
|
|
|
|
my $dbg = 0; |
|
213
|
|
|
|
|
|
|
my $check = 0; |
|
214
|
|
|
|
|
|
|
# FIXME: must be a better way to do this: |
|
215
|
|
|
|
|
|
|
my $bgcolor = "gold"; |
|
216
|
|
|
|
|
|
|
my $self = shift; |
|
217
|
|
|
|
|
|
|
my ($addr, $ang, $pt) = @_; |
|
218
|
|
|
|
|
|
|
($addr->{type} eq "images") or croak("not an image\n"); |
|
219
|
|
|
|
|
|
|
my $obj = $self->getobj($addr); |
|
220
|
|
|
|
|
|
|
my $im = $obj->{image_handle}; |
|
221
|
|
|
|
|
|
|
# Ben Franklin was retarded |
|
222
|
|
|
|
|
|
|
my $cw_deg_ang = $ang * -180 / $pi; |
|
223
|
|
|
|
|
|
|
# image rotates inside the box: |
|
224
|
|
|
|
|
|
|
$im->Rotate(degrees => $cw_deg_ang); |
|
225
|
|
|
|
|
|
|
# but now we have to change the box |
|
226
|
|
|
|
|
|
|
my ($w, $h) = $im->Get("width", "height"); |
|
227
|
|
|
|
|
|
|
$dbg && print "size now $w x $h\n"; |
|
228
|
|
|
|
|
|
|
# so we make a fake version of the image: |
|
229
|
|
|
|
|
|
|
my @pts = $self->get_world_image_rectangle($addr); |
|
230
|
|
|
|
|
|
|
print "points: \n\t", join("\n\t", map({join(",", @$_[0,1])} @pts)), "\n"; |
|
231
|
|
|
|
|
|
|
my $scrpad = CAD::Drawing->new(); |
|
232
|
|
|
|
|
|
|
my $box = $scrpad->addpolygon([map({[@$_]} @pts)]); |
|
233
|
|
|
|
|
|
|
# and rotate that |
|
234
|
|
|
|
|
|
|
$dbg && print "rotating about @$pt\n"; |
|
235
|
|
|
|
|
|
|
$scrpad->Rotate($box, $ang, $pt); |
|
236
|
|
|
|
|
|
|
print "points: \n\t", join("\n\t", map({join(",", @$_[0,1])} @pts)), "\n"; |
|
237
|
|
|
|
|
|
|
my @ext = $scrpad->getExtentsRec([$box]); |
|
238
|
|
|
|
|
|
|
$check && $scrpad->addcircle($pt, 10, {color => "red"}); |
|
239
|
|
|
|
|
|
|
$check && $scrpad->addpolygon(\@pts, {color => "green"}); |
|
240
|
|
|
|
|
|
|
$check && $scrpad->addpolygon(\@ext, {color => "red"}); |
|
241
|
|
|
|
|
|
|
$check && $scrpad->addcircle($ext[0], 5, {color => "blue"}); |
|
242
|
|
|
|
|
|
|
# so the lower-left of the extents is our new insert: |
|
243
|
|
|
|
|
|
|
my @insert = @{$ext[0]}; |
|
244
|
|
|
|
|
|
|
$obj->{pt} = [@insert]; |
|
245
|
|
|
|
|
|
|
$dbg && print "new insert: @insert\n"; |
|
246
|
|
|
|
|
|
|
$check && $scrpad->show(hang=>1); |
|
247
|
|
|
|
|
|
|
$check && exit; |
|
248
|
|
|
|
|
|
|
# set the size and we're done |
|
249
|
|
|
|
|
|
|
$obj->{size} = [$w, $h]; |
|
250
|
|
|
|
|
|
|
} # end subroutine image_rotate definition |
|
251
|
|
|
|
|
|
|
######################################################################## |
|
252
|
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
=head2 image_swap_context |
|
254
|
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
This involves a scaling of the image (the contexts should be aligned |
|
256
|
|
|
|
|
|
|
over each other at this point or everything will go to hell.) Do your |
|
257
|
|
|
|
|
|
|
own move / rotate / crop before calling this, because all this does is |
|
258
|
|
|
|
|
|
|
to scale the underlying image object such that the vec property of the |
|
259
|
|
|
|
|
|
|
image definition at $dest_addr can be used correctly. |
|
260
|
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
Note that this does not "swap" the image to $dest_addr, rather it uses |
|
262
|
|
|
|
|
|
|
the image definition of $dest_addr to change the image object and |
|
263
|
|
|
|
|
|
|
definition at $source_addr. |
|
264
|
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
Also note that the image must fit completely inside (I think) of the |
|
266
|
|
|
|
|
|
|
destination in order for the composite to work correctly. |
|
267
|
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
$drw->image_swap_context($source_addr, $dest_addr); |
|
269
|
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
=cut |
|
271
|
|
|
|
|
|
|
sub image_swap_context { |
|
272
|
|
|
|
|
|
|
my $dbg = 0; |
|
273
|
|
|
|
|
|
|
my $self = shift; |
|
274
|
|
|
|
|
|
|
my ($s_addr, $d_addr) = @_; |
|
275
|
|
|
|
|
|
|
my $bgcolor = "gold"; |
|
276
|
|
|
|
|
|
|
($s_addr->{type} eq "images") or croak("not an image\n"); |
|
277
|
|
|
|
|
|
|
($d_addr->{type} eq "images") or croak("not an image\n"); |
|
278
|
|
|
|
|
|
|
my $obj = $self->getobj($s_addr); |
|
279
|
|
|
|
|
|
|
# note: we will kill this one: |
|
280
|
|
|
|
|
|
|
my $im_in = $obj->{image_handle}; |
|
281
|
|
|
|
|
|
|
# determine the scale difference between the two definitions |
|
282
|
|
|
|
|
|
|
my $dvecs = $self->Get("vector", $d_addr); |
|
283
|
|
|
|
|
|
|
my $svecs = $self->Get("vector", $s_addr); |
|
284
|
|
|
|
|
|
|
my @scale = ( |
|
285
|
|
|
|
|
|
|
$dvecs->[0][0] / $svecs->[0][0], |
|
286
|
|
|
|
|
|
|
$dvecs->[1][1] / $svecs->[1][1], |
|
287
|
|
|
|
|
|
|
); |
|
288
|
|
|
|
|
|
|
$dbg && print "vecs scale at @scale\n"; |
|
289
|
|
|
|
|
|
|
my ($w, $h) = map({sprintf("%0.0f", $_ * $scale[0])} |
|
290
|
|
|
|
|
|
|
$im_in->Get("width", "height") |
|
291
|
|
|
|
|
|
|
); |
|
292
|
|
|
|
|
|
|
$im_in->Scale("width" => $w, "height" => $h); |
|
293
|
|
|
|
|
|
|
$dbg && print "size now $w x $h (hopefully)\n"; |
|
294
|
|
|
|
|
|
|
$dbg && print "checking: ", |
|
295
|
|
|
|
|
|
|
join(" x ", $im_in->Get("width", "height")), "\n"; |
|
296
|
|
|
|
|
|
|
# and set the vecs |
|
297
|
|
|
|
|
|
|
$obj->{vector} = [map({[@$_]} @$dvecs)]; |
|
298
|
|
|
|
|
|
|
# and the size |
|
299
|
|
|
|
|
|
|
$obj->{size} = [$w, $h]; |
|
300
|
|
|
|
|
|
|
# need to create a new image object which represents the destination |
|
301
|
|
|
|
|
|
|
# size and find the points where this one fits into that. |
|
302
|
|
|
|
|
|
|
my $d_size = $self->Get("size", $d_addr); |
|
303
|
|
|
|
|
|
|
my $im_out = Image::Magick->new(); |
|
304
|
|
|
|
|
|
|
$im_out->Set(size => sprintf("%0.0fx%0.0f", @$d_size)); |
|
305
|
|
|
|
|
|
|
$dbg && print "filling new image at @$d_size\n"; |
|
306
|
|
|
|
|
|
|
$im_out->Read("xc:$bgcolor"); |
|
307
|
|
|
|
|
|
|
$im_out->Transparent("color" => $bgcolor); |
|
308
|
|
|
|
|
|
|
# dot each corner for justification into other images |
|
309
|
|
|
|
|
|
|
my $color = $aci2hex[$self->Get("color", $s_addr)]; |
|
310
|
|
|
|
|
|
|
$dbg && print "output dot color: $color\n"; |
|
311
|
|
|
|
|
|
|
my $x = $d_size->[0] - 1; |
|
312
|
|
|
|
|
|
|
my $y = $d_size->[1] - 1; |
|
313
|
|
|
|
|
|
|
$im_out->Set("pixel[0,0]" => $color); |
|
314
|
|
|
|
|
|
|
$im_out->Set("pixel[$x,0]" => $color); |
|
315
|
|
|
|
|
|
|
$im_out->Set("pixel[0,$y]" => $color); |
|
316
|
|
|
|
|
|
|
$im_out->Set("pixel[$x,$y]" => $color); |
|
317
|
|
|
|
|
|
|
# determine placement from 0,0 of source mapped onto dest: |
|
318
|
|
|
|
|
|
|
my @placement = map({sprintf("%0.0f", $_)} |
|
319
|
|
|
|
|
|
|
$self->drw_to_img([$self->img_to_drw([0,0], $s_addr)], $d_addr) |
|
320
|
|
|
|
|
|
|
); |
|
321
|
|
|
|
|
|
|
$dbg && print "compositing...\n"; |
|
322
|
|
|
|
|
|
|
$im_out->Composite( |
|
323
|
|
|
|
|
|
|
compose => "Over", image => $im_in, |
|
324
|
|
|
|
|
|
|
x => $placement[0], y => $placement[1] |
|
325
|
|
|
|
|
|
|
); |
|
326
|
|
|
|
|
|
|
$dbg && print "done\n"; |
|
327
|
|
|
|
|
|
|
$obj->{image_handle} = $im_out; |
|
328
|
|
|
|
|
|
|
undef($im_in); |
|
329
|
|
|
|
|
|
|
# set the size, so it will be proper |
|
330
|
|
|
|
|
|
|
} # end subroutine image_swap_context definition |
|
331
|
|
|
|
|
|
|
######################################################################## |
|
332
|
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
1; |