1
1
package com .bumptech .glide .load .resource .bitmap ;
2
2
3
+ import android .os .Build ;
3
4
import com .bumptech .glide .load .Option ;
4
5
import com .bumptech .glide .util .Synthetic ;
5
6
17
18
* com.bumptech.glide.load.ResourceDecoder}s are listed below, but the list is not comprehensive
18
19
* because {@link DownsampleStrategy} only controls it's output scale value, not how that output
19
20
* value is used.
21
+ *
22
+ * <p>On some versions of Android, precise scaling is not possible. In those cases, the strategies
23
+ * can only pick between downsampling to between 1x the requested size and 2x the requested size and
24
+ * between 0.5x the requested size and 1x the requested size because only power of two downsampling
25
+ * is supported. To preserve the potential for a {@link com.bumptech.glide.load.Transformation} to
26
+ * scale precisely without a loss in quality, all but {@link #AT_MOST} will prefer to downsample to
27
+ * between 1x and 2x the requested size.
20
28
*/
21
29
// Public API.
22
30
@ SuppressWarnings ("WeakerAccess" )
23
31
public abstract class DownsampleStrategy {
24
32
33
+ /**
34
+ * Downsamples so the image's smallest dimension is between the given dimensions and 2x the given
35
+ * dimensions, with no size restrictions on the image's largest dimension.
36
+ *
37
+ * <p>Does not upscale if the requested dimensions are larger than the original dimensions.
38
+ */
39
+ public static final DownsampleStrategy AT_LEAST = new AtLeast ();
40
+
41
+ /**
42
+ * Downsamples so the image's largest dimension is between 1/2 the given dimensions and the given
43
+ * dimensions, with no restrictions on the image's smallest dimension.
44
+ *
45
+ * <p>Does not upscale if the requested dimensions are larger than the original dimensions.
46
+ */
47
+ public static final DownsampleStrategy AT_MOST = new AtMost ();
48
+
25
49
/**
26
50
* Scales, maintaining the original aspect ratio, so that one of the image's dimensions is exactly
27
51
* equal to the requested size and the other dimension is less than or equal to the requested
@@ -31,11 +55,17 @@ public abstract class DownsampleStrategy {
31
55
* and height. To avoid upscaling, use {@link #AT_LEAST}, {@link #AT_MOST} or {@link
32
56
* #CENTER_INSIDE}.
33
57
*
34
- * <p>On pre-KitKat devices, {@link Downsampler} treats this as equivalent to {@link #AT_MOST}
35
- * because only power of two downsampling can be used.
58
+ * <p>On pre-KitKat devices, {@code FIT_CENTER} will downsample by a power of two only so that one
59
+ * of the image's dimensions is greater than or equal to the requested size. No guarantees are
60
+ * made about the second dimensions. This is <em>NOT</em> the same as {@link #AT_LEAST} because
61
+ * only one dimension, not both, are greater than or equal to the requested dimensions, the other
62
+ * may be smaller.
36
63
*/
37
64
public static final DownsampleStrategy FIT_CENTER = new FitCenter ();
38
65
66
+ /** Identical to {@link #FIT_CENTER}, but never upscales. */
67
+ public static final DownsampleStrategy CENTER_INSIDE = new CenterInside ();
68
+
39
69
/**
40
70
* Scales, maintaining the original aspect ratio, so that one of the image's dimensions is exactly
41
71
* equal to the requested size and the other dimension is greater than or equal to the requested
@@ -50,31 +80,6 @@ public abstract class DownsampleStrategy {
50
80
*/
51
81
public static final DownsampleStrategy CENTER_OUTSIDE = new CenterOutside ();
52
82
53
- /**
54
- * Downsamples so the image's smallest dimension is between the given dimensions and 2x the given
55
- * dimensions, with no size restrictions on the image's largest dimension.
56
- *
57
- * <p>Does not upscale if the requested dimensions are larger than the original dimensions.
58
- */
59
- public static final DownsampleStrategy AT_LEAST = new AtLeast ();
60
-
61
- /**
62
- * Downsamples so the image's largest dimension is between 1/2 the given dimensions and the given
63
- * dimensions, with no restrictions on the image's smallest dimension.
64
- *
65
- * <p>Does not upscale if the requested dimensions are larger than the original dimensions.
66
- */
67
- public static final DownsampleStrategy AT_MOST = new AtMost ();
68
-
69
- /**
70
- * Returns the original image if it is smaller than the target, otherwise it will be downscaled
71
- * maintaining its original aspect ratio, so that one of the image's dimensions is exactly equal
72
- * to the requested size and the other is less or equal than the requested size.
73
- *
74
- * <p>Does not upscale if the requested dimensions are larger than the original dimensions.
75
- */
76
- public static final DownsampleStrategy CENTER_INSIDE = new CenterInside ();
77
-
78
83
/** Performs no downsampling or scaling. */
79
84
public static final DownsampleStrategy NONE = new None ();
80
85
@@ -92,6 +97,10 @@ public abstract class DownsampleStrategy {
92
97
Option .memory (
93
98
"com.bumptech.glide.load.resource.bitmap.Downsampler.DownsampleStrategy" , DEFAULT );
94
99
100
+ @ Synthetic
101
+ static final boolean IS_BITMAP_FACTORY_SCALING_SUPPORTED =
102
+ Build .VERSION .SDK_INT >= Build .VERSION_CODES .KITKAT ;
103
+
95
104
/**
96
105
* Returns a float (0, +infinity) indicating a scale factor to apply to the source width and
97
106
* height when displayed in the requested width and height.
@@ -133,15 +142,31 @@ private static class FitCenter extends DownsampleStrategy {
133
142
@ Override
134
143
public float getScaleFactor (
135
144
int sourceWidth , int sourceHeight , int requestedWidth , int requestedHeight ) {
136
- float widthPercentage = requestedWidth / (float ) sourceWidth ;
137
- float heightPercentage = requestedHeight / (float ) sourceHeight ;
138
- return Math .min (widthPercentage , heightPercentage );
145
+ if (IS_BITMAP_FACTORY_SCALING_SUPPORTED ) {
146
+ float widthPercentage = requestedWidth / (float ) sourceWidth ;
147
+ float heightPercentage = requestedHeight / (float ) sourceHeight ;
148
+
149
+ return Math .min (widthPercentage , heightPercentage );
150
+ } else {
151
+ // Similar to AT_LEAST, but only require one dimension or the other to be >= requested
152
+ // rather than both.
153
+ int maxIntegerFactor =
154
+ Math .max (sourceHeight / requestedHeight , sourceWidth / requestedWidth );
155
+ return maxIntegerFactor == 0 ? 1f : 1f / Integer .highestOneBit (maxIntegerFactor );
156
+ }
139
157
}
140
158
141
159
@ Override
142
160
public SampleSizeRounding getSampleSizeRounding (
143
161
int sourceWidth , int sourceHeight , int requestedWidth , int requestedHeight ) {
144
- return SampleSizeRounding .QUALITY ;
162
+ if (IS_BITMAP_FACTORY_SCALING_SUPPORTED ) {
163
+ return SampleSizeRounding .QUALITY ;
164
+ } else {
165
+ // TODO: This doesn't seem right, but otherwise we can skip a sample size because QUALITY
166
+ // prefers the smaller of the the width and height scale factor. MEMORY is a hack that
167
+ // lets us prefer the larger of the two.
168
+ return SampleSizeRounding .MEMORY ;
169
+ }
145
170
}
146
171
}
147
172
@@ -246,7 +271,10 @@ public float getScaleFactor(
246
271
@ Override
247
272
public SampleSizeRounding getSampleSizeRounding (
248
273
int sourceWidth , int sourceHeight , int requestedWidth , int requestedHeight ) {
249
- return SampleSizeRounding .QUALITY ;
274
+ return getScaleFactor (sourceWidth , sourceHeight , requestedWidth , requestedHeight ) == 1.f
275
+ ? SampleSizeRounding .QUALITY
276
+ : FIT_CENTER .getSampleSizeRounding (
277
+ sourceWidth , sourceHeight , requestedWidth , requestedHeight );
250
278
}
251
279
}
252
280
0 commit comments