Pregunta

Aquí es lo que tengo hasta ahora:

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

El código se supone que una de 200x200 PNG serán menos de 128 K, que es mi límite de tamaño.200x200 es lo suficientemente grande, pero prefiero al máximo el tamaño, si es posible.

Aquí están mis dos problemas:

  1. El código no funciona.Puedo comprobar el tamaño del archivo exportado y es del mismo tamaño que el original.
  2. Hay una manera de predecir el tamaño del archivo de salida antes de la exportación, por lo que puede máximo fuera de las dimensiones, pero aún así obtener una imagen de menos de 128K?

Aquí está el código de trabajo.Es muy descuidado y, probablemente, podría utilizar algunas optimizaciones, pero en este punto es que funciona lo suficientemente rápido como que no me importa.Se itera a través de 100x para la mayoría de las imágenes, y es en milisegundos.Además, este método es declarado en una categoría en la 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;
}
¿Fue útil?

Solución

Para 1.

Como otro cartel mencionado, setSize sólo altera el tamaño de visualización de la imagen, y no el real de los datos de los píxeles de la imagen de fondo de archivo.

Para cambiar el tamaño, puede que desee volver a dibujar la imagen de origen a otro NSImageRep y, a continuación, escribir a un archivo.

Este blog contiene algún código de ejemplo sobre cómo hacer el cambio de tamaño en esta manera.

Cómo cambiar el tamaño de un NSImage

2.

No creo que pueda, sin que, al menos, crear el objeto en la memoria y la comprobación de la longitud de la imagen.Los bytes utilizado dependerá del tipo de imagen.Los mapas de bits con ARGB será fácil predecir su tamaño, pero en PNG y JPEG sería mucho más difícil.

Otros consejos

[imageData length] debe darle la longitud de los contenidos de la NSData, que entiendo que es el tamaño final del archivo cuando se escribe en el disco. Eso te dará la oportunidad de maximizar el tamaño del archivo antes de escribirlo.

cuanto a por qué la imagen no se está reduciendo o en crecimiento, de acuerdo con la documentación para setSize :

  

El tamaño de una representación de la imagen combinada con las dimensiones físicas de los datos de imagen a determinar la resolución de la imagen.

Así que puede ser que al establecer el tamaño y la no alteración de la resolución que no está modificando los píxeles, de la manera en la que los píxeles deben ser interpretados.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top