JavaRush /Java Blog /Random-JA /ハーバード CS50: 第 4 週の課題 (講義 9 および 10)
Masha
レベル 41

ハーバード CS50: 第 4 週の課題 (講義 9 および 10)

Random-JA グループに公開済み
ハーバード CS50: 第 4 週の課題 (講義 9 および 10) - 1

仕事の準備

いつものように、まずターミナル ウィンドウを開いてコマンドを実行します。 update50 アプリケーションがすでに最新であることを確認します。開始する前に、これに従って cd ~ / workspace wget http://cdn.cs50.net/2015/fall/psets/4/pset4/pset4.zip このタスクの ZIP アーカイブをダウンロードしてください。ここでlsを実行すると、 ~/workspaceディレクトリにpset4.zipというファイルがあることがわかります。次のコマンドを使用してそれを抽出します。 ls コマンドを再度実行すると、別のディレクトリが表示されることがわかります。これで、以下に示すように zip ファイルを削除できます。 pset4ディレクトリ を開いてls を実行し、ディレクトリに次のファイルが含まれていることを確認してください。 unzip pset4.ziprm -f pset4.zip cd pset4bmp / jpg / questions.txt

フーダニットまたは「誰がこれをやった?」

デフォルトの Windows XP デスクトップ (https://en.wikipedia.org/wiki/Bliss_(image)) (丘と青空) を見たことがあるなら、BMP を見たことがあるでしょう。Web ページでは、GIF を見たことがあるでしょう。デジタル写真を見たことはありますか?それで、JPEGを見ることができてとてもうれしかったです。Mac でスクリーンショットを撮ったことがある人なら、おそらく PNG を見たことがあるでしょう。BMP、GIF、JPEG、PNG 形式についてインターネットで調べて、次の質問に答えてください。
  1. 各形式は何色をサポートしていますか?

  2. どの形式がアニメーションをサポートしていますか?

  3. 非可逆圧縮と可逆圧縮の違いは何ですか?

  4. 非可逆圧縮を使用する形式は次のうちどれですか?

英語を話せる人は、 MITの記事を参照することをお勧めします。これを勉強すれば (または、ディスクやファイル システムへのファイルの保存に関するインターネット上の他のリソースを見つければ)、次の質問に答えることができます。
  1. FAT ファイル システムでファイルが削除されると、技術的な観点からはどうなりますか?

  2. 削除されたファイルを(高い確率で)確実に復元できないようにするにはどうすればよいでしょうか?

そして今、第 4 週の最初のタスクにスムーズに流れていくストーリーに移ります。チューダー邸へようこそ!不動産の所有者であるジョン・ボディ氏は、よくわからないゲームの犠牲になり、突然私たちのもとを去りました。何が起こったのかを調べるには、whodunitを定義する必要があります。あなたにとって残念なことに (ただし、Boddy さんにとってはさらに残念ですが)、あなたが持っている唯一の証拠は 24 ビット BMP ファイルquote.bmpです。以下にその内容を示します。ボディ氏は、最後の瞬間にそれを作成し、コンピュータに保存することができました。このファイルには、赤いノイズの中に隠されたフーダユニットの画像が含まれています。ここで、あなたは本物の技術専門家のようにソリューションに取り組む必要があります。 ハーバード CS50: 第 4 週の課題 (講義 9 および 10) - 2しかしその前に、いくつかの情報を。おそらく、画像をピクセル (つまりドット) のグリッドとして考えるのが最も簡単で、それぞれが特定の色になる可能性があります。白黒画像内の点の色を設定するには、1 ビットが必要です。下の図に示すように、0 は黒を表し、1 は白を表すことができます。 ハーバード CS50: 第 4 週の課題 (講義 9 および 10) - 3したがって、この方法で表現された画像は単なるビットのマップ (英語または俗語で言うところのビットマップまたはビットマップ) です。白黒ではすべてが可能な限りシンプルですが、カラー画像を取得するには、ピクセルあたりのビット数を増やす必要があります。「8 ビット カラー」をサポートするファイル形式 (GIF など) は、1 ピクセルあたり 8 ビットを使用します。「24 ビット カラー」をサポートするファイル形式 (BMP、JPG、PNG など) は、ピクセルあたり 24 ビットを使用します (BMP は実際には 1、4、8、16、24、および 32 ビット カラーをサポートします)。 。Boddy 氏が使用する 24 ビット BMP では、赤の量を示すのに 8 ビットが必要で、緑の量も同じ量で、各ピクセルの青の量を示すのにさらに 8 ビット必要です。RGBカラーについて聞いたことがあるなら、これがそれです (R= 赤、G= 緑、B= 青)。BMP のあるピクセルの R、G、B 値が、たとえば 16 進数で 0xff、0x00、および 0x00 である場合、0xff (10 進数で 255 とも呼ばれる) は「赤が多く含まれていること」を意味するため、そのピクセルは純粋な赤になります。このとき、0x00 と 0x00 はそれぞれ「緑なし」と「青もゼロ」を意味します。Mr. Boddy の BMP 画像が私たちにどのように赤く見えるかを考えると、赤の「コンパートメント」が赤と青の「コンパートメント」よりも明らかに大きい値であることが直感的にわかります。ただし、すべてのピクセルが赤であるわけではなく、明らかに異なる色のピクセルもあります。ちなみに、HTMLやCSS(Webページを作成する際に使用されるマークアップ言語とそれを補助するスタイルシート)でも、カラーモデルは同様に配置されています。興味があれば、リンクをチェックしてください: https://ru.wikipedia.org/wiki/Colors_HTML詳細については。ここで、この問題にさらに技術的に取り組んでみましょう。ファイルとは、単に何らかの順序で配置されたビットのシーケンスであることを思い出してください。24 ビット BMP ファイルは一連のビットであり、その 24 ビットごとに (ほぼ) ピクセルの色が決まります。BMP ファイルには、カラー データに加えて、画像の幅と高さに関する情報であるメタデータも含まれています。このメタデータは、一般に「ヘッダー」と呼ばれる 2 つのデータ構造の形式でファイルの先頭に保存されます (C ヘッダー ファイルと混同しないでください)。これらのヘッダーの最初は BITMAPFILEHEADER で、長さは 14 バイト (または 14*8 ビット) です。2 番目のヘッダーは BITMAPINFOHEADER (長さ 40 バイト) です。これらのヘッダーの後にビットマップが続きます。バイトの配列で、その 3 つの要素がピクセルの色を表します (BMP では 1、4、16 ビットですが、24 ビットや 32 ビットではありません)。BITMAPINFOHEADER の直後に追加のヘッダーがあります。これは、と呼ばれます。 RGBQUAD 配列、パレット内の各色の「強度値」を定義します)。ただし、BMP はこれらのトリプレットを逆に格納し (BGR のように言えます)、青に 8 ビット、緑に 8 ビット、赤に 8 ビットを使用します。ちなみに、BMP によっては、BMP ファイルの末尾にある画像の先頭行からビットマップ全体を逆方向に保存するものもあります。私たちのタスクでは、ここで説明されているように VMR を保存しました。最初に画像の一番上の行、次に一番下の行を保存しました。言い換えれば、黒を赤に置き換えることで、1 ビットの絵文字を 24 ビットの絵文字に変えました。24 ビット BMP はこのビットマップを保存します。0000ff は赤を表し、ffffff は白を表します。0000ff のすべてのインスタンスを赤色で強調表示しました。 ハーバード CS50: 第 4 週の課題 (講義 9 および 10) - 4これらのビットを左から右、上から下に表示したため、モニターから少し離れると、これらの文字の中に赤いスマイルマークが表示されることがわかります。16 進数体系の数字は 4 ビットを表すことを思い出してください。したがって、16 進数の ffffff は、実際には 2 進数の 1111111111111111111111111 を意味します。ここで、速度を落として、0000ff が 24 ビット BMP ファイルの赤いピクセルを表す理由を確実に理解するまで、これ以上先に進まないでください。CS50 IDE ウィンドウで、 pset4フォルダーを展開し (たとえば、小さな三角形をクリックして) 、その中にある - bmp を開きます。このフォルダー内にsmiley.bmpがあり、ファイルをダブルクリックすると、そこに小さな 8x8 ピクセルのスマイリーが表示されます。ドロップダウン メニューで、画像のスケールを変更します (たとえば 100% から 400%)。これにより、絵文字がより大きく表示されますが、同時により「ぼやけた」バージョンが表示されます。実際には、この同じ画像を拡大してもぼやけてはいけません。それは、CS50 IDE が画像を滑らかにする (視覚的にエッジをぼかす) ことによって (CIA シリーズのスタイルで) ユーザーに恩恵を与えようとしているだけです。スマイリーをスムージングせずに拡大すると、次のようになります。 ハーバード CS50: 第 4 週の課題 (講義 9 および 10) - 5ピクセルが大きな正方形に変わりました。続けましょう。ターミナルで~/workspace/pset4/bmpに移動します。これを行う方法はすでに覚えていると思います。smiley.bmpに割り当てられたバイトを調べてみましょう。これは、コマンド ライン 16 進エディタ、xxdプログラムを使用して行うことができます。これを実行するには、次のコマンドを実行します。 xxd -c 24 -g 3 -s 54 smiley.bmp 以下の内容が表示されるはずです。0000ff のすべてのインスタンスを再び赤色で強調表示しました。 ハーバード CS50: 第 4 週の課題 (講義 9 および 10) - 6左端の列の画像には、ファイル内のアドレスが表示されます。これは、ファイルの最初のバイトからのオフセットに相当します。それらはすべて 16 進数体系で与えられます。16 進数の 00000036 を 10 進数に変換すると、54 が得られます。つまり、 smiley.bmpの 54 番目のバイトを見ていることになります。24 ビット BMP ファイルでは、最初の 14 + 40 = 54 バイトがメタデータで埋められることを思い出してください。したがって、メタデータを確認したい場合は、次のコマンドを実行します。 smiley.bmpにASCII 文字が含まれているxxd -c 24 -g 3 smiley.bmp 場合、それらの文字はすべてのドットではなく、xxd の右端の列に表示されます。したがって、スマイリーは 8x8 ピクセルのサイズ (解像度) を持つ 24 ビット BMP (各ピクセルは 24 ÷ 8 = 3 バイトで表されます) です。したがって、各ライン (または「スキャンライン」と呼ばれる) は、(8 ピクセル) x (ピクセルあたり 3 バイト) = 24 バイトを占めます。この数値は 4 の倍数であり、行内のバイト数が 4 の倍数でない場合、BMP ファイルの保存方法が若干異なるため、これは重要です。したがって、フォルダー内の別の 24 ビット BMP ファイルである small.bmp には、緑色の 3x3 ピクセル ボックスが表示されます。画像ビューアで開くと、以下の画像に似ていますが、サイズが小さいだけであることがわかります。 したがって、 small.bmpの各行は(3 ピクセル) × (ピクセルあたり 3 バイト) = 9 バイトを占めますが、これは 4 の倍数ではありません。行の長さを 4 の倍数にするには、追加のゼロが埋め込まれます。 0 から 3 バイトの間で、各行を 24 ビット BMP 形式で埋めます (その理由がわかりますか?)。small.bmpの場合、(3 ピクセル) x (ピクセルあたり 3 バイト) + (パディングの 3 バイト) = 12 バイトであるため、3 バイトのゼロが必要です。これは実際には 4 の倍数です。このパディングを「確認」するには、次のようにします。以下をせよ。 -cにはsmiley.bmpとは 異なる値を使用するので、今回は xxd は 4 列のみを出力することに注意してください (緑色の四角形に 3 列、パディングに 1 列)。わかりやすくするために、00ff00 のすべてのインスタンスを緑色で強調表示しました。 対照的に、 large.bmpファイルには xxd を使用してみましょう。small.bmpとまったく同じように見えます。ハーバード CS50: 第 4 週の課題 (講義 9 および 10) - 7xxd -c 12 -g 3 -s 54 small.bmpハーバード CS50: 第 4 週の課題 (講義 9 および 10) - 8、解像度のみが 12x12 ピクセル、つまり 4 倍大きくなります。以下のコマンドを実行します。転送を避けるためにウィンドウを拡大する必要がある場合があります。 xxd -c 36 -g 3 -s 54 large.bmp 次のような内容が表示されます。 ハーバード CS50: 第 4 週の課題 (講義 9 および 10) - 9この BMP には余談がないことに注意してください。結局のところ、(12 ピクセル) × (ピクセルあたり 3 バイト) = 36 バイトとなり、これは 4 の倍数になります。 xxd 16 進エディターは、BMP ファイル内のバイトを表示しました。それらをプログラムで取得するにはどうすればよいでしょうか? copy.cには、BMP のコピーを部分的に作成することを唯一の目的とするプログラムが 1 つあります。はい、これにはcpを使用できます。しかし、cpはボディさんを助けることはできません。copy.c がこれを行うことを期待しましょう。それでは、ここで ls を./copy smiley.bmp copy.bmp(適切なフラグを指定して) 実行すると、 smiley.bmpcopy.bmpが実際に同じサイズであることがわかります。これが本当に本当かどうかもう一度確認してみませんか? このコマンドで画面に何も表示されない場合は、ファイルが実際に同一であることを意味します (重要: Photoshop などの一部のプログラムでは、一部の VMP の末尾に末尾のゼロが含まれています。私たちのバージョンのコピーではそれらが破棄されるため、使用しないでください)テスト用にダウンロードまたは作成した他の BMP をコピーする場合、コピーが元の BMP よりも数バイト小さくなる場合がありますのでご注意ください)。Ristretto の画像ビューアで両方のファイルを開き (ダブルクリック)、これを視覚的に確認できます。しかし、diff はこの比較をバイトごとに行うため、彼女の視野はあなたの視野よりも鋭いのです。このコピーはどのようにして作成されたのでしょうか? copy.c がbmp.hに関連していることがわかりました。確認しましょう: bmp.hを開きます。diff smiley.bmp copy.bmp。そこには、Microsoft 独自の実装から適応された、すでに述べたヘッダーの実際の定義が表示されます。さらに、このファイルは BYTE、DWORD、LONG、および WORD データ型を定義します。これらは、Win32 (つまり Windows) プログラミングの世界で一般的に見られるデータ型です。これらは基本的に、(うまくいけば) すでによく知っているプリミティブのエイリアスであることに注意してください。BITMAPFILEHEADER と BITMAPINFOHEADER がこれらの型を使用していたことがわかりました。このファイルは、RGBTRIPLE という構造体も定義します。これは、青、緑、赤の 3 バイトを「カプセル化」します (これは、ディスク上で RGB トリプレットを探す順序です)。これらの構造体はどのように役立つのでしょうか? 要約すると、ファイルは単にディスク上の一連のバイト (最終的にはビット) です。ただし、これらのバイトは通常、最初のいくつかが何かを表し、次のいくつかが別のものを表す、というように順序付けされています。ファイルの「形式」が存在するのは、どのバイトが何を意味するかを定義する標準またはルールがあるからです。これで、ファイルを 1 つの大きなバイト配列としてディスクから RAM に読み取ることができます。そして、位置 [i] のバイトは 1 つのことを表し、位置 [j] のバイトは別の何かを表していることを思い出してください。しかし、これらのバイトの一部に名前を付けて、メモリからより簡単に取得できるようにしてはどうでしょうか? これはまさに bmp.h の構造が役に立ちます。ファイルを 1 つの長いバイトのシーケンスとして考えるのではなく、ファイルをより理解しやすいブロック、つまり一連の構造に分割すると考えます。smiley.bmpの解像度は 8x8 ピクセルなので、ディスク上で 14 + 40 + (8 × 8) × 3 = 246 バイトを占有することを思い出してください(これは ls コマンドを使用して確認できます)。Microsoft によると、ディスク上では次のようになります。 ハーバード CS50: 第 4 週の課題 (講義 9 および 10) - 10構造体のメンバーに関しては順序が重要であることがわかります。rgbtBlue は RGBTRIPLE で最初に定義されているため、バイト 57 は rgbtBlue (たとえば、rgbtRed ではありません) です。ちなみに、packed 属性を使用すると、clang がメンバーを (各メンバーの最初のバイトのアドレスが 4 の倍数になるように) 「ワード整列」しようとしないため、結果的にホールが発生することはありません。私たちの構造はディスク上にまったく存在しません。次へ移りましょう。bmp.h のコメントに従って、BITMAPFILEHEADER と BITMAPINFOHEADER に一致する URL を見つけます。注意、素晴らしい瞬間です。MSDN (Microsoft Developer Network) の使用を開始しています。copy.c をさらにスクロールする代わりに、いくつかの質問に答えて、コードがどのように機能するかを理解してください。いつものように、man コマンドはあなたの本当の友達であり、今では MSDN でもあります。答えがわからない場合は、グーグルで調べて考えてください。https://reference.cs50.net/ で stdio.h ファイルを参照することもできます。
  1. main にブレークポイントを設定します (主行番号のあるルーラーの左側をクリックします)。

  2. ターミナルタブで~/workspace/pset4/bmpに移動し、make を使用して copy.c をコピー プログラムにコンパイルします。

  3. debug50 copy smiley.bmp copy.bmpを実行すると、右側にデバッガー パネルが開きます。

  4. 右側のパネルを使用してプログラムを段階的に進めていきます。bfbiに注意してください。~/workspace/pset4/questions.txtで、次の質問に答えます。

  • stdint.hとは何ですか?

  • プログラム内でuint8_tuint32_tint32_t 、およびuint16_tを使用する意味は何ですか?

  • BYTEDWORDLONG、およびWORD にはそれぞれ何バイトが含まれますか(32 ビット アーキテクチャを想定)。

  • BMP ファイルの最初の 2 バイトは何 (ASCII、10 進数、または 16 進数) にすべきですか? (ファイル形式を (高い確率で) 識別するために使用される先頭のバイトは、多くの場合「マジック ナンバー」と呼ばれます)。
  • bfSize と biSize の違いは何ですか?

  • 負の biHeight は何を意味しますか?

  • BITMAPINFOHEADER のどのフィールドが BMP の色深度 (つまり、ピクセルあたりのビット数) を定義しますか?

  • fopen 関数が copy.c 37 で NULL を返すのはなぜですか?

  • コード内の fread の 3 番目の引数が 1 に等しいのはなぜですか?

  • bi.biWidth が 3 の場合、copy.c 70 のどの値がパディングを定義しますか?

  • fseekは何をするのですか?

  • SEEK_CURとは何ですか?

ボディさんの話に戻ります。エクササイズ:

Boddy 氏の描画を示すwhodunit.cというファイルに、whodunitというプログラムを作成します。うーん、何ですか?copy と同様に、プログラムはコマンド ライン引数を 2 つだけ取る必要があり、以下に示すようにプログラムを実行すると、結果は verdict.bmp に保存され、Boddy 氏の描画にノイズは発生しません。 以下のコマンドを実行して、この謎を解き始めることをお勧めします。 ボディ氏を助けるために何行のコードを書く必要があるかに驚かれるかもしれません。smiley.bmpには不必要な要素は何も隠されていないので、このファイルで自由にプログラムをテストしてください。これは小さいので、開発中にプログラムの出力と xxd の出力を比較できます (あるいは、 smiley.bmpに何かが隠されているのかもしれません。実際には違います)。ところで、この問題はさまざまな方法で解決できます。ボディ氏の絵を特定できれば、彼は安らかに眠るでしょう。Whodunit は複数の方法で実装できるため、 check50で実装の正確さをチェックすることはできません。楽しみが台無しになるかもしれませんが、アシスタントの解決策もフーダニット問題には利用できません。最後に、ファイル~/workspace/pset4/questions.txtで、次の質問に答えます。 ./whodunit clue.bmp verdict.bcp copy.c whodunit.cWhodunit? //ктоэтосделал?

サイズ変更

さて、次のテストです!size.c にsizeというプログラムを書いてみましょう。非圧縮 24 ビット BMP 画像のサイズを n ステップで変更します。アプリケーションは、正確に 3 つのコマンド ライン引数を受け入れる必要があります。最初の (n) は 100 以下の整数、2 番目は変更されるファイルの名前、3 番目は変更されたファイルの保存されたバージョンの名前です。ファイル。 Usage: ./resize n infile outfile このようなプログラムを使用すると、以下に示すように、small.bmp のサイズを 4 倍に変更する (つまり、幅と高さの両方を 4 倍する) ことで、small.bmp からlarge.bmp を作成できます。 簡単にするために、 copy.c を./resize 4 small.bmp large.bmp 再度コピーし、そのコピーにsize.c という名前を付けることでタスクを開始できます。しかし、まず最初に、 BMP サイズを変更することは何を意味するのか (infile サイズの n 倍は 232 - 1 を超えないと仮定できます) という質問に自問して答えてください。BITMAPFILEHEADER および BITMAPINFOHEADER のどのフィールドを変更する必要があるかを判断します。走査線フィールドを追加する必要があるか削除する必要があるかを検討してください。そして、はい、n の 0 から 1 までのすべての値を考慮するように求めているわけではないことに感謝してください。(ただし、興味があれば、これはハッカーの本の問題です ;))。ただし、n = 1 の場合、プログラムは正しく動作し、出力ファイルoutfile は元の infile と同じサイズになると仮定します。check50を使用してプログラムをチェックしますか? 次のコマンドを入力します。 check50 2015.fall.pset4.resize bmp.hsize.c CS50 アシスタントが作成したアプリケーション実装で遊んでみませんか? 次のコマンドを実行します ~cs50/pset4/resize 。 たとえば、 large.bmpヘッダー(xxd で許可されているものよりも使いやすい形式) を表示したい場合は、次のコマンドを実行する必要があります ~cs50/pset4/peek large.bmp 。ヘッダーは CS50 アシスタント ファイルのヘッダーと一致します。 ~/workspace/pset4/bmpディレクトリ内でコマンドを実行できます(各コマンドが何を行うか考えてください)。 malloc を使用した場合は、メモリ リークを防ぐために必ず freeを使用してください。 valgrindを使用してリークをチェックして みてください。 ./resize 4 small.bmp student.bmp
~cs50/pset4/resize 4 small.bmp staff.bmp
~cs50/pset4/peek student.bmp staff.bmp

