1111
1212public 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