Strategy mode 2 of Glide design pattern [DownsampleStrategy]

Posted by kemper on Mon, 10 Jan 2022 07:10:39 +0100

Strategy mode II

DownsampleStrategy

Package path: com bumptech. glide. load. resource. bitmap. DownsampleStrategy

Indicates the algorithm used when down sampling the image.
DownsampleStrategy does not provide any guarantee about the output size. The behavior will vary, depending on the strategy used by the ResourceDecoder and the Android version of the code running. Using DownsampleStrategy as an optimization only improves memory efficiency. If you need a specific size or shape output, use Transformation to replace or supplement the DownsampleStrategy.

Some differences between Android and ResourceDecoders versions are listed below, but this list is not comprehensive, because DownsampleStrategy only controls its output scale value, not how to use it.

On some versions of Android, precise scaling is impossible. In this case, since only the power of two down sampling is supported, the policy can only choose between down sampling to 1 and 2 times the request size, and between 0.5 times the request size and 1 time the request size. In order to maintain the conversion potential, scale accurately without loss of quality, except at_ Everyone except most tends to reduce the sample to between 1 and 2 times the requested size.

/**
 * Indicates the algorithm to use when downsampling images.
 *
 * <p>{@code DownsampleStrategy} does not provide any guarantees about output sizes. Behavior will
 * differ depending on the {@link com.bumptech.glide.load.ResourceDecoder} using the strategy and
 * the version of Android the code runs on. Use {@code DownsampleStrategy} as an optimization to
 * improve memory efficiency only. If you need a particular size or shape output, use an {@link
 * com.bumptech.glide.load.Transformation} either instead or in addition to a {@code
 * DownsampleStrategy}.
 *
 * <p>Some differences between versions of Android and {@link
 * com.bumptech.glide.load.ResourceDecoder}s are listed below, but the list is not comprehensive
 * because {@link DownsampleStrategy} only controls its output scale value, not how that output
 * value is used.
 *
 * <p>On some versions of Android, precise scaling is not possible. In those cases, the strategies
 * can only pick between downsampling to between 1x the requested size and 2x the requested size and
 * between 0.5x the requested size and 1x the requested size because only power of two downsampling
 * is supported. To preserve the potential for a {@link com.bumptech.glide.load.Transformation} to
 * scale precisely without a loss in quality, all but {@link #AT_MOST} will prefer to downsample to
 * between 1x and 2x the requested size.
 */
// Public API.
@SuppressWarnings("WeakerAccess")
public abstract class DownsampleStrategy {

  /**
   * Downsamples so the image's smallest dimension is between the given dimensions and 2x the given
   * dimensions, with no size restrictions on the image's largest dimension.
   *
   * <p>Does not upscale if the requested dimensions are larger than the original dimensions.
   */
   Down sampling makes the minimum size of the image between the given size and twice the given size, while there is no size limit on the maximum size of the image.
If the required size is larger than the original size, no upgrade is required.
  public static final DownsampleStrategy AT_LEAST = new AtLeast();

  /**
   * Downsamples so the image's largest dimension is between 1/2 the given dimensions and the given
   * dimensions, with no restrictions on the image's smallest dimension.
   *
   * <p>Does not upscale if the requested dimensions are larger than the original dimensions.
   */
   Down sampling makes the maximum size of the image within the given size and 1 of the given size/2 There is no limit on the minimum size of the image.
If the required size is larger than the original size, no upgrade is required.
  public static final DownsampleStrategy AT_MOST = new AtMost();

  /**
   * Scales, maintaining the original aspect ratio, so that one of the image's dimensions is exactly
   * equal to the requested size and the other dimension is less than or equal to the requested
   * size.
   *
   * <p>This method will upscale if the requested width and height are greater than the source width
   * and height. To avoid upscaling, use {@link #AT_LEAST}, {@link #AT_MOST} or {@link
   * #CENTER_INSIDE}.
   *
   * <p>On pre-KitKat devices, {@code FIT_CENTER} will downsample by a power of two only so that one
   * of the image's dimensions is greater than or equal to the requested size. No guarantees are
   * made about the second dimensions. This is <em>NOT</em> the same as {@link #AT_LEAST} because
   * only one dimension, not both, are greater than or equal to the requested dimensions, the other
   * may be smaller.
   */
   Zoom, maintaining the original aspect ratio so that the size of one image is exactly equal to the requested size and the other is less than or equal to the requested size.
If the requested width and height are greater than the width and height of the source, this method will be upgraded. To avoid upgrading, use AT_LEAST,AT_MOST or CENTER_INSIDE. 

stay kitkat On previous devices, FIT_CENTER Only the 2nd power is sampled down so that the size of one of the images is greater than or equal to the requested size. There is no guarantee for the second dimension. This and AT_LEAST Different, because only one dimension is greater than or equal to the requested dimension, rather than both dimensions are greater than or equal to the requested dimension, and the other dimension may be smaller.
  public static final DownsampleStrategy FIT_CENTER = new FitCenter();

