2011-01-05 2 views
13

나는 벽에 머리를 때리고 있는데, 나는 바보 같은 짓을하고있어, 내 어리 석음을 공개 할 시간이 있다고 확신한다.두 개의 비트 맵에서 픽셀 블렌드

두 이미지를 표준 혼합 알고리즘 (Hardlight, 소프트 라이트, 오버레이, 곱하기 등)을 사용하여 세 번째 이미지로 결합하려고합니다.

안드로이드는 이러한 블렌드 속성을 가지고 있지 않으므로 각 픽셀을 가져 와서 알고리즘을 사용하여 결합했습니다. 그러나 결과는 가비지입니다. 다음은 간단한 다중 곱 (사용 된 이미지 및 예상 결과)의 결과입니다.

BASE : alt text

BLEND : alt text

예상 결과 : alt text

쓰레기 결과 : 어떤 도움을 주시면 감사하겠습니다 alt text

. 아래 코드는 모든 "쓰레기"를 없애기 위해 노력했지만 일부는 끝났을 수 있습니다. 뭔가 명확하지 않으면 나는 그것을 정리할 것이다. 이 방법을 수행 할 수 있습니다

ImageView imageView = (ImageView) findViewById(R.id.ImageView01); 
    Bitmap base = BitmapFactory.decodeResource(getResources(), R.drawable.base); 
    Bitmap result = base.copy(Bitmap.Config.RGB_565, true); 
    Bitmap blend = BitmapFactory.decodeResource(getResources(), R.drawable.blend); 

    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 = multiply(redValueFilter, redValueSrc); 
     int greenValueFinal = multiply(greenValueFilter, greenValueSrc); 
     int blueValueFinal = multiply(blueValueFilter, blueValueSrc); 

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

     buffOut.put(pixel); 
    } 

    buffOut.rewind(); 

    result.copyPixelsFromBuffer(buffOut); 

    BitmapDrawable drawable = new BitmapDrawable(getResources(), result); 
    imageView.setImageDrawable(drawable); 
} 

int multiply(int in1, int in2) { 
    return in1 * in2/255; 
} 

답변

13

재생 후, 귀하의 문제는 RGB565 모드에서 이미지를 조작하는 것과 관련이 있다고 생각합니다. this post에서 논의 되었 듯이 비트 맵은 제대로 조작하려면 ARGB8888 모드에 있어야합니다. 내가 먼저 다음을 수행하여 다중 혼합에 예상 된 결과를 얻었다 :

Resources res = getResources(); 
BitmapFactory.Options options = new BitmapFactory.Options(); 
options.inPreferredConfig = Bitmap.Config.ARGB_8888; 
Bitmap base = BitmapFactory.decodeResource(res, R.drawable.base, options); 
Bitmap blend = BitmapFactory.decodeResource(res, R.drawable.blend, options); 

// now base and blend are in ARGB8888 mode, which is what you want 

Bitmap result = base.copy(Config.ARGB_8888, true); 
// Continue with IntBuffers as before... 

적어도 그라데이션 테스트 패턴으로, 나를 위해 작동하는 것 않았다 모드를 ARGB8888하기 위해 비트 맵 변환. 당신은 픽셀 당 계산을 수행하지 않는, 그와

// Same image creation/reading as above, then: 
Paint p = new Paint(); 
p.setXfermode(new PorterDuffXfermode(Mode.MULTIPLY)); 
p.setShader(new BitmapShader(blend, TileMode.CLAMP, TileMode.CLAMP)); 

Canvas c = new Canvas(); 
c.setBitmap(result); 
c.drawBitmap(base, 0, 0, null); 
c.drawRect(0, 0, base.getWidth(), base.getHeight(), p); 

,하지만 당신은 사전 PorterDuff.Mode s로 제한됩니다 그러나, 당신은 화면 또는 곱하기를 할 필요가, 당신은뿐만 아니라이 시도 할 수 있습니다. 내 빠르고 (그리고 더러운) 테스트에서, 블렌딩이 비 그라디언트 이미지에서 작동하도록하는 유일한 방법이었습니다.

+0

케빈, 도와 줘서 고마워. 저는 투명도가있는 이미지를 사용하지 않습니다. 그래서 불투명도는 항상 1이 될 것입니다. 이미지로 예제를 업데이트하고 코드를 정리했습니다. – MarkPowell

+0

흠 이미지에 감사드립니다. 정말 쓰레기 결과입니다. 나는 현재 안드로이드 개발 환경에 대한 액세스 권한이 없지만 비트 맵의 ​​픽셀 밀도와 관련이 없는지 궁금합니다. 비트 맵에서 RGB565 색 공간을 사용하고있는 것처럼 보입니다.하지만 ARGB4444 공간에서 Color가 작동하는 것으로 보입니다. 필자는 모든 Bitmap/Color 문서를 분석하여이 변환이 자동으로 처리되는 방법/방법을 확인하지는 않았지만 실제 플랫폼에서 일부 테스트를 수행 할 때까지 체크 아웃 할 가치가 있습니다. –

+0

좋아, 나는 그걸로 조금 놀았고 나는 너의 '쓰레기'결과를 재현 할 수 있었고, 나는 두 가지 다른 방법으로 일하도록했다.나는 이것을 반영하기 위해 원래의 대답을 바꾸려고 노력할 것이다. –

4

간단한 오버레이 (단순성을 위해이 bmp1는 BMP2와 같거나 더 큰 것으로 가정한다) : 더 복잡한 혼합 알고리즘에 대한

private Bitmap bitmapOverlay(Bitmap bmp1, Bitmap bmp2) 
{ 
    Bitmap bmOverlay = Bitmap.createBitmap(bmp1.getWidth(), bmp1.getHeight(), bmp1.getConfig()); 
    Canvas canvas = new Canvas(bmOverlay); 
    canvas.drawBitmap(bmp1, 0, 0, null); 
    canvas.drawBitmap(bmp2, 0, 0, null); 
    return bmOverlay; 
} 

, 어쩌면 당신은 몇 가지 자신을 도울 수 사용 가능한 비트 맵/캔버스 기능.

+0

고마워요.하지만 캔버스를 통해 복잡한 블렌딩이 불가능하다고 생각하게 된 것은 그 길과 다른 토론으로 이어지고있었습니다. 이것은 픽셀 블렌딩을 시도하는 결과를 낳았습니다. – MarkPowell