public abstract class

BitmapTexture

extends Texture
package org.anddev.andengine.opengl.texture.bitmap;

import java.io.IOException;
import java.io.InputStream;

import javax.microedition.khronos.opengles.GL10;

import org.anddev.andengine.opengl.texture.Texture;
import org.anddev.andengine.opengl.texture.TextureOptions;
import org.anddev.andengine.opengl.util.GLHelper;
import org.anddev.andengine.util.MathUtils;
import org.anddev.andengine.util.StreamUtils;

import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.opengl.GLUtils;

/**
 * (c) Zynga 2011
 *
 * @author Nicolas Gramlich <ngramlich@zynga.com>
 * @since 16:16:25 - 30.07.2011
 */
public abstract class BitmapTexture extends Texture {
	// ===========================================================
	// Constants
	// ===========================================================

	// ===========================================================
	// Fields
	// ===========================================================

	private final int mWidth;
	private final int mHeight;
	private final BitmapTextureFormat mBitmapTextureFormat;

	// ===========================================================
	// Constructors
	// ===========================================================

	public BitmapTexture() throws IOException {
		this(BitmapTextureFormat.RGBA_8888, TextureOptions.DEFAULT, null);
	}

	public BitmapTexture(final BitmapTextureFormat pBitmapTextureFormat) throws IOException {
		this(pBitmapTextureFormat, TextureOptions.DEFAULT, null);
	}

	public BitmapTexture(final TextureOptions pTextureOptions) throws IOException {
		this(BitmapTextureFormat.RGBA_8888, pTextureOptions, null);
	}

	public BitmapTexture(final BitmapTextureFormat pBitmapTextureFormat, final TextureOptions pTextureOptions) throws IOException {
		this(pBitmapTextureFormat, pTextureOptions, null);
	}

	public BitmapTexture(final BitmapTextureFormat pBitmapTextureFormat, final TextureOptions pTextureOptions, final ITextureStateListener pTextureStateListener) throws IOException {
		super(pBitmapTextureFormat.getPixelFormat(), pTextureOptions, pTextureStateListener);
		this.mBitmapTextureFormat = pBitmapTextureFormat;

		final BitmapFactory.Options decodeOptions = new BitmapFactory.Options();
		decodeOptions.inJustDecodeBounds = true;

		final InputStream in = null;
		try {
			BitmapFactory.decodeStream(this.onGetInputStream(), null, decodeOptions);
		} finally {
			StreamUtils.close(in);
		}

		this.mWidth = decodeOptions.outWidth;
		this.mHeight = decodeOptions.outHeight;
		
		if(!MathUtils.isPowerOfTwo(this.mWidth) || !MathUtils.isPowerOfTwo(this.mHeight)) { // TODO GLHelper.EXTENSIONS_NON_POWER_OF_TWO
			throw new IllegalArgumentException("pWidth and pHeight must be a power of 2!");
		}
	}

	// ===========================================================
	// Getter & Setter
	// ===========================================================

	@Override
	public int getWidth() {
		return this.mWidth;
	}

	@Override
	public int getHeight() {
		return this.mHeight;
	}

	// ===========================================================
	// Methods for/from SuperClass/Interfaces
	// ===========================================================

	protected abstract InputStream onGetInputStream() throws IOException;

	@Override
	protected void writeTextureToHardware(final GL10 pGL) throws IOException {
		final Config bitmapConfig = this.mBitmapTextureFormat.getBitmapConfig();
		final boolean preMultipyAlpha = this.mTextureOptions.mPreMultipyAlpha;

		final BitmapFactory.Options decodeOptions = new BitmapFactory.Options();
		decodeOptions.inPreferredConfig = bitmapConfig;

		final Bitmap bitmap = BitmapFactory.decodeStream(this.onGetInputStream(), null, decodeOptions);

		if(preMultipyAlpha) {
			GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
		} else {
			GLHelper.glTexImage2D(pGL, GL10.GL_TEXTURE_2D, 0, bitmap, 0, this.mPixelFormat);
		}

		bitmap.recycle();
	}

	// ===========================================================
	// Methods
	// ===========================================================

	// ===========================================================
	// Inner and Anonymous Classes
	// ===========================================================

	public static enum BitmapTextureFormat {
		// ===========================================================
		// Elements
		// ===========================================================

		RGBA_8888(Config.ARGB_8888, PixelFormat.RGBA_8888),
		RGB_565(Config.RGB_565, PixelFormat.RGB_565),
		RGBA_4444(Config.ARGB_4444, PixelFormat.RGBA_4444), // TODO
		A_8(Config.ALPHA_8, PixelFormat.A_8); // TODO

		// ===========================================================
		// Constants
		// ===========================================================

		// ===========================================================
		// Fields
		// ===========================================================

		private final Config mBitmapConfig;
		private final PixelFormat mPixelFormat;

		// ===========================================================
		// Constructors
		// ===========================================================

		private BitmapTextureFormat(final Config pBitmapConfig, final PixelFormat pPixelFormat) {
			this.mBitmapConfig = pBitmapConfig;
			this.mPixelFormat = pPixelFormat;
		}

		public static BitmapTextureFormat fromPixelFormat(final PixelFormat pPixelFormat) {
			switch(pPixelFormat) {
				case RGBA_8888:
					return RGBA_8888;
				case RGBA_4444:
					return RGBA_4444;
				case RGB_565:
					return RGB_565;
				case A_8:
					return A_8;
				default:
					throw new IllegalArgumentException("Unsupported " + PixelFormat.class.getName() + ": '" + pPixelFormat + "'.");
			}
		}

		// ===========================================================
		// Getter & Setter
		// ===========================================================

		public Config getBitmapConfig() {
			return this.mBitmapConfig;
		}

		public PixelFormat getPixelFormat() {
			return this.mPixelFormat;
		}

		// ===========================================================
		// Methods from SuperClass/Interfaces
		// ===========================================================

		// ===========================================================
		// Methods
		// ===========================================================

		// ===========================================================
		// Inner and Anonymous Classes
		// ===========================================================
	}
}