Ändern Sie die Größe von UIImage, indem Sie das Seitenverhältnis und die Breite beibehalten


136

Ich habe in vielen Posts gesehen, wie man die Größe des Bildes ändert, indem man das Seitenverhältnis beibehält. Diese Funktionen verwenden die Fixpunkte (Breite und Höhe) für RECT beim Ändern der Größe. In meinem Projekt muss ich die Größe der Ansicht jedoch nur anhand der Breite ändern. Die Höhe sollte automatisch anhand des Seitenverhältnisses festgelegt werden. jemand hilft mir, dies zu erreichen.

Antworten:


228

Die Methode von Srikar funktioniert sehr gut, wenn Sie sowohl die Höhe als auch die Breite Ihrer neuen Größe kennen. Wenn Sie beispielsweise nur die Breite kennen, auf die Sie skalieren möchten, und sich nicht um die Höhe kümmern, müssen Sie zuerst den Skalierungsfaktor der Höhe berechnen.

+(UIImage*)imageWithImage: (UIImage*) sourceImage scaledToWidth: (float) i_width
{
    float oldWidth = sourceImage.size.width;
    float scaleFactor = i_width / oldWidth;

    float newHeight = sourceImage.size.height * scaleFactor;
    float newWidth = oldWidth * scaleFactor;

    UIGraphicsBeginImageContext(CGSizeMake(newWidth, newHeight));
    [sourceImage drawInRect:CGRectMake(0, 0, newWidth, newHeight)];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();    
    UIGraphicsEndImageContext();
    return newImage;
}

22
Sie brauchen die newWidthVariable hier allerdings nicht wirklich , sie ist bereits vorhanden i_width.
Matthew Quiros

2
Sie müssen auch durch die Höhe dividieren und die Skalierungsfaktoren mit dem Wert vergleichen, der näher an 0 liegt. Der obige Code funktioniert nur mit Bildern, die breiter als hoch sind
IceForge

1
Ich müsste nur durch die Höhe teilen, wenn ich auch mein Höhenverhältnis kennen und durch Skalieren der Breite oder der Höhe passen möchte. Da der TO jedoch ausdrücklich darum gebeten hat, Verhältnis und Breite und nicht Breite oder Höhe beizubehalten, ist meine Antwort völlig richtig.
Maverick1st

12
Tolle Antwort, danke. Eine weitere Sache: Wenn Sie mit dieser Methode einen Verlust der Bildqualität UIGraphicsBeginImageContextWithOptions(CGSizeMake(newWidth, newHeight), NO, 0);UIGraphicsBeginImageContext(CGSizeMake(newWidth, newHeight));
feststellen,

57

Wenn Sie nicht wissen, ob das Bild im Hoch- oder Querformat angezeigt wird (z. B. nimmt der Benutzer ein Bild mit der Kamera auf), habe ich eine andere Methode erstellt, die die Parameter für die maximale Breite und Höhe verwendet.

Nehmen wir an, Sie haben ein UIImage *myLargeImageVerhältnis von 4: 3.

UIImage *myResizedImage = [ImageUtilities imageWithImage:myLargeImage 
                                        scaledToMaxWidth:1024 
                                               maxHeight:1024];

Die Größe des UIImage beträgt 1024 x 768 im Querformat. 768x1024 wenn Porträt. Diese Methode erzeugt auch Bilder mit höherer Auflösung für die Retina-Anzeige.

+ (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)size {
    if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {
        UIGraphicsBeginImageContextWithOptions(size, NO, [[UIScreen mainScreen] scale]);
    } else {
        UIGraphicsBeginImageContext(size);
    }
    [image drawInRect:CGRectMake(0, 0, size.width, size.height)];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();    
    UIGraphicsEndImageContext();

    return newImage;
}

+ (UIImage *)imageWithImage:(UIImage *)image scaledToMaxWidth:(CGFloat)width maxHeight:(CGFloat)height {
    CGFloat oldWidth = image.size.width;
    CGFloat oldHeight = image.size.height;

    CGFloat scaleFactor = (oldWidth > oldHeight) ? width / oldWidth : height / oldHeight;

    CGFloat newHeight = oldHeight * scaleFactor;
    CGFloat newWidth = oldWidth * scaleFactor;
    CGSize newSize = CGSizeMake(newWidth, newHeight);

    return [ImageUtilities imageWithImage:image scaledToSize:newSize];
}

