狛ログ

2022年9月30日金曜日

Photoshopの「書き出し形式」で数倍に書き出した時に画質が劣化してしまうオブジェクト・劣化しないオブジェクトの違い。



こんにちは、オフィス狛 デザイン部のSatoです。


初歩的な話なのですが、Photoshopの書き出し形式機能で小さい画像を2倍など大きいサイズを指定して書き出すと一部のオブジェクトの画質が劣化し、ぼやけてしまうことがあります。

過去に無知故に2倍(2x)で書き出せるなら…と作成したデータを2xで書き出したところ、画像の一部だけが少し劣化してぼやけてしまったことがありました。

この時、画像全体の画質が劣化する訳では無く画像の一部だけ劣化するのが不思議で、画質が落ちる箇所・画質が落ちない箇所の差が何なのかが気になりました🤔

今回は、Photoshopの「書き出し形式」で、元サイズより大きい書き出した時に画質が落ちてしまうオブジェクト・綺麗なオブジェクトの違いについて解説しようと思います。

Photoshopの書き出し形式機能自体は、私が書いた上記の記事でも解説しています。
合わせて読んでいただけると、書き出し形式機能についての基礎もわかりますよ。




書き出し形式機能を利用して、拡大して書き出した場合に画質が落ちぼやけるオブジェクト・画質が落ちずぼやけないオブジェクトの一覧表を作ってみました。

この一覧表自体、Photoshopの書き出し機能を利用しキャンバスサイズの3倍(3x)のサイズで書き出してみたので、クリックして拡大表示してみてくだい👇

同じ画像内でも、こんなに画質が変わってきます。

ぼやけないカテゴリの画像は画質が落ちていませんが、ぼやけるカテゴリに入れている画像はかなり画質が劣化してしまいにじんでしまっています😞


さて、この画質が劣化する・しないの違いは何かというと……。
スマートオブジェクト以外は、「ラスタ形式のオブジェクト」か「ベクタ形式のオブジェクト」かです。


ラスタ形式のオブジェクトは、色のついたピクセルで作られたデータで、拡大するとぼやけてしまいます。

ベクタ形式のオブジェクトは、点と曲線の数値で作られたデータで、拡大してもぼやけません。

ラスタ形式とベクタ形式についての解説は、アドビのラスター&ベクトルが分かりやすいと思います。ぜひ読んでみてください。



しかし、上の説明で
「Photoshopのようなグラフィックソフトで作成するオブジェクトは全部ラスタ形式のはずでは?」
と疑問に思われる方もいらっしゃるかもしれません。

実はグラフィックソフトのPhotoshopでも、ベクタ形式のオブジェクトを扱っています!


Photoshopのベクタ形式のオブジェクトをご紹介します👇

ペンツールやシェイプツール(図形ツール・カスタムシェイプ)などで製図した図形「シェイプ
シェイプで製図した際に作られるレイヤー「シェイプレイヤー」は下記のような見た目になります。



字ツールで文字を打ち込んだ際に作成される「テキスト
テキストを入力した際に作られるレイヤー「テキストレイヤー」は下記のような見た目になります。



Illustratorで作成したオブジェクトをPhotoshopのレイヤーにコピー&ペーストした際に出るペースト形式選択で、スマートオブジェクトを選択した際に作成される「ベクトルスマートオブジェクト




ベクトルスマートオブジェクトをペーストした際に作られるレイヤー「ベクトルスマートオブジェクトレイヤー」は下記のような見た目になります。



以上、3つのオブジェクトは全てベクタ形式のオブジェクトです。


また、ラスタ形式ではありませんが、「元の画像のサイズが書き出したサイズより大きいスマートオブジェクト」は縮小しても元のサイズのデータを保持している為、劣化しません。

しかし、スマートオブジェクトはあくまで元のサイズのデータを保持しているだけですので、「元の画像のサイズが書き出したサイズより小さいスマートオブジェクト」は劣化してしまいます。
スマートオブジェクトも完璧という訳ではないのです。



まとめると、
シェイプレイヤー」「テキストレイヤー」「ベクトルスマートオブジェクトレイヤー」「元の画像のサイズが書き出したサイズより大きいスマートオブジェクト
以上の4つのオブジェクトであれば、ラスタライズしない限りは画質が落ちる事なく等倍で書き出すことが可能です。

