1.) NSBitmapImageRep의 -bitmapData를 사용하여 원시 픽셀 데이터를 얻을 수 있습니다. 불행히도 CG (NSBitmapImageRep의 백엔드)는 기본 unpremultiplication을 지원하지 않으므로 자신을 unpremultiply해야합니다. 이 색상 공간은 파일에있는 것과 동일합니다. 다음은 이미지 데이터를 unpremultiply하는 방법입니다 :
NSBitmapImageRep *imageRep = [NSBitmapImageRep imageRepWithData:data];
NSInteger width = [imageRep pixelsWide];
NSInteger height = [imageRep pixelsHigh];
unsigned char *bytes = [imageRep bitmapData];
for (NSUInteger y = 0; y < width * height * 4; y += 4) { // bgra little endian + alpha first
uint8_t a, r, g, b;
if (imageRep.bitmapFormat & NSAlphaFirstBitmapFormat) {
a = bytes[y];
r = bytes[y+1];
g = bytes[y+2];
b = bytes[y+3];
} else {
r = bytes[y+0];
g = bytes[y+1];
b = bytes[y+2];
a = bytes[y+3];
}
// unpremultiply alpha if there is any
if (a > 0) {
if (!(imageRep.bitmapFormat & NSAlphaNonpremultipliedBitmapFormat)) {
float factor = 255.0f/a;
b *= factor;
g *= factor;
r *= factor;
}
} else {
b = 0;
g = 0;
r = 0;
}
bytes[y]=a; // for argb
bytes[y+1]=r;
bytes[y+2]=g;
bytes[y+3]=b;
}
2.)이 작업을 수행하는 간단한 방법을 생각할 수 없었습니다. 원시 이미지 데이터를 반복하고 값을 기반으로 새 이미지를 생성하는 고유 한 이미지 그리기 방법을 만들 수 있습니다. 그것을 시작하는 방법을 보려면 위에서 참조하십시오.
3.) 여기에 CG가 불편하게하는 경우 (당신이
static CGImageRef cgImageFrom(NSData *data, uint16_t width, uint16_t height) {
CGDataProviderRef provider = CGDataProviderCreateWithCFData((CFDataRef)data);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo bitmapInfo = kCGImageAlphaFirst;
CGImageRef cgImage = CGImageCreate(width, height, 8, 32, 4 * width, colorSpace, bitmapInfo, provider, NULL, NO, kCGRenderingIntentDefault);
CGDataProviderRelease(provider);
CGColorSpaceRelease(colorSpace);
return cgImage;
}
) 기본 CG 기능을 사용하여 파일에 PNG를 작성하거나 NSBitmapImageRep로 변환 할 수 있습니다 원시 데이터 장소에서의 CGImage를 얻을 수있는 방법이다 +dataWithBytes:length:
아야. 사전 곱셈을 제거하면 특히 알파가 작은 경우 심각한 반올림 오류가 발생합니다. 그러면 비트 맵에 액세스 할 때 문제가 발생합니다. 미리로드되지 않은 파일에 ** 정확한 ** 비트 맵 값을로드하고 저장해야합니다. CGImageCreateWithPNGDataProvider는 CGImage에 미리 곱하기 여부를 지정하는 접근자를 가지고 있으므로이 기능을 지원하는 것처럼 보입니다. CGImageDestinationCreateWithURL은 PNG를 쓰는 것처럼 들립니다. –
예, 데이터가 원본 이미지에 미리 unprimultiplied되어 있다면 CGImage/NSBitmapImageRep은 그 이미지를 그대로 취급 할 것입니다. 컨텍스트에 그려지고 메모리에 새 이미지로 초기화 된 이미지는 지원되지 않으므로 unpremultiplied되지 않습니다. 또한, unpremultiplication 동안 lossiness 불가피합니다. –
사실 ** PNG 파일의 ** 원래 ** 데이터는 ** 미리 곱셈되지 않았습니다. 로드, 수정 및 저장하려는 데이터입니다. 하지만 내가 바로 참조를 읽고 있다면 NSBitmapImageRep (비트 맵에 액세스하는 방법을 볼 수있는 유일한 클래스)은 파일의 데이터로 초기화 될 때 미리 곱해집니다. 파이썬의 PyPNG 모듈이 최선의 방법이라고 생각합니다. 데이터를 얻기 위해 Cocoa에서 쉬운 방법을 찾지 못했습니다. –