Skip to content

Commit

Permalink
Merge pull request #758 from mullender/glide-issue-738
Browse files Browse the repository at this point in the history
fix for issue #738 Some images simply do not download (Black image) -…
  • Loading branch information
sjudd committed Nov 24, 2015
2 parents aa751f6 + 59f3d9c commit ff7850c
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -400,17 +400,19 @@ private static Bitmap decodeStream(InputStream is, BitmapFactory.Options options
int sourceHeight = options.outHeight;
String outMimeType = options.outMimeType;
final Bitmap result;
TransformationUtils.getBitmapDrawableLock().lock();
try {
result = BitmapFactory.decodeStream(is, null, options);
} catch (IllegalArgumentException e) {
throw newIoExceptionForInBitmapAssertion(e, sourceWidth, sourceHeight, outMimeType, options);
} finally {
TransformationUtils.getBitmapDrawableLock().unlock();
}

if (options.inJustDecodeBounds) {
is.reset();

}

return result;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
import com.bumptech.glide.util.Preconditions;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
* A class with methods to efficiently resize Bitmaps.
*/
Expand All @@ -30,6 +35,17 @@ public final class TransformationUtils {
private static final int CIRCLE_CROP_PAINT_FLAGS = PAINT_FLAGS | Paint.ANTI_ALIAS_FLAG;
private static final Paint CIRCLE_CROP_SHAPE_PAINT = new Paint(CIRCLE_CROP_PAINT_FLAGS);
private static final Paint CIRCLE_CROP_BITMAP_PAINT;
/**
* https://github.com/bumptech/glide/issues/738 On some devices (Moto X with android 5.1) bitmap
* drawing is not thread safe.
* This lock only locks for these specific devices. For other types of devices the lock is always
* available and therefore does not impact performance
*/
private static final Lock BITMAP_DRAWABLE_LOCK = "XT1097".equals(Build.MODEL)
&& Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP_MR1
? new ReentrantLock()
: new NoLock();

static {
CIRCLE_CROP_BITMAP_PAINT = new Paint(CIRCLE_CROP_PAINT_FLAGS);
CIRCLE_CROP_BITMAP_PAINT.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
Expand All @@ -39,6 +55,11 @@ private TransformationUtils() {
// Utility class.
}


public static Lock getBitmapDrawableLock() {
return BITMAP_DRAWABLE_LOCK;
}

/**
* A potentially expensive operation to crop the given Bitmap so that it fills the given
* dimensions. This operation is significantly less expensive in terms of memory if a mutable
Expand Down Expand Up @@ -74,9 +95,7 @@ public static Bitmap centerCrop(@NonNull BitmapPool pool, @NonNull Bitmap inBitm
// We don't add or remove alpha, so keep the alpha setting of the Bitmap we were given.
TransformationUtils.setAlpha(inBitmap, result);

Canvas canvas = new Canvas(result);
canvas.drawBitmap(inBitmap, m, DEFAULT_PAINT);
clear(canvas);
applyMatrix(inBitmap, result, m);
return result;
}

Expand Down Expand Up @@ -129,11 +148,9 @@ public static Bitmap fitCenter(@NonNull BitmapPool pool, @NonNull Bitmap inBitma
Log.v(TAG, "minPct: " + minPercentage);
}

Canvas canvas = new Canvas(toReuse);
Matrix matrix = new Matrix();
matrix.setScale(minPercentage, minPercentage);
canvas.drawBitmap(inBitmap, matrix, DEFAULT_PAINT);
clear(canvas);
applyMatrix(inBitmap, toReuse, matrix);

return toReuse;
}
Expand Down Expand Up @@ -266,10 +283,7 @@ public static Bitmap rotateImageExif(@NonNull BitmapPool pool, @NonNull Bitmap i

matrix.postTranslate(-newRect.left, -newRect.top);

final Canvas canvas = new Canvas(result);
canvas.drawBitmap(inBitmap, matrix, DEFAULT_PAINT);
clear(canvas);

applyMatrix(inBitmap, result, matrix);
return result;
}

Expand Down Expand Up @@ -301,15 +315,20 @@ public static Bitmap circleCrop(@NonNull BitmapPool pool, @NonNull Bitmap inBitm

Bitmap result = pool.get(destWidth, destHeight, getSafeConfig(toTransform));
setAlphaIfAvailable(result, true /*hasAlpha*/);
Canvas canvas = new Canvas(result);

// Draw a circle
canvas.drawCircle(destRect.left + radius, destRect.top + radius, radius,
CIRCLE_CROP_SHAPE_PAINT);

// Draw the bitmap in the circle
canvas.drawBitmap(toTransform, srcRect, destRect, CIRCLE_CROP_BITMAP_PAINT);
clear(canvas);
BITMAP_DRAWABLE_LOCK.lock();
try {
Canvas canvas = new Canvas(result);
// Draw a circle
canvas.drawCircle(destRect.left + radius, destRect.top + radius, radius,
CIRCLE_CROP_SHAPE_PAINT);
// Draw the bitmap in the circle
canvas.drawBitmap(toTransform, srcRect, destRect, CIRCLE_CROP_BITMAP_PAINT);
clear(canvas);
} finally {
BITMAP_DRAWABLE_LOCK.unlock();
}

if (!toTransform.equals(inBitmap)) {
pool.put(toTransform);
Expand Down Expand Up @@ -361,10 +380,15 @@ public static Bitmap roundedCorners(@NonNull BitmapPool pool, @NonNull Bitmap in
paint.setAntiAlias(true);
paint.setShader(shader);
RectF rect = new RectF(0, 0, result.getWidth(), result.getHeight());
Canvas canvas = new Canvas(result);
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
canvas.drawRoundRect(rect, roundingRadius, roundingRadius, paint);
clear(canvas);
BITMAP_DRAWABLE_LOCK.lock();
try {
Canvas canvas = new Canvas(result);
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
canvas.drawRoundRect(rect, roundingRadius, roundingRadius, paint);
clear(canvas);
} finally {
BITMAP_DRAWABLE_LOCK.unlock();
}

if (!toTransform.equals(inBitmap)) {
pool.put(toTransform);
Expand All @@ -382,6 +406,18 @@ private static Bitmap.Config getSafeConfig(Bitmap bitmap) {
return bitmap.getConfig() != null ? bitmap.getConfig() : Bitmap.Config.ARGB_8888;
}

private static void applyMatrix(@NonNull Bitmap inBitmap, @NonNull Bitmap targetBitmap,
Matrix matrix) {
BITMAP_DRAWABLE_LOCK.lock();
try {
Canvas canvas = new Canvas(targetBitmap);
canvas.drawBitmap(inBitmap, matrix, DEFAULT_PAINT);
clear(canvas);
} finally {
BITMAP_DRAWABLE_LOCK.unlock();
}
}

// Visible for testing.
static void initializeMatrixForRotation(int exifOrientation, Matrix matrix) {
switch (exifOrientation) {
Expand Down Expand Up @@ -413,4 +449,37 @@ static void initializeMatrixForRotation(int exifOrientation, Matrix matrix) {
// Do nothing.
}
}

private static final class NoLock implements Lock {
@Override
public void lock() {
// do nothing
}

@Override
public void lockInterruptibly() throws InterruptedException {
// do nothing
}

@Override
public boolean tryLock() {
return true;
}

@Override
public boolean tryLock(long time, @NonNull TimeUnit unit) throws InterruptedException {
return true;
}

@Override
public void unlock() {
// do nothing
}

@NonNull
@Override
public Condition newCondition() {
throw new UnsupportedOperationException("Should not be called");
}
}
}

0 comments on commit ff7850c

Please sign in to comment.