~jstys-z/helioviewer.org/client5

« back to all changes in this revision

Viewing changes to api/lib/helioviewer/no-mod-imagick/JP2Image.php

  • Committer: V. Keith Hughitt
  • Date: 2009-03-17 21:05:22 UTC
  • Revision ID: hughitt1@kore-20090317210522-cm4hoy9tv1fi850c
nightly build 03-17-2009

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
<?php
2
 
require_once('DbConnection.php');
3
 
 
4
 
abstract class JP2Image {
5
 
        protected $kdu_expand   = CONFIG::KDU_EXPAND;
6
 
        protected $kdu_lib_path = CONFIG::KDU_LIBS_DIR;
7
 
        protected $cacheDir     = CONFIG::CACHE_DIR;
8
 
        protected $jp2Dir       = CONFIG::JP2_DIR;
9
 
        protected $noImage      = CONFIG::EMPTY_TILE;
10
 
        protected $baseScale    = 2.63; //Scale of an EIT image at the base zoom-level: 2.63 arcseconds/px
11
 
        protected $baseZoom     = 10;   //Zoom-level at which (EIT) images are of this scale.
12
 
        
13
 
        protected $db;
14
 
        protected $xRange;
15
 
        protected $yRange;
16
 
        protected $zoomLevel;
17
 
        protected $tileSize;
18
 
        protected $desiredScale;
19
 
        
20
 
        protected $image;
21
 
                
22
 
        protected function __construct($zoomLevel, $xRange, $yRange, $tileSize) {
23
 
                date_default_timezone_set('UTC');
24
 
                $this->db = new DbConnection();
25
 
                $this->zoomLevel = $zoomLevel;
26
 
                $this->tileSize  = $tileSize;
27
 
                $this->xRange    = $xRange;
28
 
                $this->yRange    = $yRange;
29
 
 
30
 
                // Determine desired image scale
31
 
                $this->zoomOffset   = $zoomLevel - $this->baseZoom;
32
 
                $this->desiredScale = $this->baseScale * (pow(2, $this->zoomOffset));
33
 
        }
34
 
        
35
 
        /**
36
 
         * extractRegion
37
 
         * @return Returns an Imagick object representing the extracted region
38
 
         */
39
 
        protected function extractRegion($input, $output, $imageWidth, $imageHeight, $imageScale, $detector, $measurement) {
40
 
                $cmd = "$this->kdu_expand -i " . $input . " -o $output ";
41
 
                
42
 
                // Ratio of the desired scale to the actual JP2 image scale
43
 
                $desiredToActual = $this->desiredScale / $imageScale;
44
 
                
45
 
                // Scale Factor
46
 
                $scaleFactor = log($desiredToActual, 2);                
47
 
                
48
 
                $relTs = $this->tileSize * $desiredToActual;
49
 
                
50
 
                // Case 1: JP2 image resolution = desired resolution
51
 
                // Nothing special to do...
52
 
 
53
 
                // Case 2: JP2 image resolution > desired resolution (use -reduce)              
54
 
                if ($imageScale < $this->desiredScale) {
55
 
                        $cmd .= "-reduce " . $scaleFactor . " ";
56
 
                }
57
 
 
58
 
                // Case 3: JP2 image resolution < desired resolution (get smaller tile and then enlarge)
59
 
                // Don't do anything yet...
60
 
                
61
 
                // Check to see if the tile requested is within the range of available data
62
 
                //$xRange = ceil($imageWidth  / (2 * $desiredToActual * $this->tileSize));
63
 
                //$yRange = ceil($imageHeight / (2 * $desiredToActual * $this->tileSize));
64
 
                //if ((abs($x) > $xRange) || (abs($y) > $yRange)) {
65
 
                //      print "Out of range tile request... Range- x: $xRange, y: $yRange";
66
 
                //      exit();
67
 
                //}
68
 
                
69
 
                // Add desired region
70
 
                $cmd .= $this->getRegionString($imageWidth, $imageHeight, $relTs);
71
 
                //print $cmd;
72
 
 
73
 
                
74
 
                // Execute the command
75
 
                try {
76
 
                        exec('export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:' . "$this->kdu_lib_path; " . $cmd, $out, $ret);
77
 
                        
78
 
                        if ($ret != 0)
79
 
                                throw new Exception("Failed to expand requested sub-region!<br><br> <b>Command:</b> '$cmd'");
80
 
                                
81
 
                } catch(Exception $e) {
82
 
                        echo '<span style="color:red;">Error:</span> ' .$e->getMessage();
83
 
                        exit();
84
 
                }
85
 
                
86
 
                $imcmd = "convert $output ";
87
 
 
88
 
                // For images with transparent components, convert pixels with value "0" to be transparent.
89
 
                if ($measurement == "0WL")
90
 
                        $imcmd .= "-transparent black ";
91
 
                
92
 
                // Get dimensions of extracted region
93
 
                $dimensions = split("x", trim(exec("identify $output | grep -o \" [0-9]*x[0-9]* \"")));
94
 
                $tileWidth  = $dimensions[0];
95
 
                $tileHeight = $dimensions[1];
96
 
 
97
 
                // Pad up the the relative tilesize (in cases where region extract for outer tiles is smaller than for inner tiles)
98
 
                //$tileWidth  = $im->getImageWidth();
99
 
                //$tileHeight = $im->getImageHeight();
100
 
                //if (($relTs < $this->tileSize) && (($tileWidth < $relTs) || ($tileHeight < $relTs))) {
101
 
                //      $this->padImage($im, $tileWidth, $tileHeight, $relTs, $this->xRange["start"], $this->yRange["start"]);
102
 
                //}
103
 
                
104
 
                
105
 
                // Apply color table
106
 
                if (($detector == "EIT") || ($measurement == "0WL")) {
107
 
                        $clut = $this->getColorTable($detector, $measurement);
108
 
                        $imcmd .= "$clut -clut ";
109
 
                }
110
 
                
111
 
                // Pad if tile is smaller than it should be (Case 2)
112
 
                if ($imageScale < $this->desiredScale) {
113
 
                        $imcmd .= $this->padImage($tif, $this->tileSize, $this->xRange["start"], $this->yRange["start"], $relTs);
114
 
                }
115
 
 
116
 
                // Resize if necessary (Case 3)
117
 
                if ($relTs < $this->tileSize)
118
 
                        $imcmd .= "-geometry " . $this->tileSize . "x" . $this->tileSize . "! ";
119
 
                        //exec("convert -geometry " . $this->tileSize . "x" . $this->tileSize . "! $tif $tif", $out, $ret);
120
 
                        //$im->scaleImage($this->tileSize, $this->tileSize);
121
 
 
122
 
                exec($imcmd . "$output");
123
 
 
124
 
                //echo $imcmd . $tif;
125
 
 
126
 
                //return $im;
127
 
                return $output;
128
 
        }
129
 
        
130
 
