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
// ===========================================================
}
}