55import android .graphics .Canvas ;
66import android .graphics .ColorMatrix ;
77import android .graphics .ColorMatrixColorFilter ;
8+ import android .graphics .Matrix ;
89import android .graphics .Paint ;
9- import android .graphics .Rect ;
1010import android .os .Handler ;
1111import android .os .Looper ;
1212import android .view .View ;
1616
1717public class FastBlurUtility {
1818
19- private static final float SCALE_FACTOR = 0.10f ;
19+ private static final float SCALE_FACTOR = 0.125f ; // Thu nhỏ 8 lần (giống code cũ 0.10f)
2020 private static final int BLUR_RADIUS = 8 ;
2121
22- // Executor để xử lý các tác vụ nặng ngoài UI Thread
2322 private static final ExecutorService executor = Executors .newSingleThreadExecutor ();
2423 private static final Handler mainHandler = new Handler (Looper .getMainLooper ());
2524
@@ -31,90 +30,89 @@ public interface BlurCallback {
3130 * Phương thức chính: Chụp và làm mờ không gây lag UI
3231 */
3332 public static void getBlurBackgroundAsync (Activity activity , BlurCallback callback ) {
34- // 1. Chụp màn hình phải thực hiện trên UI Thread
35- Bitmap screenshot = takeScreenShot (activity );
33+ // 1. Chụp màn hình ở dạng THU NHỎ ngay trên UI Thread (Rất nhanh, < 16ms)
34+ Bitmap smallBitmap = takeSmallScreenshot (activity );
3635
37- if (screenshot == null ) {
36+ if (smallBitmap == null ) {
3837 callback .onBlurCompleted (null );
3938 return ;
4039 }
4140
42- // 2. Đẩy việc xử lý làm mờ vào Background Thread
41+ // 2. Đẩy việc xử lý nặng (Blur + Dim) vào Background Thread
4342 executor .execute (() -> {
44- Bitmap blurred = startBlurProcess (screenshot );
43+ // Làm mờ trên ảnh nhỏ
44+ Bitmap blurred = fastBlur (smallBitmap , BLUR_RADIUS );
4545
46- // 3. Trả kết quả về Main Thread qua Callback
47- mainHandler .post (() -> callback .onBlurCompleted (blurred ));
48- });
49- }
50-
51- private static Bitmap startBlurProcess (Bitmap bkg ) {
52- if (bkg == null || bkg .isRecycled ()) return null ;
53-
54- int originWidth = bkg .getWidth ();
55- int originHeight = bkg .getHeight ();
56-
57- // Tính toán kích thước thu nhỏ
58- int width = Math .round (originWidth * SCALE_FACTOR );
59- int height = Math .round (originHeight * SCALE_FACTOR );
60-
61- if (width <= 0 || height <= 0 ) return bkg ;
62-
63- // Thu nhỏ ảnh
64- Bitmap smallBitmap = Bitmap .createScaledBitmap (bkg , width , height , true );
65-
66- // Giải phóng ảnh gốc ngay để tiết kiệm RAM
67- if (bkg != smallBitmap ) {
68- bkg .recycle ();
69- }
70-
71- // Làm mờ bằng thuật toán StackBlur
72- Bitmap blurred = fastBlur (smallBitmap , BLUR_RADIUS );
46+ // Làm tối ảnh (giống getDimmedBitmap của code cũ)
47+ Bitmap dimmed = applyDim (blurred );
48+
49+ // Phóng to ảnh bằng Matrix (giống hàm big() của code cũ)
50+ Bitmap finalBitmap = upscale (dimmed );
7351
74- // Phóng to và làm tối
75- return scaleAndDim (blurred , originWidth , originHeight );
52+ // 3. Trả kết quả về Main Thread
53+ mainHandler .post (() -> callback .onBlurCompleted (finalBitmap ));
54+ });
7655 }
7756
78- private static Bitmap takeScreenShot (Activity activity ) {
57+ /**
58+ * Chụp màn hình và thu nhỏ ngay lập tức để tiết kiệm RAM và CPU
59+ */
60+ private static Bitmap takeSmallScreenshot (Activity activity ) {
7961 try {
8062 View view = activity .getWindow ().getDecorView ();
81- if (view .getWidth () <= 0 || view .getHeight () <= 0 ) return null ;
63+ int width = view .getWidth ();
64+ int height = view .getHeight ();
65+ if (width <= 0 || height <= 0 ) return null ;
66+
67+ // Tạo bitmap nhỏ ngay từ đầu
68+ int smallW = Math .round (width * SCALE_FACTOR );
69+ int smallH = Math .round (height * SCALE_FACTOR );
8270
83- // Dùng RGB_565 để tiết kiệm 50% bộ nhớ so với ARGB_8888 (phù hợp SDK 23+)
84- Bitmap bitmap = Bitmap .createBitmap (view .getWidth (), view .getHeight (), Bitmap .Config .ARGB_8888 );
71+ Bitmap bitmap = Bitmap .createBitmap (smallW , smallH , Bitmap .Config .ARGB_8888 );
8572 Canvas canvas = new Canvas (bitmap );
73+
74+ // Scale canvas để khi view.draw nó tự thu nhỏ lại
75+ canvas .scale (SCALE_FACTOR , SCALE_FACTOR );
8676 view .draw (canvas );
77+
8778 return bitmap ;
8879 } catch (Exception e ) {
8980 return null ;
9081 }
9182 }
9283
93- private static Bitmap scaleAndDim (Bitmap bitmap , int targetW , int targetH ) {
94- Bitmap output = Bitmap .createBitmap (targetW , targetH , Bitmap .Config .ARGB_8888 );
84+ /**
85+ * Làm tối ảnh (Thay thế getDimmedBitmap)
86+ */
87+ private static Bitmap applyDim (Bitmap bitmap ) {
88+ Bitmap output = Bitmap .createBitmap (bitmap .getWidth (), bitmap .getHeight (), Bitmap .Config .ARGB_8888 );
9589 Canvas canvas = new Canvas (output );
90+ Paint paint = new Paint (Paint .ANTI_ALIAS_FLAG );
9691
97- Paint paint = new Paint (Paint .FILTER_BITMAP_FLAG | Paint .ANTI_ALIAS_FLAG );
98-
99- // Giảm độ sáng 20%
10092 ColorMatrix cm = new ColorMatrix ();
101- float contrast = 0.8f ;
93+ float contrast = 0.80f ; // Giảm độ sáng giống code cũ
10294 cm .setScale (contrast , contrast , contrast , 1.0f );
10395 paint .setColorFilter (new ColorMatrixColorFilter (cm ));
104-
105- Rect src = new Rect (0 , 0 , bitmap .getWidth (), bitmap .getHeight ());
106- Rect dst = new Rect (0 , 0 , targetW , targetH );
107- canvas .drawBitmap (bitmap , src , dst , paint );
108-
109- if (!bitmap .isRecycled ()) {
110- bitmap .recycle ();
111- }
112-
96+
97+ canvas .drawBitmap (bitmap , 0 , 0 , paint );
98+ bitmap .recycle ();
11399 return output ;
114100 }
115101
116102 /**
117- * Thuật toán StackBlur tối ưu hóa
103+ * Phóng to ảnh (Thay thế hàm big())
104+ */
105+ private static Bitmap upscale (Bitmap bitmap ) {
106+ Matrix matrix = new Matrix ();
107+ // Phóng to lại 8 lần (vì lúc đầu đã thu nhỏ 0.125)
108+ float scaleUp = 1f / SCALE_FACTOR ;
109+ matrix .postScale (scaleUp , scaleUp );
110+
111+ return Bitmap .createBitmap (bitmap , 0 , 0 , bitmap .getWidth (), bitmap .getHeight (), matrix , true );
112+ }
113+
114+ /**
115+ * Thuật toán StackBlur (Giữ nguyên từ code cũ của bạn)
118116 */
119117 private static Bitmap fastBlur (Bitmap sentBitmap , int radius ) {
120118 Bitmap bitmap = sentBitmap .copy (sentBitmap .getConfig (), true );
@@ -165,11 +163,9 @@ private static Bitmap fastBlur(Bitmap sentBitmap, int radius) {
165163 rsum += sir [0 ] * rbs ;
166164 gsum += sir [1 ] * rbs ;
167165 bsum += sir [2 ] * rbs ;
168- if (i > 0 ) {
169- rinsum += sir [0 ]; ginsum += sir [1 ]; binsum += sir [2 ];
170- } else {
171- routsum += sir [0 ]; goutsum += sir [1 ]; boutsum += sir [2 ];
172- }
166+ if (i > 0 ) rinsum += sir [0 ]; else routsum += sir [0 ];
167+ if (i > 0 ) ginsum += sir [1 ]; else goutsum += sir [1 ];
168+ if (i > 0 ) binsum += sir [2 ]; else boutsum += sir [2 ];
173169 }
174170 stackpointer = radius ;
175171 for (x = 0 ; x < w ; x ++) {
@@ -197,14 +193,12 @@ private static Bitmap fastBlur(Bitmap sentBitmap, int radius) {
197193 for (i = -radius ; i <= radius ; i ++) {
198194 yi = Math .max (0 , yp ) + x ;
199195 sir = stack [i + radius ];
200- sir [0 ] = r [yi ]; sir [1 ] = g [yi ]; sir [2 ] = b [yi ];
196+ sir [0 ] = r [yi ]; sir [1 ] = g [yi ]; sir [2 ] = b [2 ];
201197 rbs = r1 - Math .abs (i );
202198 rsum += r [yi ] * rbs ; gsum += g [yi ] * rbs ; bsum += b [yi ] * rbs ;
203- if (i > 0 ) {
204- rinsum += sir [0 ]; ginsum += sir [1 ]; binsum += sir [2 ];
205- } else {
206- routsum += sir [0 ]; goutsum += sir [1 ]; boutsum += sir [2 ];
207- }
199+ if (i > 0 ) rinsum += sir [0 ]; else routsum += sir [0 ];
200+ if (i > 0 ) ginsum += sir [1 ]; else goutsum += sir [1 ];
201+ if (i > 0 ) binsum += sir [2 ]; else boutsum += sir [2 ];
208202 if (i < hm ) yp += w ;
209203 }
210204 yi = x ;
@@ -228,7 +222,7 @@ private static Bitmap fastBlur(Bitmap sentBitmap, int radius) {
228222 }
229223 }
230224 bitmap .setPixels (pix , 0 , w , 0 , 0 , w , h );
231- sentBitmap .recycle (); // Giải phóng bitmap cũ sau khi copy
225+ sentBitmap .recycle ();
232226 return bitmap ;
233227 }
234228}
0 commit comments