Skip to content

Commit 2aa8335

Browse files
committed
Update
1 parent 813b9a7 commit 2aa8335

1 file changed

Lines changed: 49 additions & 31 deletions

File tree

app/src/main/java/com/omarea/common/ui/FastBlurUtility.java

Lines changed: 49 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111

1212
public class FastBlurUtility {
1313

14-
// Tỉ lệ thu nhỏ ảnh để xử lý nhanh
1514
private static final float SCALE_FACTOR = 0.10f;
1615
private static final int BLUR_RADIUS = 8;
1716

@@ -24,45 +23,32 @@ public static Bitmap getBlurBackgroundDrawer(Activity activity) {
2423

2524
Bitmap blurredBmp = startBlurBackground(bmp);
2625

27-
// Giải phóng bitmap chụp màn hình gốc sau khi dùng xong
2826
if (bmp != blurredBmp && !bmp.isRecycled()) {
2927
bmp.recycle();
3028
}
3129
return blurredBmp;
3230
}
3331

3432
/**
35-
* Quy trình xử lý: Thu nhỏ -> Làm mờ -> Phóng to & Nhuộm tối (Dim)
33+
* Quy trình xử lý: Thu nhỏ -> Làm mờ -> Phóng to & Dim
3634
*/
3735
public static Bitmap startBlurBackground(Bitmap bkg) {
3836
if (bkg == null || bkg.isRecycled()) return null;
3937

40-
// 1. Tính toán kích thước thu nhỏ
41-
int scaledW = Math.round(bkg.getWidth() * SCALE_FACTOR);
42-
int scaledH = Math.round(bkg.getHeight() * SCALE_FACTOR);
38+
// Đảm bảo kích thước tối thiểu 16px để tránh ảnh bị quá nhỏ gây mờ đục hoặc hỏng layout
39+
int width = Math.max(Math.round(bkg.getWidth() * SCALE_FACTOR), 16);
40+
int height = Math.max(Math.round(bkg.getHeight() * SCALE_FACTOR), 16);
4341

44-
// Đảm bảo kích thước ảnh sau thu nhỏ không được nhỏ hơn (BLUR_RADIUS * 2)
45-
// Điều này ngăn triệt để lỗi ArrayIndexOutOfBoundsException trong fastBlur
46-
int minSize = BLUR_RADIUS * 2;
47-
int width = Math.max(scaledW, minSize);
48-
int height = Math.max(scaledH, minSize);
49-
50-
if (width <= 0 || height <= 0) return null;
51-
52-
// 2. Thu nhỏ ảnh
5342
Bitmap smallBitmap = Bitmap.createScaledBitmap(bkg, width, height, true);
5443

55-
// 3. Làm mờ bằng thuật toán StackBlur gốc
5644
Bitmap blurred = fastBlur(smallBitmap, BLUR_RADIUS);
5745

58-
// Giải phóng smallBitmap tạm thời để tránh Memory Leak
5946
if (smallBitmap != null && smallBitmap != blurred && !smallBitmap.isRecycled()) {
6047
smallBitmap.recycle();
6148
}
6249

6350
if (blurred == null) return null;
6451

65-
// 4. Phóng to về kích thước gốc và áp dụng bộ lọc màu tối (scaleAndDim sẽ tự recycle 'blurred')
6652
return scaleAndDim(blurred, bkg.getWidth(), bkg.getHeight());
6753
}
6854

@@ -85,7 +71,7 @@ private static Bitmap takeScreenShot(Activity activity) {
8571
}
8672

8773
/**
88-
* Phóng to ảnh và áp dụng ColorMatrix để làm tối nền (Dim)
74+
* Phóng to ảnh và áp dụng ColorMatrix làm tối (Dim)
8975
*/
9076
private static Bitmap scaleAndDim(Bitmap bitmap, int targetW, int targetH) {
9177
if (bitmap == null || bitmap.isRecycled()) return null;
@@ -108,7 +94,6 @@ private static Bitmap scaleAndDim(Bitmap bitmap, int targetW, int targetH) {
10894
Rect dst = new Rect(0, 0, targetW, targetH);
10995
canvas.drawBitmap(bitmap, src, dst, paint);
11096

111-
// Giải phóng bitmap tạm sau khi vẽ xong
11297
if (!bitmap.isRecycled()) {
11398
bitmap.recycle();
11499
}
@@ -117,7 +102,7 @@ private static Bitmap scaleAndDim(Bitmap bitmap, int targetW, int targetH) {
117102
}
118103

119104
/**
120-
* Thuật toán StackBlur NGUYÊN BẢN GỐC (Giữ nguyên 100% phép tính toán học)
105+
* Thuật toán StackBlur đã sửa lỗi hổng chỉ số mảng & giữ nguyên 100% chất lượng Blur gốc
121106
*/
122107
private static Bitmap fastBlur(Bitmap sentBitmap, int radius) {
123108
if (sentBitmap == null || sentBitmap.isRecycled()) return null;
@@ -145,13 +130,14 @@ private static Bitmap fastBlur(Bitmap sentBitmap, int radius) {
145130
int[] r = new int[wh];
146131
int[] g = new int[wh];
147132
int[] b = new int[wh];
148-
int rsum, gsum, bsum, x, y, i, p, yp, yi, yw;
133+
int rsum, gsum, bsum, x, y, i, p, yi, yw;
149134
int[] vmin = new int[Math.max(w, h)];
150135

151136
int divsum = (div + 1) >> 1;
152137
divsum *= divsum;
153-
int[] dv = new int[256 * divsum];
154-
for (i = 0; i < 256 * divsum; i++) {
138+
int maxDv = 256 * divsum;
139+
int[] dv = new int[maxDv];
140+
for (i = 0; i < maxDv; i++) {
155141
dv[i] = (i / divsum);
156142
}
157143

@@ -165,6 +151,7 @@ private static Bitmap fastBlur(Bitmap sentBitmap, int radius) {
165151
int routsum, goutsum, boutsum;
166152
int rinsum, ginsum, binsum;
167153

154+
// --- LƯỢT 1: LÀM MỜ CHIỀU NGANG ---
168155
for (y = 0; y < h; y++) {
169156
rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
170157
for (i = -radius; i <= radius; i++) {
@@ -190,53 +177,69 @@ private static Bitmap fastBlur(Bitmap sentBitmap, int radius) {
190177
stackpointer = radius;
191178

192179
for (x = 0; x < w; x++) {
193-
r[yi] = dv[rsum];
194-
g[yi] = dv[gsum];
195-
b[yi] = dv[bsum];
180+
r[yi] = dv[Math.min(Math.max(rsum, 0), maxDv - 1)];
181+
g[yi] = dv[Math.min(Math.max(gsum, 0), maxDv - 1)];
182+
b[yi] = dv[Math.min(Math.max(bsum, 0), maxDv - 1)];
183+
196184
rsum -= routsum;
197185
gsum -= goutsum;
198186
bsum -= boutsum;
187+
199188
stackstart = stackpointer - radius + div;
200189
sir = stack[stackstart % div];
190+
201191
routsum -= sir[0];
202192
goutsum -= sir[1];
203193
boutsum -= sir[2];
194+
204195
if (y == 0) vmin[x] = Math.min(x + radius + 1, wm);
205196
p = pix[yw + vmin[x]];
197+
206198
sir[0] = (p & 0xff0000) >> 16;
207199
sir[1] = (p & 0x00ff00) >> 8;
208200
sir[2] = (p & 0x0000ff);
201+
209202
rinsum += sir[0];
210203
ginsum += sir[1];
211204
binsum += sir[2];
205+
212206
rsum += rinsum;
213207
gsum += ginsum;
214208
bsum += binsum;
209+
215210
stackpointer = (stackpointer + 1) % div;
216211
sir = stack[(stackpointer) % div];
212+
217213
routsum += sir[0];
218214
goutsum += sir[1];
219215
boutsum += sir[2];
216+
220217
rinsum -= sir[0];
221218
ginsum -= sir[1];
222219
binsum -= sir[2];
220+
223221
yi++;
224222
}
225223
yw += w;
226224
}
225+
226+
// --- LƯỢT 2: LÀM MỜ CHIỀU DỌC ---
227227
for (x = 0; x < w; x++) {
228228
rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
229-
yp = -radius * w;
229+
230+
// ĐÃ SỬA LỖI: Khởi tạo stack chuẩn xác bằng Math.min(hm, Math.max(i, 0)) * w + x
230231
for (i = -radius; i <= radius; i++) {
231-
yi = Math.max(0, yp) + x;
232+
yi = Math.min(hm, Math.max(i, 0)) * w + x;
232233
sir = stack[i + radius];
233234
sir[0] = r[yi];
234235
sir[1] = g[yi];
235236
sir[2] = b[yi];
237+
236238
rbs = r1 - Math.abs(i);
237239
rsum += r[yi] * rbs;
238240
gsum += g[yi] * rbs;
239241
bsum += b[yi] * rbs;
242+
240243
if (i > 0) {
241244
rinsum += sir[0];
242245
ginsum += sir[1];
@@ -246,42 +249,57 @@ private static Bitmap fastBlur(Bitmap sentBitmap, int radius) {
246249
goutsum += sir[1];
247250
boutsum += sir[2];
248251
}
249-
if (i < hm) yp += w;
250252
}
253+
251254
yi = x;
252255
stackpointer = radius;
253256
for (y = 0; y < h; y++) {
254-
pix[yi] = (0xff000000 & pix[yi]) | (dv[rsum] << 16) | (dv[gsum] << 8) | dv[bsum];
257+
pix[yi] = (0xff000000 & pix[yi])
258+
| (dv[Math.min(Math.max(rsum, 0), maxDv - 1)] << 16)
259+
| (dv[Math.min(Math.max(gsum, 0), maxDv - 1)] << 8)
260+
| dv[Math.min(Math.max(bsum, 0), maxDv - 1)];
261+
255262
rsum -= routsum;
256263
gsum -= goutsum;
257264
bsum -= boutsum;
265+
258266
stackstart = stackpointer - radius + div;
259267
sir = stack[stackstart % div];
268+
260269
routsum -= sir[0];
261270
goutsum -= sir[1];
262271
boutsum -= sir[2];
272+
263273
if (x == 0) vmin[y] = Math.min(y + r1, hm) * w;
264274
p = x + vmin[y];
275+
265276
sir[0] = r[p];
266277
sir[1] = g[p];
267278
sir[2] = b[p];
279+
268280
rinsum += sir[0];
269281
ginsum += sir[1];
270282
binsum += sir[2];
283+
271284
rsum += rinsum;
272285
gsum += ginsum;
273286
bsum += binsum;
287+
274288
stackpointer = (stackpointer + 1) % div;
275289
sir = stack[stackpointer];
290+
276291
routsum -= sir[0];
277292
goutsum -= sir[1];
278293
boutsum -= sir[2];
294+
279295
rinsum -= sir[0];
280296
ginsum -= sir[1];
281297
binsum -= sir[2];
298+
282299
yi += w;
283300
}
284301
}
302+
285303
bitmap.setPixels(pix, 0, w, 0, 0, w, h);
286304
return bitmap;
287305
}

0 commit comments

Comments
 (0)