Xcode(つまりpdfファイル)でベクター画像はどのように機能しますか?


176

Xcode 6でベクターサポートはどのように機能しますか?

画像のサイズを変更しようとすると、ギザギザに見えますが、何が原因ですか?

回答:


351

Xcode(7および6.3+)でベクターを使用する方法:

  1. 適切な@ 1xサイズ(たとえば、ツールバーボタンの場合は24x24)で画像を.pdfファイルとして保存します。
  2. あなたにImages.xcassetsファイル新規作成、イメージセットを
  3. インスペクタ属性、設定スケールファクター単一のベクトルを
  4. PDFファイルを「すべてのユニバーサル」セクションにドラッグアンドドロップします。
  5. これで、他の.pngファイルと同じように、イメージをその名前で参照できます。

    UIImage(named: "myImage")

古いバージョンのXcode(6.0-6.2)でベクターを使用する方法:

  • 上記のステップに従いますが、ステップ3を除いて、タイプベクトルに設定します。

Xcodeでのベクトルの仕組み

Xcodeでベクトルのサポートが混乱しているのは、ほとんどの人がベクトルを考えるとき、拡大縮小しても見栄えがよい画像を考えるからです。ただし、Xcode 6および7はiOSの完全なベクトルサポートを備えていないため、動作は少し異なります。

ベクトルシステムは本当にシンプルです。それはあなたのかかる.pdf画像を、そして作成し@1x.png@2x.png、と@3x.pngの資産ビルド時間。(Assets.carの内容を調べるツールを使用してこれを確認できます。)

たとえばfoo.pdf、44x44のベクターアセットが指定されたとします。で、ビルド時には、以下のファイルが生成されます。

  • foo@1x.png 44x44
  • foo@2x.png 88x88
  • foo@3x.png 132x132で

これは、どのサイズの画像でも同じように機能します。たとえば、bar.pdf100x100の場合、次のようになります。

  • bar@1x.png 100x100
  • bar@2x.png 200x200
  • bar@3x.png 300x300

含意:

  • 画像の新しいサイズを選択することはできません。44x44のサイズを維持する場合にのみ見栄えが良くなります。その理由は、完全なベクトルサポートが実装されていないためです。これらのベクターが行う唯一のことは、画像アセットを保存する時間を節約することです。これをワンステッププロセスにしたツール(Photoshopスクリプトなど)を使用している場合、pdfベクトルを使用することで得られる唯一のことは、将来を保証するサポートです(たとえば、iOS 9でAppleが@ 4xアセットを必要とし始めた場合、これらは正常に動作します)、維持するファイル少なくなります
  • すべてのアセットを@ 1xサイズでPDFファイルとして保存するように依頼する必要があります。特に、これにより、UIImageViewsが正しい固有のコンテンツサイズを持つことができます。

なぜ(おそらく)このように機能するのですか?

  • これにより、以前のiOSバージョンと下位互換性があります。
  • ベクトルのサイズ変更は、実行時に計算集約的なタスクになる場合があります。この方法で実装することにより、パフォーマンスへの影響はありません

8
素敵な書き込み。これについては、2014 WWDCセッション411-「Interface Builderの新機能」で44:13に説明されています。ラスタライズはビルド時に行われると彼らは言っていることに注意してください。また興味深いことに、MACでは実行時にベクターを使用します。将来のある時点で、うまくいけばiOSもそうなるでしょう。
Mike Vosseller、2014

15
残念ながら、スライス値はスケーリングされません。したがって、コーナーを5でスライスしても、2xおよび3x画像の場合、10と15にスケーリングされません。
ジェシー、

5
@Jesseスライス値をスケーリングしたい場合は、スライス値を使用resizableImageWithCapInsets:して分割することにより、コードで自分で行うことができます[UIScreen mainScreen].scale
Arie Litovsky

1
スライスに関する@ArieLitovskyの提案を明確にするには、次のように、アセットからスライス削除してコードに移動する必要がありますCGFloat scale = [UIScreen mainScreen].scale; UIImage *image = [[UIImage imageNamed:@"my_unsliced_asset"] resizableImageWithCapInsets:UIEdgeInsetsMake(10 * scale, 11 * scale, 12 * scale, 13 * scale)];
glyuck

6
XCode 8でこれを行うにはどうすればよいですか?オプションがなくなったようです!
ジェラルド

26

Xcode 8では、PDFを追加したり、新しい画像セットを作成したり、属性インスペクターでスケールをシングルスケールオプションに設定したりできます。 ここに画像の説明を入力してください


15

これは、@ Sensefulによる優れた回答の補足です。

.pdf形式でベクター画像を作成する方法

Inkscapeでこれを行う方法を説明します。これは無料でオープンソースですが、他のプログラムも同様であるためです。