  /** Identical to {@link #FIT_CENTER}, but never upscales. */
  And FIT_CENTER Same, but never upgraded
  public static final DownsampleStrategy CENTER_INSIDE = new CenterInside();

  /**
   * Scales, maintaining the original aspect ratio, so that one of the image's dimensions is exactly
   * equal to the requested size and the other dimension is greater than or equal to the requested
   * size.
   *
   * <p>This method will upscale if the requested width and height are greater than the source width
   * and height. To avoid upscaling, use {@link #AT_LEAST}, {@link #AT_MOST}, or {@link
   * #CENTER_INSIDE}.
   *
   * <p>On pre-KitKat devices, {@link Downsampler} treats this as equivalent to {@link #AT_LEAST}
   * because only power of two downsampling can be used.
   */
   Zoom, maintaining the original aspect ratio so that the size of one image is exactly equal to the requested size and the other is greater than or equal to the requested size.
If the requested width and height are greater than the width and height of the source, this method will be upgraded. To avoid upgrading, use AT_LEAST,AT_MOST or CENTER_INSIDE. 

stay KitKat On previous devices, Downsampler Treat it as equivalent to AT_LEAST,Because only the power of two down samples can be used.
  public static final DownsampleStrategy CENTER_OUTSIDE = new CenterOutside();

  /** Performs no downsampling or scaling. */
  No downsampling or scaling.
  public static final DownsampleStrategy NONE = new None();

  /** Default strategy, currently {@link #CENTER_OUTSIDE}. */
  Default policy, currently CENTER_OUTSIDE. 
  public static final DownsampleStrategy DEFAULT = CENTER_OUTSIDE;

  /**
   * Indicates the {@link com.bumptech.glide.load.resource.bitmap.DownsampleStrategy} option that
   * will be used to calculate the sample size to use to downsample an image given the original and
   * target dimensions of the image.
   */
   instructions DownsampleStrategy Option, which will be used to calculate the sample size for down sampling the image given the original and target sizes of the image.
  // The exact String value here is retained to avoid breaking cache keys for images that were
  // loaded with older versions of Glide.
  public static final Option<DownsampleStrategy> OPTION =
      Option.memory(
          "com.bumptech.glide.load.resource.bitmap.Downsampler.DownsampleStrategy", DEFAULT);

  @Synthetic
  static final boolean IS_BITMAP_FACTORY_SCALING_SUPPORTED =
      Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;

  /**
   * Returns a float (0, +infinity) indicating a scale factor to apply to the source width and
   * height when displayed in the requested width and height.
   *
   * <p>The returned scale factor will be split into a power of two sample size applied via {@link
   * android.graphics.BitmapFactory.Options#inSampleSize} and a float scale factor applied after
   * downsampling via {@link android.graphics.BitmapFactory.Options#inTargetDensity} and {@link
   * android.graphics.BitmapFactory.Options#inDensity}. Because of rounding errors the scale factor
   * may not be applied precisely.
   *
   * <p>The float scaling factor will only be applied on KitKat+. Prior to KitKat, only the power of
   * two downsampling will be applied.
   *
   * @param sourceWidth The width in pixels of the image to be downsampled.
   * @param sourceHeight The height in pixels of the image to be downsampled.
   * @param requestedWidth The width in pixels of the view/target the image will be displayed in.
   * @param requestedHeight The height in pixels of the view/target the image will be displayed in.
   */
   Returns a floating point number(0,+∞),Indicates the scale factor applied to the source width and height when displayed in the requested width and height.
The scale factor returned will be split into a power of two sample sizes by BitmapFactory.Options.inSampleSize Application, and through BitmapFactory.Options.inTargetDensity and BitmapFactory.Options.inDensity Floating scale factor after applying downsampling. The scale factor may not be applied accurately due to rounding errors.

Floating scale factor will only apply to KitKat+. stay KitKat Previously, only two down samples of power were used.

parameter:
sourceWidth -The pixel width of the image to downsample.
sourceHeight -The pixel height of the image to be downsampled.
requestedWidth -The image is displayed in the view/The pixel width of the target.
requestdheight -The view in which the image will be displayed/The pixel height of the target.
  public abstract float getScaleFactor(
      int sourceWidth, int sourceHeight, int requestedWidth, int requestedHeight);