どうやって決めるの?

  • 拡大する必要があるファイルを開き、拡大された画像を記録する新しいファイルを作成して開きます。

  • 出力ファイルのヘッダー情報を更新します。画像は BMP 形式であり、そのサイズを変更しているため、新しいファイルのヘッダーを新しいサイズで書き込む必要があります。何が変わるのでしょうか?ファイル サイズと画像サイズ (幅と高さ)。

ハーバード CS50: 第 4 週の課題 (講義 9 および 10) - 11 ヘッダーの説明を見ると、 biSizeImage変数が見つかります。画像の合計サイズをバイト単位で示します。biWidth 画像の幅から配置を差し引いた値、 biHeightは高さです。これらの変数は、BITMAPFILEHEADER 構造体および BITMAPINFOHEADER 構造体にあります。 bmp.hファイルを開くとそれらを見つけることができます。 ハーバード CS50: 第 4 週の課題 (講義 9 および 10) - 12BITMAPINFOHEADER 構造体の説明には、変数のリストが含まれています。出力ファイルのタイトルを書き込むには、高さと幅の値を変更する必要があります。ただし、後で元のファイルの元の高さと幅が必要になる可能性もあります。したがって、両方保持しておいた方が良いでしょう。出力ファイルのヘッダーに誤ったデータを書き込まないように、変数名には注意してください。
  • 送信ファイルを 1 行ずつ、ピクセルごとに読み取ります。これを行うには、再びファイル I/O ライブラリと fread 関数に目を向けます。これは、読み取られるバイト、読み取る単一要素のサイズ、そのような要素の数、および読み取り元のファイルを含む構造体へのポインタを受け取ります。

    ハーバード CS50: 第 4 週の課題 (講義 9 および 10) - 13
  • 指定されたスケールに従って各行を水平方向に増加させ、結果を出力ファイルに書き込みます。

    ハーバード CS50: 第 4 週の課題 (講義 9 および 10) - 14

    ファイルはどのように書き込むのでしょうか? ファイルに書き込まれるデータが配置されている構造体へのインジケーター、要素のサイズ、要素の数、出力ファイルへのポインターを渡す関数 fwrite があります。ループを整理するには、すでに使い慣れたforループを使用できます。

    ハーバード CS50: 第 4 週の課題 (講義 9 および 10) - 15
  • 差を埋める!ライン内のピクセル数が 4 の倍数でない場合は、「アライメント」 (ゼロ バイト) を追加する必要があります。アライメントサイズを計算するための式が必要になります。出力ファイルに null バイトを書き込むには、 fputc 関数を使用して、書き込む文字と出力ファイルへのポインターを渡します。

    ハーバード CS50: 第 4 週の課題 (講義 9 および 10) - 16

    文字列を水平に引き伸ばして出力ファイルに配置を追加したので、配置を飛び越える必要があるため、出力ファイル内の現在の位置を移動する必要があります。

    ハーバード CS50: 第 4 週の課題 (講義 9 および 10) - 17
  • 縦方向のサイズを大きくします。より複雑ですが、copy.cのサンプル コードを使用できます (copy.c は出力ファイルを開き、出力ファイルにヘッダーを書き込み、ソース ファイルから画像を 1 行ずつ、ピクセルごとに読み取り、それらを書き込みます)出力ファイルにコピーされます)。これに基づいて、最初にできることは、次のコマンドを実行することです: cp copy.csize.c

    画像を垂直方向に引き伸ばすということは、各行を数回コピーすることを意味します。これを行うには、いくつかの異なる方法があります。たとえば、書き換えを使用して、1 ラインのすべてのピクセルをメモリに保存し、ループで必要な回数だけこのラインを出力ファイルに書き込みます。もう 1 つの方法は再コピーです。送信ファイルから 1 行を読み取り、それを出力ファイルに書き込み、位置合わせした後、fseek関数を送信ファイルの行の先頭に戻し、すべてを数回繰り返します。

    ハーバード CS50: 第 4 週の課題 (講義 9 および 10) - 18
  • 回復する

    第 4 週の問題用紙を見越して、私はここ数日、デジタル カメラで 1 GB のコンパクトフラッシュ (CF) メモリ カードに JPEG 形式で保存された写真を眺めていました。私が実際にここ数日間 Facebook に費やしていたとは言わないでください。残念ながら、私のコンピュータースキルにはまだまだ不十分な点が多く、知らないうちに誤ってすべての写真を削除してしまいました。幸いなことに、コンピュータの世界では、通常、「削除」は「強制終了」と同じではありません。私のコンピュータはメモリカードが空になったと主張しますが、それが嘘であることはわかっています。 課題:これらの写真を復元するプログラムを ~/workspace/pset4/jpg/recover.cに作成します。うーん。さて、もう一つ説明があります。JPEG 形式は BMP よりも複雑ですが、JPEG には他のファイル形式と区別するのに役立つバイト パターンである「署名」があります。ほとんどの JPEG ファイルは、次の 3 バイトで始まります。 0xff 0xd8 0xff 最初のバイトから 3 番目のバイトまで、左から右へ。4 番目のバイトは、0xe0、0xe1、0xe2、0xe3、0xe4、0xe5、0xe6、0xe7、0xe8、0xe8、0xe9、0xea、0xeb、0xec、0xed、0xee、0xef の組み合わせのいずれかになる可能性が高くなります。つまり、JPEG ファイルの 4 バイト目の最初の 4 ビットは 1110 です。写真が保存されているドライブ (メモリ カードなど) でこれらのパターンのいずれかを見つけた場合、これが JPEG ファイルの始まりである可能性があります。もちろん、どのディスクでこの問題が発生するかは全くの偶然である可能性があり、データ回復は正確な科学とは言えません。

    決め方

    1. メモリカードの内容が含まれるファイルを開きます。

    2. JPEG ファイルの先頭を見つけます。このカード内のファイルはすべて JPEG 形式の画像です。

    JPEG マーカーについてはすでにご存知でしょう。 ハーバード CS50: 第 4 週の課題 (講義 9 および 10) - 19各 JPEG ファイルが 1 つのブロックとしてメモリに保存され、ファイル自体が次々に続くことを知っておくことは重要です (そして良いことです)。概略的なメモリマップを描いてみましょう。各長方形は 512 バイト長のブロックです。灰色の四角形は JPEG ファイルが存在しない領域で、アスタリスクは JPEG ファイルの始まりを示します。ファイル間に灰色のブロックはないと考えています。 ハーバード CS50: 第 4 週の課題 (講義 9 および 10) - 20このデータ (512 バイト) を読み取って、その先頭と JPEG ヘッダーを比較するにはどうすればよいでしょうか? すでによく知られているfread関数を使用できます。この関数は、読み取ったバイトが書き込まれるデータ構造へのポインタ、読み取られる要素のサイズ、そのような要素の数、およびデータを読み取るファイルへのポインタ。 ハーバード CS50: 第 4 週の課題 (講義 9 および 10) - 21512 バイトを読み取り、バッファに保存したいと考えています。これは &data ポインタとなり、inptr ポインタはメモリ カードの内容が含まれる開いているファイルを指します。それでは、保存するファイルの構造に戻りましょう。
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION