CodeNewbie Community 🌱

Flockkki
Flockkki

Posted on

Learning from My Bitmap Blunder: Adding a Sepia Filter to BoothCool

Hey everyone, I'm new to the CodeNewbie Community and super excited to share a bit about my journey as a developer for BoothCool, an Android app for clicking photos with filters, I help manage and build. My name's Flock, and I wear a couple of hats, from site management to diving into the codebase for our app. I thought I'd share a recent experience where I learned something new while working on a photo filter feature for BoothCool, including a mistake that had me scratching my head for longer than I'd like to admit.

So, BoothCool app is all about letting users capture and edit photos with cool effects, kind of like a portable photo booth. Recently, I was tasked with adding a new filter to our app, specifically a sepia effect, because users were asking for that vintage vibe. I figured it'd be straightforward, just apply a color matrix to the bitmap and call it a day. I'm working in Java for our Android app, and Android's ColorMatrix class seemed like the perfect tool.

Here's the code I started with to apply the sepia filter to a Bitmap in our image processing module:

public Bitmap applySepiaFilter(Bitmap source) {
int width = source.getWidth();
int height = source.getHeight();
Bitmap output = Bitmap.createBitmap(width, height, source.getConfig());
Canvas canvas = new Canvas(output);
Paint paint = new Paint();
ColorMatrix colorMatrix = new ColorMatrix();
colorMatrix.set(new float[] {
0.393f, 0.769f, 0.189f, 0, 0,
0.349f, 0.686f, 0.168f, 0, 0,
0.272f, 0.534f, 0.131f, 0, 0,
0, 0, 0, 1, 0
});
ColorMatrixColorFilter filter = new ColorMatrixColorFilter(colorMatrix);
paint.setColorFilter(filter);
canvas.drawBitmap(source, 0, 0, paint);
return output;
}

This code creates a new Bitmap, sets up a Canvas to draw on it, and applies a ColorMatrix to transform the RGB values for that sepia tone. I found the matrix values online, which are supposed to adjust red, green, and blue channels to give that brownish, old-timey look. I hooked this up to our app's filter pipeline, where users can select filters from a menu, and tested it on my emulator.

At first, it seemed to work. The image got that warm, vintage feel. But then I noticed a huge problem: the app was crashing on some older devices our users still have, like those running Android 6.0. I dug into the logs and saw an OutOfMemoryError. Turns out, my mistake was not recycling the source Bitmap after creating the output. On newer devices with more RAM, it was fine, but older ones couldn't handle the memory load, especially with larger images.

I felt pretty dumb because I know Bitmaps in Android are memory hogs, but I got so caught up in getting the filter right that I forgot to manage resources properly. Here's how I fixed it:

public Bitmap applySepiaFilter(Bitmap source) {
if (source == null) return null;
int width = source.getWidth();
int height = source.getHeight();
Bitmap output = Bitmap.createBitmap(width, height, source.getConfig());
Canvas canvas = new Canvas(output);
Paint paint = new Paint();
ColorMatrix colorMatrix = new ColorMatrix();
colorMatrix.set(new float[] {
0.393f, 0.769f, 0.189f, 0, 0,
0.349f, 0.686f, 0.168f, 0, 0,
0.272f, 0.534f, 0.131f, 0, 0,
0, 0, 0, 1, 0
});
ColorMatrixColorFilter filter = new ColorMatrixColorFilter(colorMatrix);
paint.setColorFilter(filter);
canvas.drawBitmap(source, 0, 0, paint);
if (source != output && !source.isRecycled()) {
source.recycle();
}
return output;
}

I added a check to recycle the source Bitmap if it's not the same as the output and hasn't already been recycled. This cleared up the crashes on older devices, and I added a null check for good measure to avoid any weird edge cases. Testing it again, the filter worked smoothly, and the app's memory usage was way better.

Another thing I learned was to test on a wider range of devices earlier. I got lazy and only used my Pixel emulator at first, which has plenty of resources. Now I make sure to spin up a couple of older Android versions in the emulator before calling anything done. It was a humbling reminder that real-world users have all sorts of devices, and I can't just assume everyone's on the latest hardware.

Working on BoothCool has been a blast, but it's these kinds of mistakes that keep me grounded. I'm curious if anyone else here has run into similar issues with Android image processing or has tips for managing Bitmaps better. Also, if anyone's worked with photo filter apps, I'd love to hear how you handle performance for effects like these. Thanks for reading, and I'm looking forward to learning from this community.

Flock

Top comments (0)