private static <T> Bitmap createScaledBitmapInto(Context context, T model, int width, int height) throws BitmapDecodingException { final Bitmap rough = Downsampler.AT_LEAST.decode(getInputStreamForModel(context, model), Glide.get(context).getBitmapPool(), width, height, DecodeFormat.PREFER_RGB_565); final Resource<Bitmap> resource = BitmapResource.obtain(rough, Glide.get(context).getBitmapPool()); final Resource<Bitmap> result = new FitCenter(context).transform(resource, width, height); if (result == null) { throw new BitmapDecodingException("unable to transform Bitmap"); } return result.get(); }
private static <T> Bitmap createScaledBitmapInto(Context context, T model, int width, int height) throws BitmapDecodingException { final Bitmap rough = Downsampler.AT_LEAST .decode(getInputStreamForModel(context, model), Glide.get(context).getBitmapPool(), width, height, DecodeFormat.PREFER_RGB_565); final Resource<Bitmap> resource = BitmapResource .obtain(rough, Glide.get(context).getBitmapPool()); final Resource<Bitmap> result = new FitCenter(context).transform(resource, width, height); if (result == null) { throw new BitmapDecodingException("unable to transform Bitmap"); } return result.get(); }
public static <T> byte[] createScaledBytes(Context context, T model, MediaConstraints constraints) throws BitmapDecodingException { int quality = MAX_COMPRESSION_QUALITY; int attempts = 0; byte[] bytes; Bitmap scaledBitmap = Downsampler.AT_MOST.decode(getInputStreamForModel(context, model), Glide.get(context).getBitmapPool(), constraints.getImageMaxWidth(context), constraints.getImageMaxHeight(context), DecodeFormat.PREFER_RGB_565); if (scaledBitmap == null) { throw new BitmapDecodingException("Unable to decode image"); } try { do { ByteArrayOutputStream baos = new ByteArrayOutputStream(); scaledBitmap.compress(CompressFormat.JPEG, quality, baos); bytes = baos.toByteArray(); Log.w(TAG, "iteration with quality " + quality + " size " + (bytes.length / 1024) + "kb"); if (quality == MIN_COMPRESSION_QUALITY) break; int nextQuality = (int)Math.floor(quality * Math.sqrt((double)constraints.getImageMaxSize() / bytes.length)); if (quality - nextQuality < MIN_COMPRESSION_QUALITY_DECREASE) { nextQuality = quality - MIN_COMPRESSION_QUALITY_DECREASE; } quality = Math.max(nextQuality, MIN_COMPRESSION_QUALITY); } while (bytes.length > constraints.getImageMaxSize() && attempts++ < MAX_COMPRESSION_ATTEMPTS); if (bytes.length > constraints.getImageMaxSize()) { throw new BitmapDecodingException("Unable to scale image below: " + bytes.length); } Log.w(TAG, "createScaledBytes(" + model.toString() + ") -> quality " + Math.min(quality, MAX_COMPRESSION_QUALITY) + ", " + attempts + " attempt(s)"); return bytes; } finally { if (scaledBitmap != null) scaledBitmap.recycle(); } }
public static <T> byte[] createScaledBytes(Context context, T model, MediaConstraints constraints) throws BitmapDecodingException { int quality = MAX_COMPRESSION_QUALITY; int attempts = 0; byte[] bytes; Bitmap scaledBitmap = Downsampler.AT_MOST.decode(getInputStreamForModel(context, model), Glide.get(context).getBitmapPool(), constraints.getImageMaxWidth(context), constraints.getImageMaxHeight(context), DecodeFormat.PREFER_RGB_565); if (scaledBitmap == null) { throw new BitmapDecodingException("Unable to decode image"); } try { do { ByteArrayOutputStream baos = new ByteArrayOutputStream(); scaledBitmap.compress(CompressFormat.JPEG, quality, baos); bytes = baos.toByteArray(); Log.w(TAG, "iteration with quality " + quality + " size " + (bytes.length / 1024) + "kb"); if (quality == MIN_COMPRESSION_QUALITY) break; int nextQuality = (int)Math.floor(quality * Math.sqrt((double)constraints.getImageMaxSize(context) / bytes.length)); if (quality - nextQuality < MIN_COMPRESSION_QUALITY_DECREASE) { nextQuality = quality - MIN_COMPRESSION_QUALITY_DECREASE; } quality = Math.max(nextQuality, MIN_COMPRESSION_QUALITY); } while (bytes.length > constraints.getImageMaxSize(context) && attempts++ < MAX_COMPRESSION_ATTEMPTS); if (bytes.length > constraints.getImageMaxSize(context)) { throw new BitmapDecodingException("Unable to scale image below: " + bytes.length); } Log.w(TAG, "createScaledBytes(" + model.toString() + ") -> quality " + Math.min(quality, MAX_COMPRESSION_QUALITY) + ", " + attempts + " attempt(s)"); return bytes; } finally { if (scaledBitmap != null) scaledBitmap.recycle(); } }
/** * Load images using the given {@link Downsampler}. Replaces any existing image decoder. Defaults to * {@link Downsampler#AT_LEAST}. Will be ignored if the data represented by the model is a video. This replaces any * previous calls to {@link #imageDecoder(ResourceDecoder)} and {@link #decoder(ResourceDecoder)} with default * decoders with the appropriate options set. * * @see #imageDecoder * * @param downsampler The downsampler * @return This RequestBuilder */ private BitmapRequestBuilder<ModelType, TranscodeType> downsample(Downsampler downsampler) { this.downsampler = downsampler; imageDecoder = new StreamBitmapDecoder(downsampler, bitmapPool, decodeFormat); super.decoder(new ImageVideoBitmapDecoder(imageDecoder, videoDecoder)); return this; }
/** * Sets the {@link DownsampleStrategy} to use when decoding {@link Bitmap Bitmaps} using * {@link Downsampler}. */ public RequestOptions downsample(@NonNull DownsampleStrategy strategy) { return set(Downsampler.DOWNSAMPLE_STRATEGY, Preconditions.checkNotNull(strategy)); }
/** * Disables the use of {@link android.graphics.Bitmap.Config#HARDWARE} in {@link Downsampler} to * avoid errors caused by inspecting Bitmap pixels, drawing with hardware support disabled, * drawing to {@link android.graphics.Canvas}s backed by {@link Bitmap}s etc. * * <p>It's almost never safe to set {@link Downsampler#ALLOW_HARDWARE_CONFIG} to {@code true} so * we only provide a way to disable hardware configs entirely. If no option is set for * {@link Downsampler#ALLOW_HARDWARE_CONFIG}, Glide will set the value per request based on * whether or not a {@link Transformation} is applied and if one is, the type of * {@link Transformation} applied. Built in transformations like {@link FitCenter} and * {@link com.bumptech.glide.load.resource.bitmap.DownsampleStrategy.CenterOutside} can safely use * {@link android.graphics.Bitmap.Config#HARDWARE} because they can be entirely replaced by * scaling within {@link Downsampler}. {@link Transformation}s like {@link #circleCrop()} that * can't be replicated by {@link Downsampler} cannot use {@link Bitmap.Config#HARDWARE} because * {@link android.graphics.Bitmap.Config#HARDWARE} cannot be drawn to * {@link android.graphics.Canvas}s, which is required by most {@link Transformation}s. */ @CheckResult public RequestOptions disallowHardwareConfig() { return set(Downsampler.ALLOW_HARDWARE_CONFIG, false); }
/** * Sets the {@link DownsampleStrategy} to use when decoding {@link Bitmap Bitmaps} using * {@link Downsampler}. * * <p>This is a component option specific to {@link Downsampler}. If the defautlt Bitmap decoder * is replaced or skipped because of your configuration, this option may be ignored. */ @CheckResult public RequestOptions downsample(@NonNull DownsampleStrategy strategy) { return set(Downsampler.DOWNSAMPLE_STRATEGY, Preconditions.checkNotNull(strategy)); }
/** * Load images at a size near the size of the target using {@link Downsampler#AT_LEAST}. * * @see #downsample(Downsampler) * * @return This RequestBuilder */ public BitmapRequestBuilder<ModelType, TranscodeType> approximate() { return downsample(Downsampler.AT_LEAST); }
/** * Load images at their original size using {@link Downsampler#NONE}. * * @see #downsample(Downsampler) * * @return This RequestBuilder */ public BitmapRequestBuilder<ModelType, TranscodeType> asIs() { return downsample(Downsampler.NONE); }