web-dev-qa-db-ja.com

アスペクト比でUIImageのサイズを変更しますか?

このコードを使用して、iPhone上の画像のサイズを変更しています。

CGRect screenRect = CGRectMake(0, 0, 320.0, 480.0);
UIGraphicsBeginImageContext(screenRect.size);
[value drawInRect:screenRect blendMode:kCGBlendModePlusDarker alpha:1];
UIImage *tmpValue = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

画像の縦横比が新しいサイズ変更後の画像の縦横比と一致している限り、これはうまくいきます。これを修正して、正しいアスペクト比を維持し、画像が表示されない場所に黒い背景を配置するようにします。そのため、元の画像サイズに応じて、320x480の画像になりますが、上下または左右に黒が表示されます。

私がやっていることと同じようにこれを行う簡単な方法はありますか?ありがとう!

37
Cory Imdieke

画面の四角形を設定した後、次のようなことを行って、画像を描画する四角形を決定します。

_float hfactor = value.bounds.size.width / screenRect.size.width;
float vfactor = value.bounds.size.height / screenRect.size.height;

float factor = fmax(hfactor, vfactor);

// Divide the size by the greater of the vertical or horizontal shrinkage factor
float newWidth = value.bounds.size.width / factor;
float newHeight = value.bounds.size.height / factor;

// Then figure out if you need to offset it to center vertically or horizontally
float leftOffset = (screenRect.size.width - newWidth) / 2;
float topOffset = (screenRect.size.height - newHeight) / 2;

CGRect newRect = CGRectMake(leftOffset, topOffset, newWidth, newHeight);
_

ScreenRectよりも小さい画像を拡大したくない場合は、factorが1以上であることを確認してください(例:factor = fmax(factor, 1))。

黒の背景を取得するには、おそらくコンテキストカラーを黒に設定し、イメージを描画する前にfillRectを呼び出します。

55
Frank Schmitt

私はこれが非常に古いことを知っていますが、その投稿に感謝します-画像を描画するために縮尺を使用することから私をリダイレクトしました。だれにとっても有益な場合に備えて、ここで投入する拡張クラスを作成しました。次のように画像のサイズを変更できます。

      UIImage imgNew = img.Fit(40.0f, 40.0f);

フィットオプションは必要ありませんが、Fillをサポートするように簡単に拡張できます。

using CoreGraphics;
using System;
using UIKit;

namespace SomeApp.iOS.Extensions
{
  public static class UIImageExtensions
  {
    public static CGSize Fit(this CGSize sizeImage,
      CGSize sizeTarget)
    {
      CGSize ret;
      float fw;
      float fh;
      float f;

      fw = (float) (sizeTarget.Width / sizeImage.Width);
      fh = (float) (sizeTarget.Height / sizeImage.Height);
      f = Math.Min(fw, fh);
      ret = new CGSize
      {
        Width = sizeImage.Width * f,
        Height = sizeImage.Height * f
      };
      return ret;
    }

    public static UIImage Fit(this UIImage image,
      float width,
      float height,
      bool opaque = false,
      float scale = 1.0f)
    {
      UIImage ret;

      ret = image.Fit(new CGSize(width, height),
        opaque,
        scale);
      return ret;
    }

    public static UIImage Fit(this UIImage image,
      CGSize sizeTarget,
      bool opaque = false,
      float scale = 1.0f)
    {
      CGSize sizeNewImage;
      CGSize size;
      UIImage ret;

      size = image.Size;
      sizeNewImage = size.Fit(sizeTarget);
      UIGraphics.BeginImageContextWithOptions(sizeNewImage,
        opaque,
        1.0f);
      using (CGContext context = UIGraphics.GetCurrentContext())
      {
        context.ScaleCTM(1, -1);
        context.TranslateCTM(0, -sizeNewImage.Height);
        context.DrawImage(new CGRect(CGPoint.Empty, sizeNewImage),
          image.CGImage);
        ret = UIGraphics.GetImageFromCurrentImageContext();
      }
      UIGraphics.EndImageContext();
      return ret;
    }
  }
}

上記の投稿に従って、それは画像の新しいコンテキストを開始し、次にその画像に対してアスペクトを把握し、画像にペイントします。 Swift xcode dev timeを実行していない場合、UIGraphicsは、私が使用するほとんどのシステムに対して少し後方ですが、悪くはありません。1つの問題は、デフォルトでビットマップが下から上にペイントされることです。その周りに、

        context.ScaleCTM(1, -1);
        context.TranslateCTM(0, -sizeNewImage.Height);

描画の方向をより一般的な左上から右下に変更します...しかし、次に原点も移動する必要があるため、TranslateCTMも移動します。

うまくいけば、誰かの時間を節約できます。

乾杯