Comment redimensionner l’image par programmation dans objective-c dans iphone

J’ai une application où j’affiche de grandes images dans un petit espace. Les images sont assez grandes, mais je ne les affiche que dans des images de 100×100 pixels. Mon application répond lentement en raison de la taille des images que j’utilise.

Pour améliorer les performances, comment puis-je redimensionner les images par programmation en utilisant Objective-C?

Veuillez trouver le code suivant.

- (UIImage *)imageWithImage:(UIImage *)image convertToSize:(CGSize)size { UIGraphicsBeginImageContext(size); [image drawInRect:CGRectMake(0, 0, size.width, size.height)]; UIImage *destImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return destImage; } 

Ce code sert uniquement à modifier l’échelle de l’image et non à redimensionner Vous devez définir CGSize comme largeur et hauteur de l’image afin que l’image ne s’étire pas et qu’elle soit disposée au milieu.

 - (UIImage *)imageWithImage:(UIImage *)image scaledToFillSize:(CGSize)size { CGFloat scale = MAX(size.width/image.size.width, size.height/image.size.height); CGFloat width = image.size.width * scale; CGFloat height = image.size.height * scale; CGRect imageRect = CGRectMake((size.width - width)/2.0f, (size.height - height)/2.0f, width, height); UIGraphicsBeginImageContextWithOptions(size, NO, 0); [image drawInRect:imageRect]; UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return newImage; } 

Ma méthode préférée consiste à CGImageSourceCreateThumbnailAtIndex (dans le cadre d’ImageIO). Le nom est un peu trompeur.

Voici un extrait d’un code d’une application récente.

 CGFloat maxw = // whatever; CGFloat maxh = // whatever; CGImageSourceRef src = NULL; if ([imageSource isKindOfClass:[NSURL class]]) src = CGImageSourceCreateWithURL((__bridge CFURLRef)imageSource, nil); else if ([imageSource isKindOfClass:[NSData class]]) src = CGImageSourceCreateWithData((__bridge CFDataRef)imageSource, nil); // if at double resolution, double the thumbnail size and use double-resolution image CGFloat scale = 1; if ([[UIScreen mainScreen] scale] > 1.0) { scale = 2; maxw *= 2; maxh *= 2; } // load the image at the desired size NSDictionary* d = @{ (id)kCGImageSourceShouldAllowFloat: (id)kCFBooleanTrue, (id)kCGImageSourceCreateThumbnailWithTransform: (id)kCFBooleanTrue, (id)kCGImageSourceCreateThumbnailFromImageAlways: (id)kCFBooleanTrue, (id)kCGImageSourceThumbnailMaxPixelSize: @((int)(maxw > maxh ? maxw : maxh)) }; CGImageRef imref = CGImageSourceCreateThumbnailAtIndex(src, 0, (__bridge CFDictionaryRef)d); if (NULL != src) CFRelease(src); UIImage* im = [UIImage imageWithCGImage:imref scale:scale orientation:UIImageOrientationUp]; if (NULL != imref) CFRelease(imref); 

Si vous utilisez une image de différentes tailles et redimensionnez à chaque fois, les performances de votre application seront dégradées. La solution est de ne pas les redimensionner, utilisez simplement le bouton à la place de imageview. et il suffit de définir l’image sur le bouton, il sera automatiquement redimensionné et vous obtiendrez d’excellentes performances.

