Я создаю приложение Какао, чтобы помочь мне организовать свои миллионы цифровых фотографий.Он предназначен для хранения очень скудной базы данных, позволяющей мне находить нужные мне изображения, а затем я могу пойти в хранилище, где храню настоящие изображения (записанные на 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, поскольку у него белый фон любой незаполненной области).).Но thumbnailImageRef
, отображаемый в drawRect
, имеет дополнительные черные метки вне изображения (в красном прямоугольнике, который я поставил под ним), если я использую JPEG-2000.Он выглядит идеально для PNG и GIF и, за исключением белого фона, выглядит нормально для JPG.Но поскольку размер JPEG-2000 составляет 1/4 размера следующего наименьшего объекта, я действительно хочу его использовать.
Я не могу понять, откуда берутся маленькие черные метки.У кого-нибудь есть какие-либо предложения?
Пример снимков экрана: изображение, на которое нужно навести ногу (игнорируя красный квадрат)
Миниатюра сверху, используя JPEG-2000 в качестве thumbnailSrc (в красном квадрате)
Миниатюра сверху, используя JPEG (в красном квадрате)
Миниатюра сверху, используя GIF (в красном квадрате)
Единственными изменениями, которые я сделал для переключения между ними, были '1' и '0' в разделе # if / # elif / # endif.
Я хотел бы использовать JPEG-2000 по соображениям размера, но он выглядиткак изображение GIF.
Спасибо!