Wie kann ich die Bildgröße mit iOS einfach ändern / optimieren?

114

Meine Anwendung lädt eine Reihe von Bilddateien aus dem Netzwerk herunter und speichert sie auf der lokalen iPhone-Festplatte. Einige dieser Bilder sind ziemlich groß (z. B. Breiten größer als 500 Pixel). Da das iPhone nicht einmal groß genug ist, um das Bild in seiner Originalgröße anzuzeigen, plane ich, die Größe des Bilds auf etwas kleiner zu ändern, um Platz und Leistung zu sparen.

Einige dieser Bilder sind JPEGs und werden nicht als übliche 60% -Qualitätseinstellung gespeichert.

Wie kann ich die Größe eines Bildes mit dem iPhone SDK ändern und wie kann ich die Qualitätseinstellung eines JPEG-Bildes ändern?

jpm
quelle

Antworten:

246

Als Antwort auf diese Frage werden einige Vorschläge gegeben . Ich hatte die in diesem Beitrag beschriebene Technik mit dem entsprechenden Code vorgeschlagen:

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

   return newImage;
}

In Bezug auf die Speicherung des Bildes ist PNG das schnellste Bildformat, das mit dem iPhone verwendet werden kann, da es Optimierungen für dieses Format aufweist. Wenn Sie diese Bilder jedoch als JPEGs speichern möchten, können Sie Ihr UIImage wie folgt ausführen:

NSData *dataForJPEGFile = UIImageJPEGRepresentation(theImage, 0.6);

Dadurch wird eine NSData-Instanz erstellt, die die Rohbytes für ein JPEG-Bild mit einer Qualitätseinstellung von 60% enthält. Der Inhalt dieser NSData-Instanz kann dann auf die Festplatte geschrieben oder im Speicher zwischengespeichert werden.

Brad Larson
quelle
1
Sir ... Ich habe die gleiche Logik geschrieben, aber eine weiße gerade Linie wird auf der rechten Seite erscheinen (Porträt). Bitte geben Sie mir eine Lösung
Nag_iphone
1
Hallo, wie gehen wir damit um, dass das Seitenverhältnis und die Clips beim Ändern der Größe gebunden bleiben? In meinem Fall erhalte ich ein deformiertes Bild in der Größe, wenn ich die Größe eines Bildes mit einer anderen Ration als "Newsize" ändere. Vielen Dank!
Van Du Tran
1
Dies hat in der Vergangenheit funktioniert, aber in iOS5.0.1 und höher führt dies zu einem Speicherverlust. Gibt es eine andere Möglichkeit, dies zu erreichen?
Usman Nisar
Empfehlen Sie die Verwendung von [image drawInRect: rect blendMode: kCGBlendModeCopy alpha: 1.0] für eine verbesserte Leistung (damit das Zeichnen während des Zeichnens keine Mischungsberechnung durchführen muss
cdemiris99
Sie sollten UIGraphicsBeginImageContextWithOptions (size, NO, 0.0) verwenden. Dabei verwendet 0.0 die Hauptbildschirmskala zur Unterstützung der Netzhaut und darüber. Apple gibt an: "Sie sollten generell vermeiden, die gleichnamige Funktion UIGraphicsBeginImageContext aufzurufen (außer als Fallback für die Abwärtskompatibilität)."
Brad Goss
65

Der einfachste und einfachste Weg, die Größe Ihrer Bilder zu ändern, ist dieser

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();
lostInTransit
quelle
Das ist schön. Ich konnte Bilder, die an einen Server gesendet wurden, von etwa 1 MB auf 100 KB reduzieren, während die Auflösung der Retina-Anzeige beibehalten wurde (obwohl ich die Werte für 320,0 und 480,0 auf 640,0 und 1136,0 geändert habe), und nach der Skalierung eine JPEG-Komprimierung durchführen: UIImageJPEGRepresentation (img, 0,7f);
Keller
2
Was ist, wenn sich das Bildverhältnis und das maximale Verhältnis als gleich herausstellen? Zum Beispiel, wenn die iamge-Größe 3200x4800 ist?
Akshay1188
Dies hat in der Vergangenheit funktioniert, aber in iOS5.0.1 und höher führt dies zu einem Speicherverlust. Gibt es eine andere Möglichkeit, dies zu erreichen?
Usman Nisar
25

Die oben genannten Methoden eignen sich gut für kleine Bilder. Wenn Sie jedoch versuchen, die Größe eines sehr großen Bildes zu ändern, geht Ihnen schnell der Speicher aus und die App stürzt ab. Eine viel bessere Möglichkeit besteht darin CGImageSourceCreateThumbnailAtIndex, die Größe des Bildes zu ändern, ohne es zuvor vollständig zu dekodieren.

Wenn Sie den Pfad zu dem Bild haben, dessen Größe Sie ändern möchten, können Sie Folgendes verwenden:

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

Weitere Details hier .

Pulkit Goyal
quelle
Vielen Dank, diese Lösung funktioniert wie ein Zauber. Kennen Sie andere Dateiformate, die CGImageSourceneben Bildern und PDFs auch unterstützt werden?
sage444
Vielen Dank. Ich suchte nach einem Analogon inSampleSize, das vom Android-Decoder verwendet wird. Und dies ist die einzige Antwort, die eine Möglichkeit bietet, ein Bild speichereffizient zu verkleinern.
Stan Mots
Ich hatte großartige Ergebnisse damit, direkt mit Dateien im Speicher zu arbeiten, funktioniert auch mit In-Memory-Bildern, aber nicht so schnell (um das große Bild auf ein UIImage zu laden und dann zu skalieren).
Kendall Helmstetter Gelner
Funktioniert nicht in der Freigabeerweiterung. App stürzt immer noch mit sehr großem Bild ab.
George
18

Der beste Weg, um Bilder zu skalieren, ohne das Seitenverhältnis zu verlieren (dh ohne das Bild zu dehnen), ist die Verwendung dieser Methode:

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

}