Inkscapeの場合:

  1. 新しいプロジェクトを作成します。
  2. [ファイル]> [ドキュメントプロパティ]に移動し、カスタムページサイズを@ 1xサイズ(44x44、100x100など)に設定します(単位はpx)。
  3. アートワークを作成します。
  4. [ファイル]> [名前を付けて保存]> [印刷可能なドキュメント形式(* .pdf)]> [保存]> [OK]に移動します。(または、[印刷]> [ファイルへ出力]> [出力形式:PDF]> [印刷]に移動できますが、オプションはそれほど多くありません。)

ノート:

  • 受け入れられた回答で述べられているように、Xcodeはビルド時にラスタライズされた画像を生成するため、画像のサイズを変更することはできません。画像のサイズを変更する必要がある場合は、異なるサイズの新しい.pdfファイルを作成する必要があります。
  • 間違ったページサイズの.svgイメージが既にある場合は、次の手順を実行します。

    1. ページサイズを変更する(Inkscape>ファイル>ドキュメントプロパティ)
    2. ワークスペースですべてのオブジェクトを選択し(Ctrl + A)、新しいページサイズに合わせてサイズを変更します。(Ctrlキーを押しながらアスペクトサイズを維持します。)
  • .svgファイルを.pdfに変換するには、作業を行うオンラインユーティリティを見つけることもできます。ここでは一例であるから、この答えが。これには、.pdfサイズを簡単に設定できるという利点があります。

参考文献


12

まだアップデートしていない人のために、Xcode 9(iOS 11)で変更がありました。

Cocoa Touchの新機能(WWDC 2017セッション201)(@ 32:55) https://developer.apple.com/videos/play/wwdc2017/201/

簡単に言うと、アセットカタログの属性インスペクターに「ベクターデータを保持」という新しいチェックボックスが追加されました。オンにすると、PDFデータがコンパイル済みバイナリに含まれ、当然サイズが増加します。しかし、それはiOSがベクトルデータを両方向にスケーリングし、素晴らしい画像を提供する機会を与えます(それ自体に困難があります)。11未満のiOSでは、上の回答で説明されている古いスケーリングメカニズムが使用されます。


1

プロジェクト内の通常のPDFファイルをベクター画像として使用し、この拡張機能を使用して任意のサイズの画像をレンダリングできます。iOSはPDFファイルから.PNG画像を生成しないため、この方法の方が優れています。さらに、任意のサイズの画像をレンダリングできます。

    extension UIImage {

    static func fromPDF(filename: String, size: CGSize) -> UIImage? {
        guard let path = Bundle.main.path(forResource: filename, ofType: "pdf") else { return nil }
        let url = URL(fileURLWithPath: path)
        guard let document = CGPDFDocument(url as CFURL) else { return nil }
        guard let page = document.page(at: 1) else { return nil }

        let imageRect = CGRect(x: 0, y: 0, width: size.width, height: size.height)
        if #available(iOS 10.0, *) {
            let renderer = UIGraphicsImageRenderer(size: size)
            let img = renderer.image { ctx in
                UIColor.white.withAlphaComponent(0).set()
                ctx.fill(imageRect)
                ctx.cgContext.translateBy(x: 0, y: size.height)
                ctx.cgContext.scaleBy(x: 1.0, y: -1.0)
                ctx.cgContext.concatenate(page.getDrawingTransform(.artBox, rect: imageRect, rotate: 0, preserveAspectRatio: true))
                ctx.cgContext.drawPDFPage(page);
            }

            return img
        } else {
            // Fallback on earlier versions
            UIGraphicsBeginImageContextWithOptions(size, false, 2.0)
            if let context = UIGraphicsGetCurrentContext() {
                context.interpolationQuality = .high
                context.setAllowsAntialiasing(true)
                context.setShouldAntialias(true)
                context.setFillColor(red: 1, green: 1, blue: 1, alpha: 0)
                context.fill(imageRect)
                context.saveGState()
                context.translateBy(x: 0.0, y: size.height)
                context.scaleBy(x: 1.0, y: -1.0)
                context.concatenate(page.getDrawingTransform(.cropBox, rect: imageRect, rotate: 0, preserveAspectRatio: true))
                context.drawPDFPage(page)
                let image = UIGraphicsGetImageFromCurrentImageContext()
                UIGraphicsEndImageContext()
                return image
            }
            return nil
        }
    }

}

1
私はこれを試しましたが、それは画像をより大きなピクセルサイズに拡大するようには見えませんか?私が取得しているUIImage自体は正しいサイズです。ベクター画像が中央に配置され、PDFの元のピクセルサイズのままであるだけです。(UIImageのサイズに合わせてスケーリングしたかったのです。)これが可能かどうか知っていますか?
DivideByZer0 2017年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.