package com.trebisky.tpqreader; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.RandomAccessFile; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.util.AttributeSet; import android.util.Log; import android.view.View; public class MyView extends View { private static final boolean drop_dead = true; private String msg1 = ""; private String msg2 = ""; private String msg3 = ""; private String msg4 = ""; private static final String TAG = "TOPO"; private Paint myPaint; private RandomAccessFile rfile; private int[] index; private int n_index; private boolean run_seq = false; private int next_map; private double my_long; private double my_lat; private double my_fx; private double my_fy; private int num_long; private int num_lat; private double elong, wlong; private double slat, nlat; private double maplet_dlong; private double maplet_dlat; private int tile_x; private int tile_y; private tpqTile draw_tile; class tpqTile { int x; /* indices in the TPQ file */ int y; Bitmap map; public tpqTile(int _x, int _y) { //Log.w(TAG,"tpq Tile: " + _x + " " + _y); x = _x; y = _y; int idx = _y * num_long + _x; //Log.w(TAG,"tpq Tile(long) " + num_long ); loadTile(idx); } // hack for special use public tpqTile(int idx) { loadTile(idx); } // This is a hack to support display // of a plain old jpeg file. public tpqTile ( String path ) { File imgFile = new File(path); if (imgFile.exists()) { map = BitmapFactory.decodeFile(imgFile.getAbsolutePath()); } } private void loadTile(int idx) { if ( idx < 0 || idx >= n_index ) { Log.e(TAG,"bad tpq index: " + idx); map = null; return; } int offset = index[idx]; int length = index[idx + 1] - index[idx]; byte[] jpeg_data = new byte[length]; try { rfile.seek(offset); rfile.read(jpeg_data, 0, length); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } // Don't know why, but the following always returned null // myBitmap = BitmapFactory.decodeFileDescriptor ( rfile.getFD() ); map = BitmapFactory.decodeByteArray(jpeg_data, 0, length); } public int getWidth () { return map.getWidth(); } public int getHeight () { return map.getHeight(); } } private void init() { myPaint = new Paint(); myPaint.setColor(Color.BLACK); myPaint.setTextSize(20); next_map = 0; } public MyView(Context context) { super(context); init(); // TODO Auto-generated constructor stub } public MyView(Context context, AttributeSet attrs) { super(context, attrs); init(); // TODO Auto-generated constructor stub } public MyView(Context context, AttributeSet attrs, int defaultStyle) { super(context, attrs, defaultStyle); init(); // TODO Auto-generated constructor stub } @Override protected void onDraw(Canvas canvas) { int ox, oy; int ex, ey; int cw, ch; // size of canvas int cx, cy; // center of canvas String bad = "NULL"; int px, py; int offx, offy; int nx1, nx2; int ny1, ny2; canvas.drawColor(Color.BLUE); // A great way to do some debugging canvas.drawText(msg1, 100, 100, myPaint); canvas.drawText(msg2, 100, 150, myPaint); canvas.drawText(msg3, 100, 200, myPaint); canvas.drawText(msg4, 100, 250, myPaint); cw = canvas.getWidth(); ch = canvas.getHeight(); cx = cw / 2; cy = ch / 2; //Log.w(TAG, "in onDraw " + draw_tile); if (draw_tile == null) { int tx = cx - (int) myPaint.measureText(bad); canvas.drawText(bad, tx, cy, myPaint); return; } // XXX // eventually this will be a global thing. // it is constant for a given TPQ file. px = draw_tile.getWidth(); py = draw_tile.getHeight(); offx = (int) (my_fx * px); offy = (int) (my_fy * py); // This puts the chosen location in the // center tile in the center of the canvas. ox = cx - offx; oy = cy - (py - offy); // This centers the center tile. //ox = (cw - px )/2; //oy = (ch - py )/2; canvas.drawBitmap(draw_tile.map, ox, oy, null); // counts from left to right nx1 = - ( ox + (px - 1)) / px; nx2 = + ( cw - (ox + px) + (px - 1)) / px; // counts from top to bottom ny1 = - ( oy + (py - 1)) / py; ny2 = + ( ch - (oy + py) + (py - 1)) / py; //msg1 = "cwh = " + cw + " " + ch; //msg1 = "fx = " + my_fx + " " + my_fy; //msg2 = "px = " + px + " " + py; //msg3 = "offx = " + offx + " " + offy; //msg4 = "ox = " + ox + " " + oy; //msg2 = "nx1,nx2 = " + nx1 + " " + nx2; //msg3 = "ny1,ny2 = " + ny1 + " " + ny2; /* ox = ox + draw_tile.getWidth(); oy = ch - draw_tile.getHeight(); canvas.drawBitmap(draw_tile.map, ox, oy, null); */ /* int xx = 1; int yy = 1; tpqTile extra = new tpqTile ( draw_tile.x +xx, draw_tile.y +yy ); ex = ox + xx * extra.getWidth(); ey = oy + yy * extra.getHeight(); canvas.drawBitmap(extra.map, ex, ey, null); */ //if ( drop_dead ) // return; for ( int xx = nx1; xx <= nx2; xx++ ) { for ( int yy = ny1; yy <= ny2; yy++ ) { if ( xx == 0 && yy == 0 ) { continue; } tpqTile extra = new tpqTile ( draw_tile.x +xx, draw_tile.y +yy ); ex = ox + xx * px; ey = oy + yy * py; if ( extra.map == null ) { canvas.drawText("MAP", ex, ey, myPaint); continue; } canvas.drawBitmap(extra.map, ex, ey, null); } } // A great way to do some debugging canvas.drawText(msg1, 100, 100, myPaint); canvas.drawText(msg2, 100, 150, myPaint); canvas.drawText(msg3, 100, 200, myPaint); canvas.drawText(msg4, 100, 250, myPaint); } // display a single .jpg or .png file public void setImage(String impath) { draw_tile = new tpqTile ( impath ); } // called whenver timer ticks and we should // go to the next file. public void nextFile() { if (!run_seq) { return; } ++next_map; if (next_map >= n_index) { next_map = 0; } msg3 = "Showing: " + next_map; draw_tile = new tpqTile(next_map); } private int swapint(int arg) { int rv; rv = ((arg & 0xff000000) >> 24) & 0xff; rv |= (arg & 0xff0000) >> 8; rv |= (arg & 0xff00) << 8; rv |= (arg & 0xff) << 24; return rv; } // did not work, not yet fixed/debugged private void fix_index(byte[] bb, int[] ii, int num) { for (int i = 0; i < num; i++) { int val; int k = i * 4; val = bb[k]; val |= bb[k + 1]; val |= bb[k + 2]; val |= bb[k + 3]; ii[i] = val; } } // read 2 bytes // 0x8950 is a PNG ? // 0xFFD8 is a JPG (swapped) private boolean is_jpeg(RandomAccessFile rf, int offset) { int val; try { rf.seek(offset); val = rf.readShort() & 0xffff; } catch (IOException e) { return false; } // msg2 = String.format("data: %X ", val); return val == 0xFFD8 ? true : false; } // This reads the entire index, but then scans to count how // many pointers are actually JPEG data (these always come first), // then returns a reduced count. private void load_index() throws IOException { int off1; int [] x_index; int count; int njpeg; rfile.seek(1024); off1 = swapint(rfile.readInt()); rfile.seek(1024); count = (off1 - 1024) / 4 - 4; x_index = new int[count]; // int nbytes = num * 4; // byte[] index_buf; // index_buf = new byte[nbytes]; // rfile.read(index_buf, 0, nbytes ); // fix_index(index_buf, index, n_index); // msg1 = "Total tiles: " + count; for (int i = 0; i < count; i++) { x_index[i] = swapint(rfile.readInt()); } // rfile.seek (index[0]); // int val = rfile.readShort(); // msg2 = String.format("data: %X ", val); // Note that for us1map2.tpq there are 6133 indices // of which only 1534 point to tiles // (this map is 59 by 26) for ( njpeg = 0; njpeg < count; njpeg++) { if ( ! is_jpeg(rfile, x_index[njpeg])) { break; } } //Log.w ( TAG, "Jpeg tiles: " + njpeg ); index = new int[njpeg]; n_index = njpeg; System.arraycopy( x_index, 0, index, 0, njpeg ); } private void read_header() throws IOException { int junk; long ljunk; junk = rfile.readInt(); // version ljunk = rfile.readLong(); // double - west ljunk = rfile.readLong(); // double - north ljunk = rfile.readLong(); // double - east ljunk = rfile.readLong(); // double - south rfile.skipBytes(456); num_long = swapint(rfile.readInt()); num_lat = swapint(rfile.readInt()); // XXX wlong = -125.0; elong = -66.0; slat = 24.0; nlat = 50.0; maplet_dlong = (elong - wlong) / num_long; maplet_dlat = (nlat - slat) / num_lat; } public void setLoc(double lng, double lat) { my_long = lng; my_lat = lat; int tile_upy; double dlong, dlat; // from map edge double tile_long, tile_lat; // from map edge (lower left) dlong = my_long - wlong; dlat = my_lat - slat; tile_x = (int) (dlong / maplet_dlong); tile_upy = (int) (dlat / maplet_dlat); tile_y = num_lat - tile_upy - 1; tile_long = (tile_x - 1) * maplet_dlong; tile_lat = (tile_upy - 1) * maplet_dlat; my_fx = (dlong - tile_x*maplet_dlong) / maplet_dlong; my_fy = (dlat - tile_upy*maplet_dlat) / maplet_dlat; // msg4 = "tile_xy = " + tile_x + " " + tile_y; draw_tile = new tpqTile(tile_x, tile_y); //Log.w(TAG, "in setLoc " + draw_tile); } public void setTPQ(String path) { File tpqfile; int off1; int offset; int length; try { tpqfile = new File(path); rfile = new RandomAccessFile(tpqfile, "r"); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } try { read_header(); load_index(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } // msg4 = "maplets: " + num_long + " by " + num_lat; // draw_tile = new tpqTile ( 0 ); } }