Есть ли лучший способ увеличить размер NSImage до максимального размера файла?

StackOverflow https://stackoverflow.com/questions/1563381

Вопрос

Вот что у меня есть на данный момент:

NSBitmapImageRep *imageRep = [NSBitmapImageRep imageRepWithData:
               [file.image TIFFRepresentation]];
// Resize image to 200x200
CGFloat maxSize = 200.0;
NSSize imageSize = imageRep.size;
if (imageSize.height>maxSize || imageSize.width>maxSize) {
    // Find the aspect ratio
    CGFloat aspectRatio = imageSize.height/imageSize.width;
    CGSize newImageSize;
    if (aspectRatio > 1.0) {
        newImageSize = CGSizeMake(maxSize / aspectRatio, maxSize);
    } else if (aspectRatio < 1.0) {
        newImageSize = CGSizeMake(maxSize, maxSize * aspectRatio);
    } else {
        newImageSize = CGSizeMake(maxSize, maxSize);
    }
    [imageRep setSize:NSSizeFromCGSize(newImageSize)];
}


NSData *imageData = [imageRep representationUsingType:NSPNGFileType properties:nil];
NSString *outputFilePath = [@"~/Desktop/output.png" stringByExpandingTildeInPath];
[imageData writeToFile:outputFilePath atomically:NO];

Код предполагает, что размер PNG размером 200x200 будет меньше 128 КБ, что является моим ограничением по размеру.200x200 - это достаточно большой размер, но я бы предпочел увеличить его по максимуму, если это вообще возможно.

Вот мои две проблемы:

  1. Код не работает.Я проверяю размер экспортированного файла, и он того же размера, что и оригинал.
  2. Есть ли способ предсказать размер выходного файла перед экспортом, чтобы я мог увеличить размеры, но при этом получить изображение размером менее 128 КБ?

Вот рабочий код.Это довольно неаккуратно, и, вероятно, не помешала бы некоторая оптимизация, но на данный момент это работает достаточно быстро, так что мне все равно.Он повторяется более 100 раз для большинства изображений, и все заканчивается за миллисекунды.Кроме того, этот метод объявлен в категории на NSImage.

- (NSData *)resizeImageWithBitSize:(NSInteger)size 
                      andImageType:(NSBitmapImageFileType)fileType {

    CGFloat maxSize = 500.0;
    NSSize originalImageSize = self.size;
    NSSize newImageSize;
    NSData *returnImageData;
    NSInteger imageIsTooBig = 1000;

    while (imageIsTooBig > 0) {
            if (originalImageSize.height>maxSize || originalImageSize.width>maxSize) {
            // Find the aspect ratio
            CGFloat aspectRatio = originalImageSize.height/originalImageSize.width;
            if (aspectRatio > 1.0) {
                newImageSize = NSMakeSize(maxSize / aspectRatio, maxSize);
            } else if (aspectRatio < 1.0) {
                newImageSize = NSMakeSize(maxSize, maxSize * aspectRatio);
            } else {
                newImageSize = NSMakeSize(maxSize, maxSize);
            }
        } else {
            newImageSize = originalImageSize;
        }

        NSImage *resizedImage = [[NSImage alloc] initWithSize:newImageSize];

        [resizedImage lockFocus];
        [self drawInRect:NSMakeRect(0, 0, newImageSize.width, newImageSize.height)
                fromRect: NSMakeRect(0, 0, originalImageSize.width, originalImageSize.height) 
               operation: NSCompositeSourceOver 
                fraction: 1.0];
        [resizedImage unlockFocus];

        NSData *tiffData = [resizedImage TIFFRepresentation];
        [resizedImage release];

        NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithData:tiffData];
        NSDictionary *imagePropDict = [NSDictionary 
                                       dictionaryWithObject:[NSNumber numberWithFloat:0.85] 
                                                     forKey:NSImageCompressionFactor];

        returnImageData = [imageRep representationUsingType:fileType properties:imagePropDict];
        [imageRep release];

        if ([returnImageData length] > size) {
            maxSize = maxSize * 0.99;
            imageIsTooBig--;
        } else {
            imageIsTooBig = 0;
        }

    }

    return returnImageData;
}
Это было полезно?

Решение

Для 1.

Как упоминалось в другом постере, setSize изменяет только размеры отображения изображения, а не фактические пиксельные данные базового файла изображения.

Чтобы изменить размер, вы можете захотеть перерисовать исходное изображение на другой NSImageRep, а затем записать это в файл.

Это сообщение в блоге содержит некоторый пример кода о том, как изменить размер таким образом.

Как изменить размер NSImage

Для 2.

Я не думаю, что вы сможете, по крайней мере, не создав объект в памяти и не проверив длину изображения.Фактическое количество используемых байтов будет зависеть от типа изображения.Растровые изображения с ARGB будет легко предсказать их размер, но PNG и JPEG будут намного сложнее.

Другие советы

[imageData length] должно дать вам длину содержимого NSData, которое, как я понимаю, является конечным размером файла при записи на диск.Это должно дать вам возможность увеличить размер файла до его фактической записи.

Что касается того, почему изображение не уменьшается и не растет, согласно документы для setSize:

Размер представления изображения в сочетании с физическими размерами данных изображения определяют разрешение изображения.

Таким образом, может случиться так, что, устанавливая размер и не изменяя разрешение, вы не изменяете никаких пикселей, а только то, как эти пиксели должны интерпретироваться.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top