Loading texture in a more efficent way

Started by ginopeloso, August 02, 2015, 06:57:13 PM

Previous topic - Next topic

ginopeloso

I need to load a texture starting from a non-squared image. The final image must be squared (with both height and width power of 2), than I am forced to load the bitmap in memory, complete it with a useless part (in order to obtain a squared bitmap) and then create a texture with it. The whole process consumes too much memory (I have very big textures, 1024x1024, 2048x2048 or also 4096x4096). Is there a smarter way for creating textures?


        int maxTextureSize = calcMaxTextureSize(); // the max size in pixels that GLSurfaceView can render on this device (tipically 2048, or 4096 for newer devices, however a power of 2)

        // do not load bitmap, just decode its bounds
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        options.inSampleSize = 1;
        BitmapFactory.decodeFile(filepath, options);

        int width = options.outWidth;
        int height = options.outHeight;

        // scale down the image if it is bigger than the maxTextureSize
        while (width / (float) options.inSampleSize > maxTextureSize || height / (float) options.inSampleSize > maxTextureSize) {
            options.inSampleSize *= 2; // inSampleSize must be a power of 2 (1, 2, 4, 8, etc... that's why this line)
        }

        // now load the bitmap
        options.inJustDecodeBounds = false;

        Bitmap bitmap = BitmapFactory.decodeFile(filepath, options); // decode the real bitmap, ONE
        int dim = Math.max(bitmap.getWidth(), bitmap.getHeight());

        // now put it in a squared bitmap (it will be used as a texture, then it must be square (dim x dim))
        Bitmap textureBitmap = Bitmap.createBitmap(dim, dim, Bitmap.Config.RGB_565); // TWO bitmaps
        Canvas canvas = new Canvas(textureBitmap);
        canvas.drawBitmap(bitmap, 0, 0, null);
        bitmap.recycle();

        // The texture must be a power-of-2 bitmap, then resize it... THREE bitmaps
        Bitmap scaledTexture = Bitmap.createScaledBitmap(textureBitmap, maxTextureSize, maxTextureSize, false);
        textureBitmap.recycle();

        Texture texture = new Texture(scaledTexture, false);
        TextureManager.getInstance().addTexture(textureName, texture); // ANOTHER bitmap in memory
        scaledTexture.recycle();


As you can see there are too many passes, and too many bitmaps allocated in memory before I can have the final texture:
1. Decode the original bitmap, not the whole one but the maximum size supported by the device
2. Put it on a square (with a useless part)
3. Resize it, in order to have a power-of-2 texture
4. Create a Texture object with that bitmap

EgonOlsen

Can't you simply process them instead of doing this at runtime? If not, maybe doing all the operations in your own code on an int-array might help...but I'm not sure if it really would. Another option is to use NPOTTexture instead, but that has other drawbacks like no mip-mapping support.