CodeIQ MAGAZINECodeIQ MAGAZINE

【謎解きプログラム】フィルターを使ってみよう【SVG】解答と解説

2017.02.09 Category:CodeIQ問題解説・リーダーボード Tag:

  • 3
  • このエントリーをはてなブックマークに追加
entry

言語不問で、プログラムにちなんだ謎を解く「謎解きプログラム」。

あなたは見事、謎を解けましたか? というわけで、出題者の柳井さんによる解答と解説をどうぞ!
by CodeIQ運営事務局

【謎解きプログラム】フィルターを使ってみよう【SVG】

本問題は、表題のテーマで、プログラムにちなんだ謎を解くというものでした。

それでは以下、各問題とその解答を見ていきましょう。

問題のオープニング

ある日、出社すると、あなたのPCのログイン画面に、謎の挑戦状が表示されていた。

「24時間以内にが解けない場合は、このPCのデータは消失する。

 は、あなたが真のプログラマーなら解けるものだ」

これは挑戦状ではなく脅迫状だ!

そこには、見たことのない謎が掲載されていた。

あなたは歴戦のプログラマーとして、データを救うために、この謎に挑むことになった。

予備知識

SVGのフィルターは、<filter>タグ内で、各種フィルターのタグを使いフィルターをかけていきます。その際、in属性で入力名、result属性で出力名を指定して、パイプ処理のように効果を連結していきます。

in属性に指定する名前には、「SourceGraphic」(元の図形)や、「SourceAlpha」(元の図形のアルファチャンネル)といった特別なものもあります。また、result属性で指定した名前を、他のフィルターのin属性で指定できます。

各種フィルターのタグは、先頭の「fe」を取った名前の効果になります。以下、例です。

「feGaussianBlur」→「GaussianBlur」(ガウスぼかし)
「feOffset」→「Offset」(オフセット)
「feMorphology」→「Morphology」(形態)、属性「operator」が「dilate」なら拡張
「feColorMatrix」→「ColorMatrix」(カラーマトリクス)

また、<feMerge>タグ内では、「<feMergeNode>」タグで入力を描画順に並べて図形を合成できます。

問題1

以下に示されたSVGの場合、実際に描画される図を、図1~3で選んでください。

<svg viewBox="0 0 200 200">
  <defs>
    <filter id="f1" filterUnits="objectBoundingBox"
      x="-1" y="-1" width="3" height="3">
      <feGaussianBlur
        in="SourceAlpha" stdDeviation="10"
        result="blur"/>
      <feMerge>
        <feMergeNode in="blur"/>
        <feMergeNode in="SourceGraphic"/>
      </feMerge>
    </filter>
  </defs>
  <rect x="0" y="0" width="200" height="200"
    stroke-width="3" stroke="#fa0" fill="#ffa"/>
  <circle cx="100" cy="100" r="75"
    filter="url(#f1)"
    stroke-width="3" stroke="#0a6" fill="#afc"/>
</svg>

図1

図2

図3

// 選択肢
図1
図2
図3

上から順番に見ていきましょう。

<feGaussianBlur in="SourceAlpha" stdDeviation="10" result="blur"/>

上記では、入力(in)が「SourceAlpha」(元の画像のアルファ値)で、出力(result)が「blur」(という名前)になっています。

「feGaussianBlur」は、ガウスぼかしのフィルターです。「standard deviation」(標準偏差、散らばり具合)では散らばり具合を指定します。これで、元画像のアルファ値を元に、ぼかした画像が作成されます。

<feMerge>
  <feMergeNode in="blur"/>
  <feMergeNode in="SourceGraphic"/>
</feMerge>

次に、「<feMerge>」で、配下の「<feMergeNode>」の2画像を合成しています。

合成する画像は、入力(in)が「blur」(先ほど、ガウスぼかしフィルターで作った画像)と、入力(in)が「SourceGraphic」(元の画像)です。

この合成の順番は、「blur」が先で、「SourceGraphic」が後になります。つまり、ガウスぼかしをかけた画像を描画して、元の画像を描画することになります。

そのため、作成される図は、図2となり、2番目の選択肢の「図2」が答えになります。

問題2

以下に示されたSVGの場合、実際に描画される図を、図1~3で選んでください。

