概要
CS50 week4 ps4 Filter (less comfortable)の課題に取り組んでいるのですが、フィルター加工の1つ、**「ぼかし」**にて、画像がぼかされているにも関わらずcheck50を通過しませんでした。
見た目上だと原因もわからず、私の行ったテストでは網羅性に欠けており原因を突き止めることが出来ませんでした。
途方に暮れそうになり、以下の該当エラーを検索すると同じような問題がstack overflowにありました。
■参考文献
CS50 blur function does not pass check50, even though image is being blurred
日本語での記事が少なかったため、上記記事を参考文献として、Qiitaに残します。
実際のエラー文言
:( blur correctly filters middle pixel
expected "127 140 149\n", not "145 160 169\n"
:( blur correctly filters pixel on edge
expected "80 95 105\n", not "90 106 116\n"
:) blur correctly filters pixel in corner
:( blur correctly filters 3x3 image
expected "70 85 95\n80 9...", not "70 85 95\n90 1..."
:( blur correctly filters 4x4 image
expected "70 85 95\n80 9...", not "70 85 95\n90 1..."
コーナーのピクセルを正しくフィルタリングするぼかしのみ成功し、その他は失敗しています。
原因
結論は、計算元と計算結果の配列を同じものにしていたことです。
今回課題のぼかし処理で使用したのは、隣接するピクセルを参照するボックスブラーという手法でした。
check50が通らなかった時の実装では、メモリ上にロードされた画像に対して直接ぼかしの処理を加えており、
それだと状況によっては既にぼかしたピクセルをボックスブラーの処理で参照してしまい、期待していた計算と差が出るピクセルがありました。
ぼかしを計算するために参照する画像とぼかしを施された画像の変数を分けることで、ぼかしを施す画像に対して正しいぼかし処理ができ、check50が通りました。
修正としては、最初に画像のコピー(今回はtemp変数)を作成し、ピクセルの値が変更されていないtemp画像内からピクセル値を取得してすべての計算を行いました。
// ぼかしを計算するために参照する画像temp変数を作成し、メモリを確保
RGBTRIPLE(*temp)[width] = malloc(height * width * sizeof(RGBTRIPLE));
// temp変数に対して、元の画像をコピー
memcpy(temp, image, height * width * sizeof(RGBTRIPLE));