2
2

More than 5 years have passed since last update.

Swift/Xcode:Image Assetsの@2x,@3x画像をコードでリサイズするときは注意しろよな☺️

Posted at

解像度が異なる画像をプラットフォームや場面ごとにいい感じに仕分けて出力してくれるAssets Catalogめちゃ便利ですよね.この画像をそのまま使うんならなんの問題もないのですが,後からコードでリサイズする場合は気をつけてください!

一例

例えばRunCatのデフォルト猫ちゃんの情報を出力してみましょう.
neko.png
画像サイズは56 × 36 pxで,Scaleは2xとなっていますね.

コードの方でも確認してみます.

let img = NSImage(imageLiteralResourceName: "cat_page0")
Swift.print(img.description)
<NSImage 0x60000177eb00 Name=cat_page0 Size={28, 18} Reps=(
    "NSCGImageRep 0x60000177ec40 Size={28, 18} ColorSpace=sRGB IEC61966-2.1 colorspace BPS=0 Pixels=56x36 Alpha=NO AppearanceName=NSAppearanceNameSystem"
)>

Size={28, 18}Pixels={56x36}に注目してください.Scaleが2xなので当然ですが,画像のサイズとピクセルサイズが異なっていますね.

この画像をCALayerを用いて表示する場合,contentsScaleを意識しないと解像度ズレがおきて大きさが正しくない画像が表示されてしまいます.
単純にリサイズせずにこのまま表示するのであれば,contentsScaleを計算して指定してあげればOKです.

let rep = img.representations[0]
let scale = CGFloat(rep.pixelsWide) / img.alignmentRect.width

layer.contents = img
layer.contentsScale = scale

リサイズする場合はどの部分をリサイズするのか,全体のアスペクトを保つのかどうか,余白を付け足すのかなどを気をつける必要があります.

例えば,ピクセルのことを意識せずに,ただ単に画像のサイズを別に指定することも可能ですが,この場合はcontentsScaleをそれに合わせないとおかしなことになります.

特に余白をつける場合はcontentsGravityも意識しないといけません.

余白つける場合
img.size = CGSize(width: img.size.width + 5.0, height: img.size.height)
//とか NSCIImageRep使ったり, CIFilter(name: "CIAffineTransform")使ったり

layer.contentsGravity = CALayerContentsGravity.left // center, rightとかで余白がつく位置が変わる.

リサイズや画像加工の状況によりやるべきことが変わりますが,contentsScalecontentsGravityの2つをきちんと意識すればなんとかなると思います.

蛇足

そもそもコードで画像を後から加工するなら,Assets Catalogでの設定をIndividual ScalesではなくSingle Scaleにしろよ.という話なのかもしれませんが.メニューバー開発においては解像度2倍がとても大切でした...

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2