  /**
   * Returns a non-null {@link SampleSizeRounding} to use to resolve rounding errors and conflicts
   * between scaling for the width and the height of the image.
   *
   * @param sourceWidth The width in pixels of the image to be downsampled.
   * @param sourceHeight The height in pixels of the image to be downsampled.
   * @param requestedWidth The width in pixels of the view/target the image will be displayed in.
   * @param requestedHeight The height in pixels of the view/target the image will be displayed in.
   */
   Returns a non empty DownsampleStrategy. SampleSizeRounding It is used to solve the conflict between rounding error and image width and height scaling.
parameter:
sourceWidth -The pixel width of the image to downsample.
sourceHeight -The pixel height of the image to be downsampled.
requestedWidth -The image is displayed in the view/The pixel width of the target.
requestdheight -The view in which the image will be displayed/The pixel height of the target.
  public abstract SampleSizeRounding getSampleSizeRounding(
      int sourceWidth, int sourceHeight, int requestedWidth, int requestedHeight);
 /**
   * Indicates whether to prefer to prefer downsampling or scaling to prefer lower memory usage or
   * higher quality.
   */
   Indicates whether sampling down or scaling is preferred for lower memory usage or higher quality.
  public enum SampleSizeRounding {
    /**
     * Prefer to round the sample size up so that the image is downsampled to smaller than the
     * requested size to use less memory.
     */
     Prefer to round the sample size to sample the image down to a smaller size than the requested size, thus using less memory.
    MEMORY,
    /**
     * Prefer to round the sample size down so that the image is downsampled to larger than the
     * requested size to maintain quality at the expense of extra memory usage.
     */
     It is preferred to round the sample size to sample the image larger than the requested size to maintain quality, but at the expense of additional memory use.
    QUALITY,
  }

The policy implementation list is as follows:

  1. AT_LEAST
  2. AT_MOST
  3. FIT_CENTER
  4. CENTER_INSIDE
  5. CENTER_OUTSIDE
  6. NONE
  7. DEFAULT= CENTER_OUTSIDE;

AT_LEAST

Down sampling makes the minimum size of the image between the given size and twice the given size, while there is no size limit on the maximum size of the image.
If the required size is larger than the original size, no upgrade is required.

  private static class AtLeast extends DownsampleStrategy {

    @Synthetic
    AtLeast() {}

    @Override
    public float getScaleFactor(
        int sourceWidth, int sourceHeight, int requestedWidth, int requestedHeight) {
      int minIntegerFactor = Math.min(sourceHeight / requestedHeight, sourceWidth / requestedWidth);
      return minIntegerFactor == 0 ? 1f : 1f / Integer.highestOneBit(minIntegerFactor);
    }

    @Override
    public SampleSizeRounding getSampleSizeRounding(
        int sourceWidth, int sourceHeight, int requestedWidth, int requestedHeight) {
      return SampleSizeRounding.QUALITY;
    }
  }

AT_MOST

Down sampling makes the maximum size of the image between the given size and 1 / 2 of the given size, and there is no limit on the minimum size of the image.
If the required size is larger than the original size, no upgrade is required.

private static class AtMost extends DownsampleStrategy {

    @Synthetic
    AtMost() {}

    @Override
    public float getScaleFactor(
        int sourceWidth, int sourceHeight, int requestedWidth, int requestedHeight) {
      int maxIntegerFactor =
          (int)
              Math.ceil(
                  Math.max(
                      sourceHeight / (float) requestedHeight,
                      sourceWidth / (float) requestedWidth));
      int lesserOrEqualSampleSize = Math.max(1, Integer.highestOneBit(maxIntegerFactor));
      int greaterOrEqualSampleSize =
          lesserOrEqualSampleSize << (lesserOrEqualSampleSize < maxIntegerFactor ? 1 : 0);
      return 1f / greaterOrEqualSampleSize;
    }

    @Override
    public SampleSizeRounding getSampleSizeRounding(
        int sourceWidth, int sourceHeight, int requestedWidth, int requestedHeight) {
      return SampleSizeRounding.MEMORY;
    }
  }

FIT_CENTER

Zoom, maintaining the original aspect ratio so that the size of one image is exactly equal to the requested size and the other is less than or equal to the requested size.
If the requested width and height are greater than the width and height of the source, this method will be upgraded. To avoid upgrading, use AT_LEAST,AT_MOST or CENTER_INSIDE.

On the device before kitkat, FIT_CENTER will only sample down to the power of 2 so that the size of one of the images is greater than or equal to the requested size. There is no guarantee for the second dimension. This is different from at_ Leap is different because only one dimension is greater than or equal to the requested dimension, rather than both dimensions are greater than or equal to the requested dimension, and the other dimension may be smaller.