Fügen Sie diese Methode Ihrer Utility-Klasse hinzu, damit Sie sie im gesamten Projekt verwenden und wie folgt darauf zugreifen können:

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

Diese Methode sorgt für die Skalierung unter Beibehaltung des Seitenverhältnisses. Außerdem werden dem Bild Einrückungen hinzugefügt, falls das verkleinerte Bild mehr Breite als Höhe hat (oder umgekehrt).

Codebrand
quelle
8

Wenn Sie die Kontrolle über den Server haben, würde ich dringend empfehlen, die Größe der Bildserverseite mit ImageMagik zu ändern . Das Herunterladen und Ändern der Größe großer Bilder auf dem Telefon ist eine Verschwendung vieler wertvoller Ressourcen - Bandbreite, Akku und Speicher. All dies ist auf Telefonen selten.

Rog
quelle
2
FTFQ: "Meine Anwendung lädt eine Reihe von Bilddateien aus dem Netzwerk herunter"
Rog
Dies könnte eine relevante Antwort sein. Die Frage besagt, dass die Bilder aus dem Netzwerk heruntergeladen werden. Wenn das OP mit der Bildserverseite arbeiten kann, sollte er dies tun. Wenn er nicht kann, hilft die Antwort mehr.
Joshua Dance
6

Ich habe in Swift eine ultimative Lösung für die Bildskalierung entwickelt.

Sie können die Größe des Bilds so ändern, dass es die angegebene Größe füllt, füllt oder anpasst.

Sie können das Bild an der Mitte oder an einer der vier Kanten und vier Ecken ausrichten.

Außerdem können Sie zusätzlichen Platz kürzen, der hinzugefügt wird, wenn die Seitenverhältnisse von Originalbild und Zielgröße nicht gleich sind.

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
    }
}

Im Folgenden finden Sie Beispiele für die Anwendung dieser Lösung.

Das graue Rechteck ist die Größe des Zielseitenbilds. Blaue Kreise im hellblauen Rechteck sind das Bild (ich habe Kreise verwendet, weil es leicht zu erkennen ist, wenn es skaliert ist, ohne den Aspekt beizubehalten). Die hellorange Farbe markiert Bereiche, die beim Passieren zugeschnitten werden trim: true.

Aspektanpassung vor und nach der Skalierung:

Aspekt fit 1 (vorher) Aspekt fit 1 (nach)

Ein weiteres Beispiel für die Aspektanpassung :

Aspekt fit 2 (vorher) Aspekt fit 2 (nach)

Aspektanpassung mit oberer Ausrichtung:

Aspekt fit 3 (vorher) Aspekt fit 3 (nach)

Aspektfüllung :

Aspektfüllung (vorher) Aspektfüllung (nach)

Füllen :

Füllen Sie (vorher) Füllen Sie (nach)

In meinen Beispielen habe ich Upscaling verwendet, weil es einfacher zu demonstrieren ist, aber die Lösung funktioniert auch für das Downscaling wie in Frage.

Für die JPEG-Komprimierung sollten Sie Folgendes verwenden:

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

Sie können meinen Kern mit Xcode Spielplatz überprüfen .

mischen
quelle
3

Bei Swift 3 skaliert der folgende Code das Bild unter Beibehaltung des Seitenverhältnisses. Weitere Informationen zum ImageContext finden Sie in der Apple-Dokumentation :

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!
    }
}

Um es zu verwenden, rufen Sie die resizeImage()Methode auf:

