1 package com.jme3.asset; 2 3 import android.graphics.Bitmap; 4 import android.graphics.BitmapFactory; 5 import android.graphics.Matrix; 6 import com.jme3.texture.Image; 7 import com.jme3.texture.Image.Format; 8 import java.io.IOException; 9 import java.io.InputStream; 10 11 /** 12 * <code>AndroidImageInfo</code> is set in a jME3 image via the {@link Image#setEfficientData(java.lang.Object)} 13 * method to retrieve a {@link Bitmap} when it is needed by the renderer. 14 * User code may extend <code>AndroidImageInfo</code> and provide their own implementation of the 15 * {@link AndroidImageInfo#loadBitmap()} method to acquire a bitmap by their own means. 16 * 17 * @author Kirill Vainer 18 */ 19 public class AndroidImageInfo { 20 21 protected AssetInfo assetInfo; 22 protected Bitmap bitmap; 23 protected Format format; 24 AndroidImageInfo(AssetInfo assetInfo)25 public AndroidImageInfo(AssetInfo assetInfo) { 26 this.assetInfo = assetInfo; 27 } 28 getBitmap()29 public Bitmap getBitmap(){ 30 if (bitmap == null || bitmap.isRecycled()){ 31 try { 32 loadBitmap(); 33 } catch (IOException ex) { 34 // If called first inside AssetManager, the error will propagate 35 // correctly. Assuming that if the first calls succeeds 36 // then subsequent calls will as well. 37 throw new AssetLoadException("Failed to load image " + assetInfo.getKey(), ex); 38 } 39 } 40 return bitmap; 41 } 42 43 44 getFormat()45 public Format getFormat(){ 46 return format; 47 } 48 49 /** 50 * Loads the bitmap directly from the asset info, possibly updating 51 * or creating the image object. 52 */ loadBitmap()53 protected void loadBitmap() throws IOException{ 54 InputStream in = null; 55 try { 56 in = assetInfo.openStream(); 57 bitmap = BitmapFactory.decodeStream(in); 58 if (bitmap == null) { 59 throw new IOException("Failed to load image: " + assetInfo.getKey().getName()); 60 } 61 } finally { 62 if (in != null) { 63 in.close(); 64 } 65 } 66 67 switch (bitmap.getConfig()) { 68 case ALPHA_8: 69 format = Image.Format.Alpha8; 70 break; 71 case ARGB_4444: 72 format = Image.Format.ARGB4444; 73 break; 74 case ARGB_8888: 75 format = Image.Format.RGBA8; 76 break; 77 case RGB_565: 78 format = Image.Format.RGB565; 79 break; 80 default: 81 // This should still work as long 82 // as renderer doesn't check format 83 // but just loads bitmap directly. 84 format = null; 85 } 86 87 TextureKey texKey = (TextureKey) assetInfo.getKey(); 88 if (texKey.isFlipY()) { 89 // Flip the image, then delete the old one. 90 Matrix flipMat = new Matrix(); 91 flipMat.preScale(1.0f, -1.0f); 92 Bitmap newBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), flipMat, false); 93 bitmap.recycle(); 94 bitmap = newBitmap; 95 96 if (bitmap == null) { 97 throw new IOException("Failed to flip image: " + texKey); 98 } 99 } 100 } 101 } 102