consideration notes: extending SurfaceView, implementing SurfaceHolder.Callback, and loading in bitmap(.png) images to render the canvas (9x9 grid).
I am trying to get the system to resize the images for me so that I don't have to manually create up-to 4 copies of everything (even 3*77 bitmaps is bad overhead [and yes I need all 77 potentially]) I would prefer just having 77 image files in res/drawables(not all of them will be drawn at any given time; at most maybe 38, but needs to be dynamicly capable to change them out).
Q1: how do I get the system to resize the images without doing the white space thing that android.develop talks about for .9.png (considering that all of my grid images have black borders, and need to butt-up together)?
Q2: is there a unifying screen proportionality (4:3, 5:4) that I can fall back on so that diagonal lines don't look really bad?
A1:
Bitmap b= BitmapFactory.decodeResource(context.getResources(), R.drawable.b);
b=Bitmap.createScaledBitmap(b,newWidth, newHeight, true);
A2: i don't think so
Related
I've been having problems with large images being resized for UI use in Android.
Look at this image, it's an ImageView:
The original image (That arc is a progressbar) is around 10 times bigger than what you see here. In UWP (Windows Platform) we had no problem using a very large image, but here in Android, I beleive it's the Nearest Neighbour method used for fitting images into UI elements, which as you see, causes sharp edges.
Is there any way to switch it into another method? Like Bicubic? It happens in all Android versions I've tested (4.1, 5.0, 6.0).
Just to mention, I'm using Xamarin 4, which I don't beleive as a contributing factor here.
No luck searching through the internet, I'm afraid I'm the only one having this problem.
Thanks.
As mentioned above, you should prefer to use vector image instead of pixel image.
But if you have to use pixel image, maybe you could use BitmapRegionDecoder to decode lines of image and write your own resample algorithm(like Bilinear Interpolation, it's much better than the Near Neighbor) to resize the image, typically in JNI side.
Another possible way is to use "filter" parameter while calling Bitmap.createBitmap method as your original image would not cause OOM issue, just set it to true, it works to reduce the artifacts.
You should use Vector Images instead of Bitmap Images.
Bitmap x Vector
A bitmap represents an image by a series of colored pixels. Whereas a vector image is represented by geometric shapes (lines, curves) using colors.
The main utility of a vector image is allowing to scale without losing definition.
I'm currently working on a simple Android game for school, and the game runs for a little bit before it runs out of memory and crashes. I suspect this has to do with the number of images I'm using in the game (small, 10-20 KB sized files for 10+ items/characters/buttons, and also a very large, 450 KB PNG file for a splash screen background).
I've been using BitmapFactory to decode all of my small item PNGs, and I also was able to set the background for my main GameView as so (only the bare minimum of example code is included):
public class GameView extends SurfaceView implements SurfaceHolder.Callback {
private Bitmap background, invincibleBitmap;
//Sets the background bitmap to an image scaled to the same size as the user's screen
background = Bitmap.createScaledBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.background), getWidth(), getHeight(), false);
invincibleBitmap = Bitmap.createScaledBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.invincible_item), 60, 60, false);
For the splash screen I mentioned earlier, however, I've been using the Activity's Layout XML file to set the image as so:
android:background="#drawable/main"
I want to be able to scale main.png the same way that I did in a View in an Activity, hoping that it would help the memory overload problem. How would I go about doing this? I'm a beginner with Android in general so the simpler the solution, the better.
To point out, image file size don't effect memory usage. It depend on the image specs: width x height x 1 byte.
You shouldn't set splash screen image in code by scaling it depending on screen resolution. The drawable folders are there to do that. Provide a different image with different specs for each of the screen resolution categories (l,m,x,xx,xxx).
As a fast solution, copy and paste the same image to all the
drawable folders. Surprisingly you will notice a difference.
I'm having trouble cleanly down-scaling images on Android. I'm looking to scale small PNG images between arbitrary sizes of about 10-100% of their original size.
I've created a sample image to demonstrate the problem and exacerbate the unusual behaviors I'm seeing in Android's image scaler:
The above image is a screenshot from an Android device with some annotations added. I've also added the same images in a second column on the left side showing how they are rendered with a linear scaling by "The GIMP" (GNU Image Manipulation Program).
The base image consists of a checkerboard pattern background of red and blue pixels. On that background I've drawn some 1px-wide yellow lines and fairly thin green text. The image is 288x288 pixels.
When scaling the image to 1/3 of its original dimensions, Android seems to simply grab one in nine pixels, throwing out all other data. Some of the yellow lines disappear entirely as a result. Remarkably, the checkerboard pattern remains intact (which is simply a result of every 3rd pixel being used).
When scaling the image to a dimension of near-but-not-exactly 50% of its original size, e.g., 142x142 or 143x143, the scaler creates some fairly large anomalies/artifacts on the image.
At 50% size (144x144), the image looks correct.
The test image does bring out the worst of the image scaler, but "normal" PNG icon images are severely impacted as well. From 10-33% or so the images aren't properly resampled, and thus appear extremely "bitmapped". And certain larger size images have very strange anomalies in them at certain sizes.
If anyone knows a means to disable this strange scaling behavior, even at a performance cost, I'd greatly appreciate knowing about it. It can certainly be solved by writing an algorithm that works directly on the pixels of bitmaps, but I'm hopeful that isn't the only option.
Also noteworthy is the fact that all image work is being done with ARGB_8888 Bitmap.Configs. I've tried manipulating image size by setting maxwidth/maxheight on ImageViews, by using Bitmap.createScaledBitmap(), and by using Bitmap.createBitmap with a Matrix. All attempts have this same result. Bitmap filtering is enabled.
Thanks again for any suggestions!
Using Bitmap.createScaledBitmap() and Bitmap.createBitmap with a Matrix is the same; see the source for Bitmap.createScaledBitmap (which hasn't changed since Android 2).
On Android 4.0+, using a matrix (as in Bitmap.createScaledBitmap) allows hardware-accelerated operations if enabled (enabled by default on 4.1+ IIRC), thus we doesn't have direct control over what is being done and how it is done.
That means you'll have to implement your own scaling method using the desired (here, linear) filtering; either by pixel processing; or using OpenGL ES with the good filter, but it may not be available on all devices.
i would like to know whether is it possible to merge several images to form one complete image. For my case, is a floor plan that is split in 18 small images and i would like to merge them into one. I had one idea but not sure whether is it workable. My idea is this:
I would first place the top left most image first, with the x and y coordinates as (0,0).
Next for the subsequent images (right/bottom of this first image), using the width and height of the image, i would find out the coordinates where the next image would be placed. Doing this i presume would required 18 ImageView to achieve that.
Btw, these 18 images are .gif format and so do i need to like convert them to Bitmap or something before i can display them using ImageView?
You could merge the images to a bigger images by drawing the small images to a canvas associated with the resulting big bitmap
Canvas c=new Canvas(result_bitmapenter);
and then draw your small images onto the canvas
c.drawBitmap(small,...);
But that might not be the best way as big images eat lots of memory - perhaps you should concider dynamic loading instead of merging then
Yes its possible create a Bitmap object large enough to hold the whole floor plan and use Canvas to paint them into to the large bitmap. Be sure to cache it or you'll be recreating it every time and you'll have to convert it to png for compatibility with older devices.
I don't have any problem managing textures. But I didn't work that much with loading textures from images. All I know is that the texture needs to be of size 2^i by 2^i.
But what's the best technique to load any images into a texture. If the images is not a square, I can fit it in the square and add two black parts to fill what is missing. But I'm not sure how to do the stretching.
So, if I have an image of let say 800x600 and I want to put it in a 512x512 square, what's the best trick to copy the pixels into texture ? Or, specially on Android, is there some functions that exists that would do that for me ? In short, it's like I want to resize the 800x600 image to be 512x384 and put it in the texture. But I want to preserve as much information as I can.
The OP Answered his own question with:
SOLVED: a friend showed me some references that covers what I want.
To resize, you can do it with the Bitmap class of Android. You can specify a Matrix, just like the one used for OpenGL to resize the Bitmap. From that point, I expect the pixels to be well preserved and will be able to put them in the texture.
If they come back and put the answer here themselves and accept it then I will delete this answer.