无法创建/使用JPEG-2000格式的缩略图

时间:2011-06-23 04:53:38

标签: cocoa thumbnails jpeg2000

我正在构建一个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 );
}

当我在预览中查看拇指。*文件时,它们看起来都很好(除了JPG,因为它有任何非填充区域的白色背景)。但是如果我使用JPEG-2000,thumbnailImageRef中显示的drawRect在图像外部(在我放在它下面的红色矩形中)会有额外的黑色标记。它看起来非常适合PNG和GIF,除了白色背景外,对于JPG来说看起来还不错。但是因为JPEG-2000的大小是我真正想要使用它的下一个最小对象的1/4。

我无法弄清楚小黑标的来源。有没有人有任何建议?

屏幕截图示例: 图像要缩略图(忽略红色方块) This is the image that the thumbnail will be created from...

以上缩略图使用JPEG-2000作为thumbnailSrc(在红色方块中) This has the thumbnail from the above in the red square...

使用JPEG从顶部开始的缩略图(在红色方块中) enter image description here

使用GIF从顶部开始的缩略图(在红色方块中) enter image description here

我在这些之间切换的唯一变化是#if /#elif /#endif部分中的'1'和'0'。

我想在尺寸方面使用JPEG-2000,但看起来像是GIF图像。

谢谢!

1 个答案:

答案 0 :(得分:0)

您是否尝试过直接使用CGImageDestination而不是NSBitmapImageRep来创建缩略图数据?