<svg viewBox="0 0 200 200">
  <defs>
    <filter id="f2" filterUnits="objectBoundingBox"
      x="-1" y="-1" width="3" height="3">
      <feGaussianBlur
        in="SourceAlpha" stdDeviation="10"
        result="blur"/>
      <feOffset
        in="blur" dx="10" dy="10"
        result="offset"/>
      <feMerge>
        <feMergeNode in="offset"/>
        <feMergeNode in="SourceGraphic"/>
      </feMerge>
    </filter>
  </defs>
  <rect x="0" y="0" width="200" height="200"
    stroke-width="3" stroke="#fa0" fill="#ffa"/>
  <circle cx="100" cy="100" r="75"
    filter="url(#f2)"
    stroke-width="3" stroke="#0a6" fill="#afc"/>
</svg>
図1

図2

図3

// 選択肢
図1
図2
図3

上から順番に見ていきましょう。

<feGaussianBlur in="SourceAlpha" stdDeviation="10" result="blur"/>

上記では、入力(in)が「SourceAlpha」(元の画像のアルファ値)で、出力(result)が「blur」(という名前)になっています。

「feGaussianBlur」は、ガウスぼかしのフィルターです。「standard deviation」(標準偏差、散らばり具合)では散らばり具合を指定します。これで、元画像のアルファ値を元に、ぼかした画像が作成されます。

<feOffset in="blur" dx="10" dy="10" result="offset"/>

次に、上記では、入力(in)が「blur」(ガウスぼかしフィルターで作った画像)で、出力が「offset」(という名前)になっています。

「feOffset」は、オフセットのフィルターです。「dx」「dy」で、X軸、Y軸の移動量を指定します。これで、入力画像を、「dx」「dy」分移動した画像が作成されます。

<feMerge>
  <feMergeNode in="offset"/>
  <feMergeNode in="SourceGraphic"/>
</feMerge>

最後に、「<feMerge>」で、「<feMergeNode>」の2つの画像を合成しています。

合成する画像は、入力(in)が「offset」(先ほど、オフセットフィルターで作った画像)と、入力(in)が「SourceGraphic」(元の画像)になります。

この合成の順番は、「offset」が先で、「SourceGraphic」が後になります。つまり、ガウスぼかしをかけて移動した画像を描画して、元の画像を描画することになります。

そのため、作成される図は、図3となり、3番目の選択肢の「図3」が答えになります。

問題3

以下に示されたSVGの場合、実際に描画される図を、図1~3で選んでください。

<svg viewBox="0 0 200 200">
  <defs>
    <filter id="f3" filterUnits="objectBoundingBox"
      x="-1" y="-1" width="3" height="3">
      <feMorphology
        in="SourceAlpha" operator="dilate" radius="3"
        result="morph"/>
      <feColorMatrix
        in="morph" type="matrix" values="0 0 0 0 1
                                         0 0 0 0 1
                                         0 0 0 0 1
                                         0 0 0 1 0"
        result="mtrx"/>
      <feOffset
        in="morph" dx="5" dy="5"
        result="offset"/>
      <feMerge>
        <feMergeNode in="offset"/>
        <feMergeNode in="mtrx"/>
        <feMergeNode in="SourceGraphic"/>
      </feMerge>
    </filter>
  </defs>
  <rect x="0" y="0" width="200" height="200"
    stroke-width="3" stroke="#fa0" fill="#ffa"/>
  <circle cx="100" cy="100" r="75"
    filter="url(#f3)"
    stroke-width="3" stroke="#0a6" fill="#afc"/>
</svg>
図1

図2

図3

// 選択肢
図1
図2
図3

上から順番に見ていきましょう。

<feMorphology in="SourceAlpha" operator="dilate" radius="3" result="morph"/>

上記では、入力(in)が「SourceAlpha」(元の画像のアルファ値)で、出力(result)が「morph」(という名前)になっています。

「feMorphology」は、形態のフィルターです。属性「operator」が「dilate」なら拡張を行ないます。その際の「radius」(半径、範囲)は「3」になります。

<feColorMatrix in="morph" type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"

次に、上記では、入力(in)が「morph」(形態フィルターで作った画像)で、出力が「matrix」(という名前)になっています。

カラーマトリクスの値として、以下の行列を指定して、真っ白にしています。

// 行列
0 0 0 0 1
0 0 0 0 1
0 0 0 0 1
0 0 0 1 0
<feOffset in="blur" dx="5" dy="5" result="offset"/>

