Domanda

Ecco quello che ho finora:

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

Il codice presuppone che un 200x200 PNG sarà inferiore a 128 K, che è il mio limite di dimensione. 200x200 è abbastanza grande, ma preferisco al massimo fuori le dimensioni, se possibile.

Ecco le mie due problemi:

  1. Il codice non funziona. Posso controllare la dimensione del file esportato ed è la stessa dimensione dell'originale.
  2. C'è un modo per prevedere la dimensione del file di output prima esporto, così posso massimo le dimensioni, ma ancora ottenere un'immagine che è meno di 128K?

Ecco il codice di lavoro. E 'piuttosto sciatta e probabilmente potrebbe utilizzare alcune ottimizzazioni, ma a questo punto si corre abbastanza veloce che non mi interessa. Si itera su 100x per la maggior parte le immagini, ed è finita in millisecondi. Inoltre, questo metodo viene dichiarato in una categoria a 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;
}
È stato utile?

Soluzione

Per 1.

Come un altro poster accennato, setSize altera solo i formati di visualizzazione dell'immagine, e non i dati effettivi di pixel del file immagine sottostante.

Per ridimensionare, si consiglia di ridisegnare l'immagine di origine su un altro NSImageRep e poi scrivere che al file.

Questo post contiene alcuni esempi di codice su come fare il ridimensionamento in questo modo.

Come ridimensionare un NSImage

Per 2.

Non credo che si può senza almeno creare l'oggetto in memoria e controllare la lunghezza dell'immagine. I byte effettivi utilizzati dipenderanno dal tipo di immagine. Bitmap con ARGB sarà facile prevedere le loro dimensioni, ma PNG e JPEG sarebbe molto più difficile.

Altri suggerimenti

[imageData length] dovrebbe dare la lunghezza del contenuto del NSData, che capisco di essere la dimensione del file finale, quando scritto su disco. Questo dovrebbe dare la possibilità di massimizzare la dimensione del file prima di poter realmente scriverlo.

Per quanto riguarda il motivo per cui l'immagine non si sta restringendo o la coltivazione, secondo il la documentazione per setSize :

  

La dimensione di una rappresentazione dell'immagine combinata con le dimensioni fisiche dei dati di immagine determina la risoluzione dell'immagine.

Quindi può essere che impostando la dimensione e non alterare la risoluzione che non stai modificando i pixel, solo il modo in cui i pixel devono essere interpretati.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top