1
Dies ist das Beste, aber es gibt immer das Doppelte meiner definierten Größe zurück
Mashhadi

2
Wenn Sie nur verkleinern und nicht vergrößern möchten, vergessen Sie nicht, die Methode imageWithImage: scaledToMaxWidth: maxHeight: mit zu starten: if (image.size.width <width && image.size.height <height) {return image; }
Arjan

5
Um in eine maximale Breite und Höhe zu passen, benötigen Sie das minimale Verhältnis als Skalierungsfaktor : min(ratioX, ratioY). Wenn die Breite größer ist, passt sie möglicherweise nicht zur maximalen Höhe.
Jason Sturges

ImageUtilities wo ist es?
Tong

42

Beste Antwort Maverick 1st ist korrekt in Swift übersetzt (arbeitet mit der neuesten Version von Swift 3 ):

func imageWithImage (sourceImage:UIImage, scaledToWidth: CGFloat) -> UIImage {
    let oldWidth = sourceImage.size.width
    let scaleFactor = scaledToWidth / oldWidth

    let newHeight = sourceImage.size.height * scaleFactor
    let newWidth = oldWidth * scaleFactor

    UIGraphicsBeginImageContext(CGSize(width:newWidth, height:newHeight))
    sourceImage.draw(in: CGRect(x:0, y:0, width:newWidth, height:newHeight))
    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return newImage!
}

38

danke @ Maverick1st den Algorithmus, den ich implementiert habe Swift, in meinem Fall ist height der Eingabeparameter

class func resizeImage(image: UIImage, newHeight: CGFloat) -> UIImage {

    let scale = newHeight / image.size.height
    let newWidth = image.size.width * scale
    UIGraphicsBeginImageContext(CGSizeMake(newWidth, newHeight))
    image.drawInRect(CGRectMake(0, 0, newWidth, newHeight))
    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return newImage
}

18

Diese Methode ist eine Kategorie in UIImage. Skaliert mit AVFoundation so, dass es in wenige Codezeilen passt. Vergessen Sie nicht zu importieren #import <AVFoundation/AVFoundation.h>.

@implementation UIImage (Helper)

- (UIImage *)imageScaledToFitToSize:(CGSize)size
{
    CGRect scaledRect = AVMakeRectWithAspectRatioInsideRect(self.size, CGRectMake(0, 0, size.width, size.height));
    UIGraphicsBeginImageContextWithOptions(size, NO, 0);
    [self drawInRect:scaledRect];
    UIImage *scaledImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return scaledImage;
}

@end

2
Ich habe festgestellt, dass dies die besten Ergebnisse für mich bei geringstem Speicherbedarf liefert. +1
Tommie C.

11

Swift 5- Version von Aspekt-Anpassung an Höhe , basierend auf der Antwort von @ János

Verwendet die moderne UIGraphicsImageRendererAPI, sodass eine gültige API UIImagegarantiert zurückgegeben wird.

extension UIImage
{
    /// Given a required height, returns a (rasterised) copy
    /// of the image, aspect-fitted to that height.

    func aspectFittedToHeight(_ newHeight: CGFloat) -> UIImage
    {
        let scale = newHeight / self.size.height
        let newWidth = self.size.width * scale
        let newSize = CGSize(width: newWidth, height: newHeight)
        let renderer = UIGraphicsImageRenderer(size: newSize)

        return renderer.image { _ in
            self.draw(in: CGRect(origin: .zero, size: newSize))
        }
    }
}

Sie können dies in Verbindung mit einem (vektorbasierten) PDF-Bildelement verwenden, um die Qualität bei jeder Rendergröße zu erhalten.


7

Am einfachsten ist es, den Rahmen von UIImageViewund contentModeeine der Größenänderungsoptionen festzulegen.

Der Code sieht folgendermaßen aus: - Dies kann als Dienstprogrammmethode verwendet werden. -

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

