Pergunta

Aqui está o que eu tenho até agora:

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];

O código pressupõe que um PNG de 200x200 será menor que 128k, que é o meu limite de tamanho. 200x200 é grande o suficiente, mas eu prefiro maximizar o tamanho, se possível.

Aqui estão meus dois problemas:

  1. O código não funciona. Eu verifico o tamanho do arquivo exportado e é do mesmo tamanho que o original.
  2. Existe uma maneira de prever o tamanho do arquivo de saída antes de exportar, para que eu possa maximizar as dimensões, mas ainda assim obter uma imagem menor que 128k?

Aqui está o código de trabalho. É muito desleixado e provavelmente poderia usar algumas otimizações, mas neste momento ele funciona rápido o suficiente para que eu não me importe. Ele itera mais de 100x para a maioria das fotos e acaba em milissegundos. Além disso, esse método é declarado em uma categoria em 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;
}
Foi útil?

Solução

Por 1.

Como outro pôster mencionado, o SetSize apenas altera os tamanhos de exibição da imagem, e não os dados pixels reais do arquivo de imagem subjacente.

Para redimensionar, convém redesenhar a imagem de origem em outro NSIMAGEREP e, em seguida, escrevê -lo para arquivar.

Esta postagem do blog contém algum código de amostra sobre como fazer o redimensionamento dessa maneira.

Como redimensionar um nsimage

Para 2.

Eu não acho que você pode sem pelo menos criar o objeto na memória e verificar o comprimento da imagem. Os bytes reais utilizados dependerão do tipo de imagem. O Bitmaps com o ARGB será fácil de prever seu tamanho, mas o PNG e o JPEG seriam muito mais difíceis.

Outras dicas

[imageData length] Deve fornecer o comprimento do conteúdo do NSDATA, que eu entendo ser o tamanho final do arquivo quando gravado no disco. Isso deve dar a você a chance de maximizar o tamanho do arquivo antes de realmente escrevê -lo.

Sobre por que a imagem não está diminuindo ou crescendo, de acordo com os documentos para o Setsize:

O tamanho de uma representação de imagem combinada com as dimensões físicas dos dados da imagem determina a resolução da imagem.

Portanto, pode ser que, ao definir o tamanho e não alterar a resolução, você não está modificando nenhum pixels, exatamente a maneira pela qual os pixels devem ser interpretados.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top