逆に「通常レイヤーのオブジェクト」や「元の画像のサイズが書き出したサイズよりも小さいスマートオブジェクト」などのオブジェクトが含まれるキャンバスを等倍で書き出すのは、画質が落ちてしまうので、やめた方が良いでしょう。

Photoshopを使われる方は、覚えておいて損はないと思います🙌

【Sourcetree】カスタムアクションで特定コミット間の差分ファイルをサクッと抽出する。(Mac版)


技術部のyuckieee(ゆっきー)です。
色々なプロジェクトで開発を行っていて、ちょいちょい発生する作業で面倒だなって思っていることがありました。それは納品物やリリース対象物の準備です。

何かというと、運用保守中に追加開発などが発生した場合に、プログラムの差分ファイルのみを納品物やリリース対象として準備する必要があります。
これ、中々に面倒くさいんですよね。間違えたら大変だし、毎回ドキドキしちゃいます(笑)

そこで、出来るだけ間違いが起こらないように自動化出来ないか探してみた結果、私がいつも使っているGit管理ツール「Sourcetree」のカスタムアクションを試してみたら良さげだったので、ご紹介しようと思います。

■作成したカスタムアクションの概要

まずはイメージ共有のため、今回作成したカスタムアクションの概要を説明します。
ざっくりした動作仕様としては「Sourcetreeで現在選択されているリポジトリ-ブランチに存在するコミット間の差分ファイルを取得する。」です。 利用イメージ(方法)は以下のとおり。

[利用イメージ(方法)]
Sourcetreeの該当ブランチの履歴から差分ファイルをとりたいコミットを選択のうえ、カスタムアクションを実行します。 差分を取るためにコミットは2つ選択。ただし、1つだけ選択した場合でも、選択したコミットから最新コミットまでを対象と実行します。
実行時は、経過が分かるようにダイアログにログが表示されます。
実行後、ログ記載の出力先に差分ファイル(zip)、差分ファイル一覧、実行結果ログが格納されます。
以上です!

■カスタムアクションの実装方法

実装完了までの大まかな流れは以下のとおりです。

[実装の流れ]
① 呼び出しスクリプト作成
② カスタムアクション登録
③ 動作確認

それではサクッと詳細の説明に入ります。

① 呼び出しスクリプト作成

最初にカスタムアクションで呼び出されるスクリプトを作成します。
今回はシェルスクリプト(sh)で作成し、実際に作成したコードは以下のとおりです。(スクリプトの引数は②で説明しますが、$1にリポジトリ名、$2$3にコミットIDが指定されています)
#!/bin/sh
#########################################
# ファイル名: export_diff.sh
# 処理内容 : 該当コミット間の差分ファイル出力
#########################################

#########################################
# 変数定義
#########################################
repo_name=$(basename "$(pwd)")
branch_name=$(git rev-parse --abbrev-ref @)
file_name="$(basename "$(pwd)")_diff.zip"
list_name="$(basename "$(pwd)")_diff_list.log"
today="$(date +"%Y%m%d")"
dir_name="export_diff/$repo_name/$branch_name/$today"
log_file=export_diff_result.log

#########################################
# 出力処理 
#########################################
export_diff() {
    # リモートブランチと同期を実行した上で、出力対象をダイアログ表示
    echo ""
    echo "出力を開始します($(date))"
    echo "-------------------"
    echo "■リモートブランチと同期"
    echo "-------------------"
    git pull
    echo ""
    echo "-------------------"
    echo "■出力対象"
    echo "-------------------"
    echo "レポジトリ:${1}"
    echo "ブランチ:${branch_name}"
    echo ""
    echo "-------------------"

    # 差分ファイル出力処理
    if  [ "$3" != "" ]; then
        # 2コミット間の差分ファイルを出力
        git archive --worktree-attributes -o "$file_name" "$2" $(git diff --name-only --diff-filter=du "$3" "$2")
        echo "■差分対象に含まれるコミット"
        echo "-------------------"
        git log "$3"..."$2" --pretty=format:"%h : %s"
        echo ""
    elif  [ "$2" != "" ]; then
        # 選択されたコミットから最新コミットまでを出力
        git archive --worktree-attributes -o "$file_name" HEAD $(git diff --name-only --diff-filter=d "$2" HEAD)
        echo "■差分対象に含まれるコミット"
        echo "-------------------"
        git log "$2"...HEAD --pretty=format:"%h : %s"
        echo ""
    else
        # 上記以外の場合は正しく出力できないためエラーとする
        echo "【ERROR】指定できるコミット数は1又は2です。"
        echo "-------------------"
        exit
    fi

    # 出力された差分ファイルの一覧をリスト出力(ディレクトリのみの表示は除く)
    zipinfo -1 "$file_name" | grep -v /$ > "$list_name"
    echo ""
    echo "-------------------"
    echo "■出力ファイル一覧"
    echo "-------------------"
    cat "$list_name"
    echo ""

    # 出力されたファイル移動(混乱しないように)
    mv "$file_name" ~/"$dir_name"
    mv "$list_name" ~/"$dir_name"
    echo "-------------------"
    echo "■ファイル出力先"
    echo "-------------------"
    echo "${HOME}/$dir_name"
    echo "-------------------"
    echo ""
    echo "出力が完了しました($(date))"
}

#########################################
# メイン処理
#########################################
if [ $# -gt 3 ]; then
    # 選択したコミットが4つ以上の場合は正しく出力できないためエラーとする
    echo "【ERROR】指定できるコミット数は1又は2です。"
    echo "-------------------"
    exit
fi

# 出力ディレクトリを作成
mkdir -p ~/"$dir_name"

# 出力処理を呼び出し
export_diff "$1" "$2" "$3" 2>&1 | tee "${HOME}/$dir_name/$log_file"

...長い!!!(笑)
ダイアログ表示やファイル移動等の余分なコードが含まれていますが、重要なのは以下に抜粋したコマンドです。
git archive --format=zip -o release.zip  --worktree-attributes "$2" $(git diff --name-only --diff-filter=d "$2" "$3")

上記は、Gitが提供している「Git管理対象のみを圧縮形式で出力してくれる」コマンドです。
出力対象の指定がない場合は、指定したブランチ又は、コミット時点のGit管理対象の全ファイルが出力されますが、ファイル名及び、パスを指定することで出力対象ファイルを絞り込むことが出来ます。
今回は、このファイル名・パス指定にgit diffコマンドを使用することで差分ファイルの抽出を実現しました。
以降、git diffgit archive、それぞれのコマンドについて紹介します。

git diffコマンド
差分ファイルを抽出するために使用したコマンドです。
オプションを省いた場合のシンプルな構成は以下のとおりです。
git diff <変更前のコミットID> <変更後のコミットID>
例) git diff 1668413042b61f16f0f353fd66b53cd4c0dbc5d5 2d13b702a783bb2c8252ba07f5410619ee3a0186 
なお、コミットIDの指定順序が逆転してしまうと「削除したファイル」と「新規作成されたファイル」の識別が逆転してしまう等、その後の出力に影響があるので注意してください。

以降に私が指定が必要そうだと考えたオプションについて補足します。

[コマンドオプション]
--name-only  (必須)
差分比較結果としてファイル名(パス含む)のみを返す指定です。
本オプションを指定しない場合、ズラズラとコミット間の比較内容が表示されるのですが、それがgit archiveに引数として渡ってしまうとエラーになりますので指定必須です。

--diff-filter=<出力対象の指定>  (必須)
例)--diff-filter=ACMR
指定することで、差分取得対象を絞り込むことが出来ます。
このオプションは、大文字で記述すると「出力対象」を、小文字で記述すると「出力除外対象」を指定することが出来ます。それぞれのオプション文字列の説明を下表にまとめました。

指定可能なオプション文字列    
オプション
文字列
説明
A/a 追加されたファイル
C/c コピーされたファイル
D/d 削除されたファイル
M/m ファイル内容又は、ファイル属性が変更されたファイル
R/r ファイル名が変更されたファイル
T/t ファイルタイプ(通常ファイル、シンボリックファイル、サブモジュール等)が変更されたファイル
U/u マージされていないファイル(コンフリクトファイル確認時に使用されるようです)
B/b ペアリングが壊れているファイル
X/x 不明な変更タイプ(通常は有り得ないようです)

今回は差分に「削除されたファイルのパス」が返ってしまうとgit archive時に対象無しのエラーになってしまうので「明確に出力対象としたいファイルのみ」を指定しました。
この指定方法以外に--diff-filter=dとすることで、削除されたファイルを「出力対象外」にすることも可能です。

git archiveコマンド
指定したコミット時点のGit管理対象ファイルを圧縮出力してくれるコマンドです。(ブランチ指定も可能ですが、Sourcetreeから引数として受け取れないので説明割愛します)
指定したコミットID時点のファイルが出力対象となりますので、当たり前ではありますが、必ず変更後のコミットIDを指定するようにしてください。
git archive <変更後コミットID>
例) git archive 1668413042b61f16f0f353fd66b53cd4c0dbc5d5

[コマンドオプション]
--format=<圧縮形式>   (任意)
例) --format=zip
出力される差分ファイルの圧縮形式として、zip形式又はtar形式が指定可能です。
このオプションが指定されていない場合は、ファイル名に付与された拡張子から推測され、推測ができない場合はtar形式となるようです。
今回はzip形式で出力したいため、念のため、フォーマットも指定しておきました。

-o <ファイル名> (必須)
※--output=<ファイル名>としても同じ
例) -o export_diff.zip
本オプションを指定しない場合は、標準出力(コンソール)に結果が出力されます。
結果をファイルに出力したい場合は、本オプションを付与した上で、 出力ファイル名称を指定する必要があります。

--worktree-attributes(任意)
Git管理対象となっているファイルでも、今回の出力対象として含めたくない!というファイルがある場合は、本オプションを使用します。 例えば、本番環境へのリリース対象としてReadMeや環境変数のサンプルファイルなどは不要で、これらを除外したい、と言う時に使います。

なお、除外対象は、リポジトリ直下にある.gitattributesファイルに記述することで認識されます。
以下のように対象ファイル export-ignoreと書き込めばOKです。
README.md export-ignore
*.example export-ignore
試してみた感じでは、今回の実装内容であれば、本ファイルをリモートリポジトリにマージしていなくても適用されるようでした。

--prefix=<プレフィックス文字列/> (任意)
例)--prefix=prod/
今回は使用しませんでしたが、出力されるファイルを特定のディレクトリでラップしたい場合に指定します。 例えば--prefix=prod/と入力しておくと、出力されたzipを解凍した際にprodディレクトリの配下に差分ファイルが格納されることになります。
試してみたところ--prefix=prod/app1/など、ディレクトリを多階層で指定することもできるようでした。

ザックリ説明はここまでとなりますが、各コマンドには他にもオプションがありますので、公式ドキュメントを参考にしながら試してみるのも面白いと思います。
git-diffコマンド (Documentation - Reference)
git-archiveコマンド (Documentation - Reference)

なお、スクリプトについては、私のやりたように書いていますが、自分仕様にカスタマイズいただければと思います♪(見やすさ重視でechoの乱れ咲きさせてたり...笑)

② カスタムアクションの登録

①で作ったスクリプトを実際にSourceTreeに登録します。
Sourcetreeを開き、左上の[Sourcetree]>[環境設定...]を押下し、設定画面を開きます。そのうえで、右上にある[>>]>[カスタムアクション]を選択してカスタムアクションの定義画面を開き、左下の[追加]ボタンを押下してください。

[注意事項]
Sourcetree日本語版では、不具合(確認したところ、4.1及び、4.2.0は駄目でした)により上記の流れで画面を開いた場合、カスタムアクションが非活性となっており選択できないようです!(笑)
選択できない場合は、対処法として2パターン有り、1つ目が言語を英語に切り替えてSourcetreeの再立ち上げを行う方法、2つ目がトップ画面で任意のリポジトリ右クリックメニューから[カスタムアクション]>[編集...]を選択する方法です。どちらかお好きな方をお試しください。

登録画面が開きますので、必要事項を入力し[OK]を押下して、登録を完了させます。

【登録内容】
 メニューキャプション:差分出力(zip) ※1
 別のウィンドウで開く:チェックオフorオン どちらでも可 ※2
 フル出力を表示:チェックオン ※3
 実行するスクリプト:①で作成したスクリプトを選択
 パラメータ:$REPO $SHA ※4
