1 package com.bumptech.glide; 2 3 import android.graphics.Bitmap; 4 import android.graphics.drawable.Drawable; 5 import android.os.ParcelFileDescriptor; 6 import android.view.animation.Animation; 7 import android.widget.ImageView; 8 9 import com.bumptech.glide.load.DecodeFormat; 10 import com.bumptech.glide.load.Encoder; 11 import com.bumptech.glide.load.Key; 12 import com.bumptech.glide.load.ResourceDecoder; 13 import com.bumptech.glide.load.ResourceEncoder; 14 import com.bumptech.glide.load.Transformation; 15 import com.bumptech.glide.load.engine.DiskCacheStrategy; 16 import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool; 17 import com.bumptech.glide.load.model.ImageVideoWrapper; 18 import com.bumptech.glide.load.resource.bitmap.BitmapTransformation; 19 import com.bumptech.glide.load.resource.bitmap.Downsampler; 20 import com.bumptech.glide.load.resource.bitmap.FileDescriptorBitmapDecoder; 21 import com.bumptech.glide.load.resource.bitmap.ImageVideoBitmapDecoder; 22 import com.bumptech.glide.load.resource.bitmap.StreamBitmapDecoder; 23 import com.bumptech.glide.load.resource.bitmap.VideoBitmapDecoder; 24 import com.bumptech.glide.load.resource.file.FileToStreamDecoder; 25 import com.bumptech.glide.load.resource.transcode.ResourceTranscoder; 26 import com.bumptech.glide.provider.LoadProvider; 27 import com.bumptech.glide.request.RequestListener; 28 import com.bumptech.glide.request.animation.ViewPropertyAnimation; 29 import com.bumptech.glide.request.target.Target; 30 31 import java.io.File; 32 import java.io.InputStream; 33 34 /** 35 * A class for creating a request to load a bitmap for an image or from a video. Sets a variety of type independent 36 * options including resizing, animations, and placeholders. 37 * 38 * <p> 39 * Warning - It is <em>not</em> safe to use this builder after calling <code>into()</code>, it may be pooled and 40 * reused. 41 * </p> 42 * 43 * @param <ModelType> The type of model that will be loaded into the target. 44 * @param <TranscodeType> The type of the transcoded resource that the target will receive 45 */ 46 public class BitmapRequestBuilder<ModelType, TranscodeType> 47 extends GenericRequestBuilder<ModelType, ImageVideoWrapper, Bitmap, TranscodeType> implements BitmapOptions { 48 private final BitmapPool bitmapPool; 49 50 private Downsampler downsampler = Downsampler.AT_LEAST; 51 private DecodeFormat decodeFormat; 52 private ResourceDecoder<InputStream, Bitmap> imageDecoder; 53 private ResourceDecoder<ParcelFileDescriptor, Bitmap> videoDecoder; 54 BitmapRequestBuilder(LoadProvider<ModelType, ImageVideoWrapper, Bitmap, TranscodeType> loadProvider, Class<TranscodeType> transcodeClass, GenericRequestBuilder<ModelType, ?, ?, ?> other)55 BitmapRequestBuilder(LoadProvider<ModelType, ImageVideoWrapper, Bitmap, TranscodeType> loadProvider, 56 Class<TranscodeType> transcodeClass, GenericRequestBuilder<ModelType, ?, ?, ?> other) { 57 super(loadProvider, transcodeClass, other); 58 this.bitmapPool = other.glide.getBitmapPool(); 59 this.decodeFormat = other.glide.getDecodeFormat(); 60 61 imageDecoder = new StreamBitmapDecoder(bitmapPool, decodeFormat); 62 videoDecoder = new FileDescriptorBitmapDecoder(bitmapPool, decodeFormat); 63 } 64 65 /** 66 * Load images at a size near the size of the target using {@link Downsampler#AT_LEAST}. 67 * 68 * @see #downsample(Downsampler) 69 * 70 * @return This request builder. 71 */ approximate()72 public BitmapRequestBuilder<ModelType, TranscodeType> approximate() { 73 return downsample(Downsampler.AT_LEAST); 74 } 75 76 /** 77 * Load images at their original size using {@link Downsampler#NONE}. 78 * 79 * @see #downsample(Downsampler) 80 * 81 * @return This request builder. 82 */ asIs()83 public BitmapRequestBuilder<ModelType, TranscodeType> asIs() { 84 return downsample(Downsampler.NONE); 85 } 86 87 /** 88 * Load images at a size that is at most exactly as big as the target using 89 * {@link com.bumptech.glide.load.resource.bitmap.Downsampler#AT_MOST}. 90 * 91 * @see #downsample(com.bumptech.glide.load.resource.bitmap.Downsampler) 92 * 93 * @return This request builder. 94 */ atMost()95 public BitmapRequestBuilder<ModelType, TranscodeType> atMost() { 96 return downsample(Downsampler.AT_MOST); 97 } 98 99 /** 100 * Load images using the given {@link Downsampler}. Replaces any existing image decoder. Defaults to 101 * {@link Downsampler#AT_LEAST}. Will be ignored if the data represented by the model is a video. This replaces any 102 * previous calls to {@link #imageDecoder(ResourceDecoder)} and {@link #decoder(ResourceDecoder)} with default 103 * decoders with the appropriate options set. 104 * 105 * @see #imageDecoder 106 * 107 * @param downsampler The downsampler. 108 * @return This request builder. 109 */ downsample(Downsampler downsampler)110 private BitmapRequestBuilder<ModelType, TranscodeType> downsample(Downsampler downsampler) { 111 this.downsampler = downsampler; 112 imageDecoder = new StreamBitmapDecoder(downsampler, bitmapPool, decodeFormat); 113 super.decoder(new ImageVideoBitmapDecoder(imageDecoder, videoDecoder)); 114 return this; 115 } 116 117 /** 118 * {@inheritDoc} 119 */ 120 @Override thumbnail(float sizeMultiplier)121 public BitmapRequestBuilder<ModelType, TranscodeType> thumbnail(float sizeMultiplier) { 122 super.thumbnail(sizeMultiplier); 123 return this; 124 } 125 126 /** 127 * Loads and displays the {@link android.graphics.Bitmap} retrieved by the given thumbnail request if it finishes 128 * before this request. Best used for loading thumbnail {@link Bitmap}s that are smaller and will be loaded more 129 * quickly than the fullsize {@link Bitmap}. There are no guarantees about the order in which the requests will 130 * actually finish. However, if the thumb request completes after the full request, the thumb 131 * {@link android.graphics.Bitmap} will never replace the full image. 132 * 133 * @see #thumbnail(float) 134 * 135 * <p> 136 * Note - Any options on the main request will not be passed on to the thumbnail request. For example, if 137 * you want an animation to occur when either the full {@link android.graphics.Bitmap} loads or the thumbnail 138 * loads, you need to call {@link #animate(int)} on both the thumb and the full request. For a simpler thumbnail 139 * option where these options are applied to the humbnail as well, see {@link #thumbnail(float)}. 140 * </p> 141 * 142 * <p> 143 * Only the thumbnail call on the main request will be obeyed, recursive calls to this method are ignored. 144 * </p> 145 * 146 * @param thumbnailRequest The request to use to load the thumbnail. 147 * @return This request builder. 148 */ thumbnail(BitmapRequestBuilder<?, TranscodeType> thumbnailRequest)149 public BitmapRequestBuilder<ModelType, TranscodeType> thumbnail(BitmapRequestBuilder<?, TranscodeType> 150 thumbnailRequest) { 151 super.thumbnail(thumbnailRequest); 152 return this; 153 } 154 155 /** 156 * {@inheritDoc} 157 */ 158 @Override sizeMultiplier(float sizeMultiplier)159 public BitmapRequestBuilder<ModelType, TranscodeType> sizeMultiplier(float sizeMultiplier) { 160 super.sizeMultiplier(sizeMultiplier); 161 return this; 162 } 163 164 /** 165 * {@inheritDoc} 166 */ 167 @Override decoder(ResourceDecoder<ImageVideoWrapper, Bitmap> decoder)168 public BitmapRequestBuilder<ModelType, TranscodeType> decoder(ResourceDecoder<ImageVideoWrapper, Bitmap> decoder) { 169 super.decoder(decoder); 170 return this; 171 } 172 173 /** 174 * {@inheritDoc} 175 */ 176 @Override cacheDecoder(ResourceDecoder<File, Bitmap> cacheDecoder)177 public BitmapRequestBuilder<ModelType, TranscodeType> cacheDecoder(ResourceDecoder<File, Bitmap> cacheDecoder) { 178 super.cacheDecoder(cacheDecoder); 179 return this; 180 } 181 182 /** 183 * {@inheritDoc} 184 */ 185 @Override encoder(ResourceEncoder<Bitmap> encoder)186 public BitmapRequestBuilder<ModelType, TranscodeType> encoder(ResourceEncoder<Bitmap> encoder) { 187 super.encoder(encoder); 188 return this; 189 } 190 191 /** 192 * Sets the {@link com.bumptech.glide.load.ResourceDecoder} that will be used to decode {@link Bitmap}s obtained 193 * from an {@link java.io.InputStream}. 194 * 195 * @see #videoDecoder 196 * 197 * @param decoder The decoder to use to decode {@link Bitmap}s. 198 * @return This request builder. 199 */ imageDecoder(ResourceDecoder<InputStream, Bitmap> decoder)200 public BitmapRequestBuilder<ModelType, TranscodeType> imageDecoder(ResourceDecoder<InputStream, Bitmap> decoder) { 201 imageDecoder = decoder; 202 super.decoder(new ImageVideoBitmapDecoder(decoder, videoDecoder)); 203 return this; 204 } 205 206 /** 207 * Sets the {@link com.bumptech.glide.load.ResourceDecoder} that will be used to decode {@link Bitmap}s obtained 208 * from an {@link android.os.ParcelFileDescriptor}. 209 * 210 * @param decoder The decoder to use to decode {@link Bitmap}s. 211 * @return This request builder. 212 */ videoDecoder( ResourceDecoder<ParcelFileDescriptor, Bitmap> decoder)213 public BitmapRequestBuilder<ModelType, TranscodeType> videoDecoder( 214 ResourceDecoder<ParcelFileDescriptor, Bitmap> decoder) { 215 videoDecoder = decoder; 216 super.decoder(new ImageVideoBitmapDecoder(imageDecoder, decoder)); 217 return this; 218 } 219 220 /** 221 * Sets the preferred format for {@link Bitmap}s decoded in this request. Defaults to 222 * {@link DecodeFormat#PREFER_RGB_565}. This replaces any previous calls to {@link #imageDecoder(ResourceDecoder)}, 223 * {@link #videoDecoder(ResourceDecoder)}, {@link #decoder(ResourceDecoder)} and 224 * {@link #cacheDecoder(com.bumptech.glide.load.ResourceDecoder)}} with default decoders with the appropriate 225 * options set. 226 * 227 * <p> 228 * Note - If using a {@link Transformation} that expect bitmaps to support transparency, this should always be 229 * set to ALWAYS_ARGB_8888. RGB_565 requires fewer bytes per pixel and is generally preferable, but it does not 230 * support transparency. 231 * </p> 232 * 233 * @see DecodeFormat 234 * 235 * @param format The format to use. 236 * @return This request builder. 237 */ format(DecodeFormat format)238 public BitmapRequestBuilder<ModelType, TranscodeType> format(DecodeFormat format) { 239 this.decodeFormat = format; 240 imageDecoder = new StreamBitmapDecoder(downsampler, bitmapPool, format); 241 videoDecoder = new FileDescriptorBitmapDecoder(new VideoBitmapDecoder(), bitmapPool, format); 242 super.cacheDecoder(new FileToStreamDecoder<Bitmap>(new StreamBitmapDecoder(downsampler, bitmapPool, format))); 243 super.decoder(new ImageVideoBitmapDecoder(imageDecoder, videoDecoder)); 244 return this; 245 } 246 247 @Override priority(Priority priority)248 public BitmapRequestBuilder<ModelType, TranscodeType> priority(Priority priority) { 249 super.priority(priority); 250 return this; 251 } 252 253 /** 254 * Transform images using the given {@link com.bumptech.glide.load.resource.bitmap.BitmapTransformation}s. 255 * 256 * @see #centerCrop() 257 * @see #fitCenter() 258 * @see #transform(com.bumptech.glide.load.Transformation[]) 259 * 260 * @param transformations The transformations to apply in order. 261 * @return This request builder. 262 */ transform(BitmapTransformation... transformations)263 public BitmapRequestBuilder<ModelType, TranscodeType> transform(BitmapTransformation... transformations) { 264 super.transform(transformations); 265 return this; 266 } 267 268 /** 269 * Transform images using {@link com.bumptech.glide.load.resource.bitmap.CenterCrop}. 270 * 271 * @see #fitCenter() 272 * @see #transform(com.bumptech.glide.load.resource.bitmap.BitmapTransformation...) 273 * @see #transform(com.bumptech.glide.load.Transformation[]) 274 * 275 * @return This request builder. 276 */ centerCrop()277 public BitmapRequestBuilder<ModelType, TranscodeType> centerCrop() { 278 return transform(glide.getBitmapCenterCrop()); 279 } 280 281 /** 282 * Transform images using {@link com.bumptech.glide.load.resource.bitmap.FitCenter}. 283 * 284 * @see #centerCrop() 285 * @see #transform(com.bumptech.glide.load.resource.bitmap.BitmapTransformation...) 286 * @see #transform(com.bumptech.glide.load.Transformation[]) 287 * 288 * @return This request builder. 289 */ fitCenter()290 public BitmapRequestBuilder<ModelType, TranscodeType> fitCenter() { 291 return transform(glide.getBitmapFitCenter()); 292 } 293 294 /** 295 * {@inheritDoc} 296 * 297 * @see #fitCenter() 298 * @see #centerCrop() 299 */ 300 @Override transform(Transformation<Bitmap>.... transformations)301 public BitmapRequestBuilder<ModelType, TranscodeType> transform(Transformation<Bitmap>... transformations) { 302 super.transform(transformations); 303 return this; 304 } 305 306 /** 307 * {@inheritDoc} 308 */ 309 @Override transcoder( ResourceTranscoder<Bitmap, TranscodeType> transcoder)310 public BitmapRequestBuilder<ModelType, TranscodeType> transcoder( 311 ResourceTranscoder<Bitmap, TranscodeType> transcoder) { 312 super.transcoder(transcoder); 313 return this; 314 } 315 316 /** 317 * {@inheritDoc} 318 */ 319 @Override dontAnimate()320 public BitmapRequestBuilder<ModelType, TranscodeType> dontAnimate() { 321 super.dontAnimate(); 322 return this; 323 } 324 325 /** 326 * {@inheritDoc} 327 */ 328 @Override animate(int animationId)329 public BitmapRequestBuilder<ModelType, TranscodeType> animate(int animationId) { 330 super.animate(animationId); 331 return this; 332 } 333 334 /** 335 * {@inheritDoc} 336 */ 337 @Deprecated 338 @SuppressWarnings("deprecation") 339 @Override animate(Animation animation)340 public BitmapRequestBuilder<ModelType, TranscodeType> animate(Animation animation) { 341 super.animate(animation); 342 return this; 343 } 344 345 /** 346 * {@inheritDoc} 347 */ 348 @Override animate(ViewPropertyAnimation.Animator animator)349 public BitmapRequestBuilder<ModelType, TranscodeType> animate(ViewPropertyAnimation.Animator animator) { 350 super.animate(animator); 351 return this; 352 } 353 354 /** 355 * {@inheritDoc} 356 */ 357 @Override placeholder(int resourceId)358 public BitmapRequestBuilder<ModelType, TranscodeType> placeholder(int resourceId) { 359 super.placeholder(resourceId); 360 return this; 361 } 362 363 /** 364 * {@inheritDoc} 365 */ 366 @Override placeholder(Drawable drawable)367 public BitmapRequestBuilder<ModelType, TranscodeType> placeholder(Drawable drawable) { 368 super.placeholder(drawable); 369 return this; 370 } 371 372 /** 373 * {@inheritDoc} 374 */ 375 @Override error(int resourceId)376 public BitmapRequestBuilder<ModelType, TranscodeType> error(int resourceId) { 377 super.error(resourceId); 378 return this; 379 } 380 381 /** 382 * {@inheritDoc} 383 */ 384 @Override error(Drawable drawable)385 public BitmapRequestBuilder<ModelType, TranscodeType> error(Drawable drawable) { 386 super.error(drawable); 387 return this; 388 } 389 390 /** 391 * {@inheritDoc} 392 */ 393 @Override listener( RequestListener<? super ModelType, TranscodeType> requestListener)394 public BitmapRequestBuilder<ModelType, TranscodeType> listener( 395 RequestListener<? super ModelType, TranscodeType> requestListener) { 396 super.listener(requestListener); 397 return this; 398 } 399 400 /** 401 * {@inheritDoc} 402 */ 403 @Override skipMemoryCache(boolean skip)404 public BitmapRequestBuilder<ModelType, TranscodeType> skipMemoryCache(boolean skip) { 405 super.skipMemoryCache(skip); 406 return this; 407 } 408 409 /** 410 * {@inheritDoc} 411 */ 412 @Override diskCacheStrategy(DiskCacheStrategy strategy)413 public BitmapRequestBuilder<ModelType, TranscodeType> diskCacheStrategy(DiskCacheStrategy strategy) { 414 super.diskCacheStrategy(strategy); 415 return this; 416 } 417 418 /** 419 * {@inheritDoc} 420 */ 421 @Override override(int width, int height)422 public BitmapRequestBuilder<ModelType, TranscodeType> override(int width, int height) { 423 super.override(width, height); 424 return this; 425 } 426 427 /** 428 * {@inheritDoc} 429 */ 430 @Override thumbnail( GenericRequestBuilder<?, ?, ?, TranscodeType> thumbnailRequest)431 public BitmapRequestBuilder<ModelType, TranscodeType> thumbnail( 432 GenericRequestBuilder<?, ?, ?, TranscodeType> thumbnailRequest) { 433 super.thumbnail(thumbnailRequest); 434 return this; 435 } 436 437 /** 438 * {@inheritDoc} 439 */ 440 @Override sourceEncoder(Encoder<ImageVideoWrapper> sourceEncoder)441 public BitmapRequestBuilder<ModelType, TranscodeType> sourceEncoder(Encoder<ImageVideoWrapper> sourceEncoder) { 442 super.sourceEncoder(sourceEncoder); 443 return this; 444 } 445 446 /** 447 * {@inheritDoc} 448 */ 449 @Override dontTransform()450 public BitmapRequestBuilder<ModelType, TranscodeType> dontTransform() { 451 super.dontTransform(); 452 return this; 453 } 454 455 @Override signature(Key signature)456 public BitmapRequestBuilder<ModelType, TranscodeType> signature(Key signature) { 457 super.signature(signature); 458 return this; 459 } 460 461 @Override load(ModelType model)462 public BitmapRequestBuilder<ModelType, TranscodeType> load(ModelType model) { 463 super.load(model); 464 return this; 465 } 466 467 @Override clone()468 public BitmapRequestBuilder<ModelType, TranscodeType> clone() { 469 return (BitmapRequestBuilder<ModelType, TranscodeType>) super.clone(); 470 } 471 472 /** 473 * {@inheritDoc} 474 * 475 * <p> 476 * Note - If no transformation is set for this load, a default transformation will be applied based on the 477 * value returned from {@link android.widget.ImageView#getScaleType()}. To avoid this default transformation, 478 * use {@link #dontTransform()}. 479 * </p> 480 * 481 * @param view {@inheritDoc} 482 * @return {@inheritDoc} 483 */ 484 @Override into(ImageView view)485 public Target<TranscodeType> into(ImageView view) { 486 return super.into(view); 487 } 488 489 @Override applyFitCenter()490 void applyFitCenter() { 491 fitCenter(); 492 } 493 494 @Override applyCenterCrop()495 void applyCenterCrop() { 496 centerCrop(); 497 } 498 } 499