我正在构建一个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。
我无法弄清楚小黑标的来源。有没有人有任何建议?
屏幕截图示例: 图像要缩略图(忽略红色方块)
以上缩略图使用JPEG-2000作为thumbnailSrc(在红色方块中)
使用JPEG从顶部开始的缩略图(在红色方块中)
使用GIF从顶部开始的缩略图(在红色方块中)
我在这些之间切换的唯一变化是#if /#elif /#endif部分中的'1'和'0'。
我想在尺寸方面使用JPEG-2000,但看起来像是GIF图像。
谢谢!
答案 0 :(得分:0)
您是否尝试过直接使用CGImageDestination而不是NSBitmapImageRep来创建缩略图数据?