Statistics
| Revision:

root / trunk / libraries / libRaster / src / org / gvsig / raster / util / RasterUtilities.java @ 13359

History | View | Annotate | Download (25.1 KB)

1
package org.gvsig.raster.util;
2

    
3
import java.awt.Dimension;
4
import java.awt.geom.AffineTransform;
5
import java.awt.geom.Dimension2D;
6
import java.awt.geom.NoninvertibleTransformException;
7
import java.awt.geom.Point2D;
8
import java.awt.geom.Rectangle2D;
9
import java.io.BufferedOutputStream;
10
import java.io.BufferedReader;
11
import java.io.DataOutputStream;
12
import java.io.File;
13
import java.io.FileInputStream;
14
import java.io.FileNotFoundException;
15
import java.io.FileOutputStream;
16
import java.io.FileReader;
17
import java.io.IOException;
18
import java.io.InputStream;
19
import java.io.OutputStream;
20

    
21
import org.gvsig.raster.buffer.RasterBuffer;
22
import org.gvsig.raster.dataset.io.rmf.RmfBlocksManager;
23
import org.gvsig.raster.dataset.serializer.GeoInfoRmfSerializer;
24
import org.gvsig.raster.datastruct.Extent;
25

    
26
import es.gva.cit.jgdal.Gdal;
27

    
28
/**
29
 * 
30
 * @author Nacho Brodin (nachobrodin@gmail.com)
31
 *
32
 */
