web-dev-qa-db-fra.com

Comment obtenir la taille d'un UIImage mis à l'échelle dans UIImageView?

L'attribut image.size de UIImageView donne la taille de la UIImage d'origine. J'aimerais connaître la taille de l'image mise à l'échelle automatiquement lorsqu'elle est placée dans la variable UIImageView (généralement plus petite que l'original).

Par exemple, l'image est définie sur Aspect Fit. Maintenant, je veux connaître sa nouvelle hauteur et sa nouvelle largeur à l'écran pour pouvoir dessiner avec précision sur la nouvelle image mise à l'échelle.

Y a-t-il un moyen de le faire sans le savoir moi-même en fonction de la taille UIImageView et de la taille originale de UIImage (essentiellement la rétro-ingénierie de sa mise à l'échelle)?

45
JasonV

Objectif c:

-(CGRect)frameForImage:(UIImage*)image inImageViewAspectFit:(UIImageView*)imageView
{
    float imageRatio = image.size.width / image.size.height;
    float viewRatio = imageView.frame.size.width / imageView.frame.size.height;
    if(imageRatio < viewRatio)
    {
        float scale = imageView.frame.size.height / image.size.height;
        float width = scale * image.size.width;
        float topLeftX = (imageView.frame.size.width - width) * 0.5;
        return CGRectMake(topLeftX, 0, width, imageView.frame.size.height);
    }
    else
    {
        float scale = imageView.frame.size.width / image.size.width;
        float height = scale * image.size.height;
        float topLeftY = (imageView.frame.size.height - height) * 0.5;

        return CGRectMake(0, topLeftY, imageView.frame.size.width, height);
    }
}

Swift 4:

func frame(for image: UIImage, inImageViewAspectFit imageView: UIImageView) -> CGRect {
  let imageRatio = (image.size.width / image.size.height)
  let viewRatio = imageView.frame.size.width / imageView.frame.size.height
  if imageRatio < viewRatio {
    let scale = imageView.frame.size.height / image.size.height
    let width = scale * image.size.width
    let topLeftX = (imageView.frame.size.width - width) * 0.5
    return CGRect(x: topLeftX, y: 0, width: width, height: imageView.frame.size.height)
  } else {
    let scale = imageView.frame.size.width / image.size.width
    let height = scale * image.size.height
    let topLeftY = (imageView.frame.size.height - height) * 0.5
    return CGRect(x: 0.0, y: topLeftY, width: imageView.frame.size.width, height: height)
  }
}
84
cncool

Cette fonction simple calculera la taille de l'image: -

[imageView setFrame:AVMakeRectWithAspectRatioInsideRect(image.size, imageView.frame)];

Pour plus de détails, vous pouvez vous référer à AVMakeRectWithAspectRatioInsideRect - AVFoundation .

15
Meet Doshi

Cette fonction simple calculera la taille de l'image après ajustement de l'aspect:

-(CGSize)imageSizeAfterAspectFit:(UIImageView*)imgview{


    float newwidth;
    float newheight;

    UIImage *image=imgview.image;

    if (image.size.height>=image.size.width){
        newheight=imgview.frame.size.height;
        newwidth=(image.size.width/image.size.height)*newheight;

        if(newwidth>imgview.frame.size.width){
            float diff=imgview.frame.size.width-newwidth;
            newheight=newheight+diff/newheight*newheight;
            newwidth=imgview.frame.size.width;
        }

    }
    else{
        newwidth=imgview.frame.size.width;
        newheight=(image.size.height/image.size.width)*newwidth;

        if(newheight>imgview.frame.size.height){
            float diff=imgview.frame.size.height-newheight;
            newwidth=newwidth+diff/newwidth*newwidth;
            newheight=imgview.frame.size.height;
        }
    }

    NSLog(@"image after aspect fit: width=%f height=%f",newwidth,newheight);


    //adapt UIImageView size to image size
    //imgview.frame=CGRectMake(imgview.frame.Origin.x+(imgview.frame.size.width-newwidth)/2,imgview.frame.Origin.y+(imgview.frame.size.height-newheight)/2,newwidth,newheight);

    return CGSizeMake(newwidth, newheight);

}
10
Oleh Kudinov

Une adaptation de cncool answer , dans Swift en tant qu’extension UIImageView, serait peut-être utile à quelqu'un:

extension UIImageView{
    func frameForImageInImageViewAspectFit() -> CGRect
    {
        if  let img = self.image {
            let imageRatio = img.size.width / img.size.height;

            let viewRatio = self.frame.size.width / self.frame.size.height;

            if(imageRatio < viewRatio)
            {
                let scale = self.frame.size.height / img.size.height;

                let width = scale * img.size.width;

                let topLeftX = (self.frame.size.width - width) * 0.5;

                return CGRectMake(topLeftX, 0, width, self.frame.size.height);
            }
            else
            {
                let scale = self.frame.size.width / img.size.width;

                let height = scale * img.size.height;

                let topLeftY = (self.frame.size.height - height) * 0.5;

                return CGRectMake(0, topLeftY, self.frame.size.width, height);
            }
        }

        return CGRectMake(0, 0, 0, 0)
    }
}
7
Cesar

Étant donné que la vue de l'image est définie sur Aspect Fit, vous pouvez simplement prendre la hauteur et la largeur de la vue de l'image avec la hauteur et la largeur de l'image d'origine et calculer la hauteur et la largeur de l'image mise à l'échelle.

Cela dit, la meilleure méthode consiste à avoir une vue personnalisée au lieu d’un UIImageView. Ensuite, dessinez vous-même l'image dans la vue personnalisée. De cette façon, vous pouvez contrôler chaque aspect de celui-ci.

4
August

Si le cadre est rempli en conservant le rapport hauteur/largeur de l'image, le cadre de visualisation ne sera pas identique à la taille de l'image.

0
JasonV

J'ai écrit une extension utile qui inclut ceci dans son ensemble d'ajouts, ça vaut peut-être la peine de le vérifier.

Fonctions incluses

func getScaledImageSize() -> CGRect?
func getScaledImageSizeWithPadding() -> CGRect?
func getPaddingTop() -> CGFloat? {
func getPaddingBottom() -> CGFloat? {
func getPaddingLeft() -> CGFloat? {
func getPaddingRight() -> CGFloat?
func getScaledCoordinate(forX x: CGFloat, andY y: CGFloat, multiplier:CGFloat = 100.0) -> CGPoint?
func getScaledCoordinateWithPadding(forX x: CGFloat, andY y: CGFloat, multiplier:CGFloat = 100.0) -> CGPoint?

https://Gist.github.com/nathan-fiscaletti/e1b85f68559f305db7342bfff9574563

0
Nathan Fiscaletti

Pour faire suite à @MeetDoshi, voici une extension qui devrait permettre cela.

extension UIImageView {
    /// Retrieve the scaled size of the image within this ImageView.
    /// - Returns: A CGRect representing the size of the image after scaling or nil if no image is set.
    func getScaledImageSize() -> CGRect? {
        if let image = self.image {
            return AVMakeRect(aspectRatio: image.size, insideRect: self.frame);
        }

        return nil;
    }
}
0
Nathan Fiscaletti