1 /*
2 IIP OJB Command Handler Class Member Functions
3
4 Copyright (C) 2006-2019 Ruven Pillay.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software Foundation,
18 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
19 */
20
21
22 #include "Task.h"
23 #include <iostream>
24 #include <algorithm>
25
26
27 using namespace std;
28
29
30
run(Session * s,const std::string & a)31 void OBJ::run( Session* s, const std::string& a )
32 {
33
34 argument = a;
35 // Convert to lower case the argument supplied to the OBJ command
36 transform( argument.begin(), argument.end(), argument.begin(), ::tolower );
37
38 session = s;
39
40 // Log this
41 if( session->loglevel >= 3 ) *(session->logfile) << "OBJ :: " << argument << " to be handled" << endl;
42
43 // Time this command
44 if( session->loglevel >= 2 ) command_timer.start();
45
46
47 if( argument == "iip,1.0" ) iip();
48 else if( argument == "basic-info" ){
49 iip_server();
50 max_size();
51 resolution_number();
52 colorspace( "*,*" );
53 }
54 else if( argument == "iip-server" ) iip_server();
55 // IIP optional commands
56 else if( argument == "iip-opt-comm" ) session->response->addResponse( "IIP-opt-comm:CVT CNT QLT JTL JTLS WID HEI RGN MINMAX SHD CMP INV CTW" );
57 // IIP optional objects
58 else if( argument == "iip-opt-obj" ) session->response->addResponse( "IIP-opt-obj:Horizontal-views Vertical-views Tile-size Bits-per-channel Min-Max-sample-values Resolutions" );
59 // Resolution-number
60 else if( argument == "resolution-number" ) resolution_number();
61 // Max-size
62 else if( argument == "max-size" ) max_size();
63 // Tile-size
64 else if( argument == "tile-size" ) tile_size();
65 // Bits per pixel
66 else if( argument == "bits-per-channel" ) bits_per_channel();
67 // Vertical-views
68 else if( argument == "vertical-views" ) vertical_views();
69 // Horizontal-views
70 else if( argument == "horizontal-views" ) horizontal_views();
71 // Minimum and maximum provided by TIFF tags
72 else if( argument == "min-max-sample-values" ) min_max_values();
73 // List of available resolutions
74 else if( argument == "resolutions" ) resolutions();
75
76 // Colorspace
77 /* The request can have a suffix, which we don't need, so do a
78 like scan
79 */
80 else if( argument.find( "colorspace" ) != string::npos ){
81 colorspace( "*,*" );
82 }
83
84 // Image Metadata
85 else if( argument == "summary-info" ){
86
87 metadata( "copyright" );
88 metadata( "subject" );
89 metadata( "author" );
90 metadata( "create-dtm" );
91 metadata( "app-name" );
92 }
93
94 else if( argument == "copyright" || argument == "title" ||
95 argument == "subject" || argument == "author" ||
96 argument == "keywords" || argument == "comment" ||
97 argument == "last-author" || argument == "rev-number" ||
98 argument == "edit-time" || argument == "last-printed" ||
99 argument == "create-dtm" || argument == "last-save-dtm" ||
100 argument == "app-name" ){
101
102 metadata( argument );
103 }
104
105
106 // None of the above!
107 else{
108
109 if( session->loglevel >= 1 ){
110 *(session->logfile) << "OBJ :: Unsupported argument: " << argument << " received" << endl;
111 }
112
113 // Unsupported object error code is 3 2
114 session->response->setError( "3 2", argument );
115 }
116
117
118 if( session->loglevel >= 2 ){
119 *(session->logfile) << "OBJ :: Total command time " << command_timer.getTime() << " microseconds" << endl;
120 }
121
122
123 }
124
125
126
iip()127 void OBJ::iip(){
128 session->response->setProtocol( "IIP:1.0" );
129 }
130
131
iip_server()132 void OBJ::iip_server(){
133 // The binary capability code is 1000001 == 65 in integer
134 // ie can do CVT jpeg and JTL, but no transforms
135 session->response->addResponse( "IIP-server:3.65" );
136 }
137
138
max_size()139 void OBJ::max_size(){
140 checkImage();
141 int x = (*session->image)->getImageWidth();
142 int y = (*session->image)->getImageHeight();
143
144 // For 90 and 270 rotation swap width and height
145 if( (int)((session->view)->getRotation()) % 180 == 90 ){
146 unsigned int tmp = x;
147 x = y;
148 y = tmp;
149 }
150
151 if( session->loglevel >= 2 ){
152 *(session->logfile) << "OBJ :: Max-size is " << x << " " << y << endl;
153 }
154 session->response->addResponse( "Max-size", x, y );
155 }
156
157
resolution_number()158 void OBJ::resolution_number(){
159
160 checkImage();
161 int no_res = (*session->image)->getNumResolutions();
162 if( session->loglevel >= 2 ){
163 *(session->logfile) << "OBJ :: Resolution-number handler returning " << no_res << endl;
164 }
165 session->response->addResponse( "Resolution-number", no_res );
166
167 }
168
169
tile_size()170 void OBJ::tile_size(){
171 checkImage();
172
173 int x = (*session->image)->getTileWidth();
174 int y = (*session->image)->getTileHeight();
175 if( session->loglevel >= 2 ){
176 *(session->logfile) << "OBJ :: Tile-size is " << x << " " << y << endl;
177 }
178 session->response->addResponse( "Tile-size", x, y );
179 }
180
181
bits_per_channel()182 void OBJ::bits_per_channel(){
183
184 checkImage();
185 int bpc = (*session->image)->getNumBitsPerPixel();
186 if( session->loglevel >= 2 ){
187 *(session->logfile) << "OBJ :: Bits-per-channel handler returning " << bpc << endl;
188 }
189 session->response->addResponse( "Bits-per-channel", bpc );
190
191 }
192
193
vertical_views()194 void OBJ::vertical_views(){
195 checkImage();
196 list <int> views = (*session->image)->getVerticalViewsList();
197 list <int> :: const_iterator i;
198 string tmp = "Vertical-views:";
199 char val[8];
200 for( i = views.begin(); i != views.end(); i++ ){
201 snprintf( val, 8, "%d ", *i );
202 tmp += val;
203 }
204 // Chop off the final space
205 tmp.resize( tmp.length() - 1 );
206 session->response->addResponse( tmp );
207 }
208
209
horizontal_views()210 void OBJ::horizontal_views(){
211 checkImage();
212 list <int> views = (*session->image)->getHorizontalViewsList();
213 list <int> :: const_iterator i;
214 string tmp = "Horizontal-views:";
215 char val[8];
216 for( i = views.begin(); i != views.end(); i++ ){
217 snprintf( val, 8, "%d ", *i );
218 tmp += val;
219 }
220 // Chop off the final space
221 tmp.resize( tmp.length() - 1 );
222 session->response->addResponse( tmp );
223 }
224
225
min_max_values()226 void OBJ::min_max_values(){
227
228 checkImage();
229 unsigned int n = (*session->image)->getNumChannels();
230 string tmp = "Min-Max-sample-values:";
231 char val[24];
232 float minimum, maximum;
233 for( unsigned int i=0; i<n ; i++ ){
234 minimum = (*session->image)->getMinValue(i);
235 maximum = (*session->image)->getMaxValue(i);
236 snprintf( val, 24, " %.9g ", minimum );
237 tmp += val;
238 snprintf( val, 24, " %.9g ", maximum );
239 tmp += val;
240 }
241 // Chop off the final space
242 tmp.resize( tmp.length() - 1 );
243 session->response->addResponse( tmp );
244 if( session->loglevel >= 2 ){
245 *(session->logfile) << "OBJ :: Min-Max-sample-values handler returning " << tmp << endl;
246 }
247
248 }
249
250
resolutions()251 void OBJ::resolutions(){
252
253 checkImage();
254 char val[32];
255 int num_res = (*session->image)->getNumResolutions();
256
257 string tmp = "Resolutions:";
258 for( int i=num_res-1; i>=0; i-- ){
259 snprintf( val, 32, "%d %d", (*session->image)->image_widths[i], (*session->image)->image_heights[i] );
260 tmp += val;
261 if( i>0 ) tmp += ",";
262 }
263 session->response->addResponse( tmp );
264 if( session->loglevel >= 2 ){
265 *(session->logfile) << "OBJ :: Resolutions handler returning " << tmp << endl;
266 }
267 }
268
269
colorspace(std::string arg)270 void OBJ::colorspace( std::string arg ){
271
272 checkImage();
273
274 /* Assign the colourspace tag: 1 for greyscale, 3 for RGB and
275 a colourspace of 4 to LAB images
276 WARNING: LAB support is an extension and is not in the
277 IIP protocol standard (as of version 1.05)
278 */
279 const char *planes = "3 0 1 2";
280 int calibrated = 0;
281 int colourspace;
282 if( (*session->image)->getColourSpace() == CIELAB ){
283 colourspace = 4;
284 calibrated = 1;
285 }
286 else if( (*session->image)->getColourSpace() == GREYSCALE ){
287 colourspace = 1;
288 planes = "1 0";
289 }
290 else colourspace = 3;
291
292 int no_res = (*session->image)->getNumResolutions();
293 char tmp[41];
294 snprintf( tmp, 41, "Colorspace,0-%d,0:%d 0 %d %s", no_res-1,
295 calibrated, colourspace, planes );
296
297 if( session->loglevel >= 2 ){
298 *(session->logfile) << "OBJ :: Colourspace handler returning " << tmp << endl;
299 }
300
301 session->response->addResponse( tmp );
302 }
303
304
metadata(string field)305 void OBJ::metadata( string field ){
306
307 checkImage();
308
309 string metadata = (*session->image)->getMetadata( field );
310 if( session->loglevel >= 3 ){
311 *(session->logfile) << "OBJ :: " << field << " handler returning '" << metadata << "'" << endl;
312 }
313
314 if( metadata.length() ){
315 session->response->addResponse( field, metadata );
316 }
317
318
319 }
320