[Muziek] ZAMYLA CHAN: Het was Miss Scarlett met de kandelaar. Wie? Nou, we gaan uitzoeken. In het bordspel Cluedo, zou je worden voorzien van een fysieke kopie rood. En dat beeld is zeer rood en vlekkerige, en uw taak is om onthullen de verborgen boodschap. En meestal je bent voorzien van een rode vergrootglas, of een rood scherm blijkt dat verborgen boodschap. Nou, we gaan na te bootsen dat. In whodunit, bent u een bitmapafbeelding gegeven dat ziet er zeer onregelmatig en rood, en voer het whodunit programma een verborgen boodschap onthullen. Dus laten we breken deze in stappen. Eerst moet je het bestand wilt openen - de aanwijzing die je hebt gekregen. En dan ook nog een maken verdict bitmap-bestand. Dan wil je de bitmap te werken header info op de uitspraak outfile. Daarover later meer. En dan moet je gaan om te lezen in de aanwijzing, scanline, pixel voor pixel, veranderen van de pixel kleuren nodig, en schrijven die in het vonnis - pixel voor pixel in de verdict scanline. Hoe beginnen we te gaan over dit? Nou, gelukkig hebben we copy.c in de verdeelsleutel. En dit gaat te bewijzen heel nuttig voor ons. Copy.c een bestand opent, leest in die infile kopbal, en werkt vervolgens de header outfile's. En dan leest elke pixel in het scanline, pixel voor pixel, en vervolgens schrijft dat pixel in de outfile. Dus, uw eerste stap zou kunnen zijn de volgende run commando in de terminal - cp copy.c whodunit.c. Hierdoor wordt een kopie van te maken copy.c genaamd whodunit.c. Dus onze eerste stap om te openen de file, goed, er is een exacte replica van die in copy.c. Dus ik zal je laten kijken. Wat we met deze PSET wordt file I / O, in principe nemen bestanden, lezen, schrijven, ze te bewerken. Hoe doe je eerst een bestand openen? Nou, je gaat naar een bestand te verklaren wijzer, en dan bel je de functie fopen. Passeren in het pad, of de naam van die bestand, en vervolgens de gewenste modus om dat bestand te openen in Passeren in een r zal openen foo.bmp voor het lezen. Overwegende fopen met het passeren in een w zal geopend bar.bmp, voor het schrijven van het bestand en eigenlijk bewerken. Dus nu dat we het bestand hebt geopend, onze volgende stap is om de header info updaten voor de outfile. Wat is een header info? Nou, ten eerste moeten we weten wat een bitmap is. Een bitmap is gewoon een simpel arrangement bytes. En ze zijn verklaard in dit bestand hier, bmp.h, met een stel informatie van wat een bitmap is eigenlijk gemaakt uit. Maar wat we echt zorgen over de bitmap-bestand header, hier, en de bitmap info header, hier. De header bestaat uit een paar variabelen die zeer nuttig zal blijken. Er is biSizeImage, de totale grootte van de afbeelding in bytes. En dit omvat pixels en opvulling. Padding is erg belangrijk, maar zullen we later op terug. BiWidth voor de breedte van de afbeelding in pixels minus de opvulling. BiHeight is dan ook de hoogte van de afbeelding in pixels. En dan de BITMAPFILEHEADER en de BITMAPINFOHEADER, zoals ik al zei eerder, die worden vertegenwoordigd als structs. Ja, kunt u geen toegang tot het bestand header zelf, maar je wilt krijgen deze variabelen binnen. OK. Dus hoe kunnen we een update van de header info? Nou, eerst moeten we zien of we moet alle informatie van veranderen de infile, de aanwijzing, het outfile, het vonnis. Is iets te veranderen in dit geval? Nou, eigenlijk niet, want we gaan gewoon veranderen de kleuren. We gaan niet naar het bestand te veranderen grootte, het beeldformaat, de breedte, of de hoogte. Dus je bent goed voor nu door gewoon kopiëren van elke pixel. OK. Dus laten we nu eens kijken hoe we eigenlijk kan elke pixel te lezen uit het bestand. Andere file I / O-functie zal komen in het spel - fread. Het neemt in een pointer naar de struct dat zal de bytes bevatten dat je leest. Dus je leest in die. En dan heb je pas in een grootte, die is de omvang van elk element dat u wilt lezen. Hier, de functie sizeof zal van pas komen. Dan pas je in getal, die geeft het aantal elementen van maat te lezen. En tenslotte, inptr, hetgeen de file pointer die je gaan lezen uit. Dus al die elementen zijn binnen inptr en ze gaan van gegevens. Laten we eens kijken naar een klein voorbeeld. Als ik wil lezen in data twee honden, Nou, ik kan het doen op twee manieren. Ik kan zowel lezen in twee objecten van grootte hond van mijn inptr, of ik kan lezen in een object de grootte van twee honden. Zo zie je maar dat afhankelijk van de manier waarop dat u regelen grootte en aantal, u lezen in hetzelfde aantal bytes. Dus nu, laten we veranderen de pixel kleur als we nodig hebben. Als je kijkt naar bmp.h weer, dan zie je dat aan de onderkant RGBTRIPLEs zijn een andere structuur, waar zij bestaan ​​uit drie bytes. Een, rgbtBlue, rgbtGreen en rgbtRed. Dus elk van deze is het bedrag blauw, de hoeveelheid groen en de hoeveelheid rood in deze pixel, waar elk bedrag wordt vertegenwoordigd door een hexadecimaal getal. Dus ff0000 zal een blauwe kleur, want het gaat van blauw, groen, rood. En dan zijn alle f's wit zijn. Laten we eens een kijkje nemen op smiley.bmp, die je hebt in je distributie code. Als je het in slechts een afbeelding te openen kijker, dan zult u net een rode smiley. Maar het nemen van een diepere duik in, we zullen zien dat de structuur van het is gewoon pixels. We hebben witte pixels, en dan de rode pixels. De witte, ffffff, en vervolgens alle rode pixels Ik heb ingekleurd hier, en je ziet dat ze 0000ff. Nul blauw, nul groen, en volle rode. En aangezien smiley is acht pixels breed, we hebben geen padding. Oke. Dus als ik verschillende waarden toekennen een RGBTRIPLE en ik wilde maken het groen, dan is wat ik zou doen is Ik zou een RGBTRIPLE, genaamd verklaren drievoud, en vervolgens elke toegang byte binnen deze structuur I zou de operator punt te gebruiken. Dus triple.rgbtBlue, ik kan toewijzen dat voor 0. Green I kan toewijzen aan volle - elke nummer, echt, tussen 0 en ff. En dan rood, ben ik ook gaan zeggen 0. Dus dan dat geeft me een groene pixel. Vervolgens, wat als ik wil controleren de waarde van iets? Ik kon iets dat de controles hebben of de triple's rgbtBlue waarde is ff en dan afdrukken, "Ik voel me blauw ", als resultaat. Nu, dat betekent niet noodzakelijkerwijs dat de pixel is blauw, toch? Omdat de pixel groene en rode waarden zou eveneens niet-0-waarden. Alles wat dit betekent, en dat alles dit is het controleren voor is voor een volledige blauwe kleur. Maar alle pixels kan ook gedeeltelijke kleurwaarden, zoals deze volgende voorbeeld hier. Het is een beetje moeilijker te zien wat dit beeld is nu. Dit ziet er een beetje meer op de clue.bmp dat je gegeven worden. Nu, fysiek, je zou dit op te lossen, omdat er veel rood, door houdt een rood scherm om het beeld zo dat de andere kleuren kunnen worden weergegeven. Dus hoe kunnen we nabootsen dit met c? Nou ja, kunnen we verwijder alle rood volledig uit het beeld. En zo te doen dat we elke zouden stellen roodwaarde pixel tot 0. En zo zou het beeld een beetje kijken beetje zoals dit, waar we hebben geen rode dan ook. We kunnen de verborgen boodschap een zien beetje meer nu duidelijk. Het is weer een smiley gezicht. Of misschien kunnen we een andere methode gebruiken. Misschien kunnen we identificeren alle rode pixels - dat wil zeggen alle pixels met 0 blauw, groen 0 en 0 rood - en verander die naar wit. En onze afbeelding ziet er misschien iets als dit. Een beetje makkelijker te zien. Er zijn veel andere manieren om te ontdekken de geheime boodschap ook, omgaan met de kleur manipulatie. Misschien heb je zou kunnen gebruiken een van de methoden die ik hierboven heb genoemd. En bovendien, wil je misschien sommige kleuren te verbeteren en brengen die uit. Dus nu dat we de pixel hebt veranderd kleur, volgende we hoeven alleen maar om ze te schrijven in de scanline, pixel voor pixel. En nog eens, wil je om terug te kijken naar copy.c, als je niet hebt gekopieerd het al, en kijk naar de fwrite functie, welke gegevens neemt, een pointer de structuur die de bytes bevat dat je het lezen van de omvang van de items, het aantal items, en vervolgens de outptr - de bestemming van die bestanden. Na het schrijven in de pixels, zul je ook te schrijven in de opvulling. Wat is padding? Nou, elke rgbt pixel drie bytes lang. Maar, het scanline voor een bitmapafbeelding moet een veelvoud van vier bytes. Als het aantal pixels is geen veelvoud van vier is, dan moeten we voegen deze padding. Padding is gewoon vertegenwoordigd door 0s. Dus, hoe kunnen we schrijven, of lezen dit? Nou, het blijkt dat je niet kunt eigenlijk fread padding, maar u kunt berekenen. In dit geval, de aanwijzing en de uitspraak dezelfde breedte, zodat de padding is hetzelfde. En de vulling, zoals u zult zien in copy.c, berekend met onderstaande formule - bi.biWidth tijden sizeof (RGBTRIPLE) zal geven ons hoeveel bytes de bmp heeft in elke rij. Van daar, de modulos en aftrekkingen met 4 kan berekenen hoe vele bytes worden toegevoegd zodat de veelvoud van bytes op elke rij vier. Nu dat we de formule voor hoeveel padding we nodig hebben, nu kunnen we het schrijven. Nu, ik eerder al noemde, padding is gewoon 0s. Dus in dat geval, we zomaar een char, in dit geval een 0, in onze outptr - onze outfile. Dus dat kan gewoon fputc zijn 0, komma outptr. Dus, terwijl we al lezen in onze bestand, heeft het dossier van I / O-spoor van hielden onze positie in die bestanden met iets riep het bestand positie-indicator. Zie het als een cursor. Kortom, het vooruit elke keer dat we fread, maar we hebben controle over het ook. Om het bestand positie-indicator verplaatsen, kunt u de functie fseek gebruiken. Wanneer de inptr voor de bestandsnaam pointer die je zoekt in, de bedrag is het aantal bytes dat u de cursor wilt verplaatsen, en vervolgens uit betrekking op het referentiepunt van waar de cursor is. Als je pas in SEEK_CUR, dat vertegenwoordigt de huidige positie in het bestand. Of u kunt gebruik maken van een aantal andere parameters. Dus, zouden we willen fseek gebruiken om over te slaan over de opvulling van de in het dossier. En nogmaals, als je vastzit, is er een voorbeeld van die in copy.c. Dus nu hebben we het bestand geopend, de aanwijzing, en het vonnis. We hebben de header info voor bijgewerkte ons oordeel, omdat elke bitmap moet een header. We hebben dan te lezen in de aanwijzing van scanline, pixel voor pixel, veranderen elke kleur nodig en het schrijven van die in de vonnis, pixel voor pixel. Zodra je uitspraak opent, kunt u zien wie de dader, of wat het geheim boodschap is. Mijn naam is Zamyla, en dit was whodunit.