続いて、上記では、入力(in)が「morph」(形態フィルターで作った画像)で、出力が「offset」(という名前)になっています。

「feOffset」は、オフセットのフィルターです。「dx」「dy」で、X軸、Y軸の移動量を指定します。これで、入力画像を、「dx」「dy」分移動した画像が作成されます。


<feMerge>
  <feMergeNode in="offset"/>
  <feMergeNode in="mtrx"/>
  <feMergeNode in="SourceGraphic"/>
</feMerge>

最後に、「<feMerge>」で、「<feMergeNode>」の3つの画像を合成しています。

合成する画像は、入力(in)が「offset」(先ほど、オフセットフィルターで作った画像)、入力(in)が「mtrx」(先ほど、カラーマトリクスフィルターで作った画像)と、入力(in)が「SourceGraphic」(元の画像)になります。

この合成の順番は、「offset」が先で、次に「mtrx」、最後に「SourceGraphic」となります。つまり、アルファ値を膨張させて移動した画像を描画して、アルファ値を膨張させて白くした画像を描画して、元の画像を描画することになります。

そのため、作成される図は、図1となり、1番目の選択肢の「図1」が答えになります。

CodeIQ運営事務局より

柳井さん、ありがとうございました!
現在、柳井さんの最新問題が出題中です。
ぜひ挑戦してみてくださいね!

  • 3
  • このエントリーをはてなブックマークに追加

■関連記事

【謎解きプログラム】弾幕の軌跡を作ってみよう【描画】解答と解説... 【謎解きプログラム】弾幕の軌跡を作ってみよう【描画】 本問題は、表題のテーマで、プログラムにちなんだ謎を解くというものでした。 それでは以下、各問題とその解答を見ていきましょう。 問題のオープニング ある日、出社すると、あなたのPCのログイン画面に、謎の挑戦状が表示されていた。 「24時間...
数学の問題をプログラミングで解こう!「キャリー・オーバー」問題解説... 問題のおさらい 9606+91377 という足し算を筆算で行いましょう。下のようになります。 この計算では繰り上がりがあります。 例えば、一の位を足すと 6+7=13 です。このとき、十の位に 1 を繰り上げます。 十の位は、繰り上げた 1 を足して、1+0+7=8 と計算します。 同様に、...
【誕生日問題12月】『ジェット機をプレゼント』解答と解説... 【誕生日問題12月】ジェット機をプレゼント 本問題は、12月誕生日の人限定の、コーディング問題でした。 それでは以下、問題とその解答、解説を見ていきましょう。 問題 あなたは誕生日プレゼントとして、ジェット機をもらえることになりました。 もらえるジェット機は、組み立て式です。胴体、右翼、左...
【謎解きプログラム】エラーの起きるJSONはどれ?【JSON】解答と解説... 【謎解きプログラム】エラーの起きるJSONはどれ?【JSON】 本問題は、表題のテーマで、プログラムにちなんだ謎を解くというものでした。 それでは以下、各問題とその解答を見ていきましょう。 問題のオープニング ある日、出社すると、あなたのPCのログイン画面に、謎の挑戦状が表示されていた。 ...
【クリスマス問題】『サンタの持ち場を計算しよう』解答と解説... 【クリスマス問題】サンタの持ち場を計算しよう 本問題は、クリスマスプレゼントが当たる、コーディング問題でした。 それでは以下、問題とその解答、解説を見ていきましょう。 問題 あなたはサンタさんです。 サンタさんは、プレゼントを配るべき家を割り当てられます。 配る家は複数あり、1~15の整...
数学の問題をプログラミングで解こう!「スパイラル・ウォーク」問題解説... 問題のおさらい 自然数 w, h に対し、横と縦の長さがそれぞれ w, h となる格子状の道を考えます。 この左上の点からスタートして、同じ交差点を二度以上通らないように、らせんを描いて進みます。 最初は下方向にまっすぐ進み、これ以上前に進めなくなったところで左折し、再びまっすぐ進みます。 これ...

今週のPickUPレポート

新着記事

週間ランキング

CodeIQとは

CodeIQ(コードアイキュー)とは、自分の実力を知りたいITエンジニア向けの、実務スキル評価サービスです。

CodeIQご利用にあたって
関連サイト
codeiq

リクルートグループサイトへ