モードを「Aspect Fit」としてイメージビューにイメージをロードしています。画像がスケーリングされるサイズを知る必要があります。助けてください。
20 に答える
OS 関数AVMakeRectWithAspectRatioInsideRectを使用しないのはなぜですか?
AVMakeRectWithAspectRatioInsideRect()
AVFoundationフレームワークを含めずに使いたかった。
そこで、次の 2 つのユーティリティ関数を実装しました。
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;
}
編集終了
これは、指定されたサイズ (最初のパラメーター) を取り、その縦横比を維持します。次に、アスペクト比に違反することなく、指定された境界 (2 番目のパラメーター) を可能な限り塗りつぶします。
これを使用して元の質問に答えます。
// Using aspect fit, scale the image (size) to the image view's size.
CGSize sizeBeingScaledTo = CGSizeAspectFit(theImage.size, theImageView.frame.size);
画像が縦横比を決定する方法と、画像ビューが塗りつぶされるサイズを決定する方法に注意してください。
フィードバックは大歓迎です。
これの代わりに@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);
}
この単純な関数は、アスペクト フィット後の画像のサイズを計算します。
スイフト5.1
extension UIImageView {
var imageSizeAfterAspectFit: CGSize {
var newWidth: CGFloat
var newHeight: CGFloat
guard let image = image else { return frame.size }
if image.size.height >= image.size.width {
newHeight = frame.size.height
newWidth = ((image.size.width / (image.size.height)) * newHeight)
if CGFloat(newWidth) > (frame.size.width) {
let diff = (frame.size.width) - newWidth
newHeight = newHeight + CGFloat(diff) / newHeight * newHeight
newWidth = frame.size.width
}
} else {
newWidth = frame.size.width
newHeight = (image.size.height / image.size.width) * newWidth
if newHeight > frame.size.height {
let diff = Float((frame.size.height) - newHeight)
newWidth = newWidth + CGFloat(diff) / newWidth * newWidth
newHeight = frame.size.height
}
}
return .init(width: newWidth, height: newHeight)
}
}
目標 C:
-(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)
たぶんあなたのケースには合わないかもしれませんが、この簡単なアプローチは同様のケースで私の問題を解決します:
UIImageView *imageView = [[UIImageView alloc] initWithImage:bigSizeImage];
[imageView sizeToFit];
画像ビューが sizeToFit を実行した後、imageView.frame.sizeをクエリすると、新しい画像サイズに適合する新しい画像ビュー サイズが取得されます。
+(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;
}
受け入れられた答えは信じられないほど複雑で、いくつかのエッジケースでは失敗します. このソリューションははるかにエレガントだと思います:
- (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 モード
- スケールと四角形を別々にクエリできます
- UIImageViewから直接画像フレームについて尋ねることができます
Swift 5拡張機能
extension CGSize {
func aspectFit(to size: CGSize) -> CGSize {
let mW = size.width / self.width;
let mH = size.height / self.height;
var result = size
if( mH < mW ) {
result.width = size.height / self.height * self.width;
}
else if( mW < mH ) {
result.height = size.width / self.width * self.height;
}
return result;
}
func aspectFill(to size: CGSize) -> CGSize {
let mW = size.width / self.width;
let mH = size.height / self.height;
var result = size
if( mH > mW ) {
result.width = size.height / self.height * self.width;
}
else if( mW > mH ) {
result.height = size.width / self.width * self.height;
}
return result;
}
}