Beachten Sie, dass das OP keine UIImageView erwähnt hat. Stattdessen wollte er vermutlich eine [Kopie eines] UIImage direkt an einen Aspekt anpassen, was sehr praktisch ist, wenn Sie CoreGraphics-Arbeiten ausführen.
Womble

6

Programmatisch:

imageView.contentMode = UIViewContentModeScaleAspectFit;

Storyboard:

Geben Sie hier die Bildbeschreibung ein


Es funktioniert, ABER es reduziert den Speicherbedarf. Sie können die App schneller arbeiten lassen, indem Sie beispielsweise viele Miniaturansichten laden.
Ingconti

Das ist ein UIImageView, kein UIImage. Manchmal müssen Sie ohne UIImageView zeichnen.
Womble

5

Nun, wir haben hier einige gute Antworten für die Größenänderung von Bildern, aber ich ändere sie nur gemäß meinen Anforderungen. hoffe das hilft jemandem wie mir.

Meine Anforderung war

  1. Wenn die Bildbreite mehr als 1920 beträgt, ändern Sie die Größe mit der Breite 1920 und behalten Sie die Höhe mit dem ursprünglichen Seitenverhältnis bei.
  2. Wenn die Bildhöhe mehr als 1080 beträgt, ändern Sie die Größe auf 1080 und behalten Sie die Breite mit dem ursprünglichen Seitenverhältnis bei.

 if (originalImage.size.width > 1920)
 {
        CGSize newSize;
        newSize.width = 1920;
        newSize.height = (1920 * originalImage.size.height) / originalImage.size.width;
        originalImage = [ProfileEditExperienceViewController imageWithImage:originalImage scaledToSize:newSize];        
 }

 if (originalImage.size.height > 1080)
 {
            CGSize newSize;
            newSize.width = (1080 * originalImage.size.width) / originalImage.size.height;
            newSize.height = 1080;
            originalImage = [ProfileEditExperienceViewController imageWithImage:originalImage scaledToSize:newSize];

 }

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

Dank @ Srikar Appal habe ich für die Größenänderung seine Methode verwendet.

Möglicherweise möchten Sie dies auch für die Größenänderungsberechnung überprüfen .


4

Einfach AVFoundation importieren und verwenden AVMakeRectWithAspectRatioInsideRect(CGRectCurrentSize, CGRectMake(0, 0, YOUR_WIDTH, CGFLOAT_MAX)


2

Um Ryans Antwort zu verbessern:

   + (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)size {
CGFloat oldWidth = image.size.width;
        CGFloat oldHeight = image.size.height;

//You may need to take some retina adjustments into consideration here
        CGFloat scaleFactor = (oldWidth > oldHeight) ? width / oldWidth : height / oldHeight;

return [UIImage imageWithCGImage:image.CGImage scale:scaleFactor orientation:UIImageOrientationUp];
    }

2
extension UIImage {

    /// Returns a image that fills in newSize
    func resizedImage(newSize: CGSize) -> UIImage? {
        guard size != newSize else { return self }

    let hasAlpha = false
    let scale: CGFloat = 0.0
    UIGraphicsBeginImageContextWithOptions(newSize, !hasAlpha, scale)
        UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0)

        draw(in: CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height))
        let newImage: UIImage? = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return newImage
    }

    /// Returns a resized image that fits in rectSize, keeping it's aspect ratio
    /// Note that the new image size is not rectSize, but within it.
    func resizedImageWithinRect(rectSize: CGSize) -> UIImage? {
        let widthFactor = size.width / rectSize.width
        let heightFactor = size.height / rectSize.height

        var resizeFactor = widthFactor
        if size.height > size.width {
            resizeFactor = heightFactor
        }

        let newSize = CGSize(width: size.width / resizeFactor, height: size.height / resizeFactor)
        let resized = resizedImage(newSize: newSize)

        return resized
    }
}

Wenn die Skalierung auf 0,0 eingestellt ist, wird der Skalierungsfaktor des Hauptbildschirms verwendet, der für Retina-Anzeigen 2,0 oder höher beträgt (3,0 auf dem iPhone 6 Plus).


1

Ryans Lösung @Ryan in schnellem Code

