| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
=head1 NAME |
|
2
|
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
XAO::ImageCache - Images caching by URLs stored in XAO::FS database |
|
4
|
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
6
|
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
use XAO::ImageCache; |
|
8
|
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
# Making new instance of Image Cache object |
|
10
|
|
|
|
|
|
|
my $image_Cache = XAO::ImageCache->new( |
|
11
|
|
|
|
|
|
|
list => $odb->fetch("/Products"), |
|
12
|
|
|
|
|
|
|
cache_path => "/var/httpd/shop/product/images/", |
|
13
|
|
|
|
|
|
|
cache_url => "/products/images/", |
|
14
|
|
|
|
|
|
|
source_url_key => "source_img", |
|
15
|
|
|
|
|
|
|
) || die "Can't make Image cache!"; |
|
16
|
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
# Init new empty Cache |
|
18
|
|
|
|
|
|
|
$image_cache->init() || die "Can't init new cache!"; |
|
19
|
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
# Start images checking and downloading to cache |
|
21
|
|
|
|
|
|
|
$image_cache->check(); |
|
22
|
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
24
|
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
When we store images links on own database we have no real |
|
26
|
|
|
|
|
|
|
images on own site. Some time it may be a problem cause images may |
|
27
|
|
|
|
|
|
|
have no right dimension or may be deleted from source site. |
|
28
|
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
XAO::ImageCache made for cache locally images his URL stored |
|
30
|
|
|
|
|
|
|
in XAO Founsation Server. Also, images may be resized automaticaly. |
|
31
|
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
This module provide easy methods to scan XAO Foundation Server data |
|
33
|
|
|
|
|
|
|
lists, to extract images source URLs from data objects, to download |
|
34
|
|
|
|
|
|
|
images to local cache, to resize a local copy of the image to fit into |
|
35
|
|
|
|
|
|
|
given dimensions and to store the new local URL of the image back to |
|
36
|
|
|
|
|
|
|
the data object. |
|
37
|
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
=head1 METHODS |
|
39
|
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
=over |
|
41
|
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
=cut |
|
43
|
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
############################################################################### |
|
45
|
|
|
|
|
|
|
package XAO::ImageCache; |
|
46
|
1
|
|
|
1
|
|
532
|
use strict; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
41
|
|
|
47
|
1
|
|
|
1
|
|
5
|
use Error qw(:try); |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
8
|
|
|
48
|
1
|
|
|
1
|
|
153
|
use XAO::Utils; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
49
|
|
|
49
|
1
|
|
|
1
|
|
385
|
use XAO::FS; |
|
|
1
|
|
|
|
|
57
|
|
|
|
1
|
|
|
|
|
23
|
|
|
50
|
1
|
|
|
1
|
|
4
|
use XAO::Errors qw(XAO::ImageCache); |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
7
|
|
|
51
|
1
|
|
|
1
|
|
280
|
use Digest::MD5 qw(md5 md5_hex md5_base64); |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
54
|
|
|
52
|
1
|
|
|
1
|
|
601
|
use LWP::UserAgent; |
|
|
1
|
|
|
|
|
34521
|
|
|
|
1
|
|
|
|
|
38
|
|
|
53
|
1
|
|
|
1
|
|
7
|
use URI; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
24
|
|
|
54
|
1
|
|
|
1
|
|
257
|
use Image::Magick; |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
use Date::Manip; |
|
56
|
|
|
|
|
|
|
use File::Path; |
|
57
|
|
|
|
|
|
|
use File::Copy; |
|
58
|
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
use vars qw($VERSION); |
|
60
|
|
|
|
|
|
|
$VERSION='1.20'; |
|
61
|
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
############################################################################### |
|
63
|
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
## |
|
65
|
|
|
|
|
|
|
# Methods prototypes |
|
66
|
|
|
|
|
|
|
# |
|
67
|
|
|
|
|
|
|
sub new ($%); |
|
68
|
|
|
|
|
|
|
sub init($); |
|
69
|
|
|
|
|
|
|
sub check($); |
|
70
|
|
|
|
|
|
|
sub download ($$); |
|
71
|
|
|
|
|
|
|
sub scale_file($$$$;$); |
|
72
|
|
|
|
|
|
|
sub scale_large($$$); |
|
73
|
|
|
|
|
|
|
sub scale_thumbnail($$$); |
|
74
|
|
|
|
|
|
|
sub remove_cache($); |
|
75
|
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
# Special functions |
|
77
|
|
|
|
|
|
|
sub get_filename($); |
|
78
|
|
|
|
|
|
|
sub treat_filename($); |
|
79
|
|
|
|
|
|
|
sub convert_time($); |
|
80
|
|
|
|
|
|
|
sub throw($$); |
|
81
|
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
############################################################################### |
|
83
|
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
sub DESTROY { |
|
85
|
|
|
|
|
|
|
my $self = shift; |
|
86
|
|
|
|
|
|
|
dprint "----- XAO Image Cache finished -----"; |
|
87
|
|
|
|
|
|
|
} |
|
88
|
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
############################################################################### |
|
90
|
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
=item new($%) |
|
92
|
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
The constructor returns a new C object. |
|
94
|
|
|
|
|
|
|
You can use it to make new images cache or check images |
|
95
|
|
|
|
|
|
|
of already existent cache. |
|
96
|
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
my $image_cache = XAO::ImageCache->new( |
|
98
|
|
|
|
|
|
|
cache_path => "cache", # set cache directory to './cache/' |
|
99
|
|
|
|
|
|
|
source_path => "cache/source", # set source directory to './cache/source/' |
|
100
|
|
|
|
|
|
|
local_path => "images/copy", # (optional) try to resolve local urls |
|
101
|
|
|
|
|
|
|
cache_url => "images/", # set cached images (relative) path to 'images/' |
|
102
|
|
|
|
|
|
|
list => $odb->fetch("/Products"), |
|
103
|
|
|
|
|
|
|
source_url_key => 'source_image_url', |
|
104
|
|
|
|
|
|
|
dest_url_key => 'dest_image_url', |
|
105
|
|
|
|
|
|
|
filename_key => 'product_id', |
|
106
|
|
|
|
|
|
|
min_width => 50, # Source image is ignored if smaller |
|
107
|
|
|
|
|
|
|
min_height => 50, |
|
108
|
|
|
|
|
|
|
size => { |
|
109
|
|
|
|
|
|
|
width => 320, |
|
110
|
|
|
|
|
|
|
height => 200, |
|
111
|
|
|
|
|
|
|
save_aspect_ratio => 1, |
|
112
|
|
|
|
|
|
|
}, |
|
113
|
|
|
|
|
|
|
thumbnails => { |
|
114
|
|
|
|
|
|
|
path => '/var/httpd/shop/product/images/tbn', |
|
115
|
|
|
|
|
|
|
url => '/products/images/tbn/' |
|
116
|
|
|
|
|
|
|
geometry => "25%", |
|
117
|
|
|
|
|
|
|
url_key => 'thumbnail_url', |
|
118
|
|
|
|
|
|
|
}, |
|
119
|
|
|
|
|
|
|
autocreate => 1, |
|
120
|
|
|
|
|
|
|
useragent => { |
|
121
|
|
|
|
|
|
|
agent => 'My Lovely Browser/v13.01', |
|
122
|
|
|
|
|
|
|
timeout => 30, |
|
123
|
|
|
|
|
|
|
}, |
|
124
|
|
|
|
|
|
|
force_download => 1, # to enforce re-downloads |
|
125
|
|
|
|
|
|
|
force_scale => 1, # to enforce re-scaling |
|
126
|
|
|
|
|
|
|
clear_on_error => 0, # don't clear DB properties even on permanent errors |
|
127
|
|
|
|
|
|
|
) || die "Image cache creation failure!"; |
|
128
|
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
A number of configuration parameters can be passed to |
|
130
|
|
|
|
|
|
|
XAO::ImageCache to tune functionality. |
|
131
|
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
=over |
|
133
|
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
=item autocreate |
|
135
|
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
=item cache_path |
|
137
|
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
=item cache_url |
|
139
|
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
=item clear_on_error |
|
141
|
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
=item dest_url_key |
|
143
|
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
=item force_download |
|
145
|
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
=item force_scale |
|
147
|
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
=item list |
|
149
|
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
=item source_url_key |
|
151
|
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
=item size |
|
153
|
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
=item thumbnails |
|
155
|
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
=item useragent |
|
157
|
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
=back |
|
159
|
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
Follow to L |
|
161
|
|
|
|
|
|
|
section to see what each parameter does. |
|
162
|
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
If any required parameter is not present an error will be thrown. |
|
164
|
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
=cut |
|
166
|
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
# |
|
168
|
|
|
|
|
|
|
# Creating new instance of Image Cache object. |
|
169
|
|
|
|
|
|
|
# |
|
170
|
|
|
|
|
|
|
# Parameters hash should contain following keys: |
|
171
|
|
|
|
|
|
|
# |
|
172
|
|
|
|
|
|
|
# cache_path => path to image cache directory |
|
173
|
|
|
|
|
|
|
# source_path => path to source image directory |
|
174
|
|
|
|
|
|
|
# cache_url => relative URL pointing to cached images |
|
175
|
|
|
|
|
|
|
# list => reference to XAO::DO::FS::List object |
|
176
|
|
|
|
|
|
|
# containing data elements with images data |
|
177
|
|
|
|
|
|
|
# source_url_key => source image url key name |
|
178
|
|
|
|
|
|
|
# filename_key => key name image and thumbnail file names will |
|
179
|
|
|
|
|
|
|
# be based on |
|
180
|
|
|
|
|
|
|
# |
|
181
|
|
|
|
|
|
|
# Optional parameters: |
|
182
|
|
|
|
|
|
|
# |
|
183
|
|
|
|
|
|
|
# dest_url_key => key name containing destination url name |
|
184
|
|
|
|
|
|
|
# size => { |
|
185
|
|
|
|
|
|
|
# width => |
|
186
|
|
|
|
|
|
|
# height => |
|
187
|
|
|
|
|
|
|
# } |
|
188
|
|
|
|
|
|
|
# autocreate => |
|
189
|
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
sub new ($%) { |
|
191
|
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
my $class = shift; |
|
193
|
|
|
|
|
|
|
my $self = {}; |
|
194
|
|
|
|
|
|
|
bless $self,$class; |
|
195
|
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
# Predefined parameters |
|
197
|
|
|
|
|
|
|
$self->{useragent} = { 'agent' => "XAO-ImageCache/$VERSION", }; |
|
198
|
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
# Passed parameters |
|
200
|
|
|
|
|
|
|
if (@_) { |
|
201
|
|
|
|
|
|
|
my %extra = @_; |
|
202
|
|
|
|
|
|
|
@$self{keys %extra} = values %extra; |
|
203
|
|
|
|
|
|
|
} |
|
204
|
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
# |
|
206
|
|
|
|
|
|
|
# Check required parameters |
|
207
|
|
|
|
|
|
|
# |
|
208
|
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
unless (defined($self->{source_path})) { |
|
210
|
|
|
|
|
|
|
$self->throw("- missing 'source_path' parameter!"); |
|
211
|
|
|
|
|
|
|
} |
|
212
|
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
unless (defined($self->{cache_path})) { |
|
214
|
|
|
|
|
|
|
$self->throw("- missing 'cache_path' parameter!"); |
|
215
|
|
|
|
|
|
|
} |
|
216
|
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
unless (defined($self->{list})) { |
|
218
|
|
|
|
|
|
|
$self->throw("- missing 'list' parameter!"); |
|
219
|
|
|
|
|
|
|
} |
|
220
|
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
unless (defined($self->{cache_url})){ |
|
222
|
|
|
|
|
|
|
$self->throw("- missing 'cache_url' parameter!") ; |
|
223
|
|
|
|
|
|
|
} |
|
224
|
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
unless (defined($self->{source_url_key})) { |
|
226
|
|
|
|
|
|
|
$self->throw("- missing 'source_url_key' parameter!"); |
|
227
|
|
|
|
|
|
|
} |
|
228
|
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
unless (defined($self->{dest_url_key})) { |
|
230
|
|
|
|
|
|
|
$self->throw("- missing 'dest_url_key' parameter!"); |
|
231
|
|
|
|
|
|
|
} |
|
232
|
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
# |
|
234
|
|
|
|
|
|
|
# Make sure paths end with / |
|
235
|
|
|
|
|
|
|
# |
|
236
|
|
|
|
|
|
|
$self->{'source_path'} .= '/' if $self->{'source_path'} !~ /\/$/; |
|
237
|
|
|
|
|
|
|
$self->{'cache_path'} .= '/' if $self->{'cache_path'} !~ /\/$/; |
|
238
|
|
|
|
|
|
|
$self->{'cache_url'} .= '/' if $self->{'cache_url'} !~ /\/$/; |
|
239
|
|
|
|
|
|
|
$self->{'thumbnails'}->{'cache_path'}.= '/' if $self->{'thumbnails'}->{'cache_path'} |
|
240
|
|
|
|
|
|
|
&& $self->{'thumbnails'}->{'cache_path'} !~ /\/$/; |
|
241
|
|
|
|
|
|
|
$self->{'thumbnails'}->{'cache_url'} .= '/' if $self->{'thumbnails'}->{'cache_url'} |
|
242
|
|
|
|
|
|
|
&& $self->{'thumbnails'}->{'cache_url'} !~ /\/$/; |
|
243
|
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
if (defined($self->{'min_period'}) && $self->{'min_period'}) { |
|
245
|
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
unless ($self->{'min_period'} =~ /\d+[smhd]/) { |
|
247
|
|
|
|
|
|
|
$self->throw("- incorrectly formatted 'min_period' parameter!"); |
|
248
|
|
|
|
|
|
|
} |
|
249
|
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
# Make sure 'min_period' parameters is in seconds |
|
251
|
|
|
|
|
|
|
$self->{'min_period'} =~ s/(\d+)([smhd])/$1/; |
|
252
|
|
|
|
|
|
|
if ($2 eq 'm') { |
|
253
|
|
|
|
|
|
|
$self->{'min_period'} *= 60; |
|
254
|
|
|
|
|
|
|
} |
|
255
|
|
|
|
|
|
|
elsif ($2 eq 'h') { |
|
256
|
|
|
|
|
|
|
$self->{'min_period'} *= 3600; |
|
257
|
|
|
|
|
|
|
} |
|
258
|
|
|
|
|
|
|
elsif ($2 eq 'd') { |
|
259
|
|
|
|
|
|
|
$self->{'min_period'} *= 86400; |
|
260
|
|
|
|
|
|
|
} |
|
261
|
|
|
|
|
|
|
} |
|
262
|
|
|
|
|
|
|
else { |
|
263
|
|
|
|
|
|
|
$self->{min_period} = 0; |
|
264
|
|
|
|
|
|
|
} |
|
265
|
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
$self->{'reload'}=1 if $self->{'force_download'}; |
|
267
|
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
$self->{'size'}->{'quality'}||=88; |
|
269
|
|
|
|
|
|
|
$self->{'thumbnails'}->{'quality'}||=88; |
|
270
|
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
# Make LWP::UserAgent instance |
|
272
|
|
|
|
|
|
|
my $hash_ref = $self->{'useragent'}; |
|
273
|
|
|
|
|
|
|
$self->{ua} = LWP::UserAgent->new( %$hash_ref) |
|
274
|
|
|
|
|
|
|
|| $self->throw("- LWP::UserAgent creation failure!"); |
|
275
|
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
$self->init() if defined($self->{autocreate} && $self->{autocreate}); |
|
277
|
|
|
|
|
|
|
$self; |
|
278
|
|
|
|
|
|
|
} |
|
279
|
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
############################################################################### |
|
281
|
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
=item init($) |
|
283
|
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
Cache structure initialization. |
|
285
|
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
Executed automaticaly if C parameter present. |
|
287
|
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
Create image cache directory if non existent and thumbnail cache |
|
289
|
|
|
|
|
|
|
directory if non existent and defined as initialization parameter. |
|
290
|
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
=cut |
|
292
|
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
sub init($) { |
|
294
|
|
|
|
|
|
|
my $self = shift; |
|
295
|
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
dprint "----- XAO Image Cache Initialization started -----"; |
|
297
|
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
my $source_path = $self->{source_path}; |
|
299
|
|
|
|
|
|
|
my $img_cache_path = $self->{cache_path}; |
|
300
|
|
|
|
|
|
|
my $thm_cache_path = $self->{thumbnails}->{cache_path}; |
|
301
|
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
# |
|
303
|
|
|
|
|
|
|
# Create directories if non existent |
|
304
|
|
|
|
|
|
|
# |
|
305
|
|
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
unless (-d $source_path) { |
|
307
|
|
|
|
|
|
|
mkdir($source_path,0777) |
|
308
|
|
|
|
|
|
|
|| $self->throw("- cache directory can't be created! $!"); |
|
309
|
|
|
|
|
|
|
dprint "Image Cache directory '$source_path' created."; |
|
310
|
|
|
|
|
|
|
} |
|
311
|
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
unless (-d $img_cache_path) { |
|
313
|
|
|
|
|
|
|
mkdir($img_cache_path,0777) |
|
314
|
|
|
|
|
|
|
|| $self->throw("- cache directory can't be created! $!"); |
|
315
|
|
|
|
|
|
|
dprint "Image Cache directory '$img_cache_path' created."; |
|
316
|
|
|
|
|
|
|
} |
|
317
|
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
if ($thm_cache_path) { |
|
319
|
|
|
|
|
|
|
unless (-d $thm_cache_path) { |
|
320
|
|
|
|
|
|
|
mkdir($thm_cache_path, 0777) |
|
321
|
|
|
|
|
|
|
|| $self->throw("- can't create thumbnails cache directory ($thm_cache_path)! $!"); |
|
322
|
|
|
|
|
|
|
dprint "Thumbnail Cache directory '$thm_cache_path' created."; |
|
323
|
|
|
|
|
|
|
} |
|
324
|
|
|
|
|
|
|
} |
|
325
|
|
|
|
|
|
|
|
|
326
|
|
|
|
|
|
|
$self->check() if defined($self->{autocreate} && $self->{autocreate}); |
|
327
|
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
return 1; |
|
329
|
|
|
|
|
|
|
} |
|
330
|
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
############################################################################### |
|
332
|
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
=item check($) |
|
334
|
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
Goes through given XAO FS data list, downloads images from source url |
|
336
|
|
|
|
|
|
|
to cache and puts cache url into destination url key and thumbnail url |
|
337
|
|
|
|
|
|
|
key (where applicable). |
|
338
|
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
XAO::ImageCache->download() will be executed for downloading each image. |
|
340
|
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
=cut |
|
342
|
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
sub check($) { |
|
344
|
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
my $self = shift; |
|
346
|
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
my $img_src_url_key = $self->{'source_url_key'}; |
|
348
|
|
|
|
|
|
|
my $img_dest_url_key = $self->{'dest_url_key'}; |
|
349
|
|
|
|
|
|
|
my $img_cache_url = $self->{'cache_url'}; |
|
350
|
|
|
|
|
|
|
my $thm_src_url_key = $self->{'thumbnails'}->{'source_url_key'} || ''; |
|
351
|
|
|
|
|
|
|
my $thm_dest_url_key = $self->{'thumbnails'}->{'dest_url_key'} || ''; |
|
352
|
|
|
|
|
|
|
my $thm_cache_url = $self->{'thumbnails'}->{'cache_url'} || ''; |
|
353
|
|
|
|
|
|
|
my $thm_cache_path = $self->{'thumbnails'}->{'cache_path'} || ''; |
|
354
|
|
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
my $getter=$self->{'get_property_sub'} || sub ($$) { |
|
356
|
|
|
|
|
|
|
my ($obj,$prop)=@_; |
|
357
|
|
|
|
|
|
|
return $prop ? $obj->get($prop) : ''; |
|
358
|
|
|
|
|
|
|
}; |
|
359
|
|
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
my $checked = 0; |
|
361
|
|
|
|
|
|
|
my $list = $self->{'list'}; |
|
362
|
|
|
|
|
|
|
my $list_keys = $self->{'list_keys'} || [ $list->keys ]; |
|
363
|
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
my $count=0; |
|
365
|
|
|
|
|
|
|
my $total=scalar(@$list_keys); |
|
366
|
|
|
|
|
|
|
foreach my $item_id (@$list_keys) { |
|
367
|
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
dprint "Checking ID='$item_id', count=".$count++."/$total"; |
|
369
|
|
|
|
|
|
|
|
|
370
|
|
|
|
|
|
|
my $item = $list->get($item_id); |
|
371
|
|
|
|
|
|
|
my $img_src_url = $getter->($item,$img_src_url_key); |
|
372
|
|
|
|
|
|
|
my $thm_src_url = $getter->($item,$thm_src_url_key); |
|
373
|
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
# Skipping products without images |
|
375
|
|
|
|
|
|
|
# |
|
376
|
|
|
|
|
|
|
next unless $img_src_url || $thm_src_url; |
|
377
|
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
# Download source image and create cache image and thumbnail |
|
379
|
|
|
|
|
|
|
# |
|
380
|
|
|
|
|
|
|
try { |
|
381
|
|
|
|
|
|
|
my ($img_cache_file, $thm_cache_file)=$self->download( |
|
382
|
|
|
|
|
|
|
$item, |
|
383
|
|
|
|
|
|
|
$img_src_url, |
|
384
|
|
|
|
|
|
|
$thm_src_url, |
|
385
|
|
|
|
|
|
|
); |
|
386
|
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
dprint ".storing('$img_cache_file','$thm_cache_file')"; |
|
388
|
|
|
|
|
|
|
my %d; |
|
389
|
|
|
|
|
|
|
$d{$img_dest_url_key}=$img_cache_url.$img_cache_file if $img_dest_url_key; |
|
390
|
|
|
|
|
|
|
$d{$thm_dest_url_key}=$thm_cache_url.$thm_cache_file if $thm_dest_url_key; |
|
391
|
|
|
|
|
|
|
$item->put(\%d); |
|
392
|
|
|
|
|
|
|
} |
|
393
|
|
|
|
|
|
|
otherwise { |
|
394
|
|
|
|
|
|
|
my $e=shift; |
|
395
|
|
|
|
|
|
|
eprint "$e"; |
|
396
|
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
# We don't update the item unless this is a permanent error |
|
398
|
|
|
|
|
|
|
# and we have a 'clear_on_error' argument. |
|
399
|
|
|
|
|
|
|
# |
|
400
|
|
|
|
|
|
|
if("$e" =~ /PERMANENT/) { |
|
401
|
|
|
|
|
|
|
if($self->{'clear_on_error'}) { |
|
402
|
|
|
|
|
|
|
dprint ".permanent error - clearing existing image/thumbnail urls"; |
|
403
|
|
|
|
|
|
|
my %d; |
|
404
|
|
|
|
|
|
|
$d{$img_dest_url_key}='' if $img_dest_url_key; |
|
405
|
|
|
|
|
|
|
$d{$thm_dest_url_key}='' if $thm_dest_url_key; |
|
406
|
|
|
|
|
|
|
$item->put(\%d); |
|
407
|
|
|
|
|
|
|
} |
|
408
|
|
|
|
|
|
|
} |
|
409
|
|
|
|
|
|
|
}; |
|
410
|
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
$checked++; |
|
412
|
|
|
|
|
|
|
} |
|
413
|
|
|
|
|
|
|
|
|
414
|
|
|
|
|
|
|
return $checked; |
|
415
|
|
|
|
|
|
|
} |
|
416
|
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
############################################################################### |
|
418
|
|
|
|
|
|
|
|
|
419
|
|
|
|
|
|
|
=item download($$) |
|
420
|
|
|
|
|
|
|
|
|
421
|
|
|
|
|
|
|
Downloads image into cache directory. |
|
422
|
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
If C contains C parameter, thumbnail is either |
|
424
|
|
|
|
|
|
|
downloaded into thumbnail cache directory or created from downloaded |
|
425
|
|
|
|
|
|
|
image. |
|
426
|
|
|
|
|
|
|
|
|
427
|
|
|
|
|
|
|
Source image URL should be passed as parameter. Source thumbnail URL is |
|
428
|
|
|
|
|
|
|
an optional parameter: |
|
429
|
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
$img_cache->download($image_source_url, $thumbnail_source_url); |
|
431
|
|
|
|
|
|
|
|
|
432
|
|
|
|
|
|
|
Downloaded image is resized if C parameter present. Thumbnail is |
|
433
|
|
|
|
|
|
|
resized as specified by C C parameter. |
|
434
|
|
|
|
|
|
|
|
|
435
|
|
|
|
|
|
|
When C configuration parameter is not set to True value, image |
|
436
|
|
|
|
|
|
|
will be downloaded into cache only if image is not already cached or if |
|
437
|
|
|
|
|
|
|
cached image has a later modification date than source image. |
|
438
|
|
|
|
|
|
|
|
|
439
|
|
|
|
|
|
|
=cut |
|
440
|
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
sub download ($$) { |
|
442
|
|
|
|
|
|
|
my ($self, $item, $img_src_url, $thm_src_url) = @_; |
|
443
|
|
|
|
|
|
|
|
|
444
|
|
|
|
|
|
|
my $fnm_key = $self->{filename_key} || ''; |
|
445
|
|
|
|
|
|
|
my $base_fnm = $fnm_key ? treat_filename($item->get($fnm_key)) |
|
446
|
|
|
|
|
|
|
: get_filename($img_src_url); |
|
447
|
|
|
|
|
|
|
my $img_fnm = $img_src_url ? $base_fnm.'_img.jpeg' : ''; |
|
448
|
|
|
|
|
|
|
my $img_src_fnm = $img_src_url ? $base_fnm.'_src.jpeg' : ''; |
|
449
|
|
|
|
|
|
|
|
|
450
|
|
|
|
|
|
|
my $user_agent = $self->{ua}; |
|
451
|
|
|
|
|
|
|
my $source_path = $self->{source_path}; |
|
452
|
|
|
|
|
|
|
my $img_cache_path = $self->{cache_path}; |
|
453
|
|
|
|
|
|
|
my $thm_cache_path = $self->{thumbnails}->{cache_path} || ''; |
|
454
|
|
|
|
|
|
|
|
|
455
|
|
|
|
|
|
|
## |
|
456
|
|
|
|
|
|
|
# Local path can be a reference to an array of paths |
|
457
|
|
|
|
|
|
|
# |
|
458
|
|
|
|
|
|
|
my $local_path=$self->{'local_path'} || ''; |
|
459
|
|
|
|
|
|
|
$local_path=[ $local_path ] unless ref($local_path); |
|
460
|
|
|
|
|
|
|
|
|
461
|
|
|
|
|
|
|
my $img_src_file = $source_path.$img_src_fnm; |
|
462
|
|
|
|
|
|
|
my $img_cache_file = $img_cache_path.$img_fnm; |
|
463
|
|
|
|
|
|
|
|
|
464
|
|
|
|
|
|
|
my ($thm_fnm, $thm_cache_file, $thm_src_file); |
|
465
|
|
|
|
|
|
|
if ($thm_cache_path) { |
|
466
|
|
|
|
|
|
|
$thm_fnm = $thm_src_url ? get_filename($thm_src_url) : $base_fnm; |
|
467
|
|
|
|
|
|
|
my $thm_src_fnm = $thm_fnm.'_thmsrc.jpeg'; |
|
468
|
|
|
|
|
|
|
$thm_fnm .= '_thm.jpeg'; |
|
469
|
|
|
|
|
|
|
$thm_cache_file = $thm_cache_path.$thm_fnm; |
|
470
|
|
|
|
|
|
|
$thm_src_file = $source_path.$thm_src_fnm; |
|
471
|
|
|
|
|
|
|
} |
|
472
|
|
|
|
|
|
|
|
|
473
|
|
|
|
|
|
|
# Download thumbnail if specified and resize (keep source and |
|
474
|
|
|
|
|
|
|
# resized images). If the file is missed in the cache, but it |
|
475
|
|
|
|
|
|
|
# exists in the sources and is actual -- then resizing it without |
|
476
|
|
|
|
|
|
|
# downloading. |
|
477
|
|
|
|
|
|
|
# |
|
478
|
|
|
|
|
|
|
my $time_now = time; |
|
479
|
|
|
|
|
|
|
if($thm_cache_path && $thm_src_url) { |
|
480
|
|
|
|
|
|
|
my $mtime_src = (stat($thm_src_file))[9]; |
|
481
|
|
|
|
|
|
|
my $period = $time_now - $mtime_src; |
|
482
|
|
|
|
|
|
|
if($period > $self->{'min_period'}) { |
|
483
|
|
|
|
|
|
|
if($thm_src_url !~ m/^(https?|ftp):\/\//i) { |
|
484
|
|
|
|
|
|
|
my $lfound; |
|
485
|
|
|
|
|
|
|
if($thm_src_url=~/^\// && -r $thm_src_url) { |
|
486
|
|
|
|
|
|
|
$lfound=1; |
|
487
|
|
|
|
|
|
|
copy($thm_src_url,$thm_src_file); |
|
488
|
|
|
|
|
|
|
} |
|
489
|
|
|
|
|
|
|
else { |
|
490
|
|
|
|
|
|
|
foreach my $lpath (@$local_path) { |
|
491
|
|
|
|
|
|
|
if(-r "$lpath/$thm_src_url") { |
|
492
|
|
|
|
|
|
|
copy("$lpath/$thm_src_url",$thm_src_file); |
|
493
|
|
|
|
|
|
|
$lfound=1; |
|
494
|
|
|
|
|
|
|
last; |
|
495
|
|
|
|
|
|
|
} |
|
496
|
|
|
|
|
|
|
} |
|
497
|
|
|
|
|
|
|
} |
|
498
|
|
|
|
|
|
|
if(!$lfound) { |
|
499
|
|
|
|
|
|
|
$self->throw("- seems to be a local URL and no local file ($thm_src_url)"); |
|
500
|
|
|
|
|
|
|
} |
|
501
|
|
|
|
|
|
|
} |
|
502
|
|
|
|
|
|
|
else { |
|
503
|
|
|
|
|
|
|
my $response = $user_agent->head($thm_src_url); |
|
504
|
|
|
|
|
|
|
if ($response->is_success) { |
|
505
|
|
|
|
|
|
|
my $mtime_web = convert_time($response->header('Last-Modified')); |
|
506
|
|
|
|
|
|
|
if ((!-r $thm_src_file) || ($mtime_src < $mtime_web) || $self->{'reload'} || $self->{'force_download'}) { |
|
507
|
|
|
|
|
|
|
$self->download_file($thm_src_url, $thm_src_file); |
|
508
|
|
|
|
|
|
|
} |
|
509
|
|
|
|
|
|
|
} |
|
510
|
|
|
|
|
|
|
else { |
|
511
|
|
|
|
|
|
|
if(-r $thm_src_file) { |
|
512
|
|
|
|
|
|
|
dprint "...error downloading thumbnail (".$response->status_line."), keeping existing source $thm_src_file"; |
|
513
|
|
|
|
|
|
|
} |
|
514
|
|
|
|
|
|
|
else { |
|
515
|
|
|
|
|
|
|
$self->throw("- can't get thumbnail header '$thm_src_url' - ".$response->status_line." (NETWORK)"); |
|
516
|
|
|
|
|
|
|
$thm_src_file = ''; |
|
517
|
|
|
|
|
|
|
} |
|
518
|
|
|
|
|
|
|
} |
|
519
|
|
|
|
|
|
|
} |
|
520
|
|
|
|
|
|
|
} |
|
521
|
|
|
|
|
|
|
else { |
|
522
|
|
|
|
|
|
|
dprint ".thumbnail source file current: $thm_src_url"; |
|
523
|
|
|
|
|
|
|
} |
|
524
|
|
|
|
|
|
|
|
|
525
|
|
|
|
|
|
|
# Resizing if required |
|
526
|
|
|
|
|
|
|
# |
|
527
|
|
|
|
|
|
|
if($thm_src_file) { |
|
528
|
|
|
|
|
|
|
my $mtime_cache=(stat($thm_cache_file))[9]; |
|
529
|
|
|
|
|
|
|
$mtime_src=(stat($thm_src_file))[9]; |
|
530
|
|
|
|
|
|
|
if($mtime_cache<=$mtime_src) { |
|
531
|
|
|
|
|
|
|
$self->scale_thumbnail($thm_src_file, $thm_cache_file); |
|
532
|
|
|
|
|
|
|
} |
|
533
|
|
|
|
|
|
|
} |
|
534
|
|
|
|
|
|
|
} |
|
535
|
|
|
|
|
|
|
|
|
536
|
|
|
|
|
|
|
# Download source image and resize (keep source and resized |
|
537
|
|
|
|
|
|
|
# images). Only download source image if cached image not present or |
|
538
|
|
|
|
|
|
|
# older than source. |
|
539
|
|
|
|
|
|
|
# |
|
540
|
|
|
|
|
|
|
if($img_src_url) { |
|
541
|
|
|
|
|
|
|
my $mtime_src = (stat($img_src_file))[9] || 0; |
|
542
|
|
|
|
|
|
|
my $period = $time_now - $mtime_src; |
|
543
|
|
|
|
|
|
|
if($self->{'force_download'} || $period>$self->{'min_period'}) { |
|
544
|
|
|
|
|
|
|
if($img_src_url !~ m/^(https?|ftp):\/\//i) { |
|
545
|
|
|
|
|
|
|
my $lfound; |
|
546
|
|
|
|
|
|
|
if($img_src_url=~/^\// && -r $img_src_url) { |
|
547
|
|
|
|
|
|
|
$lfound=1; |
|
548
|
|
|
|
|
|
|
copy($img_src_url,$img_src_file); |
|
549
|
|
|
|
|
|
|
} |
|
550
|
|
|
|
|
|
|
else { |
|
551
|
|
|
|
|
|
|
foreach my $lpath (@$local_path) { |
|
552
|
|
|
|
|
|
|
if(-r "$lpath/$img_src_url") { |
|
553
|
|
|
|
|
|
|
copy("$lpath/$img_src_url",$img_src_file); |
|
554
|
|
|
|
|
|
|
$lfound=1; |
|
555
|
|
|
|
|
|
|
last; |
|
556
|
|
|
|
|
|
|
} |
|
557
|
|
|
|
|
|
|
} |
|
558
|
|
|
|
|
|
|
} |
|
559
|
|
|
|
|
|
|
if(!$lfound) { |
|
560
|
|
|
|
|
|
|
$self->throw("- seems to be a local URL and no local file ($img_src_url)"); |
|
561
|
|
|
|
|
|
|
} |
|
562
|
|
|
|
|
|
|
} |
|
563
|
|
|
|
|
|
|
else { |
|
564
|
|
|
|
|
|
|
my $response = $user_agent->head($img_src_url); |
|
565
|
|
|
|
|
|
|
if ($response->is_success) { |
|
566
|
|
|
|
|
|
|
my $mtime_web = convert_time($response->header('Last-Modified')); |
|
567
|
|
|
|
|
|
|
if ((!-r $img_src_file) || ($mtime_src < $mtime_web) || $self->{'reload'} || $self->{'force_download'}) { |
|
568
|
|
|
|
|
|
|
$self->download_file($img_src_url, $img_src_file); |
|
569
|
|
|
|
|
|
|
} |
|
570
|
|
|
|
|
|
|
else { |
|
571
|
|
|
|
|
|
|
dprint ".image source file current: $img_src_url"; |
|
572
|
|
|
|
|
|
|
} |
|
573
|
|
|
|
|
|
|
} |
|
574
|
|
|
|
|
|
|
else { |
|
575
|
|
|
|
|
|
|
|
|
576
|
|
|
|
|
|
|
# This is here mainly for situations like this: a |
|
577
|
|
|
|
|
|
|
# superseded item content gets into a new item, but |
|
578
|
|
|
|
|
|
|
# the image URL is long gone, not accessible; we |
|
579
|
|
|
|
|
|
|
# have a cached copy and we use it. |
|
580
|
|
|
|
|
|
|
# |
|
581
|
|
|
|
|
|
|
if(-r $img_src_file) { |
|
582
|
|
|
|
|
|
|
dprint "...error downloading image (".$response->status_line."), keeping existing source $thm_src_file"; |
|
583
|
|
|
|
|
|
|
} |
|
584
|
|
|
|
|
|
|
else { |
|
585
|
|
|
|
|
|
|
$self->throw("- can't get image header for $img_src_url - ".$response->status_line." (NETWORK)"); |
|
586
|
|
|
|
|
|
|
$img_src_file = ''; |
|
587
|
|
|
|
|
|
|
} |
|
588
|
|
|
|
|
|
|
} |
|
589
|
|
|
|
|
|
|
} |
|
590
|
|
|
|
|
|
|
$mtime_src=(stat($img_src_file))[9] if $img_src_file; |
|
591
|
|
|
|
|
|
|
} |
|
592
|
|
|
|
|
|
|
|
|
593
|
|
|
|
|
|
|
if($img_src_file) { |
|
594
|
|
|
|
|
|
|
|
|
595
|
|
|
|
|
|
|
# Now checking if the source file we have is newer then what's in |
|
596
|
|
|
|
|
|
|
# the cache and updating the cache in that case. |
|
597
|
|
|
|
|
|
|
# |
|
598
|
|
|
|
|
|
|
my $mtime_cache=(stat($img_cache_file))[9] || 0; |
|
599
|
|
|
|
|
|
|
if($self->{'force_scale'} || $mtime_cache < $mtime_src) { |
|
600
|
|
|
|
|
|
|
$self->scale_large($img_src_file, $img_cache_file); |
|
601
|
|
|
|
|
|
|
} |
|
602
|
|
|
|
|
|
|
|
|
603
|
|
|
|
|
|
|
# Create thumbnail from the image source file if necessary |
|
604
|
|
|
|
|
|
|
# |
|
605
|
|
|
|
|
|
|
if($thm_cache_file && (!$thm_src_url || !$thm_src_file)) { |
|
606
|
|
|
|
|
|
|
$mtime_cache=(stat($thm_cache_file))[9] || 0; |
|
607
|
|
|
|
|
|
|
if($self->{'force_scale'} || $mtime_cache < $mtime_src) { |
|
608
|
|
|
|
|
|
|
$self->scale_thumbnail($img_src_file,$thm_cache_file); |
|
609
|
|
|
|
|
|
|
} |
|
610
|
|
|
|
|
|
|
$thm_src_file=1; # Just to mark that we have it |
|
611
|
|
|
|
|
|
|
} |
|
612
|
|
|
|
|
|
|
} |
|
613
|
|
|
|
|
|
|
} |
|
614
|
|
|
|
|
|
|
|
|
615
|
|
|
|
|
|
|
$img_fnm='' unless $img_src_file; |
|
616
|
|
|
|
|
|
|
$thm_fnm='' unless $thm_src_file; |
|
617
|
|
|
|
|
|
|
|
|
618
|
|
|
|
|
|
|
### dprint "...scaled->('$img_fnm','$thm_fnm')"; |
|
619
|
|
|
|
|
|
|
|
|
620
|
|
|
|
|
|
|
return ($img_fnm, $thm_fnm); |
|
621
|
|
|
|
|
|
|
} |
|
622
|
|
|
|
|
|
|
|
|
623
|
|
|
|
|
|
|
############################################################################### |
|
624
|
|
|
|
|
|
|
|
|
625
|
|
|
|
|
|
|
sub download_file { |
|
626
|
|
|
|
|
|
|
my $self = shift; |
|
627
|
|
|
|
|
|
|
my $source_url = shift; |
|
628
|
|
|
|
|
|
|
my $source_file = shift; |
|
629
|
|
|
|
|
|
|
|
|
630
|
|
|
|
|
|
|
dprint "DOWNLOAD ($source_url)->($source_file)"; |
|
631
|
|
|
|
|
|
|
|
|
632
|
|
|
|
|
|
|
my $response=$self->{'ua'}->get($source_url); |
|
633
|
|
|
|
|
|
|
my $errstr; |
|
634
|
|
|
|
|
|
|
if($response->is_success) { |
|
635
|
|
|
|
|
|
|
if($response->content_type =~ /^image\//) { |
|
636
|
|
|
|
|
|
|
open(F,"> $source_file.tmp") || $self->throw("- unable to save file '$source_file': $!"); |
|
637
|
|
|
|
|
|
|
binmode(F); |
|
638
|
|
|
|
|
|
|
print F $response->content; |
|
639
|
|
|
|
|
|
|
close(F); |
|
640
|
|
|
|
|
|
|
rename("$source_file.tmp",$source_file); |
|
641
|
|
|
|
|
|
|
} |
|
642
|
|
|
|
|
|
|
else { |
|
643
|
|
|
|
|
|
|
$errstr="downloaded '$source_url' is not an image (".$response->content_type.") (PERMANENT)"; |
|
644
|
|
|
|
|
|
|
} |
|
645
|
|
|
|
|
|
|
} |
|
646
|
|
|
|
|
|
|
else { |
|
647
|
|
|
|
|
|
|
$errstr="can't download '$source_url' - ".$response->status_line." (NETWORK)"; |
|
648
|
|
|
|
|
|
|
} |
|
649
|
|
|
|
|
|
|
|
|
650
|
|
|
|
|
|
|
return unless $errstr; |
|
651
|
|
|
|
|
|
|
|
|
652
|
|
|
|
|
|
|
# If the file is already there (from previous downloads then just |
|
653
|
|
|
|
|
|
|
# printing the error, but returning normally to let the file be scaled and |
|
654
|
|
|
|
|
|
|
# stored as image/thumbnail |
|
655
|
|
|
|
|
|
|
# |
|
656
|
|
|
|
|
|
|
if(-f $source_file && !$self->{'clear_on_error'}) { |
|
657
|
|
|
|
|
|
|
eprint "download_file: $errstr -- ignoring and keeping existing file"; |
|
658
|
|
|
|
|
|
|
return; |
|
659
|
|
|
|
|
|
|
} |
|
660
|
|
|
|
|
|
|
else { |
|
661
|
|
|
|
|
|
|
$self->throw("- $errstr"); |
|
662
|
|
|
|
|
|
|
} |
|
663
|
|
|
|
|
|
|
} |
|
664
|
|
|
|
|
|
|
|
|
665
|
|
|
|
|
|
|
############################################################################### |
|
666
|
|
|
|
|
|
|
|
|
667
|
|
|
|
|
|
|
sub scale_file ($$$$;$) { |
|
668
|
|
|
|
|
|
|
my ($self,$infile,$outfile,$params,$label)=@_; |
|
669
|
|
|
|
|
|
|
|
|
670
|
|
|
|
|
|
|
$label||='unknown'; |
|
671
|
|
|
|
|
|
|
|
|
672
|
|
|
|
|
|
|
if(!$params) { |
|
673
|
|
|
|
|
|
|
dprint "Copying $infile to $outfile as is ($label)"; |
|
674
|
|
|
|
|
|
|
copy($infile,$outfile); |
|
675
|
|
|
|
|
|
|
return; |
|
676
|
|
|
|
|
|
|
} |
|
677
|
|
|
|
|
|
|
|
|
678
|
|
|
|
|
|
|
my $geometry = ''; # image dimensions in ImageMagick geometry format |
|
679
|
|
|
|
|
|
|
|
|
680
|
|
|
|
|
|
|
my $image = Image::Magick->new() || $self->throw("- Image::Magick creation failure!"); |
|
681
|
|
|
|
|
|
|
my $err = $image->ReadImage($infile); |
|
682
|
|
|
|
|
|
|
### dprint ".source in '$infile'"; |
|
683
|
|
|
|
|
|
|
|
|
684
|
|
|
|
|
|
|
# Only throwing an error if no image was read. If we consider all |
|
685
|
|
|
|
|
|
|
# warnings as errors then some 3M tiff files don't parse. |
|
686
|
|
|
|
|
|
|
# |
|
687
|
|
|
|
|
|
|
# From http://www.imagemagick.org/script/perl-magick.php: |
|
688
|
|
|
|
|
|
|
# |
|
689
|
|
|
|
|
|
|
# $x = $image->Read(...); |
|
690
|
|
|
|
|
|
|
# warn "$x" if "$x"; # print the error message |
|
691
|
|
|
|
|
|
|
# $x =~ /(\d+)/; |
|
692
|
|
|
|
|
|
|
# print $1; # print the error number |
|
693
|
|
|
|
|
|
|
# print 0+$x; # print the number of images read |
|
694
|
|
|
|
|
|
|
# |
|
695
|
|
|
|
|
|
|
### $self->throw("- parsing error ($err) (PERMANENT)") if $err; |
|
696
|
|
|
|
|
|
|
(0 + $err)>0 || |
|
697
|
|
|
|
|
|
|
$self->throw("- parsing error ($err) (PERMANENT)"); |
|
698
|
|
|
|
|
|
|
|
|
699
|
|
|
|
|
|
|
# We only deal with image/* types -- otherwise ImageMagick can |
|
700
|
|
|
|
|
|
|
# sometimes successfully open and convert HTML or text messages into |
|
701
|
|
|
|
|
|
|
# images. |
|
702
|
|
|
|
|
|
|
# |
|
703
|
|
|
|
|
|
|
$image->Get('mime')=~/^image\// || $self->throw("- not an image file '$infile' (".$image->Get('mime').")"); |
|
704
|
|
|
|
|
|
|
|
|
705
|
|
|
|
|
|
|
# Get source image dimensions |
|
706
|
|
|
|
|
|
|
# |
|
707
|
|
|
|
|
|
|
my ($src_width, $src_height) = $image->Get('columns','rows'); |
|
708
|
|
|
|
|
|
|
|
|
709
|
|
|
|
|
|
|
my $min_width=$self->{'min_width'} || 10; |
|
710
|
|
|
|
|
|
|
my $min_height=$self->{'min_height'} || $min_width; |
|
711
|
|
|
|
|
|
|
|
|
712
|
|
|
|
|
|
|
if($src_height<=1 || $src_width<=1 || ($src_height<$min_height && $src_width<$min_width)) { |
|
713
|
|
|
|
|
|
|
$self->throw("- image ($src_width,$src_height) is smaller than the minimum ($min_width,$min_height) for '$label' (PERMANENT)"); |
|
714
|
|
|
|
|
|
|
} |
|
715
|
|
|
|
|
|
|
|
|
716
|
|
|
|
|
|
|
# Getting target image width and height |
|
717
|
|
|
|
|
|
|
# |
|
718
|
|
|
|
|
|
|
if($params->{'geometry'}){ |
|
719
|
|
|
|
|
|
|
$geometry = $params->{geometry}; # size was set as geometry string |
|
720
|
|
|
|
|
|
|
} |
|
721
|
|
|
|
|
|
|
elsif($params->{'save_aspect_ratio'}) { |
|
722
|
|
|
|
|
|
|
my $src_aspect=$src_width/$src_height; |
|
723
|
|
|
|
|
|
|
|
|
724
|
|
|
|
|
|
|
my $target_width=$params->{'width'} || $src_width; |
|
725
|
|
|
|
|
|
|
my $target_height=$params->{'height'} || $src_height; |
|
726
|
|
|
|
|
|
|
my $target_aspect=$target_width/$target_height; |
|
727
|
|
|
|
|
|
|
|
|
728
|
|
|
|
|
|
|
my ($width,$height); |
|
729
|
|
|
|
|
|
|
|
|
730
|
|
|
|
|
|
|
if($src_width<=$target_width && $src_height<=$target_height) { |
|
731
|
|
|
|
|
|
|
if(lc($image->Get('mime')) eq 'image/jpeg' && ($image->get('colorspace') || '') =~ /^s?RGB$/i) { |
|
732
|
|
|
|
|
|
|
copy($infile,$outfile); |
|
733
|
|
|
|
|
|
|
dprint "..copied ${src_width}x${src_height} as is for '$label' (jpeg, fits into ${target_width}x${target_height})"; |
|
734
|
|
|
|
|
|
|
return; |
|
735
|
|
|
|
|
|
|
} |
|
736
|
|
|
|
|
|
|
else { |
|
737
|
|
|
|
|
|
|
$width=$src_width; |
|
738
|
|
|
|
|
|
|
$height=$src_height; |
|
739
|
|
|
|
|
|
|
} |
|
740
|
|
|
|
|
|
|
} |
|
741
|
|
|
|
|
|
|
elsif($target_aspect>$src_aspect) { |
|
742
|
|
|
|
|
|
|
$height=$target_height; |
|
743
|
|
|
|
|
|
|
$width=int($height*$src_aspect+0.5); |
|
744
|
|
|
|
|
|
|
} |
|
745
|
|
|
|
|
|
|
else { |
|
746
|
|
|
|
|
|
|
$width=$target_width; |
|
747
|
|
|
|
|
|
|
$height=int($width/$src_aspect+0.5); |
|
748
|
|
|
|
|
|
|
} |
|
749
|
|
|
|
|
|
|
|
|
750
|
|
|
|
|
|
|
$geometry=$width.'x'.$height.'!'; |
|
751
|
|
|
|
|
|
|
} |
|
752
|
|
|
|
|
|
|
else { |
|
753
|
|
|
|
|
|
|
# Use given width & height as is (or image size if not set) |
|
754
|
|
|
|
|
|
|
$geometry = ($params->{'width'} || $src_width) .'x'. |
|
755
|
|
|
|
|
|
|
($params->{'height'} || $src_height).'!'; |
|
756
|
|
|
|
|
|
|
} |
|
757
|
|
|
|
|
|
|
|
|
758
|
|
|
|
|
|
|
# We don't support transparency and by default transparent regions |
|
759
|
|
|
|
|
|
|
# sometimes get translated to black. Forcing them into white. |
|
760
|
|
|
|
|
|
|
# |
|
761
|
|
|
|
|
|
|
$image->Set(background => 'white'); |
|
762
|
|
|
|
|
|
|
$image=$image->Flatten(); |
|
763
|
|
|
|
|
|
|
|
|
764
|
|
|
|
|
|
|
# This is required, otherwise new ImageMagick sometimes converts |
|
765
|
|
|
|
|
|
|
# images to CMYK colorspace for whatever reason. |
|
766
|
|
|
|
|
|
|
# |
|
767
|
|
|
|
|
|
|
# sRGB is the standard colorspace for monitors and printing, RGB |
|
768
|
|
|
|
|
|
|
# is an unspecified Red/Green/Blue encoding. Some images come out |
|
769
|
|
|
|
|
|
|
# darker when converted to RGB. |
|
770
|
|
|
|
|
|
|
# |
|
771
|
|
|
|
|
|
|
$image->Set( |
|
772
|
|
|
|
|
|
|
colorspace => 'sRGB', |
|
773
|
|
|
|
|
|
|
depth => 8, |
|
774
|
|
|
|
|
|
|
); |
|
775
|
|
|
|
|
|
|
|
|
776
|
|
|
|
|
|
|
# Scaling |
|
777
|
|
|
|
|
|
|
# |
|
778
|
|
|
|
|
|
|
$image->Scale(geometry => $geometry); |
|
779
|
|
|
|
|
|
|
|
|
780
|
|
|
|
|
|
|
# Stripping embedded profiles & comments. They sometimes take |
|
781
|
|
|
|
|
|
|
# upwards of 500kb |
|
782
|
|
|
|
|
|
|
# |
|
783
|
|
|
|
|
|
|
$image->Strip; |
|
784
|
|
|
|
|
|
|
|
|
785
|
|
|
|
|
|
|
# Writing the results |
|
786
|
|
|
|
|
|
|
# |
|
787
|
|
|
|
|
|
|
$image->Set(magick => 'JPEG'); |
|
788
|
|
|
|
|
|
|
$image->Set(quality => ($params->{'quality'} || 88)); |
|
789
|
|
|
|
|
|
|
|
|
790
|
|
|
|
|
|
|
my $rc=$image->Write($outfile); |
|
791
|
|
|
|
|
|
|
|
|
792
|
|
|
|
|
|
|
!"$rc" || die "Error writing scaled image: $rc"; |
|
793
|
|
|
|
|
|
|
|
|
794
|
|
|
|
|
|
|
dprint "..resized ${src_width}x${src_height} to $geometry for '$label'"; |
|
795
|
|
|
|
|
|
|
} |
|
796
|
|
|
|
|
|
|
|
|
797
|
|
|
|
|
|
|
############################################################################### |
|
798
|
|
|
|
|
|
|
|
|
799
|
|
|
|
|
|
|
=item scale_large($$$) |
|
800
|
|
|
|
|
|
|
|
|
801
|
|
|
|
|
|
|
Scaling image to given size. |
|
802
|
|
|
|
|
|
|
|
|
803
|
|
|
|
|
|
|
=cut |
|
804
|
|
|
|
|
|
|
|
|
805
|
|
|
|
|
|
|
sub scale_large($$$) { |
|
806
|
|
|
|
|
|
|
my ($self,$infile,$outfile)=@_; |
|
807
|
|
|
|
|
|
|
|
|
808
|
|
|
|
|
|
|
return $self->scale_file($infile,$outfile,$self->{'size'},'large'); |
|
809
|
|
|
|
|
|
|
} |
|
810
|
|
|
|
|
|
|
|
|
811
|
|
|
|
|
|
|
############################################################################### |
|
812
|
|
|
|
|
|
|
|
|
813
|
|
|
|
|
|
|
=item scale_thumbnail($$$) |
|
814
|
|
|
|
|
|
|
|
|
815
|
|
|
|
|
|
|
Creates thumbnail image from given source image. |
|
816
|
|
|
|
|
|
|
|
|
817
|
|
|
|
|
|
|
=cut |
|
818
|
|
|
|
|
|
|
|
|
819
|
|
|
|
|
|
|
sub scale_thumbnail($$$) { |
|
820
|
|
|
|
|
|
|
my ($self,$infile,$outfile)=@_; |
|
821
|
|
|
|
|
|
|
|
|
822
|
|
|
|
|
|
|
return $self->scale_file($infile,$outfile,$self->{'thumbnails'},'thumbnail'); |
|
823
|
|
|
|
|
|
|
} |
|
824
|
|
|
|
|
|
|
|
|
825
|
|
|
|
|
|
|
############################################################################### |
|
826
|
|
|
|
|
|
|
|
|
827
|
|
|
|
|
|
|
=item remove_cache($) |
|
828
|
|
|
|
|
|
|
|
|
829
|
|
|
|
|
|
|
Removing the ENTIRE cache directory from disk. |
|
830
|
|
|
|
|
|
|
|
|
831
|
|
|
|
|
|
|
Be carefully to use this method!!! |
|
832
|
|
|
|
|
|
|
|
|
833
|
|
|
|
|
|
|
Cache structure will be removed from disk completely! |
|
834
|
|
|
|
|
|
|
Set C parameter to True value to download |
|
835
|
|
|
|
|
|
|
images to cache without any conditions. |
|
836
|
|
|
|
|
|
|
|
|
837
|
|
|
|
|
|
|
=cut |
|
838
|
|
|
|
|
|
|
|
|
839
|
|
|
|
|
|
|
sub remove_cache($) { |
|
840
|
|
|
|
|
|
|
my $self = shift; |
|
841
|
|
|
|
|
|
|
rmtree($self->{'cache_path'}); |
|
842
|
|
|
|
|
|
|
} |
|
843
|
|
|
|
|
|
|
|
|
844
|
|
|
|
|
|
|
############################################################################### |
|
845
|
|
|
|
|
|
|
|
|
846
|
|
|
|
|
|
|
sub throw($$) { |
|
847
|
|
|
|
|
|
|
my ($self,$message)=@_; |
|
848
|
|
|
|
|
|
|
|
|
849
|
|
|
|
|
|
|
if($message=~/^-/) { |
|
850
|
|
|
|
|
|
|
(my $fname=(caller(1))[3])=~s/^.*://; |
|
851
|
|
|
|
|
|
|
$message=$fname." ".$message; |
|
852
|
|
|
|
|
|
|
} |
|
853
|
|
|
|
|
|
|
|
|
854
|
|
|
|
|
|
|
throw XAO::E::ImageCache $message; |
|
855
|
|
|
|
|
|
|
} |
|
856
|
|
|
|
|
|
|
|
|
857
|
|
|
|
|
|
|
############################################################################### |
|
858
|
|
|
|
|
|
|
|
|
859
|
|
|
|
|
|
|
=item get_filename($) |
|
860
|
|
|
|
|
|
|
|
|
861
|
|
|
|
|
|
|
File name generation for cached images. |
|
862
|
|
|
|
|
|
|
|
|
863
|
|
|
|
|
|
|
Source image URL should be passed. Returned file name is an MD5 digest |
|
864
|
|
|
|
|
|
|
of the source URL converted to Base64 string with all non alpha numeric |
|
865
|
|
|
|
|
|
|
characters are converted to C<_>. |
|
866
|
|
|
|
|
|
|
|
|
867
|
|
|
|
|
|
|
Example. |
|
868
|
|
|
|
|
|
|
|
|
869
|
|
|
|
|
|
|
Location: |
|
870
|
|
|
|
|
|
|
http://localhost/icons/medbutton.jpeg |
|
871
|
|
|
|
|
|
|
|
|
872
|
|
|
|
|
|
|
provide file name: |
|
873
|
|
|
|
|
|
|
4aFNA1utpmCNG2wEIF69mg.jpeg |
|
874
|
|
|
|
|
|
|
|
|
875
|
|
|
|
|
|
|
=cut |
|
876
|
|
|
|
|
|
|
|
|
877
|
|
|
|
|
|
|
# Return MD5 digest of given URL converted to Base64 |
|
878
|
|
|
|
|
|
|
# string with extension and |
|
879
|
|
|
|
|
|
|
sub get_filename($) { |
|
880
|
|
|
|
|
|
|
my $source = shift; |
|
881
|
|
|
|
|
|
|
my $url = URI->new($source); |
|
882
|
|
|
|
|
|
|
my $path= $url->path(); |
|
883
|
|
|
|
|
|
|
$path =~ /\./; |
|
884
|
|
|
|
|
|
|
my $file = md5_base64($source); |
|
885
|
|
|
|
|
|
|
return treat_filename($file); |
|
886
|
|
|
|
|
|
|
} |
|
887
|
|
|
|
|
|
|
|
|
888
|
|
|
|
|
|
|
############################################################################### |
|
889
|
|
|
|
|
|
|
|
|
890
|
|
|
|
|
|
|
=item treat_filename($) |
|
891
|
|
|
|
|
|
|
|
|
892
|
|
|
|
|
|
|
Makes sure only file name friendly characters are present: all non alpha |
|
893
|
|
|
|
|
|
|
numeric characters are converted to C<_>. |
|
894
|
|
|
|
|
|
|
|
|
895
|
|
|
|
|
|
|
=cut |
|
896
|
|
|
|
|
|
|
|
|
897
|
|
|
|
|
|
|
sub treat_filename($) { |
|
898
|
|
|
|
|
|
|
my $fnm = shift; |
|
899
|
|
|
|
|
|
|
$fnm =~ s/\W/_/gm; |
|
900
|
|
|
|
|
|
|
#$fnm =~ s/\//_/gm; |
|
901
|
|
|
|
|
|
|
#$fnm =~ s/\+/\-/gm; |
|
902
|
|
|
|
|
|
|
#$fnm =~ s/=/\-/gm; |
|
903
|
|
|
|
|
|
|
return $fnm; |
|
904
|
|
|
|
|
|
|
} |
|
905
|
|
|
|
|
|
|
|
|
906
|
|
|
|
|
|
|
############################################################################### |
|
907
|
|
|
|
|
|
|
# Convert 'Last-Modified' Date/Time in internet format |
|
908
|
|
|
|
|
|
|
# to seconds since epoch format |
|
909
|
|
|
|
|
|
|
# Wed, 21 Jan 2001 24:55:55 GMT |
|
910
|
|
|
|
|
|
|
sub convert_time($) { |
|
911
|
|
|
|
|
|
|
my $date_str = shift; |
|
912
|
|
|
|
|
|
|
#print "Last Modified: $date_str\n"; |
|
913
|
|
|
|
|
|
|
$date_str =~ s/,//; |
|
914
|
|
|
|
|
|
|
my @date_arr = split(/[\s+|:]/,$date_str); |
|
915
|
|
|
|
|
|
|
my %month = ( |
|
916
|
|
|
|
|
|
|
Jan => 0, Feb => 1, Mar => 2, Apr => 3, |
|
917
|
|
|
|
|
|
|
May => 4, Jun => 5, Jul => 6, Aug => 7, |
|
918
|
|
|
|
|
|
|
Sep => 8, Oct => 9, Nov => 10, Dec => 11, |
|
919
|
|
|
|
|
|
|
); |
|
920
|
|
|
|
|
|
|
my %wday = (Sun => 0, Mon => 1, Tue => 2, Wed => 3, Thu => 4, Fri => 5, Sat => 6); |
|
921
|
|
|
|
|
|
|
# Clearing leading zero |
|
922
|
|
|
|
|
|
|
$date_arr[1] =~ s/^0//; # Month days |
|
923
|
|
|
|
|
|
|
$date_arr[4] =~ s/^0//; # Hours |
|
924
|
|
|
|
|
|
|
$date_arr[5] =~ s/^0//; # Minutes |
|
925
|
|
|
|
|
|
|
$date_arr[6] =~ s/^0//; # Seconds |
|
926
|
|
|
|
|
|
|
my $time=eval { |
|
927
|
|
|
|
|
|
|
if ($date_arr[7] eq 'GMT') { |
|
928
|
|
|
|
|
|
|
Time::Local::timegm( |
|
929
|
|
|
|
|
|
|
$date_arr[6], |
|
930
|
|
|
|
|
|
|
$date_arr[5], |
|
931
|
|
|
|
|
|
|
$date_arr[4], |
|
932
|
|
|
|
|
|
|
$date_arr[1], |
|
933
|
|
|
|
|
|
|
$month{$date_arr[2]}, |
|
934
|
|
|
|
|
|
|
$date_arr[3], |
|
935
|
|
|
|
|
|
|
); |
|
936
|
|
|
|
|
|
|
} |
|
937
|
|
|
|
|
|
|
else{ |
|
938
|
|
|
|
|
|
|
Time::Local::timelocal( |
|
939
|
|
|
|
|
|
|
$date_arr[6], |
|
940
|
|
|
|
|
|
|
$date_arr[5], |
|
941
|
|
|
|
|
|
|
$date_arr[4], |
|
942
|
|
|
|
|
|
|
$date_arr[1], |
|
943
|
|
|
|
|
|
|
$month{$date_arr[2]}, |
|
944
|
|
|
|
|
|
|
$date_arr[3], |
|
945
|
|
|
|
|
|
|
); |
|
946
|
|
|
|
|
|
|
} |
|
947
|
|
|
|
|
|
|
}; |
|
948
|
|
|
|
|
|
|
return $time || 0; |
|
949
|
|
|
|
|
|
|
} |
|
950
|
|
|
|
|
|
|
|
|
951
|
|
|
|
|
|
|
############################################################################### |
|
952
|
|
|
|
|
|
|
|
|
953
|
|
|
|
|
|
|
1; |
|
954
|
|
|
|
|
|
|
|
|
955
|
|
|
|
|
|
|
=back |
|
956
|
|
|
|
|
|
|
|
|
957
|
|
|
|
|
|
|
=head1 CONFIGURATION PARAMETERS |
|
958
|
|
|
|
|
|
|
|
|
959
|
|
|
|
|
|
|
The set of configuration parameters contain required and optional parameters. |
|
960
|
|
|
|
|
|
|
|
|
961
|
|
|
|
|
|
|
Required parameters should be defined. Execution will be stoped if required |
|
962
|
|
|
|
|
|
|
parameter not present. |
|
963
|
|
|
|
|
|
|
|
|
964
|
|
|
|
|
|
|
Optional parameters just configure aditional functionality and may not present. |
|
965
|
|
|
|
|
|
|
|
|
966
|
|
|
|
|
|
|
=head2 Required parameters |
|
967
|
|
|
|
|
|
|
|
|
968
|
|
|
|
|
|
|
=over |
|
969
|
|
|
|
|
|
|
|
|
970
|
|
|
|
|
|
|
=item cache_path |
|
971
|
|
|
|
|
|
|
|
|
972
|
|
|
|
|
|
|
- Path string where the cache should be placed. |
|
973
|
|
|
|
|
|
|
|
|
974
|
|
|
|
|
|
|
May be absolute or relative from current execution directory path. |
|
975
|
|
|
|
|
|
|
|
|
976
|
|
|
|
|
|
|
For example. Set it to C<./cache> if you whant to place cache in |
|
977
|
|
|
|
|
|
|
C subdirectory of your script working directory. |
|
978
|
|
|
|
|
|
|
|
|
979
|
|
|
|
|
|
|
=item cache_url |
|
980
|
|
|
|
|
|
|
|
|
981
|
|
|
|
|
|
|
- complet URL (or relative location) to cached images. |
|
982
|
|
|
|
|
|
|
|
|
983
|
|
|
|
|
|
|
Place here your URL reflection of cache directory in condition with |
|
984
|
|
|
|
|
|
|
your HTTP server configuration. |
|
985
|
|
|
|
|
|
|
|
|
986
|
|
|
|
|
|
|
For example. Set it to C if your HTTP |
|
987
|
|
|
|
|
|
|
server configured for provide access to your cache directory by |
|
988
|
|
|
|
|
|
|
hostname C and location C. Cached images names |
|
989
|
|
|
|
|
|
|
will be added to image URL automaticaly. |
|
990
|
|
|
|
|
|
|
|
|
991
|
|
|
|
|
|
|
=item list |
|
992
|
|
|
|
|
|
|
|
|
993
|
|
|
|
|
|
|
- reference to C object containing the data objects |
|
994
|
|
|
|
|
|
|
with Image source URL |
|
995
|
|
|
|
|
|
|
|
|
996
|
|
|
|
|
|
|
Meaning, your data look like a XAO Foundation Server list of objects |
|
997
|
|
|
|
|
|
|
with references to images. This parameter should contain reference to |
|
998
|
|
|
|
|
|
|
to XAO::DO::FS::List object. This reference may be result of |
|
999
|
|
|
|
|
|
|
XAO::Objects->fetch() methode. |
|
1000
|
|
|
|
|
|
|
|
|
1001
|
|
|
|
|
|
|
XAO::ImageCache will process each record of this list. |
|
1002
|
|
|
|
|
|
|
|
|
1003
|
|
|
|
|
|
|
=item source_url_key |
|
1004
|
|
|
|
|
|
|
|
|
1005
|
|
|
|
|
|
|
- data key containing the URL of source image. |
|
1006
|
|
|
|
|
|
|
|
|
1007
|
|
|
|
|
|
|
Contain the name of key of data object containing the source image reference. |
|
1008
|
|
|
|
|
|
|
|
|
1009
|
|
|
|
|
|
|
=back |
|
1010
|
|
|
|
|
|
|
|
|
1011
|
|
|
|
|
|
|
=head2 Optional parameters |
|
1012
|
|
|
|
|
|
|
|
|
1013
|
|
|
|
|
|
|
=over |
|
1014
|
|
|
|
|
|
|
|
|
1015
|
|
|
|
|
|
|
=item dest_url_key |
|
1016
|
|
|
|
|
|
|
|
|
1017
|
|
|
|
|
|
|
- data key for storing URL of image in cache. |
|
1018
|
|
|
|
|
|
|
|
|
1019
|
|
|
|
|
|
|
Optional parameter cause image name in cache will be a MD5 Base64 |
|
1020
|
|
|
|
|
|
|
digest of source image path where C<=> character removed, C<\> and C<+> |
|
1021
|
|
|
|
|
|
|
translated to C<_> and C<-> simultaniosely. |
|
1022
|
|
|
|
|
|
|
|
|
1023
|
|
|
|
|
|
|
To get cached image name |
|
1024
|
|
|
|
|
|
|
|
|
1025
|
|
|
|
|
|
|
=item size |
|
1026
|
|
|
|
|
|
|
|
|
1027
|
|
|
|
|
|
|
- Prefered image size may set as C equal to C parameter |
|
1028
|
|
|
|
|
|
|
of Image::Magick module to pass it dirrectly to Image::Magick Scale function. |
|
1029
|
|
|
|
|
|
|
|
|
1030
|
|
|
|
|
|
|
Other way to set the image size is set a width and height keys to preffered |
|
1031
|
|
|
|
|
|
|
values. |
|
1032
|
|
|
|
|
|
|
|
|
1033
|
|
|
|
|
|
|
If one of image dimension is not defined then corresponding parameter of |
|
1034
|
|
|
|
|
|
|
original image will be used. |
|
1035
|
|
|
|
|
|
|
|
|
1036
|
|
|
|
|
|
|
This way, image will be resized with same aspect ratio (same proportions) to |
|
1037
|
|
|
|
|
|
|
the original image if C parameter present. |
|
1038
|
|
|
|
|
|
|
|
|
1039
|
|
|
|
|
|
|
Image width and height will be resized exactly to given size if |
|
1040
|
|
|
|
|
|
|
C parameter not present. |
|
1041
|
|
|
|
|
|
|
|
|
1042
|
|
|
|
|
|
|
Parameter C has higher priority and other parameters has no effects |
|
1043
|
|
|
|
|
|
|
if C peresent. |
|
1044
|
|
|
|
|
|
|
|
|
1045
|
|
|
|
|
|
|
For example. |
|
1046
|
|
|
|
|
|
|
|
|
1047
|
|
|
|
|
|
|
# Size 320x200 as geometry settings |
|
1048
|
|
|
|
|
|
|
%params = (size => {geometry => "320x200!"} ); |
|
1049
|
|
|
|
|
|
|
|
|
1050
|
|
|
|
|
|
|
# Size 320x200 as dimensions settings |
|
1051
|
|
|
|
|
|
|
%params = (size => {width => 320, height => 200} ); |
|
1052
|
|
|
|
|
|
|
|
|
1053
|
|
|
|
|
|
|
# Fit size into 320x200 with saving image proportions |
|
1054
|
|
|
|
|
|
|
%params = ( |
|
1055
|
|
|
|
|
|
|
size => { |
|
1056
|
|
|
|
|
|
|
width => 320, |
|
1057
|
|
|
|
|
|
|
height => 200, |
|
1058
|
|
|
|
|
|
|
save_aspect_ratio => 1, |
|
1059
|
|
|
|
|
|
|
} |
|
1060
|
|
|
|
|
|
|
); |
|
1061
|
|
|
|
|
|
|
|
|
1062
|
|
|
|
|
|
|
=item autocreate |
|
1063
|
|
|
|
|
|
|
|
|
1064
|
|
|
|
|
|
|
- create or check cache content automaticaly. |
|
1065
|
|
|
|
|
|
|
|
|
1066
|
|
|
|
|
|
|
If non zero value present, cache directory will be created |
|
1067
|
|
|
|
|
|
|
and images checking will be runned. Otherwithe you should run |
|
1068
|
|
|
|
|
|
|
init() and check() methodes manualy. |
|
1069
|
|
|
|
|
|
|
|
|
1070
|
|
|
|
|
|
|
Existent cache directory will not be removed. You may do it |
|
1071
|
|
|
|
|
|
|
manualy using remove_cache() methode. |
|
1072
|
|
|
|
|
|
|
|
|
1073
|
|
|
|
|
|
|
=item force_download |
|
1074
|
|
|
|
|
|
|
|
|
1075
|
|
|
|
|
|
|
- each image should be reloaded to cache and processed without |
|
1076
|
|
|
|
|
|
|
dependance of source image modification time. Any conditions |
|
1077
|
|
|
|
|
|
|
ignored. |
|
1078
|
|
|
|
|
|
|
|
|
1079
|
|
|
|
|
|
|
=item thumbnail |
|
1080
|
|
|
|
|
|
|
|
|
1081
|
|
|
|
|
|
|
- thumbnails creator configuration |
|
1082
|
|
|
|
|
|
|
|
|
1083
|
|
|
|
|
|
|
Some thubnails configuration parameters may be set for |
|
1084
|
|
|
|
|
|
|
automatic thumbnails creation. This parameter should contain |
|
1085
|
|
|
|
|
|
|
the reference to hash with thumbnails configuration parameters. |
|
1086
|
|
|
|
|
|
|
|
|
1087
|
|
|
|
|
|
|
Only C parameter is required. Other parameters are |
|
1088
|
|
|
|
|
|
|
optional. |
|
1089
|
|
|
|
|
|
|
|
|
1090
|
|
|
|
|
|
|
=over |
|
1091
|
|
|
|
|
|
|
|
|
1092
|
|
|
|
|
|
|
=item path |
|
1093
|
|
|
|
|
|
|
|
|
1094
|
|
|
|
|
|
|
path where thumbnail images should be placed. |
|
1095
|
|
|
|
|
|
|
|
|
1096
|
|
|
|
|
|
|
=item url |
|
1097
|
|
|
|
|
|
|
|
|
1098
|
|
|
|
|
|
|
URL for access to thumbnails directory. Same way as C. |
|
1099
|
|
|
|
|
|
|
|
|
1100
|
|
|
|
|
|
|
=item url_key |
|
1101
|
|
|
|
|
|
|
|
|
1102
|
|
|
|
|
|
|
Data object key name where thumbnail URL should be stored. |
|
1103
|
|
|
|
|
|
|
|
|
1104
|
|
|
|
|
|
|
=item geometry |
|
1105
|
|
|
|
|
|
|
|
|
1106
|
|
|
|
|
|
|
Geometry string to set thumbnail images size in Image Magick geometry |
|
1107
|
|
|
|
|
|
|
format. May be set as dimension ("320x200!") or as persent of actual |
|
1108
|
|
|
|
|
|
|
size of cached image ("25%"). |
|
1109
|
|
|
|
|
|
|
|
|
1110
|
|
|
|
|
|
|
Default value is "50%" the half of actual image size. |
|
1111
|
|
|
|
|
|
|
|
|
1112
|
|
|
|
|
|
|
=back |
|
1113
|
|
|
|
|
|
|
|
|
1114
|
|
|
|
|
|
|
=item useragent |
|
1115
|
|
|
|
|
|
|
|
|
1116
|
|
|
|
|
|
|
- configuration parameters hash for LWP::UserAgent |
|
1117
|
|
|
|
|
|
|
|
|
1118
|
|
|
|
|
|
|
=over |
|
1119
|
|
|
|
|
|
|
|
|
1120
|
|
|
|
|
|
|
=item agent |
|
1121
|
|
|
|
|
|
|
|
|
1122
|
|
|
|
|
|
|
Default value C |
|
1123
|
|
|
|
|
|
|
|
|
1124
|
|
|
|
|
|
|
=item env_proxy |
|
1125
|
|
|
|
|
|
|
|
|
1126
|
|
|
|
|
|
|
Default value 1 |
|
1127
|
|
|
|
|
|
|
|
|
1128
|
|
|
|
|
|
|
=item keep_alive |
|
1129
|
|
|
|
|
|
|
|
|
1130
|
|
|
|
|
|
|
Default value 1 |
|
1131
|
|
|
|
|
|
|
|
|
1132
|
|
|
|
|
|
|
=item timeout |
|
1133
|
|
|
|
|
|
|
|
|
1134
|
|
|
|
|
|
|
Default value 30 |
|
1135
|
|
|
|
|
|
|
|
|
1136
|
|
|
|
|
|
|
=back |
|
1137
|
|
|
|
|
|
|
|
|
1138
|
|
|
|
|
|
|
For more information please follow to L |
|
1139
|
|
|
|
|
|
|
|
|
1140
|
|
|
|
|
|
|
=back |
|
1141
|
|
|
|
|
|
|
|
|
1142
|
|
|
|
|
|
|
=head1 SEE ALSO |
|
1143
|
|
|
|
|
|
|
|
|
1144
|
|
|
|
|
|
|
Specifics of List API can be found in |
|
1145
|
|
|
|
|
|
|
|
|
1146
|
|
|
|
|
|
|
L. |
|
1147
|
|
|
|
|
|
|
|
|
1148
|
|
|
|
|
|
|
For additional information please see |
|
1149
|
|
|
|
|
|
|
|
|
1150
|
|
|
|
|
|
|
L, |
|
1151
|
|
|
|
|
|
|
|
|
1152
|
|
|
|
|
|
|
L, |
|
1153
|
|
|
|
|
|
|
|
|
1154
|
|
|
|
|
|
|
L, |
|
1155
|
|
|
|
|
|
|
|
|
1156
|
|
|
|
|
|
|
Refer to L documentation for additional |
|
1157
|
|
|
|
|
|
|
information about setting of image scaling parameters. |
|
1158
|
|
|
|
|
|
|
|
|
1159
|
|
|
|
|
|
|
Refer to L documentation for additional |
|
1160
|
|
|
|
|
|
|
information about user agent parameters. |
|
1161
|
|
|
|
|
|
|
|
|
1162
|
|
|
|
|
|
|
=head1 BUGS |
|
1163
|
|
|
|
|
|
|
|
|
1164
|
|
|
|
|
|
|
Please, inform me about found bugs. |
|
1165
|
|
|
|
|
|
|
|
|
1166
|
|
|
|
|
|
|
=head1 AUTHORS |
|
1167
|
|
|
|
|
|
|
|
|
1168
|
|
|
|
|
|
|
The XAO::ImageCache package maintained by |
|
1169
|
|
|
|
|
|
|
Konstantin Safronov . Specification by |
|
1170
|
|
|
|
|
|
|
Andrew Maltsew |
|
1171
|
|
|
|
|
|
|
|
|
1172
|
|
|
|
|
|
|
=cut |