Проблемы с созданием / использованием эскиза формата JPEG-2000 - PullRequest
0 голосов
/ 23 июня 2011

Я создаю приложение Какао, чтобы помочь мне организовать свои миллионы цифровых фотографий.Он предназначен для хранения очень скудной базы данных, позволяющей мне находить нужные мне изображения, а затем я могу пойти в хранилище, где храню настоящие изображения (записанные на 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 размера следующего наименьшего объекта, я действительно хочу его использовать.

Я не могу понять, откуда берутся маленькие черные метки.У кого-нибудь есть какие-либо предложения?

Пример снимков экрана: изображение, на которое нужно навести ногу (игнорируя красный квадрат) 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

Единственными изменениями, которые я сделал для переключения между ними, были '1' и '0' в разделе # if / # elif / # endif.

Я хотел бы использовать JPEG-2000 по соображениям размера, но он выглядиткак изображение GIF.

Спасибо!

1 Ответ

0 голосов
/ 24 июня 2011

Вы пытались использовать CGImageDestination напрямую вместо NSBitmapImageRep для создания миниатюрных данных?

...