JavaRush /Blogue Java /Random-PT /Harvard CS50: Tarefas da Semana 4 (Aulas 9 e 10)
Masha
Nível 41

Harvard CS50: Tarefas da Semana 4 (Aulas 9 e 10)

Publicado no grupo Random-PT
Harvard CS50: Tarefas da Semana Quatro (Aulas 9 e 10) - 1

Preparando-se para o trabalho

Como sempre, primeiro abra uma janela de terminal e execute o comando. update50 para ter certeza de que seu aplicativo já está atualizado. Antes de começar, siga este procedimento cd ~ / workspace wget http://cdn.cs50.net/2015/fall/psets/4/pset4/pset4.zip para baixar um arquivo ZIP desta tarefa. Agora, se você executar ls , verá que possui um arquivo chamado pset4.zip em seu diretório ~/workspace . Extraia-o usando o comando: Se você executar o comando lsunzip pset4.zip novamente , verá que outro diretório apareceu. Agora você pode excluir o arquivo zip conforme mostrado abaixo: Vamos abrir o diretório pset4 , executar ls e verificar se o diretório contém rm -f pset4.zip cd pset4bmp / jpg / questions.txt

whodunit ou “Quem fez isso?”

Se você já viu a área de trabalho padrão do Windows XP (https://en.wikipedia.org/wiki/Bliss_(image)) (colinas e céu azul), então você viu o BMP. Nas páginas da web, você provavelmente já viu GIFs. Você já olhou fotos digitais? Então, tivemos a alegria de ver JPEG. Se você já fez uma captura de tela em um Mac, provavelmente já viu um PNG. Leia na Internet sobre os formatos BMP, GIF, JPEG, PNG e responda a estas perguntas:
  1. Quantas cores cada formato suporta?

  2. Qual formato suporta animação?

  3. Qual é a diferença entre compactação com e sem perdas?

  4. Qual desses formatos usa compactação com perdas?

Aqueles que falam inglês são aconselhados a consultar o artigo do MIT . Se você estudá-lo (ou encontrar outros recursos na Internet sobre como armazenar arquivos em discos e sistemas de arquivos), poderá responder às seguintes perguntas:
  1. O que acontece do ponto de vista técnico quando um arquivo é excluído em um sistema de arquivos FAT?

  2. O que pode ser feito para garantir (com alta probabilidade) que os arquivos excluídos não possam ser recuperados?

E agora - para a nossa história, que flui suavemente para a primeira tarefa da quarta semana. Bem-vindo à Mansão Tudor! O dono da propriedade, Sr. John Boddy, nos deixou de repente, vítima de um jogo obscuro. Para descobrir o que aconteceu, você deve definir whodunit . Infelizmente para você (embora ainda mais infelizmente para o Sr. Boddy), a única evidência que você tem é o arquivo BMP de 24 bits pista.bmp . É o seu conteúdo que você vê abaixo. Boddy conseguiu fazer e salvá-lo em seu computador em seus últimos momentos. O arquivo contém uma imagem policial escondida entre o ruído vermelho . Agora você precisa trabalhar na solução como um verdadeiro especialista técnico. Harvard CS50: Tarefas da Semana Quatro (Aulas 9 e 10) - 2Mas primeiro, algumas informações. Provavelmente é mais fácil pensar em uma imagem como uma grade de pixels (isto é, pontos), cada um dos quais pode ter uma cor específica. Para definir a cor de um ponto em uma imagem em preto e branco, precisamos de 1 bit. 0 pode representar preto e 1 pode representar branco, conforme mostrado na imagem abaixo. Harvard CS50: Tarefas da Semana Quatro (Aulas 9 e 10) - 3Assim, as imagens representadas desta forma são simplesmente um mapa de bits (bitmap ou bitmap, como se diz em inglês ou na gíria). Com preto e branco tudo é o mais simples possível, mas para obter imagens coloridas precisamos apenas de mais bits por pixel. Um formato de arquivo (como GIF) que suporta "cores de 8 bits" usa 8 bits por pixel. Um formato de arquivo (por exemplo, BMP, JPG, PNG) que suporta "cor de 24 bits" usa 24 bits por pixel (BMP na verdade suporta cores de 1, 4, 8, 16, 24 e 32 bits) . No BMP de 24 bits que o Sr. Boddy usa, são necessários 8 bits para indicar a quantidade de vermelho, a mesma quantidade para o verde e novamente 8 bits para indicar a quantidade de azul em cada pixel. Se você já ouviu falar em cores RGB , é isso (R=vermelho, G=verde, B=azul). Se os valores R, G e B de algum pixel em BMP forem, digamos, 0xff, 0x00 e 0x00 em hexadecimal, então o pixel será vermelho puro, já que 0xff (também conhecido como 255 em decimal) significa "muito vermelho " naquele momento, como 0x00 e 0x00 significam “sem verde” e “azul também zeros”, respectivamente. Dado o quão vermelha a imagem BMP do Sr. Boddy nos parece, é intuitivo que o “compartimento” vermelho tenha um valor claramente maior do que os “compartimentos” vermelho e azul. No entanto, nem todos os pixels são vermelhos; alguns são claramente de uma cor diferente. A propósito, em HTML e CSS (a linguagem de marcação e as folhas de estilo que o auxiliam, usadas para criar páginas da web), os modelos de cores são organizados da mesma maneira. Se estiver interessado, confira o link: https://ru.wikipedia.org/wiki/Colors_HTMLpara mais detalhes. Agora vamos abordar o problema de forma mais técnica. Lembre-se de que um arquivo é simplesmente uma sequência de bits organizados em alguma ordem. Um arquivo BMP de 24 bits é uma sequência de bits, cada 24 dos quais (bem, quase) determinam a cor de qual pixel. Além dos dados de cores, um arquivo BMP também contém metadados – informações sobre a largura e a altura da imagem. Esses metadados são armazenados no início do arquivo na forma de duas estruturas de dados comumente chamadas de "cabeçalhos" (não confundir com arquivos de cabeçalho C). O primeiro desses cabeçalhos é BITMAPFILEHEADER, que tem 14 bytes (ou 14*8 bits). O segundo cabeçalho é BITMAPINFOHEADER (40 bytes de comprimento). Depois desses cabeçalhos vem o bitmap: uma matriz de bytes, cujos trigêmeos representam a cor do pixel (1, 4 e 16 bits em BMP, mas não 24 ou 32, eles têm um cabeçalho adicional logo após o BITMAPINFOHEADER. É chamado a matriz RGBQUAD, definindo o “valor de intensidade” para cada uma das cores da paleta). No entanto, o BMP armazena esses trigêmeos ao contrário (poderíamos dizer como BGR), com 8 bits para azul, 8 bits para verde e 8 bits para vermelho. A propósito, alguns BMPs também armazenam o bitmap inteiro ao contrário, começando pela linha superior da imagem no final do arquivo BMP. Em nossa tarefa, salvamos o VMR conforme descrito aqui, primeiro a linha superior da imagem, depois as inferiores. Em outras palavras, transformamos um emoji de um bit em um de 24 bits, substituindo o preto pelo vermelho. Um BMP de 24 bits armazenará esse bitmap, onde 0000ff representa vermelho e ffffff representa branco; destacamos todas as instâncias de 0000ff em vermelho. Harvard CS50: Tarefas da Semana Quatro (Aulas 9 e 10) - 4Como apresentamos esses bits da esquerda para a direita, de cima para baixo, você poderá ver o rosto sorridente vermelho nessas letras se se afastar um pouco do monitor. Lembre-se de que um dígito no sistema numérico hexadecimal representa 4 bits. Conseqüentemente, ffffff em hexadecimal na verdade significa 111111111111111111111111 em binário. Agora, diminua a velocidade e não prossiga até ter certeza de que entendeu por que 0000ff representa um pixel vermelho em um arquivo BMP de 24 bits. Na janela CS50 IDE, expanda (por exemplo, clicando no pequeno triângulo) a pasta pset4 e nela - bmp . Nesta pasta você encontrará smiley.bmp , clique duas vezes no arquivo e você encontrará um pequeno smiley de 8x8 pixels. No menu suspenso, altere a escala da imagem, digamos de 100% a 400%, isso permitirá que você veja uma versão maior, mas ao mesmo tempo mais “borrada” do emoticon. Embora na realidade esta mesma imagem não deva ficar desfocada mesmo quando ampliada. Acontece que o IDE CS50 está tentando lhe fazer um favor (no estilo da série CIA) suavizando a imagem (desfocando visualmente as bordas). Esta é a aparência do nosso smiley se o ampliarmos sem suavizar: Harvard CS50: Tarefas da Semana Quatro (Aulas 9 e 10) - 5Pixels se transformaram em grandes quadrados. Vamos continuar. No terminal, vá para ~/workspace/pset4/bmp . Achamos que você já se lembra de como fazer isso. Vamos examinar os bytes alocados em smiley.bmp . Isso pode ser feito usando o editor hexadecimal de linha de comando, o programa xxd . Para executá-lo, execute o comando: xxd -c 24 -g 3 -s 54 smiley.bmp Você deverá ver o que é mostrado abaixo; Destacamos novamente em vermelho todas as instâncias de 0000ff. Harvard CS50: Tarefas da Semana Quatro (Aulas 9 e 10) - 6Na imagem da coluna mais à esquerda você pode ver os endereços do arquivo, que equivalem ao deslocamento do primeiro byte do arquivo. Todos eles são fornecidos em sistema de numeração hexadecimal. Se convertermos hexadecimal 00000036 em decimal, obteremos 54. Então você está olhando para o 54º byte de smiley.bmp . Lembre-se de que em arquivos BMP de 24 bits, os primeiros 14 + 40 = 54 bytes são preenchidos com metadados. Então, se você quiser ver os metadados, execute o seguinte comando: xxd -c 24 -g 3 smiley.bmp If smiley.bmp contém caracteres ASCII , nós os veremos na coluna mais à direita em xxd em vez de todos aqueles pontos. Portanto, smiley é um BMP de 24 bits (cada pixel é representado por 24 ÷ 8 = 3 bytes) com tamanho (resolução) de 8x8 pixels. Cada linha (ou "Scanline" como é chamada) ocupa (8 pixels) x (3 bytes por pixel) = 24 bytes. Esse número é um múltiplo de quatro e é importante porque o arquivo BMP é armazenado de maneira um pouco diferente se o número de bytes na linha não for um múltiplo de quatro. Então, em small.bmp, outro arquivo BMP de 24 bits em nossa pasta, você pode ver uma caixa verde de 3x3 pixels. Se você abri-lo em um visualizador de imagens, verá que ele se parece com a imagem mostrada abaixo, só que menor em tamanho. Harvard CS50: Tarefas da Semana Quatro (Aulas 9 e 10) - 7Cada linha em small.bmp ocupa, portanto, (3 pixels) × (3 bytes por pixel) = 9 bytes, o que não é um múltiplo de 4. Para obter um comprimento de linha que seja múltiplo de 4, ele é preenchido com zeros adicionais: entre 0 e 3 bytes preenchemos cada linha no formato BMP de 24 bits (você consegue adivinhar por que isso acontece?). Para small.bmp , são necessários 3 bytes de zeros, pois (3 pixels) x (3 bytes por pixel) + (3 bytes de preenchimento) = 12 bytes, que na verdade é um múltiplo de 4. Para "ver" esse preenchimento, faça o seguinte. xxd -c 12 -g 3 -s 54 small.bmp Observe que usamos um valor diferente para -c do que para smiley.bmp , então xxd gera apenas 4 colunas desta vez (3 para o quadrado verde e 1 para preenchimento). Para maior clareza, destacamos todas as ocorrências de 00ff00 em verde. Harvard CS50: Tarefas da Semana Quatro (Aulas 9 e 10) - 8Por outro lado, vamos usar xxd para o arquivo large.bmp . Parece exatamente igual a small.bmp, apenas sua resolução é de 12x12 pixels, ou seja, quatro vezes maior. Execute o comando abaixo. Pode ser necessário expandir a janela para evitar a transferência. xxd -c 36 -g 3 -s 54 large.bmp Você verá algo assim: Harvard CS50: Tarefas da Semana 4 (Aulas 9 e 10) - 9Observe que não há digressões neste BMP! Afinal, (12 pixels) × (3 bytes por pixel) = 36 bytes, e isso é um múltiplo de 4. O editor hexadecimal xxd nos mostrou os bytes em nossos arquivos BMP. Como podemos obtê-los programaticamente? Em copy.c existe um programa cujo único propósito na vida é criar uma cópia do BMP, peça por peça. Sim, você pode usar cp para isso . No entanto, cp não poderá ajudar o Sr. Boddy. Esperemos que copy.c faça isso, então vamos lá: Se você executar ls./copy smiley.bmp copy.bmp agora (com o sinalizador apropriado), verá que smiley.bmp e copy.bmp são de fato do mesmo tamanho. Vamos verificar novamente se isso é realmente verdade? Se este comando não exibir nada na tela, significa que os arquivos são realmente idênticos (importante: alguns programas, como o Photoshop, incluem zeros à direita no final de alguns VMPs. Nossa versão de cópia os descarta, então não faça isso. preocupe-se se no caso de copiar outros BMPs que você baixou ou criou para teste, a cópia será alguns bytes menor que o original). Você pode abrir ambos os arquivos no visualizador de imagens do Ristretto (clique duas vezes) para confirmar visualmente. Mas diff faz essa comparação byte por byte, então a visão dela é mais nítida que a sua! Como esta cópia foi criada? Acontece que copy.c está relacionado a bmp.h . Vamos ter certeza: abra bmp.hdiff smiley.bmp copy.bmp. Lá você verá as definições reais dos cabeçalhos que já mencionamos, adaptadas das próprias implementações da Microsoft. Além disso, este arquivo define os tipos de dados BYTE, DWORD, LONG e WORD, que são os tipos de dados normalmente encontrados no mundo da programação Win32 (ou seja, Windows). Observe que estes são essencialmente aliases para primitivos com os quais você (espero) já está familiarizado. Acontece que BITMAPFILEHEADER e BITMAPINFOHEADER estavam usando esses tipos. Este arquivo também define uma estrutura chamada RGBTRIPLE. Ele “encapsula” três bytes: um azul, um verde e um vermelho (esta é a ordem em que procuraremos os trigêmeos RGB no disco). Como essas estruturas são úteis? Para recapitular, um arquivo é simplesmente uma sequência de bytes (ou, em última análise, bits) no disco. No entanto, esses bytes são normalmente ordenados de modo que os primeiros representem algo, depois os próximos representem outra coisa e assim por diante. Os "formatos" de arquivo existem porque temos padrões, ou regras, que definem o que bytes significam. Agora podemos simplesmente ler o arquivo do disco para a RAM como uma grande matriz de bytes. E lembramos que o byte na posição [i] representa uma coisa, enquanto o byte na posição [j] é outra coisa. Mas por que não dar nomes a alguns desses bytes para que possamos recuperá-los mais facilmente da memória? É exatamente nisso que as estruturas em bmp.h nos ajudam. Em vez de pensar em um arquivo como uma longa sequência de bytes, nós o vemos dividido em blocos mais compreensíveis – sequências de estruturas. Lembre-se de que smiley.bmp tem resolução de 8x8 pixels, portanto ocupa 14 + 40 + (8 × 8) × 3 = 246 bytes no disco (você pode verificar isso usando o comando ls). Esta é a aparência do disco, de acordo com a Microsoft: Harvard CS50: Tarefas da Semana Quatro (Aulas 9 e 10) - 10Podemos ver que a ordem é importante quando se trata de membros de estruturas. O byte 57 é rgbtBlue (não, digamos, rgbtRed) porque rgbtBlue é definido primeiro em RGBTRIPLE. A propósito, nosso uso do atributo empacotado garante que o clang não tente “alinhar palavras” nos membros (com o endereço do primeiro byte de cada membro sendo um múltiplo de 4), para que não acabemos com buracos no nossas estruturas que não existem no disco. Vamos continuar. Encontre os URLs que correspondem a BITMAPFILEHEADER e BITMAPINFOHEADER, conforme os comentários em bmp.h. Atenção, ótimo momento: você está começando a usar o MSDN (Microsoft Developer Network)! Em vez de rolar ainda mais copy.c , responda algumas perguntas para entender como o código funciona. Como sempre, o comando man é seu verdadeiro amigo, e agora também o MSDN. Se você não sabe as respostas, pesquise no Google e pense a respeito. Você também pode consultar o arquivo stdio.h em https://reference.cs50.net/.
  1. Defina um ponto de interrupção em main (clicando à esquerda da régua com os números das linhas principais).

  2. Em uma guia do terminal , vá para ~/workspace/pset4/bmp e compile copy.c no programa de cópia usando make.

  3. Execute debug50 copy smiley.bmp copy.bmp , isso abrirá o painel do depurador à direita.

  4. Percorra o programa passo a passo usando o painel à direita. Observe bf e bi . Em ~/workspace/pset4/questions.txt , responda às perguntas:

  • O que é stdint.h ?

  • Qual é o sentido de usar uint8_t , uint32_t , int32_t e uint16_t em um programa?

  • Quantos bytes BYTE , DWORD , LONG e WORD contêm respectivamente (assumindo arquitetura de 32 bits)?

  • Quais devem ser (ASCII, decimal ou hexadecimal) os primeiros dois bytes de um arquivo BMP? (bytes iniciais, que são usados ​​para identificar o formato do arquivo (com alta probabilidade) são frequentemente chamados de "números mágicos").
  • Qual é a diferença entre bfSize e biSize?

  • O que significa um biHeight negativo?

  • Qual campo no BITMAPINFOHEADER define a profundidade de cor em BMP (ou seja, bits por pixel)?

  • Por que a função fopen pode retornar NULL em copy.c 37?

  • Por que o terceiro argumento para fread em nosso código é igual a 1?

  • Qual valor em copy.c 70 define o preenchimento se bi.biWidth for 3?

  • O que o fseek faz?

  • O que é SEEK_CUR?

De volta ao Sr. Boddy. Exercício:

Escreva um programa chamado whodunit em um arquivo chamado whodunit.c que mostre o desenho do Sr. Boddy. Hummm, o quê? Assim como a cópia, o programa deve receber exatamente dois argumentos de linha de comando e, se você executar o programa conforme mostrado abaixo, o resultado será armazenado em verdict.bmp, no qual o desenho do Sr. Boddy não terá ruído. ./whodunit clue.bmp verdict.b Sugerimos que você comece a resolver esse mistério executando o comando abaixo. cp copy.c whodunit.c Você pode se surpreender com quantas linhas de código precisa escrever para ajudar o Sr. Boddy. Não há nada desnecessário escondido em smiley.bmp , então sinta-se à vontade para testar o programa neste arquivo. É pequeno e você pode comparar a saída do seu programa e a saída do xxd durante o desenvolvimento (ou talvez haja algo oculto em smiley.bmp ? Na verdade, não). Aliás, esse problema pode ser resolvido de diferentes maneiras. Depois de identificar o desenho do Sr. Boddy, ele descansará em paz. Como o whodunit pode ser implementado de várias maneiras, você não poderá verificar a exatidão das implementações com check50 . E deixe que isso estrague a sua diversão, mas a solução dos assistentes também não está disponível para o problema do policial . Por fim, no arquivo In ~/workspace/pset4/questions.txt , responda a seguinte pergunta: Whodunit? //ктоэтосделал?

redimensionar

Bem, agora - o próximo teste! Vamos escrever um programa chamado resize em resize.c . Ele redimensionará uma imagem BMP descompactada de 24 bits em etapas de n. Sua aplicação deve aceitar exatamente três argumentos de linha de comando, sendo o primeiro (n) um número inteiro não maior que 100, o segundo sendo o nome do arquivo que será modificado e o terceiro sendo o nome da versão salva do arquivo modificado. arquivo. Usage: ./resize n infile outfile Com tal programa, poderíamos criar large.bmp a partir de small.bmp redimensionando este último por 4 (ou seja, multiplicando a largura e a altura por 4), conforme mostrado abaixo. Para simplificar, você pode iniciar a tarefa copiando copy.c./resize 4 small.bmp large.bmp novamente e nomeando a cópia resize.c . Mas primeiro, pergunte-se e responda a estas perguntas: o que significa alterar o tamanho do BMP (você pode assumir que n vezes o tamanho do arquivo não excederá 232 - 1) . Determine quais campos em BITMAPFILEHEADER e BITMAPINFOHEADER você precisa alterar. Considere se você precisa adicionar ou remover campos de scanlines . E, sim, fique grato por não estarmos pedindo para você considerar todos os valores possíveis de n de 0 a 1! (embora, se você estiver interessado, este seja um problema do livro de um hacker;)). No entanto, assumimos que para n = 1 o programa funcionará corretamente e o arquivo de saída do arquivo de saída terá o mesmo tamanho do arquivo de entrada original. Quer verificar o programa usando check50? Digite o seguinte comando: check50 2015.fall.pset4.resize bmp.h resize.c Quer brincar com a implementação da aplicação feita pelos assistentes CS50? Execute o seguinte: ~cs50/pset4/resize Bem, se você quiser ver, por exemplo, os cabeçalhos large.bmp (em uma forma mais amigável do que o xxd permite), você precisa executar o seguinte comando: ~cs50/pset4/peek large.bmp Melhor ainda, se você quiser comparar seus cabeçalhos com os cabeçalhos dos arquivos do assistente CS50. Você pode executar comandos dentro do diretório ~/workspace/pset4/bmp (pense no que cada comando faz). Se você usou malloc , certifique-se de usar free para evitar vazamentos de memória. Tente usar o valgrind para verificar se há vazamentos. ./resize 4 small.bmp student.bmp
~cs50/pset4/resize 4 small.bmp staff.bmp
~cs50/pset4/peek student.bmp staff.bmp

