OSMdroid - Replace empty grid background when no tile available (offline) - java

I'm using OSMdroid library in my project to display map tiles (it's a shape with lines and blank background) from my company local sever in my app. The thing is when I use the app in offline mode and I browse the map shows an empty grey grid background for the tiles that aren't in the cache, and I want to change that empty grey grid for an blank background image/tile.
The only workaround that I've found to achieve this is the following:
Add a tile overlay and set setLoadingBackgroundColor and setLoadingLineColor to Color.WHITE, and then set the TileSource from the local server from OnlineTileSourceBase. I know this is not quite performant, so is there a better way to do this? Thanks in advance!
final ITileSource tileSource = new OnlineTileSourceBase(...)
{
#Override
public String getTileURLString(MapTile aTile) {
return getBaseUrl() + aTile.getX() + "+" + aTile.getY() + "+" + aTile.getZoomLevel();
}
};
tileProvider = new MapTileProviderBasic(context, tileSource);
tilesOverlay = new TilesOverlay(tileProvider , context);
tilesOverlay.setLoadingBackgroundColor(Color.WHITE);
tilesOverlay.setLoadingLineColor(Color.WHITE);
this.map.getOverlays().add(tilesOverlay);
this.map.setTileSource(tileProvider.getTileSource());
map.invalidate();

Your code is an example on adding a secondary tile overlay. That's useful for when you need another raster graphics overlay on top of the map imagery.
You can also change the loading lines and background for the existing and default tiles overlay. This should get you going
mMapView.getOverlayManager().getTilesOverlay().setLoadingBackgroundColor(Color.TRANSPARENT);
mMapView.getOverlayManager().getTilesOverlay().setLoadingLineColor(Color.TRANSPARENT);

Related

Using UrlImage causes bad quality scaled image

I am trying to create an app using codename one that uses a RESTful web service to download details to be displayed including an image url.
I think what I need is ScaleImageButton, the purpose of which is to have a list of items to be clicked to display more information (so several ScaleImageButtons).
The code I am currently using to create the button is as follows:
java.util.List<String> splitImage = tokenize(url, '/');
EncodedImage placeholder = FontImage.createMaterial(FontImage.MATERIAL_SAVE, btnStyle.getUnselectedStyle()).toEncodedImage();
URLImage image = URLImage.createToStorage(placeholder, splitImage.get(splitImage.size() - 1), url, URLImage.RESIZE_SCALE_TO_FILL);
ScaleImageButton btn = new ScaleImageButton(image);
btn.setBackgroundType(Style.BACKGROUND_IMAGE_SCALED_FILL);
The background image of this button is of very poor quality (a few millimetres per pixel) even though the image displays in the larger browser window.
How can I have the image fill the background but also keep its quality?
Thanks in advance.
What you are doing is downloading an image which is the size of your placeholder and scaling it up by applying it to a ScaleImageButton, instead of downloading an image of the right size.
Be sure that your placeholder image is of the right size before using it to download the actual image.
For instance:
//half the size of device width image
EncodedImage placeholder = FontImage.createMaterial(FontImage.MATERIAL_SAVE, btnStyle.getUnselectedStyle(), CN.getDisplayWidth() / 2).toEncodedImage();

Putting Markers inside Venue

I am currently working on the Venues3D provided by Here-api.
Here is my problem:
I want to put a Marker inside a Venue and ontop of a Space.
Here is a example picture of what I want from the official Here WeGo Android-App.
Example: Marker ontop of Space inside venue
I already checked out the "normal" MapMarkers but they only take GeoCoordinate and not Spaces inside a Venue.
The Venue3DTutorial didn't help too much either. There is a routing option shipped with it that pins the markers when calculating a route between two points inside a venue. But this is done in the background.(Also called Flags)
Is there an other Class that provides this functionality?
Each Space has a center as GeoCoordinate, so you can use it for your marker. You should also specify correct parameters, so the marker will be visible on top of the venue. Here's an example how to do it with a marker similar to the one in HERE WeGo app:
public void showMarker(Space space) {
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.your_marker_image);
Image image = new Image();
image.setBitmap(bitmap);
m_marker = new MapMarker(space.getCenter(), image);
// Set anchor point to the centre-bottom area of the marker
m_marker.setAnchorPoint(new PointF(image.getWidth() / 2f, image.getHeight()));
m_marker.setOverlayType(MapOverlayType.FOREGROUND_OVERLAY);
m_marker.setZIndex(100);
// You can get map from VenueMapFragment, for example.
getMap().addMapObject(m_marker);
}

How do I supply a Color Model to a .tiff image in Java when the image does not provide a Color Model to be used?