※1:メニューに表示される名称なので、お好きなものを指定してください。
※2:選択したファイルをVSCodeなどの別ウィンドウで表示したい場合は、このチェックをオンにします。なお、このチェックをオンにすることでダイアログも別ウィンドウとなるのでダイアログの拡大縮小が可能になります。
※3:チェックがオフの場合は、エラーのみがダイアログ表示されます。今回は全て表示したいのでチェックをオンにします。
※4:$SHAについては、複数コミットを選択した場合、コミットタイミングが新しいコミットIDから順に、選択した全てのコミットIDがスクリプトの引数として渡されます。(順番の選択順には依らないようです)

③ 動作確認

最後に動作確認を行います。
今回登録したカスタムアクションは、できるだけ汎用的に作っているので、どのリポジトリ、ブランチでも対応可能(な、はず)ですので、皆さんも動作確認してみてください。
実行方法は、「■作成したカスタムアクションの概要」と同様の流れになるため、説明は割愛しますが、コミットの選択方法について、少しだけ補足します。

[実行時の補足事項]
Sourcetreeのデフォルトでは、履歴に「すべてのブランチ」のコミットが表示されています。
この場合、親ブランチの差分を取得しようとした際に、間違って未マージの子ブランチのコミットを選択してしまっても、それらが差分出力対象となっているようでした。(これは--diff-filter=uとしても結果は変わりませんでした)

そのため、履歴の表示フィルターを使用して「現在のブランチ」のみの表示にしておくと、ミスがなくて良いのかなと思います。

ここまでで、カスタムアクションの実装は完了となります!
これでサクッと差分ファイルの抽出ができるようになったので、これからのリリース準備作業も捗りそうです♪
ただし、自動化しても、間違いがないかのダブルチェックは怠らず!!

■まとめ

Sourcetreeやgitには、沢山の便利機能やコマンドがあるのに活用できていないなぁ、と、改めて感じました。
特に今回使ったSourcetreeのカスタムアクションは、利用の幅が広く、もっと色々な応用がききそうだなと感じたため、継続して色々と試してみたいと思います。

laravel-analyticsを使用して、Universal Analyticsの値を取得する方法。


オフィス狛 技術部のmmm(むー)です。

今回、LaravelからUniversal Analyticsの値を取得する必要があり、調査したため記事に残します。

※ちなみに、Universal Analyticsは2023年7月1日にサービスが終了されるので、時間に余裕があり移行できる場合、Google Analytics 4を使用しましょう。

前提条件

Universal Analyticsの設定が完了していること

■Laravel バージョン
$ php artisan -V
Laravel Framework 8.27.0

■Comporser バージョン
$ composer --version 
Composer version 2.4.1 2022-08-20 11:44:50


1. laravel-analyticsをインストールする

laravel-analyticsをインストールします。
# laravel-analytics(バージョン 4.0.1)をインストールする
$ composer require spatie/laravel-analytics 4.0.1

■補足
・ 2022/09/07現在、laravel-analyticsの最新バージョンは 4.1.0ですが、今回のプロジェクトのLaravelのバージョンが8で対応していなかったので、1つ下のバージョンの 4.0.1をインストールしています。
・Laravel 9を使用している場合、(試していませんが)最新バージョンを使用できるので、バージョン指定なしで、composer require spatie/laravel-analyticsを代わりに実行してください。

■エラーが起きた場合
・composerのバージョンが1でメモリエラーになる場合、composerを2に更新すると解決することがあるようです。
# comporserのバージョンを「1」から「2」に更新する
$ docker exec -it yanase-ybs_app_1 composer self-update --2

・また関連してインストールされるパッケージが多く、私の環境の場合、google/apiclient-servicesをインストールしている最中にタイムアウトしました。その場合、laravel-analyticsをインストールするコマンドをもう一度実行すると、google/apiclient-servicesだけ差分でインストールできます。
# laravel-analyticsをインストールした際のエラーログ
$ composer require spatie/laravel-analytics 4.0.1

〜省略〜

  - Installing symfony/cache (v5.4.11): Extracting archive
  - Installing spatie/laravel-package-tools (1.12.1): Extracting archive
  - Installing google/apiclient (v2.12.1): Extracting archive
  - Installing spatie/laravel-analytics (4.0.1): Extracting archive
 103/104 [===========================>]  99%    Install of google/apiclient-services failed

