001/*
002 * $Id: McIdasXFrameInfo.java,v 1.8 2011/03/24 16:06:32 davep Exp $
003 *
004 * This file is part of McIDAS-V
005 *
006 * Copyright 2007-2011
007 * Space Science and Engineering Center (SSEC)
008 * University of Wisconsin - Madison
009 * 1225 W. Dayton Street, Madison, WI 53706, USA
010 * https://www.ssec.wisc.edu/mcidas
011 * 
012 * All Rights Reserved
013 * 
014 * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and
015 * some McIDAS-V source code is based on IDV and VisAD source code.  
016 * 
017 * McIDAS-V is free software; you can redistribute it and/or modify
018 * it under the terms of the GNU Lesser Public License as published by
019 * the Free Software Foundation; either version 3 of the License, or
020 * (at your option) any later version.
021 * 
022 * McIDAS-V is distributed in the hope that it will be useful,
023 * but WITHOUT ANY WARRANTY; without even the implied warranty of
024 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
025 * GNU Lesser Public License for more details.
026 * 
027 * You should have received a copy of the GNU Lesser Public License
028 * along with this program.  If not, see http://www.gnu.org/licenses.
029 */
030
031package edu.wisc.ssec.mcidasv.data;
032
033import edu.wisc.ssec.mcidasv.data.McIdasXInfo;
034import edu.wisc.ssec.mcidas.AREAnav;
035
036import java.io.*;
037import java.util.ArrayList;
038import java.util.List;
039
040import java.awt.Image;
041import java.awt.Toolkit;
042
043import ucar.unidata.util.Misc;
044
045public class McIdasXFrameInfo {
046
047    private int myFrameNumber;
048    private McIdasXInfo myXInfo;
049
050    private int width = 0;
051    private int height = 0;
052    private int[] stretchTable = new int[256];
053    private int[] colorTable = new int[256];
054    private int[] graphicsTable = new int[256];
055
056    private byte myImage[];
057    
058    private boolean isLoaded = false;
059    
060    /**
061     * Constructor
062     */
063    public McIdasXFrameInfo() {
064        this.myFrameNumber = 0;
065        this.myXInfo = new McIdasXInfo();
066        this.isLoaded = false;
067    }
068
069    /**
070     * Copy constructor
071     *
072     * @param that The McIdasXFrameInfo to copy
073     *
074     */
075    public McIdasXFrameInfo(McIdasXFrameInfo that) {
076        this.myFrameNumber = that.myFrameNumber;
077        this.myXInfo = that.myXInfo;
078        this.isLoaded = false;
079    }
080    
081    /**
082     * Copy constructor
083     *
084     * @param that The McIdasXFrameInfo to copy
085     *
086     */
087    public McIdasXFrameInfo(int frameNumber, McIdasXInfo xInfo) {
088//      System.out.println("McIdasXFrameInfo constructor: frame " + frameNumber + ", xInfo " + xInfo.toString());
089        this.myFrameNumber = frameNumber;
090        this.myXInfo = xInfo;
091        this.isLoaded = false;
092    }
093    
094    public void setRefreshData(boolean refresh) {
095        if (refresh) this.isLoaded = false;
096    }
097    
098    private int setFrameData() {
099//      System.out.println(" <=> setFrameData frame " + this.myFrameNumber);
100        int ret = -1;
101        DataInputStream inputStream = myXInfo.getDataInputStream(this.myFrameNumber);
102        try {
103            this.width = inputStream.readInt();
104            this.height = inputStream.readInt();
105        } catch (Exception e) {
106            System.out.println("getFrameData exception: " + e);
107            return ret;
108        }
109
110        if (!getTable(inputStream, stretchTable)) return ret;
111        if (!getTable(inputStream, colorTable)) return ret;
112        if (!getTable(inputStream, graphicsTable)) return ret;
113
114        int havebytes = 0;
115        int needbytes = this.width * this.height;
116        byte[] image = new byte[needbytes];
117        int count = 0;
118        int num = 0;
119        int indx = 0;
120        try {
121            while (needbytes > 0) {
122                num = inputStream.read(image, indx, needbytes);
123                indx += num;
124                havebytes += num;
125                needbytes -= num;
126                count++;
127                Misc.sleep(10);
128                if (count > 100) return ret;
129            }
130        } catch (Exception e) {
131            System.out.println("getFrameData exception: " + e);
132            return ret;
133        }
134        this.isLoaded = true;
135        this.myImage = image;
136        ret = 0;
137        return ret;
138    }
139
140    public List getGraphics() {
141//      System.out.println(" <=> getGraphics frame " + this.myFrameNumber);
142        DataInputStream inputStream = myXInfo.getGraphicsInputStream(this.myFrameNumber);
143        List graphics = new ArrayList();
144        int pixels = 0;
145        try {
146                BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
147                String lineOut = br.readLine();
148                while (lineOut != null) {
149//                      System.out.println("getGraphics adding pixel: " + lineOut);
150                graphics.add(lineOut);
151                        pixels++;
152                        lineOut = br.readLine();
153                }
154            } catch (Exception e) {
155                System.out.println("getGraphics exception: " + e);
156            try { inputStream.close(); }
157            catch (Exception ee) {}
158                return graphics;
159            }
160//        System.out.println("getGraphics: " + pixels);
161            return graphics;
162    }
163    
164    public int[] getFrameDirectory() {
165//      System.out.println(" <=> getFrameDirectory frame " + this.myFrameNumber);
166        String filename = "Frame" + this.myFrameNumber + ".0";
167        DataInputStream inputStream = myXInfo.getFileInputStream(filename);
168
169        int dirLength = 64;
170        int[] dir = getInts(inputStream, dirLength);
171        
172        // The next byte tells us what type of nav we have...
173        // it also needs to be the first byte of the nav array
174        int navLength;
175        int[] navType = getInts(inputStream, 1);
176        if (navType[0] == AREAnav.LALO) navLength = 128;
177        else navLength = 640;
178        int[] navRest = getInts(inputStream, navLength - 1);
179        int[] nav = new int[navLength];
180        System.arraycopy(navType, 0, nav, 0, 1);
181        System.arraycopy(navRest, 0, nav, 1, navLength - 1);
182
183        int auxLength = 0;
184        int rows = 0;
185        int cols = 0;
186        int begLat= 0;
187        int begLon =0;
188        if (navLength == 128) {
189            rows = nav[65];
190            cols = nav[66];
191            begLat = nav[78]/4;
192            begLon = nav[79]/4;
193            auxLength = begLon + (rows*cols);
194        }
195        int[] aux = getInts(inputStream, auxLength);
196
197        int[] frmdir = new int[dirLength + navLength + auxLength];
198        System.arraycopy(dir, 0, frmdir, 0, dirLength);
199        System.arraycopy(nav, 0, frmdir, dirLength, navLength);
200        if (auxLength > 0)
201            System.arraycopy(aux, 0, frmdir, dirLength+navLength, auxLength);
202      
203        try { inputStream.close(); }
204        catch (Exception ee) {}
205 
206        return frmdir;
207    }
208
209    private boolean getTable(DataInputStream inputStream, int[] tbl) {
210        try {
211            for (int i=0; i<256; i++) {
212                tbl[i] = inputStream.readInt();
213            }
214        } catch (Exception e) {
215            System.out.println("getTable exception: " + e);
216            return false;
217        }
218        return true;
219    }
220    
221    private int[] getInts(DataInputStream stream, int count) {
222        int[] buf = new int[count];
223        if (count < 1) return buf;
224
225        int havebytes=0;
226        int needbytes=count;
227
228        try {
229            while (havebytes<needbytes) {
230                buf[havebytes] = stream.readInt();
231                havebytes++;
232            }
233        } catch (Exception e) {
234            System.out.println("getInts exception: " + e);
235            return buf;
236        }
237
238        return buf;
239    }
240    
241    public int getFrameNumber() {
242        return this.myFrameNumber;
243    }
244
245    public int getLineSize() {
246        if (!this.isLoaded) {
247           if (setFrameData() < 0) this.height = -1;
248        }
249        return this.height;
250    }
251
252    public int getElementSize() {
253        if (!this.isLoaded) {
254            if (setFrameData() < 0) this.width = -1;
255        }
256        return this.width;
257    }
258
259    public int[] getStretchTable() {
260        if (!this.isLoaded) {
261                if (setFrameData() < 0) this.stretchTable = new int[256];
262        }
263        return this.stretchTable;
264    }
265    
266    public int[] getColorTable() {
267        if (!this.isLoaded) {
268                if (setFrameData() < 0) this.colorTable = new int[256];
269        }
270        return this.colorTable;
271    }
272    
273    public int[] getGraphicsTable() {
274        if (!this.isLoaded) {
275                if (setFrameData() < 0) this.graphicsTable = new int[256];
276        }
277        return this.graphicsTable;
278    }
279    
280    public float[][] getEnhancementTable() {
281        float[][] enhancementTable = new float[3][256];
282        if (!this.isLoaded) {
283                if (setFrameData() < 0) return enhancementTable;
284        }
285        for (int i=1; i<18; i++) {
286                enhancementTable[0][i] = (float)((this.colorTable[i]/0x10000)&0xff);
287                enhancementTable[1][i] = (float)((this.colorTable[i]/0x100)&0xff);
288                enhancementTable[2][i] = (float)(this.colorTable[i]&0xff);
289        }
290        for (int i=18; i<256; i++) {
291                enhancementTable[0][i] = (float)((this.colorTable[this.stretchTable[i]]/0x10000)&0xff);
292                enhancementTable[1][i] = (float)((this.colorTable[this.stretchTable[i]]/0x100)&0xff);
293                enhancementTable[2][i] = (float)(this.colorTable[this.stretchTable[i]]&0xff);
294        }
295        for (int i=0; i<256; i++) {
296                enhancementTable[0][i] /= 0xff;
297                enhancementTable[1][i] /= 0xff;
298                enhancementTable[2][i] /= 0xff;
299        }
300        return enhancementTable;
301    }
302
303    public byte[] getImage() {
304        if (!this.isLoaded) {
305                if (setFrameData() < 0) this.myImage = new byte[0];
306        }
307        return this.myImage;
308    }
309
310    public Image getGIF() {
311        int MAX_BYTES = 1048576;
312        byte[] imagebytes = new byte[MAX_BYTES];
313        DataInputStream inputStream = this.myXInfo.getGIFInputStream(this.myFrameNumber);
314        int n = 0;
315        int i = 0;
316        for (n=0; n<MAX_BYTES; n++) {
317                try {
318                        i = inputStream.read();
319                } catch (Exception ee) { }
320                if (i < 0) break;
321                imagebytes[n] = (byte)i;
322        }
323        byte[] gifbytes = new byte[n];
324        System.arraycopy(imagebytes, 0, gifbytes, 0, n);
325        Image imageGIF = Toolkit.getDefaultToolkit().createImage(gifbytes);
326        imagebytes = null;
327        try { inputStream.close(); }
328        catch (Exception ee) {}
329        return imageGIF;
330    }
331
332}