I am fairly new to Java, and so some of the classes like Color Model and JAI are not familiar to me. I have a tiff image I am reading into a program in Java. This is my read-in code:
BufferedImage img = null;
String input[] = {"LE70160412002112EDC00_sr_band5", "LE70160412002144EDC00_sr_band5"};
String filetype = "tif";
File file = new File(input[0] + "output.csv");
int numFiles = 0;
while (numFiles < 2){
if (filetype == "tif"){
FileSeekableStream stream = new FileSeekableStream(new File(input[numFiles] + ".tif"));
TIFFDecodeParam decodeParam = new TIFFDecodeParam();
decodeParam.setDecodePaletteAsShorts(true);
ParameterBlock params = new ParameterBlock();
params.add(stream);
RenderedOp image1 = JAI.create("tiff", params);
img = image1.getAsBufferedImage();
}
}
To be clear, other things are done further down in the while loop that I excluded such that the files are not overwriting each other. The problem I am having is not being able read in the file and get further into the loop. I had a tiff file that only had black and white pixels (0 or 255 red value for all pixels), and the code ran correctly because the file supplied the Color Model. The new tiff file I am trying to use is a greyscale picture (0 to 255 red value for all pixels), and every time I run the code it gives me the following error message:
Exception in thread "main" java.lang.IllegalArgumentException: No ColorModel is supplied and the image ColorModel is null.
at javax.media.jai.PlanarImage.getAsBufferedImage(PlanarImage.java:2500)
at javax.media.jai.PlanarImage.getAsBufferedImage(PlanarImage.java:2546)
at Soda.DoStuff.doStuff(DoStuff.java:60)
at Soda.Driver.main(Driver.java:6)
My first instinct given the error message is to create a new Color Model. There may also be a better way to use JAI to import the tiff file such that it supplies the Color Model for the greyscale image. My end goal is to get the red value for each pixel in the image, so I do not want the data coming in to be altered from it's original form.
Any help I can get would be much appreciated. I am open to any suggestions.
EDIT:
Someone commented to try and use the getDefaultColorModel class inside the PlanarImage library, so I changed the bottom line of the code to this:
cm = PlanarImage.getDefaultColorModel(0, 1); //
img = image1.getAsBufferedImage(null, cm);
This also did not completely work but provided a different error message:
Exception in thread "main" java.lang.IllegalArgumentException: SampleModel and ColorModel parameters must be non-null.
at com.sun.media.jai.util.JDKWorkarounds.areCompatibleDataModels(JDKWorkarounds.java:363)
at javax.media.jai.PlanarImage.getAsBufferedImage(PlanarImage.java:2505)
at Soda.DoStuff.doStuff(DoStuff.java:64)
at Soda.Driver.main(Driver.java:6)
I have extensively read through https://docs.oracle.com/cd/E17802_01/products/products/java-media/jai/forDevelopers/jai-apidocs/javax/media/jai/PlanarImage.html to learn about the PlanarImage class, but I still cannot figure out how to properly format a ColorModel. (0,1) creates a color model with 8 pixel bits and 1 component. I also tried with (1,1) which creates a color model with 16 pixel bits and 1 component. Both provided the same error message above.
EDIT2: Unfortunately, I cannot link the image itself. However, I can tell you how I got the image from USGS. Forewarning, getting this image requires you to make a free account, and then afterwards you have to 'order' the picture from USGS, which is simply they need to process the request and give a download link for a zip file. It WILL take some time before you can actually access the picture. I also suggest making the account first because it will not let you start the image checkout process until you have an account made.
Using this link, http://earthexplorer.usgs.gov/, you pick a point on the map, then set the date range so that it ends on 12/31/2002 (the start date does not matter). The go to the Data set tab where under the "Landsat Archive" bullet, you will hit the checkbox for "Landsat Surface Reflectance - L7 ETM+". Hit OK on the dialogue, then hit "Results" at the bottom of the screen.
Once you have signed into your account and done this search, you should see many images on the left side of your screen with similar names to the filenames in my code above. You want to hit the shopping cart next to one of the images (You only need one, my whole project required 2, but for the purposes of reading in the file, that's not necessary). The shopping cart should turn green. Then in the top right corner there is a link to an Item Basket. You hit "Proceed to Checkout" and "Submit Order" on successive screens, and then you wait for an email from USGS.
Finally unzip the file, and you should have about 10 images. As you can see in the code, I am using the image with the name "sr_band5", but I believe any of the bands are greyscale which I cannot read in. Hope this can help.

Store sprites from spritesheet in array Libgdx

I have 960x960 spritesheet stored as a png inside of my Libgdx android assets. In a class I have specified towards initializing sprites for use in my game, I am trying to make it so there is a 120x120 sprite cut from the spritesheet (so there should be 64 items in the array). How am I able to do this? This is what I have tried in a similar situation:
public static Texture spritesheet;
public static Sprite[] textures = new Sprite[64];
...
//inside method that gets called once to initialize variables
spritesheet = new Texture(
Gdx.app.getType() == Application.ApplicationType.Android ?
"...Spritesheet.png" :
"android/assets/...Spritesheet.png"
);
spritesheet.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear);
for (int x = 0; x < 64; x ++) {
textures[x] = new Sprite(spritesheet, x, (x%8), 64, 64);
textures[x].flip(false, true);
}
I then render the sprite in other classes with this:
batch.draw(Assets.textures[0 /*this can be any number*/], (float) x, (float) y, 108, 108);
When I do this, it acts really weird. It says there are elements filled in the array, but there's still Array Index Out of Bounds Exceptions or the sprites just render crazily. Overall, it's not working out. What I'm trying to do is make it so I don't have to initialize 64 different sprites separately, and make it so I can easily change the sprite by changing the index inputted when rendering the sprite so I can do some other things later on, like an animation. How can I go about doing this?
You should use a TextureAtlas for this purpose. A atlas is a file generated automatically from separate images by the LibGDX TexturePacker. It stores everything from image bounds within your sheet to NinePatch information. All you need to do is put your separate images in a folder and run the TexturePacker on that folder. This will create a sheet and a .atlas/.pack file for you that can easily loaded.
There exists a TexturePackerGui if you have difficulty with the commandline but I do recommend the command line or even using it within your app.
What I usually do is create these sheets on the fly when I'm developing. I can easily overwrite separate images and they have a immediate effect after I run my app again. I start with creating a new folder images at the root of my project. Then for each pack I need I create another folder. For this example I create the folder tileset in images. In the DesktopLauncher I will setup this folder to produce a atlas from the images.
TexturePacker.Settings settings = new TexturePacker.Settings();
settings.maxWidth = 1024;
settings.maxHeight = 1024;
The settings file specifies everything about your atlas. The maximum size of a single sheet, if it should strip transparency from images, padding, rotation, etc. They are all very straightforward and you can look these all up in the documentation. Using these settings you can create your atlas.
TexturePacker.process(settings,
"../../images/tileset", //where to find the images to be packed.
"../../android/assets/tileset/", //where to store the atlas and sheet
"tileset"); //what filename to use
Now you can open your .atlas file and you see it uses the filenames as a alias. This alias is used to look them up but let's load the atlas first.
TextureAtlas atlas = new TextureAtlas("tileset/tileset.atlas");
By passing just a string to the constructor it looks by default in your local path which in turn is by default in android/assets/. Now we can ask the atlas to hand over our assets in the sheet.
atlas.findRegion("alias"); //hands over the image on the sheet named "alias"
Looking up textures like this is somewhat expensive. You don't want to look up many textures like this each update so you still need to store them somewhere.
If you name your image sequence like image_01.png, image_02.png, image_03.png it stores them all under the same name and within the atlas it sorts them bu it's index. So if you want a separate array of certain textures you can name them with _xx and get them all in one go:
atlas.findRegions("alias");
This is especially handy for Animation. Just copy your image sequence to a folder and specify it to be packed. Name your sequence correctly and give the regions to the animation. Everything will work right off the bat.
Loading a TextureAtlas with the AssetManager is pretty much the same as a normal Texture except you would specify it's from a TextureAtlas.class. You always load the .atlas which in turn handles your image.
I always use AssetDescriptor to load my assets. If I where you I would get rid of the static Assets.textures[] since that will get you into trouble sooner or later.
//None static AssetManager with getter
private AssetManager manager = new AssetManager();
public AssetManager getManager() { return manager; }
//Specify a descriptor for the atlas, this is static so I can acces it anywhere.
//It's just a descriptor of the asset so this is safe.
public static final AssetDescriptor<TextureAtlas> TileSet = new AssetDescriptor<TextureAtlas>("tileset/tileset.atlas", TextureAtlas.class);
//then just load everything
public void load()
{
manager.load(tileSet);
//... load other stuff
}
Now just pass the AssetManager object anywhere you need access to your assets and you can load any asset just like so:
TextureAtlas tileset = assetManager.get(Assets.TileSet);
I think your for loop should look like this
for(int x = 0; x < 64; x ++){
textures[x] = new Sprite(
spritesheet,
(x%8)*64, //where x=3, (3%8)*64 = 3*64 = 192px sourceX
(x/8)*64, //where x=3, (int)(3/8)*64 = 0*64 = 0px sourceY
64, //source width
64 //source height
);
Another test case where x=20;
(20%8)*64 = 4*64 = 256px SourceX
(20/8)*64 = 2*64 = 128px SourceY

How to get the rectangular coordinates of the annotation using ice pdf viewer

I need to get the rectangular coordinates of the annotation using ice pdf viewer. Is there anyway to achieve this?
You'll need to go into the Viewer RI source code make a few changes and then rebuild the icepdf-viewer.jar.
The class org.icepdf.ri.common.tools.SquareAnnotationHandler handles all the mouse events and drawing for creating a Square annotation. This is a good place to start for extending or using it as a reference.
Add a message dialog to under mouseReleased
JOptionPane.showMessageDialog(null, "Rectangle coordinates x ---> "+rectToDraw.x+" y --> "+ rectToDraw.y+" Width --> "+ rectToDraw.width+" height --> "+ rectToDraw.height);
If anyone is still looking for answer.
Icepdf's Annotation class holds these coordinates. They can be retrieved like this:
Rectangle2D.Float box = annotation.getUserSpaceRectangle();
Map<String, Double> bounds = new HashMap<String, Double>();
bounds.put("height", box.getHeight());
bounds.put("width", box.getWidth());
bounds.put("x", box.getX());
bounds.put("y", box.getY());

Categories

Resources