Skip to content

Commit

Permalink
Correct handling of width/height keys in LBP
Browse files Browse the repository at this point in the history
Using object keys lets us hash on both width
width and height without giving up the ability to
handle collisions.
  • Loading branch information
Sam Judd committed Sep 4, 2013
1 parent e6f1e3d commit 77e5613
Showing 1 changed file with 76 additions and 19 deletions.
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package com.bumptech.glide.resize.bitmap_recycle;

import android.graphics.Bitmap;
import android.util.SparseArray;
import com.bumptech.glide.util.Log;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;

public class LruBitmapPool implements BitmapPool {
private final GroupedBitmapLinkedMap pool = new GroupedBitmapLinkedMap();
Expand All @@ -19,10 +22,10 @@ public LruBitmapPool(int maxSize) {

@Override
public synchronized boolean put(Bitmap bitmap) {
final int key = getKey(bitmap);
final int size = getSize(bitmap);

pool.put(key, bitmap);
pool.put(bitmap);

currentSize += size;
evict();

Expand All @@ -37,8 +40,7 @@ private void evict() {

@Override
public synchronized Bitmap get(int width, int height) {
final int sizeKey = getKey(width, height);
final Bitmap result = pool.get(sizeKey);
final Bitmap result = pool.get(width, height);
if (result == null) {
Log.d("LBP: missing bitmap for width=" + width + " height=" + height);
} else {
Expand All @@ -48,14 +50,6 @@ public synchronized Bitmap get(int width, int height) {
return result;
}

private static int getKey(Bitmap bitmap) {
return getKey(bitmap.getWidth(), bitmap.getHeight());
}

private static int getKey(int width, int height) {
return width >= height ? width * width + width + height : width + height * height;
}

private static int getSize(Bitmap bitmap) {
return bitmap.getHeight() * bitmap.getWidth();
}
Expand All @@ -70,25 +64,87 @@ private static int getSize(Bitmap bitmap) {
* of that size are present. We do not count addition or removal of bitmaps as an access.
*/
private static class GroupedBitmapLinkedMap {
private final SparseArray<LinkedEntry> keyToEntry = new SparseArray<LinkedEntry>();
private final Map<Key, LinkedEntry> keyToEntry = new HashMap<Key, LinkedEntry>();
private final LinkedEntry head = new LinkedEntry();
private final KeyPool keyPool = new KeyPool();

private static class KeyPool {
private static final int MAX_SIZE = 20;

private Queue<Key> keyPool = new LinkedList<Key>();

public Key get(int width, int height) {
Key result = keyPool.poll();
if (result == null) {
result = new Key();
}
result.init(width, height);
return result;
}

public void offer(Key key) {
if (keyPool.size() <= MAX_SIZE) {
keyPool.offer(key);
}
}
}

private static class Key {
private int width;
private int height;

public void init(int width, int height) {
this.width = width;
this.height = height;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

Key key = (Key) o;

if (height != key.height) return false;
if (width != key.width) return false;

return true;
}

@Override
public int hashCode() {
int result = width;
result = 31 * result + height;
return result;
}
}

public void put(Bitmap bitmap) {
final Key key = keyPool.get(bitmap.getWidth(), bitmap.getHeight());

public void put(int key, Bitmap bitmap) {
LinkedEntry entry = keyToEntry.get(key);
if (entry == null) {
entry = new LinkedEntry(key);
makeTail(entry);
keyToEntry.put(key, entry);
} else {
keyPool.offer(key);
}

entry.add(bitmap);
}

public Bitmap get(int key) {
public Bitmap get(int width, int height) {
final Key key = keyPool.get(width, height);

LinkedEntry entry = keyToEntry.get(key);
if (entry == null) {
entry = new LinkedEntry(key);
keyToEntry.put(key, entry);
} else {
keyPool.offer(key);
}

makeHead(entry);

return entry.removeLast();
Expand All @@ -108,6 +164,7 @@ public Bitmap removeLast() {
//large sizes
removeEntry(last);
keyToEntry.remove(last.key);
keyPool.offer(last.key);
}

last = last.prev;
Expand Down Expand Up @@ -144,16 +201,16 @@ private static void removeEntry(LinkedEntry entry) {

private static class LinkedEntry {
private List<Bitmap> value;
private final int key;
private final Key key;
LinkedEntry next;
LinkedEntry prev;

//head only
public LinkedEntry() {
this(-1);
this(null);
}

public LinkedEntry(int key) {
public LinkedEntry(Key key) {
next = prev = this;
this.key = key;
}
Expand Down

0 comments on commit 77e5613

Please sign in to comment.