1
|
<?php
|
2
|
/*
|
3
|
|
4
|
This is a PHP file to be used as a backend for a ka-Map layer. It requires
|
5
|
PHP with Mapscript and libgd modules installed. The top of the file
|
6
|
is a configuration section: please edit the variables in this configuration
|
7
|
section to meet your needs, then rename this file to tile.php or something
|
8
|
similar and put it in a web accessible directory. More information
|
9
|
on the OpenLayers ka-Map layer is available from:
|
10
|
|
11
|
http://trac.openlayers.org/wiki/OpenLayers.Layer.KaMap
|
12
|
|
13
|
*/
|
14
|
/**********************************************************************
|
15
|
*
|
16
|
* $Id$
|
17
|
*
|
18
|
* purpose: a simple phpmapscript-based tile renderer that implements
|
19
|
* rudimentary caching for reasonable efficiency. Note the
|
20
|
* cache never shrinks in this version so your disk could
|
21
|
* easily fill up!
|
22
|
*
|
23
|
* author: Paul Spencer (pspencer@dmsolutions.ca)
|
24
|
*
|
25
|
* modifications by Daniel Morissette (dmorissette@dmsolutions.ca)
|
26
|
*
|
27
|
* Modified by Christopher Schmidt for OpenLayers redistribution.
|
28
|
*
|
29
|
**********************************************************************
|
30
|
*
|
31
|
* Copyright (c) 2005, DM Solutions Group Inc.
|
32
|
*
|
33
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
34
|
* copy of this software and associated documentation files (the "Software"),
|
35
|
* to deal in the Software without restriction, including without limitation
|
36
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
37
|
* and/or sell copies of the Software, and to permit persons to whom the
|
38
|
* Software is furnished to do so, subject to the following conditions:
|
39
|
*
|
40
|
* The above copyright notice and this permission notice shall be included
|
41
|
* in all copies or substantial portions of the Software.
|
42
|
*
|
43
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
44
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
45
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
46
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
47
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
48
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
49
|
* DEALINGS IN THE SOFTWARE.
|
50
|
*
|
51
|
**********************************************************************/
|
52
|
|
53
|
|
54
|
/******************************************************************************
|
55
|
* basic system configuration
|
56
|
*
|
57
|
* kaMap! uses PHP/MapScript and the PHP GD extension to
|
58
|
* render tiles, and uses PHP/MapScript to generate initialization parameters
|
59
|
* a legend, and a keymap from the selected map file.
|
60
|
*
|
61
|
* Make sure to set the correct module names for your PHP extensions.
|
62
|
*
|
63
|
* WINDOWS USERS: you will likely need to use php_gd2.dll instead of php_gd.dll
|
64
|
*/
|
65
|
$szPHPMapScriptModule = 'php_mapscript.'.PHP_SHLIB_SUFFIX;
|
66
|
$szPHPGDModule = 'php_gd.'.PHP_SHLIB_SUFFIX;
|
67
|
|
68
|
/******************************************************************************
|
69
|
* tile generation parameters
|
70
|
*
|
71
|
* kaMap! generates tiles to load in the client application by first rendering
|
72
|
* larger areas from the map file and then slicing them up into smaller tiles.
|
73
|
* This approach reduces the overhead of loading PHP/MapScript and PHP GD and
|
74
|
* drawing the map file. These larger areas are referred to as metaTiles in
|
75
|
* the code. You can set the size of both the small tiles and the metaTiles
|
76
|
* here. A reasonable size for the small tiles seems to be 200 pixels square.
|
77
|
* Smaller tiles seem to cause problems in client browsers by causing too many
|
78
|
* images to be created and thus slowing performance of live dragging. Larger
|
79
|
* tiles take longer to download to the client and are inefficient.
|
80
|
*
|
81
|
* The number of smaller tiles that form a metaTile can also be configured.
|
82
|
* This parameter allows tuning of the tile generator to ensure optimal
|
83
|
* performance and for label placement. MapServer will produce labels only
|
84
|
* within a rendered area. If the area is too small then features may be
|
85
|
* labelled multiple times. If the area is too large, it may exceed MapServer,s
|
86
|
* maximum map size (by default 2000x2000) or be too resource-intensive on the
|
87
|
* server, ultimately reducing performance.
|
88
|
*/
|
89
|
$tileWidth = 256;
|
90
|
$tileHeight = 256;
|
91
|
$metaWidth = 5;
|
92
|
$metaHeight = 5;
|
93
|
/* $metaBuffer = Buffer size in pixels to add around metatiles to avoid
|
94
|
* rendering issues along the edge of the map image
|
95
|
*/
|
96
|
$metaBuffer = 10;
|
97
|
|
98
|
/******************************************************************************
|
99
|
* in-image debugging information - tile location, outlines etc.
|
100
|
* to use this, you need to remove images from your cache first. This also
|
101
|
* affects the meta tiles - if debug is on, they are not deleted.
|
102
|
*/
|
103
|
$bDebug = false;
|
104
|
|
105
|
/******************************************************************************
|
106
|
* aszMapFiles - an array of map files available to the application. How this
|
107
|
* is used is determined by the application. Each map file is entered into
|
108
|
* this array as a key->value pair.
|
109
|
*
|
110
|
* The key is the name to be used by the tile caching system to store cached
|
111
|
* tiles within the base cache directory. This key should be a single word
|
112
|
* that uniquely identifies the map.
|
113
|
*
|
114
|
* The value associated with each key is an array of three values. The first
|
115
|
* value is a human-readable name to be presented to the user (should the
|
116
|
* application choose to do so) and the second value is the path to the map
|
117
|
* file. It is assumed that the map file is fully configured for use with
|
118
|
* MapServer/MapScript as no error checking or setting of values is done. The
|
119
|
* third value is an array of scale values for zooming.
|
120
|
*/
|
121
|
|
122
|
$aszMapFiles = array(
|
123
|
"world" => array( "World", "/path/to/your/mapfile",
|
124
|
array( 10000 ), # in openlayers, the scale array doesn't matter.
|
125
|
"PNG24")
|
126
|
|
127
|
/* Add more elements to this array to offer multiple mapfiles */
|
128
|
|
129
|
);
|
130
|
|
131
|
/******************************************************************************
|
132
|
* figure out which map file to use and set up the necessary variables for
|
133
|
* the rest of the code to use. This does need to be done on every page load
|
134
|
* unfortunately.
|
135
|
*
|
136
|
* szMap should be set to the default map file to use but can change if
|
137
|
* this script is called with map=<mapname>.
|
138
|
*/
|
139
|
$szMap = 'world';
|
140
|
|
141
|
/******************************************************************************
|
142
|
* kaMap! caching
|
143
|
*
|
144
|
* this is the directory within which kaMap! will create its tile cache. The
|
145
|
* directory does NOT have to be web-accessible, but it must be writable by the
|
146
|
* web-server-user and allow creation of both directories AND files.
|
147
|
*
|
148
|
* the tile caching system will create a separate subdirectory within the base
|
149
|
* cache directory for each map file. Within the cache directory for each map
|
150
|
* file, directories will be created for each group of layers. Within the group
|
151
|
* directories, directories will be created at each of the configured scales
|
152
|
* for the application (see mapfile configuration above.)
|
153
|
*/
|
154
|
$szBaseCacheDir = "/var/cache/kamap/";
|
155
|
|
156
|
/***** END OF CONFIGURABLE STUFF - unless you know what you are doing *****/
|
157
|
/***** *****/
|
158
|
/***** *****/
|
159
|
/***** *****/
|
160
|
/***** END OF CONFIGURABLE STUFF - unless you know what you are doing *****/
|
161
|
|
162
|
if (isset($_REQUEST['map']) && isset($aszMapFiles[$_REQUEST['map']]))
|
163
|
{
|
164
|
$szMap = $_REQUEST['map'];
|
165
|
}
|
166
|
|
167
|
$szMapCacheDir = $szBaseCacheDir.$szMap."/";
|
168
|
$szMapName = $aszMapFiles[$szMap][0];
|
169
|
$szMapFile = $aszMapFiles[$szMap][1];
|
170
|
$anScales = $aszMapFiles[$szMap][2];
|
171
|
setOutputFormat($aszMapFiles[$szMap][3]);
|
172
|
/******************************************************************************
|
173
|
* output format of the map and resulting tiles
|
174
|
*
|
175
|
* The output format used with MapServer can greatly affect appearance and
|
176
|
* performance. It is recommended to use an 8 bit format such as PNG
|
177
|
*
|
178
|
* NOTE: the tile caching code in tile.php is not configurable here. It
|
179
|
* currently assumes that it is outputting 8bit PNG files. If you change to
|
180
|
* PNG24 here then you will need to update tile.php to use the gd function
|
181
|
* imagecreatetruecolor. If you change the output format to jpeg then
|
182
|
* you would need to change imagepng() to imagejpeg(). A nice enhancement
|
183
|
* would be to make that fully configurable from here.
|
184
|
*/
|
185
|
function setOutputFormat($szFormat)
|
186
|
{
|
187
|
switch($szFormat) {
|
188
|
case "PNG24":
|
189
|
$GLOBALS['szMapImageFormat'] = 'PNG24'; //mapscript format name
|
190
|
$GLOBALS['szMapImageCreateFunction'] = "imagecreatefrompng"; // appropriate GD function
|
191
|
$GLOBALS['szImageExtension'] = '.png'; //file extension
|
192
|
$GLOBALS['szImageCreateFunction'] = "imagecreatetruecolor"; //or imagecreatetruecolor if PNG24 ...
|
193
|
$GLOBALS['szImageOutputFunction'] = "imagepng"; //or imagegif, imagejpeg ...
|
194
|
$GLOBALS['szImageHeader'] = 'image/png'; //the content-type of the image
|
195
|
break;
|
196
|
case "GIF":
|
197
|
$GLOBALS['szMapImageFormat'] = 'GIF'; //mapscript format name
|
198
|
$GLOBALS['szMapImageCreateFunction'] = "imagecreatefromgif"; // appropriate GD function
|
199
|
$GLOBALS['szImageExtension'] = '.gif'; //file extension
|
200
|
$GLOBALS['szImageCreateFunction'] = "imagecreate"; //or imagecreatetruecolor if PNG24 ...
|
201
|
$GLOBALS['szImageOutputFunction'] = "imagegif"; //or imagegif, imagejpeg ...
|
202
|
$GLOBALS['szImageHeader'] = 'image/gif'; //the content-type of the image
|
203
|
break;
|
204
|
case "JPEG":
|
205
|
$GLOBALS['szMapImageFormat'] = 'JPEG'; //mapscript format name
|
206
|
$GLOBALS['szMapImageCreateFunction'] = "imagecreatefromjpeg"; // appropriate GD function
|
207
|
$GLOBALS['szImageExtension'] = '.jpg'; //file extension
|
208
|
$GLOBALS['szImageCreateFunction'] = "imagecreatetruecolor"; //or imagecreatetruecolor if PNG24 ...
|
209
|
$GLOBALS['szImageOutputFunction'] = "imagejpeg"; //or imagegif, imagejpeg ...
|
210
|
$GLOBALS['szImageHeader'] = 'image/jpeg'; //the content-type of the image
|
211
|
break;
|
212
|
case "PNG":
|
213
|
$GLOBALS['szMapImageFormat'] = 'PNG'; //mapscript format name
|
214
|
$GLOBALS['szMapImageCreateFunction'] = "imagecreatefrompng"; // appropriate GD function
|
215
|
$GLOBALS['szImageExtension'] = '.png'; //file extension
|
216
|
$GLOBALS['szImageCreateFunction'] = "imagecreate"; //or imagecreatetruecolor if PNG24 ...
|
217
|
$GLOBALS['szImageOutputFunction'] = "imagepng"; //or imagegif, imagejpeg ...
|
218
|
$GLOBALS['szImageHeader'] = 'image/png'; //the content-type of the image
|
219
|
break;
|
220
|
case "DITHERED":
|
221
|
case "PNG8":
|
222
|
$GLOBALS['szMapImageFormat'] = 'dithered';
|
223
|
$GLOBALS['szMapImageCreateFunction'] = "imagecreatefrompng";
|
224
|
$GLOBALS['szImageExtension'] = '.png';
|
225
|
$GLOBALS['szImageCreateFunction'] = "imagecreate";
|
226
|
$GLOBALS['szImageOutputFunction'] = "imagepng";
|
227
|
$GLOBALS['szImageHeader'] = 'image/png';
|
228
|
break;
|
229
|
}
|
230
|
}
|
231
|
|
232
|
/**
|
233
|
* create all directories in a directory tree - found on the php web site
|
234
|
* under the mkdir function ...
|
235
|
*/
|
236
|
function makeDirs($strPath, $mode = 0775)
|
237
|
{
|
238
|
return is_dir($strPath) or ( makeDirs(dirname($strPath), $mode) and mkdir($strPath, $mode) );
|
239
|
}
|
240
|
|
241
|
/**
|
242
|
* This function replaces all special characters in the given string.
|
243
|
*
|
244
|
* @param szString string - The string to convert.
|
245
|
*
|
246
|
* @return string converted
|
247
|
*/
|
248
|
function normalizeString($szString)
|
249
|
{
|
250
|
// Normalize string by replacing all special characters
|
251
|
// e.g. "http://my.host.com/cgi-bin/mywms?"
|
252
|
// becomes "http___my_host_com_cgi_bin_mywms_"
|
253
|
return preg_replace("/(\W)/", "_", $szString);
|
254
|
}
|
255
|
|
256
|
/* bug 1253 - root permissions required to delete cached files */
|
257
|
$orig_umask = umask(0);
|
258
|
|
259
|
/* create the main cache directory if necessary */
|
260
|
if (!@is_dir($szMapCacheDir))
|
261
|
makeDirs($szMapCacheDir);
|
262
|
|
263
|
/* get the various request parameters
|
264
|
* also need to make sure inputs are clean, especially those used to
|
265
|
* build paths and filenames
|
266
|
*/
|
267
|
/*
|
268
|
* the tile renderer accepts several parameters and returns a tile image from
|
269
|
* the cache, creating the tile only if necessary.
|
270
|
*
|
271
|
* all requests include the pixel location of the request at a certain scale
|
272
|
* and this script figures out the geographic location of the tile from the
|
273
|
* scale assuming that 0,0 in pixels is 0,0 in geographic units
|
274
|
*
|
275
|
* Request parameters are:
|
276
|
*
|
277
|
* map: the name of the map to use. This is handled by config.php.
|
278
|
*
|
279
|
* t: top pixel position
|
280
|
* l: left pixel position
|
281
|
* s: scale
|
282
|
* g: (optional) comma-delimited list of group names to draw
|
283
|
* layers: (optional) comma-delimited list of layers to draw
|
284
|
* force: optional. If set, force redraw of the meta tile. This was added to
|
285
|
* help with invalid images sometimes being generated.
|
286
|
* tileid: (optional) can be used instead of t+l to specify the tile coord.,
|
287
|
* useful in regenerating the cache
|
288
|
*/
|
289
|
|
290
|
$top = isset( $_REQUEST['t'] ) ? intval($_REQUEST['t']) : 0;
|
291
|
$left = isset( $_REQUEST['l'] ) ? intval($_REQUEST['l']) : 0;
|
292
|
$scale = isset( $_REQUEST['s'] ) ? $_REQUEST['s'] : $anScales[0];
|
293
|
$bForce = isset($_REQUEST['force'])? true : false;
|
294
|
$groups = isset( $_REQUEST['g'] ) ? $_REQUEST['g'] : "";
|
295
|
$layers = isset( $_REQUEST['layers'] ) ? $_REQUEST['layers'] : "";
|
296
|
|
297
|
// dynamic imageformat ----------------------------------------------
|
298
|
//use the function in config.php to set the output format
|
299
|
if (isset($_REQUEST['i']))
|
300
|
setOutputFormat( $_REQUEST['i'] );
|
301
|
//----------------------------------------------------------------
|
302
|
|
303
|
/* tileid=t#####l#### can be used instead of t+l parameters. Useful in
|
304
|
* regenerating the cache for instance.
|
305
|
*/
|
306
|
if (isset( $_REQUEST['tileid']) &&
|
307
|
preg_match("/t(-?\d+)l(-?\d+)/", $_REQUEST['tileid'], $aMatch) )
|
308
|
{
|
309
|
$top = intval($aMatch[1]);
|
310
|
$left = intval($aMatch[2]);
|
311
|
}
|
312
|
|
313
|
/* Calculate the metatile's top-left corner coordinates.
|
314
|
* Include the $metaBuffer around the metatile to account for various
|
315
|
* rendering issues happening around the edge of a map
|
316
|
*/
|
317
|
$metaLeft = floor( ($left)/($tileWidth*$metaWidth) ) * $tileWidth * $metaWidth;
|
318
|
$metaTop = floor( ($top)/($tileHeight*$metaHeight) ) * $tileHeight *$metaHeight;
|
319
|
$szMetaTileId = "t".$metaTop."l".$metaLeft;
|
320
|
$metaLeft -= $metaBuffer;
|
321
|
$metaTop -= $metaBuffer;
|
322
|
|
323
|
/* caching is done by scale value, then groups and layers and finally metatile
|
324
|
* and tile id. Create a new directory if necessary
|
325
|
*/
|
326
|
$szGroupDir = $groups != "" ? normalizeString($groups) : "def";
|
327
|
$szLayerDir = $layers != "" ? normalizeString($layers) : "def";
|
328
|
|
329
|
$szCacheDir = $szMapCacheDir."/".$scale."/".$szGroupDir."/".$szLayerDir."/".$szMetaTileId;
|
330
|
if (!@is_dir($szCacheDir))
|
331
|
makeDirs($szCacheDir);
|
332
|
|
333
|
/* resolve cache hit - clear the os stat cache if necessary */
|
334
|
$szTileId = "t".$top."l".$left;
|
335
|
$szCacheFile = $szCacheDir."/".$szTileId.$szImageExtension;
|
336
|
clearstatcache();
|
337
|
|
338
|
$szMetaDir = $szCacheDir."/meta";
|
339
|
if (!@is_Dir($szMetaDir))
|
340
|
makeDirs($szMetaDir);
|
341
|
|
342
|
/* simple locking in case there are several requests for the same meta
|
343
|
tile at the same time - only draw it once to help with performance */
|
344
|
$szLockFile = $szMetaDir."/lock_".$metaTop."_".$metaLeft;
|
345
|
$fpLockFile = fopen($szLockFile, "a+");
|
346
|
clearstatcache();
|
347
|
if (!file_exists($szCacheFile) || $bForce)
|
348
|
{
|
349
|
flock($fpLockFile, LOCK_EX);
|
350
|
fwrite($fpLockFile, ".");
|
351
|
|
352
|
//check once more to see if the cache file was created while waiting for
|
353
|
//the lock
|
354
|
clearstatcache();
|
355
|
if (!file_exists($szCacheFile) || $bForce)
|
356
|
{
|
357
|
if (!extension_loaded('MapScript'))
|
358
|
{
|
359
|
dl( $szPHPMapScriptModule );
|
360
|
}
|
361
|
if (!extension_loaded('gd'))
|
362
|
{
|
363
|
dl( $szPHPGDModule);
|
364
|
}
|
365
|
|
366
|
if (!@is_Dir($szMetaDir))
|
367
|
makeDirs($szMetaDir);
|
368
|
|
369
|
$oMap = ms_newMapObj($szMapFile);
|
370
|
|
371
|
/* Metatile width/height include 2x the metaBuffer value */
|
372
|
$oMap->set('width', $tileWidth * $metaWidth + 2*$metaBuffer);
|
373
|
$oMap->set('height', $tileHeight * $metaHeight + 2*$metaBuffer);
|
374
|
|
375
|
/* Tell MapServer to not render labels inside the metaBuffer area
|
376
|
* (new in 4.6)
|
377
|
* TODO: Until MapServer bugs 1353/1355 are resolved, we need to
|
378
|
* pass a negative value for "labelcache_map_edge_buffer"
|
379
|
*/
|
380
|
$oMap->setMetadata("labelcache_map_edge_buffer", -$metaBuffer);
|
381
|
|
382
|
$inchesPerUnit = array(1, 12, 63360.0, 39.3701, 39370.1, 4374754);
|
383
|
$geoWidth = $scale/($oMap->resolution*$inchesPerUnit[$oMap->units]);
|
384
|
$geoHeight = $scale/($oMap->resolution*$inchesPerUnit[$oMap->units]);
|
385
|
|
386
|
/* draw the metatile */
|
387
|
$minx = $metaLeft * $geoWidth;
|
388
|
$maxx = $minx + $geoWidth * $oMap->width;
|
389
|
$maxy = -1 * $metaTop * $geoHeight;
|
390
|
$miny = $maxy - $geoHeight * $oMap->height;
|
391
|
|
392
|
$nLayers = $oMap->numlayers;
|
393
|
$oMap->setExtent($minx,$miny,$maxx,$maxy);
|
394
|
$oMap->selectOutputFormat( $szMapImageFormat );
|
395
|
$aszLayers = array();
|
396
|
if ($groups || $layers)
|
397
|
{
|
398
|
/* Draw only specified layers instead of default from mapfile*/
|
399
|
if ($layers)
|
400
|
{
|
401
|
$aszLayers = explode(",", $layers);
|
402
|
}
|
403
|
|
404
|
if ($groups)
|
405
|
{
|
406
|
$aszGroups = explode(",", $groups);
|
407
|
}
|
408
|
|
409
|
for($i=0;$i<$nLayers;$i++)
|
410
|
{
|
411
|
$oLayer = $oMap->getLayer($i);
|
412
|
if (($aszGroups && in_array($oLayer->group,$aszGroups)) ||
|
413
|
($aszLayers && in_array($oLayer->name,$aszLayers)) ||
|
414
|
($aszGroups && $oLayer->group == '' &&
|
415
|
in_array( "__base__", $aszGroups)))
|
416
|
{
|
417
|
$oLayer->set("status", MS_ON );
|
418
|
}
|
419
|
else
|
420
|
{
|
421
|
$oLayer->set("status", MS_OFF );
|
422
|
}
|
423
|
}
|
424
|
//need transparency if groups or layers are used
|
425
|
$oMap->outputformat->set("transparent", MS_ON );
|
426
|
}
|
427
|
else
|
428
|
{
|
429
|
$oMap->outputformat->set("transparent", MS_OFF );
|
430
|
}
|
431
|
|
432
|
|
433
|
$szMetaImg = $szMetaDir."/t".$metaTop."l".$metaLeft.$szImageExtension;
|
434
|
$oImg = $oMap->draw();
|
435
|
$oImg->saveImage($szMetaImg);
|
436
|
$oImg->free();
|
437
|
eval("\$oGDImg = ".$szMapImageCreateFunction."('".$szMetaImg."');");
|
438
|
if ($bDebug)
|
439
|
{
|
440
|
$blue = imagecolorallocate($oGDImg, 0, 0, 255);
|
441
|
imagerectangle($oGDImg, 0, 0, $tileWidth * $metaWidth - 1, $tileHeight * $metaHeight - 1, $blue );
|
442
|
}
|
443
|
for($i=0;$i<$metaWidth;$i++)
|
444
|
{
|
445
|
for ($j=0;$j<$metaHeight;$j++)
|
446
|
{
|
447
|
eval("\$oTile = ".$szImageCreateFunction."( ".$tileWidth.",".$tileHeight." );");
|
448
|
// Allocate BG color for the tile (in case the metatile has transparent BG)
|
449
|
$nTransparent = imagecolorallocate($oTile, $oMap->imagecolor->red, $oMap->imagecolor->green, $oMap->imagecolor->blue);
|
450
|
//if ($oMap->outputformat->transparent == MS_ON)
|
451
|
//{
|
452
|
imagecolortransparent( $oTile,$nTransparent);
|
453
|
//}
|
454
|
$tileTop = $j*$tileHeight + $metaBuffer;
|
455
|
$tileLeft = $i*$tileWidth + $metaBuffer;
|
456
|
imagecopy( $oTile, $oGDImg, 0, 0, $tileLeft, $tileTop, $tileWidth, $tileHeight );
|
457
|
/* debugging stuff */
|
458
|
if ($bDebug)
|
459
|
{
|
460
|
$black = imagecolorallocate($oTile, 1, 1, 1);
|
461
|
$green = imagecolorallocate($oTile, 0, 128, 0 );
|
462
|
$red = imagecolorallocate($oTile, 255, 0, 0);
|
463
|
imagerectangle( $oTile, 1, 1, $tileWidth-2, $tileHeight-2, $green );
|
464
|
imageline( $oTile, 0, $tileHeight/2, $tileWidth-1, $tileHeight/2, $red);
|
465
|
imageline( $oTile, $tileWidth/2, 0, $tileWidth/2, $tileHeight-1, $red);
|
466
|
imagestring ( $oTile, 3, 10, 10, ($metaLeft+$tileLeft)." x ".($metaTop+$tileTop), $black );
|
467
|
imagestring ( $oTile, 3, 10, 30, ($minx+$i*$geoWidth)." x ".($maxy - $j*$geoHeight), $black );
|
468
|
}
|
469
|
$szTileImg = $szCacheDir."/t".($metaTop+$tileTop)."l".($metaLeft+$tileLeft).$szImageExtension;
|
470
|
eval("$szImageOutputFunction( \$oTile, '".$szTileImg."' );");
|
471
|
imagedestroy($oTile);
|
472
|
$oTile = null;
|
473
|
}
|
474
|
}
|
475
|
if ($oGDImg != null)
|
476
|
{
|
477
|
imagedestroy($oGDImg);
|
478
|
$oGDImg = null;
|
479
|
}
|
480
|
if (!$bDebug)
|
481
|
{
|
482
|
unlink( $szMetaImg );
|
483
|
}
|
484
|
}
|
485
|
//release the exclusive lock
|
486
|
flock($fpLockFile, LOCK_UN );
|
487
|
}
|
488
|
|
489
|
//acquire shared lock for reading to prevent a problem that could occur
|
490
|
//if a tile exists but is only partially generated.
|
491
|
flock($fpLockFile, LOCK_SH);
|
492
|
|
493
|
$h = fopen($szCacheFile, "r");
|
494
|
header("Content-Type: ".$szImageHeader);
|
495
|
header("Content-Length: " . filesize($szCacheFile));
|
496
|
header("Expires: " . date( "D, d M Y H:i:s GMT", time() + 31536000 ));
|
497
|
header("Cache-Control: max-age=31536000, must-revalidate" );
|
498
|
fpassthru($h);
|
499
|
fclose($h);
|
500
|
|
501
|
//release lock
|
502
|
fclose($fpLockFile);
|
503
|
|
504
|
/* bug 1253 - root permissions required to delete cached files */
|
505
|
umask($orig_umask);
|
506
|
|
507
|
exit;
|
508
|
?>
|