Самый эффективный способ показать анимацию по кадру за кадром

Я пытаюсь показать покадровую анимацию, изменяя изображения в изображении. Я попробовал анимацию в xml, а также изменил растровое изображение изображения внутри обработчика. Я также пытался хранить только три растровых изображения внутри arraylist (чтобы избежать нехватки памяти) в качестве механизма кэширования, но на самом деле малое улучшение. Мне нужно повторить 36 изображений для полной анимации. Проблема, с которой я сталкиваюсь, заключается в том, что во всех методах, которые я использовал, я не могу завершить анимацию в заданный промежуток времени 50 мс. Изображения варьируются от 250 кбайт до 540 кб. Fps анимации действительно низкий. Когда версия приложения ios готова, я вынужден показать анимацию, совместимую с версией ios. Я noob в renderscript и opengl. Есть ли способ показать гладкую анимацию для больших изображений в 50-60 мс. Любые намеки или предложения заслуживают высокой оценки. Heres моментальный снимок анимации: Вот ссылка на мои изображения для любой заинтересованной. Введите описание изображения здесь

Я написал простую деятельность, которая делает самую основную вещь:

Загружает все растровые изображения в потоке, затем отправляет изменения в ImageView каждые 40 мс.

package mk.testanimation; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Bundle; import android.os.Handler; import android.util.Log; import android.widget.ImageView; import java.util.ArrayList; public class MainActivity extends Activity { ImageView mImageView; private int mImageRes[] = new int[]{ R.drawable.s0, R.drawable.s1, R.drawable.s2, R.drawable.s3, R.drawable.s4, R.drawable.s5, R.drawable.s6, R.drawable.s7, R.drawable.s8, R.drawable.s9, R.drawable.s10, R.drawable.s11, R.drawable.s12, R.drawable.s13, R.drawable.s14, R.drawable.s15, R.drawable.s16, R.drawable.s17, R.drawable.s18, R.drawable.s19, R.drawable.s20, R.drawable.s21, R.drawable.s22, R.drawable.s23, R.drawable.s24, R.drawable.s25, R.drawable.s26, R.drawable.s27, R.drawable.s28, R.drawable.s29, R.drawable.s30, R.drawable.s31, R.drawable.s32, R.drawable.s33, R.drawable.s34, R.drawable.s35, }; private ArrayList<Bitmap> mBitmaps = new ArrayList<Bitmap>(mImageRes.length); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); final Handler handler = new Handler(); mImageView = new ImageView(this); setContentView(mImageView); Thread important = new Thread() { @Override public void run() { long timestamp = System.currentTimeMillis(); for (int i = 0; i < mImageRes.length; i++) { mBitmaps.add(BitmapFactory.decodeResource(getResources(), mImageRes[i])); } Log.d("ANIM-TAG", "Loading all bitmaps took " + (System.currentTimeMillis() - timestamp) + "ms"); for (int i = 0; i < mBitmaps.size(); i++) { final int idx = i; handler.postDelayed(new Runnable() { @Override public void run() { mImageView.setImageBitmap(mBitmaps.get(idx)); } }, i * 40); } } }; important.setPriority(Thread.MAX_PRIORITY); important.start(); } } 

Это выглядело довольно прилично на моем Nexus 7, но для загрузки всех растровых изображений потребовалось немного больше 4 секунд.

Можете ли вы загружать растровые изображения заранее?

Кроме того, он не будет экономить тонну, но ваши pngs имеют кучу дополнений вокруг прозрачного пространства. Вы можете обрезать их и немного уменьшить память. В противном случае сжатие изображений также поможет (например, ограничение количества используемых цветов).

В идеале, в вышеупомянутом решении, вы должны переработать растровые изображения сразу же после того, как они больше не будут использоваться.

Кроме того, если это слишком тяжело для памяти, вы можете сделать то, что вы упомянули, и иметь бит-бит, но я уверен, что это должно быть больше трех изображений.