Como decidir?

  • Abra o arquivo que precisamos ampliar, e também crie e abra um novo arquivo no qual será gravada a imagem ampliada;

  • atualizar informações de cabeçalho para o arquivo de saída. Como nossa imagem está no formato BMP e estamos alterando seu tamanho, precisamos escrever o cabeçalho do novo arquivo com as novas dimensões. O que vai mudar? O tamanho do arquivo, bem como o tamanho da imagem - largura e altura.

Harvard CS50: Tarefas da Semana Quatro (Aulas 9 e 10) - 11Se olharmos a descrição do cabeçalho, veremos a variável biSizeImage . Indica o tamanho total da imagem em bytes, biWidth é a largura da imagem menos o alinhamento, biHeight é a altura. Estas variáveis ​​estão localizadas nas estruturas BITMAPFILEHEADER e BITMAPINFOHEADER. Você pode encontrá- los se abrir o arquivo bmp.h. Harvard CS50: Tarefas da Semana Quatro (Aulas 9 e 10) - 12A descrição da estrutura BITMAPINFOHEADER contém uma lista de variáveis. Para escrever o título do arquivo de saída, você precisará alterar os valores de altura e largura. Mas também há uma chance de que mais tarde você precise da altura e largura originais do arquivo original. Portanto, é melhor manter ambos. Tenha cuidado com os nomes das variáveis ​​para não escrever acidentalmente dados errados no cabeçalho do arquivo de saída.
  • Lemos o arquivo de saída, linha por linha, pixel por pixel. Para fazer isso, recorremos novamente à nossa biblioteca de E/S de arquivos e à função fread. É necessário um ponteiro para uma estrutura que conterá os bytes lidos, o tamanho do único elemento que iremos ler, o número de tais elementos e um ponteiro para o arquivo do qual iremos ler.

    Harvard CS50: Tarefas da Semana Quatro (Aulas 9 e 10) - 13
  • Aumentamos cada linha horizontalmente de acordo com a escala especificada e escrevemos o resultado no arquivo de saída.

    Harvard CS50: Tarefas da Semana Quatro (Aulas 9 e 10) - 14

    Como escrevemos arquivos? Temos uma função fwrite, para a qual passamos um indicador para a estrutura onde estão os dados a serem gravados no arquivo, o tamanho do elemento, seu número e um ponteiro para o arquivo de saída. Para organizar o loop, podemos usar o loop for com o qual já estamos familiarizados .

    Harvard CS50: Tarefas da Semana Quatro (Aulas 9 e 10) - 15
  • Preencha nos espaços! Se o número de pixels em uma linha não for múltiplo de quatro, devemos adicionar "alinhamento" - zero bytes. Precisaremos de uma fórmula para calcular o tamanho do alinhamento. Para escrever bytes nulos em um arquivo de saída, você pode usar a função fputc, passando o caractere que deseja escrever e um ponteiro para o arquivo de saída.

    Harvard CS50: Tarefas da Semana Quatro (Aulas 9 e 10) - 16

    Agora que esticamos a string horizontalmente e adicionamos um alinhamento ao arquivo de saída, precisamos mover a posição atual no arquivo de saída porque precisamos pular o alinhamento.

    Harvard CS50: Tarefas da Semana Quatro (Aulas 9 e 10) - 17
  • Aumente o tamanho vertical. É mais complicado, mas podemos usar o código de exemplo de copy.c (copy.c abre o arquivo de saída, grava um cabeçalho no arquivo de saída, lê a imagem do arquivo de origem linha por linha, pixel por pixel, e os grava para o arquivo de saída). Com base nisso, a primeira coisa que você pode fazer é executar o seguinte comando: cp copy.c resize.c

    Esticar uma imagem verticalmente significa copiar cada linha várias vezes. Existem várias maneiras diferentes de fazer isso. Por exemplo, usando reescrita, quando salvamos todos os pixels de uma linha na memória e escrevemos essa linha no arquivo de saída em um loop quantas vezes forem necessárias. Outro método é copiar novamente: após ler uma linha do arquivo de saída, gravá-la no arquivo de saída e alinhá-la, retorne a função fseek de volta ao início da linha no arquivo de saída e repita tudo novamente várias vezes.

    Harvard CS50: Tarefas da Semana 4 (Aulas 9 e 10) - 18
  • recuperar

    Antecipando o problema da Semana 4, passei os últimos dias olhando fotos salvas em formato JPEG pela minha câmera digital em um cartão de memória CompactFlash (CF) de 1 GB. Por favor, não me diga que passei os últimos dias no Facebook. Infelizmente, meus conhecimentos de informática deixam muito a desejar e, sem saber, apaguei acidentalmente todas as fotos! Felizmente, no mundo da informática, “excluído” geralmente não significa “morto”. Meu computador insiste que o cartão de memória está vazio, mas sei que está mentindo. Tarefa: Escreva um programa em ~/workspace/pset4/jpg/recover.c que recupere essas fotos. Hmmm. Ok, aqui vai mais um esclarecimento. Embora o formato JPEG seja mais complexo que o BMP, o JPEG possui "assinaturas", padrões de bytes que ajudam a distingui-lo de outros formatos de arquivo. A maioria dos arquivos JPEG começa com os três bytes a seguir: 0xff 0xd8 0xff Do primeiro ao terceiro byte, da esquerda para a direita. O quarto byte provavelmente será uma das seguintes combinações: 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,0xe8, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef. Em outras palavras, os primeiros quatro bits do quarto byte de um arquivo JPEG são 1110. Provavelmente, se você encontrar um desses padrões na unidade onde as fotos foram armazenadas (como meu cartão de memória), este será o início do arquivo JPEG. Claro, você pode encontrar isso em qual disco por puro acaso; a recuperação de dados não pode ser chamada de ciência exata.

    Como decidir

    1. Abra o arquivo com o conteúdo do cartão de memória.

    2. Encontre o início do arquivo JPEG. Todos os arquivos neste cartão são imagens em formato JPEG.

    Você já conhece os marcadores JPEG: Harvard CS50: Tarefas da Semana Quatro (Aulas 9 e 10) - 19é importante (e interessante) saber que cada arquivo JPEG é armazenado na memória como um único bloco, e os próprios arquivos seguem um após o outro. Vamos desenhar um mapa esquemático de memória. Cada retângulo é um bloco de 512 bytes de comprimento. Retângulos cinza são áreas onde não há arquivos JPEG; asteriscos indicam o início do arquivo JPEG. Acreditamos que não temos blocos cinza entre os arquivos. Harvard CS50: Tarefas da Semana Quatro (Aulas 9 e 10) - 20Como lemos esses dados, esses 512 bytes, para comparar o início deles com o cabeçalho JPEG? Podemos usar a função fread , que já nos é familiar, que leva um ponteiro para a estrutura de dados onde serão gravados os bytes lidos, bem como o tamanho do elemento que está sendo lido, a quantidade desses elementos, e um ponteiro para o arquivo do qual estamos lendo os dados. Harvard CS50: Tarefas da Semana Quatro (Aulas 9 e 10) - 21Queremos ler 512 bytes e armazená-los em um buffer. Este será o ponteiro &data, e o ponteiro inptr apontará para o arquivo aberto com o conteúdo do cartão de memória. Então, voltemos à estrutura do nosso arquivo, no qual salvamos
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION