-1

無数のデジタル写真を整理するのに役立つ Cocoa アプリケーションを作成しています。必要な画像を見つけることができるように、情報の非常に無駄のないデータベースを保持することを目的としています。その後、実際の画像 (DVD や CD に焼いたもの) を保管するストレージに移動できます。画像をブラウズして、評価やタグなどを設定できます。次に、このデータをハード ディスクに保存し、数十枚の写真よりも小さいデータベースを作成します。私のデータベースにサムネイル画像を保存したいと思います(これにより、約10倍大きくなります)。いくつかの手法を試してみましたが、JPEG-2000 形式を使用するのが最小ですが、適切に表示されないようですか?

サムネイルを作成する私のコードは次のとおりです。

    // This code 'downsamples' my very large digital pictures
        // Thumbnail size
        int pixelsWide = 72;
        int pixelsHigh = 72;
        CGContextRef    myBitmapContext = NULL;
        CGColorSpaceRef colorSpace;
        void        *bitmapData;
        int     bitmapByteCount;
        int     bitmapBytesPerRow;

        bitmapBytesPerRow   = (pixelsWide * 4);
        bitmapByteCount     = (bitmapBytesPerRow * pixelsHigh);

        colorSpace = CGColorSpaceCreateWithName( kCGColorSpaceGenericRGB );
        bitmapData = calloc( 1, bitmapByteCount );
        if( bitmapData == NULL ) {
            NSLog( @"Memory not allocated!" );
        } else {
            myBitmapContext = CGBitmapContextCreate( bitmapData,
                         pixelsWide,
                         pixelsHigh,
                         8,      // bits per component
                         bitmapBytesPerRow,
                         colorSpace,
                         kCGImageAlphaPremultipliedLast );
            if( myBitmapContext == NULL ) {
                free (bitmapData);
                NSLog( @"myBitmapContext not created!" );
            }
        }
        CGColorSpaceRelease( colorSpace );

        // This gets any zooming or rotating that I've done to the master image
        CGAffineTransform imageTransformMatrix = [self generateImageTransformMatrixForRect: NSMakeRect( 0.0, 0.0, (CGFloat) pixelsWide, (CGFloat) pixelsHigh )];

        CGContextConcatCTM( myBitmapContext, imageTransformMatrix );
        // imageRef is a CGImageRef to the master image to create the thumbnail of
        double imgWidth  = (double) CGImageGetWidth( imageRef );
        double imgHeight = (double) CGImageGetHeight( imageRef );
        NSRect dr = NSMakeRect( 0, 0, imgWidth, imgHeight );
        CGContextDrawImage( myBitmapContext, dr, imageRef );
    // This code pulls the downsampled image back in to save to the database
        thumbnailImageRef = CGBitmapContextCreateImage( myBitmapContext );
        bitmapData = CGBitmapContextGetData( myBitmapContext ); 
        CGContextRelease( myBitmapContext );
        if( bitmapData ) free( bitmapData );

        NSDictionary *JPGopts = [NSDictionary dictionaryWithObjectsAndKeys: NSImageCompressionFactor, [NSNumber numberWithFloat: 0.0], nil];
        NSBitmapImageRep *thumbnailBitmap = [[NSBitmapImageRep alloc] initWithCGImage: thumbnailImageRef];
        NSData *thumbnailDataJPG = [thumbnailBitmap representationUsingType: NSJPEGFileType properties: JPGopts];
        [thumbnailDataJPG writeToFile: @"/tmp/thumb.jpg" atomically: NO];
        NSData *thumbnailDataPNG = [thumbnailBitmap representationUsingType: NSPNGFileType properties: nil];
        [thumbnailDataPNG writeToFile: @"/tmp/thumb.png" atomically: NO];
        NSData *thumbnailDataGIF = [thumbnailBitmap representationUsingType: NSGIFFileType properties: nil];
        [thumbnailDataGIF writeToFile: @"/tmp/thumb.gif" atomically: NO];
        NSData *thumbnailDataJPG2 = [thumbnailBitmap representationUsingType: NSJPEG2000FileType properties: nil];
        [thumbnailDataJPG2 writeToFile: @"/tmp/thumb.jp2" atomically: NO];
        [thumbnailBitmap release];
        NSLog( @"The thumbnail sizes are %d for JPG, %d for PNG, %d for GIF, and %d for JPEG2000",
                    [thumbnailDataJPG length], 
                    [thumbnailDataPNG length], 
                    [thumbnailDataGIF length], 
                    [thumbnailDataJPG2 length] );
        // At this point I will store the selected NSData object to a BLOB in my database...

    // I change the 1's to 0's and rebuild to try different formats
    #if 1
        CGImageSourceRef thumbSrc = CGImageSourceCreateWithData( (CFDataRef) thumbnailDataJPG2, NULL );
    #elif 1
        CGImageSourceRef thumbSrc = CGImageSourceCreateWithData( (CFDataRef) thumbnailDataGIF, NULL );
    #elif 1
        CGImageSourceRef thumbSrc = CGImageSourceCreateWithData( (CFDataRef) thumbnailDataPNG, NULL );
    #else
        CGImageSourceRef thumbSrc = CGImageSourceCreateWithData( (CFDataRef) thumbnailDataJPG, NULL );
    #endif
        thumbnailImageRef = CGImageSourceCreateImageAtIndex( thumbSrc, 0, NULL );

次に、私のdrawRect方法では次のことを行います。

CGContextRef myContext = [[NSGraphicsContext currentContext] graphicsPort]; 
if( thumbnailImageRef ) {
    imgWidth  = (double) CGImageGetWidth( thumbnailImageRef );
    imgHeight = (double) CGImageGetHeight( thumbnailImageRef );
    // Make 4-pixel red border around thumbnail
    CGContextSetRGBFillColor( myContext, 1, 0, 0, 1);
    CGContextFillRect( myContext, CGRectMake( 96, 96, imgWidth+8, imgHeight+8 ) );
    // Draw the thumbnail image
    CGContextDrawImage( myContext, NSMakeRect( 100, 100, imgWidth, imgHeight ), thumbnailImageRef );
}

プレビューでthumb.*ファイルを見ると、すべて正常に見えます(塗りつぶされていない領域の白い背景があるため、JPGを除く)。しかし、JPEG-2000 を使用すると、画像の外側 (下に置いた赤い四角形) に余分な黒いマークthumbnailImageRefが表示されます。drawRectPNG と GIF には完璧に見えますが、白い背景を除けば JPG でも問題ありません。しかし、JPEG-2000 は次に小さいオブジェクトの 1/4 のサイズなので、どうしても使いたいと思います。

小さな黒いマークがどこから来ているのかわかりません。誰か提案はありますか?

スクリーンショットの例: サムネイルにする画像 (赤い四角は無視) これは、サムネイルが作成される画像です...

サムネイルSrcとしてJPEG-2000を使用した上記のサムネイル(赤い四角) これには、上の赤い四角のサムネイルがあります...

上からJPEGを使用したサムネイル(赤枠内) ここに画像の説明を入力

上からGIFを使ったサムネイル(赤枠内) ここに画像の説明を入力

これらを切り替えるために行った唯一の変更は、#if/#elif/#endif セクションの「1」と「0」です。

サイズの理由で JPEG-2000 を使用したいのですが、GIF 画像のように見えます。

ありがとう!

4

1 に答える 1

0

NSBitmapImageRep の代わりに CGImageDestination を直接使用してサムネイル データを作成しようとしましたか?

于 2011-06-23T20:15:13.047 に答える