+ if (!self) return 0;
+
+ GisTile *tile = gis_tile_find(self->tiles, lat, lon);
+ if (!tile) return 0;
+
+ struct _TileData *data = tile->data;
+ if (!data) return 0;
+
+ guint16 *bil = data->bil;
+ if (!bil) return 0;
+
+ gint w = TILE_WIDTH;
+ gint h = TILE_HEIGHT;
+
+ gdouble ymin = tile->edge.s;
+ gdouble ymax = tile->edge.n;
+ gdouble xmin = tile->edge.w;
+ gdouble xmax = tile->edge.e;
+
+ gdouble xdist = xmax - xmin;
+ gdouble ydist = ymax - ymin;
+
+ gdouble x = (lon-xmin)/xdist * w;
+ gdouble y = (1-(lat-ymin)/ydist) * h;
+
+ gdouble x_rem = x - (int)x;
+ gdouble y_rem = y - (int)y;
+ guint x_flr = (int)x;
+ guint y_flr = (int)y;
+
+ //if (lon == 180 || lon == -180)
+ // g_message("lon=%f w=%d min=%f max=%f dist=%f x=%f rem=%f flr=%d",
+ // lon, w, xmin, xmax, xdist, x, x_rem, x_flr);
+
+ /* TODO: Fix interpolation at edges:
+ * - Pad these at the edges instead of wrapping/truncating
+ * - Figure out which pixels to index (is 0,0 edge, center, etc) */
+ gint16 px00 = bil[MIN((y_flr ),h-1)*w + MIN((x_flr ),w-1)];
+ gint16 px10 = bil[MIN((y_flr ),h-1)*w + MIN((x_flr+1),w-1)];
+ gint16 px01 = bil[MIN((y_flr+1),h-1)*w + MIN((x_flr ),w-1)];
+ gint16 px11 = bil[MIN((y_flr+1),h-1)*w + MIN((x_flr+1),w-1)];
+
+ gdouble elev =
+ px00 * (1-x_rem) * (1-y_rem) +
+ px10 * ( x_rem) * (1-y_rem) +
+ px01 * (1-x_rem) * ( y_rem) +
+ px11 * ( x_rem) * ( y_rem);
+ return elev;
+}
+
+/**********************
+ * Loader and Freeers *
+ **********************/
+#define LOAD_BIL TRUE
+#define LOAD_OPENGL FALSE
+struct _LoadTileData {
+ GisPluginSrtm *self;
+ gchar *path;
+ GisTile *tile;
+ GdkPixbuf *pixbuf;
+ struct _TileData *data;
+};
+static guint16 *_load_bil(gchar *path)
+{
+ gchar *data;
+ g_file_get_contents(path, &data, NULL, NULL);
+ g_debug("GisPluginSrtm: load_bil %p", data);
+ return (guint16*)data;
+}
+static GdkPixbuf *_load_pixbuf(guint16 *bil)
+{
+ GdkPixbuf *pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, TILE_WIDTH, TILE_HEIGHT);
+ guchar *pixels = gdk_pixbuf_get_pixels(pixbuf);
+ gint stride = gdk_pixbuf_get_rowstride(pixbuf);
+ gint nchan = gdk_pixbuf_get_n_channels(pixbuf);
+
+ for (int r = 0; r < TILE_HEIGHT; r++) {
+ for (int c = 0; c < TILE_WIDTH; c++) {
+ gint16 value = bil[r*TILE_WIDTH + c];
+ //guchar color = (float)(MAX(value,0))/8848 * 255;
+ guchar color = (float)value/8848 * 255;
+ pixels[r*stride + c*nchan + 0] = color;
+ pixels[r*stride + c*nchan + 1] = color;
+ pixels[r*stride + c*nchan + 2] = color;
+ if (nchan == 4)
+ pixels[r*stride + c*nchan + 3] = 128;
+ }