        /**
131
 
         * getRegionString
132
 
         * Build a region string to be used by kdu_expand. e.g. "-region {0.0,0.0},{0.5,0.5}"
133
 
         */
134
 
        public function getRegionString($jp2Width, $jp2Height, $ts) {
135
 
                // Parameters
136
 
                $top = $left = $width = $height = null;
137
 
                
138
 
                // Number of tiles for the entire image
139
 
                $imgNumTilesX = max(2, ceil($jp2Width  / $ts));
140
 
                $imgNumTilesY = max(2, ceil($jp2Height / $ts));
141
 
                
142
 
                // Tile placement architecture expects an even number of tiles along each dimension
143
 
                if ($imgNumTilesX % 2 != 0)
144
 
                        $imgNumTilesX += 1;
145
 
 
146
 
                if ($imgNumTilesY % 2 != 0)
147
 
                        $imgNumTilesY += 1;
148
 
                        
149
 
                // Shift so that 0,0 now corresponds to the top-left tile
150
 
                $relX = (0.5 * $imgNumTilesX) + $this->xRange["start"];
151
 
                $relY = (0.5 * $imgNumTilesY) + $this->yRange["start"];
152
 
 
153
 
                // number of tiles (may be greater than one for movies, etc)
154
 
                $numTilesX = min($imgNumTilesX - $relX, $this->xRange["end"] - $this->xRange["start"] + 1);
155
 
                $numTilesY = min($imgNumTilesY - $relY, $this->yRange["end"] - $this->yRange["start"] + 1);
156
 
 
157
 
                // Number of "inner" tiles
158
 
                $numTilesInsideX = $imgNumTilesX - 2;
159
 
                $numTilesInsideY = $imgNumTilesY - 2;
160
 
                
161
 
                // Dimensions for inner and outer tiles
162
 
                $innerTS = $ts;
163
 
                $outerTS = ($jp2Width - ($numTilesInsideX * $innerTS)) / 2;
164
 
                
165
 
                // <top>
166
 
                $top  = (($relY == 0) ? 0 :  $outerTS + ($relY - 1) * $innerTS) / $jp2Height;
167
 
 
168
 
                // <left>
169
 
                $left = (($relX == 0) ? 0 :  $outerTS + ($relX - 1) * $innerTS) / $jp2Width;
170
 
                
171
 
                // <height>
172
 
                $height = ((($relY == 0) || ($relY == (imgNumTilesY -1))) ? $outerTS : $innerTS) / $jp2Height;
173
 
                
174
 
                // <width>
175
 
                $width  = ((($relX == 0) || ($relX == (imgNumTilesX -1))) ? $outerTS : $innerTS) / $jp2Width;
176
 
 
177
 
                // {<top>,<left>},{<height>,<width>}
178
 
                $region = "-region \{$top,$left\},\{$height,$width\}";
179
 
 
180
 
                return $region;
181
 
        }
182
 
        
183
 
