1 00:00:00,000 --> 00:00:09,500 >> [Música tocando] 2 00:00:09,500 --> 00:00:12,350 >> ZAMYLA CHAN: Foi senhorita Scarlett com o castiçal. 3 00:00:12,350 --> 00:00:13,560 Whodunit? 4 00:00:13,560 --> 00:00:15,030 Bem, vamos descobrir. 5 00:00:15,030 --> 00:00:20,870 No Clue jogo de tabuleiro, você pode ser dada uma imagem vermelha física. 6 00:00:20,870 --> 00:00:24,120 E essa imagem é muito vermelho e irregular, e seu trabalho é 7 00:00:24,120 --> 00:00:25,490 revelar a mensagem escondida. 8 00:00:25,490 --> 00:00:29,740 E, geralmente, você está equipado com um vermelho lupa, ou uma tela vermelha para 9 00:00:29,740 --> 00:00:31,410 revelam que a mensagem escondida. 10 00:00:31,410 --> 00:00:33,340 Bem, nós estamos indo para imitar isso. 11 00:00:33,340 --> 00:00:37,960 >> No romance policial, você está dado uma imagem bitmap que se parece muito irregular e vermelho, 12 00:00:37,960 --> 00:00:43,430 e, em seguida, executar o programa whodunit para revelar uma mensagem escondida. 13 00:00:43,430 --> 00:00:45,650 >> Então, vamos quebrar isso em etapas. 14 00:00:45,650 --> 00:00:50,390 Em primeiro lugar, você deseja abrir o arquivo - a pista que lhe foi dado. 15 00:00:50,390 --> 00:00:53,880 E depois também criar um arquivo veredicto bitmap. 16 00:00:53,880 --> 00:00:58,240 Então você deseja atualizar o bitmap cabeçalho informações para o outfile veredicto. 17 00:00:58,240 --> 00:00:59,920 Mais sobre isso mais tarde. 18 00:00:59,920 --> 00:01:04,319 E então você vai ler na pista, scanline, pixel por pixel, 19 00:01:04,319 --> 00:01:07,320 mudando as cores do pixel como necessário, e escrita 20 00:01:07,320 --> 00:01:08,960 aqueles em que o veredicto - 21 00:01:08,960 --> 00:01:12,000 pixel por pixel na scanline veredicto. 22 00:01:12,000 --> 00:01:13,780 >> Como é que vamos começar a ir a este respeito? 23 00:01:13,780 --> 00:01:16,940 Bem, felizmente, temos copy.c no código de distribuição. 24 00:01:16,940 --> 00:01:21,240 E isso vai provar muito útil para nós. 25 00:01:21,240 --> 00:01:29,700 Copy.c abre um arquivo, lê nesse cabeçalho do infile, e atualiza o 26 00:01:29,700 --> 00:01:31,070 cabeçalho do arquivo de saída. 27 00:01:31,070 --> 00:01:37,010 E, em seguida, lê-se a cada pixel na scanline, pixel por pixel, e, em seguida, 28 00:01:37,010 --> 00:01:42,390 escreve que de pixel para o arquivo de saída. 29 00:01:42,390 --> 00:01:45,020 >> Então, o primeiro passo pode a de executar o seguinte 30 00:01:45,020 --> 00:01:46,420 comando no terminal - 31 00:01:46,420 --> 00:01:50,270 cp copy.c whodunit.c. 32 00:01:50,270 --> 00:01:55,320 Isto irá criar uma cópia de copy.c chamado whodunit.c. 33 00:01:55,320 --> 00:01:58,320 Assim, o nosso primeiro passo para abrir o arquivo, bem, há uma exata 34 00:01:58,320 --> 00:02:00,070 réplica do que em copy.c. 35 00:02:00,070 --> 00:02:03,360 Então, eu vou deixar você olhar para isso. 36 00:02:03,360 --> 00:02:07,860 >> O que estamos lidando neste PSET é arquivo I / O, basicamente tomando arquivos, 37 00:02:07,860 --> 00:02:10,229 leitura, escrita, editá-los. 38 00:02:10,229 --> 00:02:12,650 Como você abre um arquivo? 39 00:02:12,650 --> 00:02:16,800 Bem, você está indo para declarar um arquivo ponteiro, e depois você chamar o 40 00:02:16,800 --> 00:02:18,670 função fopen. 41 00:02:18,670 --> 00:02:23,150 Passe no caminho, ou o nome da arquivo e, em seguida, o modo que você quer 42 00:02:23,150 --> 00:02:24,700 para abrir esse arquivo dentro 43 00:02:24,700 --> 00:02:28,620 Passando uma r abrirá foo.bmp para a leitura. 44 00:02:28,620 --> 00:02:35,670 Considerando fopen com passando um w vai bar.bmp aberto, para gravar o arquivo e 45 00:02:35,670 --> 00:02:37,020 realmente editá-lo. 46 00:02:37,020 --> 00:02:41,970 >> Portanto, agora que você abriu o arquivo, a nossa próximo passo é atualizar as informações do cabeçalho 47 00:02:41,970 --> 00:02:43,230 para o arquivo de saída. 48 00:02:43,230 --> 00:02:44,610 O que é uma informação de cabeçalho? 49 00:02:44,610 --> 00:02:48,160 Bem, primeiro precisamos saber o que é um bitmap é. 50 00:02:48,160 --> 00:02:51,000 Um bitmap é apenas um simples arranjo de bytes. 51 00:02:51,000 --> 00:02:55,480 E eles estão declarados neste arquivo aqui, bmp.h, com um monte de 52 00:02:55,480 --> 00:02:58,610 informação do que um bitmap é realmente feita de fora. 53 00:02:58,610 --> 00:03:05,730 Mas o que realmente importa é o cabeçalho do arquivo bitmap, bem aqui, e 54 00:03:05,730 --> 00:03:08,460 a informação bitmap cabeçalho, aqui. 55 00:03:08,460 --> 00:03:13,170 O cabeçalho é constituído por um par de variáveis ​​que poderá ser muito útil. 56 00:03:13,170 --> 00:03:18,400 Há biSizeImage, que é o tamanho total da imagem em bytes. 57 00:03:18,400 --> 00:03:20,890 E isso inclui pixels e estofamento. 58 00:03:20,890 --> 00:03:24,210 Padding é muito importante, mas nós vamos chegar a isso mais tarde. 59 00:03:24,210 --> 00:03:30,000 >> BiWidth representa a largura da imagem em pixels menos o estofamento. 60 00:03:30,000 --> 00:03:34,220 BiHeight é então também a altura da imagem em pixels. 61 00:03:34,220 --> 00:03:38,240 E, em seguida, o BITMAPFILEHEADER ea BITMAPINFOHEADER, como mencionei 62 00:03:38,240 --> 00:03:40,900 anterior, aqueles representados como estruturas. 63 00:03:40,900 --> 00:03:45,410 Então, você não pode acessar o cabeçalho do arquivo si mesmo, mas você vai querer começar a 64 00:03:45,410 --> 00:03:47,370 essas variáveis ​​dentro. 65 00:03:47,370 --> 00:03:48,170 >> OK. 66 00:03:48,170 --> 00:03:50,600 Então, como vamos atualizar as informações do cabeçalho? 67 00:03:50,600 --> 00:03:54,020 Bem, primeiro temos que ver se nós precisa alterar qualquer informação do 68 00:03:54,020 --> 00:03:58,480 o infile, a pista, com o outfile, o veredicto. 69 00:03:58,480 --> 00:04:00,250 Qualquer coisa está mudando neste caso? 70 00:04:00,250 --> 00:04:04,320 Bem, não realmente, porque nós vamos para ser apenas mudando as cores. 71 00:04:04,320 --> 00:04:07,550 Nós não vamos estar mudando o arquivo o tamanho, o tamanho da imagem, a largura, 72 00:04:07,550 --> 00:04:08,310 ou a altura. 73 00:04:08,310 --> 00:04:14,010 Então, você está bem por agora por apenas copiando cada pixel. 74 00:04:14,010 --> 00:04:14,840 >> OK. 75 00:04:14,840 --> 00:04:20,720 Então agora vamos olhar como nós, na verdade, pode ler cada pixel do arquivo. 76 00:04:20,720 --> 00:04:23,640 Outro arquivo função I / O vai entrar em jogo - 77 00:04:23,640 --> 00:04:24,700 fread. 78 00:04:24,700 --> 00:04:28,440 Leva em um ponteiro para a struct que irá conter os bytes 79 00:04:28,440 --> 00:04:30,110 você está lendo. 80 00:04:30,110 --> 00:04:31,890 Então você está lendo para isso. 81 00:04:31,890 --> 00:04:36,090 E então você passa em um tamanho, que é o tamanho de cada elemento que lhe 82 00:04:36,090 --> 00:04:37,360 deseja ler. 83 00:04:37,360 --> 00:04:40,640 Aqui, a função sizeof virá a calhar. 84 00:04:40,640 --> 00:04:45,570 Então você passa em número, que representa o número de elementos de 85 00:04:45,570 --> 00:04:47,480 tamanho de ler. 86 00:04:47,480 --> 00:04:51,180 E, em seguida, finalmente, inptr, que é o ponteiro do arquivo que você está 87 00:04:51,180 --> 00:04:52,530 indo para ler. 88 00:04:52,530 --> 00:04:58,650 Então, todos esses elementos estão dentro inptr e eles estão indo para dados. 89 00:04:58,650 --> 00:05:01,660 >> Vejamos um pequeno exemplo. 90 00:05:01,660 --> 00:05:07,590 Se eu quero ler em dados de dois cães, bem, eu posso fazer isso de duas maneiras. 91 00:05:07,590 --> 00:05:15,250 I pode ler em dois objetos de tamanho cão do meu inptr, ou eu posso ler 92 00:05:15,250 --> 00:05:19,280 em um objeto do tamanho de dois cães. 93 00:05:19,280 --> 00:05:23,580 Então você vê que, dependendo da forma que você organize tamanho e número, você 94 00:05:23,580 --> 00:05:25,840 pode ler o mesmo número de bytes. 95 00:05:25,840 --> 00:05:28,720 96 00:05:28,720 --> 00:05:33,020 >> Então, agora, vamos mudar o pixel de cor como nós precisamos. 97 00:05:33,020 --> 00:05:37,320 Se você olhar para bmp.h novamente, então você verá que na parte inferior 98 00:05:37,320 --> 00:05:42,920 RGBTRIPLEs são outra estrutura, onde eles são constituídos por três bytes. 99 00:05:42,920 --> 00:05:49,220 Um, rgbtBlue, rgbtGreen, e rgbtRed. 100 00:05:49,220 --> 00:05:52,480 Assim, cada um deles representa a quantidade de azul, a quantidade de verde, eo 101 00:05:52,480 --> 00:05:57,250 quantidade de vermelho dentro deste pixel, onde cada valor é representado por um 102 00:05:57,250 --> 00:05:58,670 número hexadecimal. 103 00:05:58,670 --> 00:06:04,370 >> Então ff0000 será uma cor azul, porque ele vai de azul, 104 00:06:04,370 --> 00:06:05,850 a verde, a vermelha. 105 00:06:05,850 --> 00:06:09,300 E então, f será de branco. 106 00:06:09,300 --> 00:06:13,440 Vamos dar uma olhada em smiley.bmp, que você tem no seu código de distribuição. 107 00:06:13,440 --> 00:06:15,690 Se você abri-lo em apenas uma imagem espectador, então você 108 00:06:15,690 --> 00:06:17,080 basta ver um smiley vermelho. 109 00:06:17,080 --> 00:06:20,380 Mas tomar um mergulho mais profundo em, vamos ver que a estrutura 110 00:06:20,380 --> 00:06:22,340 de que é apenas pixels. 111 00:06:22,340 --> 00:06:25,880 Temos pixels brancos, e, em seguida, vermelho pixels. 112 00:06:25,880 --> 00:06:31,000 O branco, ffffff, e então todo o pixels vermelhos Eu coloridas em para você 113 00:06:31,000 --> 00:06:35,440 aqui, e você vê que eles estão 0000ff. 114 00:06:35,440 --> 00:06:39,760 Zero azul, verde zero, e cheio vermelho. 115 00:06:39,760 --> 00:06:45,350 E uma vez que emoticon é de oito pixels de largura, não temos qualquer preenchimento. 116 00:06:45,350 --> 00:06:47,360 Tudo bem. 117 00:06:47,360 --> 00:06:53,310 >> Então, se eu fosse para atribuir valores diferentes a um RGBTRIPLE e eu queria 118 00:06:53,310 --> 00:06:58,350 torná-lo verde, então o que eu gostaria de fazer é Gostaria de declarar um RGBTRIPLE, nomeado 119 00:06:58,350 --> 00:07:02,660 triplo, em seguida, para acessar cada byte em que a estrutura I 120 00:07:02,660 --> 00:07:04,030 usaria o operador ponto. 121 00:07:04,030 --> 00:07:08,430 Então triple.rgbtBlue, eu posso atribuir que a 0. 122 00:07:08,430 --> 00:07:13,460 Verde posso atribuí-lo a full - qualquer número, na verdade, entre 0 e ss. 123 00:07:13,460 --> 00:07:15,470 E, em seguida, vermelho, eu também vou dizer a 0. 124 00:07:15,470 --> 00:07:19,160 Então isso me dá um pixel verde. 125 00:07:19,160 --> 00:07:23,030 >> Em seguida, o que se eu quiser verificar o valor de alguma coisa? 126 00:07:23,030 --> 00:07:27,250 Eu poderia ter algo que verifica se o valor rgbtBlue do triplo é 127 00:07:27,250 --> 00:07:31,080 ff e, em seguida, imprimir, "Estou me sentindo azul! ", como um resultado. 128 00:07:31,080 --> 00:07:35,640 Agora, isso não significa necessariamente que o pixel é azul, certo? 129 00:07:35,640 --> 00:07:40,060 Como os valores verdes e vermelhas do pixels Também pode ter valores não-0. 130 00:07:40,060 --> 00:07:43,470 Tudo o que isso significa, e tudo o que este está verificando é 131 00:07:43,470 --> 00:07:45,610 para uma cor azul completa. 132 00:07:45,610 --> 00:07:50,050 Mas todos os pixels também poderia ter parcial valores de cor, como este 133 00:07:50,050 --> 00:07:52,180 próximo exemplo aqui. 134 00:07:52,180 --> 00:07:55,400 >> É um pouco mais difícil de ver o que esta imagem é agora. 135 00:07:55,400 --> 00:08:00,320 Isso parece um pouco mais parecido com o clue.bmp que você vai ser dada. 136 00:08:00,320 --> 00:08:03,600 Agora, fisicamente, você pode resolver isso, porque há um monte de vermelho, por 137 00:08:03,600 --> 00:08:07,040 segurando uma tela vermelha para a imagem de modo que as outras cores podem aparecer. 138 00:08:07,040 --> 00:08:10,968 Então, como podemos imitar esta com c? 139 00:08:10,968 --> 00:08:15,640 Bem, podemos remover todo vermelho a partir da imagem totalmente. 140 00:08:15,640 --> 00:08:21,870 E assim fazer que iríamos definir cada valor vermelho pixel a 0. 141 00:08:21,870 --> 00:08:25,020 E assim a imagem ficaria um pouco pouco como este, onde não temos vermelho 142 00:08:25,020 --> 00:08:26,300 qualquer. 143 00:08:26,300 --> 00:08:29,390 >> Podemos ver a mensagem de uma oculta pouco mais claramente agora. 144 00:08:29,390 --> 00:08:31,730 É mais um rosto sorridente. 145 00:08:31,730 --> 00:08:33,870 Ou talvez nós poderíamos usar outro método. 146 00:08:33,870 --> 00:08:36,480 Talvez, poderíamos identificar todos os pixels vermelhos - 147 00:08:36,480 --> 00:08:41,100 isto é, todos os pixels com 0 azul, verde 0 e 0 vermelho - 148 00:08:41,100 --> 00:08:43,169 e mudar aqueles para branco. 149 00:08:43,169 --> 00:08:45,470 E a nossa imagem pode parecer algo como isto. 150 00:08:45,470 --> 00:08:48,250 Um pouco mais fácil de ver. 151 00:08:48,250 --> 00:08:51,170 >> Há muitas outras maneiras de descobrir a mensagem secreta, bem como, 152 00:08:51,170 --> 00:08:53,730 lidar com a manipulação de cor. 153 00:08:53,730 --> 00:08:57,050 Talvez você pode usar um dos métodos que eu mencionei acima. 154 00:08:57,050 --> 00:08:59,600 E além disso, você pode querer para melhorar algumas cores 155 00:08:59,600 --> 00:09:02,620 e levar os para fora. 156 00:09:02,620 --> 00:09:06,190 >> Portanto, agora que nós mudamos o pixel cor, ao lado só precisamos de escrevê-los 157 00:09:06,190 --> 00:09:08,500 em que a linha de varredura, pixel por pixel. 158 00:09:08,500 --> 00:09:11,860 E mais uma vez, você vai querer olhar para trás para copy.c, se você não copiou 159 00:09:11,860 --> 00:09:18,170 já, e olhar para o fwrite função, a qual leva dados, um ponteiro 160 00:09:18,170 --> 00:09:23,230 para a estrutura que contém o bytes que você está lendo a partir, o tamanho da 161 00:09:23,230 --> 00:09:26,610 os itens, o número de itens, e, em seguida, o outptr - 162 00:09:26,610 --> 00:09:29,450 o destino desses arquivos. 163 00:09:29,450 --> 00:09:34,010 >> Depois de escrever nos pixels, você vai também tem que escrever no estofamento. 164 00:09:34,010 --> 00:09:34,970 O que é o preenchimento? 165 00:09:34,970 --> 00:09:38,670 Bem, cada pixel RGBT é de três bytes. 166 00:09:38,670 --> 00:09:43,670 Mas, a linha de varredura de uma imagem de bitmap para tem de ser um múltiplo de quatro bytes. 167 00:09:43,670 --> 00:09:47,650 Se o número de pixels não é um múltiplo de quatro, então precisamos adicionar 168 00:09:47,650 --> 00:09:48,880 este preenchimento. 169 00:09:48,880 --> 00:09:51,420 O preenchimento é apenas representado por 0s. 170 00:09:51,420 --> 00:09:54,380 Então, como é que vamos escrever ou ler isso? 171 00:09:54,380 --> 00:09:59,280 Bem, acontece que você não pode estofamento realmente fread, mas você pode 172 00:09:59,280 --> 00:10:00,970 calculá-lo. 173 00:10:00,970 --> 00:10:04,400 >> Neste caso, a pista eo veredicto têm a mesma largura, de modo que o 174 00:10:04,400 --> 00:10:05,910 acolchoamento é a mesma. 175 00:10:05,910 --> 00:10:09,370 E o preenchimento, como você verá em copy.c, é calculado 176 00:10:09,370 --> 00:10:11,790 com a seguinte fórmula - 177 00:10:11,790 --> 00:10:16,690 bi.biWidth vezes sizeof (RGBTRIPLE) vai dê-nos quantos bytes o bmp 178 00:10:16,690 --> 00:10:18,280 tem em cada linha. 179 00:10:18,280 --> 00:10:21,890 De lá, os modulos e subtrações com 4 pode calcular quanto 180 00:10:21,890 --> 00:10:25,610 deve ser adicionado de modo a que muitos bytes o múltiplo de bytes em 181 00:10:25,610 --> 00:10:27,250 cada linha é quatro. 182 00:10:27,250 --> 00:10:30,490 >> Agora que temos a fórmula para quanto estofamento que precisamos, agora 183 00:10:30,490 --> 00:10:31,610 podemos escrevê-lo. 184 00:10:31,610 --> 00:10:34,080 Agora, eu mencionei antes, preenchimento é apenas 0s. 185 00:10:34,080 --> 00:10:39,730 Então, nesse caso, estamos apenas colocando char, neste caso, um 0, para o nosso 186 00:10:39,730 --> 00:10:41,710 outptr - nosso outfile. 187 00:10:41,710 --> 00:10:47,530 Então isso pode ser apenas fputc 0, vírgula outptr. 188 00:10:47,530 --> 00:10:52,400 >> Assim, enquanto nós temos a leitura em nosso arquivo, arquivo I / O tem mantido o controle de nossa 189 00:10:52,400 --> 00:10:57,440 posição nesses arquivos com algo chamado o indicador de posição de arquivo. 190 00:10:57,440 --> 00:10:59,350 Pense nisso como um cursor. 191 00:10:59,350 --> 00:11:03,550 Basicamente, ela avança cada vez que fread, mas temos 192 00:11:03,550 --> 00:11:05,671 controle sobre isso, também. 193 00:11:05,671 --> 00:11:11,030 >> Para mover o indicador de posição de arquivo, você pode usar a função fseek. 194 00:11:11,030 --> 00:11:15,600 Quando o inptr representa o arquivo ponteiro que você está procurando, em, a 195 00:11:15,600 --> 00:11:20,370 montante é o número de bytes que deseja mover o cursor e, em seguida, a partir de 196 00:11:20,370 --> 00:11:23,470 refere-se ao ponto de referência a partir de onde está o cursor. 197 00:11:23,470 --> 00:11:26,770 Se você passar em SEEK_CUR, que representa o actual 198 00:11:26,770 --> 00:11:28,100 posição no arquivo. 199 00:11:28,100 --> 00:11:31,020 Ou você pode usar alguns outros parâmetros. 200 00:11:31,020 --> 00:11:35,400 Então, a gente pode querer usar fseek para pular sobre o preenchimento do arquivo em. 201 00:11:35,400 --> 00:11:39,410 E, novamente, se você está preso, não há um exemplo de que, em copy.c. 202 00:11:39,410 --> 00:11:43,260 >> Então, agora nós abrimos o arquivo, a pista, eo veredicto. 203 00:11:43,260 --> 00:11:46,450 Nós atualizamos as informações do cabeçalho para nosso veredicto, porque cada 204 00:11:46,450 --> 00:11:48,730 bitmap precisa de um cabeçalho. 205 00:11:48,730 --> 00:11:52,280 Então Nós lemos na pista de scanline, pixel a pixel, mudando 206 00:11:52,280 --> 00:11:55,210 todas as cores conforme necessário, e escrevendo aqueles no 207 00:11:55,210 --> 00:11:57,340 veredicto, pixel por pixel. 208 00:11:57,340 --> 00:12:01,550 Uma vez que você abrir o veredicto, você pode ver quem o culpado, ou qual é o segredo 209 00:12:01,550 --> 00:12:02,850 mensagem é. 210 00:12:02,850 --> 00:12:05,550 Meu nome é Zamyla e este era whodunit. 211 00:12:05,550 --> 00:12:12,864