JavaRush /Java Blog /Random-KO /Harvard CS50: 4주차 과제(강의 9 및 10)
Masha
레벨 41

Harvard CS50: 4주차 과제(강의 9 및 10)

Random-KO 그룹에 게시되었습니다
Harvard 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

whodunit 또는 "누가 그랬어?"

기본 Windows XP 데스크톱(https://en.wikipedia.org/wiki/Bliss_(image))(언덕과 푸른 하늘)을 본 적이 있다면 BMP를 본 것입니다. 웹페이지에서 GIF를 본 적이 있을 것입니다. 디지털 사진을 보셨나요? 그래서 우리는 JPEG를 보는 기쁨을 누렸습니다. Mac에서 스크린샷을 찍어본 적이 있다면 PNG를 본 적이 있을 것입니다. 인터넷에서 BMP, GIF, JPEG, PNG 형식에 대해 읽고 다음 질문에 답하세요.
  1. 각 형식은 몇 가지 색상을 지원합니까?

  2. 애니메이션을 지원하는 형식은 무엇입니까?

  3. 손실 압축과 무손실 압축의 차이점은 무엇입니까?

  4. 다음 중 손실 압축을 사용하는 형식은 무엇입니까?

영어를 구사하는 분들은 MIT 의 기사를 참고하시기 바랍니다 . 이를 연구하거나 인터넷에서 디스크 및 파일 시스템에 파일을 저장하는 방법에 대한 다른 리소스를 찾으면 다음 질문에 답할 수 있습니다.
  1. FAT 파일 시스템에서 파일이 삭제되면 기술적인 관점에서 어떤 일이 발생합니까?

  2. 삭제된 파일을 복구할 수 없도록 (높은 확률로) 어떻게 해야 합니까?

그리고 이제 넷째 주의 첫 번째 작업으로 원활하게 흘러가는 우리의 이야기입니다. 튜더 맨션에 오신 것을 환영합니다! 부동산 소유자인 Mr. John Boddy가 갑자기 우리를 떠나 모호한 게임의 희생양이 되었습니다. 무슨 일이 일어났는지 알아내려면 whodunit 을 정의해야 합니다 . 불행하게도 (Boddy 씨에게는 더욱 불행한 일이지만) 당신이 가지고 있는 유일한 증거는 24비트 BMP 파일 explainue.bmp 뿐입니다 . 아래에서 보는 것이 그 내용입니다. Boddy 씨는 마지막 순간에 그것을 만들어 자신의 컴퓨터에 저장했습니다. 파일에는 레드 노이즈 사이에 숨겨진 추리 이미지가 포함되어 있습니다 . 이제 실제 기술 전문가처럼 솔루션을 개발해야 합니다. Harvard CS50: 4주차 과제(강의 9 및 10) - 2하지만 먼저 몇 가지 정보를 알아보세요. 이미지를 픽셀(즉, 점) 격자로 생각하는 것이 가장 쉬울 것입니다. 각 픽셀은 특정 색상일 수 있습니다. 흑백 이미지에서 점의 색상을 설정하려면 1비트가 필요합니다. 아래 그림과 같이 0은 검정색을 나타내고 1은 흰색을 나타낼 수 있습니다. Harvard CS50: 4주차 과제(강의 9 및 10) - 3따라서 이러한 방식으로 표현된 이미지는 단순히 비트 맵(영어 또는 속어로 말하는 비트맵 또는 비트맵)입니다. 흑백을 사용하면 모든 것이 가능한 한 간단하지만 컬러 이미지를 얻으려면 픽셀당 더 많은 비트가 필요합니다. "8비트 색상"을 지원하는 파일 형식(예: GIF)은 픽셀당 8비트를 사용합니다. "24비트 색상"을 지원하는 파일 형식(예: BMP, JPG, PNG)은 픽셀당 24비트를 사용합니다(BMP는 실제로 1, 4, 8, 16, 24 및 32비트 색상을 지원합니다). . Mr. Boddy가 사용하는 24비트 BMP에서는 빨간색의 양을 나타내는 데 8비트가 필요하고 녹색의 양도 동일하며 각 픽셀의 파란색 양을 나타내는 데 다시 8비트가 필요합니다. RGB 색상 에 대해 들어본 적이 있다면 바로 이것이다(R=빨간색, G=녹색, B=파란색). BMP에서 일부 픽셀의 R, G 및 B 값이 16진수로 0xff, 0x00 및 0x00인 경우 0xff(10진수로 255라고도 함)는 "많은 빨간색"을 의미하므로 픽셀은 순수한 빨간색이 됩니다. " 당시 0x00과 0x00은 각각 "녹색 없음"과 "파란색도 0"을 의미합니다. Mr. Boddy의 BMP 이미지가 우리에게 얼마나 빨간색으로 나타나는지를 고려하면 빨간색 "구획"이 빨간색과 파란색 "구획"보다 분명히 더 큰 값을 갖는다는 것을 직관적으로 알 수 있습니다. 그러나 모든 픽셀이 빨간색인 것은 아니며 일부 픽셀은 분명히 다른 색상입니다. 그런데 HTML과 CSS(웹 페이지를 만드는 데 사용되는 마크업 언어 및 스타일 시트)에서 색상 모델은 동일한 방식으로 배열됩니다. 관심이 있으시면 https://ru.wikipedia.org/wiki/Colors_HTML 링크를 확인하세요.상세 사항은. 이제 좀 더 기술적으로 문제에 접근해 보겠습니다. 파일은 단순히 어떤 순서로 배열된 일련의 비트라는 점을 기억하세요. 24비트 BMP 파일은 일련의 비트로, 각 24비트가 (거의) 어떤 픽셀의 색상을 결정합니다. BMP 파일에는 색상 데이터 외에도 이미지의 너비와 높이에 대한 정보인 메타데이터도 포함되어 있습니다. 이 메타데이터는 일반적으로 "헤더"라고 불리는 두 가지 데이터 구조 형태로 파일 시작 부분에 저장됩니다(C 헤더 파일과 혼동하지 마세요). 이들 헤더 중 첫 번째는 BITMAPFILEHEADER이며 길이가 14바이트(또는 14*8비트)입니다. 두 번째 헤더는 BITMAPINFOHEADER(40바이트 길이)입니다. 이러한 헤더 뒤에는 비트맵이 옵니다. 바이트 배열은 픽셀의 색상(BMP에서는 1, 4, 16비트이지만 24 또는 32는 아님)을 나타내는 세 개의 비트로 BITMAPINFOHEADER 바로 뒤에 추가 헤더가 있습니다. 이를 호출합니다. 팔레트의 각 색상에 대한 "강도 값"을 정의하는 RGBQUAD 배열) 그러나 BMP는 이러한 삼중항을 역방향(BGR처럼 말할 수 있음)으로 저장합니다. 파란색은 8비트, 녹색은 8비트, 빨간색은 8비트입니다. 그런데 일부 BMP는 BMP 파일 끝에 있는 이미지의 맨 윗줄부터 시작하여 전체 비트맵을 거꾸로 저장하기도 합니다. 우리 작업에서는 여기에 설명된 대로 VMR을 저장했습니다. 먼저 이미지의 맨 위 행, 그 다음 맨 아래 행을 저장했습니다. 즉, 1비트 이모지를 검정색을 빨간색으로 대체하여 24비트 이모지를 만들었습니다. 24비트 BMP는 이 비트맵을 저장합니다. 여기서 0000ff는 빨간색을 나타내고 ffffff는 흰색을 나타냅니다. 0000ff의 모든 인스턴스를 빨간색으로 강조 표시했습니다. Harvard CS50: 4주차 과제(강의 9 및 10) - 4이 비트를 왼쪽에서 오른쪽, 위에서 아래로 표시했기 때문에 모니터에서 조금 멀어지면 이 글자에 있는 빨간색 웃는 얼굴을 볼 수 있습니다. 16진수 체계의 숫자는 4비트를 나타냅니다. 따라서 16진수로 된 ffffff는 실제로 이진수로 1111111111111111111111111을 의미합니다. 이제 속도를 늦추고 0000ff가 24비트 BMP 파일에서 빨간색 픽셀을 나타내는 이유를 확실히 이해할 때까지 더 이상 진행하지 마세요. CS50 IDE 창에서 pset4 폴더를 확장(예: 작은 삼각형 클릭) 하고 해당 폴더에서 - bmp 를 확장합니다 . 이 폴더에는 smiley.bmp 가 있으며 파일을 두 번 클릭하면 작은 8x8 픽셀 스마일리를 찾을 수 있습니다. 드롭다운 메뉴에서 이미지 배율을 100%에서 400%로 변경하면 더 크지만 동시에 더 "흐릿한" 버전의 이모티콘을 볼 수 있습니다. 실제로는 동일한 이미지를 확대해도 흐려져서는 안 됩니다. CS50 IDE는 그림을 부드럽게(가장자리를 시각적으로 흐리게 처리)하여(CIA 시리즈 스타일로) 사용자에게 유리하게 작용하려고 합니다. 스무딩 없이 확대하면 스마일리 모양은 다음과 같습니다. Harvard CS50: 4주차 과제(강의 9 및 10) - 5픽셀이 큰 사각형으로 바뀌었습니다. 계속합시다. 터미널에서 ~/workspace/pset4/bmp 로 이동합니다 . 이 작업을 수행하는 방법을 이미 기억하고 있다고 생각합니다. smiley.bmp 에 할당된 바이트를 살펴보겠습니다 . 이는 명령줄 16진수 편집기인 xxd 프로그램을 사용하여 수행할 수 있습니다 . 이를 실행하려면 다음 명령을 실행하십시오. xxd -c 24 -g 3 -s 54 smiley.bmp 아래에 표시된 내용이 표시되어야 합니다. 0000ff의 모든 인스턴스를 빨간색으로 다시 강조 표시했습니다. Harvard 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의 가장 오른쪽 열에 해당 문자가 표시됩니다. 따라서 Smiley는 크기(해상도)가 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으로 채워집니다. 0에서 3바이트 사이의 각 줄을 24비트 BMP 형식으로 채웁니다(이유가 무엇인지 추측할 수 있습니까?). small.bmp 의 경우 (3픽셀) x (픽셀당 3바이트) + (3바이트 패딩) = 12바이트이므로 실제로는 4의 배수이므로 3바이트의 0이 필요합니다. 이 패딩을 "확인"하려면, 다음을 수행하십시오. -c 에는 smiley.bmp 와 다른 값을 사용하므로 xxd는 이번에는 4개의 열만 출력합니다(녹색 사각형에 3개, 패딩에 1개). 명확성을 위해 00ff00의 모든 인스턴스를 녹색으로 강조 표시했습니다. 대조적으로, Large.bmp 파일 에는 xxd를 사용하겠습니다 . small.bmp 와 정확히 동일해 보입니다.Harvard CS50: 4주차 과제(강의 9 및 10) - 7xxd -c 12 -g 3 -s 54 small.bmpHarvard CS50: 4주차 과제(강의 9 및 10) - 8, 해상도만 12x12 픽셀, 즉 4배 더 큽니다. 아래 명령을 실행하세요. 전송을 방지하려면 창을 확장해야 할 수도 있습니다. xxd -c 36 -g 3 -s 54 large.bmp 다음과 같은 내용이 표시됩니다. Harvard CS50: 4주차 과제(강의 9 및 10) - 9이 BMP에는 여담이 없습니다. 결국 (12픽셀) × (픽셀당 3바이트) = 36바이트이며 이는 4의 배수입니다. xxd 16진수 편집기는 BMP 파일의 바이트를 보여주었습니다. 프로그래밍 방식으로 어떻게 얻을 수 있습니까? copy.c 에는 BMP의 복사본을 하나씩 생성하는 것이 유일한 목적인 프로그램이 하나 있습니다. 예, 이에 대해 cp를 사용할 수 있습니다 . 그러나 CP는 Boddy 씨를 도울 수 없습니다. copy.c 가 이를 수행하기를 바랍니다 . 이제 ls를./copy smiley.bmp copy.bmp 실행하면 (적절한 플래그와 함께) smiley.bmpcopy.bmp 가 실제로 동일한 크기임을 알 수 있습니다 . 이것이 실제로 사실인지 다시 확인해 볼까요? 이 명령이 화면에 아무것도 표시하지 않으면 파일이 실제로 동일하다는 의미입니다(중요: Photoshop과 같은 일부 프로그램에는 일부 VMP 끝에 후행 0이 포함됩니다. 우리 버전의 복사본에서는 이를 삭제하므로 하지 마십시오). 테스트를 위해 다운로드했거나 생성한 다른 BMP를 복사하는 경우 복사본이 원본보다 몇 바이트 더 작아질 수 있으니 걱정하세요. Ristretto의 이미지 뷰어에서 두 파일을 모두 열어(더블 클릭) 이를 시각적으로 확인할 수 있습니다. 하지만 diff는 이 비교를 바이트 단위로 수행하므로 그녀의 시력은 귀하의 시력보다 더 예리합니다! 이 사본은 어떻게 만들어졌나요? copy.c는 bmp.h 와 관련이 있는 것으로 나타났습니다 . 확인하자: bmp.h를 엽니다.diff smiley.bmp copy.bmp. 여기서는 이미 언급한 헤더의 실제 정의를 Microsoft 자체 구현에서 적용한 내용을 볼 수 있습니다. 또한 이 파일은 Win32(예: Windows) 프로그래밍 세계에서 일반적으로 발견되는 데이터 유형인 BYTE, DWORD, LONG 및 WORD 데이터 유형을 정의합니다. 이는 본질적으로 여러분에게 이미 친숙한 기본 요소에 대한 별칭입니다. BITMAPFILEHEADER 및 BITMAPINFOHEADER가 이러한 유형을 사용하고 있는 것으로 나타났습니다. 이 파일은 RGBTRIPLE이라는 구조체도 정의합니다. 이는 3바이트(파란색, 녹색, 빨간색) 3바이트를 "캡슐화"합니다(이는 디스크에서 RGB 삼중항을 찾는 순서입니다). 이 구조체는 어떻게 유용합니까? 요약하자면, 파일은 단순히 디스크에 있는 일련의 바이트(또는 궁극적으로 비트)입니다. 그러나 이러한 바이트는 일반적으로 처음 몇 개가 무언가를 나타내고 다음 몇 개가 다른 것을 나타내는 식으로 순서가 지정됩니다. 파일 "형식"은 바이트의 의미를 정의하는 표준 또는 규칙이 있기 때문에 존재합니다. 이제 디스크에서 RAM으로 파일을 하나의 큰 바이트 배열로 간단히 읽을 수 있습니다. 그리고 위치 [i]에 있는 바이트는 한 가지를 나타내고 위치 [j]에 있는 바이트는 다른 것을 나타낸다는 것을 기억합니다. 하지만 메모리에서 더 쉽게 검색할 수 있도록 이러한 바이트 중 일부에 이름을 지정하는 것은 어떨까요? 이것이 바로 bmp.h의 구조가 우리에게 도움이 되는 것입니다. 파일을 하나의 긴 바이트 시퀀스로 생각하는 대신 파일을 더 이해하기 쉬운 블록, 즉 구조 시퀀스로 분류하는 것을 볼 수 있습니다. smiley.bmp 의 해상도 는 8x8픽셀이므로 디스크에서 14 + 40 + (8 × 8) × 3 = 246바이트를 차지합니다(ls 명령을 사용하여 확인할 수 있습니다). Microsoft에 따르면 디스크에서의 모습은 다음과 같습니다. Harvard CS50: 4주차 과제(강의 9 및 10) - 10구조체 멤버의 경우 순서가 중요하다는 것을 알 수 있습니다. rgbtBlue가 RGBTRIPLE에 먼저 정의되었기 때문에 바이트 57은 rgbtBlue(rgbtRed가 아님)입니다. 그건 그렇고, pack 속성을 사용하면 clang이 멤버를 "단어 정렬"(각 멤버의 첫 번째 바이트 주소가 4의 배수인 상태)하려고 시도하지 않도록 하여 결과에 구멍이 생기지 않도록 합니다. 디스크에는 전혀 존재하지 않는 구조입니다. 계속 진행합시다. bmp.h의 설명에 따라 BITMAPFILEHEADER 및 BITMAPINFOHEADER와 일치하는 URL을 찾으세요. 주목하세요. 좋은 순간입니다. MSDN(Microsoft Developer Network)을 사용하기 시작하셨습니다! copy.c 를 더 스크롤하는 대신 몇 가지 질문에 답하여 코드 작동 방식을 이해하세요. 언제나 그렇듯이 man 명령은 진정한 친구이며 이제 MSDN이기도 합니다. 답을 모른다면 구글에 검색해서 생각해 보세요. https://reference.cs50.net/에서 stdio.h 파일을 참조할 수도 있습니다.
  1. 메인에 중단점을 설정합니다(메인 라인 번호가 있는 눈금자의 왼쪽을 클릭하여).

  2. 터미널 탭 에서 ~/workspace/pset4/bmp 로 이동 하고 make를 사용하여 copy.c를 복사 프로그램으로 컴파일합니다.

  3. debug50 copy smiley.bmp copy.bmp 를 실행하면 오른쪽에 디버거 패널이 열립니다.

  4. 오른쪽 패널을 사용하여 프로그램을 단계별로 살펴보세요. 참고 bfbi . ~/workspace/pset4/questions.txt 에서 다음 질문에 답하세요.

  • stdint.h 는 무엇입니까 ?

  • 프로그램에서 uint8_t , uint32_t , int32_tuint16_t 를 사용하는 이유는 무엇입니까 ?

  • BYTE , DWORD , LONGWORD 는 각각 몇 바이트를 포함합니까 (32비트 아키텍처 가정)?

  • BMP 파일의 처음 2바이트는 무엇(ASCII, 10진수 또는 16진수)이어야 합니까? (파일 형식을 식별하는 데 사용되는 선행 바이트(확률 높음)를 종종 "마법의 숫자"라고 합니다).
  • bfSize와 biSize의 차이점은 무엇입니까?

  • 음수 biHeight는 무엇을 의미합니까?

  • BITMAPINFOHEADER의 어떤 필드가 BMP의 색상 심도(즉, 픽셀당 비트 수)를 정의합니까?

  • copy.c 37에서 fopen 함수가 NULL을 반환할 수 있는 이유는 무엇입니까?

  • 코드에서 fread의 세 번째 인수가 1인 이유는 무엇입니까?

  • bi.biWidth가 3인 경우 copy.c 70의 어떤 값이 패딩을 정의합니까?

  • fseek는 무엇을 합니까?

  • SEEK_CUR이 무엇인가요?

Mr. Boddy에게 돌아가세요. 운동:

Mr. Boddy의 그림을 보여주는 whodunit.c 라는 파일에 whodunit 이라는 프로그램을 작성하세요 . 흠, 뭐? 복사와 마찬가지로 프로그램은 정확히 두 개의 명령줄 인수를 취해야 하며, 아래와 같이 프로그램을 실행하면 결과가 verdict.bmp에 저장되므로 Boddy 씨의 그림이 시끄럽지 않게 됩니다. 아래 명령을 실행하여 이 미스터리 해결을 시작해 보세요. Mr. Boddy를 돕기 위해 작성해야 하는 코드 라인이 얼마나 많은지 보면 놀랄 것입니다. smiley.bmp 에는 불필요한 숨겨진 내용이 없으므로 이 파일에서 프로그램을 자유롭게 테스트해 보세요. 이것은 작으며 개발 중에 프로그램의 출력과 xxd의 출력을 비교할 수 있습니다(아니면 smiley.bmp 에 뭔가 숨겨진 것이 있을 수도 있습니까 ? 실제로는 그렇지 않습니다). 그런데 이 문제는 다양한 방법으로 해결될 수 있습니다. 일단 Boddy 씨의 그림을 확인하시면, 그는 편히 쉬실 것입니다. whodunit은 다양한 방법으로 구현될 수 있으므로 check50을 사용하여 구현의 정확성을 확인할 수 없습니다 . 그리고 그것이 당신의 재미를 망치게 놔두십시오. 그러나 추리 문제 에 대한 보조자의 솔루션도 사용할 수 없습니다 . 마지막으로 ~/workspace/pset4/questions.txt 파일에서 다음 질문에 답하세요. ./whodunit clue.bmp verdict.bcp copy.c whodunit.cWhodunit? //ктоэтосделал?

크기 조정

자, 이제 다음 테스트입니다! resize.c에 resize 라는 프로그램을 작성해 보겠습니다 . 압축되지 않은 24비트 BMP 이미지의 크기를 n단계로 조정합니다. 애플리케이션은 정확히 3개의 명령줄 인수를 허용해야 합니다. 첫 번째(n)는 100보다 크지 않은 정수, 두 번째는 수정될 파일의 ​​이름, 세 번째는 수정된 파일의 저장된 버전의 이름입니다. 파일. Usage: ./resize n infile outfile 이러한 프로그램을 사용하면 아래와 같이 Small.bmp의 크기를 4로 조정하여(즉, 너비와 높이에 4를 곱하여) Large.bmp를 만들 수 있습니다. 단순화를 위해 copy.c를./resize 4 small.bmp large.bmp 다시 복사 하고 복사본 이름을 resize.c 로 지정하여 작업을 시작할 수 있습니다 . 그러나 먼저 다음 질문에 답해 보십시오. BMP 크기를 변경한다는 것은 무엇을 의미합니까(infile 크기의 n배는 232-1을 초과하지 않는다고 가정할 수 있습니다) . BITMAPFILEHEADER 및 BITMAPINFOHEADER에서 변경해야 할 필드를 결정합니다. 주사선 필드를 추가하거나 제거해야 하는지 고려하십시오 . 그리고 네, 0에서 1까지 n의 가능한 모든 값을 고려하라고 요청하는 것이 아니라는 사실에 감사하세요! (하지만 관심이 있으시다면 이것은 해커의 책에 나오는 문제입니다 ;)). 그러나 n = 1인 경우 프로그램은 올바르게 작동하고 출력 파일 outfile은 원래 infile과 동일한 크기라고 가정합니다. check50을 사용하여 프로그램을 확인하시겠습니까? 다음 명령을 입력하십시오. check50 2015.fall.pset4.resize bmp.h resize.c CS50 보조자가 만든 애플리케이션 구현을 가지고 놀고 싶습니까? 다음을 실행하십시오. ~cs50/pset4/resize 예를 들어, (xxd 가 허용하는 것보다 더 사용자 친화적인 형식으로) Large.bmp 헤더 를 보려면 다음 명령을 실행해야 합니다. ~cs50/pset4/peek large.bmpCS50 보조 파일의 헤더와 헤더. ~/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 형식이고 크기를 변경 중이므로 새 크기로 새 파일의 헤더를 작성해야 합니다. 무엇이 바뀔까요? 파일 크기와 이미지 크기 - 너비와 높이.

