uiimage에 대한 픽셀 알파 값을 검색합니다
-
22-07-2019 - |
문제
나는 현재 uiimageview에서 픽셀의 알파 값을 얻으려고 노력하고 있습니다. [uiimageview image]에서 cgimage를 얻었고 이것으로부터 RGBA 바이트 배열을 만들었습니다. 알파는 전형적입니다.
CGImageRef image = uiImage.CGImage;
NSUInteger width = CGImageGetWidth(image);
NSUInteger height = CGImageGetHeight(image);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
rawData = malloc(height * width * 4);
bytesPerPixel = 4;
bytesPerRow = bytesPerPixel * width;
NSUInteger bitsPerComponent = 8;
CGContextRef context = CGBitmapContextCreate(
rawData, width, height, bitsPerComponent, bytesPerRow, colorSpace,
kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big
);
CGColorSpaceRelease(colorSpace);
CGContextDrawImage(context, CGRectMake(0, 0, width, height), image);
CGContextRelease(context);
그런 다음 uiimageview의 좌표를 사용하여 주어진 알파 채널의 배열 인덱스를 계산합니다.
int byteIndex = (bytesPerRow * uiViewPoint.y) + uiViewPoint.x * bytesPerPixel;
unsigned char alpha = rawData[byteIndex + 3];
그러나 나는 내가 기대하는 가치를 얻지 못한다. 이미지의 완전히 검은 색 투명 영역의 경우 알파 채널에 대해 0이 아닌 값을 얻습니다. Uikit과 Core Graphics 사이의 코디네이트를 번역해야합니까? 즉, y 축은 뒤집어 졌습니까? 아니면 전술 한 알파 가치를 오해 했습니까?
업데이트:
@Nikolai Ruhe의 제안은 이것의 핵심이었습니다. 실제로 Uikit 좌표와 핵심 그래픽 좌표 사이를 번역 할 필요는 없었습니다. 그러나 블렌드 모드를 설정 한 후 알파 값이 예상했던 것입니다.
CGContextSetBlendMode(context, kCGBlendModeCopy);
해결책
그렇습니다. 문서를 참조하십시오.
코드를 읽은 후 편집 :
또한 이미지의 알파 값이 아니라 이미지의 알파 값을 원하기 때문에 이미지를 그리기 전에 블렌드 모드를 교체하도록 설정하려고합니다.
CGContextSetBlendMode(context, kCGBlendModeCopy);
생각 후 편집 :
조회를 할 수 있습니다 많이 가능한 가장 작은 cgbitmapcontext (1x1 pixel? 아마 8x8? 시도 할 수 있음)를 구축하고 그리기 전에 원하는 위치로 컨텍스트를 번역함으로써 더 효율적입니다.
CGContextTranslateCTM(context, xOffset, yOffset);
다른 팁
당신이 원하는 것은 단일 지점의 알파 값이라면 알파 전용 단일 포인트 버퍼 만 있으면됩니다. 나는 이것이 충분해야한다고 믿는다 :
// assume im is a UIImage, point is the CGPoint to test
CGImageRef cgim = im.CGImage;
unsigned char pixel[1] = {0};
CGContextRef context = CGBitmapContextCreate(pixel,
1, 1, 8, 1, NULL,
kCGImageAlphaOnly);
CGContextDrawImage(context, CGRectMake(-point.x,
-point.y,
CGImageGetWidth(cgim),
CGImageGetHeight(cgim)),
cgim);
CGContextRelease(context);
CGFloat alpha = pixel[0]/255.0;
BOOL transparent = alpha < 0.01;
uiimage를 매번 재현 할 필요가 없다면 이것은 매우 효율적입니다.
2011 년 12 월 8 일 편집 :
의견 제시자는 특정 상황에서 이미지가 뒤집을 수 있다고 지적합니다. 나는 이것에 대해 생각하고 있었고, UIIMAGE를 직접 사용하여 코드를 쓰지 않았기 때문에 미안합니다. UIGraphicsPushContext
):
// assume im is a UIImage, point is the CGPoint to test
unsigned char pixel[1] = {0};
CGContextRef context = CGBitmapContextCreate(pixel,
1, 1, 8, 1, NULL,
kCGImageAlphaOnly);
UIGraphicsPushContext(context);
[im drawAtPoint:CGPointMake(-point.x, -point.y)];
UIGraphicsPopContext();
CGContextRelease(context);
CGFloat alpha = pixel[0]/255.0;
BOOL transparent = alpha < 0.01;
나는 그것이 뒤집는 문제를 해결했을 것이라고 생각합니다.
직사각형 경계 상자가 아닌 이미지 데이터의 알파 값을 사용하여 스프라이트 간의 충돌 감지 방법을 연구 하면서이 질문/답변을 찾았습니다. 컨텍스트는 iPhone 앱입니다 ... 위의 제안 된 1 픽셀 드로우를하려고 노력하고 있으며 여전히 작동하는 데 문제가 있지만 이미지 자체의 데이터를 사용하여 CGContexTref를 만드는 데 더 쉬운 방법을 찾았습니다. 여기에 헬퍼 기능 :
CGContextRef context = CGBitmapContextCreate(
rawData,
CGImageGetWidth(cgiRef),
CGImageGetHeight(cgiRef),
CGImageGetBitsPerComponent(cgiRef),
CGImageGetBytesPerRow(cgiRef),
CGImageGetColorSpace(cgiRef),
kCGImageAlphaPremultipliedLast
);
이것은 위의 샘플의 모든 못생긴 하드 코딩을 우회합니다. 마지막 값은 cgimagegetbitmapinfo ()를 호출하여 검색 할 수 있지만 내 경우에는 컨텍스트 크리징 함수에서 오류가 발생한 이미지에서 값을 반환합니다. 여기에 문서화 된대로 특정 조합 만 유효합니다. http://developer.apple.com/qa/qa2001/qa1037.html
이것이 도움이되기를 바랍니다!
Uikit과 Core Graphics 사이의 코디네이트를 번역해야합니까? 즉, y 축은 뒤집어 졌습니까?
있을 수있다. CGIMAGE에서 픽셀 데이터는 영어 읽기 순서 : 왼쪽에서 오른쪽, 상단에서 바닥입니다. 따라서 배열의 첫 번째 픽셀은 왼쪽 상단입니다. 두 번째 픽셀은 상단 행의 왼쪽에서 하나입니다. 등.
당신이 그 권리가 있다고 가정하면, 당신은 또한 픽셀 내의 올바른 구성 요소를보고 있는지 확인해야합니다. 아마도 당신은 RGBA를 기대하지만 ArgB를 요구하거나 그 반대도 마찬가지입니다. 또는 바이트 순서가 잘못되었을 수도 있습니다 (iPhone의 엔디 언이 무엇인지 모르겠습니다).
아니면 전술 한 알파 가치를 오해 했습니까?
처럼 들리지 않습니다.
모르는 사람들의 경우 : Pimultiplied는 색상 구성 요소가 알파에 의해 전형적임을 의미합니다. 알파 구성 요소는 색상 구성 요소가 전형적으로 배정되는지 여부에 관계없이 동일합니다. 색상 구성 요소를 알파로 나누어이를 (비 배상) 반전시킬 수 있습니다.