Android createBitmap(...) 带有 RGB_565 选项而不是 ARGB_8888

问题描述 投票:0回答:0

我正在尝试提高绘制位图的速度。我读到我可以尝试使用 RGB_565 选项而不是 ARGB_8888 当涉及到

createBitmap(...)
最后一个参数时。我还在自定义 SurfaceView 类的构造函数中设置了
getHolder().setFormat(PixelFormat.RGB_565)

问题是,当我在所有这些地方设置这个 RGB_565 时,位图没有绘制,我得到空白屏幕,但是当设置了 ARGB_8888 时,我的位图正确显示但速度很慢。根据带有 RGB_565(空屏幕)的 TinyDancer 库,我得到 60FPS,而使用 ARGB_8888 我只得到 20FPS,所以我想尽可能地改进它。

编辑

这是我的代码。

GameMainSurface.java

public class GameMainSurface extends GameSurface implements SurfaceHolder.Callback {

(...)

    public GameMainSurface(Context context) {
        super(context);
        this.context = context;
        getHolder().setFormat(PixelFormat.RGB_565);
        getHolder().addCallback(this);
        setWillNotDraw(false);
    }

    public GameMainSurface(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        getHolder().setFormat(PixelFormat.RGB_565);
        getHolder().addCallback(this);
        setWillNotDraw(false);
    }

    public GameMainSurface(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        this.context = context;
        getHolder().setFormat(PixelFormat.RGB_565);
        getHolder().addCallback(this);
        setWillNotDraw(false);
    }

    @Override
    public void draw(Canvas canvas) {
        super.draw(canvas);

        Loader.drawTmxMaps(canvas, getContext());

        invalidate();
    }

@Override
public void surfaceCreated(SurfaceHolder holder) {
    this.holder = holder;
    (...)
    initMaps();
}

protected void initMaps() {
    TileMapData tileMainMapData = TmxLoader.readTMX("map_main4.tmx", context);
    TmxLoader.createBitmaps(tileMainMapData, 0, 4, this);
 } 
}

Loader.java

