Statistics
| Revision:

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

History | View | Annotate | Download (17.5 KB)

1 10939 nacho
package org.gvsig.raster.util;
2
3
import java.awt.Dimension;
4
import java.awt.geom.Point2D;
5
import java.awt.geom.Rectangle2D;
6
import java.io.File;
7
import java.io.FileInputStream;
8
import java.io.FileNotFoundException;
9
import java.io.FileOutputStream;
10
import java.io.IOException;
11
import java.io.InputStream;
12
import java.io.OutputStream;
13
14
import org.gvsig.raster.dataaccess.buffer.RasterBuffer;
15
import org.gvsig.raster.shared.Extent;
16
17
import es.gva.cit.jgdal.Gdal;
18
19
/**
20
 *
21
 * @author Nacho Brodin (nachobrodin@gmail.com)
22
 *
23
 */
24
public class RasterUtilities {
25
        public static final        int MAX_BYTE_BIT_VALUE        = 255;
26
        public static final        int MAX_SHORT_BIT_VALUE        = 65535;
27
28
    //---------------------------------------------------------------
29
    //TIPOS DE DATOS
30
31
    /**
32
     * Conversi?n de los tipos de datos de gdal a los tipos de datos de
33
     * RasterBuf
34
     * @param gdalType Tipo de dato de gdal
35
     * @return Tipo de dato de RasterBuf
36
     */
37
    public static int getRasterBufTypeFromGdalType(int gdalType){
38
            switch(gdalType){
39
                case 1:return  RasterBuffer.TYPE_BYTE;//GDT_BYTE
40
                case 2://GDT_UInt16
41
                case 8://GDT_CInt16
42
                case 3:return RasterBuffer.TYPE_SHORT;//GDT_Int16
43
                case 4://GDT_UInt32
44
                case 9://GDT_CInt32
45
                case 5:return RasterBuffer.TYPE_INT;//GDT_Int32
46
                case 10://GDT_CFloat32
47
                case 6:return RasterBuffer.TYPE_FLOAT;//GDT_Float32
48
                case 11://GDT_CFloat64
49
                case 7:return RasterBuffer.TYPE_DOUBLE;//GDT_Float64
50
                }
51
            return RasterBuffer.TYPE_UNDEFINED;
52
    }
53
54
    /**
55
     * Conversi?n de los tipos de datos de RasterBuf en los de gdal.
56
     * @param rasterBufType Tipo de dato de RasterBuf
57
     * @return Tipo de dato de Gdal
58
     */
59
    public static int getGdalTypeFromRasterBufType(int rasterBufType){
60
            switch(rasterBufType){
61
                case RasterBuffer.TYPE_BYTE:return Gdal.GDT_Byte;
62
                case RasterBuffer.TYPE_USHORT: return Gdal.GDT_UInt16;
63
                case RasterBuffer.TYPE_SHORT: return Gdal.GDT_Int16;
64
                case RasterBuffer.TYPE_INT: return Gdal.GDT_Int32;
65
                case RasterBuffer.TYPE_FLOAT: return Gdal.GDT_Float32;
66
                case RasterBuffer.TYPE_DOUBLE: return Gdal.GDT_Float64;
67
                case RasterBuffer.TYPE_UNDEFINED: return Gdal.GDT_Unknown;
68
                case RasterBuffer.TYPE_IMAGE: return Gdal.GDT_Byte;
69
                }
70
            return Gdal.GDT_Unknown;
71
    }
72
73
    /**
74
     * Conversi?n de los tipos de datos de MrSID a los tipos de datos de
75
     * RasterBuf
76
     * @param mrsidType Tipo de dato de MrSID
77
     * @return Tipo de dato de RasterBuf
78
     */
79
    public static int getRasterBufTypeFromMrSIDType(int mrsidType){
80
            switch(mrsidType){
81
            case 0:return RasterBuffer.TYPE_UNDEFINED;//INVALID
82
                case 1://UINT8
83
                case 2:return  RasterBuffer.TYPE_BYTE;//SINT8
84
                case 3://UINT16
85
                case 4:return RasterBuffer.TYPE_SHORT;//SINT16
86
                case 5://UINT32
87
                case 6:return RasterBuffer.TYPE_INT;//SINT32
88
                case 7:return RasterBuffer.TYPE_FLOAT;//FLOAT32
89
                case 8:return RasterBuffer.TYPE_DOUBLE;//FLOAT64
90
                }
91
            return RasterBuffer.TYPE_UNDEFINED;
92
    }
93
94
    /**
95
     * Obtiene el n?mero de bytes que ocupa un tipo de dato concreto.
96
     * Los tipos de datos son los utilizados en RasterBuffer
97
     * @param rasterBufType Tipo de dato del que se solicita el n?mero de bytes ocupados
98
     * @return
99
     */
100
    public static int getBytesFromRasterBufType(int rasterBufType){
101
            switch(rasterBufType){
102
                case RasterBuffer.TYPE_BYTE:return 1;
103
                case RasterBuffer.TYPE_USHORT:
104
                case RasterBuffer.TYPE_SHORT: return 2;
105
                case RasterBuffer.TYPE_INT:
106
                case RasterBuffer.TYPE_FLOAT:
107
                case RasterBuffer.TYPE_IMAGE: return 4;
108
                case RasterBuffer.TYPE_DOUBLE: return 8;
109
                }
110
            return 0; //TYPE_UNDEFINED
111
    }
112
113
    /**
114
     * Convierte un tipo de dato a cadena
115
     * @param type Tipo de dato
116
     * @return cadena  que representa el tipo de dato
117
     */
118
    public static String typesToString(int type) {
119
        switch (type) {
120
        case RasterBuffer.TYPE_IMAGE:
121
            return new String("Image");
122
123
        case RasterBuffer.TYPE_BYTE:
124
            return new String("Byte");
125
126
        case RasterBuffer.TYPE_DOUBLE:
127
            return new String("Double");
128
129
        case RasterBuffer.TYPE_FLOAT:
130
            return new String("Float");
131
132
        case RasterBuffer.TYPE_INT:
133
                return new String("Integer");
134
135
        case RasterBuffer.TYPE_USHORT:
136
        case RasterBuffer.TYPE_SHORT:
137
            return new String("Short");
138
        }
139
140
        return null;
141
    }
142
143
    /**
144
     * Parseo de las proyecciones que genera gdal para meter espaciados y saltos de l?nea HTML
145
     * @param proj Proyecci?n
146
     * @return Cadena con la proyecci?n parseada
147
     */
148
    public static String parserGdalProj(String proj){
149
            String[] list = proj.split(",");
150
            int level = 0;
151
            for(int i = 0; i < list.length; i++){
152
                    if(list[i].indexOf("[") >= 0){
153
                            level ++;
154
                            String spaces = "";
155
                            for(int j = 0; j < level; j++)
156
                                    spaces += "&nbsp;&nbsp;";
157
                            list[i] = spaces + list[i];
158
                    }
159
                    if(list[i].indexOf("]]") >= 0)
160
                            level = level - 2;
161
                    else if(list[i].indexOf("]") >= 0)
162
                            level --;
163
            }
164
            StringBuffer str = new StringBuffer();
165
            for(int i = 0; i < list.length; i++){
166
                    if(i < list.length){
167
                            if(i + 1 < list.length && list[i + 1].indexOf("[") >= 0)
168
                                    str.append(list[i] + ",<BR>");
169
                            else
170
                                    str.append(list[i] + ",");
171
                    }
172
            }
173
            return str.toString();
174
    }
175
176
    //---------------------------------------------------------------
177
    //ESPACIO DE COLOR
178
179
    /**
180
     * Descompone un entero que representa un ARGB en sus 4 valores byte
181
     * Obtiene un array de 4 elementos donde el elemento 0 es el Rojo, el 1 es el
182
     * verde, el 2 el azul y el 3 el alpha.
183
     * @param rgb Entero con el valor ARGB a descomponer;
184
     * @return Array de cuatro elementos
185
     */
186
    public static byte[] getARGBFromIntToByteArray(int rgb){
187
            byte[] b = new byte[4];
188
            b[0] = (byte)((rgb & 0x00ff0000) >> 16);
189
            b[1] = (byte)((rgb & 0x0000ff00) >> 8);
190
            b[2] = (byte)(rgb & 0x000000ff);
191
            b[3] = (byte)((rgb & 0xff000000) >> 24);
192
            return b;
193
    }
194
195
    /**
196
     * Descompone un entero que representa un ARGB en sus 4 valores byte
197
     * Obtiene un array de 4 elementos donde el elemento 0 es el Rojo, el 1 es el
198
     * verde, el 2 el azul y el 3 el alpha.
199
     * @param rgb Entero con el valor ARGB a descomponer;
200
     * @return
201
     */
202
    public static int[] getARGBFromIntToIntArray(int rgb){
203
            int[] i = new int[4];
204
            i[0] = (((rgb & 0x00ff0000) >> 16) & 0xff);
205
            i[1] = (((rgb & 0x0000ff00) >> 8) & 0xff);
206
            i[2] = ((rgb & 0x000000ff) & 0xff);
207
            i[3] = (((rgb & 0xff000000) >> 24) & 0xff);
208
            return i;
209
    }
210
211
    /**
212
     * Obtiene un entero con los valores ARGB pasados por par?metro
213
     * @param a Valor de alpha
214
     * @param r Valor del rojo
215
     * @param g Valor del verde
216
     * @param b Valor del azul
217
     * @return entero con la mezcla de valores
218
     */
219
    public static int getIntFromARGB(int a, int r, int g, int b){
220
              return (((a & 0xff) << 24) + ((r & 0xff) << 16) + ((g & 0xff) << 8) + (b & 0xff));
221
    }
222
223
    //---------------------------------------------------------------
224
    //CONVERSI?N DE COORDENADAS
225
226
    /**
227
     * Convierte una ventana en coordenadas del mundo real a sus coordenadas relativas en pixels teniendo
228
     * en cuenta que la coordenada superior izquierda es 0,0 y la inferior derecha es maxX y maY
229
     * @param extent Extent de la imagen original
230
     * @param widthPx Ancho en pixeles de la imagen original
231
     * @param heightPx Alto en pixeles de la imagen original
232
     * @param window Ventana en coordenadas reales a transportar a coordenadas pixel
233
     * @return Ventana en coordenadas pixel
234
     */
235
    public static Rectangle2D getPxRectFromMapRect(Rectangle2D extent, double widthPx, double heightPx, Rectangle2D window){
236
            double widthWC = extent.getWidth();
237
                double heightWC = extent.getHeight();
238
239
                double wWindowWC = Math.abs(window.getMaxX() - window.getMinX());
240
                   double hWindowWC = Math.abs(window.getMaxY() - window.getMinY());
241
242
                   double wWindowPx = ((wWindowWC * widthPx) /  widthWC);
243
                   double hWindowPx = ((hWindowWC * heightPx) /  heightWC);
244
245
                   double initDistanceX = Math.abs(window.getMinX() - extent.getMinX());
246
                   double initDistanceY = Math.abs(window.getMaxY() - extent.getMaxY());
247
248
                   double initPxX = ((initDistanceX * widthPx) /  widthWC);
249
                   double initPxY = ((initDistanceY * heightPx) /  heightWC);
250
251
                   Rectangle2D pxRec = new Rectangle2D.Double(        initPxX,
252
                                                                                                           initPxY,
253
                                                                                                           wWindowPx,
254
                                                                                                           hWindowPx);
255
                   return pxRec;
256
    }
257
258
    /**
259
     * Convierte una ventana en coordenadas del mundo real a sus coordenadas relativas en pixels teniendo
260
     * en cuenta que la coordenada superior izquierda es 0,0 y la inferior derecha es maxX y maY
261
     * @param extent Extent de la imagen original
262
     * @param widthPx Ancho en pixeles de la imagen original
263
     * @param heightPx Alto en pixeles de la imagen original
264
     * @param window Ventana en coordenadas reales a transportar a coordenadas pixel
265
     * @return Ventana en coordenadas pixel
266
     */
267
    public static Rectangle2D getMapRectFromPxRect(Rectangle2D extent, double widthPx, double heightPx, Rectangle2D pxWindow){
268
                   double wWindowWC = ((pxWindow.getWidth() * extent.getWidth()) /  widthPx);
269
                   double hWindowWC = ((pxWindow.getHeight() * extent.getHeight()) /  heightPx);
270
271
                   double initWCX = extent.getMinX() + ((pxWindow.getMinX() * extent.getWidth()) /  widthPx);
272
                   double initWCY = extent.getMaxY() - ((pxWindow.getMinY() * extent.getHeight()) /  heightPx);
273
274
                   Rectangle2D mapRec = new Rectangle2D.Double(initWCX,
275
                                                                                                           initWCY - hWindowWC,
276
                                                                                                           wWindowWC,
277
                                                                                                           hWindowWC);
278
                   return mapRec;
279
    }
280
281
    /**
282
     * Convierte un punto en coordenadas del mundo a coordenadas pixel
283
     * @param p Punto a convertir
284
     * @param ext Extent completo de la imagen
285
     * @return Punto en coordenadas pixel
286
     */
287
    public static Point2D worldPointToRaster(Point2D p, Extent ext, int pxWidth, int pxHeight) {
288
            double x = p.getX() - ext.getMin().getX();
289
            double y = p.getY() - ext.getMin().getY();
290
            int pxX = (int)((x * pxWidth) / ext.width());
291
            int pxY = (int)((y * pxHeight) / ext.height());
292
            return new Point2D.Double(pxX, pxY);
293
    }
294
295
    /**
296
     * Ajusta la extensi?n pasada por par?metro a los valores m?ximos y m?nimos de la
297
     * imagen. Esto sirve para que la petici?n al driver nunca sobrepase los l?mites
298
     * de la imagen tratada aunque la vista donde se dibuje sea de mayor tama?o.
299
     *
300
     * @param imgExt Extent completo de la vista donde se va a dibujar.
301
     * @param extToAdj Extent a ajustar.
302
     * @return adjustedExtent Extent ajustado a m?ximos y m?nimos
303
     */
304
    public static Extent calculateAdjustedView(Extent extToAdj, Extent imgExt) {
305
        double vx = extToAdj.minX();
306
        double vy = extToAdj.minY();
307
        double vx2 = extToAdj.maxX();
308
        double vy2 = extToAdj.maxY();
309
310
        if (extToAdj.minX() < imgExt.minX())
311
            vx = imgExt.minX();
312
313
        if (extToAdj.minY() < imgExt.minY())
314
            vy = imgExt.minY();
315
316
        if (extToAdj.maxX() > imgExt.maxX())
317
            vx2 = imgExt.maxX();
318
319
        if (extToAdj.maxY() > imgExt.maxY())
320
            vy2 = imgExt.maxY();
321
322
        Extent adjustedExtent = new Extent(vx, vy, vx2, vy2);
323
        return adjustedExtent;
324
    }
325
326
    /**
327
     * Compara dos extents y devuelve true si son iguales
328
     * @param e1 Extent a comparar
329
     * @param e2 Extent a comparar
330
     * @return true si los extents pasados por par?metro son iguales y false si no lo son
331
     */
332
    public static boolean compareExtents(Extent e1, Extent e2){
333
            return ((e1.getMin().getX() == e2.getMin().getX()) && (e1.getMin().getY() == e2.getMin().getY()) &&
334
                            (e1.getMax().getX() == e2.getMax().getX())) && (e1.getMax().getY() == e2.getMax().getY());
335
    }
336
337
    /**
338
     * Comprueba si un extent est? contenido dentro de otro y devuelve true en este caso.
339
     * @param e1 Extent a comprobar si est? contenido en e2
340
     * @param e2 Extent sobre el que se comprueba si e1 est? dentro
341
     * @return true si e1 est? dentro de e1
342
     */
343
    public static boolean isInside(Extent e1, Extent e2){
344
            return ((e1.getMin().getX() >= e2.getMin().getX()) && (e1.getMin().getY() >= e2.getMin().getY()) &&
345
                            (e1.getMax().getX() <= e2.getMax().getX())) && (e1.getMax().getY() <= e2.getMax().getY());
346
    }
347
348 10952 nacho
    /**
349
     * Comprueba si alguna parte de un extent est? fuera del extent que tenemos como referencia.
350
     * @param e1 Extent a comprobar si est? fuera
351
     * @param ref Extent de referencia
352
     * @return Devuelve true si alguna parte de e1 cae fuera de ref y false si no tiene ninguna fuera.
353
     */
354
    public static boolean isOutside(Extent e1, Extent ref){
355
            return ((e1.getMin().getX() < ref.getMin().getX()) || (e1.getMin().getY() < ref.getMin().getY()) ||
356
                            (e1.getMax().getX() > ref.getMax().getX()) || (e1.getMax().getY() > ref.getMax().getY()));
357
    }
358
359 10939 nacho
        /**
360
         * Calcula los par?metros de un worl file a partir de las esquinas del raster.
361
         *    1. X pixel size A
362
         *    2. X rotation term D
363
         *    3. Y rotation term B
364
         *    4. Y pixel size E
365
         *    5. X coordinate of upper left corner C
366
         *    6. Y coordinate of upper left corner F
367
         * where the real-world coordinates x',y' can be calculated from
368
         * the image coordinates x,y with the equations
369
         *  x' = Ax + By + C and y' = Dx + Ey + F.
370
         *  The signs of the first 4 parameters depend on the orientation
371
         *  of the image. In the usual case where north is more or less
372
         *  at the top of the image, the X pixel size will be positive
373
         *  and the Y pixel size will be negative. For a south-up image,
374
         *  these signs would be reversed.
375
         *
376
         * You can calculate the World file parameters yourself based
377
         * on the corner coordinates. The X and Y pixel sizes can be
378
         *  determined simply by dividing the distance between two
379
         *  adjacent corners by the number of columns or rows in the image.
380
         *  The rotation terms are calculated with these equations:
381
         *
382
         *  # B = (A * number_of_columns + C - lower_right_x') / number_of_rows * -1
383
         *  # D = (E * number_of_rows + F - lower_right_y') / number_of_columns * -1
384
         *
385
         * @param corner (tl, tr, br, bl)
386
         * @return
387
         */
388
        public static double [] cornersToWorldFile(Point2D [] esq, Dimension size) {
389
                double a = 0, b = 0, c = 0, d = 0, e = 0, f = 0;
390
                double x1 = esq[0].getX(), y1 = esq[0].getY();
391
                double x2 = esq[1].getX(), y2 = esq[1].getY();
392
                double x3 = esq[2].getX(), y3 = esq[2].getY();
393
                double x4 = esq[3].getX(), y4 = esq[3].getY();
394
                // A: X-scale
395
                a = Math.abs( Math.sqrt( (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2))
396
                      / size.getWidth());
397
398
                // E: negative Y-scale
399
                e =  - Math.abs(Math.sqrt((x1 - x4) * (x1 - x4) +
400
                      (y1 - y4) * (y1 - y4)) / size.getHeight());
401
402
                // C, F: upper-left coordinates
403
                c = x1;
404
                f = y1;
405
406
                // B & D: rotation parameters
407
                b = (a * size.getWidth() + c - x3 ) / size.getHeight() * -1;
408
                d = (e * size.getHeight() + f - y3 ) / size.getWidth() * -1;
409
410
                double [] wf = {a, d, b, e, c, f};
411
                return wf;
412
        }
413
414
    //---------------------------------------------------------------
415
    //TRATAMIENTO DE FICHEROS
416
417
    /**
418
     * Copia de ficheros
419
     * @param pathOrig Ruta de origen
420
     * @param pathDst Ruta de destino.
421
     */
422
    public static void copyFile(String pathOrig, String pathDst)
423
            throws FileNotFoundException, IOException{
424
             InputStream in;
425
             OutputStream out;
426
427
             if(pathOrig == null || pathDst == null){
428
                     System.err.println("Error en path");
429
                     return;
430
             }
431
432
             File orig = new File(pathOrig);
433
             if(!orig.exists() || !orig.isFile() || !orig.canRead()){
434
                     System.err.println("Error en fichero de origen");
435
                     return;
436
             }
437
438
             File dest = new File(pathDst);
439
             String file = pathOrig.substring(pathOrig.lastIndexOf(File.separator), pathOrig.length());
440
             if(dest.isDirectory())
441
                     pathDst += file;
442
443
             in = new FileInputStream(pathOrig);
444
             out = new FileOutputStream(pathDst);
445
446
             byte[] buf = new byte[1024];
447
             int len;
448
449
             while ((len = in.read(buf)) > 0)
450
                        out.write(buf, 0, len);
451
452
             in.close();
453
             out.close();
454
    }
455
456
    /**
457
     * Formatea en forma de cadena un tama?o dado en bytes. El resultado
458
     * ser? una cadena con GB, MB, KB y B
459
     * @param size tama?o a formatear
460
     * @return cadena con la cantidad formateada
461
     */
462
    public static String formatFileSize(long size){
463
            double bytes = (double)size, kBytes = 0, mBytes = 0, gBytes = 0;
464
                if(size >= 1024){
465
                        kBytes = (double)(size / 1024D);
466
                        bytes = (int)(size - (((int)kBytes) * 1024));
467
                        if(kBytes >= 1024){
468
                                mBytes = (double)(((int)kBytes) / 1024D);
469
                                kBytes = (double)(((int)kBytes) - (((int)mBytes) * 1024));
470
                                if(mBytes >= 1024){
471
                                        gBytes = (int)(((int)mBytes) / 1024);
472
                                        mBytes = (int)(((int)mBytes) - (gBytes * 1024));
473
                                }
474
                        }
475
                }
476
477
                if(gBytes > 0)
478
                        return format(gBytes, 1) + "G";
479
                if(mBytes > 0)
480
                        return format(mBytes, 1) + "M";
481
                if(kBytes > 0)
482
                        return format(kBytes, 1) + "K";
483
                if(bytes != 0)
484
                        return ((int)bytes) + "";
485
486
                return "";
487
    }
488
489
    //---------------------------------------------------------------
490
    //VARIOS
491
492
    /**
493
         * Formats a double with an specified number of decimals.
494
         * @param num
495
         * Value to tail
496
         * @param n
497
         * Number of decimals
498
         * @return
499
         * The formatted double
500
         */
501
    public static double format(double num, int n){
502
            long m = (long)Math.pow(10, n);
503
        num *= m;
504
        long aux = ((long)num);
505
        num = (double)((double)aux / (double)m);
506
        return num;
507
    }
508
509
}