        /**
184
 
         * padImage
185
 
         */
186
 
        //function padImage($im, $ts, $x, $y) {
187
 
        function padImage($tif, $ts, $x, $y, $relTs) {
188
 
                $padx = $ts - $relTs;
189
 
                $pady = $ts - $relTs;
190
 
 
191
 
                // top-left
192
 
                if (($x == -1) && ($y == -1))
193
 
                        return "-background transparent -gravity SouthEast -extent $ts" . "x" . "$ts ";
194
 
 
195
 
                // top-right
196
 
                if (($x == 0) && ($y == -1))
197
 
                        return "-background transparent -gravity SouthWest -extent $ts" . "x" . "$ts ";
198
 
 
199
 
                // bottom-right
200
 
                if (($x == 0) && ($y == 0))
201
 
                        return "-background transparent -gravity NorthWest -extent $ts" . "x" . "$ts ";
202
 
 
203
 
                // bottom-left
204
 
                if (($x == -1) && ($y == 0))
205
 
                        return "-background transparent -gravity NorthEast -extent $ts" . "x" . "$ts ";
206
 
 
207
 
        }
208
 
        
209
 
        private function padImage ($im, $jp2Width, $jp2Height, $tileWidth, $tileHeight, $ts, $x, $y) {
210
 
                // Determine min and max tile numbers
211
 
                $imgNumTilesX = max(2, ceil($jp2Width  / $ts));
212
 
                $imgNumTilesY = max(2, ceil($jp2Height / $ts));
213
 
                $tileMinX = - ($imgNumTilesX / 2);
214
 
                $tileMaxX =   ($imgNumTilesX / 2) - 1;
215
 
                $tileMinY = - ($imgNumTilesY / 2);
216
 
                $tileMaxY =   ($imgNumTilesY / 2) - 1; 
217
 
                                
218
 
                // Determine where the tile is located (where tile should lie in the padding)
219
 
                $gravity = null;
220
 
                if ($x == $tileMinX) {
221
 
                        if ($y == $tileMinY) {
222
 
                                $gravity = "SouthEast";
223
 
                        }
224
 
                        else if ($y == $tileMaxY) {
225
 
                                $gravity = "NorthEast";
226
 
                        }
227
 
                        else {
228
 
                                $gravity = "East";
229
 
                        }
230
 
                }
231
 
                else if ($x == $tileMaxX) {
232
 
                        if ($y == $tileMinY) {
233
 
                                $gravity = "SouthWest";
234
 
                        }
235
 
                        else if ($y == $tileMaxY) {
236
 
                                $gravity = "NorthWest";
237
 
                        }
238
 
                        else {
239
 
                                $gravity = "West";
240
 
                        }
241
 
                }
242
 
                
243
 
                else {
244
 
                        if ($y == $tileMinY) {
245
 
                                $gravity = "South";
246
 
                        }
247
 
                        else {
248
 
                                $gravity = "North";
249
 
                        }
250
 
                }
251
 
                
252
 
                // Construct padding command
253
 
                return "-background transparent -gravity $gravity -extent $ts" . "x" . "$ts ";
254
 
        }
255
 
        
256
 
        private function getColorTable($detector, $measurement) {
257
 
                if ($detector == "EIT") {
258
 
                        return "/home/esahelio/public_html/images/color-tables/ctable_EIT_$measurement.png";
259
 
                }
260
 
                else if ($detector == "0C2") {
261
 
                        return "/home/esahelio/public_html/images/color-tables/ctable_idl_3.png";
262
 
                }
263
 
                else if ($detector == "0C3") {
264
 
                        return "/home/esahelio/public_html/images/color-tables/ctable_idl_1.png";
265
 
                }               
266
 
        }
267
 
        
268
 
        public function display() {
269
 
                // Cache-Lifetime (in minutes)
270
 
                $lifetime = 60;
271
 
                $exp_gmt = gmdate("D, d M Y H:i:s", time() + $lifetime * 60) ." GMT";
272
 
                header("Expires: " . $exp_gmt);
273
 
                header("Cache-Control: public, max-age=" . $lifetime * 60);
274
 
 
275
 
                // Special header for MSIE 5
276
 
                header("Cache-Control: pre-check=" . $lifetime * 60, FALSE);
277
 
                
278
 
                header( "Content-Type: image/png" );
279
 
                //echo $this->image;
280
 
            readfile($this->image);
281
 
        }
282
 
}
283
 
?>