[Powered by Google Translate] [Paso a paso - conxunto de problemas 4] [Zamyla Chan - Harvard University] [Esta é CS50. - CS50.TV] Todo ben. Ola, todos, e ben benvida ao Paso a paso 4. Hoxe a nosa pset é Forensics. Forense é un pset moi divertido que implica xestionar arquivos de bitmap para descubrir quen cometeu un crime. Entón imos redimensionar algúns arquivos de bitmap, entón imos para xestionar unha parte moi divertido chamado recuperar, en que estamos, basicamente, entregoulle unha tarxeta de memoria en que alguén accidentalmente borrado todos os seus arquivos, e estamos pediu para recuperar estes arquivos. Pero, primeiro, antes de entrar na pset, realmente só quero felicitar todos. Estamos a piques de medio deste curso. 0 Quiz está detrás de nós, e nós estamos en pset4, así, esencialmente, estamos a medio camiño. Percorremos un longo camiño, se ollar cara atrás a súa serie de exercicios, pset0 e pset1, para felicitar-se por tanto, e nós imos entrar en algunhas cousas realmente divertido. Polo tanto, a nosa caixa de ferramentas a este pset, de novo, en vez de correr o yum update-y sudo somos capaces de executar só update50 se está na versión 17,3 e por riba do aparello. Entón non se esqueza de executar update50 - é moito máis doado, algúns personaxes menos - estar seguro de que está na última versión do aparello. Especialmente é importante update50 cando comezar a usar CS50 Check. Entón, asegúrese de facelo. Para todas as seccións para este pset, imos estar lidando con entradas e saídas de arquivo, arquivo I / O. Nós imos estar pasando por unha serie de programas que lidan con matrices apuntando para arquivos e cousas así, por iso queremos estar seguro de que estamos realmente familiar e cómodo xestionar a forma de entrada e saída en arquivos. O código de distribución para este pset é un arquivo chamado copy.c, e iso é o que imos atopar, vai ser moi útil para nós porque nós imos acabar realmente copiar o ficheiro copy.c e só cambiando lixeiramente para ser capaz de alcanzar as 2 primeiras partes do conxunto de problemas. E entón, como dixen antes, estamos lidando con bitmaps, así como JPEGs. Entón, realmente comprender a estrutura como estes arquivos son organizados, como podemos realmente traducir os 0s e 1s en estruturas e as cousas que podemos realmente entender e interpretar e editar, que será realmente importante, para entrar en JPEG e arquivos de bitmap e comprender a estrutura destes. Pset4, como de costume, comeza con unha sección de preguntas. Aqueles ha xestionar o ficheiro de E / S e levalo acostumado a iso. A continuación, parte 1 é Whodunit, en que recibe un arquivo de bitmap que parece moito con puntos vermellos todo. E entón basicamente o que imos facer é pegar este ficheiro e Edit-lo só lixeiramente nunha versión que podemos ler. Esencialmente, unha vez que termine, nós imos ter o mesmo arquivo, excepto nós imos ser capaces de ver a mensaxe agochada escondida por todos os puntos vermellos. Entón Resize é un programa que, dado un ficheiro e entón deu o nome do ficheiro que xera e, entón, dado un número, así como, vai realmente redimensionar este bitmap por ese valor enteiro. Entón, por fin, temos a pset recuperar. Recibimos unha tarxeta de memoria e logo ter que recuperar todas as fotos que foron borrados accidentalmente, mais, como veremos, non realmente excluídos e eliminados do arquivo; Nós medio que perdeu cando eles estaban no arquivo, pero imos recuperar iso. Grande. Entón vai en arquivo I / O, especialmente, estes son toda unha lista de funcións que estará usando. Xa viu un pouco o básico de fopen, fread e fwrite, pero imos ollar máis para un ficheiro I / O funciona como fputc, en que acaba de escribir un personaxe de cada vez, para fseek, onde tipo de mover o indicador de posición do ficheiro para adiante e cara atrás, e, a continuación, algúns outros. Pero nós falaremos sobre isto un pouco máis tarde, durante o pset. Entón, primeiro, só para entrar no arquivo I / O, antes de ir para o pset, para abrir un arquivo, por exemplo, o que ten que facer é realmente definir un punteiro para o arquivo. Polo tanto, temos un punteiro FILE *. Neste caso, eu estou chamando-o dun punteiro porque ese vai ser o meu infile. E así eu vou usar a función fopen e despois o nome do ficheiro e, a continuación, o modo en que eu vou estar lidando con o arquivo. Polo tanto, non hai "r", neste caso, para a lectura, "w" para a escrita, e entón "a" para engadir. Por exemplo, cando está lidando con un infile e todo o que quere facer é ler os bits e bytes almacenados alí, entón probablemente vai querer usar "r", como o seu modo. Cando queres realmente escribir, tipo de facer un novo arquivo, entón o que imos facer é que imos abrir o novo ficheiro e usar o "w" modo de escribir. Entón cando estás lendo nos arquivos, a estrutura é a seguinte. Primeiro incluír o punteiro para a estrutura que contén os bytes que estás lendo. Así que vai ser o lugar final de bytes que estás lendo. Está indo entón para indicar o tamaño, sabor basicamente cantos bytes seu programa ten que ler o ficheiro, o tamaño basicamente un elemento, e entón vai para especificar cantos elementos que quere ler. E entón, finalmente, ten que saber onde estás lendo, de xeito que vai ser o punteiro no. Eu codificados por cores estes porque fread tamén é moi semellante á fwrite, excepto que quere estar seguro de que use a orde correcta, asegúrese de que está realmente escribir ou ler o ficheiro correcto. Entón, a continuación, como antes, se temos a dimensión do elemento, así como o número de elementos, entón podemos xogar un pouco aquí. Digamos que teña unha estrutura can e entón quero ler dous cans dunha vez. O que eu podería facer é dicir o tamaño dun elemento que vai ser do tamaño dun can e eu vou realmente ler dous deles. Como alternativa, o que eu podería facer é dicir que eu estou indo só para ler un elemento e que un elemento vai ser o tamaño de dous cans. Entón, iso é análogo como pode tipo de xogar con tamaño e número dependendo do que é máis intuitivo para ti. Todo ben. Entón, agora temos de ficheiros escrita. Cando se quere escribir un arquivo, o primeiro argumento é realmente onde está lendo. Entón é iso, basicamente, os datos que vai escribir para o arquivo, Que é o punteiro no final. Entón, cando está lidando con o pset, asegúrese de que non confundirse. Quizais ter o lado definicións con cóbado. Podes puxar as definicións do manual, escribindo o home e despois fwrite, por exemplo, no terminal, ou pode referirse a este slide e asegúrese de que está a usar o camiño certo. Entón, de novo, para fwrite, cando ten un arquivo que quere escribir para, que vai ser o último argumento, e que vai ser un punteiro para o arquivo. Entón é así que xestione a escrita, quizais varios bytes de cada vez, pero dicir que quere só escribir só un personaxe único. Como veremos máis adiante neste exemplo, nos bitmaps que imos ter que usar isto. É cando podemos utilizar fputc, esencialmente, só poñendo un personaxe de cada vez, CHR, para o punteiro do ficheiro, e iso é o punteiro nosa alí. Entón sempre que buscar ou escribir nun ficheiro, o ficheiro é manter o control de onde estamos. Entón, é unha especie de cursor, o indicador de posición do ficheiro. E así, cada vez que escribir ou ler outra vez nun arquivo, o arquivo realmente se lembra de onde é, e por iso segue a partir de onde o cursor está. Isto pode ser beneficioso cando quere, por exemplo, ler unha certa cantidade para facer algo e en seguida, ler o seguinte cantidade, pero ás veces podemos querer volver ou comezar realmente a partir dun valor de referencia determinado. Entón a función fseek, o que fai é que nos permite mover o cursor nun determinado ficheiro un determinado número de bytes. E entón o que temos que facer é especificar onde o valor de referencia é. Así, ou se move cara adiante ou cara atrás, de onde o cursor está actualmente, ou podemos especificar que debe moverse en só a partir do inicio do arquivo ou desde o fin do ficheiro. E así pode pasar valores positivos ou negativos para montante, e que tipo de mover o cursor cara adiante ou cara atrás. Antes de entrar en serie de exercicios outros, dúbidas en arquivo I / O? Okay. Como entramos en máis exemplos, Sinto-se libre para me deixar para preguntas. Así, en Whodunit, está entregado un ficheiro bitmap semellante a esta vermello no slide, e parece que iso - unha morea de puntos vermellos - e non sabe realmente o que está escrito. Se vostede é Vesgo, pode ser capaz de ver unha lixeira cor azulada dentro da media. Esencialmente, que é onde o texto está almacenado. Houbo un asasinato que pasou, e necesitamos descubrir quen fixo iso. Co fin de facer iso, necesitamos tipo de converter esa imaxe nun formato lexible. Se vós xa atopou este, ás veces, non habería kits pequenos onde tería unha lupa cun filme vermello. Alguén? Si Entón sería algo handed así, que tería unha lupa co filme vermello sobre el, que ía poñelas sobre a imaxe, e sería capaz de ver a mensaxe agochada nela. Nós non temos unha lupa con película vermella, entón en vez imos especie de crear a nosa propia neste pset. E así, o usuario vai whodunit entrada, entón a pista. BMP, entón esa é a infile, esa é a mensaxe punto vermello, e entón eles están dicindo verdict.bmp vai ser o noso ficheiro de saída. Por iso, vai crear unha nova imaxe bitmap semellante á pista un excepto nun formato lexible, onde podemos ver a mensaxe oculta. Xa que imos estar lidando con edición e manipulación de bitmaps de calquera tipo, imos tipo de mergullo no estructura destes arquivos bitmap. Nós fomos sobre estes un pouco en clase, pero imos ollar para eles un pouco máis. Bitmaps son esencialmente só un arranxo de bytes onde teña indicado que máis significa o que. Entón aquí é como unha especie de mapa de imaxe de bitmap dicindo que comeza con algúns arquivos de cabeceira, comeza con unha información alí. Vostede ve que o número de bytes tamaño 14 indícase da imaxe bitmap, e segue. Pero entón o que estamos realmente interesados ​​en aquí está comezando en torno a byte número 54. Temos estes triplica RGB. O que vai facer é conter os píxeles reais, os valores de cor. Todo o anteriormente exposto, que a cabeceira é unha información correspondente ao tamaño da imaxe, o ancho da imaxe, e á altura. Cando imos para o recheo máis tarde, imos ver por que o tamaño da imaxe pode ser diferente do que a anchura ou altura. Entón para representar eses - estas imaxes bitmap son secuencias de bytes - o que podemos facer é dicir todo ben, eu vou lembrar que o índice 14, é aí onde o tamaño é, por exemplo, pero en vez diso o que imos facer para facer isto máis doado e compacta-lo nunha estrutura. E así temos dúas estruturas feitas para nós, un BITMAPFILEHEADER e un BITMAPINFOHEADER, e por iso sempre que lemos no para o arquivo, por defecto vai estar indo en orde, e así, de xeito que tamén vai cubrir en variables como biWidth e biSize. E, a continuación, finalmente, cada pixel é representado por tres bytes. O primeiro é a cantidade de azul no pixel, o segundo é a cantidade de verde, e, finalmente, a cantidade de vermello, onde 0 é esencialmente non verde, azul ou ningún ou ningún vermello e en seguida, ss é o valor máximo. Estes son valores hexadecimais. Entón, a continuación, se temos FF0000, a continuación, que corresponde á cantidade máxima de azul e, a continuación, sen verde e sen vermello, para, entón, que nos daría un pixel azul. Entón, se temos todos os FF a través da tarxeta, entón iso significa que temos un pixel branco. Esta é unha especie de oposto ao normalmente cando dicimos RGB. Está realmente a suceder BGR. Entón, se nós realmente ollar para un exemplo dunha imaxe bitmap - déixame sacar unha. É un pouco pequena. Estou de ampliar, e podemos ver que está pixelizada. Parece que os bloques de cores. Ten bloques brancos e despois bloques vermellos. Se xogar en Microsoft Paint, por exemplo, vostede podería facer algo así por basicamente só pintando algunhas prazas nunha orde específica. Entón, o que se traduce no bitmap é a seguinte. Aquí temos primeiro píxeles brancos, que todos os seis son f, e entón temos píxeles vermellos, indicado por 0000ff. E así a secuencia de bytes que temos indica como a imaxe bitmap vai mirar. Entón, o que eu teño feito aquí é só escrito todos eses bytes e colorido entón no vermello de modo que pode tipo de ver, se ollar de esguello un pouco, como este tipo de indica un rostro sorridente. O xeito que o traballo de imaxes bitmap é, eu imaxino que, basicamente, como unha reixa. E así por defecto, todas as liñas da reixa ten que ser un múltiplo de 4 bytes. Se olharmos para unha imaxe bitmap, está cubrindo todos os valores. Por exemplo, pode ter un vermello aquí, un verde aquí, dun azul aquí, pero tes que estar seguro de que a imaxe é cuberto con un múltiplo de catro bytes. Entón, se eu quero a miña imaxe para ser a tres bloques de ancho, entón eu tería que poñer un valor baleiro no último a facelo un múltiplo de catro. Entón gustaríame engadir algo que estamos chamando de recheo. Eu só vou para indicar que alí cun x. Agora dicir que queremos unha imaxe que é de 7 píxeles de lonxitude, por exemplo. Temos 1, 2, 3, 4, 5, 6, 7, e todo isto é cuberto coa cor. O xeito que as imaxes bitmap traballar é que necesitamos unha oitava. Agora temos 1, 2, 3, 4, 5, 6, 7. Necesitamos 8 espazos para a imaxe bitmap para ler correctamente. Entón o que temos que facer é engadir un pouco de recheo para asegurarse de que todas as ancho son uniformes e que todas as ancho son un múltiplo de 4. E así eu indicado anteriormente, acolchoar como un X ou unha liña sinuosa, pero as imaxes reais bitmap do estofo indícase por un 0 hexadecimal. Entón, que sería un personaxe único, 0. O que pode vir a cadra é o comando XXD. O que fai é, en realidade, mostra, como semellante ao que eu facía antes co Smiley cando realmente imprimiu o que cada cor sería a pixel e entón un código de cores que cando executar xxd cos seguintes comandos, entón el vai realmente imprimir o que as cores son para aqueles píxeles. O que ten que facer é por aquí que eu indicar, como o S-54 di que eu vou comezar no byte 54 porque, antes diso, lembre, se olharmos para o mapa dos bitmaps, que é toda a información da cabeceira e cousas así. Pero o que realmente importa é os píxeles reais que indican a cor. Así, engadindo que a bandeira,-s 54, entón somos capaces de ver os valores de cor. E non se preocupe coas bandeiras complicados e cousas así. Na especificación do conxunto de problemas, terá instrucións sobre como usar xxd para amosar os píxeles. Entón, se ve aquí, medio que se parece unha caixa verde, esa cousa pequena. Eu teño un código de cores a 00ff00 basicamente como dicir non azul, moi verde, e non vermello. De xeito que corresponde a verde. Como podes ver aquí, vemos un rectángulo verde. Este rectángulo verde é de só 3 píxeles de ancho, entón o que temos que facer para estar seguro de que a imaxe é un múltiplo de 4 ancha é engadir en estofado extra. E entón é así que ver eses 0s aquí. Isto vai realmente ser o resultado do seu pset Resize, esencialmente tomar o pequeno bitmap e despois ampliala lo por 4. E entón o que vemos é que, en realidade, esta imaxe é de 12 píxeles de ancho, pero 12 é un múltiplo de 4, e así nós realmente non vexo ningún 0s ao final, porque non necesita engadir ningún porque está totalmente cuberto. El non ten espazo máis. Okay. Calquera dúbida sobre o recheo? Okay. Cool. Como mencionei antes, os bitmaps son só unha secuencia de bytes. E entón o que temos é, en vez de ter saber exactamente o número de bytes que corresponde a un elemento específico, que realmente crearon unha estrutura para representar isto. Entón, o que temos é unha estrutura RGBTRIPLE. Sempre que ten unha instancia dun triplo RGB, porque este é un tipo de definir struct, entón pode acceder a variable rgbtBlue, Similarmente as variables verde e vermello, o que indicará a cantidade de azul, verde e vermello respectivamente, o que ten. Entón, se temos a variable azul a 0, o conxunto verde para FF, que é o valor máximo que pode ter, e entón a variable vermello definido como 0, entón o que a cor que neste particular RGB triplo representa? >> [Alumno] Verde. Green. Exactamente. Vai ser útil saber que sempre que teña unha instancia dun triplo RGB, realmente pode acceder a cantidade de memoria - azul, verde e vermello - separado. Agora que xa falamos sobre a estrutura do que imos dar un ollo ao ficheiro BMP. Estes son estruturas deseñadas para ti. Aquí temos unha estrutura BITMAPFILEHEADER. De interese é o tamaño. Máis tarde, temos a cabeceira da información, que ten máis algunhas cousas que son interesantes para nós, a saber, o tamaño, a anchura e altura. Como imos entrar en máis tarde, cando le o ficheiro, el automaticamente le porque definir a fin de ser o mesmo. Así, o biSize conterá os bytes dereitas que corresponden ao tamaño real da imaxe. E entón, aquí, por último, como falamos, temos a estrutura RGBTRIPLE typedef. Temos un rgbtBlue, verde e vermello asociados. Grande. Okay. Agora que entendemos bitmaps un pouco, entender que temos unha cabeceira do ficheiro e unha cabeceira información asociada a ela e despois diso, temos a parte interesante das cores, e as cores son representados por estruturas RGBTRIPLE, e os que, á súa vez, ten tres valores asociados ao azul, o verde eo vermello. Entón, agora, podemos tipo de pensar en recuperar un pouco. Sentímolo. Debería Whodunit. Cando temos o noso arquivo de pista, entón o que queremos facer é ler para el píxel por píxel e despois de algunha maneira cambiar os píxeles para que poidamos producir nun formato lexible. E así a saída, imos escribir pixel por pixel no arquivo verdict.bmp. Este é un tipo de moito para facelo. Nós entendemos iso. Entón, o que fixemos é que, en realidade, sempre que copy.c. O que fai é só copy.c fai unha copia exacta dun arquivo de bitmap dado e en seguida, xera-lo. Entón, iso xa abre o arquivo para ti, le en píxeles por pixel, e despois escribe-in nun ficheiro de saída. Imos dar un ollo niso. Este é asegurar unha utilización axeitada, recibindo os nomes aquí. O que isto significa que define o ficheiro de entrada para ser o que pasamos en en infile aquí, que é o noso argumento de liña de comandos segundo. Verifica para estar seguro de que podemos abrir o ficheiro. Comproba que podemos facer unha outfile novo aquí. Entón, o que iso fai aquí, é basicamente só comeza a ler para o ficheiro de bitmap dende o principio. O inicio, como se sabe, contén o BITMAPFILEHEADER, e así as secuencias de bits pode directamente encher o BITMAPFILEHEADER. Entón o que temos aquí está dicindo que bf BITMAPFILEHEADER - esa é a nosa nova variable do tipo BITMAPFILEHEADER - imos poñer dentro bf que lemos no punteiro, que é o noso infile. Canto é que lemos? Lemos en cantos bytes que necesitamos para conter a BITMAPFILEHEADER todo. Do mesmo xeito, iso é o que nós facemos a cabeceira info. Entón, nós estamos continuando ao longo da nosa arquivo no infile, e estamos lendo os bits e bytes, e estamos ligando-os directamente no nestes casos das variables que estamos facendo. Aquí estamos só estar seguro de que o bitmap é un bitmap. Agora temos un outfile, non? Así como está cando a creamos, é esencialmente baleiro. Entón temos que, basicamente, crear un novo bitmap a partir de cero. O que facemos é que temos que estar seguro de que copiamos na cabeceira do arquivo eo cabeceira información como o infile ten. O que nós facemos é escribir - e lembre que bf é a variable de BITMAPFILEHEADER tipo, entón o que facemos é só usar este contido escribir no ficheiro de saída. Aquí, lembro que falou sobre o recheo, como é importante estar seguro de que a cantidade de píxeles que temos é un múltiplo de 4. Esta é unha fórmula moi útil para calcular a cantidade de recheo que ten dada a anchura do seu arquivo. Eu quero que vostedes lembrar que en copy.c temos unha fórmula para calcular o estofado. Ok? Entón, lembre que todos. Grande. Entón o que copy.c fai a seguir é que itera sobre todos os scanlines. El vai percorrer as liñas e despois almacena todos os triples que le e despois grava-lo no ficheiro de saída. Entón aquí estamos lendo só un RGB triplo de cada vez e logo poñer que Triple mesmos para o ficheiro de saída. A parte complicada é que o recheo non é unha tripla RGB, e por iso non pode só ler que cantidade de recheo de triples RGB. O que temos que facer é realmente só mover o noso indicador de posición do arquivo, mover noso cursor, que tipo de saltar sobre todo estofado de xeito que estamos na liña seguinte. E entón o que iso fai é copia mostra como pode querer engadir o estofado. Entón, nós calculamos a cantidade de recheo que necesitamos, o que significa que necesitamos número recheo de 0s. O que isto fai é un loop que pon estofo número de 0s no noso ficheiro de saída. E entón, finalmente, pechar os dous arquivos. Vostede pecha o infile, así como o ficheiro de saída. Entón é así que copy.c obras, e que vai ser moi útil. En vez de só a verdade directamente copiar e pegar ou só mirando para el e escribindo o que quere, pode só querer executar este comando no terminal, CP copy.c whodunit.c, que creará un novo arquivo, whodunit.c, que contén exactamente o mesmo contido como copia fai. Entón o que podemos facer é usar isto como unha estrutura sobre a que construír e editar para o noso arquivo whodunit. Estes son os nosos para-dos a facer para Whodunit, pero o que fai copy.c é realmente toma conta da maioría deles a nós. Entón, todo o que cómpre facer agora é cambiar os píxeles que corresponda para realmente facer o ficheiro lexíbel. Lembre que para un determinado pixel triple, así, para unha determinada variable de RGBTRIPLE tipo, pode acceder aos azuis, os valores ecolóxicos e vermello. Isto vai vir a cadra, porque se pode acceder a eles, Isto significa que tamén pode ve-los, e iso significa que tamén pode muda-los. Entón, cando nós volvemos para o noso exemplo vermello lupa, basicamente, que estaba actuando como unha especie de filtro para nós. Entón, o que queremos facer é que queremos para filtrar todos os triples que están vindo dentro Existen varias maneiras diferentes de facelo. Basicamente, pode ter calquera tipo de filtro que quere. Quizais queira cambiar os píxeles vermellos ou quizais quere cambiar un pixel de cor diferente para unha cor diferente. Isto é con vostede. Lembre que pode comprobar que a cor do pixel é e entón tamén pode muda-lo como está pasando. Okay. Entón, iso é Whodunit. Unha vez que executar Whodunit, vai saber quen é o culpable do crime era. Agora estamos indo a ir a redimensionar. Nós imos aínda estar lidando con bitmaps. O que imos facer é que imos ter un bitmap de entrada e despois imos pasar nun número e en seguida, obter un bitmap outfile onde iso é basicamente a nosa infile escalado por n. Diga meu arquivo era só un pixel grande. Entón, se o meu n foi de 3, o deseño por 3, entón quere repetir que o pixel n número de veces, Polo tanto, 3 veces, e, a continuación, reducir a escala 3 veces tamén. Entón ve que eu estou escalando o en vertical coma en horizontal. E entón aquí está un exemplo. Se ten n = 2, ve que o primeiro pixel azul alí repetido dúas veces horizontalmente, así como dúas veces verticalmente. E, entón, que segue, e entón vostede ten unha escala directa da súa imaxe orixinal por dous. Entón, se fósemos para detallar o pseudocódigo para iso, queremos abrir o ficheiro. E entón, sabendo que volver aquí, vemos que a anchura para o outfile vai ser diferente do que a anchura para o infile. O que significa isto? Isto significa que o noso información de cabeceira vai cambiar. E entón o que queremos facer é actualizar a información da cabeceira, sabendo que cando lemos nos arquivos se está operando no marco copy.c, xa temos unha variable que indica que o tamaño é, e cousas así. Polo tanto, unha vez que ten, o que pode querer facer é cambiar as variables particulares. Teña en conta que, se ten unha estrutura, como acceder as variables dentro desa. Usa o operador punto, non? Entón usando iso, vostede sabe que vai ter para cambiar a información da cabeceira. Entón, aquí é só unha lista dos elementos reais que van estar cambiando no seu arquivo. O tamaño do ficheiro pode estar a cambiar, da imaxe, así como a anchura e altura. Entón, a continuación, volver ao mapa dos bitmaps, mira se é a cabeceira do ficheiro ou a cabeceira que contén información que a información e, a continuación, faga as modificacións necesarias. Unha vez máis, dicir CP copy.c resize.c. Isto significa que resize.c agora contén todo o que está contido dentro copia copia porque nos ofrece unha forma de ler para cada pixel por pixel scanline. Só que agora, en vez de só cambiando os valores como fixemos no Whodunit, o que queremos facer é que queremos escribir en múltiples píxeles sempre que o noso n é maior que 1. Entón, o que queremos facer é que queremos estirar horizontalmente por n, así como estirala-lo na vertical, n. Como podemos facer iso? Diga o n é 2 e ten ese infile dado. O cursor vai comezar no primeiro, eo que quere facer, se n é 2, quere imprimir en dúas delas. Entón imprimir en dúas delas. A continuación, o cursor vai cambiar para o próximo pixel, que é o vermello, e vai imprimir dúas daqueles vermellos, anexando-lo para o que está feito antes. A continuación, o cursor ha moverse ao seguinte pixel e deseñar en dúas delas. Se ollar cara atrás para o cadro copy.c, o que iso fai aquí é el crea unha nova instancia dun triplo RGB, unha nova variable chamada triple. E aquí, cando se le para el, el le a partir do 1 infile RGBTRIPLE e almacena-lo dentro desa variable triplo. Entón realmente ten unha variable que representa o pixel particular. Entón, cando escribe, o que pode querer facer é pechar a declaración fwrite para un ciclo que escribe na súa outfile tantas veces como sexa necesario. Isto é moi sinxelo. Basicamente só repetir o proceso de escritura n número de veces para escala-lo en horizontal. Pero, entón, hai que lembrar que o noso espazo vai cambiar. Anteriormente, dicir que tiña algo de lonxitude 3. Entón nós só engadir en canto estofado? Só unha para facelo un múltiplo de 4. Pero dicir que estamos escalando esa imaxe en particular ao n = 2. Entón cantos píxeles azuis teriamos a finais? Teriamos 6. 1, 2, 3, 4, 5, 6. Todo ben. 6 non é un múltiplo de catro. Cal é o múltiplo máis próximo de 4? Isto vai ser 8. Entón, nós estamos realmente vai ter dous caracteres de recheo alí. Alguén se lembra se temos unha fórmula para calcular o recheo e onde que podería ser? [Resposta do alumno inaudível] >> Si copy.c., Dereito. Hai unha fórmula en copy.c para calcular a cantidade de recheo que ten dada unha anchura particular da imaxe bitmap. Entón iso vai ser útil cando precisa engadir unha certa cantidade de estofado para realmente descubrir o que estofado precisa engadir. Pero unha nota, con todo, é que quere estar seguro de que está a usar o tamaño correcto. Só Tomé coidado porque está basicamente vai ser tratar con dúas imaxes bitmap. Quere estar seguro de que está a usar o camiño certo. Cando está calculando o recheo para o outfile, que desexa utilizar o ancho da outfile e non o ancho da anterior. Grande. Este tipo de coida de estirar unha imaxe bitmap enteiro horizontalmente. Pero o que queremos facer é realmente estirar-lo na vertical tamén. Este vai ser un pouco máis complicado, porque cando termine de copiar unha liña e escrita nesa liña, o noso cursor vai ser ao final. Entón, se ler de novo, el só vai ler a seguinte liña. Entón, o que queremos facer é unha especie de atopar algunha maneira de copiar as liñas novo ou só unha especie de tomar esa liña e despois reescribir-lo de novo. Como eu medio que aludiu, hai moitas maneiras diferentes de facelo. O que podería facer é como está pasando e lectura a través da scanline especial e cambia-lo, se é necesario, a continuación, tipo de tenda todos os píxeles nunha matriz. Despois, máis tarde vostede sabe que vai ter para imprimir esa matriz de novo, e así pode só usar esa matriz para facelo. Outra forma de facelo é que pode copiar unha liña para abaixo, entender que precisa copiar iso de novo, entón realmente mover o cursor, e que vai estar usando o fseek método. Pode mover o cursor todo o camiño de volta e repita o proceso de copia de novo. Entón, o noso número de escala é n, entón cantas veces teriamos que volver e reescribir unha liña? >> [Alumno] n - 1. >> Si, perfecto. n - 1. Nós fixemos iso unha vez máis, e por iso, entón imos querer repetir o proceso voltar n - 1 cantidade de veces. Okay. Polo tanto, ten a súa función de cambio de tamaño. Agora podemos chegar a unha parte moi divertido, miña pset favorito, que é recuperar. En vez de bitmaps, esta vez estamos lidando con JPEG. Non estamos realmente dado un ficheiro só de JPEGs, Estamos dando basicamente un formato de tarxeta de memoria prima. E así, este contén un pouco de valores e información de lixo, en principio, e entón comeza e ten unha morea de arquivos JPEG. Con todo, estamos entregou unha tarxeta onde nós excluímos as fotos; esencialmente, esquecemos onde as imaxes están situados dentro da tarxeta. Entón a nosa tarefa en recuperación e para pasar por este formato de tarxeta e atopar as fotos de novo. Afortunadamente, a estrutura de ficheiros JPEG eo arquivo de tarxeta é un pouco útil. El definitivamente podería ser un pouco máis complicado se non fose ese formato particular. Cada ficheiro JPEG realmente comeza con dúas secuencias posibles, listados enriba. Basicamente, sempre que ten un novo ficheiro JPEG, que comeza coa secuencia de calquera FFD8 FFE0 ou ​​outro, FFD8 ffe1. Outra cousa útil é saber que JPEGs son almacenados de forma contigua. Así, sempre que un arquivo JPEG remata, o outro empeza. Polo tanto, non hai ningún tipo de en-entre os valores alí. Despois de bater o inicio dun JPEG, se xa foi a lectura dun JPEG, vostede sabe que bateu o final do anterior eo inicio do próximo. Para tipo de ver iso, eu fixen un esquema. Outra cousa sobre JPEGs que pode le-los en secuencias de 512 bytes de cada vez, de forma semellante co inicio da tarxeta. Nós non precisamos de estar comprobar cada byte, porque iso sería un saco. Entón, en vez diso, o que podemos facer é realmente acaba de ler en 512 bytes de cada vez e entón, en vez de comprobar entre os naquelas pequenas franxas pequenas, podemos comprobar só o inicio dos 512 bytes. Esencialmente, neste cadro, o que ve é o inicio da tarxeta, ten valores que non son realmente relevantes para os JPEGs propiamente ditas. Pero entón o que eu teño é unha estrela para indicar unha das dúas secuencias de partida para un JPEG. Así, sempre que ve unha estrela, vostede sabe que ten un arquivo JPEG. E entón todos os ficheiros JPEG vai ser un múltiplo de 512 bytes pero non necesariamente o mesmo múltiple. O xeito que vostede sabe que bateu outro JPEG é se bater outra estrela, outra secuencia de partida bytes. Entón, o que ten aquí é que ten o vermello arquivo JPEG continuar ata que bata unha estrela, o que é indicado por unha nova cor. Vostede segue e despois de bater outra estrela, bateu outro JPEG, continúa todo o camiño ata o final. Vostede está na última foto aquí, a unha rosa. Vai para o fin até chegar ao final do ficheiro de caracteres. Isto vai ser realmente útil. A poucos takeaways principais aquí: O arquivo de tarxeta non comezar con un JPEG, pero unha vez que comeza un JPEG, todas as imaxes JPEG gárdanse de xeito conxunto entre si. Algúns pseudocódigo para a recuperar. En primeiro lugar, imos abrir o noso arquivo de tarxeta, e que vai estar usando o noso arquivo de E / S funcións. Imos repetir o proceso a seguir ata que teñamos acadado o final do arquivo. Nós imos ler 512 bytes de cada vez. E o que eu dixen aquí é que estamos indo a almacena-lo nun buffer, Entón, basicamente soster a eses 512 bytes ata que saibamos exactamente o que facer con eles. Entón, o que queremos facer é que queremos comprobar se se loita dunha estrela ou non. Se se loita dunha estrela, se se loita unha das secuencias iniciais, entón sabemos que se loita un novo ficheiro JPEG. O que queremos facer é que imos querer crear un novo arquivo no noso directorio pset4 para continuar a facer ese arquivo. Pero tamén, se xa fixo un JPEG antes, entón queremos acabar con ese arquivo e empurra-lo para o cartafol pset4, onde teremos que ficheiro gardado, porque se non especificar que xa rematou o ficheiro JPEG, entón basicamente ten unha cantidade indeterminada. Os JPEGs nunca vai acabar. Entón, nós queremos estar seguro de que cando estamos lendo nun arquivo JPEG e escrita que, queremos pechar especificamente que, a fin de abrir o próximo. Imos querer comprobar varias cousas. Queremos comprobar se estamos no inicio dun novo JPEG co noso buffer e tamén xa ter atopado un JPEG antes porque iso vai cambiar o seu proceso lixeiramente. Entón despois de pasar por todo o camiño e acadar o fin do ficheiro, entón o que vai querer facer é que vai querer pechar todos os ficheiros que están abertos. Isto probablemente vai ser o último ficheiro JPEG que ten, así como o arquivo de tarxeta que está lidando. O último obstáculo que temos que afrontar é como realmente facer un arquivo JPEG e como realmente empurra-lo para o cartafol. O pset require que cada JPEG que atopa estar no seguinte formato, onde ten o número. jpg. O número, aínda que sexa 0, chamamos iso 000.jpg. Sempre que atopar un JPEG no seu programa, vai querer nomealo na orde en que se atopa. O que significa isto? Necesitamos tipo de manter o control de cantos atopamos e que o número de cada JPEG debe ser. Aquí imos aproveitar da función sprintf. Semellante ao printf que só un tipo de impresións un valor fóra no terminal, sprintf imprime o arquivo na carpeta. E entón o que este faría se eu tivese sprintf título, e logo a corda alí, sería imprimir 2.jpg. Supoñendo que eu Fechei meus arquivos correctamente, que contén o ficheiro que eu tiña escrito para fóra. Pero unha cousa é que o código que eu teño aquí non moi satisfacer o que require o pset. O pset require que o ficheiro JPEG segundo debe ser nomeado 002 en vez de só dous. Entón, cando imprimir o nome, entón quizais pode querer cambiar o espazo reservado lixeiramente. Alguén se lembra de como permitir espazos extras cando imprimir algo? Si >> [Alumno] Vostede coloca un 3 por cento entre o sinal ea 2. >> Si, perfecto. Vai poñer un 3 neste caso, porque queremos espazo para 3. 3d% probablemente darlle 002.jpg vez de 2. O primeiro argumento para a función sprintf é na verdade unha matriz de char, que xa sabía como cadeas. Os vontade, especie de máis como un almacenamento temporal, só almacenar a cadea resultante. Realmente non vai ser tratar con isto, pero ten que inclui-lo. Sabendo que cada nome de ficheiro ten o número que leva ata tres personaxes, e despois. jpg, canto tempo debe ser esa matriz? Xoga fóra dun número. Cantos caracteres no título, o nome? Polo tanto, hai tres hashtags, período, jpg. >> [Alumno] 7. >> 7. Non é ben así. Nós imos querer 8 porque queremos permitir que o terminador nulo tamén. Finalmente, só para aproveitar o proceso que vai facer para recuperar, tes algunha información comezo. Vostede segue ata atopar o inicio dun ficheiro JPEG, e que pode ser calquera das dúas secuencias de partida. Vostede segue lendo. Cada barra aquí representa 512 bytes. Vostede segue a lectura, manter a lectura ata atopar outra secuencia de partida. Unha vez que ten iso, remata o actual JPEG - neste caso, é o vermello, así que quere acabar con iso. Queres sprintf o nome do que no seu cartafol pset4, Entón quere abrir un novo JPEG e manter a lectura ata o seguinte. Siga a ler, manter a lectura, e, finalmente, finalmente, vai chegar ao final do arquivo, e así que vai querer pechar o JPEG pasado que estaba a traballar, sprintf que na súa carpeta pset4, e despois ollar para todas as fotos que xa conquistou. Estas fotos son realmente imaxes de CS50 persoal, e por iso este é o lugar onde a parte divertida bonos do pset vén é que está competindo nas súas seccións para atopar os TFS nas fotos e sacar fotos con eles para probar que fixo o pset e así podes ver que os membros do equipo están nas fotos. Entón aproveitar fotos co persoal. Ás veces, ten que persegui-los. Probablemente algúns deles van tentar fuxir de ti. Sacar fotos con eles. Isto está en curso. Non é debido cando o pset é debido. O prazo será anunciado na especificación. A continuación, xunto coa súa sección, calquera sección leva máis fotos cos membros da maioría dos funcionarios vai gañar un premio moi legal. Este é un tipo de incentivo para que o seu pset4 rematar o máis rápido posible porque entón podes comezar a traballar cazando os diferentes CS50 funcionarios. Isto non é obrigatorio, pero, así que unha vez que obter as imaxes, entón está remate con pset4. E eu estou acabado con Paso a paso 4, polo tanto, grazas a todos por teren benvida. Boa sorte con Forensics. [Aplausos] [CS50.TV]