In Filesystem.php line 314:
                                                                                                                                    
  Could not delete /work/vendor/composer/e8a27dbc/googleapis-google-api-php-client-services-28c4208/src/SASPortalTesting/Resource:


2. laravel-analyticsを使用するための設定を行う

下記コマンドを実行すると、設定ファイル(config/analytics.php)が作成されます。
# 設定ファイル(config/analytics.php)を作成する
$ php artisan vendor:publish --provider="Spatie\Analytics\AnalyticsServiceProvider"

config/analytics.phpの中身を見ると下記の様になっています。
// config/analytics.php
return [

    /*
     * The view id of which you want to display data.
     */
    'view_id' => env('ANALYTICS_VIEW_ID'),

    /*
     * Path to the client secret json file. Take a look at the README of this package
     * to learn how to get this file. You can also pass the credentials as an array
     * instead of a file path.
     */
    'service_account_credentials_json' => storage_path('app/analytics/service-account-credentials.json'),

    /*
     * The amount of minutes the Google API responses will be cached.
     * If you set this to zero, the responses won't be cached at all.
     */
    'cache_lifetime_in_minutes' => 60 * 24,

    /*
     * Here you may configure the "store" that the underlying Google_Client will
     * use to store it's data.  You may also add extra parameters that will
     * be passed on setCacheConfig (see docs for google-api-php-client).
     *
     * Optional parameters: "lifetime", "prefix"
     */
    'cache' => [
        'store' => 'file',
    ],
];

まず、view_idを設定する必要があるので、.env に値をUniversal Analyticsの画面で取得した値を記載してください。 (下記は例となりますので、ご自身の環境に合わせて値を修正してください。)
// .env
ANALYTICS_VIEW_ID=1234567

次に、service_account_credentials_jsonを設定する必要があるので、app/analytics/フォルダの配下にservice-account-credentials.jsonファイルを作成して、Universal Analyticsの画面で取得した値を記載してください。 (下記は例となりますので、ご自身の環境に合わせて値を修正してください。)
// app/analytics/service-account-credentials.json
{
  "type": "service_account",
  "project_id": "testapi",
  "private_key_id": "...",
  "private_key": "...",
  "client_email": "...",
  "client_id": "1234",
  "auth_uri": "...",
  "token_uri": "...",
  "auth_provider_x509_cert_url": "...",
  "client_x509_cert_url": "..."
}


3. Universal Analyticsの値を取得する

下記に、一例ですが値を取得する方法を記載します。
namespace App\Console\Commands;

use Illuminate\Console\Command;
use Analytics;
use Spatie\Analytics\Period;

class TestCommand extends Command
{

	// 例1:
	// 1日分の訪問者数とページビューを取得します。
	// こちらはlaravel-analyticsが用意しているメソッドとなります。
	$data1 = Analytics::fetchVisitorsAndPageViews(Period::days(1));

	// 例2:
	// 期間を指定して、7日分の訪問者数とページビューを取得します。
	// ちなみにライブラリ内で日付に変換されるので、時間は設定できません。
	$periodFrom = Carbon::now()->subDay(7);
	$periodTo = Carbon::now();
	$period = Period::create($periodFrom, $periodTo);
	$data2 = Analytics::fetchVisitorsAndPageViews($period);

	// 例3:
	// 取得する指標、取得項目、ソート順をカスタムしたい場合は、performQuery()を使用してください。
	// 指標(合計イベント数)
	$metrics = 'ga:totalEvents';
	// 取得項目(イベントラベル)、ソート(合計イベント数の降順)
	$item = [
            'dimensions' => 'ga:eventLabel',
            'sort' => '-ga:totalEvents',
	];
	$data3 = Analytics::performQuery(Period::days(3), $metrics, $item);

}

fetchVisitorsAndPageViews()以外のメソッドについては、公式ページを確認してみてください。
公式が用意しているメソッドで、項目が取得できない場合はperformQuery()メソッドを使用してください。
指定する項目は、下記から必要なものを指定してください。
■参考サイト:https://ga-dev-tools.web.app/dimensions-metrics-explorer/

以上となります。
参考にして頂ければ幸いです。

,