001package cnslab.image;
002import java.awt.*;
003import java.awt.image.*;
004import java.io.*;
005import java.util.*;
006import java.util.Vector.*;
007
008
009public class utils{
010
011    /*loadbitmap originally written by Jeff West, and published at
012     *http://www.javaworld.com/javaworld/javatips/jw-javatip43.html
013     *modified slightly by Jeb Thorley.
014     */
015
016    public static  Image loadbitmap (String sdir, String sfile)
017    {
018        Image image;
019        System.out.println("loading:"+sdir+sfile);
020        try
021            {
022                FileInputStream fs;
023                if(sdir.equals("./")){//a bit of a hack
024                    fs=new FileInputStream(sfile);
025                }
026                else{
027                    fs=new FileInputStream(sdir+sfile);
028                }
029
030                int bflen=14; // 14 byte BITMAPFILEHEADER
031                byte bf[]=new byte[bflen];
032                fs.read(bf,0,bflen);
033                int bilen=40; // 40-byte BITMAPINFOHEADER
034                byte bi[]=new byte[bilen];
035                fs.read(bi,0,bilen);
036
037                // Interperet data.
038                int nsize = (((int)bf[5]&0xff)<<24)
039                    | (((int)bf[4]&0xff)<<16)
040                    | (((int)bf[3]&0xff)<<8)
041                    | (int)bf[2]&0xff;
042                //System.out.println("File type is :"+(char)bf[0]+(char)bf[1]);
043                //System.out.println("Size of file is :"+nsize);
044
045                int nbisize = (((int)bi[3]&0xff)<<24)
046                    | (((int)bi[2]&0xff)<<16)
047                    | (((int)bi[1]&0xff)<<8)
048                    | (int)bi[0]&0xff;
049                //System.out.println("Size of bitmapinfoheader is :"+nbisize);
050
051                int nwidth = (((int)bi[7]&0xff)<<24)
052                    | (((int)bi[6]&0xff)<<16)
053                    | (((int)bi[5]&0xff)<<8)
054                    | (int)bi[4]&0xff;
055                //System.out.println("Width is :"+nwidth);
056
057                int nheight = (((int)bi[11]&0xff)<<24)
058                    | (((int)bi[10]&0xff)<<16)
059                    | (((int)bi[9]&0xff)<<8)
060                    | (int)bi[8]&0xff;
061                //System.out.println("Height is :"+nheight);
062
063
064                int nplanes = (((int)bi[13]&0xff)<<8) | (int)bi[12]&0xff;
065                //System.out.println("Planes is :"+nplanes);
066
067                int nbitcount = (((int)bi[15]&0xff)<<8) | (int)bi[14]&0xff;
068                //System.out.println("BitCount is :"+nbitcount);
069
070                // Look for non-zero values to indicate compression
071                int ncompression = (((int)bi[19])<<24)
072                    | (((int)bi[18])<<16)
073                    | (((int)bi[17])<<8)
074                    | (int)bi[16];
075                //System.out.println("Compression is :"+ncompression);
076
077                int nsizeimage = (((int)bi[23]&0xff)<<24)
078                    | (((int)bi[22]&0xff)<<16)
079                    | (((int)bi[21]&0xff)<<8)
080                    | (int)bi[20]&0xff;
081                //System.out.println("SizeImage is :"+nsizeimage);
082
083                int nxpm = (((int)bi[27]&0xff)<<24)
084                    | (((int)bi[26]&0xff)<<16)
085                    | (((int)bi[25]&0xff)<<8)
086                    | (int)bi[24]&0xff;
087                //System.out.println("X-Pixels per meter is :"+nxpm);
088
089                int nypm = (((int)bi[31]&0xff)<<24)
090                    | (((int)bi[30]&0xff)<<16)
091                    | (((int)bi[29]&0xff)<<8)
092                    | (int)bi[28]&0xff;
093                //System.out.println("Y-Pixels per meter is :"+nypm);
094
095                int nclrused = (((int)bi[35]&0xff)<<24)
096                    | (((int)bi[34]&0xff)<<16)
097                    | (((int)bi[33]&0xff)<<8)
098                    | (int)bi[32]&0xff;
099                //System.out.println("Colors used are :"+nclrused);
100
101                int nclrimp = (((int)bi[39]&0xff)<<24)
102                    | (((int)bi[38]&0xff)<<16)
103                    | (((int)bi[37]&0xff)<<8)
104                    | (int)bi[36]&0xff;
105                //System.out.println("Colors important are :"+nclrimp);
106
107                if (nbitcount==24)
108                    {
109                        // No Palatte data for 24-bit format but scan lines are
110                        // padded out to even 4-byte boundaries.
111                        int npad = (nsizeimage / nheight) - nwidth * 3;
112                        //added for Bug correction
113                        if(npad == 4){
114                            npad=0;
115                        }
116                        int ndata[] = new int [nheight * nwidth];
117                        byte brgb[] = new byte [( nwidth + npad) * 3 * nheight];
118
119                        fs.read (brgb, 0, (nwidth + npad) * 3 * nheight);
120                        int nindex = 0;
121                        for (int j = 0; j < nheight; j++)
122                            {
123                                for (int i = 0; i < nwidth; i++)
124                                    {
125                                        ndata [nwidth * (nheight - j - 1) + i] =
126
127                                            (255&0xff)<<24
128                                            | (((int)brgb[nindex+2]&0xff)<<16)
129                                            | (((int)brgb[nindex+1]&0xff)<<8)
130                                            | (int)brgb[nindex]&0xff;
131                                        nindex += 3;
132                                    }
133                                nindex += npad;
134                            }
135
136                        image = Toolkit.getDefaultToolkit().createImage( new MemoryImageSource (nwidth, nheight,ndata, 0, nwidth));
137                    }
138                else if (nbitcount == 8)
139                    {
140                        // Have to determine the number of colors, the clrsused
141                        // parameter is dominant if it is greater than zero. If
142                        // zero, calculate colors based on bitsperpixel.
143                        int nNumColors = 0;
144                        if (nclrused > 0)
145                            {
146                                nNumColors = nclrused;
147                            }
148                        else
149                            {
150                                nNumColors = (1&0xff)<<nbitcount;
151                            }
152                        //System.out.println("The number of Colors is"+nNumColors);
153
154                        // Some bitmaps do not have the sizeimage field calculated
155                        // Ferret out these cases and fix 'em.
156                        if (nsizeimage == 0)
157                            {
158                                nsizeimage = ((((nwidth*nbitcount)+31) & ~31 ) >> 3);
159                                nsizeimage *= nheight;
160                                //System.out.println("nsizeimage (backup) is"+nsizeimage);
161                            }
162
163                        // Read the palatte colors.
164                        int npalette[] = new int [nNumColors];
165                        byte bpalette[] = new byte [nNumColors*4];
166                        fs.read (bpalette, 0, nNumColors*4);
167                        int nindex8 = 0;
168                        for (int n = 0; n < nNumColors; n++)
169                            {
170                                npalette[n] = (255&0xff)<<24
171                                    | (((int)bpalette[nindex8+2]&0xff)<<16)
172                                    | (((int)bpalette[nindex8+1]&0xff)<<8)
173                                    | (int)bpalette[nindex8]&0xff;
174                                nindex8 += 4;
175                            }
176                        // Read the image data (actually indices into the palette)
177                        // Scan lines are still padded out to even 4-byte
178                        // boundaries.
179                        int npad8 = (nsizeimage / nheight) - nwidth;
180                        //System.out.println("nPad is:"+npad8);
181
182                        int ndata8[] = new int [nwidth*nheight];
183                        byte bdata[] = new byte [(nwidth+npad8)*nheight];
184                        fs.read (bdata, 0, (nwidth+npad8)*nheight);
185                        nindex8 = 0;
186                        for (int j8 = 0; j8 < nheight; j8++)
187                            {
188                                for (int i8 = 0; i8 < nwidth; i8++)
189                                    {
190                                        ndata8 [nwidth*(nheight-j8-1)+i8] =
191                                            npalette [((int)bdata[nindex8]&0xff)];
192                                        nindex8++;
193                                    }
194                                nindex8 += npad8;
195                            }
196
197                        image = Toolkit.getDefaultToolkit().createImage( new MemoryImageSource (nwidth, nheight,ndata8, 0, nwidth));
198                    }
199                else if (nbitcount == 1) {
200
201                    int npad1 = (nsizeimage / nheight) - nwidth/8;
202                    byte bdata[] = new byte [(nwidth+npad1)*nheight];
203                    fs.read (bdata, 0, 8);
204                    fs.read (bdata, 0, (nwidth+npad1)*nheight);
205                    int ndata1[] = new int [nwidth*nheight];
206                    int nindex1 = 0 ;
207
208                    int max = 0 ;
209                    //System.out.println (" npad1 = " + npad1);
210
211                    for (int j1 = 0 ; j1 < nheight ; j1++) {
212                        int iindex ;
213                        iindex = nindex1 ;
214                        for (int i1 = 0 ; i1 <= nwidth/8 ; i1++) {
215                            int ib1 = 0 ;
216                            if (i1*8 < nwidth) {
217                                for (int b1 = 128 ; b1 > 0 ; b1 = b1 / 2) {
218                                    ndata1 [nwidth*(nheight-j1-1)+i1*8+ib1] = ((b1 & bdata[iindex]) > 0) ? 255+(255+255*256)*256 : 0 ;
219                                    ib1++ ;
220                                    if (i1*8+ib1 >= nwidth) {
221                                        b1 = 0 ;
222                                    }
223                                }
224                            }
225                            max = i1 * 8 + ib1 ;
226                            iindex++ ;
227                        }
228                        nindex1 += (nsizeimage / nheight) ;
229                    }
230                    //System.out.println ("max = " + max);
231
232                    image = Toolkit.getDefaultToolkit().createImage( new MemoryImageSource (nwidth, nheight,ndata1, 0, nwidth));
233                }
234                else
235                    {
236                        System.out.println ("Not a 24-bit or 8-bit or 1-bit Windows Bitmap, aborting...");
237                        image = (Image)null;
238                    }
239
240                fs.close();
241                return image;
242
243            }
244        catch (Exception e)
245            {
246                System.out.println("Caught exception in loadbitmap!");
247            }
248        return (Image)null;
249    }
250
251
252    public static  int[] getPixels(Image parImage, int parWidth, int parHeight)
253    {
254        int[] bitmap = new int [parWidth * parHeight];
255        PixelGrabber pg = new PixelGrabber (parImage, 0, 0, parWidth, parHeight,
256                                            bitmap, 0, parWidth);
257        try {
258            pg.grabPixels ();
259        }
260        catch (InterruptedException e) {
261            e.printStackTrace ();
262        }
263        return bitmap;
264    }
265}