Je redimensionnais aussi les images en les plaçant sur la cellule, mais mon application était lente. J’ai donc utilisé Button à la place de imageview (le fait de ne pas redimensionner les images par bouton fait ce travail) et cela fonctionne parfaitement.

  -(UIImage *)scaleImage:(UIImage *)image toSize:. (CGSize)targetSize { //If scaleFactor is not touched, no scaling will occur CGFloat scaleFactor = 1.0; //Deciding which factor to use to scale the image (factor = targetSize / imageSize) if (image.size.width > targetSize.width || image.size.height > targetSize.height || image.size.width == image.size.height) if (!((scaleFactor = (targetSize.width / image.size.width)) > (targetSize.height / image.size.height))) //scale to fit width, or scaleFactor = targetSize.height / image.size.height; // scale to fit heigth. 

Étant donné que le code fonctionnait parfaitement dans iOS 4, pour une compatibilité ascendante, j’ai ajouté un chèque pour la version du système d’exploitation et pour tout ce qui était inférieur à 5.0, l’ancien code fonctionnerait.

 - (UIImage *)resizedImage:(CGSize)newSize interpolationQuality:(CGInterpolationQuality)quality { BOOL drawTransposed; CGAffineTransform transform = CGAffineTransformIdentity; if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 5.0) { // Apprently in iOS 5 the image is already correctly rotated, so we don't need to rotate it manually drawTransposed = NO; } else { switch (self.imageOrientation) { case UIImageOrientationLeft: case UIImageOrientationLeftMirrored: case UIImageOrientationRight: case UIImageOrientationRightMirrored: drawTransposed = YES; break; default: drawTransposed = NO; } transform = [self transformForOrientation:newSize]; } return [self resizedImage:newSize transform:transform drawTransposed:drawTransposed interpolationQuality:quality]; } 

Vous pouvez utiliser ceci.

[m_Image.layer setMinificationFilter:kCAFilterTrilinear];

Ce fil de discussion est ancien, mais c’est ce que j’ai fait en essayant de résoudre ce problème. Une fois l’image mise à l’échelle, elle ne s’affichait pas bien dans mon conteneur même si je désactivais la mise en page automatique. Le moyen le plus simple de résoudre ce problème pour l’afficher dans une ligne de tableau était de peindre l’image sur un fond blanc de taille fixe.

Fonction d’assistance

 +(UIImage*)scaleMaintainAspectRatio:(UIImage*)sourceImage :(float)i_width :(float)i_height { float newHeight = 0.0; float newWidth = 0.0; float oldWidth = sourceImage.size.width; float widthScaleFactor = i_width / oldWidth; float oldHeight = sourceImage.size.height; float heightScaleFactor = i_height / oldHeight; if (heightScaleFactor > widthScaleFactor) { newHeight = oldHeight * widthScaleFactor; newWidth = sourceImage.size.width * widthScaleFactor; } else { newHeight = sourceImage.size.height * heightScaleFactor; newWidth = oldWidth * heightScaleFactor; } // return image in white rect float cxPad = i_width - newWidth; float cyPad = i_height - newHeight; if (cyPad > 0) { cyPad = cyPad / 2.0; } if (cxPad > 0) { cxPad = cxPad / 2.0; } CGSize size = CGSizeMake(i_width, i_height); UIGraphicsBeginImageContextWithOptions(CGSizeMake(size.width, size.height), YES, 0.0); [[UIColor whiteColor] setFill]; UIRectFill(CGRectMake(0, 0, size.width, size.height)); [sourceImage drawInRect:CGRectMake((int)cxPad, (int)cyPad, newWidth, newHeight)]; UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return newImage; // will return scaled image at actual size, not in white rect // UIGraphicsBeginImageContext(CGSizeMake(newWidth, newHeight)); // [sourceImage drawInRect:CGRectMake(0, 0, newWidth, newHeight)]; // UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); // UIGraphicsEndImageContext(); // return newImage; } 

J’ai appelé ceci comme ceci à partir de ma vue de la table cellForRowAtIndexPath

  PFFile *childsPicture = [object objectForKey:@"picture"]; [childsPicture getDataInBackgroundWithBlock:^(NSData *imageData, NSError *error) { if (!error) { UIImage *largePicture = [UIImage imageWithData:imageData]; UIImage *scaledPicture = [Utility scaleMaintainAspectRatio:largePicture :70.0 :70.0 ]; PFImageView *thumbnailImageView = (PFImageView*)[cell viewWithTag:100]; thumbnailImageView.image = scaledPicture; [self.tableView reloadData]; } }];