Удачи.

EDIT: попытка 2. Сначала я обрезал все изображения до 590×590. Это бритая около 1 мб изображений. Затем я создал новый класс, который немного «занят» и не имеет фиксированной частоты кадров, но отображает изображения, как только они будут готовы:

 package mk.testanimation; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Bundle; import android.os.Handler; import android.util.Log; import android.widget.ImageView; import java.util.ArrayList; public class MainActivity extends Activity { ImageView mImageView; private int mImageRes[] = new int[]{R.drawable.s0, R.drawable.s1, R.drawable.s2, R.drawable.s3, R.drawable.s4, R.drawable.s5, R.drawable.s6, R.drawable.s7, R.drawable.s8, R.drawable.s9, R.drawable.s10, R.drawable.s11, R.drawable.s12, R.drawable.s13, R.drawable.s14, R.drawable.s15, R.drawable.s16, R.drawable.s17, R.drawable.s18, R.drawable.s19, R.drawable.s20, R.drawable.s21, R.drawable.s22, R.drawable.s23, R.drawable.s24, R.drawable.s25, R.drawable.s26, R.drawable.s27, R.drawable.s28, R.drawable.s29, R.drawable.s30, R.drawable.s31, R.drawable.s32, R.drawable.s33, R.drawable.s34, R.drawable.s35}; private ArrayList<Bitmap> mBitmaps = new ArrayList<Bitmap>(mImageRes.length); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); final long timestamp = System.currentTimeMillis(); final Handler handler = new Handler(); mImageView = new ImageView(this); setContentView(mImageView); Thread important = new Thread() { @Override public void run() { for (int i = 0; i < mImageRes.length; i++) { mBitmaps.add(BitmapFactory.decodeResource(getResources(), mImageRes[i])); } } }; important.setPriority(Thread.MAX_PRIORITY); important.start(); Thread drawing = new Thread() { @Override public void run() { int i = 0; while (i < mImageRes.length) { if (i >= mBitmaps.size()) { Thread.yield(); } else { final Bitmap bitmap = mBitmaps.get(i); handler.post(new Runnable() { @Override public void run() { mImageView.setImageBitmap(bitmap); } }); i++; } } Log.d("ANIM-TAG", "Time to render all frames:" + (System.currentTimeMillis() - timestamp) + "ms"); } }; drawing.setPriority(Thread.MAX_PRIORITY); drawing.start(); } } 

Вышеуказанное начало рендеринга почти сразу, и на моем 2012 Nexus 7 это заняло менее 4 с.

В качестве последнего усилия я преобразовал все изображения в 8-битные PNG вместо 32-разрядных. Это привело к рендерингу менее 2 секунд!

Я готов поспорить, что любое решение, в результате которого вы закончите, поможет сделать изображения как можно меньше.

Опять же – удача!

