2010-03-03 3 views
6

본질적으로 1 비트 값을 가진 알파 채널이있는 32 비트 NSBitmapImageRep (픽셀은 켜짐 또는 꺼짐)이 있습니다.NSBitmapImageRep에서 투명도가있는 8 비트 PNG를 만드는 방법은 무엇입니까?

이 비트 맵을 투명도가있는 8 비트 PNG 파일로 저장하려고합니다. -representationUsingType:properties: 메서드를 NSBitmapImageRep으로 사용하고 NSPNGFileType을 전달하면 32 비트 PNG가 만들어 지는데, 이는 내가 원하는 것이 아닙니다.

8 비트 PNG는 읽을 수 있지만 문제없이 미리보기에서 열 수 있지만 내장 된 Mac OS X API를 사용하여이 유형의 PNG 파일을 작성할 수 있습니까? 필요하다면 코어 이미지 또는 QuickTime으로 내려와 드리겠습니다. CGImage 문서의 간단한 시험에서 명백한 어떤 것도 밝혀 내지 못했습니다.

편집 : 누군가가 32 비트 NSBitmapImageRep를 받아 1 비트의 투명성과 256 색 PNG를 기록 작업 소스 코드를 제공 할 수 있는지 내가 그것은 당신이야,이 질문에 현상금을 시작했습니다.

+0

8 비트가 256 색으로 표시됩니까? 이미지에 256 색 이상 만 있으면 좋겠다. 256 색 이상일 경우 pngnq (앱에 번들로 묶어 NSTask로 실행)를 사용하는 것이 좋습니다. http://pngnq.sourceforge.net/ –

+0

예, 256 색. 출력으로 8 비트 PNG를 제외하고'-representationUsingType : properties'와'NSGIFFileType'을 사용하여 출력물을 찾고 있습니다. pngnq는 옵션 (감사합니다)이지만 가능하다면 작업 생성없이 처리하기를 바라고 있습니다. –

답변

1

pngnq (및 더 높은 품질을 달성하는 new pngquant)에는 BSD 스타일의 라이센스가 있으므로 그냥 포함시킬 수 있습니다 r 프로그램. 별도의 작업으로 생성 할 필요가 없습니다.

+0

이것은 실제로 작동하며 문제, 고마워. –

0

시도해 볼 것은 NSBitmapImageRep을 8 비트로 생성 한 다음 데이터를 복사하는 것입니다.

직접 색 인덱스 테이블을 계산해야하므로 실제로 많은 작업이 필요합니다.

+0

수정하십시오. ** pngnq **를 사용하는 Peter Hosey의 제안은 작업을 생성 할 필요가 있음에도 불구하고이 팔레트 생성 문제를 아주 잘 해결합니다. –

2

어때 대략 pnglib? 정말 가볍고 사용하기 쉽습니다.

+0

이것은 분명히 선택 사항이지만, 많은 학습이 있기 전에'pnglib'로 작업하지 않았기 때문에, 나는 더 높은 수준의 것을 정말로 기대하고있었습니다. –

+0

@Rob, pnglib에 대한 많은 학습은 없지만 C 라이브러리가 제공되는 한 매우 직접적입니다. 당신은 다른 것을 고집 할 수도 있지만 대부분의 상위 레벨 API는 더 일반적인 경우를 가정합니다. 보통 24 또는 32 bpp 이미지를 의미합니다. –

0

CGImageDestination은 저급 이미지 작성을 담당하는 사람이지만 그 특정 기능을 지원하는지는 알 수 없습니다. 낮은 수준의 API를 사용하기위한

+0

그래, 그것이 답변이어야하지만 지금까지는 내가 만드는 모든 PNG 형식을 지정하는 방법을 찾을 수 없습니다, 내가 시도하는 모든 32 비트 PNG를 씁니다. –

1

좋은 참조가 Programming With Quartz

아래의 코드 중 일부는 그 책에서 예제를 기반으로합니다.

참고 :

