web-dev-qa-db-fra.com

Comment redimensionner l'image par programme 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 par trames de 100x100 pixels . Mon application réagit lentement à cause de la taille des images que j'utilise.

Pour améliorer les performances, comment puis-je redimensionner les images par programme à l'aide d'Objective-C?

42
Madan Mohan

S'il vous plaît 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;
}
93
Satya

Ce code est juste pour changer l'échelle de l'image et non pour le redimensionner. Vous devez définir CGSize comme largeur et hauteur de votre image pour que l’image ne s’étire pas et qu’elle s’arrange 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;
}
9
Kaushik Movaliya

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

Voici un extrait de 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);
4
matt

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

J'étais également en train de redimensionner des images tout en l'installant dans la cellule, mais mon application est devenue lente. J'ai donc utilisé Button à la place de imageview (le redimensionnement non programmé des images est effectué par ce bouton) et tout fonctionne parfaitement.

2
Vijay Sharma
   -(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.
1
user8115970

Vous pouvez utiliser ceci.

[m_Image.layer setMinificationFilter:kCAFilterTrilinear];

0
Yusuf terzi

Comme le code fonctionnait parfaitement sous iOS 4, pour des raisons de compatibilité ascendante, j’ai ajouté une vérification de la version du système d’exploitation.

- (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];
}
0
iAndroid

Bonjour à partir de fin 2018 . Résolu avec la solution suivante (vous n'avez besoin que de la dernière ligne, les première et deuxième sont juste pour des explications):

NSURL *url = [NSURL URLWithString:response.json[0][@"photo_50"]];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:data scale:customScale];

'customScale' est l'échelle que vous souhaitez (> 1 si l'image doit être plus petite, <1 si l'image doit être plus grande).

0
Sergey Alyoshin

Ce fil est vieux, mais c’est ce que j’ai tiré en essayant de résoudre ce problème. Une fois que l'image a été redimensionnée, son conteneur ne s'affichait pas bien que j'aie désactivé la mise en page automatique. Pour moi, le moyen le plus simple de résoudre ce problème et de l’afficher dans une ligne du tableau consistait à 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é cela comme ceci depuis ma vue de 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];
    }
}];
0
Eric Witherspoon