public class Loader {

private static final String TAG = TmxLoader.class.getSimpleName();

private static final Map<Integer, Bitmap[]> framesMap = new HashMap<>();
private static final Map<Integer, Canvas[]> canvasesMap = new HashMap<>();
private static final Map<Integer, Long> animsDuration = new HashMap<>();
private static final List<Runnable> runnables = new ArrayList<>();
private static final Handler handler = new Handler();

private static boolean isIterStarted = false;

(...)

public static TileMapData readTMX(String filename, Context c) {
    TileMapData tileMapData = null;

    // Initialize SAX
    try {

        SAXParserFactory spf = SAXParserFactory.newInstance();
        SAXParser parser = spf.newSAXParser();
        XMLReader reader = parser.getXMLReader();

        // Create an instance of the TMX XML handler
        // that will create a TileMapData object
        TmxHandler handler = new TmxHandler();

        reader.setContentHandler(handler);

        AssetManager assetManager = c.getAssets();

        reader.parse((new InputSource(assetManager.open(filename))));

        // Extract the created object
        tileMapData = handler.getData();


    } catch (ParserConfigurationException pce) {
        Log.e(TAG, "SAX XML parse error", pce);
    } catch (SAXException se) {
        Log.e(TAG, "SAX XML error", se);
    } catch (IOException ioe) {
        Log.e(TAG, "SAX XML parse io error", ioe);
    }

    return tileMapData;
}

public static void createBitmaps(TileMapData t, int startLayer, int endLayer, GameSurface gameSurface) {

    try {
        AssetManager assetManager = gameSurface.getContext().getAssets();

        Bitmap[] tilesets = new Bitmap[t.tilesets.size()];

        for (int i = 0; i < tilesets.length; i++) {
            tilesets[i] = BitmapFactory.decodeStream(assetManager.open(t.tilesets.get(i).ImageFilename));
        }

        long currentGID;
        Long localGID;
        Integer currentTileSetIndex;
        Rect source = new Rect(0, 0, 0, 0);
        Rect dest = new Rect(0, 0, 0, 0);

        boolean isAfterInit = false;
        List<Integer> animFrames = new ArrayList<>();

        for (int i = startLayer; i < endLayer; i++) {
            // endlessblow_main4.tmx = 12
            for (int j = 0; j < t.layers.get(i).height; j++) {
                // endlessblow_main4.tmx = 8
                for (int k = 0; k < t.layers.get(i).width; k++) {

                    currentGID = t.getGIDAt(k, j, i);
                    localGID = t.getLocalID(currentGID);
                    currentTileSetIndex = t.getTileSetIndex(currentGID);



                    if (!isAfterInit) {
                        animFrames = Stream.of(t.tilesets.get(currentTileSetIndex).tileAnimations).map(tileAnimation -> tileAnimation.getTileFrames().size()).collect(Collectors.toList());
                        for (int l = 0; l < t.tilesets.get(currentTileSetIndex).tileAnimations.size(); l++) {
                            for (int m = 0; m < t.tilesets.get(currentTileSetIndex).tileAnimations.get(l).getTileFrames().size(); m++) {
                                animsDuration.put(l, t.tilesets.get(currentTileSetIndex).tileAnimations.get(l).getTileFrames().get(m).getDuration());
                            }
                        }
                        init(animFrames, t);
                        isAfterInit = true;
                    }

                    if (localGID != null) {
                        if (i == startLayer) {
                            source.top = (((localGID).intValue()) / ((t.tilesets.get(currentTileSetIndex).imageWidth) / t.tilewidth)) * t.tileheight;
                            source.left = (((localGID).intValue()) % ((t.tilesets.get(currentTileSetIndex).imageWidth) / t.tilewidth)) * t.tilewidth;
                            source.bottom = source.top + t.tileheight;
                            source.right = source.left + t.tilewidth;

                            dest.top = j * t.tileheight;
                            dest.left = k * t.tilewidth;
                            dest.bottom = dest.top + t.tileheight;
                            dest.right = dest.left + t.tilewidth;

                            for (Canvas canvas : canvasesMap.get(0)) {
                                canvas.drawBitmap(tilesets[currentTileSetIndex], source, dest, null);
                            }
                        } else {
                            for (int l = 0; l < t.tilesets.get(currentTileSetIndex).tileAnimations.size(); l++) {

                                if (localGID == t.tilesets.get(currentTileSetIndex).tileAnimations.get(l).getLocalGID()) {
                                    for (int frame = 0; frame < t.tilesets.get(currentTileSetIndex).tileAnimations.get(l).getTileFrames().size(); frame++) {

                                        source.top = (int) ((t.tilesets.get(currentTileSetIndex).tileAnimations.get(l).getTileFrames().get(frame).getTileId() / ((t.tilesets.get(currentTileSetIndex).imageWidth) / t.tilewidth)) * t.tileheight);
                                        source.left = (int) ((t.tilesets.get(currentTileSetIndex).tileAnimations.get(l).getTileFrames().get(frame).getTileId() % ((t.tilesets.get(currentTileSetIndex).imageWidth) / t.tilewidth)) * t.tilewidth);
                                        source.bottom = source.top + t.tileheight;
                                        source.right = source.left + t.tilewidth;

                                        dest.top = j * t.tileheight;
                                        dest.left = k * t.tilewidth;
                                        dest.bottom = dest.top + t.tileheight;
                                        dest.right = dest.left + t.tilewidth;

                                        canvasesMap.get(l)[frame].drawBitmap(tilesets[currentTileSetIndex], source, dest, null);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        for (int i = 0; i < framesMap.size(); i++) {
            for (int j = 0; j < animFrames.get(i); j++) {
                framesMap.get(i)[j] = Bitmap.createScaledBitmap(framesMap.get(i)[j], gameSurface.getCellWidth() * t.width, gameSurface.getCellHeight() * t.height, false);
            }
        }
    } catch (IOException e) {
        Log.e(TAG, e.getMessage());
    }
}


private static void init(List<Integer> animFrames, TileMapData t) {
    for (int i = 0; i < animFrames.size(); i++) {
        runnables.add(new FrameDurationRunnable(animFrames.get(i), animsDuration.get(i)));
        framesMap.put(i, new Bitmap[animFrames.get(i)]);
        canvasesMap.put(i, new Canvas[animFrames.get(i)]);
        for (int j = 0; j < animFrames.get(i); j++) {
            framesMap.get(i)[j] = Bitmap.createBitmap(t.width * t.tilewidth, t.height * t.tileheight, Bitmap.Config.RGB_565);
            canvasesMap.get(i)[j] = new Canvas(framesMap.get(i)[j]);
        }
    }
}


public static void drawTmxMaps(Canvas canvas, Context context) {
    for (int i = 0; i < framesMap.size(); i++) {
        canvas.drawBitmap(framesMap.get(i)[((FrameDurationRunnable) runnables.get(i)).iter], 0, 0, null);
    }

    if (!isIterStarted) {
        iterTmxFrames();
        isIterStarted = true;
    }
}


private static void iterTmxFrames() {
    for (int i = 0; i < runnables.size(); i++) {
        handler.postDelayed(runnables.get(i), animsDuration.get(i));
    }
}

private static class FrameDurationRunnable implements Runnable {
    private final int animMaxIter;
    private final long frameDuration;

    private int iter;

    FrameDurationRunnable(final int animMaxIter, final long frameDuration) {
        this.animMaxIter = animMaxIter;
        this.frameDuration = frameDuration;
    }

    public void run() {
        iter++;
        if (iter == animMaxIter) iter = 0;
        handler.postDelayed(this, frameDuration);
    }
}
}

你能看到什么解决方案?

java android kotlin surfaceview
© www.soinside.com 2019 - 2024. All rights reserved.