Ticket #5: RasdamanUtils.java

File RasdamanUtils.java, 13.7 KB (added by Andrei Aiordachioaie, 15 years ago)
Line 
1/*
2 * This file is part of PetaScope.
3 *
4 * PetaScope is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as
6 * published by the Free Software Foundation, either version 3 of
7 * the License, or (at your option) any later version.
8 *
9 * PetaScope is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
16 *
17 * For more information please see <http://www.PetaScope.org>
18 * or contact Peter Baumann via <baumann@rasdaman.com>.
19 *
20 * Copyright 2009 Jacobs University Bremen, Peter Baumann.
21 */
22
23
24package wcst.transaction.tools;
25
26//~--- non-JDK imports --------------------------------------------------------
27
28import org.odmg.DBag;
29import org.odmg.Database;
30import org.odmg.Implementation;
31import org.odmg.ODMGException;
32import org.odmg.OQLQuery;
33import org.odmg.Transaction;
34
35import rasj.RasGMArray;
36import rasj.RasImplementation;
37import rasj.RasMInterval;
38import rasj.RasResultIsNoIntervalException;
39
40import wcst.transaction.WCSTException;
41
42//~--- JDK imports ------------------------------------------------------------
43
44import java.awt.Graphics;
45import java.awt.image.BufferedImage;
46import java.awt.image.DataBuffer;
47
48import java.io.ByteArrayInputStream;
49
50import java.util.Iterator;
51
52/**
53 * Utility class for doing various tasks that involve the Rasdaman server.
54 *
55 * @author Andrei Aiordachioaie
56 */
57public class RasdamanUtils
58{
59 Implementation myApp = null;
60 Database myDb = null;
61 Transaction myTa = null;
62 private String base;
63 private String server;
64
65 /**
66 * Simple constructor
67 *
68 * @param s server string
69 * @param b database name
70 */
71 public RasdamanUtils(String s, String b)
72 {
73 this.server = s;
74 this.base = b;
75 }
76
77 public void log(String msg)
78 {
79 System.err.flush();
80 System.out.println("Rasdaman Utils: " + msg);
81 System.out.flush();
82 }
83
84 /**
85 * Opens a new connection to the Rasdaman server, and starts a new transaction.
86 * @throws WCSTException on connection error
87 */
88 public void init() throws WCSTException
89 {
90 try
91 {
92 if ( myApp == null )
93 {
94 myApp = new RasImplementation(server);
95 }
96 if ( myDb == null )
97 {
98 myDb = myApp.newDatabase();
99 log("Opening database...");
100 myDb.open(base, Database.OPEN_READ_WRITE);
101 }
102 if ( myTa == null )
103 {
104 log("Beginning new transaction ...");
105 myTa = myApp.newTransaction();
106 myTa.begin();
107 }
108 }
109 catch (Exception e)
110 {
111// e.printStackTrace();
112 throw new WCSTException("RasdamanUnavailable",
113 "Could not connect to the Rasdaman server !");
114 }
115 }
116
117 public void commitAndClose() throws ODMGException
118 {
119 if ( myTa != null )
120 {
121 log("Commiting transaction ...");
122 myTa.commit();
123 myTa = null;
124 }
125 if ( myDb != null )
126 {
127 log("Closing database...");
128 myDb.close();
129 myDb = null;
130 }
131 log("Finished !");
132 }
133
134 public void abortAndClose() throws ODMGException
135 {
136 if ( myTa != null )
137 {
138 log("Aborting transaction...");
139 myTa.abort();
140 myTa = null;
141 }
142 if ( myDb != null )
143 {
144 log("Closing database...");
145 myDb.close();
146 myDb = null;
147 }
148 log("Finished !");
149 }
150
151 public BufferedImage loadCoverage(String name) throws Exception
152 {
153 init();
154
155 log("Running Load Coverage " + name + " query!");
156 OQLQuery myQu = myApp.newOQLQuery();
157
158 myQu.create("select jpeg(" + name + ") from " + name);
159 DBag resultSet = (DBag) myQu.execute();
160
161 if ( resultSet != null )
162 {
163 log("Query successful !");
164 Iterator iter = resultSet.iterator();
165
166 if ( iter.hasNext() )
167 {
168 RasGMArray result = (RasGMArray) iter.next();
169 byte[] ba = result.getArray();
170 ByteArrayInputStream bas = new ByteArrayInputStream(ba);
171 com.sun.image.codec.jpeg.JPEGImageDecoder decoder = com.sun.image.codec.jpeg
172 .JPEGCodec.createJPEGDecoder(bas);
173 BufferedImage bufImg = null;
174
175 try
176 {
177 bufImg = decoder.decodeAsBufferedImage();
178 }
179 catch (Exception e)
180 {
181 System.err.println("Error decoding the image !!!");
182 }
183
184 commitAndClose();
185
186 return bufImg;
187 }
188 }
189
190 abortAndClose();
191
192 return null;
193 }
194
195 public RasGMArray createMDD() throws RasResultIsNoIntervalException
196 {
197 // create 2-D MDD with cell length 1, i.e., type “byte”:
198 RasGMArray myMDD = new RasGMArray(new RasMInterval("[1:400,1:400]"), 1);
199 // byte container for array data, matching in size:
200 byte[] mydata = new byte[160000];
201
202 // initialize array as grid of gray and black stripes:
203 for (int y = 0; y < 400; y++)
204 for (int x = 0; x < 400; x++)
205 mydata[y * 399 + x] = (byte) ((y % 4) > 1
206 ? 80
207 : 0);
208 // now insert byte array into MDD object
209 // (sets only the pointer, no copying takes place!):
210 myMDD.setArray(mydata);
211
212 return myMDD;
213 }
214
215 public void insertGrayImageAsArray(String name) throws ODMGException
216 {
217 try
218 {
219 init();
220
221 log("Creating grey image ...");
222 RasGMArray myMDD = createMDD();
223 // set up query object for collection creation:
224 OQLQuery myQu = myApp.newOQLQuery();
225
226 myQu.create("create collection " + name + " GreySet");
227 // set the object type name (used for server type checking):
228 myMDD.setObjectTypeName("GreyImage");
229 // finally, execute “create collection” statement:
230 log("Creating collection '" + name + "'");
231 myQu.execute();
232 // now create the insert statement:
233 myQu.create("insert into " + name + " values $1");
234 // let the server generate a new OID for the object to be
235 // inserted, and remember this OID locally:
236 String myNewOID = myApp.getObjectId(myMDD);
237
238 // bind the MDD value which substitutes formal parameter $1:
239 myQu.bind(myMDD);
240 // 
and ship the complete statement to the server:
241 log("Inserting data into the collection");
242 myQu.execute();
243 log("Done !");
244
245 commitAndClose();
246 }
247 catch (Exception e)
248 {
249 e.printStackTrace();
250 abortAndClose();
251 }
252 }
253
254 public void updateGrayImageWithArray(String name, BufferedImage img, int x1, int y1, int x2,
255 int y2)
256 {
257 try
258 {
259 log("Building query for updating gray image ...");
260 RasGMArray myMDD = createMddFromImage(img);
261
262 myMDD.setObjectTypeName("GreyImage");
263 // set up query object for collection creation:
264 OQLQuery myQu = myApp.newOQLQuery();
265 // Where to insert new image
266 String interval = String.valueOf(x1) + ":" + String.valueOf(x2) + ","
267 + String.valueOf(y1) + ":" + String.valueOf(y2);
268 // Size of new image
269 String interval2 = String.valueOf(0) + ":" + String.valueOf(x2 - x1) + ","
270 + String.valueOf(0) + ":" + String.valueOf(y2 - y1);
271
272 myQu.create("update " + name + " AS c SET c[" + interval + "] "
273 + "assign maaray x in [" + interval2 + "] values $1");
274 // let the server generate a new OID for the object to be
275 // inserted, and remember this OID locally:
276 String myNewOID = myApp.getObjectId(myMDD);
277
278 // bind the MDD value which substitutes formal parameter $1:
279 myQu.bind(myMDD);
280 // 
and ship the complete statement to the server:
281 log("Updating image ...");
282 myQu.execute();
283 log("Done !");
284 }
285 catch (Exception e)
286 {
287 e.printStackTrace();
288 }
289 }
290
291 public void insertGrayImageAsArray(String name, BufferedImage img) throws ODMGException
292 {
293 try
294 {
295 log("Creating grey image ...");
296 RasGMArray myMDD = createMddFromImage(img);
297 // set up query object for collection creation:
298 OQLQuery myQu = myApp.newOQLQuery();
299
300 myQu.create("create collection " + name + " GreySet");
301 // set the object type name (used for server type checking):
302 myMDD.setObjectTypeName("GreyImage");
303 // finally, execute “create collection” statement:
304 log("Creating collection '" + name + "'");
305 myQu.execute();
306 // now create the insert statement:
307 myQu.create("insert into " + name + " values $1");
308 // let the server generate a new OID for the object to be
309 // inserted, and remember this OID locally:
310 String myNewOID = myApp.getObjectId(myMDD);
311
312 // bind the MDD value which substitutes formal parameter $1:
313 myQu.bind(myMDD);
314 // 
and ship the complete statement to the server:
315 log("Inserting data into the collection");
316 myQu.execute();
317 log("Done !");
318 }
319 catch (Exception e)
320 {
321 e.printStackTrace();
322 }
323 }
324
325 public void insertColorImageAsArray(String name, BufferedImage img) throws ODMGException
326 {
327 try
328 {
329 log("Creating grey image ...");
330 RasGMArray myMDD = createMddFromImage(img);
331 // set up query object for collection creation:
332 OQLQuery myQu = myApp.newOQLQuery();
333
334 myQu.create("create collection " + name + " RGBSet");
335 // set the object type name (used for server type checking):
336 myMDD.setObjectTypeName("RGBImage");
337 // finally, execute “create collection” statement:
338 log("Creating collection '" + name + "'");
339 myQu.execute();
340 // now create the insert statement:
341 myQu.create("insert into " + name + " values $1");
342 // let the server generate a new OID for the object to be
343 // inserted, and remember this OID locally:
344 String myNewOID = myApp.getObjectId(myMDD);
345
346 // bind the MDD value which substitutes formal parameter $1:
347 myQu.bind(myMDD);
348 // 
and ship the complete statement to the server:
349 log("Inserting data into the collection");
350 myQu.execute();
351 log("Done !");
352 }
353 catch (Exception e)
354 {
355 e.printStackTrace();
356 }
357 }
358
359 public void insertImageAsJpeg(String name, byte[] img, int maxX, int maxY) throws ODMGException
360 {
361 try
362 {
363 init();
364
365 log("Creating image from bytes ...");
366 RasGMArray myMDD = createRasArrayFromBytes(img, maxX, maxY);
367 // set up query object for collection creation:
368 OQLQuery myQu = myApp.newOQLQuery();
369
370 myQu.create("create collection " + name + " GreySet");
371 // set the object type name (used for server type checking):
372 myMDD.setObjectTypeName("GreyImage");
373 // finally, execute “create collection” statement:
374 log("Creating collection '" + name + "'");
375 myQu.execute();
376 // now create the insert statement:
377 myQu.create("insert into " + name + " values inv_jpeg($1)");
378 // let the server generate a new OID for the object to be
379 // inserted, and remember this OID locally:
380 String myNewOID = myApp.getObjectId(myMDD);
381
382 // bind the MDD value which substitutes formal parameter $1:
383 myQu.bind(myMDD);
384 // 
and ship the complete statement to the server:
385 log("Inserting data into the collection");
386 myQu.execute();
387 log("Done !");
388
389 commitAndClose();
390 }
391 catch (Exception e)
392 {
393 System.out.flush();
394 e.printStackTrace();
395 System.err.flush();
396 abortAndClose();
397 }
398 }
399
400 private RasGMArray createRasArrayFromBytes(byte[] bytes, int maxX, int maxY)
401 throws RasResultIsNoIntervalException
402 {
403 // create 2-D MDD with cell length 1, i.e., type “byte”:
404 String strX = String.valueOf(maxX), strY = String.valueOf(maxY);
405 String interval = "[1:" + strX + "],1:" + strY + "]";
406 // FIXME: maybe change cell type?
407 int cellType = 1;
408
409 // create the RasGMArray object
410 RasGMArray myMDD = new RasGMArray(new RasMInterval(interval), cellType);
411
412 myMDD.setArray(bytes);
413
414 return myMDD;
415 }
416
417 public void deleteCollection(String name)
418 throws ODMGException, ODMGException, ODMGException, Exception
419 {
420 try
421 {
422// init();
423
424 log("Creating query...");
425 // set up query object for collection creation:
426 OQLQuery myQu = myApp.newOQLQuery();
427
428 myQu.create("drop collection " + name);
429 // finally, execute “create collection” statement:
430 log("Executing deletion query...");
431 myQu.execute();
432 // now create the insert statement:
433 log("Query finished !");
434
435// commitAndClose();
436 }
437 catch (Exception e)
438 {
439 e.printStackTrace();
440
441 throw e;
442// abortAndClose();
443 }
444 }
445
446 public void printAllCollections() throws ODMGException
447 {
448 String query = "select r from RAS_COLLECTIONNAMES as r";
449
450// init();
451
452 log("Querying for all available collections ...");
453 OQLQuery myQu = myApp.newOQLQuery();
454
455 myQu.create(query);
456
457 DBag resultSet = (DBag) myQu.execute();
458
459 if ( resultSet != null )
460 {
461 Iterator iter = resultSet.iterator();
462
463 while (iter.hasNext())
464 {
465 RasGMArray result = (RasGMArray) iter.next();
466 byte[] ba = result.getArray();
467 String name = new String(ba);
468
469 if ( name.endsWith("\u0000") )
470 {
471 name = name.substring(0, name.length() - (new String("\u0000")).length());
472 }
473
474 System.out.println("* " + name);
475 }
476 }
477
478// commitAndClose();
479 }
480
481 public RasGMArray createMddFromImage(BufferedImage img) throws RasResultIsNoIntervalException
482 {
483 int cols = img.getWidth();
484 int rows = img.getHeight();
485 // create 2-D MDD with cell length 1, i.e., type “byte”:
486 String interval = "[1:" + cols + ",1:" + rows + "]";
487 int cellType = 1;
488
489 // create the RasGMArray object
490 RasGMArray myMDD = new RasGMArray(new RasMInterval(interval), cellType);
491 DataBuffer db = img.getData().getDataBuffer();
492 byte[] bytes = new byte[cols * rows];
493
494 System.out.println("Processing image with size: " + interval);
495 System.out.println("Created vector with size: " + cols * rows);
496 System.out.println("Processing data with size: " + db.getSize());
497 int i = 0;
498
499 /*
500 * Java image data-types store an image as a 1-D array, reading the
501 * image row-wise. Rasdaman stores the image column-wise. So we need to
502 * convert between the two representations.
503 */
504 for (int c = 0; c < cols; c++)
505 for (int r = 0; r < rows; r++)
506 {
507 bytes[i++] = (byte) db.getElem(r * cols + c);
508 }
509 myMDD.setArray(bytes);
510
511 return myMDD;
512 }
513
514 public BufferedImage convertImageToGray(BufferedImage img)
515 {
516 BufferedImage image = new BufferedImage(img.getWidth(), img.getHeight(),
517 BufferedImage.TYPE_BYTE_GRAY);
518 Graphics g = image.getGraphics();
519
520 g.drawImage(img, 0, 0, null);
521 g.dispose();
522
523 return image;
524 }
525}