1 package com.bumptech.glide.util; 2 3 import android.annotation.TargetApi; 4 import android.graphics.Bitmap; 5 import android.os.Build; 6 import android.os.Looper; 7 8 import java.util.ArrayDeque; 9 import java.util.Queue; 10 11 /** 12 * A collection of assorted utility classes. 13 */ 14 public final class Util { 15 private static final char[] HEX_CHAR_ARRAY = "0123456789abcdef".toCharArray(); 16 // 32 bytes from sha-256 -> 64 hex chars. 17 private static final char[] SHA_256_CHARS = new char[64]; 18 // 20 bytes from sha-1 -> 40 chars. 19 private static final char[] SHA_1_CHARS = new char[40]; 20 Util()21 private Util() { 22 // Utility class. 23 } 24 25 /** 26 * Returns the hex string of the given byte array representing a SHA256 hash. 27 */ sha256BytesToHex(byte[] bytes)28 public static String sha256BytesToHex(byte[] bytes) { 29 return bytesToHex(bytes, SHA_256_CHARS); 30 } 31 32 /** 33 * Returns the hex string of the given byte array representing a SHA1 hash. 34 */ sha1BytesToHex(byte[] bytes)35 public static String sha1BytesToHex(byte[] bytes) { 36 return bytesToHex(bytes, SHA_1_CHARS); 37 } 38 39 // Taken from: 40 // http://stackoverflow.com/questions/9655181/convert-from-byte-array-to-hex-string-in-java/9655275#9655275 bytesToHex(byte[] bytes, char[] hexChars)41 private static String bytesToHex(byte[] bytes, char[] hexChars) { 42 int v; 43 for (int j = 0; j < bytes.length; j++) { 44 v = bytes[j] & 0xFF; 45 hexChars[j * 2] = HEX_CHAR_ARRAY[v >>> 4]; 46 hexChars[j * 2 + 1] = HEX_CHAR_ARRAY[v & 0x0F]; 47 } 48 return new String(hexChars); 49 } 50 51 /** 52 * Returns the allocated byte size of the given bitmap. 53 * 54 * @see #getBitmapByteSize(android.graphics.Bitmap) 55 * 56 * @deprecated Use {@link #getBitmapByteSize(android.graphics.Bitmap)} instead. Scheduled to be removed in Glide 57 * 4.0. 58 */ 59 @Deprecated getSize(Bitmap bitmap)60 public static int getSize(Bitmap bitmap) { 61 return getBitmapByteSize(bitmap); 62 } 63 64 /** 65 * Returns the in memory size of the given {@link Bitmap} in bytes. 66 */ 67 @TargetApi(Build.VERSION_CODES.KITKAT) getBitmapByteSize(Bitmap bitmap)68 public static int getBitmapByteSize(Bitmap bitmap) { 69 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 70 // Workaround for KitKat initial release NPE in Bitmap, fixed in MR1. See issue #148. 71 try { 72 return bitmap.getAllocationByteCount(); 73 } catch (NullPointerException e) { 74 // Do nothing. 75 } 76 } 77 return bitmap.getHeight() * bitmap.getRowBytes(); 78 } 79 80 /** 81 * Returns the in memory size of {@link android.graphics.Bitmap} with the given width, height, and 82 * {@link android.graphics.Bitmap.Config}. 83 */ getBitmapByteSize(int width, int height, Bitmap.Config config)84 public static int getBitmapByteSize(int width, int height, Bitmap.Config config) { 85 return width * height * getBytesPerPixel(config); 86 } 87 getBytesPerPixel(Bitmap.Config config)88 private static int getBytesPerPixel(Bitmap.Config config) { 89 // A bitmap by decoding a gif has null "config" in certain environments. 90 if (config == null) { 91 config = Bitmap.Config.ARGB_8888; 92 } 93 94 int bytesPerPixel; 95 switch (config) { 96 case ALPHA_8: 97 bytesPerPixel = 1; 98 break; 99 case RGB_565: 100 case ARGB_4444: 101 bytesPerPixel = 2; 102 break; 103 case ARGB_8888: 104 default: 105 bytesPerPixel = 4; 106 } 107 return bytesPerPixel; 108 } 109 110 /** 111 * Throws an {@link java.lang.IllegalArgumentException} if called on a thread other than the main thread. 112 */ assertMainThread()113 public static void assertMainThread() { 114 if (!isOnMainThread()) { 115 throw new IllegalArgumentException("You must call this method on the main thread"); 116 } 117 } 118 119 /** 120 * Throws an {@link java.lang.IllegalArgumentException} if called on the main thread. 121 */ assertBackgroundThread()122 public static void assertBackgroundThread() { 123 if (!isOnBackgroundThread()) { 124 throw new IllegalArgumentException("YOu must call this method on a background thread"); 125 } 126 } 127 128 /** 129 * Returns {@code true} if called on the main thread, {@code false} otherwise. 130 */ isOnMainThread()131 public static boolean isOnMainThread() { 132 return Looper.myLooper() == Looper.getMainLooper(); 133 } 134 135 /** 136 * Returns {@code true} if called on the main thread, {@code false} otherwise. 137 */ isOnBackgroundThread()138 public static boolean isOnBackgroundThread() { 139 return !isOnMainThread(); 140 } 141 142 /** 143 * Creates a {@link java.util.Queue} of the given size using Glide's preferred implementation. 144 */ createQueue(int size)145 public static <T> Queue<T> createQueue(int size) { 146 return new ArrayDeque<T>(size); 147 } 148 } 149