読者です 読者をやめる 読者になる 読者になる

しっぽを追いかけて

ぐるぐるしながら考えています

Unity と猫の話題が中心   掲載内容は個人の私見であり、所属組織の見解ではありません

Path からスプラッシュ画像やアプリロゴ画像を作成するツール

Windows ストアアプリ C# WPF Windows ランタイムアプリ

Windows ストアアプリのアプリロゴ、スプラッシュなどのロゴは、オリジナルの物の用意が必須なうえに、さまざまなデバイスで美しく表示されるようにするためには下記のページにあるような多くのサイズの画像素材を用意する必要が出てきます。

アプリ画像の選択 (Windows)

デザイナーさんでもこれはなかなかに大変!

画像をもとにしてこれらを作る場合は、エバンジェリストの高橋忍さん開発の Windows Store App logo Maker という大変便利なツールで簡単に作成できます。

ただ自分の場合はベクターベースの Path でロゴ素材を作りたい!・・・探してみましたがありませんでした;

もはやこのブログの決まり文句になりつつある・・・ないならば作るしかない!

f:id:matatabi_ux:20140228075427p:plain

ということ自分のほしいものを作ってみました!

日本語版インストーラsetup-ja.zip

English Installer:setup-en.zip

Metro Studiio 2 などで XAML の Path の Data 部分をコピーして貼り付けると、各種ロゴにレイアウトされます。

前景色、背景色、大きさ、余白、アプリ名と表示の有無などを調整して、F5 キーでロゴをエクスポートできます。

いつぞやの Path 正規化ツールがベースになっているのですが、少し Path データの解析が改良されています。

/// <summary>
/// Data の変更後の処理
/// </summary>
partial void OnDataChanged()
{
    if (string.IsNullOrWhiteSpace(this.Data))
    {
        this.Geometry = null;
        return;
    }

    try
    {
        var pathGeometory = (Geometry.Parse(this.Data).Clone() as StreamGeometry).GetOutlinedPathGeometry();
        var width = pathGeometory.Bounds.Width;
        var height = pathGeometory.Bounds.Height;
        var scaled = new PathGeometry();

        foreach (var figure in pathGeometory.Figures)
        {
            var newFigure = new PathFigure();

            newFigure.StartPoint = figure.StartPoint;
            newFigure.StartPoint.Offset(-pathGeometory.Bounds.Left, -pathGeometory.Bounds.Top);

            foreach (PathSegment segment in figure.Segments)
            {
                PathSegment newSegment = null;

                switch (segment.GetType().Name)
                {
                    case "BezierSegment":
                        var bezier = new BezierSegment()
                        {
                            Point1 = ((BezierSegment)segment).Point1,
                            Point2 = ((BezierSegment)segment).Point2,
                            Point3 = ((BezierSegment)segment).Point3,
                            IsSmoothJoin = segment.IsSmoothJoin,
                            IsStroked = segment.IsStroked,
                        };
                        bezier.Point1.Offset(-pathGeometory.Bounds.Left, -pathGeometory.Bounds.Top);
                        bezier.Point2.Offset(-pathGeometory.Bounds.Left, -pathGeometory.Bounds.Top);
                        bezier.Point3.Offset(-pathGeometory.Bounds.Left, -pathGeometory.Bounds.Top);

                        newSegment = bezier;
                        break;

                    case "PolyBezierSegment":
                        var polyBezier = new PolyBezierSegment()
                        {
                            IsSmoothJoin = segment.IsSmoothJoin,
                            IsStroked = segment.IsStroked,
                        };

                        foreach (var point in ((PolyBezierSegment)segment).Points)
                        {
                            polyBezier.Points.Add(
                                new Point(
                                point.X - pathGeometory.Bounds.Left,
                                point.Y - pathGeometory.Bounds.Top));
                        }
                        newSegment = polyBezier;
                        break;

                    case "PolyLineSegment":
                        var polyLine = new PolyLineSegment()
                        {
                            IsSmoothJoin = segment.IsSmoothJoin,
                            IsStroked = segment.IsStroked,
                        };

                        foreach (var point in ((PolyLineSegment)segment).Points)
                        {
                            polyLine.Points.Add(
                                new Point(
                                point.X - pathGeometory.Bounds.Left,
                                point.Y - pathGeometory.Bounds.Top));
                        }
                        newSegment = polyLine;
                        break;

                    case "LineSegment":
                        var line = new LineSegment()
                        {
                            Point = ((LineSegment)segment).Point,
                            IsSmoothJoin = segment.IsSmoothJoin,
                            IsStroked = segment.IsStroked,
                        };
                        line.Point.Offset(-pathGeometory.Bounds.Left, -pathGeometory.Bounds.Top);

                        newSegment = line;
                        break;
                }
                newFigure.Segments.Add(newSegment);
            }
            scaled.Figures.Add(newFigure);
        }
        scaled.Freeze();

        this.Geometry = scaled;
        this.data = scaled.ToString();

        if (!string.IsNullOrEmpty(this.data))
        {
            initialData = this.data;
        }
    }
    catch (Exception)
    {
        this.Geometry = null;
    }

    this.RaisePropertyChanged("Data");
}

上記のように直線だけでなくベジェ曲線による描画も行うようにしたので、ロゴ部分を拡大しても曲線の滑らかさが維持されるようになりました!