1 /*
2 IIP Zoomify Request Command Handler Class Member Function
3
4 * Development carried out thanks to R&D grant DC08P02OUK006 - Old Maps Online *
5 * (www.oldmapsonline.org) from Ministry of Culture of the Czech Republic *
6
7
8 Copyright (C) 2008-2015 Ruven Pillay.
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software Foundation,
22 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
23 */
24
25 #include <cmath>
26
27 #include "Task.h"
28 #include "Transforms.h"
29 #include "Tokenizer.h"
30
31
32
33 using namespace std;
34
35
36
run(Session * session,const std::string & argument)37 void Zoomify::run( Session* session, const std::string& argument ){
38
39 if( session->loglevel >= 3 ) (*session->logfile) << "Zoomify handler reached" << endl;
40
41 // Time this command
42 if( session->loglevel >= 2 ) command_timer.start();
43
44
45 // The argument is in the form Zoomify=TileGroup0/r-x-y.jpg where r is the resolution
46 // number and x and y are the tile coordinates starting from the bottom left.
47 string prefix, suffix;
48 suffix = argument.substr( argument.find_last_of( "/" )+1, argument.length() );
49
50 // We need to extract the image path, which is not always the same
51 if( suffix == "ImageProperties.xml" )
52 prefix = argument.substr( 0, argument.find_last_of( "/" ) );
53 else
54 prefix = argument.substr( 0, argument.find( "TileGroup" )-1 );
55
56
57 // As we don't have an independent FIF request, we need to run it now
58 FIF fif;
59 fif.run( session, prefix );
60
61
62 // Get the full image size and the total number of resolutions available
63 unsigned int width = (*session->image)->getImageWidth();
64 unsigned int height = (*session->image)->getImageHeight();
65
66
67 unsigned int tw = (*session->image)->getTileWidth();
68 unsigned int numResolutions = (*session->image)->getNumResolutions();
69
70
71 // Zoomify does not accept arbitrary numbers of resolutions. The lowest
72 // level must be the largest size that can fit within a single tile, so
73 // we must discard any smaller than this
74 unsigned int n;
75
76 unsigned int discard = 0;
77
78 for( n=0; n<numResolutions; n++ ){
79 if( (*session->image)->image_widths[n] < tw && (*session->image)->image_heights[n] < tw ){
80 discard++;
81 }
82 }
83
84
85 if( discard > 0 ) discard -= 1;
86
87 if( session->loglevel >= 2 ){
88 if( discard > 0 ){
89 *(session->logfile) << "Zoomify :: Discarding " << discard << " resolutions that are too small for Zoomify" << endl;
90 }
91 }
92
93 // Zoomify clients have 2 phases, the initialization phase where they request
94 // an XML file containing image data and the tile requests themselves.
95 // These 2 phases are handled separately
96 if( suffix == "ImageProperties.xml" ){
97
98 if( session->loglevel >= 2 ){
99 *(session->logfile) << "Zoomify :: ImageProperties.xml request" << endl;
100 *(session->logfile) << "Zoomify :: Total resolutions: " << numResolutions << ", image width: " << width
101 << ", image height: " << height << endl;
102 }
103
104 int ntiles = (int) ceil( (double)width/tw ) * (int) ceil( (double)height/tw );
105
106 char str[1024];
107 snprintf( str, 1024,
108 "Server: iipsrv/%s\r\n"
109 "Content-Type: application/xml\r\n"
110 "Last-Modified: %s\r\n"
111 "%s\r\n"
112 "\r\n"
113 "<IMAGE_PROPERTIES WIDTH=\"%d\" HEIGHT=\"%d\" NUMTILES=\"%d\" NUMIMAGES=\"1\" VERSION=\"1.8\" TILESIZE=\"%d\" />",
114 VERSION, (*session->image)->getTimestamp().c_str(), session->response->getCacheControl().c_str(), width, height, ntiles, tw );
115
116 session->out->printf( (const char*) str );
117 session->response->setImageSent();
118
119 return;
120 }
121
122
123 // Get the tile coordinates. Zoomify requests are of the form r-x-y.jpg
124 // where r is the resolution number and x and y are the tile coordinates
125 Tokenizer izer( suffix, "-" );
126 int resolution=0, x=0, y=0;
127 if( izer.hasMoreTokens() ) resolution = atoi( izer.nextToken().c_str() );
128 if( izer.hasMoreTokens() ) x = atoi( izer.nextToken().c_str() );
129 if( izer.hasMoreTokens() ) y = atoi( izer.nextToken().c_str() );
130
131 // Bump up to take account of any levels too small for Zoomify
132 resolution += discard;
133
134 if( session->loglevel >= 2 ){
135 *(session->logfile) << "Zoomify :: Tile request for resolution:"
136 << resolution << " at x:" << x << ", y:" << y << endl;
137 }
138
139
140 // Get the width and height for the requested resolution
141 width = (*session->image)->getImageWidth(numResolutions-resolution-1);
142 height = (*session->image)->getImageHeight(numResolutions-resolution-1);
143
144
145 // Get the width of the tiles and calculate the number
146 // of tiles in each direction
147 unsigned int rem_x = width % tw;
148 unsigned int ntlx = (width / tw) + (rem_x == 0 ? 0 : 1);
149
150
151 // Calculate the tile index for this resolution from our x, y
152 unsigned int tile = y*ntlx + x;
153
154
155 // Simply pass this on to our JTL send command
156 JTL jtl;
157 jtl.send( session, resolution, tile );
158
159
160 // Total Zoomify response time
161 if( session->loglevel >= 2 ){
162 *(session->logfile) << "Zoomify :: Total command time " << command_timer.getTime() << " microseconds" << endl;
163 }
164
165
166 }
167