Я сталкиваюсь с той же проблемой, и я решил ее, переопределив AnimationDrawable. Итак, если проблема заключается в том, что вы не можете загружать все изображения в массив, потому что она слишком велика для хранения памяти, а затем загружает изображение, когда вам это нужно. My AnimationDrawable:

 public abstract class MyAnimationDrawable extends AnimationDrawable { private Context context; private int current; private int reqWidth; private int reqHeight; private int totalTime; public MyAnimationDrawable(Context context, int reqWidth, int reqHeight) { this.context = context; this.current = 0; //In my case size of screen to scale Drawable this.reqWidth = reqWidth; this.reqHeight = reqHeight; this.totalTime = 0; } @Override public void addFrame(Drawable frame, int duration) { super.addFrame(frame, duration); totalTime += duration; } @Override public void start() { super.start(); new Handler().postDelayed(new Runnable() { public void run() { onAnimationFinish(); } }, totalTime); } public int getTotalTime() { return totalTime; } @Override public void draw(Canvas canvas) { try { //Loading image from assets, you could make it from resources Bitmap bmp = BitmapFactory.decodeStream(context.getAssets().open("presentation/intro_000"+(current < 10 ? "0"+current : current)+".jpg")); //Scaling image to fitCenter Matrix m = new Matrix(); m.setRectToRect(new RectF(0, 0, bmp.getWidth(), bmp.getHeight()), new RectF(0, 0, reqWidth, reqHeight), Matrix.ScaleToFit.CENTER); bmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), m, true); //Calculating the start 'x' and 'y' to paint the Bitmap int x = (reqWidth - bmp.getWidth()) / 2; int y = (reqHeight - bmp.getHeight()) / 2; //Painting Bitmap in canvas canvas.drawBitmap(bmp, x, y, null); //Jump to next item current++; } catch (IOException e) { e.printStackTrace(); } } abstract void onAnimationFinish(); } 

Теперь, чтобы воспроизвести анимацию, вам нужно сделать следующее:

  //Get your ImageView View image = MainActivity.this.findViewById(R.id.presentation); //Create AnimationDrawable final AnimationDrawable animation = new MyAnimationDrawable(this, displayMetrics.widthPixels, displayMetrics.heightPixels) { @Override void onAnimationFinish() { //Do something when finish animation } }; animation.setOneShot(true); //dont repeat animation //This is just to say that my AnimationDrawable has 72 frames with 50 milliseconds interval try { //Always load same bitmap, anyway you load the right one in draw() method in MyAnimationDrawable Bitmap bmp = BitmapFactory.decodeStream(MainActivity.this.getAssets().open("presentation/intro_00000.jpg")); for (int i = 0; i < 72; i++) { animation.addFrame(new BitmapDrawable(getResources(), bmp), 50); } } catch (IOException e) { e.printStackTrace(); } //Set AnimationDrawable to ImageView if (Build.VERSION.SDK_INT < 16) { image.setBackgroundDrawable(animation); } else { image.setBackground(animation); } //Start animation image.post(new Runnable() { @Override public void run() { animation.start(); } }); 

Вот и все, и работает ОК, форма меня !!!

Попробуйте использовать AnimationDrawable для вашего ImageView . См. Мой ответ здесь, например.

Самый эффективный способ показать фрейм-анимацию в андроиде – использовать OpenGL с NDK .

Создайте imageView с помощью программирования, а затем поверните его под углом, а затем создайте еще один, а затем поверните его .. сделайте это для количества изображений, которое вы хотите показать. Вам нужно добавить только одно изображение. Вы можете повернуть изображение следующим образом.

 Matrix matrix=new Matrix(); imageView.setScaleType(ScaleType.MATRIX); //required matrix.postRotate((float) angle, pivX, pivY); imageView.setImageMatrix(matrix); 

Может быть, глупый ответ, но это может вам помочь. Сделайте анимацию с помощью другого инструмента и сохраните ее как высококачественное видео, а затем просто воспроизведите видео.

Попробуйте экспортировать свои изображения в GIF? Android поддерживает декодирование GIF-файлов.

Посмотрите: Поддерживаемые форматы носителей.

Загрузка битмапов из активов вместо ресурсов, которые были сохранены на 40% для меня. Вы можете попробовать это.

Так что это продолжалось от 5 секунд с ресурсами до 3 секунд на ваших фотографиях на моем Nexus 7:

 long time = System.currentTimeMillis(); try { for (int i = 0; i < 35; i++) { InputStream assetStream = getAssets().open( "_step" + (i + 1) + ".png"); try { Bitmap bitmap = BitmapFactory.decodeStream(assetStream); if (bitmap == null) { throw new RuntimeException("Could not load bitmap"); } mBitmaps.add(bitmap); } finally { assetStream.close(); } } } catch (Exception e) { throw new RuntimeException(e); } Log.d("ANIM", "Loading bitmaps elapsed "+(System.currentTimeMillis() - time)+"ms"); 
Intereting Posts