CGContextRef createRGBBitmapContext(size_t width, size_t height, Boolean needsTransparentBitmap) 
{ 
    CGContextRef context; 
    size_t bytesPerRow; 
    unsigned char *rasterData; 

    //minimum bytes per row is 4 bytes per sample * number of samples 
    bytesPerRow = width*4; 
    //round up to nearest multiple of 16. 
    bytesPerRow = COMPUTE_BEST_BYTES_PER_ROW(bytesPerRow); 

    int bitsPerComponent = 2; // to get 256 colors (2xRGBA) 

    //use function 'calloc' so memory is initialized to 0. 
    rasterData = calloc(1, bytesPerRow * height); 
    if(rasterData == NULL){ 
     fprintf(stderr, "Couldn't allocate the needed amount of memory!\n"); 
     return NULL; 
    } 

    // uses the generic calibrated RGB color space. 
    context = CGBitmapContextCreate(rasterData, width, height, bitsPerComponent, bytesPerRow, 
            CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB), 
            (needsTransparentBitmap ? kCGImageAlphaPremultipliedFirst : 
            kCGImageAlphaNoneSkipFirst) 
            ); 
    if(context == NULL){ 
     free(rasterData); 
     fprintf(stderr, "Couldn't create the context!\n"); 
     return NULL; 
    } 

    //Either clear the rect or paint with opaque white, 
    if(needsTransparentBitmap){ 
     CGContextClearRect(context, CGRectMake(0, 0, width, height)); 
    }else{ 
     CGContextSaveGState(context); 
     CGContextSetFillColorWithColor(context, getRGBOpaqueWhiteColor()); 
     CGContextFillRect(context, CGRectMake(0, 0, width, height)); 
     CGContextRestoreGState(context); 
    } 
    return context; 
} 

사용법은 다음과 같습니다 :

NSBitmapImageRep *startingImage; // assumed to be previously set. 
NSBitmapImageRep *endingImageRep = [self convertImageRep:startingImage]; 
// Write out as data 
NSData *outputData = [endingImageRep representationUsingType:NSPNGFileType properties:nil]; 
// somePath is set elsewhere 
[outputData writeToFile:somePath atomically:YES]; 

- (NSBitmapImageRep*)convertImageRep:(NSBitmapImageRep*)startingImage{ 

    CGImageRef anImage = [startingImage CGImage]; 

    CGContextRef bitmapContext; 
    CGRect ctxRect; 
    size_t bytesPerRow, width, height; 

    width = CGImageGetWidth(anImage); 
    height = CGImageGetHeight(anImage); 
    ctxRect = CGRectMake(0.0, 0.0, width, height); 
    bytesPerRow = (width * 4 + 63) & ~63; 
    bitmapData = calloc(bytesPerRow * height, 1); 
    bitmapContext = createRGBBitmapContext(width, height, TRUE); 
    CGContextDrawImage (bitmapContext, ctxRect, anImage); 

    //Now extract the image from the context 
    CGImageRef  bitmapImage = nil; 
    bitmapImage = CGBitmapContextCreateImage(bitmapContext); 
    if(!bitmapImage){ 
     fprintf(stderr, "Couldn't create the image!\n"); 
     return nil; 
    } 

    NSBitmapImageRep *newImage = [[NSBitmapImageRep alloc] initWithCGImage:bitmapImage]; 
    return newImage; 
} 

컨텍스트 생성 기능 .... 해제 테스트 코드는 출발점이 될 운명이다

+0

감사합니다. 비트 맵을 만드는 데는 잘 작동하지만 실제로 256 색 8 비트 PNG 파일을 쓰는 문제는 해결되지 않습니다. –

+0

죄송합니다. 나는 그 단계를 나 았습니다. 내 대답을 편집하여 필요한 두 번의 호출을 포함시킵니다. –

+0

저는 이것을 살펴 봤으며 Quartz 2D Programming Guide의 "Supported Pixel Formats"에 따르면 8 비트 RGB 컨텍스트를 만들 수 없으므로이 코드는 작동하지 않습니다. 실행하려고하면 "잘못된 매개 변수 조합"으로 인해 컨텍스트를 만들지 못합니다. http://developer.apple.com/mac/library/DOCUMENTATION/GraphicsImaging/Conceptual/drawingwithquartz2d/dq_context/dq_context.html#//apple_ref/doc/uid/TP30001066-CH203-BCIBHHBB –

관련 문제