33
public class RasterUtilities {        
34
        public static final        int MAX_BYTE_BIT_VALUE        = 255;
35
        public static final        int MAX_SHORT_BIT_VALUE        = 65535;
36
            
37
    //---------------------------------------------------------------
38
    //TIPOS DE DATOS
39
    
40
    /**
41
     * Conversi?n de los tipos de datos de gdal a los tipos de datos de 
42
     * RasterBuf
43
     * @param gdalType Tipo de dato de gdal
44
     * @return Tipo de dato de RasterBuf
45
     */
46
    public static int getRasterBufTypeFromGdalType(int gdalType){
47
            switch(gdalType){
48
                case 1:return  RasterBuffer.TYPE_BYTE;//GDT_BYTE 
49
                case 2://GDT_UInt16
50
                case 8://GDT_CInt16
51
                case 3:return RasterBuffer.TYPE_SHORT;//GDT_Int16        
52
                case 4://GDT_UInt32
53
                case 9://GDT_CInt32
54
                case 5:return RasterBuffer.TYPE_INT;//GDT_Int32
55
                case 10://GDT_CFloat32
56
                case 6:return RasterBuffer.TYPE_FLOAT;//GDT_Float32
57
                case 11://GDT_CFloat64
58
                case 7:return RasterBuffer.TYPE_DOUBLE;//GDT_Float64
59
                }
60
            return RasterBuffer.TYPE_UNDEFINED;
61
    }
62
    
63
    /**
64
     * Conversi?n de los tipos de datos de RasterBuf en los de gdal.
65
     * @param rasterBufType Tipo de dato de RasterBuf
66
     * @return Tipo de dato de Gdal
67
     */
68
    public static int getGdalTypeFromRasterBufType(int rasterBufType){
69
            switch(rasterBufType){
70
                case RasterBuffer.TYPE_BYTE:return Gdal.GDT_Byte;
71
                case RasterBuffer.TYPE_USHORT: return Gdal.GDT_UInt16;
72
                case RasterBuffer.TYPE_SHORT: return Gdal.GDT_Int16;
73
                case RasterBuffer.TYPE_INT: return Gdal.GDT_Int32;
74
                case RasterBuffer.TYPE_FLOAT: return Gdal.GDT_Float32;
75
                case RasterBuffer.TYPE_DOUBLE: return Gdal.GDT_Float64;
76
                case RasterBuffer.TYPE_UNDEFINED: return Gdal.GDT_Unknown;
77
                case RasterBuffer.TYPE_IMAGE: return Gdal.GDT_Byte;
78
                }
79
            return Gdal.GDT_Unknown;
80
    }
81
    
82
    /**
83
     * Conversi?n de los tipos de datos de MrSID a los tipos de datos de 
84
     * RasterBuf
85
     * @param mrsidType Tipo de dato de MrSID
86
     * @return Tipo de dato de RasterBuf
87
     */
88
    public static int getRasterBufTypeFromMrSIDType(int mrsidType){
89
            switch(mrsidType){
90
            case 0:return RasterBuffer.TYPE_UNDEFINED;//INVALID
91
                case 1://UINT8 
92
                case 2:return  RasterBuffer.TYPE_BYTE;//SINT8
93
                case 3://UINT16
94
                case 4:return RasterBuffer.TYPE_SHORT;//SINT16        
95
                case 5://UINT32
96
                case 6:return RasterBuffer.TYPE_INT;//SINT32        
97
                case 7:return RasterBuffer.TYPE_FLOAT;//FLOAT32
98
                case 8:return RasterBuffer.TYPE_DOUBLE;//FLOAT64
99
                }
100
            return RasterBuffer.TYPE_UNDEFINED;
101
    }
102
    
103
    /**
104
     * Obtiene el n?mero de bytes que ocupa un tipo de dato concreto. 
105
     * Los tipos de datos son los utilizados en RasterBuffer
106
     * @param rasterBufType Tipo de dato del que se solicita el n?mero de bytes ocupados
107
     * @return
108
     */
109
    public static int getBytesFromRasterBufType(int rasterBufType){
110
            switch(rasterBufType){
111
                case RasterBuffer.TYPE_BYTE:return 1;
112
                case RasterBuffer.TYPE_USHORT:
113
                case RasterBuffer.TYPE_SHORT: return 2;
114
                case RasterBuffer.TYPE_INT:
115
                case RasterBuffer.TYPE_FLOAT:
116
                case RasterBuffer.TYPE_IMAGE: return 4;
117
                case RasterBuffer.TYPE_DOUBLE: return 8;
118
                }
119
            return 0; //TYPE_UNDEFINED
120
    }
121
    
122
    /**
123
     * Convierte un tipo de dato a cadena
124
     * @param type Tipo de dato
125
     * @return cadena  que representa el tipo de dato
126
     */
127
    public static String typesToString(int type) {
128
        switch (type) {
129
        case RasterBuffer.TYPE_IMAGE:
130
            return new String("Image");
131

    
132
        case RasterBuffer.TYPE_BYTE:
133
            return new String("Byte");
134

    
135
        case RasterBuffer.TYPE_DOUBLE:
136
            return new String("Double");
137

    
138
        case RasterBuffer.TYPE_FLOAT:
139
            return new String("Float");
140

    
141
        case RasterBuffer.TYPE_INT:
142
                return new String("Integer");
143
                
144
        case RasterBuffer.TYPE_USHORT:
145
        case RasterBuffer.TYPE_SHORT:
146
            return new String("Short");
147
        }
148

    
149
        return null;
150
    }
151
    
152
    /**
153
     * Parseo de las proyecciones que genera gdal para meter espaciados y saltos de l?nea HTML
154
     * @param proj Proyecci?n
155
     * @return Cadena con la proyecci?n parseada
156
     */
157
    public static String parserGdalProj(String proj){
158
            if(proj == null)
159
                    return "";
160
            String[] list = proj.split(",");
161
            int level = 0;
162
            for(int i = 0; i < list.length; i++){
163
                    if(list[i].indexOf("[") >= 0){
164
                            level ++;
165
                            String spaces = "";
166
                            for(int j = 0; j < level; j++)
167
                                    spaces += "&nbsp;&nbsp;"; 
168
                            list[i] = spaces + list[i];
169
                    }
170
                    if(list[i].indexOf("]]") >= 0)
171
                            level = level - 2;
172
                    else if(list[i].indexOf("]") >= 0)
173
                            level --;
174
            }
175
            StringBuffer str = new StringBuffer();            
176
            for(int i = 0; i < list.length; i++){
177
                    if(i < list.length){
178
                            if(i + 1 < list.length && list[i + 1].indexOf("[") >= 0)
179
                                    str.append(list[i] + ",<BR>");
180
                            else
181
                                    str.append(list[i] + ",");
182
                    }
183
            }
184
            return str.toString();
185
    }
186
        
187
    //---------------------------------------------------------------
188
    //ESPACIO DE COLOR
189
    
190
    /**
191
     * Descompone un entero que representa un ARGB en sus 4 valores byte
192
     * Obtiene un array de 4 elementos donde el elemento 0 es el Rojo, el 1 es el
193
     * verde, el 2 el azul y el 3 el alpha.
194
     * @param rgb Entero con el valor ARGB a descomponer;
195
     * @return Array de cuatro elementos
196
     */
197
    public static byte[] getARGBFromIntToByteArray(int rgb){
198
            byte[] b = new byte[4];
199
            b[0] = (byte)((rgb & 0x00ff0000) >> 16);
200
            b[1] = (byte)((rgb & 0x0000ff00) >> 8);
201
            b[2] = (byte)(rgb & 0x000000ff);
202
            b[3] = (byte)((rgb & 0xff000000) >> 24);
203
            return b;
204
    }
205
    
206
    /**
207
     * Descompone un entero que representa un ARGB en sus 4 valores byte
208
     * Obtiene un array de 4 elementos donde el elemento 0 es el Rojo, el 1 es el
209
     * verde, el 2 el azul y el 3 el alpha.
210
     * @param rgb Entero con el valor ARGB a descomponer;
211
     * @return
212
     */
213
    public static int[] getARGBFromIntToIntArray(int rgb){
214
            int[] i = new int[4];
215
            i[0] = (((rgb & 0x00ff0000) >> 16) & 0xff);
216
            i[1] = (((rgb & 0x0000ff00) >> 8) & 0xff);
217
            i[2] = ((rgb & 0x000000ff) & 0xff);
218
            i[3] = (((rgb & 0xff000000) >> 24) & 0xff);
219
            return i;
220
    }
221
    
222
    /**
223
     * Obtiene un entero con los valores ARGB pasados por par?metro
224
     * @param a Valor de alpha
225
     * @param r Valor del rojo
226
     * @param g Valor del verde
227
     * @param b Valor del azul
228
     * @return entero con la mezcla de valores
229
     */
230
    public static int getIntFromARGB(int a, int r, int g, int b){
231
              return (((a & 0xff) << 24) + ((r & 0xff) << 16) + ((g & 0xff) << 8) + (b & 0xff));
232
    }
233
    
234
    //---------------------------------------------------------------
235
    //CONVERSI?N DE COORDENADAS
236
    
237
    /**
238
     * Convierte una ventana en coordenadas del mundo real a sus coordenadas relativas en pixels teniendo
239
     * en cuenta que la coordenada superior izquierda es 0,0 y la inferior derecha es maxX y maY
240
     * @param extent Extent de la imagen original
241
     * @param widthPx Ancho en pixeles de la imagen original
242
     * @param heightPx Alto en pixeles de la imagen original
243
     * @param window Ventana en coordenadas reales a transportar a coordenadas pixel
244
     * @return Ventana en coordenadas pixel
245
     */
246
    public static Rectangle2D getPxRectFromMapRect(Rectangle2D extent, double widthPx, double heightPx, Rectangle2D window){
247
            double widthWC = extent.getWidth();
248
                double heightWC = extent.getHeight();
249
                
250
                double wWindowWC = Math.abs(window.getMaxX() - window.getMinX());
251
                   double hWindowWC = Math.abs(window.getMaxY() - window.getMinY());
252
                   
253
                   double wWindowPx = ((wWindowWC * widthPx) /  widthWC);
254
                   double hWindowPx = ((hWindowWC * heightPx) /  heightWC);
255
                   
256
                   double initDistanceX = Math.abs(window.getMinX() - extent.getMinX());
257
                   double initDistanceY = Math.abs(window.getMaxY() - extent.getMaxY());
258
                   
259
                   double initPxX = ((initDistanceX * widthPx) /  widthWC);
260
                   double initPxY = ((initDistanceY * heightPx) /  heightWC);
261
                   
262
                   Rectangle2D pxRec = new Rectangle2D.Double(        initPxX, 
263
                                                                                                           initPxY,
264
                                                                                                           wWindowPx,
265
                                                                                                           hWindowPx); 
266
                   return pxRec;
267
    }
268
    
269
    /**
270
     * Convierte una ventana en coordenadas del mundo real a sus coordenadas relativas en pixels teniendo
271
     * en cuenta que la coordenada superior izquierda es 0,0 y la inferior derecha es maxX y maY
272
     * @param extent Extent de la imagen original
273
     * @param widthPx Ancho en pixeles de la imagen original
274
     * @param heightPx Alto en pixeles de la imagen original
275
     * @param window Ventana en coordenadas reales a transportar a coordenadas pixel
276
     * @return Ventana en coordenadas pixel
277
     */
278
    public static Rectangle2D getMapRectFromPxRect(Rectangle2D extent, double widthPx, double heightPx, Rectangle2D pxWindow){
279
                   double wWindowWC = ((pxWindow.getWidth() * extent.getWidth()) /  widthPx);
280
                   double hWindowWC = ((pxWindow.getHeight() * extent.getHeight()) /  heightPx);
281
                   
282
                   double initWCX = extent.getMinX() + ((pxWindow.getMinX() * extent.getWidth()) /  widthPx);
283
                   double initWCY = extent.getMaxY() - ((pxWindow.getMinY() * extent.getHeight()) /  heightPx);
284
                   
285
                   Rectangle2D mapRec = new Rectangle2D.Double(initWCX, 
286
                                                                                                           initWCY - hWindowWC,
287
                                                                                                           wWindowWC,
288
                                                                                                           hWindowWC); 
289
                   return mapRec;
290
    }
291
    
292
    /**
293
     * Convierte un punto en coordenadas del mundo a coordenadas pixel
294
     * @param p Punto a convertir
295
     * @param ext Extent completo de la imagen
296
     * @return Punto en coordenadas pixel
297
     */
298
    public static Point2D worldPointToRaster(Point2D p, Extent ext, int pxWidth, int pxHeight) { 
299
            double x = p.getX() - ext.getMin().getX();
300
            double y = p.getY() - ext.getMin().getY();
301
            int pxX = (int)((x * pxWidth) / ext.width());
302
            int pxY = (int)((y * pxHeight) / ext.height());
303
            return new Point2D.Double(pxX, pxY);
304
    }
305
    
306
    /**
307
     * Ajusta la extensi?n pasada por par?metro a los valores m?ximos y m?nimos de la 
308
     * imagen. Esto sirve para que la petici?n al driver nunca sobrepase los l?mites 
309
     * de la imagen tratada aunque la vista donde se dibuje sea de mayor tama?o.
310
     * 
311
     * @param imgExt Extent completo de la vista donde se va a dibujar.
312
     * @param extToAdj Extent a ajustar.
313
     * @return adjustedExtent Extent ajustado a m?ximos y m?nimos
314
     */
315
    public static Extent calculateAdjustedView(Extent extToAdj, Extent imgExt) { 
316
        double vx = extToAdj.minX();
317
        double vy = extToAdj.minY();
318
        double vx2 = extToAdj.maxX();
319
        double vy2 = extToAdj.maxY();
320

    
321
        if (extToAdj.minX() < imgExt.minX())
322
            vx = imgExt.minX();
323
        
324
        if (extToAdj.minY() < imgExt.minY()) 
325
            vy = imgExt.minY();
326
        
327
        if (extToAdj.maxX() > imgExt.maxX()) 
328
            vx2 = imgExt.maxX();
329
        
330
        if (extToAdj.maxY() > imgExt.maxY())
331
            vy2 = imgExt.maxY();
332
        
333
        return new Extent(vx, vy, vx2, vy2);
334
    }
335
    
336
    /**
337
     * Ajusta la extensi?n pasada por par?metro a los valores m?ximos y m?nimos de la 
338
     * imagen. Esto sirve para que la petici?n al driver nunca sobrepase los l?mites 
339
     * de la imagen tratada aunque la vista donde se dibuje sea de mayor tama?o. Este m?todo 
340
     * tiene en cuenta la rotaci?n aplicada al raster por lo que no ajustamos a un extent sino
341
     * a una matriz de transformaci?n. Esta tiene los par?metros de traslaci?n, rotaci?n y
342
     * escalado del raster destino. Esta matriz transforma coordenadas pixel a real y viceversa.
343
     * 
344
     * @param imgExt Extent completo de la vista donde se va a dibujar.
345
     * @param AffineTransform Matriz de transformaci?n del raster destino
346
     * @return adjustedExtent Extent ajustado a m?ximos y m?nimos
347
     */
348
    public static Extent calculateAdjustedView(Extent extToAdj, AffineTransform at, Dimension2D dim) { 
349
            //Obtenemos los cuatro puntos de la petici?n de origen
350
                Point2D ul = new Point2D.Double(extToAdj.getULX(), extToAdj.getULY());
351
                Point2D lr = new Point2D.Double(extToAdj.getLRX(), extToAdj.getLRY());
352
                
353
                //Los convertimos a coordenadas pixel con la matriz de transformaci?n
354
                try {
355
                        at.inverseTransform(ul, ul);
356
                        at.inverseTransform(lr, lr);
357
                } catch (NoninvertibleTransformException e) {
358
                        return extToAdj;
359
                }
360
                
361
                //Ajustamos a la dimensi?n del raster en pixeles
362
        if (ul.getX() < 0)
363
            ul.setLocation(0, ul.getY());
364
        if (ul.getX() >= dim.getWidth())
365
            ul.setLocation(dim.getWidth(), ul.getY());
366
        if (ul.getY() < 0)
367
            ul.setLocation(ul.getX(), 0);
368
        if (ul.getY() >= dim.getHeight())
369
            ul.setLocation(ul.getX(), dim.getHeight());
370
        
371
        if (lr.getX() < 0)
372
                lr.setLocation(0, lr.getY());
373
        if (lr.getX() >= dim.getWidth())
374
                lr.setLocation(dim.getWidth(), lr.getY());
375
        if (lr.getY() < 0)
376
                lr.setLocation(lr.getX(), 0);
377
        if (lr.getY() >= dim.getHeight())
378
                lr.setLocation(lr.getX(), dim.getHeight());
379
        
380
        //Lo convertimos a coordenadas reales nuevamente
381
        at.transform(ul, ul);
382
        at.transform(lr, lr);
383
        return new Extent(ul, lr);
384
    }
385
    
386
    /**
387
     * Compara dos extents y devuelve true si son iguales
388
     * @param e1 Extent a comparar
389
     * @param e2 Extent a comparar
390
     * @return true si los extents pasados por par?metro son iguales y false si no lo son
391
     */
392
    public static boolean compareExtents(Extent e1, Extent e2){
393
            return ((e1.getMin().getX() == e2.getMin().getX()) && (e1.getMin().getY() == e2.getMin().getY()) &&
394
                            (e1.getMax().getX() == e2.getMax().getX())) && (e1.getMax().getY() == e2.getMax().getY());
395
    }
396
    
397
    /**
398
     * Comprueba si un extent est? contenido dentro de otro y devuelve true en este caso.
399
     * @param e1 Extent a comprobar si est? contenido en e2
400
     * @param e2 Extent sobre el que se comprueba si e1 est? dentro
401
     * @return true si e1 est? dentro de e1
402
     */
403
    public static boolean isInside(Extent e1, Extent e2){
404
            return ((e1.getMin().getX() >= e2.getMin().getX()) && (e1.getMin().getY() >= e2.getMin().getY()) &&
405
                            (e1.getMax().getX() <= e2.getMax().getX())) && (e1.getMax().getY() <= e2.getMax().getY());
406
    }
407
    
408
    /**
409
     * Comprueba si un extent est? fuera de otro extent que tenemos como referencia.
410
     * @param e1 Extent a comprobar si est? fuera
411
     * @param ref Extent de referencia
412
     * @return Devuelve true si todo el extent cae fuera de ref y false si no est? fuera.
413
     */
414
    public static boolean isOutside(Extent e1, Extent ref){
415
            return ((e1.getMin().getX() > ref.getMax().getX()) || (e1.getMin().getY() > ref.getMax().getY()) ||
416
                            (e1.getMax().getX() < ref.getMin().getX()) || (e1.getMax().getY() < ref.getMin().getY()));
417
    }
418
    
419
        /**
420
         * Calcula los par?metros de un worl file a partir de las esquinas del raster.
421
         *    1. X pixel size A
422
         *    2. X rotation term D
423
         *    3. Y rotation term B
424
         *    4. Y pixel size E
425
         *    5. X coordinate of upper left corner C
426
         *    6. Y coordinate of upper left corner F
427
         * where the real-world coordinates x',y' can be calculated from
428
         * the image coordinates x,y with the equations
429
         *  x' = Ax + By + C and y' = Dx + Ey + F.
430
         *  The signs of the first 4 parameters depend on the orientation
431
         *  of the image. In the usual case where north is more or less
432
         *  at the top of the image, the X pixel size will be positive
433
         *  and the Y pixel size will be negative. For a south-up image,
434
         *  these signs would be reversed.
435
         * 
436
         * You can calculate the World file parameters yourself based
437
         * on the corner coordinates. The X and Y pixel sizes can be
438
         *  determined simply by dividing the distance between two
439
         *  adjacent corners by the number of columns or rows in the image.
440
         *  The rotation terms are calculated with these equations:
441
         * 
442
         *  # B = (A * number_of_columns + C - lower_right_x') / number_of_rows * -1
443
         *  # D = (E * number_of_rows + F - lower_right_y') / number_of_columns * -1
444
         * 
445
         * @param corner (tl, tr, br, bl)
446
         * @return
447
         */
448
        public static double [] cornersToWorldFile(Point2D [] esq, Dimension size) {
449
                double a = 0, b = 0, c = 0, d = 0, e = 0, f = 0;
450
                double x1 = esq[0].getX(), y1 = esq[0].getY();
451
                double x2 = esq[1].getX(), y2 = esq[1].getY();
452
                double x3 = esq[2].getX(), y3 = esq[2].getY();
453
                double x4 = esq[3].getX(), y4 = esq[3].getY();
454
                // A: X-scale
455
                a = Math.abs( Math.sqrt( (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2))
456
                      / size.getWidth());
457

    
458
                // E: negative Y-scale
459
                e =  - Math.abs(Math.sqrt((x1 - x4) * (x1 - x4) +
460
                      (y1 - y4) * (y1 - y4)) / size.getHeight());
461

    
462
                // C, F: upper-left coordinates
463
                c = x1;
464
                f = y1;
465
                
466
                // B & D: rotation parameters
467
                b = (a * size.getWidth() + c - x3 ) / size.getHeight() * -1;
468
                d = (e * size.getHeight() + f - y3 ) / size.getWidth() * -1;
469

    
470
                double [] wf = {a, d, b, e, c, f}; 
471
                return wf;  
472
        }
473
        
474
        /**
475
         * Ajusta el valor del array de puntos pasado como primer par?metro a las 
476
         * dimensiones de la imagen. Estas dimensiones ser?n 0-dim.getX() a 0-dim.getY(). Para cada
477
         * valor, si es menor que 0 se pondr?  a 0 y si es mayor del m?ximo se asignar? al m?ximo.
478
         * @param points Lista de puntos a ajustar
479
         * @param dim Dimension
480
         */
481
        public static void adjustToPixelSize(Point2D[] points, Point2D dim) {
482
                for (int i = 0; i < points.length; i++) {
483
                        if(points[i].getX() < 0)
484
                                points[i].setLocation(0, points[i].getY());
485
                        if(points[i].getX() >= (dim.getX() - 1))
486
                                points[i].setLocation(dim.getX() - 1, points[i].getY());        
487
                        if(points[i].getY() < 0)
488
                                points[i].setLocation(points[i].getX(), 0);
489
                        if(points[i].getY() >= (dim.getY() - 1))
490
                                points[i].setLocation(points[i].getX(), dim.getY() - 1);
491
                }
492
        }
493
        
494
    //---------------------------------------------------------------
495
    //TRATAMIENTO DE FICHEROS
496
    
497
    /**
498
     * Copia de ficheros
499
     * @param pathOrig Ruta de origen
500
     * @param pathDst Ruta de destino.
501
     */
502
    public static void copyFile(String pathOrig, String pathDst) 
503
            throws FileNotFoundException, IOException{
504
             InputStream in;
505
             OutputStream out;
506
             
507
             if(pathOrig == null || pathDst == null){
508
                     System.err.println("Error en path");
509
                     return;
510
             }
511
             
512
             File orig = new File(pathOrig);
513
             if(!orig.exists() || !orig.isFile() || !orig.canRead()){
514
                     System.err.println("Error en fichero de origen");
515
                     return;
516
             }
517
             
518
             File dest = new File(pathDst);
519
             String file = pathOrig.substring(pathOrig.lastIndexOf(File.separator), pathOrig.length());
520
             if(dest.isDirectory())
521
                     pathDst += file;
522
            
523
             in = new FileInputStream(pathOrig);
524
             out = new FileOutputStream(pathDst);
525
            
526
             byte[] buf = new byte[1024];
527
             int len;
528
             
529
             while ((len = in.read(buf)) > 0)
530
                        out.write(buf, 0, len);
531
                
532
             in.close();
533
             out.close();
534
    }
535
    
536
    /**
537
         * Crea un fichero de georeferenciaci?n (world file) para un dataset determinado
538
         * @param GdalDriver
539
         * @param fileName Nombre completo del fichero de raster
540
         * @param Extent 
541
         * @param pxWidth Ancho en p?xeles
542
         * @param pxHeight Alto en p?xeles
543
         * @return
544
         * @throws IOException
545
         */
546
        public static void createWorldFile(String fileName, Extent ext, int pxWidth, int pxHeight) throws IOException {
547
            File tfw = null;
548
            
549
            String extWorldFile = ".wld";
550
            if(fileName.endsWith("tif"))
551
                    extWorldFile = ".tfw";
552
            if(fileName.endsWith("jpg") || fileName.endsWith("jpeg"))
553
                    extWorldFile = ".jpgw";
554
                                
555
            tfw = new File(fileName.substring(0, fileName.lastIndexOf(".")) + extWorldFile);
556
            
557
            //Generamos un world file para gdal
558
            DataOutputStream dos = new DataOutputStream( new BufferedOutputStream(new FileOutputStream(tfw)) );
559
            dos.writeBytes((ext.getMax().getX() - ext.getMin().getX()) / pxWidth + "\n");
560
            dos.writeBytes("0.0\n");
561
            dos.writeBytes("0.0\n");
562
            dos.writeBytes((ext.getMin().getY() - ext.getMax().getY()) / pxHeight + "\n");
563
            dos.writeBytes("" + ext.getMin().getX() + "\n");
564
            dos.writeBytes("" + ext.getMax().getY() + "\n");
565
            dos.close();    
566
        }
567
        
568
    /**
569
         * Crea un fichero de georeferenciaci?n (world file) para un dataset determinado
570
         * @param GdalDriver
571
         * @param fileName Nombre completo del fichero de raster
572
         * @param AffineTransform 
573
         * @param pxWidth Ancho en p?xeles
574
         * @param pxHeight Alto en p?xeles
575
         * @return
576
         * @throws IOException
577
         */
578
        public static void createWorldFile(String fileName, AffineTransform at, int pxWidth, int pxHeight) throws IOException {
579
            File tfw = null;
580
            
581
            String extWorldFile = ".wld";
582
            if(fileName.endsWith("tif"))
583
                    extWorldFile = ".tfw";
584
            if(fileName.endsWith("jpg") || fileName.endsWith("jpeg"))
585
                    extWorldFile = ".jpgw";
586
                                
587
            tfw = new File(fileName.substring(0, fileName.lastIndexOf(".")) + extWorldFile);
588
            
589
            //Generamos un world file para gdal
590
            DataOutputStream dos = new DataOutputStream( new BufferedOutputStream(new FileOutputStream(tfw)) );
591
            dos.writeBytes(at.getScaleX() + "\n");
592
            dos.writeBytes(at.getShearX() + "\n");
593
            dos.writeBytes(at.getShearY() + "\n");
594
            dos.writeBytes(at.getScaleY() + "\n");
595
            dos.writeBytes("" + at.getTranslateX() + "\n");
596
            dos.writeBytes("" + at.getTranslateY() + "\n");
597
            dos.close();    
598
        }
599
        
600
    /**
601
     * Formatea en forma de cadena un tama?o dado en bytes. El resultado
602
     * ser? una cadena con GB, MB, KB y B
603
     * @param size tama?o a formatear
604
     * @return cadena con la cantidad formateada
605
     */
606
    public static String formatFileSize(long size){
607
            double bytes = (double)size, kBytes = 0, mBytes = 0, gBytes = 0;
608
                if(size >= 1024){
609
                        kBytes = (double)(size / 1024D);
610
                        bytes = (int)(size - (((int)kBytes) * 1024));
611
                        if(kBytes >= 1024){
612
                                mBytes = (double)(((int)kBytes) / 1024D);
613
                                kBytes = (double)(((int)kBytes) - (((int)mBytes) * 1024));
614
                                if(mBytes >= 1024){
615
                                        gBytes = (int)(((int)mBytes) / 1024);
616
                                        mBytes = (int)(((int)mBytes) - (gBytes * 1024));
617
                                }
618
                        }
619
                }
620

    
621
                if(gBytes > 0)
622
                        return MathUtils.format(gBytes, 1) + "G";
623
                if(mBytes > 0)
624
                        return MathUtils.format(mBytes, 1) + "M";
625
                if(kBytes > 0)
626
                        return MathUtils.format(kBytes, 1) + "K";
627
                if(bytes != 0)
628
                        return ((int)bytes) + "";
629
                
630
                return "";
631
    }
632
    
633
    /**
634
     * Obtiene la extensi?n del fichero a partir de su nombre.
635
     * @param file Nombre o ruta del fichero
636
     * @return Cadena con la extensi?n que representa el tipo de fichero.
637
     */
638
    public static String getExtensionFromFileName(String file) {
639
            return file.toLowerCase().substring(file.lastIndexOf(".") + 1);
640
    }
641
    
642
        /**
643
         * Obtiene la codificaci?n de un fichero XML
644
         * @param file Nombre del fichero XML
645
         * @return Codificaci?n
646
         */
647
        public static String readFileEncoding(String file){
648
                FileReader fr;
649
                String encoding = null;
650
                try {
651
                        fr = new FileReader(file);
652
                    BufferedReader br = new BufferedReader(fr);
653
                    char[] buffer = new char[100];
654
                    br.read(buffer);
655
                    StringBuffer st = new StringBuffer(new String(buffer));
656
                    String searchText = "encoding=\"";
657
                    int index = st.indexOf(searchText);
658
                    if (index >- 1) {
659
                            st.delete(0, index+searchText.length());
660
                            encoding = st.substring(0, st.indexOf("\""));
661
                    }
662
                    fr.close();
663
            } catch(FileNotFoundException ex)        {
664
                    ex.printStackTrace();
665
            } catch (IOException e) {
666
                        e.printStackTrace();
667
                }
668
            return encoding;
669
        }
670
        
671
        /**
672
         * Guarda la informaci?n de georreferenciaci?n de un raster en su fichero rmf adjunto.
673
         * @param path
674
         * @param at
675
         * @param dim
676
         * @throws IOException 
677
         */
678
        public static void saveGeoInfo(String outRmf, AffineTransform at, Point2D dim) throws IOException {
679
                RmfBlocksManager manager = new RmfBlocksManager(outRmf + ".rmf");
680
                GeoInfoRmfSerializer ser3 = new GeoInfoRmfSerializer(at, dim);
681
                manager.addClient(ser3);
682
                manager.write();
683
        }
684
        
685
    //---------------------------------------------------------------
686
    //VARIOS
687
    
688
        /**
689
         * Formatea el tiempo en milisegundos devolviendo un String en formato .
690
         * dias, horas, minutos y segundos.
691
         * @param time Tiempo en milisegundos
692
         */
693
        public static String formatTime(long time) {
694
                int hours = 0, minuts = 0, seconds = (int)(time / 1000D);
695
                if(seconds >= 60){
696
                        minuts = (int)(seconds / 60);
697
                        seconds = (int)(seconds - (minuts * 60));
698
                        if(minuts >= 60){
699
                                hours = (int)(minuts / 1024);
700
                                minuts = (int)(minuts - (hours * 60));
701
                        }
702
                }
703
                StringBuffer s = new StringBuffer();
704
                if(hours != 0)
705
                        s.append(hours+" H ");
706
                if(minuts != 0)
707
                        s.append(minuts+" Min ");
708
                if(seconds != 0)
709
                        s.append(seconds+" Sec ");
710
                return s.toString();
711
        }        
712
}