2015-09-26 24 views
8

Cho hình ảnh có kênh alpha (độ trong suốt) Tôi muốn xóa bất kỳ khoảng trắng nào giữa ranh giới hình ảnh và hình ảnh thực tế. Điều này nên được thực hiện trong tác vụ backgound hoặc với màn hình tải, với thời gian chạy được chấp nhận để không làm tê liệt trải nghiệm người dùng.Làm thế nào để loại bỏ không gian trống xung quanh một hình ảnh trong Android?

enter image description here

Làm cách nào để đạt được kết quả này?

Trả lời

17

Tôi gặp khó khăn trong việc tìm các phương pháp hay nhất hoặc thậm chí là lời khuyên để giải quyết vấn đề của mình. Dựa trên this anwer by JannGabriel, người cắt hình ảnh bên phải và dưới cùng bằng cách giảm kích thước hình ảnh, tôi đã quản lý để tiến thêm một bước và cũng loại bỏ các khoảng trống trên cùng và bên trái, và nói chung cải thiện thời gian xây dựng. Kết quả là tốt, và tôi hiện đang sử dụng nó trong dự án của tôi. Tôi khá mới đối với lập trình Android và mọi lời khuyên về phương pháp này đều được hoan nghênh.

public static Bitmap TrimBitmap(Bitmap bmp) { 
    int imgHeight = bmp.getHeight(); 
    int imgWidth = bmp.getWidth(); 


    //TRIM WIDTH - LEFT 
    int startWidth = 0; 
    for(int x = 0; x < imgWidth; x++) { 
     if (startWidth == 0) { 
      for (int y = 0; y < imgHeight; y++) { 
       if (bmp.getPixel(x, y) != Color.TRANSPARENT) { 
        startWidth = x; 
        break; 
       } 
      } 
     } else break; 
    } 


    //TRIM WIDTH - RIGHT 
    int endWidth = 0; 
    for(int x = imgWidth - 1; x >= 0; x--) { 
     if (endWidth == 0) { 
      for (int y = 0; y < imgHeight; y++) { 
       if (bmp.getPixel(x, y) != Color.TRANSPARENT) { 
        endWidth = x; 
        break; 
       } 
      } 
     } else break; 
    } 



    //TRIM HEIGHT - TOP 
    int startHeight = 0; 
    for(int y = 0; y < imgHeight; y++) { 
     if (startHeight == 0) { 
      for (int x = 0; x < imgWidth; x++) { 
       if (bmp.getPixel(x, y) != Color.TRANSPARENT) { 
        startHeight = y; 
        break; 
       } 
      } 
     } else break; 
    } 



    //TRIM HEIGHT - BOTTOM 
    int endHeight = 0; 
    for(int y = imgHeight - 1; y >= 0; y--) { 
     if (endHeight == 0) { 
      for (int x = 0; x < imgWidth; x++) { 
       if (bmp.getPixel(x, y) != Color.TRANSPARENT) { 
        endHeight = y; 
        break; 
       } 
      } 
     } else break; 
    } 


    return Bitmap.createBitmap(
      bmp, 
      startWidth, 
      startHeight, 
      endWidth - startWidth, 
      endHeight - startHeight 
    ); 

} 

Giải thích: Đối với mỗi bên của hình ảnh, một for loop được điều hành để kiểm tra xem pixel không chứa màu trong suốt, trở pixel không trong suốt đầu tiên có ích phối hợp. Điều này được thực hiện việc xây dựng các tọa độ bằng cách sử dụng làm cơ số cho chiều ngược lại so với kích thước để cắt: để tìm y, quét x cho mọi y.

Để kiểm tra nơi Vertical-Top khoảng trống kết thúc, nó chạy theo các bước sau:

  1. bắt đầu là từ hàng trên cùng (y = 0)
  2. Kiểm tra tất cả các cột của hàng (x từ 0 đến imageWidth)
  3. Nếu tìm thấy pixel không trong suốt, hãy ngắt vòng lặp và lưu tọa độ y. Nếu không thì tiếp tục.
  4. Ở cuối cột, chuyển đến hàng tiếp theo (y + 1) và bắt đầu kiểm tra lại các cột. Phá vỡ nếu một điểm ảnh không trong suốt đã được tìm thấy.

Các phương thức quen thuộc được sử dụng cho các thứ nguyên khác, chỉ thay đổi hướng quét.

Khi đã nhận được 4 tọa độ cho các pixel hữu ích đầu tiên của hình ảnh, phương thức Bitmap.createBitmap được gọi, với bitmap ban đầu làm hình nền và các pixel hữu ích tọa độ giới hạn trên cùng và dưới cùng bên phải để thay đổi kích thước .

Lưu ý 1: Cần lưu ý rằng các tọa độ 0, 0 bằng Trên cùng bên trái.

Lưu ý 2: Chiều rộng và chiều cao kết thúc trong Bitmap.createBitmap bị giảm theo tọa độ tương đối bắt đầu mới, nếu không, hình ảnh mới sẽ có ranh giới bị đẩy xuống dưới cùng bên phải. Hình nó như thế này: bạn có một hình ảnh 100x100px, vì vậy với kết thúc tọa độ 100,100. Thay đổi các tọa độ bắt đầu thành 50,50 sẽ mang các tọa độ kết thúc của hình chữ nhật của bạn thành 150.150 (100 toạ độ gốc + 50 điểm bắt đầu được sửa đổi), đẩy nó ra ngoài ranh giới hình ảnh gốc. Để tránh điều này, tọa độ kết thúc mới bị giảm theo tọa độ bắt đầu mới (100 + 50 phối hợp khởi động mới - 50 điều chỉnh phối hợp khởi động mới)

Lưu ý 3: trong câu trả lời gốc, kiểm tra tất cả các pixel trong một hướng được chạy bằng cách sử dụng cùng kích thước của tọa độ để tìm, trả về điểm ảnh hữu ích tiên tiến nhất.Kiểm tra kích thước ngược lại và dừng lại ở điểm ảnh hữu ích đầu tiên tăng hiệu suất.

+1

Mã mẫu của bạn sẽ cắt ít nhất một pixel, ngay cả khi hình ảnh không có cột hoặc hàng trong suốt. Tốt hơn là sử dụng cách được mô tả trong 'http: // stackoverflow.com/a/886979/1043882' thay vì' if (startWidth == 0) 'và các câu lệnh tương tự khác. – hasanghaforian

+0

'startWidth' và' startHeight' không được đặt thành 0 ban đầu, bởi vì nếu hình ảnh của bạn không có khoảng trống trên đầu và bên trái, các vòng lặp của bạn sẽ chạy đến cuối. Vì vậy, bạn sẽ lãng phí thời gian tính toán bằng '2 * chiều rộng * chiều cao'. Tôi nghĩ tốt hơn là đặt chúng thành '-1'. – Ruslan

Các vấn đề liên quan