Harvard CS50: 4주차 과제(강의 9 및 10) - 11헤더 설명을 보면 biSizeImage 변수가 표시됩니다 . 이미지의 전체 크기를 바이트 단위로 나타내며, biWidth 는 이미지 너비에서 정렬을 뺀 값이고, biHeight 는 높이입니다. 이러한 변수는 BITMAPFILEHEADER 및 BITMAPINFOHEADER 구조에 있습니다. bmp.h 파일을 열면 찾을 수 있습니다 . Harvard CS50: 4주차 과제(강의 9 및 10) - 12BITMAPINFOHEADER 구조에 대한 설명에는 변수 목록이 포함되어 있습니다. 출력 파일의 제목을 쓰려면 높이와 너비 값을 변경해야 합니다. 그러나 나중에 원본 파일의 원래 높이와 너비가 필요할 수도 있습니다. 그러므로 둘 다 유지하는 것이 좋습니다. 실수로 출력 파일의 헤더에 잘못된 데이터를 쓰지 않도록 변수 이름에 주의하세요.
  • 우리는 나가는 파일을 한 줄씩, 한 픽셀씩 읽습니다. 이를 위해 다시 파일 I/O 라이브러리와 fread 함수를 사용합니다. 읽은 바이트 수, 읽을 단일 요소의 크기, 해당 요소의 수 및 읽을 파일에 대한 포인터를 포함하는 구조에 대한 포인터를 사용합니다.

    Harvard CS50: 4주차 과제(강의 9 및 10) - 13
  • 지정된 스케일에 따라 각 라인을 수평으로 늘리고 그 결과를 출력 파일에 씁니다.

    Harvard CS50: 4주차 과제(강의 9 및 10) - 14

    파일을 어떻게 작성하나요? 파일에 쓸 데이터가 있는 구조, 요소의 크기, 요소 수 및 출력 파일에 대한 포인터에 대한 표시기를 전달하는 fwrite 함수가 있습니다. 루프를 구성하려면 이미 익숙한 for 루프를 사용할 수 있습니다 .

    Harvard CS50: 4주차 과제(강의 9 및 10) - 15
  • 부족한 부분을 채워보세요! 한 줄의 픽셀 수가 4의 배수가 아닌 경우 "정렬"(0바이트)을 추가해야 합니다. 정렬 크기를 계산하려면 공식이 필요합니다. 출력 파일에 널 바이트를 쓰려면 fputc 함수를 사용하여 쓰려는 문자와 출력 파일에 대한 포인터를 전달할 수 있습니다.

    Harvard CS50: 4주차 과제(강의 9 및 10) - 16

    이제 문자열을 가로로 늘이고 출력 파일에 정렬을 추가했으므로 정렬을 뛰어넘어야 하므로 출력 파일에서 현재 위치를 이동해야 합니다.

    Harvard CS50: 4주차 과제(강의 9 및 10) - 17
  • 세로 크기를 늘립니다. 더 복잡하지만 copy.c 의 샘플 코드를 사용할 수 있습니다(copy.c는 출력 파일을 열고, 출력 파일에 헤더를 쓰고, 소스 파일에서 이미지를 한 줄씩, 픽셀 단위로 읽고 이를 씁니다. 출력 파일에). 이를 바탕으로 가장 먼저 할 수 있는 일은 다음 명령을 실행하는 것입니다: cp copy.c resize.c

    이미지를 세로로 늘린다는 것은 각 줄을 여러 번 복사하는 것을 의미합니다. 이를 수행하는 방법에는 여러 가지가 있습니다. 예를 들어, 다시 쓰기를 사용하면 한 줄의 모든 픽셀을 메모리에 저장하고 이 줄을 필요한 만큼 루프의 출력 파일에 쓸 수 있습니다. 또 다른 방법은 다시 복사하는 것입니다. 나가는 파일에서 한 줄을 읽고 이를 출력 파일에 쓰고 정렬한 후 fseek 함수 를 나가는 파일의 줄 시작 부분으로 되돌리고 모든 것을 여러 번 다시 반복합니다.

    Harvard CS50: 4주차 과제(강의 9 및 10) - 18
  • 다시 덮다

    4주차 문제지를 예상하면서 지난 며칠 동안 디지털 카메라로 1GB CompactFlash(CF) 메모리 카드에 JPEG 형식으로 저장된 사진을 살펴보았습니다. 대신 제가 실제로 지난 며칠 동안 페이스북에서 시간을 보냈다고 말하지 마세요. 불행하게도 제 컴퓨터 실력이 많이 부족해서 저도 모르게 실수로 사진을 모두 삭제하게 되었어요! 다행스럽게도 컴퓨터 세계에서 "삭제"는 일반적으로 "죽음"을 의미하지 않습니다. 내 컴퓨터는 이제 메모리 카드가 비어 있다고 주장하지만 나는 그것이 거짓말이라는 것을 알고 있습니다. 과제: ~/workspace/pset4/jpg/recover.c 에 이 사진을 복구할 프로그램을 작성하세요 . 흠. 좋습니다. 한 가지 더 설명하겠습니다. JPEG 형식은 BMP보다 복잡하지만 JPEG에는 다른 파일 형식과 구별하는 데 도움이 되는 바이트 패턴인 "서명"이 있습니다. 대부분의 JPEG 파일은 다음과 같은 3바이트로 시작합니다. 0xff 0xd8 0xff 첫 번째 바이트부터 세 번째 바이트까지, 왼쪽에서 오른쪽으로. 네 번째 바이트는 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,0xe8, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef 조합 중 하나일 가능성이 높습니다. 즉, JPEG 파일의 네 번째 바이트의 처음 4비트는 1110입니다. 사진이 저장된 드라이브(내 메모리 카드 등)에서 이러한 패턴 중 하나를 발견하면 이것이 JPEG 파일의 시작이 될 가능성이 있습니다. 물론 어떤 디스크에서 우연히 이런 일이 발생할 수 있으며 데이터 복구는 정확한 과학이라고 할 수 없습니다.

    결정하는 방법

    1. 메모리 카드의 내용이 담긴 파일을 엽니다.

    2. JPEG 파일의 시작 부분을 찾습니다. 이 카드의 모든 파일은 JPEG 형식의 이미지입니다.

    당신은 이미 JPEG 마커에 대해 알고 있습니다. Harvard CS50: 4주차 과제(강의 9 및 10) - 19각 JPEG 파일이 메모리에 단일 블록으로 저장되고 파일 자체가 차례로 이어진다는 것을 아는 것이 중요합니다. 개략적인 메모리 맵을 그려보자. 각 직사각형은 길이가 512바이트인 블록입니다. 회색 직사각형은 JPEG 파일이 없는 영역이고 별표는 JPEG 파일의 시작 부분을 나타냅니다. 우리는 파일 사이에 회색 블록이 없다고 믿습니다. Harvard CS50: 4주차 과제(강의 9 및 10) - 20512바이트의 데이터를 어떻게 읽어서 JPEG 헤더와 시작 부분을 비교합니까? 우리에게 이미 친숙한 fread 함수를 사용할 수 있습니다 . 이 함수는 읽은 바이트가 기록될 데이터 구조에 대한 포인터뿐만 아니라 읽고 있는 요소의 크기, 그러한 요소의 수 및 데이터를 읽고 있는 파일에 대한 포인터입니다. Harvard CS50: 4주차 과제(강의 9 및 10) - 21우리는 512바이트를 읽고 이를 버퍼에 저장하려고 합니다. 이는 &data 포인터가 되고 inptr 포인터는 메모리 카드의 내용이 포함된 열린 파일을 가리킵니다. 이제 우리가 저장하는 파일 구조로 돌아가 보겠습니다.
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION