SVG render SDK vs NDK - android

I would like to know what is the speed difference at rendering SDK side and NDK side with bigger SVG files.
I have tried with NDK here but doesn't support bigger SVG files.
Probably the best SDK parser -at least this is I am using is androidsvg
Does it worth the effort to get into Native side? - no heap limit, if the recursive calls are rewritten to iterative ones.
SDK depends on device: 1-12 sec rendering with a big SVG file ( 350kb ).

I don't know how is with NDK, but I took 2x phone with same Android OS and same svg.
Nexus One with 4.2.2 ( Cyanogen mode )
Thl w8s , aka Galaxy s4 Chinese clone:
I starting I have printed out the max available memory, with large heap enabled.
Than loaded the svg file from assets. An svg made by artists, has around 350kb the file, and the SVG dom object has aroung 7-8Mb in memory, so this is not a circle + 1 rectangle....
Than based on screen resolution need to render the svg to a square area.
The 480x800 to a 356x356 area.
The 1080x1920 phone to a bigger area, you can do the math, now I am lazy. Anyway, this need to fill a lot more pixel area.
I think the 400 milliseconds it is an acceptable result from him to make a logo / background. Not need to re-draw often, since isn't a game element.
For games: at first time loading transform from SVG to png all files and use the cached one.
It will take time, only the first time.
It will take space , user can clear it. - than re-make, if needed

Related

Should Android app make use of SVG's to maximum extent?

The official documentation Vector Asset Studio states that SVG can be used to reduce APK size. It also states that SVGs take much CPU cycles for drawing.
The initial loading of a vector graphic can cost more CPU cycles than
the corresponding raster image. Afterward, memory use and performance
are similar between the two. We recommend that you limit a vector
image to a maximum of 200 x 200 dp; otherwise, it can take too long to
draw.
Also, it is supported from Lollipop onwards. On backward compatibility, it states that-
Android 4.4 (API level 20) and lower doesn't support vector drawables.
If your minimum API level is set at one of these API levels, you have
two options when using Vector Asset Studio: generate Portable Network
Graphic (PNG) files (the default) or use the Support Library.
For backward-compatibility, Vector Asset Studio generates raster
images of the vector drawable. The vector and raster drawables are
packaged together in the APK.
Raster images look like more efficient than the SVGs. Also, though the size of APK will be reduced, what will be the impact of SVG on memory and app performance as the doc states that it will take time to draw large SVG files.
As an android developer, what should be my approach? Which of above or any other ways will ensure my apps be optimized and deliver good performance.
Edit : A query then, What should be the best approach among the two -
Reduce the apk size by using the SVGs but will increase CPU cycles for drawing
Use raster images
In my own experience Vector Asset Studio is picky about what it accepts in an SVG. If you are not well versed in SVG you are going to have a hard time massaging the SVG markup into something that VAS accepts. From the top of my head I recall it doesn't support defs or filter, but some vector graphics software seems to include it even if it's not strictly necessary. Given flat icons (no gradients or shadows, for example) you can work around this by manually editing the mark-up.
As for performance, it really depends on the amount of icons you will display per screen, and the complexity of these icons. You will have to conduct some stress tests to see if your target devices hold up. Note that this only impacts the initial load, behind the scenes these vector images are rasterized and—as the text you cited mentions: Afterward, memory use and performance are similar between the two.
Your approach should be pragmatic, attempt to draw a couple of your icons on the screen and see how smoothly it goes. This is a subjective question that depends on the constraints of the device and the person who implements it.
My experience using react-native-svg was very good, but animation performance that needs to recompute dynamic SVG suffered from I think they call it 'too many passes over the bridge'. There may be a way to optimise it, and I intend to investigate this on my next RN project. I should qualify this last statement by emphasising that animation only suffers when the SVG needs to be recomputed during the animation (on the JS side). For example have a native ScrollView component with your SVGs inside it, the ScrollView can animate perfectly performantly, but if you want to change the SVGs programatically as a function of scroll position within the React/JS side, you will have the bridge problem, and dropped frames galore.
Here is my boilerplate which sets up a few basic shapes in Android RN:
proto__33__boilerplate
Generally I would say (programmatic) SVGs are great for Android, but I haven't yet found a performant way to use them for animations. Will update if I find that.

Android decrease size of graphic in application

I use bitmaps in application and work with .bmp or .png formats. I try to comply with standards from developer android page - Supporting Different Densities
But if I use bitmaps on background and also on imageviews and imagebuttons my application is very huge. Let's say about 40 MB. What is the best way to make graphic the smallest size ?
Of course I can use some tools such as PngCrush to decrease size but it helps only little bit.
I was looking on other applications they are full of graphics and it has only for example 12 MB. How does they reach so small size of application ? Because I don't know using openGL, using images is one and only way to use at the moment. What is the difference in data size when using OpenGL in comparision with using images ? Do you think if I have a lot of graphics I must start with OpenGl using ?
Do you have any interesting tips to make the smallest graphic ?

Displaying and navigating large custom maps offline using Phonegap

My question is how to efficiently display large custom maps in an offline Phonegap application, allowing them to be panned and zoomed smoothly while still supporting older mobile devices?
I’m developing a mobile application that involves using geolocation to navigate walking routes in remote areas where it’s likely the user won’t have a signal and therefore an internet connection. It’s important that the app works well with Android 2.2+ (so SVG is not an option) as well as iOS4+.
I’ve drawn custom vector maps using Adobe Illustrator at resolutions appropriate to each route, the average being about 2000x2000 pixels and the largest of which so far results in an image 4000x2400 pixels.
I’ve chosen to go with Phonegap/JQM rather than native simply because I come from a web programming background and it seemed the fastest way to get a user interface up and running without needing to delve into native code too much, although I’ve written a couple of Phonegap plugins using native code for the purposes of power and screen management.
The application needs to allow the user to pan around the map (by dragging) and zoom in/out (by pinching) between about 25% to 200% of the original image size.
Most of the testing I’ve done has been on an HTC Desire running Android 2.3.3 and an HTC Wildfire running Android 2.2 since these are likely to be some of the lowest spec devices the app is going to have to run on.
I’ve tried out various approaches to display the map (detailed below), but so far each has proved unfit for purpose either because the memory usage of the app is too great, the storage space required makes the app too large to download or the CPU usage is too intensive causing lag when panning/zooming.
Any suggestions much appreciated. Thanks in advance.
Approaches I’ve tried:
1. Display map as raster PNG using tag
This was the first approach I tried. Exporting the 4000x2400 pixel image from Illustrator as a 128 colour PNG-8 resulted in a 746Kb file. I panned the image by absolutely positioning it relative to the viewport and zoomed the image by scaling the width/height attributes of the tag.
The problem with this approach was that even at a 1:1 zoom level, the Android application used 60Mb of RAM for the image and zooming in to 200% caused this to increase 120Mb, causing the app to crash on the HTC Wildfire.
2. Display portions of raster PNG using HTML5 canvas
To avoid the problem of zooming-in causing a proportional increase in memory usage, I tried loading the image via JS then copying the portion of the image to be displayed to a canvas the size of the viewport, something like:
var canvas = $(‘canvas#mycanvas’);
canvas.width = $(window).width;
canvas.height = $(window).height;
...
var img = new Image();
img.src = “map.png”;
...
var context = canvas[0].getContext("2d");
context.drawImage(img, x, y, w, h, 0, 0, canvas.width, canvas.height);
where x,y is the top-left corner within the source image defined by panning
and w,h is the area size within the source image determined by zoom level
The problem here was that large map images were somehow losing quality while in memory (I can only assume there’s some upper memory limit which is resulting in dithering), causing the maps to look distorted in the app: see here for an example screenshot
3. Display map as vector using HTML5 canvas
A bit of Googling led me to discover ai2canvas, an Illustrator plugin that enables you to export artwork as vectors displayed in an HTML5 canvas. The result of the export is an html file containing a chunk of JS which represents all the paths in illustrator as bezier curves. Exporting my 4000x2400 map resulted in a 550Kb html file containing the vector paths.
In my test app, I rendered the entire map to an in-memory canvas (not attached to the DOM) of 4000x2400 pixels, then copied the relevant portions of it to a viewport-sized canvas using context.drawImage() with the in-memory canvas as the source.
On the HTC Wildfire, although the initial render of all the bezier curves to the in-memory canvas took around 2000ms, copying between canvases was fast enough to allow smooth panning and zooming. The problem was when I looked at the memory usage of the app, it was using 120Mb for the in-memory canvas once all the vectors had rendered.
I tried a second approach using the vector map; instead of rendering all the vectors to a large in-memory canvas, I made the app calculate which vector paths were visible within the viewport at the current pan position/zoom level during each drag/pinch event and only draw the visible vectors to the viewport-sized canvas. While this reduced the required memory usage to 10Mb, the CPU cycles required to perform these calculations on every drag/pinch cycle made the app lag so much on the old android phones it was unusable.
4. Display map using offline tiling
Using map tiler, I created PNG tiles for my maps at zoom levels from 25% to 100%. In my test app, I was then able to lazy load the tiles on demand reducing memory usage and producing a smooth pan/zoom experience even on the HTC Wildfire. I thought I’d found the solution until I looked at the size of the APK produced: for my 4000x2400 map, map tiler produced 4Mb of tile images. Most of my maps are around 2000x2000 pixels, resulting in about 2Mb of tiles. The code of my proper application plus the Phonegap overhead is another 2Mb.
My intention is to release a series of apps available on the Android/Apple markets, each with a set of around 10 maps, but with tiling each map weighs in at between 1-4Mb so the resulting app becomes a very large download.
In case this is of interest to anyone else, I solved this by using map tiling in the end, using a tool called pnqnq to create 8-bit PNGs constrained to 256 colours. The resulting set of tiles for my 4000x2000 map was about 800K in size as opposed to 4Mb for PNG-24, which was an acceptable size for assets in my Android and iOS applications.

Android: pixel quality reduction in Images loaded in WebView

I am building Javascript application for mobile browsers (not wrapped-as-native app).
I noticed that Android (tested 2.3 emulator and Galaxy S device) reduces the quality of loaded images if the image dimensions exceed certain threshold (width above 1400 px or so). This make it impossible to load big bitmap images (2000 x 2000 px) without the quality going unusable.
I tested this by
Loading one big image and drawing it on the - I got pixel garbage out. If I draw grid lines using lineTo() on they have perfect quality, so the bad must be in the image pixel data
Slicing the big image to 100 x 100 slices and drawing them to a canvas - this is the only method I found resulting no quality reduction. However, slicing is cumbersome, adds extra step to preprocess images and page loading times suffers
I tested tring to load image with new Image() object, tag and CSS background: everything suffers from the reduced quality, so I suspect the probelm is the image loader itself
I also tried everything with CSS image-rendering https://developer.mozilla.org/En/CSS/Image-rendering - no luck
Viewport tag seems to have no effect to the image loading - the data is already garbage when you try to touch the loaded pixel data. I tried all possible values suggested in Android's SDK documentation http://developer.android.com/reference/android/webkit/WebView.html
Tested also Firefox mobile, desktop browsers, iOS: everything is good there.
So, what is going on - Android WebView simply can't load big images?
(smiley of hung Android robot here)
Android unconditionally resamples images and reduces quality if a certain threshold of memory usage is exceeded.
https://android.googlesource.com/platform/external/webkit/+/android-3.2.4_r1/WebCore/platform/graphics/android/ImageSourceAndroid.cpp
There is no way to access the original image data in intact.
I posted a question regarding this to android-developers Google Group and kindly asking to maybe provide some kind of flag to opt-out from this behavior.
Meanwhile, if you are considering developing HTML5 web apps and you might use big images, you simply need to preprocess them on the server-side by slicing, send in smaller images to the device and then reconstuct the original image using or putting many tags inside a container element.
Another option would be load image "manually" by writing a PNG decoder which directly loads the image to , bypassing ImageSourceAndroid class.
The question is old so probably few things changed, but if you are having image quality issues with WebView then consider converting your image into PNG format.
Somehow when I load the jpeg version of the image the quality is low, while loading the png image with the same resolution the quality is high.

Why an android application becomes slower to respond

I had an android app built especially for medium screen size android devices.
Now it was required to build that same app for a device called nook-color (by Barnes & Noble)
So for this we made all the images bigger & size & changed the layouts.
The result is that the apk which was 97.5 Mb earlier has now become 124 Mb in size.
Now the testers have complained that the application has become slower and it takes a little longer for any screen to open up. I am wondering whether this is due to bigger images or there is something else.
Can you please tell me what could be the reason for this.
124 Mb for an app seems to be a little bit excessive. I'd suggest trying to scale down the image assets, use Nine Patch images, as well as using PNGCrush
Yes. The delays are (at least in part) due to loading larger images (de-compressing them to bitmaps, to be more exact). Unless you can't help it, you should attempt to convert as many of these images to 9-patches : http://developer.android.com/guide/developing/tools/draw9patch.html.

Categories

Resources