77 votes

Comment réduire une UIImage et de le rendre croustillant / sharp à la même heure, au lieu de flou?

J'ai besoin de redimensionner une image, mais une forte. Dans Photoshop par exemple, il ya la taille de l'image options de réduction "Bicubique plus Lisse" (flou) et "Bicubique plus net".

Est-ce l'image de désagrégation de l'algorithme open source ou documenté quelque part ou le SDK offrir des méthodes pour faire cela?

127voto

Yar Points 25421

Simplement en utilisant imageWithCGImage n'est pas suffisante. Il sera mis à l'échelle, mais le résultat sera floue et sous-optimale si la mise à l'échelle vers le haut ou vers le bas.

Si vous souhaitez obtenir de l'aliasing à droite et de se débarrasser de la dentelage vous besoin de quelque chose comme ceci: http://vocaro.com/trevor/blog/2009/10/12/resize-a-uiimage-the-right-way/.

Mon travail de test de code ressemble à quelque chose comme ceci, qui est de Trevor solution avec un petit ajustement à travailler avec mes transparent Png:

- (UIImage *)resizeImage:(UIImage*)image newSize:(CGSize)newSize {
    CGRect newRect = CGRectIntegral(CGRectMake(0, 0, newSize.width, newSize.height));
    CGImageRef imageRef = image.CGImage;

    UIGraphicsBeginImageContextWithOptions(newSize, NO, 0);
    CGContextRef context = UIGraphicsGetCurrentContext();

    // Set the quality level to use when rescaling
    CGContextSetInterpolationQuality(context, kCGInterpolationHigh);
    CGAffineTransform flipVertical = CGAffineTransformMake(1, 0, 0, -1, 0, newSize.height);

    CGContextConcatCTM(context, flipVertical);  
    // Draw into the context; this scales the image
    CGContextDrawImage(context, newRect, imageRef);

    // Get the resized image from the context and a UIImage
    CGImageRef newImageRef = CGBitmapContextCreateImage(context);
    UIImage *newImage = [UIImage imageWithCGImage:newImageRef];

    CGImageRelease(newImageRef);
    UIGraphicsEndImageContext();    

    return newImage;
}

21voto

BZMWillemsen Points 1104

Pour ceux qui utilisent Swift ici est la réponse à Swift:

func resizeImage(image: UIImage, newSize: CGSize) -> (UIImage) {
    let newRect = CGRectIntegral(CGRectMake(0,0, newSize.width, newSize.height))
    let imageRef = image.CGImage

    UIGraphicsBeginImageContextWithOptions(newSize, false, 0)
    let context = UIGraphicsGetCurrentContext()

    // Set the quality level to use when rescaling
    CGContextSetInterpolationQuality(context, kCGInterpolationHigh)
    let flipVertical = CGAffineTransformMake(1, 0, 0, -1, 0, newSize.height)

    CGContextConcatCTM(context, flipVertical)
    // Draw into the context; this scales the image
    CGContextDrawImage(context, newRect, imageRef)

    let newImageRef = CGBitmapContextCreateImage(context) as CGImage
    let newImage = UIImage(CGImage: newImageRef)

    // Get the resized image from the context and a UIImage
    UIGraphicsEndImageContext()

    return newImage
}

13voto

NSExplorer Points 1308

Si vous conserver les proportions d'origine de l'image pendant la mise à l'échelle, vous aurez toujours se retrouver avec une image nette, peu importe combien vous l'échelle vers le bas.

Vous pouvez utiliser la méthode suivante pour la mise à l'échelle:

+ (UIImage *)imageWithCGImage:(CGImageRef)imageRef scale:(CGFloat)scale orientation:(UIImageOrientation)orientation

2voto

Alexander Points 2514

@YAR votre solution fonctionne correctement.

Il y a une seule chose qui ne correspond pas à mes exigences: La totalité de l'image est redimensionnée. J'ai écrit une Méthode qui n'a comme l' photos app on iphone. Ce calcule le "côté le plus long" et coupe la "superposition" qui résulte de l'obtenir de bien meilleurs résultats concernant la qualité de l'image.

- (UIImage *)resizeImageProportionallyIntoNewSize:(CGSize)newSize;
{
    CGFloat scaleWidth = 1.0f;
    CGFloat scaleHeight = 1.0f;

    if (CGSizeEqualToSize(self.size, newSize) == NO) {

        //calculate "the longer side"
        if(self.size.width > self.size.height) {
            scaleWidth = self.size.width / self.size.height;
        } else {
            scaleHeight = self.size.height / self.size.width;
        }
    }    

    //prepare source and target image
    UIImage *sourceImage = self;
    UIImage *newImage = nil;

    // Now we create a context in newSize and draw the image out of the bounds of the context to get
    // A proportionally scaled image by cutting of the image overlay
    UIGraphicsBeginImageContext(newSize);

    //Center image point so that on each egde is a little cutoff
    CGRect thumbnailRect = CGRectZero;
    thumbnailRect.size.width  = newSize.width * scaleWidth;
    thumbnailRect.size.height = newSize.height * scaleHeight;
    thumbnailRect.origin.x = (int) (newSize.width - thumbnailRect.size.width) * 0.5;
    thumbnailRect.origin.y = (int) (newSize.height - thumbnailRect.size.height) * 0.5;

    [sourceImage drawInRect:thumbnailRect];

    newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    if(newImage == nil) NSLog(@"could not scale image");

    return newImage ;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X