UIImage.resizeImage(image: yourImageName, newHeight: yourImageNewHeight)
Alexandre Lara
quelle
2

Mit diesem Code können Sie das Bild in der erforderlichen Größe skalieren.

+ (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;
}
Amit Shelgaonkar
quelle
1

Ein Problem, das bei Retina-Displays auftreten kann, besteht darin, dass der Maßstab des Bildes von ImageCapture oder so festgelegt wird. Die obigen Größenänderungsfunktionen ändern dies nicht. In diesen Fällen funktioniert die Größenänderung nicht ordnungsgemäß.

Im folgenden Code wird die Skalierung auf 1 gesetzt (nicht skaliert) und das zurückgegebene Bild hat die erwartete Größe. Dies wird in dem getan UIGraphicsBeginImageContextWithOptionsAnruf.

-(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;
}
Vincent
quelle
1

Ich habe mich hier für eine Lösung entschieden, deren Größe sich eher nach Dateigröße als nach Abmessungen ändert.

Dadurch werden sowohl die Abmessungen als auch die Qualität des Bildes reduziert, bis die angegebene Größe erreicht ist.

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
}

Gutschrift für die Skalierung nach Größenantwort

Harry Bloom
quelle
1

Schnelle Version

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
}
Softlabsindia
quelle
1

Laut dieser Sitzung, iOS Memory Deep Dive , sollten wir ImageIOBilder besser verkleinern.

Das Schlechte an der Verwendung von UIImageverkleinerten Bildern.

  • Dekomprimiert das Originalbild in den Speicher
  • Interne Koordinatenraumtransformationen sind teuer

Verwenden ImageIO

  • ImageIO kann Bildgrößen und Metadateninformationen lesen, ohne den Speicher zu verschmutzen.

  • ImageIO kann die Größe von Bildern nur zum Preis der Bildgröße ändern.

Über Bild im Speicher

  • Die Speichernutzung hängt von den Abmessungen der Bilder ab, nicht von der Dateigröße.
  • UIGraphicsBeginImageContextWithOptionsVerwendet immer das SRGBRendering-Format, das 4 Bytes pro Pixel verwendet.
  • Ein Bild hat load -> decode -> render3 Phasen.
  • UIImage ist teuer für die Dimensionierung und Größenänderung

Wenn Sie für das folgende Bild UIGraphicsBeginImageContextWithOptions nur 590 KB zum Laden eines Bildes benötigen, benötigen 2048 pixels x 1536 pixels x 4 bytes per pixelwir beim Dekodieren = 10 MB Geben Sie hier die Bildbeschreibung ein

während UIGraphicsImageRenderer, 10 in iOS eingeführt, wird das beste Grafikformat in iOS12 automatisch auswählen. Es bedeutet, dass Sie 75% der Speicher sparen durch Ersetzen UIGraphicsBeginImageContextWithOptionsmit , UIGraphicsImageRendererwenn Sie SRGB nicht brauchen.

Dies ist mein Artikel über iOS-Bilder im Speicher

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)

oder

// 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)
}
RY Zheng
quelle
0

Am Ende habe ich die Brads-Technik verwendet, um eine scaleToFitWidthMethode zu erstellen , UIImage+Extensionswenn dies für jemanden nützlich ist ...

-(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;
}

dann wo immer du willst

#import "UIImage+Extensions.h"

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

UIView+ExtensionsErwähnenswert ist auch, dass Sie dies weiter nach unten in eine Klasse verschieben können, wenn Sie Bilder aus einer UIView rendern möchten

Magoo
quelle
0

Ich wollte diese Frage nur für Cocoa Swift-Programmierer beantworten. Diese Funktion gibt NSImage mit neuer Größe zurück. Sie können diese Funktion so verwenden.

        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

}
Hoffnung
quelle
0

Wenn sich Ihr Bild im Dokumentverzeichnis befindet, fügen Sie diese URL- Erweiterung hinzu:

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
        }
    }
}

Verwendung:

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)")

Hinweis: - Ändern Sie <LocalImagePath.jpg> mit Ihrem lokalen JPG-Bildpfad.

Mohammad Zaid Pathan
quelle
-1

Wenn jemand noch nach einer besseren Option sucht

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

}
Seema Sharma
quelle
-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;
}
Backbencher
quelle
Bitte geben Sie in Ihrer Antwort mindestens eine Erklärung des Codes an. Formatieren Sie den Code auch mit dem Antworteditor, um ihn lesbar zu machen.
Xpereta
-2

Um die Größe eines Bildes zu ändern, habe ich bessere (grafische) Ergebnisse, wenn ich diese Funktion anstelle von DrawInRect verwende:

- (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;
}

Das Seitenverhältnis wird automatisch berücksichtigt

Jebu
quelle