I have a transparent sprite consists of 10 images which each image has size of 1,000x1,000 px (that means the sprite has size of 10,000x1,000 px). The reason I made quite big resolution because actually I have a full screen animation application and I just want to make sure the image still has a good quality on a big screen phones.
So I have class Sprite.java
public class Sprite {
private static final int BMP_ROWS =1;
private static final int BMP_COLUMNS = 10;
private int x= 0;
private int y = 0;
private GameView gameView;
private Bitmap bmp;
private int currentFrame =0;
private int width;
private int height;
public Sprite(GameView gameView, Bitmap bmp){
this.gameView = gameView;
this.bmp = bmp;
this.width = bmp.getWidth() / BMP_COLUMNS;
this.height = bmp.getHeight() / BMP_ROWS;
}
private void update(){
currentFrame = ++currentFrame % BMP_COLUMNS;
}
public void onDraw(Canvas canvas){
update();
int srcX = currentFrame*width;
int srcY = 0 * height;
Rect src = new Rect(srcX, srcY, srcX+width, srcY+height);
Rect dst = new Rect(x, y, x+width, y+height);
canvas.drawBitmap(bmp, src, dst, null);
}
}
and this is the code of GameView.java
public class GameView extends SurfaceView {
private Bitmap bmp;
private SurfaceHolder holder;
private GameLoopThread gameLoopThread;
private Sprite sprite;
public GameView(Context context) {
super(context);
gameLoopThread = new GameLoopThread(this);
holder = getHolder();
holder.addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
gameLoopThread.setRunning(false);
while(retry){
try{
gameLoopThread.join();
retry = false;
} catch(InterruptedException e){}
}
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
gameLoopThread.setRunning(true);
gameLoopThread.start();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
});
bmp = BitmapFactory.decodeResource(getResources(), R.drawable.elephant);
sprite = new Sprite(this, bmp);
}
@SuppressLint("WrongCall")
@Override
protected void onDraw(Canvas canvas){
canvas.drawColor(Color.WHITE);
sprite.onDraw(canvas);
}
}
However, when I run it on the emulator, I got error
08-19 11:14:21.103: E/AndroidRuntime(385): FATAL EXCEPTION: main
08-19 11:14:21.103: E/AndroidRuntime(385): java.lang.OutOfMemoryError: bitmap size exceeds VM budget
08-19 11:14:21.103: E/AndroidRuntime(385): at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
08-19 11:14:21.103: E/AndroidRuntime(385): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:460)
08-19 11:14:21.103: E/AndroidRuntime(385): at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:336)
08-19 11:14:21.103: E/AndroidRuntime(385): at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:359)
08-19 11:14:21.103: E/AndroidRuntime(385): at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:385)
08-19 11:14:21.103: E/AndroidRuntime(385): at binus.killthemall.GameView.<init>(GameView.java:49)
08-19 11:14:21.103: E/AndroidRuntime(385): at binus.killthemall.MainActivity.onCreate(MainActivity.java:15)
08-19 11:14:21.103: E/AndroidRuntime(385): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
08-19 11:14:21.103: E/AndroidRuntime(385): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1611)
08-19 11:14:21.103: E/AndroidRuntime(385): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1663)
08-19 11:14:21.103: E/AndroidRuntime(385): at android.app.ActivityThread.access1500ドル(ActivityThread.java:117)
08-19 11:14:21.103: E/AndroidRuntime(385): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931)
08-19 11:14:21.103: E/AndroidRuntime(385): at android.os.Handler.dispatchMessage(Handler.java:99)
08-19 11:14:21.103: E/AndroidRuntime(385): at android.os.Looper.loop(Looper.java:123)
08-19 11:14:21.103: E/AndroidRuntime(385): at android.app.ActivityThread.main(ActivityThread.java:3683)
08-19 11:14:21.103: E/AndroidRuntime(385): at java.lang.reflect.Method.invokeNative(Native Method)
08-19 11:14:21.103: E/AndroidRuntime(385): at java.lang.reflect.Method.invoke(Method.java:507)
08-19 11:14:21.103: E/AndroidRuntime(385): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
08-19 11:14:21.103: E/AndroidRuntime(385): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
08-19 11:14:21.103: E/AndroidRuntime(385): at dalvik.system.NativeStart.main(Native Method)
I don't want to scale my image into smaller size. So, what's wrong and what should I do?
-
wanna display 10 images at a time?Exceptional– Exceptional2013年08月19日 05:04:56 +00:00Commented Aug 19, 2013 at 5:04
-
stackoverflow.com/questions/8417034/…Exceptional– Exceptional2013年08月19日 05:06:23 +00:00Commented Aug 19, 2013 at 5:06
-
@Exeptional I'm making an animation using .png sprite that consists of 10 images, let's say every image changes every 1 second. Actually like this edumatica.ing.ula.ve/teleclases/tecnomatica/Animatica/Teleclase/…noobprogrammer– noobprogrammer2013年08月19日 05:16:04 +00:00Commented Aug 19, 2013 at 5:16
-
@Exeptional 1000x1000 pixelsnoobprogrammer– noobprogrammer2013年08月19日 05:48:47 +00:00Commented Aug 19, 2013 at 5:48
-
@noobprogrammer : I have already answer a similar question here. It might be helpful to you. stackoverflow.com/questions/18255572/…arshu– arshu2013年08月19日 06:26:24 +00:00Commented Aug 19, 2013 at 6:26
4 Answers 4
Your bitmap size is 80 MBytes. It's really heavy and it's normal that android kills your app with such memory requests. You need to split it somehow, or use Bitmap Options to get image that you actually need.
1 Comment
An app tends to get about 40ish MB of memory on Android (it varies based on device)- and that includes the size of all resources. So half of that is already gone. You really don't have a lot of memory to work with. You'll be able to load 1 image of that size on most devices. You won't be able to have 2, and if you try to page 1 in and the original out you'll end up spinning up the GC constantly. This approach won't work with images of this size on Android.
2 Comments
For decoding bitmap use this method and -See this also -Out of memory while creating bitmaps on device
public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, resId, options);
}
public static int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
// Calculate ratios of height and width to requested height and width
final int heightRatio = Math.round((float) height / (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
// Choose the smallest ratio as inSampleSize value, this will guarantee
// a final image with both dimensions larger than or equal to the
// requested height and width.
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
return inSampleSize;
}
Comments
Show a scaled image normally.
Decode and show a portion of bitmap using
BitmapRegionDecoder, when zoomed in.Use a disc Cache to store bitmaps.
Comments
Explore related questions
See similar questions with these tags.