verwenden:

 func imageWithSize(image: UIImage,size: CGSize)->UIImage{
    if UIScreen.mainScreen().respondsToSelector("scale"){
        UIGraphicsBeginImageContextWithOptions(size,false,UIScreen.mainScreen().scale);
    }
    else
    {
         UIGraphicsBeginImageContext(size);
    }

    image.drawInRect(CGRectMake(0, 0, size.width, size.height));
    var newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return newImage;
}

//Summon this function VVV
func resizeImageWithAspect(image: UIImage,scaledToMaxWidth width:CGFloat,maxHeight height :CGFloat)->UIImage
{
    let oldWidth = image.size.width;
    let oldHeight = image.size.height;

    let scaleFactor = (oldWidth > oldHeight) ? width / oldWidth : height / oldHeight;

    let newHeight = oldHeight * scaleFactor;
    let newWidth = oldWidth * scaleFactor;
    let newSize = CGSizeMake(newWidth, newHeight);

    return imageWithSize(image, size: newSize);
}

1

In Swift 3 gibt es einige Änderungen. Hier ist eine Erweiterung von UIImage:

public extension UIImage {
    public func resize(height: CGFloat) -> UIImage? {
        let scale = height / self.size.height
        let width = self.size.width * scale
        UIGraphicsBeginImageContext(CGSize(width: width, height: height))
        self.draw(in: CGRect(x:0, y:0, width:width, height:height))
        let resultImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return resultImage
    }
}

1

Zeeshan Tufail und Womble antworten in Swift 5 mit kleinen Verbesserungen. Hier haben wir eine Erweiterung mit 2 Funktionen, um Bilder auf maxLengthjede Dimension und JPEG-Komprimierung zu skalieren .

extension UIImage {
    func aspectFittedToMaxLengthData(maxLength: CGFloat, compressionQuality: CGFloat) -> Data {
        let scale = maxLength / max(self.size.height, self.size.width)
        let format = UIGraphicsImageRendererFormat()
        format.scale = scale
        let renderer = UIGraphicsImageRenderer(size: self.size, format: format)
        return renderer.jpegData(withCompressionQuality: compressionQuality) { context in
            self.draw(in: CGRect(origin: .zero, size: self.size))
        }
    }
    func aspectFittedToMaxLengthImage(maxLength: CGFloat, compressionQuality: CGFloat) -> UIImage? {
        let newImageData = aspectFittedToMaxLengthData(maxLength: maxLength, compressionQuality: compressionQuality)
        return UIImage(data: newImageData)
    }
}

0

Dieser war perfekt für mich. Hält das Seitenverhältnis und nimmt a maxLength. Breite oder Höhe wird nicht größer sein alsmaxLength

-(UIImage*)imageWithImage: (UIImage*) sourceImage maxLength: (float) maxLength
{
    CGFloat scaleFactor = maxLength / MAX(sourceImage.size.width, sourceImage.size.height);

    float newHeight = sourceImage.size.height * scaleFactor;
    float newWidth = sourceImage.size.width * scaleFactor;

    UIGraphicsBeginImageContext(CGSizeMake(newWidth, newHeight));
    [sourceImage drawInRect:CGRectMake(0, 0, newWidth, newHeight)];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return newImage;
}

0

Berechnet die beste Höhe des Bildes für die verfügbare Breite.

import Foundation

public extension UIImage {
    public func height(forWidth width: CGFloat) -> CGFloat {
        let boundingRect = CGRect(
            x: 0,
            y: 0,
            width: width,
            height: CGFloat(MAXFLOAT)
        )
        let rect = AVMakeRect(
            aspectRatio: size,
            insideRect: boundingRect
        )
        return rect.size.height
    }
}

-1

Ich habe es viel einfacher gelöst

UIImage *placeholder = [UIImage imageNamed:@"OriginalImage.png"];
self.yourImageview.image = [UIImage imageWithCGImage:[placeholder CGImage] scale:(placeholder.scale * 1.5)
                                  orientation:(placeholder.imageOrientation)];

Der Multiplikator der Skala definiert die Abplatzung des Bildes, je kleiner der Multiplikator, desto kleiner das Bild. So können Sie überprüfen, was zu Ihrem Bildschirm passt.

Sie können den Multiplire auch erhalten, indem Sie die Bildbreite / Bildschirmbreite teilen.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.