Statistics
| Revision:

gvsig-raster / org.gvsig.raster / branches / org.gvsig.raster_dataaccess_refactoring / org.gvsig.raster.lib / org.gvsig.raster.lib.impl / src / main / java / org / gvsig / raster / impl / store / FramedBufferResampling.java @ 2236

History | View | Annotate | Download (6.8 KB)

1
package org.gvsig.raster.impl.store;
2

    
3
import java.awt.Rectangle;
4

    
5
import org.gvsig.fmap.dal.coverage.RasterLocator;
6
import org.gvsig.fmap.dal.coverage.dataset.Buffer;
7
import org.gvsig.fmap.dal.coverage.datastruct.Extent;
8
import org.gvsig.fmap.dal.coverage.datastruct.NoData;
9
import org.gvsig.fmap.dal.coverage.exception.ProcessInterruptedException;
10
import org.gvsig.fmap.dal.coverage.exception.QueryException;
11
import org.gvsig.fmap.dal.coverage.exception.RasterDriverException;
12
import org.gvsig.fmap.dal.coverage.store.RasterDataStore;
13
import org.gvsig.raster.impl.DefaultRasterManager;
14
import org.gvsig.raster.impl.buffer.DefaultRasterQuery;
15
import org.gvsig.raster.impl.provider.AbstractRasterProvider;
16
import org.gvsig.raster.impl.provider.RasterProvider;
17

    
18
/**
19
 * The requests to a <code>RasterDataStore</code> adjust the bounding box and the size in pixels 
20
 * to the source limits. The user can need a buffer that exceeds the raster dimension. 
21
 * In this case, the area that is out of the raster limits should be set to nodata values or 
22
 * transparent in RGB cases. 
23
 * 
24
 * @author Nacho Brodin (nachobrodin@gmail.com)
25
 */
