2016-08-30 5 views
0

SDCard에 저장된 PNG의 특정 색상을 변경해야합니다. 비트 맵 위에 또는 다른 객체 위에 틴 컬러를 사용할 수 없습니다. 특정 픽셀 색상이 아닌 모든 이미지에 색조를 적용 할 수 있기 때문입니다.Android에서 픽셀 단위로 PNG 색상을 변경하는 가장 좋은 방법은 무엇입니까?

왜 이렇게해야합니까?
아바타 응용 프로그램을 개발하려고하는데 팔레트에서 선택한 색상으로 아바타의 머리카락을 바꿀 수 있어야합니다. 이 머리카락에는 국경 용과 머리카락 용의 두 가지 색상이 있습니다. 나는 공기 색을 바꾸고 국경을 유지하고 싶다.

이 간단한 경우이지만 이미지에 둘 이상의 색상이있을 수 있습니다.

나는 해결책을 찾고 있었다. 이것은 내가 찾은 유일한 일 (meaby 더있을 수 있지만 나는 운이 아니다) :

Android Bitmap: Convert transparent pixels to a color

그리고 이것은 거기 노출되는 것입니다 :

Bitmap b = ...; 
for(int x = 0; x<b.getWidth(); x++){ 
    for(int y = 0; y<b.getHeight(); y++){ 
     if(b.getPixel(x, y) == Color.TRANSPARENT){ 
      b.setPixel(x, y, Color.WHITE); 
     } 
    } 
} 

내가 알고 싶은 이것을하는 더 좋은 방법이 있습니다. 뭔가 같은 :

루프를 사용하여 픽셀을 확인하는 것이 좋은 성능인지는 모르겠다. 1080 x 1080 이미지를 상상해보십시오.

미리 감사드립니다.

+0

투명도를 사용하여 어떤 픽셀이 머리카락인지 나타 냅니까? – samgak

+0

특히 성능 및 소형성을 위해 OpenCV Matrix API를 사용하는 것이 좋습니다. –

+0

@samgak 같은 이미지에서 여러 색상을 변경할 수 있으므로 투명도를 사용하지 않습니다. –

답변

2

성능이 더욱 향상 비트 맵으로 다시 버퍼로부터 복사 copyPixelsFromBuffer() 호출 마지막 그리고, 버퍼에 화소를 복사 copyPixelsToBuffer() 호출 버퍼의 픽셀 값을 수정 의해 getPixel()setPixel()에 비해 얻을 수

boolean changeColor(Bitmap bitmap, int originalColor, int newColor) 
{ 
    // bitmap must be mutable and 32 bits per pixel: 
    if((bitmap.getConfig() != Bitmap.Config.ARGB_8888) || !bitmap.isMutable()) 
     return false; 

    int pixelCount = bitmap.getWidth() * bitmap.getHeight(); 
    IntBuffer buffer = IntBuffer.allocate(pixelCount); 
    bitmap.copyPixelsToBuffer(buffer); 
    int[] array = buffer.array(); 
    for(int i = 0; i < pixelCount; i++) 
    { 
     if(array[i] == originalColor) 
      array[i] = newColor; 
    } 
    bitmap.copyPixelsFromBuffer(buffer); 

    return true;  
} 

그러나 비트 맵에는 ARGB_8888 픽셀 형식을 사용해야하며 (다른 경우이를 처리하기 위해 추가 코드를 작성해야 함) 비트 맵을 할당 할 때 발생할 수있는 메모리 예외를 찾아 낼 필요가 있습니다. IntBuffer. 먼저 setPixels()을 사용하여 코드를 프로파일 링해야하며 속도가 받아 들여지지 않는지 확인해야합니다.

이것은 아마도 가장 빠른 솔루션이 아니기 때문에 라이브러리에서 기본 함수 호출을 사용하는 것일 수 있습니다. 그러나 여전히 setPixel()보다 빠르며 프로젝트에 라이브러리를 추가 할 필요가 없습니다.

+0

예를 들어 보시고 예상되는 색상 대신 다른 색상의 이미지를 얻으십시오. 이유가 무엇이라고 생각하십니까? –

+0

@ Сергей 가장 가능성있는 이유는 int 값의 rgba 순서가 Android Bitmap 클래스가 기대하는 것과 다릅니다. 색상은 다음과 같이 형성되어야합니다. int color = (a << 24) | (r << 16) | (g << 8) | 비; 여기서 rgb는 0-255 범위에 있습니다. 자세한 내용은 여기를 참조하십시오. https://developer.android.com/reference/android/graphics/Color.html – samgak

1

특히 성능 및 소형성을 위해 OpenCV 매트릭스 API를 사용하는 것이 좋습니다.

OpenCV Android 튜토리얼 here을 확인하세요.

OpenCV 기능을 설치했다고 가정하면 이미지의 특정 영역의 색상을 변경할 수 있습니다.

(먼저 Mat 기능을 이해해야합니다.) 사실 나는 안드로이드에서 OpenCV 사용하지 않은

합니다.
여기 ++ 몇 가지 예제 코드는 C에서 빨간색으로 머리 색을 변경할 수있다 :

// 1. Loading 
Mat src = imread("yourImagePath/yourOriginalImage.jpg"); // This code will automatically loads image to Mat with 3-channel(BGR) format 
Mat mask = imread("yourImagePath/yourHairMaskImage.png", CV_GRAYSCALE); // This code will automatically loads mask image to Mat with 1-channel(grayscale) format 

// 2. Splitting RGB channel into 3 separate channels 
vector<Mat> channels; // C++ version of ArrayList<Mat> 
split(src, channels); // Automatically splits channels and adds them to channels. The size of channels = 3 

// 3-1. Adjusting red color 
Mat adjustRed = channels[0]*1.5; 

// 3-2. Copy the adjusted pixels into org Mat with mask 
channels[2] = adjustRed & mask + channels[0] & ~mask; 

// 4. Merging channels 
Mat dst; 
merge(channels, dst); // dst is re-created with 3-channel(BGR). 
// Note that OpenCV applies BGR by default if your array size is 3, 
// even if actual order is different. In this case this makes sense. 

// 5. Saving 
imwrite("yourImagePath/yourDstImage.jpg", dst); 


안드로이드 버전 코드는하지 내가 생각 다릅니다.

+0

내가 원하는 것을 직접 할 수있는 방법이기 때문에 나는 samgak의 대답을 받아 들인다. 나는 너의 것을 평가 중이다. 어쩌면 내 생각이 너와 똑같지는 않을지 모르지만, 너의 생각은 시작하는 법이 좋은데, 이것이 성과에 대해 말하는 가장 좋은 방법이 될 수있다. 모두에게 감사드립니다. –

관련 문제