Question

Voici ce que j'ai à ce jour:

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

Le code suppose qu'un PNG 200x200 sera inférieure à 128K, qui est ma limite de taille. 200x200 est assez grand, mais je préfère au maximum de la taille si possible.

Voici mes deux problèmes:

  1. Le code ne fonctionne pas. Je vérifie la taille du fichier exporté et il est de la même taille que l'original.
  2. Est-il possible de prédire la taille du fichier de sortie avant l'exportation, donc je peux max les dimensions mais toujours obtenir une image qui est inférieur à 128K?

Voici le code de travail. Il est assez bâclée et pourrait probablement utiliser quelques optimisations, mais à ce stade, il va assez vite que je ne me soucie pas. Il itère sur 100x pour la plupart des images, et il est plus en millisecondes. En outre, cette méthode est déclarée dans une catégorie sur 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;
}
Était-ce utile?

La solution

Pour 1.

Comme autre affiche mentionné, setSize modifie uniquement la taille d'affichage de l'image, et non les données de pixel réel du fichier d'image sous-jacente.

Pour redimensionner, vous pouvez redessiner l'image source sur un autre NSImageRep puis écrire que le fichier.

Ce blog contient quelques exemples de code sur la façon de faire le redimensionnement de cette manière.

Comment Redimensionner un NSImage

Pour 2.

Je ne pense pas que vous pouvez sans au moins créer l'objet en mémoire et vérifier la longueur de l'image. Les octets réels utilisés dépendront du type d'image. Bitmaps avec ARVB seront faciles à prédire leur taille, mais PNG et JPEG serait beaucoup plus difficile.

Autres conseils

[imageData length] devrait vous donner la longueur du contenu du NSData, que je crois être la taille du fichier final lors de l'écriture sur le disque. Cela devrait vous donner une chance de maximiser la taille du fichier avant d'écrire réellement.

Quant à savoir pourquoi l'image ne diminue pas ou de plus en plus, selon la documentation pour setSize :

  

La taille d'une représentation d'image combinée avec les dimensions physiques des données d'image détermine la résolution de l'image.

Il se peut que la taille en définissant et ne pas modifier la résolution que vous n'êtes pas modifier les pixels, juste la façon dont les pixels doivent être interprétés.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top