2013-12-17 1 views
1

알파 투명도를 가진 여러 PNG 이미지가 있습니다. UI와 같이 일반적인 Quartz 용으로 사용되면 제대로 표시됩니다. 그러나 이미지를 가져 와서 OpenGL로 가져 오면 얻을 데이터에 255의 단색 알파가 있습니다. 보통 UIImage가 CGImage로 변환되어 컨텍스트로 렌더링되는 것을 사용하고 있습니다. 아래에 관련 코드를 게시하겠습니다.iOS PNG OpenGL 용 UIImage를 CGImage로 변환 할 때 알파 채널이 단색 임

나는 많은 검색을했는데 마침내이 문제를 해결하고 싶었지만 여기서 공유하고 싶었지만 모든 픽셀을 반복하고 알파 채널로 복사해야하므로 느리다. 이 문제를 해결하는 방법을 알고 싶습니다.

:이 도움이 있는지 확인하기 위해 (즉, 설정 위치를 확인하지 않음) 난 .. 내 빌드에서

감사

먼저 내가 같이 추가 내 응용 프로그램에서있는 UIImage 얻을 어떤 PNG 옵션을 전환하지 않은

UIImage *image = [UIImage imageNamed:imageName]; 

는 내가 CGImageRef로 변환 나는 보통의 문맥을 할 경우에만이 해당 줄처럼 만들 : 그럼

CGContextRef spriteContext = CGBitmapContextCreate(spriteData, width, height, 
              bitsPerComponent, bytesPerRow, 
              CGImageGetColorSpace(spriteImage), 
                kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); 

이 다음 두 줄은 REAL PNG 원료 다 저를 얻을 수있는 마법이다 타 ... 아마 RGBA 대 다른 형식을 확인해야하지만 게으른 ... 그 후 이미지를 그려 돌아가서 알파를 수정 ... 그래, 난 이걸 한 루프에서 할 수 있고 바이트 건너 뛰는 더 많은 ... 지금은 읽을 수

// THIS data actually HAS the alpha!! 
CFDataRef data = CGDataProviderCopyData(CGImageGetDataProvider(spriteImage)); 
GLubyte *pixels = (GLubyte *)CFDataGetBytePtr(data); 

// 3 
CGContextDrawImage(spriteContext, CGRectMake(0, 0, width, height), spriteImage); 


// Sadly we now have to loop and fix the ALPHA directly from the raw PNG source 
// data as otherwise we get wrong/missing alpha... 
for (int y=0; y < height; ++y) { 
    for (int x=0; x < width; ++x) { 
     int byteIndex = (bytesPerRow * y) + (x * bytesPerPixel); 

     spriteData[byteIndex + 3] = pixels[byteIndex +3 ]; 
    } 
} 

는 내가 평소 glTexture 등등 호출 할 ... 나는 알파 없음 고체 스프라이트를 얻을 위에 나는 복사 루프를 떠날 경우는 .. 잘 작동합니다. 위의 작업을 수행하면 스프라이트가 올바르게 투명하게 그립니다.

나는 iOS가하는 모든 곱셈 된 곱셈을 알고있다. 그러나 이것은 깨진 것처럼 보인다. 적어도 위의 것은 누군가를 도울 수 있지만 더 좋은 방법이 있어야한다 ???

생각하십니까? 감사!

+0

CGDataProviderCopyData()에서 올바른 원시 데이터를 제공하는 경우 CGContextDrawImage()로 다시 그려주는 대신 텍스처에 사용하지 않는 이유는 무엇입니까? 후자 또는 루프가 필요 없습니다. –

+0

좋은 지적 .... 나는 그것을 시도해야한다. 나는 그것을 다른 방법으로 사용하려고 시도했는데 물론 읽었을뿐 아니라 통과하는 것을 제한하여 오류를 낳았습니다 ... 그게 뭔지 잊어 버렸습니다 ... 좋은 생각 이군요 ...이 코드를 언급해야합니다. 애플 출신이다. 그것과 올바른 코드가 사전 멀티 알파없이 파일을 읽을 수있는 샘플이 있습니다. 제 진짜 이유는 그게 정확하고 CGImage가 정확하지 않은 것으로 남아 있습니다 ... – mcomet

+0

CGBitmapContextCreate()는 i 곱하기에서만 미리 곱셈 된 알파를 지원합니다 , 적어도),하지만 CGDataProviderCopyData() 이미지에서 원시 픽셀 데이터를 추출, 일반적으로 미리 곱슬 곱슬하지 않습니다 믿습니다. –

답변

2

가 좋아 나는

먼저

이있는 UIImage와의 CGImage에 의해 제공되는 데이터는 알파가 미리 곱셈 것 ... 나 자신 나의 발견과 억측을 기반으로 질문에 응답 할 것 같아요. 그것이 최적화 된 PNG를 사용하는 경우입니다. 그 시점에서 알파는 쓸모가없는 것처럼 보입니다. Apple이 직접 제공 한 샘플 GLImageProcessing 코드를 기반으로하면 원시 PNG 알파를 얻는 적절한 방법은 해당 예제에서와 같이 CGImageGetDataProvider 메서드를 사용하는 것입니다. 이는 특별히 처리하지 않고 이미지에서 가져옵니다. 한 가지 주목할 점은 데이터가 RGB 순서가 아닌 BGR에있을 가능성이 높다는 것입니다. 필요한 경우 샘플 코드에 변환이 있습니다. 필자의 경우이 작업을 수행합니다 :

CGImageRef spriteImage = image.CGImage; 
if (!spriteImage) { 
    NSLog(@"Failed to load image"); 
    exit(1); 
} 

CFDataRef data = CGDataProviderCopyData(CGImageGetDataProvider(CGImage)); 
pixels = (GLubyte *)CFDataGetBytePtr(data); 

// … do other GL calls here like gl Gen and Bind… 

// NOTE the reverse BGRA here for the 7th parameter only!: 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (int)width, (int)height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pixels); 

// Don't forget to release BOTH the CF data and the CGImage or you will get memory leaks! 
CFRelease(data);  // Release the CF data 

이 작업은 저에게 효과적이며 적절한 알파를 얻습니다. 빠르고 정확합니다. 한 가지 메모는 내 이미지의 크기를 조정할 필요가 없습니다. 그렇다면 보통의 CGBitmapContextCreate 및 ContextDraw 물건을 원할 것입니다. 평소와 같이 적절하게 제공되는 데이터로 작동합니다. 석방하는 것을 잊지 마세요 ... 기억을 새기면서 이것을 잊어 버렸습니다. 이 사람하는 데 도움이

희망 ...

0

그것은 CGImageGetDataProvider (의 CGImage) 알파 premultiplication 않는 것을 알 수있다. 빨강 = 255 및 알파 = 128 인 PNG가 있고로드 된 픽셀의 빨강 = 128입니다. 어느 쪽이 슬프지 ....

관련 문제