diff --git a/src/org/andengine/opengl/texture/atlas/bitmap/source/AssetBitmapTextureAtlasSource.java b/src/org/andengine/opengl/texture/atlas/bitmap/source/AssetBitmapTextureAtlasSource.java index 9b8462aab..08830da51 100644 --- a/src/org/andengine/opengl/texture/atlas/bitmap/source/AssetBitmapTextureAtlasSource.java +++ b/src/org/andengine/opengl/texture/atlas/bitmap/source/AssetBitmapTextureAtlasSource.java @@ -13,7 +13,7 @@ import android.graphics.BitmapFactory; /** - * (c) 2010 Nicolas Gramlich + * (c) 2010 Nicolas Gramlich * (c) 2011 Zynga Inc. * * @author Nicolas Gramlich @@ -55,9 +55,35 @@ public static AssetBitmapTextureAtlasSource create(final AssetManager pAssetMana return new AssetBitmapTextureAtlasSource(pAssetManager, pAssetPath, pTextureX, pTextureY, decodeOptions.outWidth, decodeOptions.outHeight); } + + public static AssetBitmapTextureAtlasSource createSampled(final AssetManager pAssetManager, final String pAssetPath, final int pReqWidth, final int pReqHeight) { + final BitmapFactory.Options decodeOptions = new BitmapFactory.Options(); + decodeOptions.inJustDecodeBounds = true; + + InputStream in = null; + try { + in = pAssetManager.open(pAssetPath); + BitmapFactory.decodeStream(in, null, decodeOptions); + } catch (final IOException e) { + Debug.e("Failed loading Bitmap in AssetBitmapTextureAtlasSource. AssetPath: " + pAssetPath, e); + } finally { + StreamUtils.close(in); + } + + // Calculate inSampleSize + final int lInSampleSize = calculateInSampleSize(decodeOptions, pReqWidth, pReqHeight); + final int lTextureWidth = decodeOptions.outWidth / lInSampleSize; + final int lTextureHeight = decodeOptions.outHeight / lInSampleSize; + Debug.i("createSampled(pAssetManager, pAssetPath=" + pAssetPath + ", pReqWidth=" + pReqWidth + ", pReqHeight=" + pReqHeight + ") original image of " + decodeOptions.outWidth + "x" + decodeOptions.outHeight + " lInSampleSize=" + lInSampleSize + " -> resampled to size " + lTextureWidth + "x" + lTextureHeight); + return new AssetBitmapTextureAtlasSource(pAssetManager, pAssetPath, 0, 0, lTextureWidth, lTextureHeight, lInSampleSize); + } AssetBitmapTextureAtlasSource(final AssetManager pAssetManager, final String pAssetPath, final int pTextureX, final int pTextureY, final int pTextureWidth, final int pTextureHeight) { - super(pTextureX, pTextureY, pTextureWidth, pTextureHeight); + this(pAssetManager, pAssetPath, pTextureX, pTextureY, pTextureWidth, pTextureHeight, 1); + } + + AssetBitmapTextureAtlasSource(final AssetManager pAssetManager, final String pAssetPath, final int pTextureX, final int pTextureY, final int pTextureWidth, final int pTextureHeight, final int pSampleSize) { + super(pTextureX, pTextureY, pTextureWidth, pTextureHeight, pSampleSize); this.mAssetManager = pAssetManager; this.mAssetPath = pAssetPath; @@ -82,7 +108,9 @@ public Bitmap onLoadBitmap(final Config pBitmapConfig) { try { final BitmapFactory.Options decodeOptions = new BitmapFactory.Options(); decodeOptions.inPreferredConfig = pBitmapConfig; - + if (mSampleSize != 1) { + decodeOptions.inSampleSize = mSampleSize; + } in = this.mAssetManager.open(this.mAssetPath); return BitmapFactory.decodeStream(in, null, decodeOptions); } catch (final IOException e) { @@ -101,6 +129,27 @@ public String toString() { // =========================================================== // Methods // =========================================================== + + public static int calculateInSampleSize(final BitmapFactory.Options pOptions, final int pReqWidth, final int pReqHeight) { + // Raw height and width of image + final int lHeight = pOptions.outHeight; + final int lWidth = pOptions.outWidth; + int lInSampleSize = 1; + + if (lHeight > pReqHeight || lWidth > pReqWidth) { + + // Calculate ratios of height and width to requested height and width + final int lHeightRatio = Math.round((float) lHeight / (float) pReqHeight); + final int lWidthRatio = Math.round((float) lWidth / (float) pReqWidth); + + // Choose the smallest ratio as inSampleSize value, this will guarantee + // a final image with both dimensions larger than or equal to the + // requested height and width. + lInSampleSize = lHeightRatio < lWidthRatio ? lHeightRatio : lWidthRatio; + } + + return lInSampleSize; + } // =========================================================== // Inner and Anonymous Classes diff --git a/src/org/andengine/opengl/texture/atlas/source/BaseTextureAtlasSource.java b/src/org/andengine/opengl/texture/atlas/source/BaseTextureAtlasSource.java index 47968fc59..1e322837e 100644 --- a/src/org/andengine/opengl/texture/atlas/source/BaseTextureAtlasSource.java +++ b/src/org/andengine/opengl/texture/atlas/source/BaseTextureAtlasSource.java @@ -20,16 +20,22 @@ public abstract class BaseTextureAtlasSource implements ITextureAtlasSource { protected int mTextureY; protected int mTextureWidth; protected int mTextureHeight; + protected int mSampleSize; // =========================================================== // Constructors // =========================================================== - public BaseTextureAtlasSource(final int pTextureX, final int pTextureY, final int pTextureWidth, final int pTextureHeight) { + public BaseTextureAtlasSource(final int pTextureX, final int pTextureY, final int pTextureWidth, final int pTextureHeight, final int pSampleSize) { this.mTextureX = pTextureX; this.mTextureY = pTextureY; this.mTextureWidth = pTextureWidth; this.mTextureHeight = pTextureHeight; + this.mSampleSize = pSampleSize; + } + + public BaseTextureAtlasSource(final int pTextureX, final int pTextureY, final int pTextureWidth, final int pTextureHeight) { + this(pTextureX, pTextureY, pTextureWidth, pTextureHeight, 1); } // =========================================================== @@ -80,6 +86,11 @@ public void setTextureHeight(final int pTextureHeight) { // Methods for/from SuperClass/Interfaces // =========================================================== + @Override + public int getSampleSize() { + return mSampleSize; + } + @Override public String toString() { return this.getClass().getSimpleName() + "( " + this.getTextureWidth() + "x" + this.getTextureHeight() + " @ "+ this.mTextureX + "/" + this.mTextureY + " )"; diff --git a/src/org/andengine/opengl/texture/atlas/source/ITextureAtlasSource.java b/src/org/andengine/opengl/texture/atlas/source/ITextureAtlasSource.java index 8141f6f61..659b1110d 100644 --- a/src/org/andengine/opengl/texture/atlas/source/ITextureAtlasSource.java +++ b/src/org/andengine/opengl/texture/atlas/source/ITextureAtlasSource.java @@ -26,6 +26,8 @@ public interface ITextureAtlasSource { public int getTextureHeight(); public void setTextureWidth(final int pTextureWidth); public void setTextureHeight(final int pTextureHeight); + + public int getSampleSize(); public ITextureAtlasSource deepCopy(); } \ No newline at end of file diff --git a/src/org/andengine/opengl/texture/region/TextureRegionFactory.java b/src/org/andengine/opengl/texture/region/TextureRegionFactory.java index fd4d05097..636679a22 100644 --- a/src/org/andengine/opengl/texture/region/TextureRegionFactory.java +++ b/src/org/andengine/opengl/texture/region/TextureRegionFactory.java @@ -67,7 +67,7 @@ public static TextureRegion createFromSource(fin } public static TextureRegion createFromSource(final ITextureAtlas pTextureAtlas, final T pTextureAtlasSource, final int pTextureX, final int pTextureY, final boolean pRotated) { - final TextureRegion textureRegion = new TextureRegion(pTextureAtlas, pTextureX, pTextureY, pTextureAtlasSource.getTextureWidth(), pTextureAtlasSource.getTextureHeight(), pRotated); + final TextureRegion textureRegion = new TextureRegion(pTextureAtlas, pTextureX, pTextureY, pTextureAtlasSource.getTextureWidth(), pTextureAtlasSource.getTextureHeight(), pTextureAtlasSource.getSampleSize(), pRotated); pTextureAtlas.addTextureAtlasSource(pTextureAtlasSource, pTextureX, pTextureY); return textureRegion; }