package at.favre.lib.dali.builder; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Point; import android.view.View; import java.io.File; import java.io.IOException; import java.io.InputStream; import at.favre.lib.dali.util.BuilderUtil; import at.favre.lib.dali.util.LegacySDKUtil; /** * This is a wrapper for the different * options one can specify a reference of * an image. This will only load (if necessary) * the image ondemand. */ public class ImageReference { private static final String CACHE_KEY_PREFIX = "cachekey_"; public enum SourceType {RES_ID,INPUT_STREAM,BITMAP, FILE, VIEW, UNKNOWN} private Integer resId; private InputStream inputStream; private Bitmap bitmap; private File fileToBitmap; private View view; private String contentId; private SourceType type = SourceType.UNKNOWN; private BitmapFactory.Options decoderOptions; public ImageReference(int resId) { this.resId = resId; this.contentId = "resid_"+resId; this.type=SourceType.RES_ID; } public ImageReference(InputStream inputStream) { this(inputStream, String.valueOf(inputStream.hashCode())); } public ImageReference(InputStream inputStream, String cacheKey) { this.inputStream = inputStream; this.contentId = CACHE_KEY_PREFIX+cacheKey; this.type=SourceType.INPUT_STREAM; } public ImageReference(Bitmap bitmap) { this(bitmap,LegacySDKUtil.getBitmapId(bitmap)); } public ImageReference(Bitmap bitmap, String cacheKey) { this.bitmap = bitmap; this.contentId = CACHE_KEY_PREFIX+cacheKey; this.type=SourceType.BITMAP; } public ImageReference(File fileToBitmap) { this(fileToBitmap,"file_"+fileToBitmap.getAbsolutePath()); } public ImageReference(File fileToBitmap, String cacheKey) { this.fileToBitmap = fileToBitmap; this.contentId = cacheKey; this.type=SourceType.FILE; } public ImageReference(View view) { this.view = view; this.contentId = "view_"+view.hashCode(); this.type=SourceType.VIEW; } public void setDecoderOptions(BitmapFactory.Options decoderOptions) { this.decoderOptions = decoderOptions; } public BitmapFactory.Options getDecoderOptions() { return decoderOptions; } public void setContentId(String contentId) { this.contentId = contentId; } /** * This returns a string which identifies the content. Take care to * give your own key in inputStream and bitmap since these usually have * weak ids. * * This is used for caching as a key. * * There is no restriction what kind of chars this can return, so only use * this either hashed or base64 encoded or similar if using in a filesystem. * * @return the id or the empty string if the id could not be generated */ public String getContentId() { return contentId; } /** * This will synchronously load the bitmap (if needed) maybe don't * call this in the main thread. Loading of large bitmaps can take up * 500 ms+ on faster devices. * * @param resources {@link android.content.Context#getResources()} * @return the loaded bitmap. If custom options are provided these will be used here */ public Bitmap synchronouslyLoadBitmap(Resources resources) { if(bitmap != null) { if(decoderOptions != null && decoderOptions.inSampleSize > 1) { return Bitmap.createScaledBitmap(bitmap,bitmap.getWidth()/decoderOptions.inSampleSize,bitmap.getHeight()/decoderOptions.inSampleSize,false); } else { return bitmap; } } else if(resId != null) { return BitmapFactory.decodeResource(resources, resId, decoderOptions); } else if(fileToBitmap != null) { return BitmapFactory.decodeFile(fileToBitmap.getAbsolutePath(), decoderOptions); } else if(inputStream != null) { return BitmapFactory.decodeStream(inputStream, null,decoderOptions); } else if(view != null) { int downSample = 1; Bitmap.Config config = Bitmap.Config.ARGB_8888; if(decoderOptions != null) { if(decoderOptions.inSampleSize > 1) { downSample = decoderOptions.inSampleSize; } if(decoderOptions.inPreferredConfig != null) { config = decoderOptions.inPreferredConfig; } } return BuilderUtil.drawViewToBitmap(bitmap,view,downSample,config); } throw new IllegalStateException("No image resource was set"); } /** * If the not a bitmap itself, this will read the file's meta data. * * @param resources {@link android.content.Context#getResources()} * @return Point where x = width and y = height */ public Point measureImage(Resources resources) { BitmapFactory.Options justBoundsOptions = new BitmapFactory.Options(); justBoundsOptions.inJustDecodeBounds = true; if(bitmap != null) { return new Point(bitmap.getWidth(),bitmap.getHeight()); } else if(resId != null) { BitmapFactory.decodeResource(resources, resId, justBoundsOptions); float scale = (float) justBoundsOptions.inTargetDensity / justBoundsOptions.inDensity; return new Point((int) (justBoundsOptions.outWidth * scale + 0.5f),(int) (justBoundsOptions.outHeight * scale + 0.5f)); } else if(fileToBitmap != null) { BitmapFactory.decodeFile(fileToBitmap.getAbsolutePath(), justBoundsOptions); } else if(inputStream != null) { BitmapFactory.decodeStream(inputStream, null,justBoundsOptions); try {inputStream.reset();} catch (IOException e) {} } else if(view != null) { return new Point(view.getWidth(),view.getHeight()); } return new Point(justBoundsOptions.outWidth,justBoundsOptions.outHeight); } /** * Returns the readable type of source data (eg. view, bitmap, file, etc.) */ public SourceType getSourceType() { return type; } public Integer getResId() { return resId; } public InputStream getInputStream() { return inputStream; } public Bitmap getBitmap() { return bitmap; } public File getFileToBitmap() { return fileToBitmap; } public View getView() { return view; } }