7

基本的に1ビット値のアルファチャネルを持つ32ビットNSBitmapImageRepがあります(ピクセルはオンまたはオフのいずれかです)。

このビットマップを透明度のある8ビットPNGファイルに保存したいと思います。-representationUsingType:properties:のメソッドを使用してNSBitmapImageRep渡すとNSPNGFileType、32ビットのPNGが作成されますが、これは私が望むものではありません。

8ビットのPNGを読み取ることができ、プレビューで問題なく開くことは知っていますが、組み込みのMac OS X APIを使用してこのタイプのPNGファイルを書き込むことは可能ですか?必要に応じて、CoreImageまたはQuickTimeにドロップダウンできてうれしいです。ドキュメントをざっと調べても、CGImage明らかなことは何もわかりませんでした。

編集: 私はこの質問に報奨金を始めました。誰かが32ビットを取り、NSBitmapImageRep1ビットの透明度で256色のPNGを書き込む実用的なソースコードを提供できるなら、それはあなたのものです。

4

5 に答える 5

2

どうpnglibですか?本当に軽量で使いやすいです。

于 2010-03-03T04:17:14.423 に答える
1

低レベルのAPIを操作するための優れたリファレンスは、Quartzを使用したプログラミングです。

以下のコードの一部は、その本の例に基づいています。

注:これはテストされていないコードであり、開始点としてのみ使用されます。

- (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;
}

コンテキスト作成機能:

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];
于 2010-03-03T15:12:35.150 に答える
1

pngnq(およびより高い品質を実現する新しいpngquant)にはBSDスタイルのライセンスがあるため、プログラムに含めることができます。別のタスクとしてスポーンする必要はありません。

于 2010-03-10T12:49:59.250 に答える
0

試してみる1つのことは、8ビットでNSBitmapImageRepを作成し、それにデータをコピーすることです。

カラーインデックステーブルを自分で計算する必要があるため、これは実際には多くの作業になります。

于 2010-03-03T04:16:36.243 に答える
0

CGImageDestination低レベルの画像作成のあなたの男ですが、それがその特定の能力をサポートしているかどうかはわかりません。

于 2010-03-03T10:18:38.107 に答える