 private static class FitCenter extends DownsampleStrategy {

    @Synthetic
    FitCenter() {}

    @Override
    public float getScaleFactor(
        int sourceWidth, int sourceHeight, int requestedWidth, int requestedHeight) {
      if (IS_BITMAP_FACTORY_SCALING_SUPPORTED) {
        float widthPercentage = requestedWidth / (float) sourceWidth;
        float heightPercentage = requestedHeight / (float) sourceHeight;

        return Math.min(widthPercentage, heightPercentage);
      } else {
        // Similar to AT_LEAST, but only require one dimension or the other to be >= requested
        // rather than both.
        int maxIntegerFactor =
            Math.max(sourceHeight / requestedHeight, sourceWidth / requestedWidth);
        return maxIntegerFactor == 0 ? 1f : 1f / Integer.highestOneBit(maxIntegerFactor);
      }
    }

    @Override
    public SampleSizeRounding getSampleSizeRounding(
        int sourceWidth, int sourceHeight, int requestedWidth, int requestedHeight) {
      if (IS_BITMAP_FACTORY_SCALING_SUPPORTED) {
        return SampleSizeRounding.QUALITY;
      } else {
        // TODO: This doesn't seem right, but otherwise we can skip a sample size because QUALITY
        // prefers the smaller of the width and height scale factor. MEMORY is a hack that
        // lets us prefer the larger of the two.
        return SampleSizeRounding.MEMORY;
      }
    }
  }

CENTER_INSIDE

And fit_ Same as center, but never upgraded

  private static class CenterInside extends DownsampleStrategy {

    @Synthetic
    CenterInside() {}

    @Override
    public float getScaleFactor(
        int sourceWidth, int sourceHeight, int requestedWidth, int requestedHeight) {

      return Math.min(
          1.f,
          FIT_CENTER.getScaleFactor(sourceWidth, sourceHeight, requestedWidth, requestedHeight));
    }

    @Override
    public SampleSizeRounding getSampleSizeRounding(
        int sourceWidth, int sourceHeight, int requestedWidth, int requestedHeight) {
      return getScaleFactor(sourceWidth, sourceHeight, requestedWidth, requestedHeight) == 1.f
          ? SampleSizeRounding.QUALITY
          : FIT_CENTER.getSampleSizeRounding(
              sourceWidth, sourceHeight, requestedWidth, requestedHeight);
    }
  }

CENTER_OUTSIDE

Zoom, maintaining the original aspect ratio so that the size of one image is exactly equal to the requested size and the other is greater than or equal to the requested size.
If the requested width and height are greater than the width and height of the source, this method will be upgraded. To avoid upgrading, use AT_LEAST,AT_MOST or CENTER_INSIDE.

On devices prior to KitKat, Downsampler regarded it as equivalent to at_ Leap, because only the power of two down samples can be used

 private static class CenterOutside extends DownsampleStrategy {

    @Synthetic
    CenterOutside() {}

    @Override
    public float getScaleFactor(
        int sourceWidth, int sourceHeight, int requestedWidth, int requestedHeight) {
      float widthPercentage = requestedWidth / (float) sourceWidth;
      float heightPercentage = requestedHeight / (float) sourceHeight;
      return Math.max(widthPercentage, heightPercentage);
    }

    @Override
    public SampleSizeRounding getSampleSizeRounding(
        int sourceWidth, int sourceHeight, int requestedWidth, int requestedHeight) {
      return SampleSizeRounding.QUALITY;
    }
  }

NONE

No downsampling or scaling.

 private static class None extends DownsampleStrategy {

    @Synthetic
    None() {}

    @Override
    public float getScaleFactor(
        int sourceWidth, int sourceHeight, int requestedWidth, int requestedHeight) {
      return 1f;
    }

    @Override
    public SampleSizeRounding getSampleSizeRounding(
        int sourceWidth, int sourceHeight, int requestedWidth, int requestedHeight) {
      return SampleSizeRounding.QUALITY;
    }
  }

DEFAULT= CENTER_OUTSIDE (see CENTER_OUTSIDE)

Default collection policy

Topics: Java Android Design Pattern Interview OOP