Come ridimensionare / ottimizzare facilmente le dimensioni di un'immagine con iOS?


114

La mia applicazione sta scaricando una serie di file immagine dalla rete e li sta salvando sul disco locale dell'iPhone. Alcune di queste immagini sono di dimensioni piuttosto grandi (larghezze superiori a 500 pixel, ad esempio). Poiché l'iPhone non ha nemmeno un display abbastanza grande per mostrare l'immagine nella sua dimensione originale, ho intenzione di ridimensionare l'immagine in qualcosa di un po 'più piccolo per risparmiare spazio / prestazioni.

Inoltre, alcune di queste immagini sono JPEG e non vengono salvate come normale impostazione di qualità del 60%.

Come posso ridimensionare un'immagine con iPhone SDK e come posso modificare l'impostazione della qualità di un'immagine JPEG?

Risposte:


246

Vengono forniti un paio di suggerimenti come risposte a questa domanda . Avevo suggerito la tecnica descritta in questo post , con il relativo codice:

+ (UIImage*)imageWithImage:(UIImage*)image 
               scaledToSize:(CGSize)newSize;
{
   UIGraphicsBeginImageContext( newSize );
   [image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
   UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
   UIGraphicsEndImageContext();

   return newImage;
}

Per quanto riguarda la memorizzazione dell'immagine, il formato immagine più veloce da utilizzare con l'iPhone è PNG, perché ha ottimizzazioni per quel formato. Tuttavia, se desideri memorizzare queste immagini come JPEG, puoi prendere il tuo UIImage e fare quanto segue:

NSData *dataForJPEGFile = UIImageJPEGRepresentation(theImage, 0.6);

Questo crea un'istanza NSData contenente i byte grezzi per un'immagine JPEG con un'impostazione di qualità del 60%. Il contenuto di tale istanza NSData può quindi essere scritto su disco o memorizzato nella cache.


1
signore ... ho scritto la stessa logica ma apparirà una linea retta bianca (ritratto) sul lato destro per favore dammi la soluzione
Nag_iphone

1
Ciao, come ci occupiamo di mantenere le proporzioni e le clip vincolate durante il ridimensionamento? Nel mio caso, quando ridimensiono un'immagine che ha una razione diversa da "newsize", ottengo un'immagine ridimensionata deformata. Grazie!
Van Du Tran

1
Questo ha funzionato in passato, ma in iOS5.0.1 e versioni successive si verifica una perdita di memoria. Qualche altro modo per ottenere questo risultato?
Usman Nisar

Consiglia di utilizzare [image drawInRect: rect blendMode: kCGBlendModeCopy alpha: 1.0] per prestazioni migliorate (quindi draw non deve eseguire calcoli di fusione durante il disegno
cdemiris99

Dovresti usare UIGraphicsBeginImageContextWithOptions (size, NO, 0.0); dove 0.0 utilizzerà la scala dello schermo principale per supportare la retina e oltre. Apple afferma: "In genere dovresti evitare di chiamare la funzione UIGraphicsBeginImageContext denominata in modo simile (tranne come riserva per la compatibilità con le versioni precedenti)".
Brad Goss

65

Il modo più semplice e diretto per ridimensionare le tue immagini sarebbe questo

float actualHeight = image.size.height;
float actualWidth = image.size.width;
float imgRatio = actualWidth/actualHeight;
float maxRatio = 320.0/480.0;

if(imgRatio!=maxRatio){
    if(imgRatio < maxRatio){
        imgRatio = 480.0 / actualHeight;
        actualWidth = imgRatio * actualWidth;
        actualHeight = 480.0;
    }
    else{
        imgRatio = 320.0 / actualWidth;
        actualHeight = imgRatio * actualHeight;
        actualWidth = 320.0;
    }
}
CGRect rect = CGRectMake(0.0, 0.0, actualWidth, actualHeight);
UIGraphicsBeginImageContext(rect.size);
[image drawInRect:rect];
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

Questo è bellissimo. Sono stato in grado di ridurre le immagini inviate a un server da circa 1Mb a 100k mantenendo la risoluzione del display retina (anche se ho cambiato i valori 320.0 e 480.0 in 640.0 e 1136.0) e ho anche fatto un po 'di compressione JPEG dopo il ridimensionamento: UIImageJPEGRepresentation (img, 0.7f);
Keller

2
E se il rapporto immagine e il rapporto massimo risultassero uguali? Ad esempio, se la dimensione di iamge è 3200x4800?
akshay1188

Questo ha funzionato in passato, ma in iOS5.0.1 e versioni successive si verifica una perdita di memoria. Qualche altro modo per ottenere questo risultato?
Usman Nisar

25

I metodi di cui sopra funzionano bene per immagini piccole, ma quando provi a ridimensionare un'immagine molto grande, esaurirai rapidamente la memoria e l'app si bloccherà. Un modo molto migliore è quello CGImageSourceCreateThumbnailAtIndexdi ridimensionare l'immagine senza prima decodificarla completamente.

Se hai il percorso dell'immagine che vuoi ridimensionare, puoi usare questo:

- (void)resizeImageAtPath:(NSString *)imagePath {
    // Create the image source (from path)
    CGImageSourceRef src = CGImageSourceCreateWithURL((__bridge CFURLRef) [NSURL fileURLWithPath:imagePath], NULL);

    // To create image source from UIImage, use this
    // NSData* pngData =  UIImagePNGRepresentation(image);
    // CGImageSourceRef src = CGImageSourceCreateWithData((CFDataRef)pngData, NULL);

    // Create thumbnail options
    CFDictionaryRef options = (__bridge CFDictionaryRef) @{
            (id) kCGImageSourceCreateThumbnailWithTransform : @YES,
            (id) kCGImageSourceCreateThumbnailFromImageAlways : @YES,
            (id) kCGImageSourceThumbnailMaxPixelSize : @(640)
    };
    // Generate the thumbnail
    CGImageRef thumbnail = CGImageSourceCreateThumbnailAtIndex(src, 0, options); 
    CFRelease(src);
    // Write the thumbnail at path
    CGImageWriteToFile(thumbnail, imagePath);
}

Maggiori dettagli qui .


Grazie, questa soluzione funziona a meraviglia), Conosci altri formati di file supportati da CGImageSourceoltre alle immagini e ai pdf?
sage444

Grazie. Stavo cercando un analogo inSampleSizeutilizzato dal decoder di Android. E questa è l'unica risposta che fornisce un modo per ridimensionare un'immagine in modo efficiente per la memoria.
Stan Mots

Ho ottenuto ottimi risultati lavorando direttamente con i file in archivio, funziona anche con le immagini in memoria ma non così rapidamente (per caricare l'immagine grande su un UIImage quindi ridimensionare).
Kendall Helmstetter Gelner

Non funziona nell'estensione di condivisione. L'app si blocca ancora con un'immagine molto grande.
George

18

Il modo migliore per ridimensionare le immagini senza perdere le proporzioni (ovvero senza allungare l'immagine) è utilizzare questo metodo:

//to scale images without changing aspect ratio
+ (UIImage *)scaleImage:(UIImage *)image toSize:(CGSize)newSize {

    float width = newSize.width;
    float height = newSize.height;

    UIGraphicsBeginImageContext(newSize);
    CGRect rect = CGRectMake(0, 0, width, height);

    float widthRatio = image.size.width / width;
    float heightRatio = image.size.height / height;
    float divisor = widthRatio > heightRatio ? widthRatio : heightRatio;

    width = image.size.width / divisor;
    height = image.size.height / divisor;

    rect.size.width  = width;
    rect.size.height = height;

    //indent in case of width or height difference
    float offset = (width - height) / 2;
    if (offset > 0) {
        rect.origin.y = offset;
    }
    else {
        rect.origin.x = -offset;
    }

    [image drawInRect: rect];

    UIImage *smallImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return smallImage;

}

Aggiungi questo metodo alla tua classe Utility in modo da poterlo utilizzare in tutto il progetto e accedervi in ​​questo modo:

xyzImageView.image = [Utility scaleImage:yourUIImage toSize:xyzImageView.frame.size];

Questo metodo si occupa del ridimensionamento mantenendo le proporzioni. Aggiunge anche rientri all'immagine nel caso in cui l'immagine ridotta abbia più larghezza che altezza (o viceversa).


8

Se hai il controllo sul server, ti consiglio vivamente di ridimensionare il lato server delle immagini con ImageMagik . Scaricare immagini di grandi dimensioni e ridimensionarle sul telefono è uno spreco di molte risorse preziose: larghezza di banda, batteria e memoria. Che sono scarsi sui telefoni.


2
FTFQ: "La mia applicazione sta scaricando una serie di file di immagine dalla rete"
Rog,

Questa potrebbe essere una risposta pertinente. La domanda indica che le immagini vengono scaricate dalla rete. Se l'OP può lavorare con il lato server delle immagini, dovrebbe. Se non può, la risposta aiuterà di più.
Joshua Dance

6

Ho sviluppato una soluzione definitiva per il ridimensionamento delle immagini in Swift.

Puoi usarlo per ridimensionare l'immagine per riempire, riempire l'aspetto o adattarlo alle dimensioni specificate.

È possibile allineare l'immagine al centro o uno qualsiasi dei quattro bordi e quattro angoli.

Inoltre, puoi ritagliare lo spazio aggiuntivo che viene aggiunto se le proporzioni dell'immagine originale e le dimensioni del target non sono uguali.

enum UIImageAlignment {
    case Center, Left, Top, Right, Bottom, TopLeft, BottomRight, BottomLeft, TopRight
}

enum UIImageScaleMode {
    case Fill,
    AspectFill,
    AspectFit(UIImageAlignment)
}

extension UIImage {
    func scaleImage(width width: CGFloat? = nil, height: CGFloat? = nil, scaleMode: UIImageScaleMode = .AspectFit(.Center), trim: Bool = false) -> UIImage {
        let preWidthScale = width.map { $0 / size.width }
        let preHeightScale = height.map { $0 / size.height }
        var widthScale = preWidthScale ?? preHeightScale ?? 1
        var heightScale = preHeightScale ?? widthScale
        switch scaleMode {
        case .AspectFit(_):
            let scale = min(widthScale, heightScale)
            widthScale = scale
            heightScale = scale
        case .AspectFill:
            let scale = max(widthScale, heightScale)
            widthScale = scale
            heightScale = scale
        default:
            break
        }
        let newWidth = size.width * widthScale
        let newHeight = size.height * heightScale
        let canvasWidth = trim ? newWidth : (width ?? newWidth)
        let canvasHeight = trim ? newHeight : (height ?? newHeight)
        UIGraphicsBeginImageContextWithOptions(CGSizeMake(canvasWidth, canvasHeight), false, 0)

        var originX: CGFloat = 0
        var originY: CGFloat = 0
        switch scaleMode {
        case .AspectFit(let alignment):
            switch alignment {
            case .Center:
                originX = (canvasWidth - newWidth) / 2
                originY = (canvasHeight - newHeight) / 2
            case .Top:
                originX = (canvasWidth - newWidth) / 2
            case .Left:
                originY = (canvasHeight - newHeight) / 2
            case .Bottom:
                originX = (canvasWidth - newWidth) / 2
                originY = canvasHeight - newHeight
            case .Right:
                originX = canvasWidth - newWidth
                originY = (canvasHeight - newHeight) / 2
            case .TopLeft:
                break
            case .TopRight:
                originX = canvasWidth - newWidth
            case .BottomLeft:
                originY = canvasHeight - newHeight
            case .BottomRight:
                originX = canvasWidth - newWidth
                originY = canvasHeight - newHeight
            }
        default:
            break
        }
        self.drawInRect(CGRectMake(originX, originY, newWidth, newHeight))
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }
}

Di seguito sono riportati esempi di applicazione di questa soluzione.

Il rettangolo grigio è l'immagine del sito di destinazione che verrà ridimensionata. I cerchi blu nel rettangolo azzurro è l'immagine (ho usato i cerchi perché è facile vedere quando è ridimensionato senza preservarne l'aspetto). Il colore arancione chiaro segna le aree che verranno tagliate se si passa trim: true.

Adattamento dell'aspetto prima e dopo il ridimensionamento:

Aspect fit 1 (prima) Aspect fit 1 (dopo)

Un altro esempio di adattamento dell'aspetto :

Aspect fit 2 (prima) Aspect fit 2 (dopo)

Aspetto in forma con allineamento in alto:

Aspect fit 3 (prima) Aspect fit 3 (dopo)

Riempimento aspetto :

Riempimento aspetto (prima) Riempimento aspetto (dopo)

Riempi :

Fill (prima) Riempi (dopo)

Ho usato l'upscaling nei miei esempi perché è più semplice da dimostrare, ma la soluzione funziona anche per il downscaling come in questione.

Per la compressione JPEG dovresti usare questo:

let compressionQuality: CGFloat = 0.75 // adjust to change JPEG quality
if let data = UIImageJPEGRepresentation(image, compressionQuality) {
  // ...
}

Puoi dare un'occhiata alla mia sintesi con il playground Xcode.


3

Per Swift 3, il codice seguente ridimensiona l'immagine mantenendo le proporzioni. Puoi leggere di più su ImageContext nella documentazione di Apple :

extension UIImage {
    class func resizeImage(image: UIImage, newHeight: CGFloat) -> UIImage {
        let scale = newHeight / image.size.height
        let newWidth = image.size.width * scale
        UIGraphicsBeginImageContext(CGSize(width: newWidth, height: newHeight))
        image.draw(in: CGRect(x: 0, y: 0, width: newWidth, height: newHeight))
        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return newImage!
    }
}

Per usarlo, chiama il resizeImage()metodo:

UIImage.resizeImage(image: yourImageName, newHeight: yourImageNewHeight)

2

puoi usare questo codice per ridimensionare l'immagine nella dimensione richiesta.

+ (UIImage *)scaleImage:(UIImage *)image toSize:(CGSize)newSize
{
    CGSize actSize = image.size;
    float scale = actSize.width/actSize.height;

    if (scale < 1) {
        newSize.height = newSize.width/scale;
    } 
    else {
        newSize.width = newSize.height*scale;
    }

    UIGraphicsBeginImageContext(newSize);
    [image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
    UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return newImage;
}

2

Secondo questa sessione, iOS Memory Deep Dive , faremmo un uso migliore ImageIOper ridimensionare le immagini.

Il cattivo dell'utilizzo di UIImageimmagini in scala ridotta.

  • Decomprimerà l'immagine originale nella memoria
  • Le trasformazioni dello spazio delle coordinate interne sono costose

Uso ImageIO

  • ImageIO può leggere le dimensioni delle immagini e le informazioni sui metadati senza sporcare la memoria.

  • ImageIO può ridimensionare le immagini solo al costo dell'immagine ridimensionata.

Informazioni sull'immagine in memoria

  • L'utilizzo della memoria è correlato alle dimensioni delle immagini, non alla dimensione del file.
  • UIGraphicsBeginImageContextWithOptionsutilizza sempre il SRGBformato di rendering, che utilizza 4 byte per pixel.
  • Un'immagine ha load -> decode -> render3 fasi.
  • UIImage è costoso per il dimensionamento e il ridimensionamento

Per l'immagine seguente, se si utilizza, UIGraphicsBeginImageContextWithOptions abbiamo solo bisogno di 590 KB per caricare un'immagine, mentre abbiamo bisogno di 2048 pixels x 1536 pixels x 4 bytes per pixel= 10 MB per la decodifica inserisci qui la descrizione dell'immagine

mentre UIGraphicsImageRenderer, introdotto in iOS 10, sceglierà automaticamente il miglior formato grafico in iOS12. Significa che puoi risparmiare il 75% della memoria sostituendolo UIGraphicsBeginImageContextWithOptionscon UIGraphicsImageRendererse non hai bisogno di SRGB.

Questo è il mio articolo sulle immagini iOS in memoria

func resize(url: NSURL, maxPixelSize: Int) -> CGImage? {
    let imgSource = CGImageSourceCreateWithURL(url, nil)
    guard let imageSource = imgSource else {
        return nil
    }

    var scaledImage: CGImage?
    let options: [NSString: Any] = [
            // The maximum width and height in pixels of a thumbnail.
            kCGImageSourceThumbnailMaxPixelSize: maxPixelSize,
            kCGImageSourceCreateThumbnailFromImageAlways: true,
            // Should include kCGImageSourceCreateThumbnailWithTransform: true in the options dictionary. Otherwise, the image result will appear rotated when an image is taken from camera in the portrait orientation.
            kCGImageSourceCreateThumbnailWithTransform: true
    ]
    scaledImage = CGImageSourceCreateThumbnailAtIndex(imageSource, 0, options as CFDictionary)

    return scaledImage
}


let filePath = Bundle.main.path(forResource:"large_leaves_70mp", ofType: "jpg")

let url = NSURL(fileURLWithPath: filePath ?? "")

let image = resize(url: url, maxPixelSize: 600)

o

// Downsampling large images for display at smaller size
func downsample(imageAt imageURL: URL, to pointSize: CGSize, scale: CGFloat) -> UIImage {
    let imageSourceOptions = [kCGImageSourceShouldCache: false] as CFDictionary
    let imageSource = CGImageSourceCreateWithURL(imageURL as CFURL, imageSourceOptions)!
    let maxDimensionInPixels = max(pointSize.width, pointSize.height) * scale
    let downsampleOptions =
        [kCGImageSourceCreateThumbnailFromImageAlways: true,
        kCGImageSourceShouldCacheImmediately: true,
        // Should include kCGImageSourceCreateThumbnailWithTransform: true in the options dictionary. Otherwise, the image result will appear rotated when an image is taken from camera in the portrait orientation.
        kCGImageSourceCreateThumbnailWithTransform: true,
        kCGImageSourceThumbnailMaxPixelSize: maxDimensionInPixels] as CFDictionary
    let downsampledImage =
        CGImageSourceCreateThumbnailAtIndex(imageSource, 0, downsampleOptions)!
    return UIImage(cgImage: downsampledImage)
}

1

Un problema che potrebbe verificarsi sui display retina è che la scala dell'immagine è impostata da ImageCapture o giù di lì. Le funzioni di ridimensionamento sopra non lo cambieranno. In questi casi il ridimensionamento non funzionerà correttamente.

Nel codice seguente, la scala è impostata su 1 (non ridimensionata) e l'immagine restituita ha le dimensioni che ti aspetteresti. Questo viene fatto durante la UIGraphicsBeginImageContextWithOptionschiamata.

-(UIImage *)resizeImage :(UIImage *)theImage :(CGSize)theNewSize {
    UIGraphicsBeginImageContextWithOptions(theNewSize, NO, 1.0);
    [theImage drawInRect:CGRectMake(0, 0, theNewSize.width, theNewSize.height)];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return newImage;
}

1

Aggiungendo alla sfilza di risposte qui, ma ho scelto una soluzione che ridimensiona in base alle dimensioni del file, piuttosto che alle dimensioni.

Ciò ridurrà sia le dimensioni che la qualità dell'immagine fino a raggiungere la dimensione specificata.

func compressTo(toSizeInMB size: Double) -> UIImage? {
    let bytes = size * 1024 * 1024
    let sizeInBytes = Int(bytes)
    var needCompress:Bool = true
    var imgData:Data?
    var compressingValue:CGFloat = 1.0

    while (needCompress) {

        if let resizedImage = scaleImage(byMultiplicationFactorOf: compressingValue), let data: Data = UIImageJPEGRepresentation(resizedImage, compressingValue) {

            if data.count < sizeInBytes || compressingValue < 0.1 {
                needCompress = false
                imgData = data
            } else {
                compressingValue -= 0.1
            }
        }
    }

    if let data = imgData {
        print("Finished with compression value of: \(compressingValue)")
        return UIImage(data: data)
    }
    return nil
}

private func scaleImage(byMultiplicationFactorOf factor: CGFloat) -> UIImage? {
    let size = CGSize(width: self.size.width*factor, height: self.size.height*factor)
    UIGraphicsBeginImageContext(size)
    draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
    if let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext() {
        UIGraphicsEndImageContext()
        return newImage;
    }
    return nil
}

Credito per il ridimensionamento in base alla dimensione della risposta


1

Versione rapida

func resizeImage(image: UIImage, newWidth: CGFloat) -> UIImage? {

    let scale = newWidth / image.size.width
    let newHeight = CGFloat(200.0)
    UIGraphicsBeginImageContext(CGSize(width: newWidth, height: newHeight))
    image.draw(in: CGRect(x: 0, y: 0, width: newWidth, height: newHeight))

    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return newImage
}

0

Ho finito per usare la tecnica Brads per creare un scaleToFitWidthmetodo UIImage+Extensionsse fosse utile a chiunque ...

-(UIImage *)scaleToFitWidth:(CGFloat)width
{
    CGFloat ratio = width / self.size.width;
    CGFloat height = self.size.height * ratio;

    NSLog(@"W:%f H:%f",width,height);

    UIGraphicsBeginImageContext(CGSizeMake(width, height));
    [self drawInRect:CGRectMake(0.0f,0.0f,width,height)];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return newImage;
}

poi ovunque tu voglia

#import "UIImage+Extensions.h"

UIImage *newImage = [image scaleToFitWidth:100.0f];

Vale anche la pena notare che potresti spostarlo più in basso in una UIView+Extensionsclasse se vuoi rendere le immagini da una UIView


0

Volevo solo rispondere a questa domanda per i programmatori di Cocoa Swift. Questa funzione restituisce NSImage con una nuova dimensione. Puoi usare quella funzione in questo modo.

        let sizeChangedImage = changeImageSize(image, ratio: 2)






 // changes image size

    func changeImageSize (image: NSImage, ratio: CGFloat) -> NSImage   {

    // getting the current image size
    let w = image.size.width
    let h = image.size.height

    // calculating new size
    let w_new = w / ratio 
    let h_new = h / ratio 

    // creating size constant
    let newSize = CGSizeMake(w_new ,h_new)

    //creating rect
    let rect  = NSMakeRect(0, 0, w_new, h_new)

    // creating a image context with new size
    let newImage = NSImage.init(size:newSize)



    newImage.lockFocus()

        // drawing image with new size in context
        image.drawInRect(rect)

    newImage.unlockFocus()


    return newImage

}

0

Se l'immagine è nella directory dei documenti, aggiungi questa estensione URL :

extension URL {
    func compressedImageURL(quality: CGFloat = 0.3) throws -> URL? {
        let imageData = try Data(contentsOf: self)
        debugPrint("Image file size before compression: \(imageData.count) bytes")

        let compressedURL = NSURL.fileURL(withPath: NSTemporaryDirectory() + NSUUID().uuidString + ".jpg")

        guard let actualImage = UIImage(data: imageData) else { return nil }
        guard let compressedImageData = UIImageJPEGRepresentation(actualImage, quality) else {
            return nil
        }
        debugPrint("Image file size after compression: \(compressedImageData.count) bytes")

        do {
            try compressedImageData.write(to: compressedURL)
            return compressedURL
        } catch {
            return nil
        }
    }
}

Uso:

guard let localImageURL = URL(string: "< LocalImagePath.jpg >") else {
    return
}

//Here you will get URL of compressed image
guard let compressedImageURL = try localImageURL.compressedImageURL() else {
    return
}

debugPrint("compressedImageURL: \(compressedImageURL.absoluteString)")

Nota: - Cambia <LocalImagePath.jpg> con il percorso dell'immagine jpg locale.


-1

Se qualcuno sta ancora cercando un'opzione migliore

-(UIImage *)scaleImage:(UIImage *)image toSize:(CGSize)targetSize {


    UIImage *sourceImage = image;
    UIImage *newImage = nil;

    CGSize imageSize = sourceImage.size;
    CGFloat width = imageSize.width;
    CGFloat height = imageSize.height;

    CGFloat targetWidth = targetSize.width;
    CGFloat targetHeight = targetSize.height;

    CGFloat scaleFactor = 0.0;
    CGFloat scaledWidth = targetWidth;
    CGFloat scaledHeight = targetHeight;

    CGPoint thumbnailPoint = CGPointMake(0.0,0.0);

    if (CGSizeEqualToSize(imageSize, targetSize) == NO) {

        CGFloat widthFactor = targetWidth / width;
        CGFloat heightFactor = targetHeight / height;

        if (widthFactor < heightFactor)
            scaleFactor = widthFactor;
        else
            scaleFactor = heightFactor;

        scaledWidth  = width * scaleFactor;
        scaledHeight = height * scaleFactor;

        // center the image


        if (widthFactor < heightFactor) {
            thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5;
        } else if (widthFactor > heightFactor) {
            thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5;
        }
    }


    // this is actually the interesting part:

    UIGraphicsBeginImageContext(targetSize);

    CGRect thumbnailRect = CGRectZero;
    thumbnailRect.origin = thumbnailPoint;
    thumbnailRect.size.width  = scaledWidth;
    thumbnailRect.size.height = scaledHeight;

    [sourceImage drawInRect:thumbnailRect];

    newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

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


    return newImage ;

}

-1
- (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();

    CGContextSetInterpolationQuality(context, kCGInterpolationHigh);
    CGAffineTransform flipVertical = CGAffineTransformMake(1, 0, 0, -1, 0, newSize.height);

    CGContextConcatCTM(context, flipVertical);
    CGContextDrawImage(context, newRect, imageRef);

    CGImageRef newImageRef = CGBitmapContextCreateImage(context);
    UIImage *newImage = [UIImage imageWithCGImage:newImageRef];

    CGImageRelease(newImageRef);
    UIGraphicsEndImageContext();

    return newImage;
}

Per favore, fornisci almeno qualche spiegazione del codice nella tua risposta. Inoltre, formatta il codice utilizzando l'editor di risposte per renderlo leggibile.
xpereta

-2

Per ridimensionare un'immagine ho risultati (grafici) migliori usando questa funzione al posto di DrawInRect:

- (UIImage*) reduceImageSize:(UIImage*) pImage newwidth:(float) pWidth
{
    float lScale = pWidth / pImage.size.width;
    CGImageRef cgImage = pImage.CGImage;
    UIImage   *lResult = [UIImage imageWithCGImage:cgImage scale:lScale
                            orientation:UIImageOrientationRight];
    return lResult;
}

Il rapporto di aspetto viene curato automaticamente

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.