Skip to content

Instantly share code, notes, and snippets.

@dptsolutions
Last active April 25, 2018 20:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dptsolutions/24234530484f38f80adec08f0651fe2b to your computer and use it in GitHub Desktop.
Save dptsolutions/24234530484f38f80adec08f0651fe2b to your computer and use it in GitHub Desktop.
Using RxJava 2 to tint & merge an arbitrary number of Bitmaps into a single Bitmap and display the merged bitmap into an ImageView
public class RxjavaBitmapMergeView {
SchedulersFacade schedulersFacade;
@BindView(R.id.map)
ImageView map;
@BindArray(R.array.impact_map_colors)
@ColorInt
int[] mapColors;
@BindBitmap(R.drawable.map_layer_base)
Bitmap mapBase;
Paint[] mapPaints;
CompositeDisposable disposables;
public RxjavaBitmapMergeView(@NonNull Context context) {
super(context);
initialize();
}
public RxjavaBitmapMergeView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
initialize();
}
public RxjavaBitmapMergeView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initialize();
}
private void initialize() {
ActivityComponent activityComponent = ((BaseActivity)getContext()).getActivityComponent();
schedulersFacade = activityComponent.schedulersFacade();
disposables = new CompositeDisposable();
inflate(getContext(), R.layout.view_rxjava_bitmap_merge, this);
ButterKnife.bind(this);
//Create the Paint objects for all the colors
mapPaints = new Paint[mapColors.length];
for(int i = 0; i < mapColors.length; i++) {
Paint mapPaint = new Paint();
mapPaint.setColorFilter(new PorterDuffColorFilter(mapColors[i], PorterDuff.Mode.SRC_IN));
mapPaints[i] = mapPaint;
}
//Tint the mapBase bitmap and set it to the view to start
mapBase = tintBitmap(mapBase, mapPaints[0]);
map.setImageBitmap(mapBase);
}
public void setData(@NonNull List<State> usStates) {
disposables.add(Observable.fromIterable(usStates)
.map(this::getMapBitmapForState)
.reduce((merged, next) -> {
Canvas canvas = new Canvas(merged);
canvas.drawBitmap(next, 0, 0, null);
return merged;
})
.map(statesBitmap -> {
Bitmap mergedMap = mapBase.copy(Bitmap.Config.ARGB_8888, true);
Canvas canvas = new Canvas(mergedMap);
canvas.drawBitmap(statesBitmap, 0, 0, null);
return mergedMap;
})
.subscribeOn(schedulersFacade.computation())
.observeOn(schedulersFacade.ui())
.subscribe(
mapBitmap -> {
BitmapDrawable mapDrawable = new BitmapDrawable(getResources(), mapBitmap);
Drawable imageViewDrawable = map.getDrawable();
Drawable[] layers = new Drawable[] {imageViewDrawable, mapDrawable};
TransitionDrawable td = new TransitionDrawable(layers);
map.setImageDrawable(td);
td.startTransition(1000);
},
error -> Timber.e(error, "Error setting map data"),
() -> Timber.w("We completed without emitting map data..how did this happen? Not setting map data")
));
}
private Bitmap tintBitmap(@NonNull Bitmap source, Paint paint) {
Bitmap result = Bitmap.createBitmap(getResources().getDisplayMetrics(),
source.getWidth(),
source.getHeight(),
Bitmap.Config.ARGB_8888,
true);
Canvas canvas = new Canvas(result);
canvas.drawBitmap(source, 0, 0, paint);
return result;
}
private Bitmap getMapBitmapForState(State state) {
@DrawableRes int stateResId;
switch (state.abbreviation().toUpperCase(Locale.getDefault())) {
case "AK":
stateResId = R.drawable.map_layer_ak;
break;
case "AL":
stateResId = R.drawable.map_layer_al;
break;
case "AR":
stateResId = R.drawable.map_layer_ar;
break;
case "AZ":
stateResId = R.drawable.map_layer_az;
break;
case "CA":
stateResId = R.drawable.map_layer_ca;
break;
case "CO":
stateResId = R.drawable.map_layer_co;
break;
case "CT":
stateResId = R.drawable.map_layer_ct;
break;
case "DE":
stateResId = R.drawable.map_layer_de;
break;
case "FL":
stateResId = R.drawable.map_layer_fl;
break;
case "GA":
stateResId = R.drawable.map_layer_ga;
break;
case "HI":
stateResId = R.drawable.map_layer_hi;
break;
case "IA":
stateResId = R.drawable.map_layer_ia;
break;
case "ID":
stateResId = R.drawable.map_layer_id;
break;
case "IL":
stateResId = R.drawable.map_layer_il;
break;
case "IN":
stateResId = R.drawable.map_layer_in;
break;
case "KS":
stateResId = R.drawable.map_layer_ks;
break;
case "KY":
stateResId = R.drawable.map_layer_ky;
break;
case "LA":
stateResId = R.drawable.map_layer_la;
break;
case "MA":
stateResId = R.drawable.map_layer_ma;
break;
case "MD":
stateResId = R.drawable.map_layer_md;
break;
case "ME":
stateResId = R.drawable.map_layer_me;
break;
case "MI":
stateResId = R.drawable.map_layer_mi;
break;
case "MN":
stateResId = R.drawable.map_layer_mn;
break;
case "MO":
stateResId = R.drawable.map_layer_mo;
break;
case "MS":
stateResId = R.drawable.map_layer_ms;
break;
case "MT":
stateResId = R.drawable.map_layer_mt;
break;
case "NC":
stateResId = R.drawable.map_layer_nc;
break;
case "ND":
stateResId = R.drawable.map_layer_nd;
break;
case "NE":
stateResId = R.drawable.map_layer_ne;
break;
case "NH":
stateResId = R.drawable.map_layer_nh;
break;
case "NJ":
stateResId = R.drawable.map_layer_nj;
break;
case "NM":
stateResId = R.drawable.map_layer_nm;
break;
case "NV":
stateResId = R.drawable.map_layer_nv;
break;
case "NY":
stateResId = R.drawable.map_layer_ny;
break;
case "OH":
stateResId = R.drawable.map_layer_oh;
break;
case "OK":
stateResId = R.drawable.map_layer_ok;
break;
case "OR":
stateResId = R.drawable.map_layer_or;
break;
case "PA":
stateResId = R.drawable.map_layer_pa;
break;
case "RI":
stateResId = R.drawable.map_layer_ri;
break;
case "SC":
stateResId = R.drawable.map_layer_sc;
break;
case "SD":
stateResId = R.drawable.map_layer_sd;
break;
case "TN":
stateResId = R.drawable.map_layer_tn;
break;
case "TX":
stateResId = R.drawable.map_layer_tx;
break;
case "UT":
stateResId = R.drawable.map_layer_ut;
break;
case "VA":
stateResId = R.drawable.map_layer_va;
break;
case "VT":
stateResId = R.drawable.map_layer_vt;
break;
case "WA":
stateResId = R.drawable.map_layer_wa;
break;
case "WI":
stateResId = R.drawable.map_layer_wi;
break;
case "WV":
stateResId = R.drawable.map_layer_wv;
break;
case "WY":
stateResId = R.drawable.map_layer_wy;
break;
default:
throw new IllegalArgumentException(String.format("Unknown state[%s]", state));
}
return tintBitmap(BitmapFactory.decodeResource(getResources(), stateResId),
mapPaints[state.colorIndex()]);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment