2011-01-12 29 views
5

Tôi đang cố gắng áp dụng bộ lọc pha trộn trên hai hình ảnh (trong trường hợp này là HardLight). HardLight không được hỗ trợ trong thư viện Android cơ sở, vì vậy, tôi đang làm điều đó bằng tay trên mỗi pixel. Chạy đầu tiên đang hoạt động, nhưng tốc độ ít hơn sao. Tạo hình ảnh 500x500 từ hình ảnh 500x500 cơ sở và bộ lọc 500x500 mất quá nhiều thời gian. Đoạn mã này cũng được sử dụng để tạo ra các hình thu nhỏ (72x72), và nó không thể tách rời với cốt lõi của ứng dụng. Tôi rất thích một số lời khuyên và/hoặc gợi ý về cách tăng tốc độ này.Tối ưu hóa mỗi Pixel Blending trên Android Bitmaps

Nếu lợi ích lớn có thể được thực hiện bằng cách giả định rằng cả hai hình ảnh sẽ không có alpha, điều đó là tốt. CHÚ Ý: BlendMode và alpha là các giá trị không được sử dụng trong ví dụ (BlendMode sẽ chọn loại hỗn hợp, trong trường hợp này là Hardcoded HardLight).

public Bitmap blendedBitmap(Bitmap source, Bitmap layer, BlendMode blendMode, float alpha) { 
    Bitmap base = source.copy(Config.ARGB_8888, true); 
    Bitmap blend = layer.copy(Config.ARGB_8888, false); 

    IntBuffer buffBase = IntBuffer.allocate(base.getWidth() * base.getHeight()); 
    base.copyPixelsToBuffer(buffBase); 
    buffBase.rewind(); 

    IntBuffer buffBlend = IntBuffer.allocate(blend.getWidth() * blend.getHeight()); 
    blend.copyPixelsToBuffer(buffBlend); 
    buffBlend.rewind(); 

    IntBuffer buffOut = IntBuffer.allocate(base.getWidth() * base.getHeight()); 
    buffOut.rewind(); 

    while (buffOut.position() < buffOut.limit()) { 
     int filterInt = buffBlend.get(); 
     int srcInt = buffBase.get(); 

     int redValueFilter = Color.red(filterInt); 
     int greenValueFilter = Color.green(filterInt); 
     int blueValueFilter = Color.blue(filterInt); 

     int redValueSrc = Color.red(srcInt); 
     int greenValueSrc = Color.green(srcInt); 
     int blueValueSrc = Color.blue(srcInt); 

     int redValueFinal = hardlight(redValueFilter, redValueSrc); 
     int greenValueFinal = hardlight(greenValueFilter, greenValueSrc); 
     int blueValueFinal = hardlight(blueValueFilter, blueValueSrc); 

     int pixel = Color.argb(255, redValueFinal, greenValueFinal, blueValueFinal); 

     buffOut.put(pixel); 
    } 

    buffOut.rewind(); 

    base.copyPixelsFromBuffer(buffOut); 
    blend.recycle(); 

    return base; 
} 

private int hardlight(int in1, int in2) { 
    float image = (float)in2; 
    float mask = (float)in1; 
    return ((int)((image < 128) ? (2 * mask * image/255):(255 - 2 * (255 - mask) * (255 - image)/255))); 

} 
+0

Xin chào, bạn có thể giúp tôi về cách sử dụng alpha trong chức năng này không? –

Trả lời

0

Có một câu hỏi như thế này trong khi quay lại (Link). Tôi không chắc rằng OP đã từng giải quyết vấn đề của anh ta chưa.

Những gì tôi đã làm trong trường hợp của mình để đạt được "hỗn hợp photoshop" là bằng cách áp dụng lớp phủ bóng mờ vào một màu duy nhất. Nó chỉ đơn giản là một vấn đề của nhà thiết kế đồ họa của tôi tìm ra cách để làm lớp phủ bóng tối. Nó làm việc ra tuyệt vời và tôi hoàn toàn bỏ qua vấn đề phải lặp qua các pixel trong một bitmap (tôi đã sử dụng getPixels() và setPixels()). Phần khó khăn đã được thực sự trên thiết kế của tôi kết thúc, nhưng một khi ông đã tìm ra nó, ông đã tạo ra một số hình ảnh tìm kiếm tuyệt vời.

Tôi về cơ bản đã sử dụng mặt nạ alpha (để tạo ra màu động) với lớp phủ bóng. Tôi rất muốn tìm hiểu về một giải pháp thông qua mã, vì vậy chúc may mắn cho bạn!

Chỉnh sửa: Ngoài ra, tôi không quen với BlendMode. Bạn không bao giờ sử dụng nó trong phương pháp của bạn. Đây là gì, một lớp học tùy chỉnh?

+0

Thật không may, giải pháp này sẽ không hoạt động trong trường hợp của tôi. – MarkPowell

2

Thao tác dấu chấm động thường chậm hơn số nguyên mặc dù tôi không thể nói bất kỳ điều gì về Android cụ thể. Tôi tự hỏi tại sao bạn đang chuyển đổi đầu vào sang hardlight thành điểm nổi, khi các hoạt động trông giống như chúng hoạt động hoàn hảo dưới dạng số nguyên?

Bạn cũng có thể tăng tốc bằng cách đặt công thức nội tuyến vào vòng lặp, thay vì gọi hàm. Hoặc có thể không, nhưng đáng để thử và điểm chuẩn.

+0

Thử những thứ khác nhau, tôi có thể tăng khoảng 40% hiệu năng bằng cách sử dụng các mảng int thay vì Buffers (sử dụng 'getPixels()' và 'setPixels()'), và không chuyển đổi các giá trị thành float trong 'hardlight' . Ngoài ra, tôi nghĩ hiệu suất tốt nhất mà bạn sẽ nhận được là tính toán đó đến cấp độ gốc, có thể triển khai Xfermode tùy chỉnh. –

+0

hmm, chuyển sang getPixels()/setPixels() Tôi thấy một đôi trong tính toán thời gian, trừ khi tôi hiểu lầm những gì bạn đang nói? – MarkPowell

+0

@MarkPowell, tôi nghĩ @Kevin đang tranh luận ủng hộ mảng int, và tranh cãi * chống lại * getPixels/setPixels. Bạn sẽ cần hướng dẫn nhận xét của mình bằng cách bắt đầu bằng @Kevin nếu bạn có thêm câu hỏi. –

1

Ngoài ra nếu bạn có thể hy sinh 3 bit/pixel của thức chất lượng hình ảnh/chính xác, - chúng ta có thể giành chiến thắng khoảng 25% hiệu suất đạt được trong chức năng hardlight(), bằng cách viết lại nó với những hoạt động chút khôn ngoan:

int hardlight(int image, int mask) { 
    return (((image < 128) ? 
      ((((mask << 1) * image) >> 8)): 
      (255^((((255^mask) << 1) * (255^image)) >> 8)))); 
} 
+0

Cảm ơn bạn, nhìn thấy khoảng 10% cải thiện tốc độ tổng thể với điều này. Tuy nhiên, sẽ phải xem liệu sự hy sinh 3 bit/pixel có thể thực hiện được hay không. – MarkPowell

+0

Ok. Thật đáng tiếc là hiệu suất đạt được chỉ là 10% thay vì 25% như trong cửa sổ máy của tôi.Tôi nghi ngờ rằng các nhà khai thác bitwise Android ít được tối ưu hóa so với cửa sổ nền tảng/MS VS C/C + + trình biên dịch. Hoặc có thể nút thắt cổ chai hiệu suất chính không có trong chức năng đèn cứng nhưng ở một nơi khác. –