UIImageView에서 이미지에 Aspect Fit을 적용한 후 이미지 크기를 아는 방법
모드가 'Aspect Fit'인 imageview에 이미지를로드하고 있습니다. 내 이미지가 조정되는 크기를 알아야합니다. 도와주세요.
이 대신 @ Paul-de-Lange의 답변을 참조하십시오.
쉽게 접근 할 수있는 변수에서 이것을 찾을 수 없었으므로 여기에 무차별 대입 방법이 있습니다.
- (CGSize) aspectScaledImageSizeForImageView:(UIImageView *)iv image:(UIImage *)im {
float x,y;
float a,b;
x = iv.frame.size.width;
y = iv.frame.size.height;
a = im.size.width;
b = im.size.height;
if ( x == a && y == b ) { // image fits exactly, no scaling required
// return iv.frame.size;
}
else if ( x > a && y > b ) { // image fits completely within the imageview frame
if ( x-a > y-b ) { // image height is limiting factor, scale by height
a = y/b * a;
b = y;
} else {
b = x/a * b; // image width is limiting factor, scale by width
a = x;
}
}
else if ( x < a && y < b ) { // image is wider and taller than image view
if ( a - x > b - y ) { // height is limiting factor, scale by height
a = y/b * a;
b = y;
} else { // width is limiting factor, scale by width
b = x/a * b;
a = x;
}
}
else if ( x < a && y > b ) { // image is wider than view, scale by width
b = x/a * b;
a = x;
}
else if ( x > a && y < b ) { // image is taller than view, scale by height
a = y/b * a;
b = y;
}
else if ( x == a ) {
a = y/b * a;
b = y;
} else if ( y == b ) {
b = x/a * b;
a = x;
}
return CGSizeMake(a,b);
}
OS 함수 AVMakeRectWithAspectRatioInsideRect를 사용하지 않는 이유는 무엇 입니까?
AVMakeRectWithAspectRatioInsideRect()
AVFoundation 프레임 워크를 포함하지 않고 사용하고 싶었습니다 .
그래서 다음 두 가지 유틸리티 기능을 구현했습니다.
CGSize CGSizeAspectFit(CGSize aspectRatio, CGSize boundingSize)
{
float mW = boundingSize.width / aspectRatio.width;
float mH = boundingSize.height / aspectRatio.height;
if( mH < mW )
boundingSize.width = boundingSize.height / aspectRatio.height * aspectRatio.width;
else if( mW < mH )
boundingSize.height = boundingSize.width / aspectRatio.width * aspectRatio.height;
return boundingSize;
}
CGSize CGSizeAspectFill(CGSize aspectRatio, CGSize minimumSize)
{
float mW = minimumSize.width / aspectRatio.width;
float mH = minimumSize.height / aspectRatio.height;
if( mH > mW )
minimumSize.width = minimumSize.height / aspectRatio.height * aspectRatio.width;
else if( mW > mH )
minimumSize.height = minimumSize.width / aspectRatio.width * aspectRatio.height;
return minimumSize;
}
편집 : 중복 부서를 제거하여 아래에 최적화되었습니다.
CGSize CGSizeAspectFit(const CGSize aspectRatio, const CGSize boundingSize)
{
CGSize aspectFitSize = CGSizeMake(boundingSize.width, boundingSize.height);
float mW = boundingSize.width / aspectRatio.width;
float mH = boundingSize.height / aspectRatio.height;
if( mH < mW )
aspectFitSize.width = mH * aspectRatio.width;
else if( mW < mH )
aspectFitSize.height = mW * aspectRatio.height;
return aspectFitSize;
}
CGSize CGSizeAspectFill(const CGSize aspectRatio, const CGSize minimumSize)
{
CGSize aspectFillSize = CGSizeMake(minimumSize.width, minimumSize.height);
float mW = minimumSize.width / aspectRatio.width;
float mH = minimumSize.height / aspectRatio.height;
if( mH > mW )
aspectFillSize.width = mH * aspectRatio.width;
else if( mW > mH )
aspectFillSize.height = mW * aspectRatio.height;
return aspectFillSize;
}
편집 끝
이것은 주어진 크기 (첫 번째 매개 변수)를 취하고 종횡비를 유지합니다. 그런 다음 가로 세로 비율을 위반하지 않고 가능한 한 주어진 경계 (두 번째 매개 변수)를 채 웁니다.
이것을 사용하여 원래 질문에 답하십시오.
// Using aspect fit, scale the image (size) to the image view's size.
CGSize sizeBeingScaledTo = CGSizeAspectFit(theImage.size, theImageView.frame.size);
이미지는 가로 세로 비율을 결정하는 반면 이미지보기는 채울 크기를 결정합니다.
피드백은 매우 환영합니다.
이 간단한 함수는 가로 세로 맞춤 후 이미지의 크기를 계산합니다.
-(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);
}
또한 테이블 뷰의 셀 높이를 계산할 수 있도록 종횡비를 적용한 후 높이를 계산하고 싶었습니다. 그래서 저는 약간의 수학을 통해
ratio = width / height
그리고 높이가 될 것입니다
height = width / ratio
따라서 코드 스 니펫은
UIImage *img = [UIImage imageNamed:@"anImage"];
float aspectRatio = img.size.width/img.size.height;
float requiredHeight = self.view.bounds.size.width / aspectRatio;
아래 코드에서 Swift 사용
func imageSizeAspectFit(imgview: UIImageView) -> CGSize {
var newwidth: CGFloat
var newheight: CGFloat
let image: UIImage = imgFeed.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 {
let diff: CGFloat = 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 {
let diff: CGFloat = imgview.frame.size.height - newheight
newwidth = newwidth + diff / newwidth * newwidth
newheight = imgview.frame.size.height
}
}
print(newwidth, newheight)
//adapt UIImageView size to image size
return CGSizeMake(newwidth, newheight)
}
그리고 호출 기능
imgFeed.sd_setImageWithURL(NSURL(string:"Your image URL")))
self.imageSizeAfterAspectFit(imgFeed)
Swift 3 사람이 읽을 수있는 버전
extension UIImageView {
/// Find the size of the image, once the parent imageView has been given a contentMode of .scaleAspectFit
/// Querying the image.size returns the non-scaled size. This helper property is needed for accurate results.
var aspectFitSize: CGSize {
guard let image = image else { return CGSize.zero }
var aspectFitSize = CGSize(width: frame.size.width, height: frame.size.height)
let newWidth: CGFloat = frame.size.width / image.size.width
let newHeight: CGFloat = frame.size.height / image.size.height
if newHeight < newWidth {
aspectFitSize.width = newHeight * image.size.width
} else if newWidth < newHeight {
aspectFitSize.height = newWidth * image.size.height
}
return aspectFitSize
}
/// Find the size of the image, once the parent imageView has been given a contentMode of .scaleAspectFill
/// Querying the image.size returns the non-scaled, vastly too large size. This helper property is needed for accurate results.
var aspectFillSize: CGSize {
guard let image = image else { return CGSize.zero }
var aspectFillSize = CGSize(width: frame.size.width, height: frame.size.height)
let newWidth: CGFloat = frame.size.width / image.size.width
let newHeight: CGFloat = frame.size.height / image.size.height
if newHeight > newWidth {
aspectFillSize.width = newHeight * image.size.width
} else if newWidth > newHeight {
aspectFillSize.height = newWidth * image.size.height
}
return aspectFillSize
}
}
아마도 귀하의 경우에 맞지 않을 수도 있지만이 간단한 접근 방식은 비슷한 경우 내 문제를 해결합니다.
UIImageView *imageView = [[UIImageView alloc] initWithImage:bigSizeImage];
[imageView sizeToFit];
imageView.frame.size 를 쿼리하면 이미지보기가 sizeToFit을 실행 한 후 새 이미지 크기에 맞는 새 이미지보기 크기를 얻을 수 있습니다.
+(UIImage *)CreateAResizeImage:(UIImage *)Img ThumbSize:(CGSize)ThumbSize
{
float actualHeight = Img.size.height;
float actualWidth = Img.size.width;
if(actualWidth==actualHeight)
{
actualWidth = ThumbSize.width;
actualHeight = ThumbSize.height;
}
float imgRatio = actualWidth/actualHeight;
float maxRatio = ThumbSize.width/ThumbSize.height; //320.0/480.0;
if(imgRatio!=maxRatio)
{
if(imgRatio < maxRatio)
{
imgRatio = ThumbSize.height / actualHeight; //480.0 / actualHeight;
actualWidth = imgRatio * actualWidth;
actualHeight = ThumbSize.height; //480.0;
}
else
{
imgRatio = ThumbSize.width / actualWidth; //320.0 / actualWidth;
actualHeight = imgRatio * actualHeight;
actualWidth = ThumbSize.width; //320.0;
}
}
else
{
actualWidth = ThumbSize.width;
actualHeight = ThumbSize.height;
}
CGRect rect = CGRectMake(0, 0, (int)actualWidth, (int)actualHeight);
UIGraphicsBeginImageContext(rect.size);
[Img drawInRect:rect];
UIImage *NewImg = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return NewImg;
}
Swift 4 :.aspectFit
이미지 프레임 은-
import AVFoundation
let x: CGRect = AVMakeRect(aspectRatio: myImage.size, insideRect: sampleImageView.frame)
받아 들여지는 대답은 엄청나게 복잡하며 일부 경우에 실패합니다. 이 솔루션이 훨씬 더 우아하다고 생각합니다.
- (CGSize) sizeOfImage:(UIImage*)image inAspectFitImageView:(UIImageView*)imageView
{
UKAssert(imageView.contentMode == UIViewContentModeScaleAspectFit, @"Image View must use contentMode = UIViewContentModeScaleAspectFit");
CGFloat imageViewWidth = imageView.bounds.size.width;
CGFloat imageViewHeight = imageView.bounds.size.height;
CGFloat imageWidth = image.size.width;
CGFloat imageHeight = image.size.height;
CGFloat scaleFactor = MIN(imageViewWidth / imageWidth, imageViewHeight / imageHeight);
return CGSizeMake(image.size.width*scaleFactor, image.size.height*scaleFactor);
}
다음은 같은 문제에 대한 내 솔루션입니다. https://github.com/alexgarbarev/UIImageView-ImageFrame
장점 :
- 지원되는 UIViewContentMode 모드
- 스케일과 rect를 별도로 쿼리 할 수 있습니다.
- UIImageView에서 바로 이미지 프레임에 대해 질문 할 수 있습니다.
Swift 3 UIImageView 확장 :
import AVFoundation
extension UIImageView {
var imageSize: CGSize {
if let image = image {
return AVMakeRect(aspectRatio: image.size, insideRect: bounds).size
}
return CGSize.zero
}
}
여기 내 AVFoundation이없는 솔루션이 있습니다.
먼저 다른 크기에 맞는 크기를 계산하기위한 CGSize 확장이 있습니다.
extension CGSize
{
func sizeThatFitsSize(_ aSize: CGSize) -> CGSize
{
let width = min(self.width * aSize.height / self.height, aSize.width)
return CGSize(width: width, height: self.height * width / self.width)
}
}
따라서 OP의 문제에 대한 해결책은 다음과 같습니다.
let resultSize = image.size.sizeThatFitsSize(imageView.bounds.size)
또한 다른 rect 내에 rect를 맞추기위한 또 다른 확장이 있습니다 (위의 CGSize 확장을 활용 함).
extension CGRect
{
func rectThatFitsRect(_ aRect:CGRect) -> CGRect
{
let sizeThatFits = self.size.sizeThatFitsSize(aRect.size)
let xPos = (aRect.size.width - sizeThatFits.width) / 2
let yPos = (aRect.size.height - sizeThatFits.height) / 2
let ret = CGRect(x: xPos, y: yPos, width: sizeThatFits.width, height: sizeThatFits.height)
return ret
}
}
이 한 줄로이 작업을 수행 할 수 있습니다.
CGSize sizeInView = AVMakeRectWithAspectRatioInsideRect(imgViewFake.image.size, imgViewFake.bounds).size;
Swift에서 다음을 사용하고 있습니다.
private func CGSizeAspectFit(aspectRatio:CGSize,boundingSize:CGSize) -> CGSize
{
var aspectFitSize = boundingSize
let mW = boundingSize.width / aspectRatio.width
let mH = boundingSize.height / aspectRatio.height
if( mH < mW )
{
aspectFitSize.width = mH * aspectRatio.width
}
else if( mW < mH )
{
aspectFitSize.height = mW * aspectRatio.height
}
return aspectFitSize
}
private func CGSizeAspectFill(aspectRatio:CGSize,minimumSize:CGSize) -> CGSize
{
var aspectFillSize = minimumSize
let mW = minimumSize.width / aspectRatio.width
let mH = minimumSize.height / aspectRatio.height
if( mH > mW )
{
aspectFillSize.width = mH * aspectRatio.width
}
else if( mW > mH )
{
aspectFillSize.height = mW * aspectRatio.height
}
return aspectFillSize
}
다음과 같이 사용하고 있습니다.
let aspectSize = contentMode == .ScaleAspectFill ? CGSizeAspectFill(oldSize,minimumSize: newSize) : CGSizeAspectFit(oldSize, boundingSize: newSize)
let newRect = CGRect( x: (newSize.width - aspectSize.width)/2, y: (newSize.height - aspectSize.height)/2, width: aspectSize.width, height: aspectSize.height)
CGContextSetFillColorWithColor(context,IOSXColor.whiteColor().CGColor)
CGContextFillRect(context, CGRect(origin: CGPointZero,size: newSize))
CGContextDrawImage(context, newRect, cgImage)
imageview의 너비 만 알고 이미지의 높이가 동적 일 때 이미지 위와 아래의 공백을 제거하기 위해 주어진 너비에 따라 이미지의 높이를 조정해야합니다. 여기 에서 다음 방법을 사용 하여 화면의 표준 너비에 따라 이미지의 높이를 조정합니다.
-(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;
}
다음과 같이 cellForRowAtIndexPath : 메서드에서 호출합니다.
UIImage *img = [dictImages objectForKey:yourImageKey]; // loaded the image
cell.imgView.image = [self imageWithImage:img scaledToWidth:self.view.frame.size.width];
Swift 4 버전
extension CGSize {
enum AspectMode {
case fit
case fill
}
enum Orientation {
case portrait
case landscape
}
func aspectCorrectSizeToFit(targetSize: CGSize, aspectMode: AspectMode = .fill) -> CGSize {
switch aspectMode {
case .fill: return aspectFill(targetSize: targetSize)
case .fit: return aspectFit(targetSize: targetSize)
}
}
var orientation: Orientation {
if height >= width { return .portrait }
else { return .landscape }
}
func aspectFit(targetSize: CGSize) -> CGSize {
let wRatio = targetSize.width / width
let hRatio = targetSize.height / height
let scale = min(wRatio, hRatio)
return applying(CGAffineTransform(scaleX: scale, y: scale))
}
func aspectFill(targetSize: CGSize) -> CGSize {
let wRatio = targetSize.width / width
let hRatio = targetSize.height / height
let scale = max(wRatio, hRatio)
return applying(CGAffineTransform(scaleX: scale, y: scale))
}
}
위에서 언급 한 방법은 절대 필요한 값을 제공하지 않습니다. aspect fit은 동일한 aspect ratio를 유지하므로 값을 계산하기 위해 간단한 수학 만 필요합니다.
종횡비 감지
CGFloat imageViewAspectRatio = backgroundImageView.bounds.size.width / backgroundImageView.bounds.size.height;
CGFloat imageAspectRatio = backgroundImageView.image.size.width / backgroundImageView.image.size.height;
CGFloat mulFactor = imageViewAspectRatio/imageAspectRatio;
새로운 가치 얻기
CGFloat newImageWidth = mulFactor * backgroundImageView.bounds.size.width;
CGFloat newImageHeight = mulFactor * backgroundImageView.bounds.size.height;
'Program Club' 카테고리의 다른 글
프로그래밍 방식으로 imageview의 높이를 matchparent로 설정 (0) | 2020.10.30 |
---|---|
해시 함수가 O (1)이 아닌데도 O (1) 키로 사전의 요소에 액세스하는 이유는 무엇입니까? (0) | 2020.10.30 |
MSBuild 대상 패키지를 찾을 수 없습니다. (0) | 2020.10.29 |
오늘 날짜에서 30 일 전 날짜를 가져 오는 방법 (0) | 2020.10.29 |
DVM과 JVM의 차이점은 무엇입니까? (0) | 2020.10.29 |