es.eucm.ead.engine.android.AndroidImageUtils.java Source code

Java tutorial

Introduction

Here is the source code for es.eucm.ead.engine.android.AndroidImageUtils.java

Source

/**
 * eAdventure is a research project of the
 *    e-UCM research group.
 *
 *    Copyright 2005-2014 e-UCM research group.
 *
 *    You can access a list of all the contributors to eAdventure at:
 *          http://e-adventure.e-ucm.es/contributors
 *
 *    e-UCM is a research group of the Department of Software Engineering
 *          and Artificial Intelligence at the Complutense University of Madrid
 *          (School of Computer Science).
 *
 *          CL Profesor Jose Garcia Santesmases 9,
 *          28040 Madrid (Madrid), Spain.
 *
 *          For more info please visit:  <http://e-adventure.e-ucm.es> or
 *          <http://www.e-ucm.es>
 *
 * ****************************************************************************
 *
 *  This file is part of eAdventure
 *
 *      eAdventure is free software: you can redistribute it and/or modify
 *      it under the terms of the GNU Lesser General Public License as published by
 *      the Free Software Foundation, either version 3 of the License, or
 *      (at your option) any later version.
 *
 *      eAdventure is distributed in the hope that it will be useful,
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *      GNU Lesser General Public License for more details.
 *
 *      You should have received a copy of the GNU Lesser General Public License
 *      along with eAdventure.  If not, see <http://www.gnu.org/licenses/>.
 */
package es.eucm.ead.engine.android;

import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.BufferUtils;
import com.badlogic.gdx.utils.GdxRuntimeException;
import com.badlogic.gdx.utils.StreamUtils;
import es.eucm.ead.engine.assets.GameAssets.ImageUtils;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.IntBuffer;

public class AndroidImageUtils implements ImageUtils {

    private static final String TAG = "ImageUtils";

    private int maxSize = -1;

    public AndroidImageUtils() {
        // We do this to make sure it is called in a opengl thread
        maxSize();
    }

    @Override
    public boolean imageSize(FileHandle fileHandle, Vector2 size) {
        BitmapFactory.Options options = new Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(fileHandle.read(), null, options);
        size.set(options.outWidth, options.outHeight);
        return true;
    }

    private int maxSize() {
        if (maxSize == -1) {
            IntBuffer intBuffer = BufferUtils.newIntBuffer(16);
            Gdx.gl.glGetIntegerv(GL20.GL_MAX_TEXTURE_SIZE, intBuffer);
            maxSize = Math.min(intBuffer.get(0), Math.max(Gdx.graphics.getHeight(), Gdx.graphics.getWidth()));
        }
        return maxSize;
    }

    @Override
    public boolean validSize(Vector2 size) {
        return size.x < maxSize() && size.y < maxSize();
    }

    @Override
    public float scale(FileHandle src, FileHandle target) {
        return decodeFile(src, maxSize(), maxSize(), target);
    }

    /**
     * Decodes an image and scales it to reduce memory consumption if its width
     * or height is higher than the provided {@code targetWidth} or
     * {@code targetHeight} respectively. The scaling is done without loading
     * the image into video memory. Also, the scaling keeps the aspect ratio of
     * the source {@code file}.
     * 
     * @param file
     *            the source file to be decoded and possibly scaled.
     * @param targetWidth
     *            the maximum width of the resulting scaled file.
     * @param targetHeight
     *            the maximum height of the resulting scaled file.
     * @param result
     *            the destination of the scaled image. If null the source file
     *            will be overridden. If no scaling is needed the source
     *            {@code file} is copied to {@code result}.
     * @return true if the scaling has been successful, false otherwise.
     */
    public float decodeFile(FileHandle file, int targetWidth, int targetHeight, FileHandle result) {
        if (result == null) {
            result = file;
        }
        InputStream decodedFis = null;
        InputStream scaledFis = null;
        OutputStream savedFos = null;
        Bitmap tempBmap = null;
        try {

            // Decode image size
            BitmapFactory.Options bmOptions = new BitmapFactory.Options();
            bmOptions.inJustDecodeBounds = true;
            decodedFis = file.read();
            BitmapFactory.decodeStream(decodedFis, null, bmOptions);

            // Find the correct scale value.
            // It should be the power of 2.
            int scale = 1;
            int tmpWidth = bmOptions.outWidth;
            int tmpHeight = bmOptions.outHeight;
            while (tmpWidth > targetWidth || tmpHeight > targetHeight) {
                tmpWidth = (int) (tmpWidth * .5f);
                tmpHeight = (int) (tmpHeight * .5f);
                scale *= 2;
            }

            if (scale != 1) {
                // Decode with inSampleSize
                bmOptions.inJustDecodeBounds = false;
                bmOptions.inSampleSize = scale;
                scaledFis = file.read();
                tempBmap = BitmapFactory.decodeStream(scaledFis, null, bmOptions);

                savedFos = result.write(false);
                String extension = result.extension();
                tempBmap.compress((extension.equalsIgnoreCase("jpg") || extension.equalsIgnoreCase("jpeg"))
                        ? CompressFormat.JPEG
                        : CompressFormat.PNG, 90, savedFos);
                savedFos.flush();
                Gdx.app.log(TAG, "Scaling image, scalingFactor:  " + scale);
            } else if (file != result) {
                file.copyTo(result);
            }
            Gdx.app.log(TAG, "New image saved! " + file.path());
            return scale;
        } catch (FileNotFoundException fnfex) {
            Gdx.app.error(TAG, "File not found! ", fnfex);
        } catch (IOException ioex) {
            Gdx.app.error(TAG, "I/O error! ", ioex);
        } catch (GdxRuntimeException grex) {
            Gdx.app.error(TAG, "The file handle represents a directory, " + "doesn't exist, or could not be read! ",
                    grex);
        } finally {
            if (tempBmap != null) {
                tempBmap.recycle();
            }
            StreamUtils.closeQuietly(decodedFis);
            StreamUtils.closeQuietly(scaledFis);
            StreamUtils.closeQuietly(savedFos);
        }
        return -1;
    }
}