26
public class FramedBufferResampling {
27
        private DefaultRasterQuery           query            = null;
28
        private DefaultRasterQuery           originalQuery    = null;
29
        private RasterDataStore              store            = null; 
30
        protected byte                       byteNoData       = (byte)0x00;
31
        protected short                      shortNoData      = Short.MIN_VALUE;
32
        protected int                        intNoData        = Integer.MIN_VALUE;
33
        protected float                      floatNoData      = -99999;
34
        protected double                     doubleNoData     = -99999;
35
        
36
        public FramedBufferResampling(DefaultRasterQuery q, RasterDataStore store) {
37
                this.query = q;
38
                this.store = store;
39
                this.originalQuery = (DefaultRasterQuery)query.clone();
40
                setNoDataValue(store.getNoDataValue());
41
        }
42
        
43
        public Buffer query(RasterProvider provider) throws QueryException, ProcessInterruptedException {
44
                adjustQueryToTheStore();
45
                query.calculateParameters(store);
46
                originalQuery.calculateParameters(store);
47
                Buffer bufResult = null;
48
                try {
49
                        Buffer buf = ((AbstractRasterProvider)provider).getDataSet(query);
50
                        bufResult = buildBuffer(buf.getBandCount(), originalQuery.getAdjustedBufWidth(), originalQuery.getAdjustedBufHeight());
51
                        RasterLocator.getManager().getRasterUtils().copyToBuffer(
52
                                        bufResult, 
53
                                        originalQuery.getAdjustedRequestBoundingBox(), 
54
                                        buf, 
55
                                        query.getAdjustedRequestBoundingBox(), 
56
                                        1, 
57
                                        store.getColorInterpretation().hasAlphaBand());
58
                        buf.dispose();
59
                } catch (RasterDriverException e) {
60
                        throw new QueryException("Error getting data", e);
61
                }
62
                return bufResult;
63
        }
64
        
65
        /**
66
         * Sets the nodata value
67
         * @param noData
68
         */
69
        private void setNoDataValue(NoData noData) {
70
                if(noData == null)
71
                        return;
72
                switch (store.getDataType()[0]) {
73
                case Buffer.TYPE_BYTE:
74
                        byteNoData = noData.getValue().byteValue();
75
                        break;
76
                case Buffer.TYPE_SHORT:
77
                        shortNoData = noData.getValue().shortValue();
78
                        break;
79
                case Buffer.TYPE_INT:
80
                        intNoData = noData.getValue().intValue();
81
                        break;
82
                case Buffer.TYPE_FLOAT:
83
                        floatNoData = noData.getValue().floatValue();
84
                        break;
85
                case Buffer.TYPE_DOUBLE:
86
                        doubleNoData = ((NoData)noData).getValue().doubleValue();
87
                        break;
88
                }
89
        }
90
        
91
        /**
92
         * Builds a buffer using the specified number of bands and initialize it
93
         * @param nbands
94
         * @return
95
         */
96
        private Buffer buildBuffer(int nbands, int w, int h) {
97
                Buffer bufResult = DefaultRasterManager.getInstance().createBuffer(store.getDataType()[0], w, h, nbands, true);
98
                for (int i = 0; i < bufResult.getBandCount(); i++) {
99
                        clearMaskBuffer(bufResult, i);
100
                }
101
                return bufResult;
102
        }
103
        
104
        /**
105
         * Sets a band to NODATA value 
106
         * @param bufResult
107
         * @param tileExtent
108
         * @param buf
109
         * @param ex
110
         * @param pixelSize
111
         */
112
        protected void clearMaskBuffer(Buffer buf, int nBand) {
113
                if(buf.getDataType() == Buffer.TYPE_BYTE) {
114
                        for (int i = 0; i < buf.getHeight(); i++) {
115
                                for (int j = 0; j < buf.getWidth(); j++) {
116
                                        buf.setElem(i, j, nBand, byteNoData);
117
                                }
118
                        }
119
                        return;
120
                }
121
                if(buf.getDataType() == Buffer.TYPE_SHORT) {
122
                        for (int i = 0; i < buf.getHeight(); i++) {
123
                                for (int j = 0; j < buf.getWidth(); j++) {
124
                                        buf.setElem(i, j, nBand, shortNoData);
125
                                }
126
                        }
127
                        return;
128
                }
129
                if(buf.getDataType() == Buffer.TYPE_INT) {
130
                        for (int i = 0; i < buf.getHeight(); i++) {
131
                                for (int j = 0; j < buf.getWidth(); j++) {
132
                                        buf.setElem(i, j, nBand, intNoData);
133
                                }
134
                        }
135
                        return;
136
                }
137
                if(buf.getDataType() == Buffer.TYPE_FLOAT) {
138
                        for (int i = 0; i < buf.getHeight(); i++) {
139
                                for (int j = 0; j < buf.getWidth(); j++) {
140
                                        buf.setElem(i, j, nBand, floatNoData);
141
                                }
142
                        }
143
                        return;
144
                }
145
                if(buf.getDataType() == Buffer.TYPE_DOUBLE) {
146
                        for (int i = 0; i < buf.getHeight(); i++) {
147
                                for (int j = 0; j < buf.getWidth(); j++) {
148
                                        buf.setElem(i, j, nBand, doubleNoData);
149
                                }
150
                        }
151
                        return;
152
                }
153
        }
154
        
155
        private double round(double value) {
156
                double a = (value - (int)value);
157
                return (a > 0.95 || a < 0.05) ? Math.round(value) : value;
158
        }
159
        
160
        private void adjustQueryToTheStore() {
161
                if(query.getType() == DefaultRasterQuery.TYPE_WCOORDS_SHIFT) {
162
                        Extent e = query.getAdjustedRequestBoundingBox().intersection(store.getExtent());
163
                        int w = (int)Math.ceil(round((query.getBufWidth() * e.width()) /  query.getAdjustedRequestBoundingBox().width()));
164
                        int h = (int)Math.ceil(round((query.getBufHeight() * e.height()) /  query.getAdjustedRequestBoundingBox().height()));
165
                        query.setAdjustedRequestBoundingBox(e);
166
                        query.setBufWidth(w);
167
                        query.setBufHeight(h);
168
                }
169
                
170
                if(query.getType() == DefaultRasterQuery.TYPE_PX_SHIFT) {
171
                        Rectangle r = adjustRectangleToStoreSize(query.getRequestPxWindow());
172
                        query.setRequestPixelWindow(r);
173
                }
174
                
175
                if(query.getType() == DefaultRasterQuery.TYPE_PX_RESCALED_SHIFT) {
176
                        Rectangle r = adjustRectangleToStoreSize(query.getRequestPxWindow());
177
                        query.setRequestPixelWindow(r);
178
                        int w = (int)r.getWidth() - (int)originalQuery.getRequestPxWindow().getWidth();
179
                        int h = (int)r.getHeight() - (int)originalQuery.getRequestPxWindow().getHeight();
180
                        query.setBufWidth(query.getBufWidth() - w);
181
                        query.setBufHeight(query.getBufHeight() - h);
182
                }
183
        }
184
        
185
        /**
186
         * Adjusts the limits of the rectangle to the store limits
187
         * @param r
188
         * @return
189
         */
190
        private Rectangle adjustRectangleToStoreSize(Rectangle r) {
191
                Rectangle newRect = (Rectangle)r.clone();  
192
                if(r.getX() < 0)
193
                        newRect.setBounds(0, (int)r.getY(), (int)(r.getWidth() + r.getX()), (int)r.getHeight());
194
                if(r.getY() < 0)
195
                        newRect.setBounds((int)r.getX(), 0, (int)r.getWidth(), (int)(r.getHeight() + r.getY()));
196
                if(newRect.getWidth() > store.getWidth())
197
                        newRect.setSize((int)store.getWidth(), (int)r.getHeight());
198
                if(newRect.getHeight() > store.getHeight())
199
                        newRect.setSize((int)r.getWidth(), (int)store.getHeight());
200
                return newRect;
201
        }
202
}