1 00:00:00,506 --> 00:00:09,216 [ Silence ] 2 00:00:09,716 --> 00:00:12,336 >> Alright, hello everybody, welcome to the walkthrough 3 00:00:12,416 --> 00:00:17,116 for our problem set 5, our forensics pset, today's music 4 00:00:17,116 --> 00:00:19,576 and other mashup group, so I want to take this opportunity 5 00:00:19,576 --> 00:00:21,356 to thank everyone for filling out the feedback, 6 00:00:21,356 --> 00:00:23,096 particularly the walkthrough question. 7 00:00:23,336 --> 00:00:25,316 I learned that a lot of people don't like my taste 8 00:00:25,316 --> 00:00:26,686 in music and I'm sorry. 9 00:00:27,126 --> 00:00:30,276 I also learned that a lot of you would 10 00:00:30,276 --> 00:00:32,746 like to see more code examples and more syntax 11 00:00:32,746 --> 00:00:34,586 and have it be less conceptual and more like, 12 00:00:34,896 --> 00:00:37,256 here is like the code, what it kind of looks like what you need 13 00:00:37,256 --> 00:00:39,106 to type, and so keeping all that in mind, 14 00:00:39,106 --> 00:00:40,596 we'll try to do that moving forward. 15 00:00:40,596 --> 00:00:41,836 So that was really helpful and thanks 16 00:00:41,836 --> 00:00:43,026 for being honest on those. 17 00:00:44,226 --> 00:00:46,346 So, here is a list of things we'll be covering for today. 18 00:00:46,346 --> 00:00:49,726 So I should note that we'll see file I/O much more 19 00:00:49,726 --> 00:00:51,696 in lecture this week, lecture in section. 20 00:00:51,936 --> 00:00:54,346 And so if you're a little bit confused after the walkthrough 21 00:00:54,346 --> 00:00:56,446 like the finer details of the file I/O, 22 00:00:56,706 --> 00:00:59,016 don't worry all your questions will be answered this week 23 00:00:59,016 --> 00:00:59,946 in lecture in section. 24 00:01:00,746 --> 00:01:03,656 So, on the topic bitmaps and the different image types you'll see 25 00:01:03,656 --> 00:01:06,566 in this pset and then the four programs that you'll encounter 26 00:01:06,566 --> 00:01:08,316 as you're going through forensics. 27 00:01:08,936 --> 00:01:12,436 So file I/O, so this is the major overarching topic 28 00:01:12,436 --> 00:01:17,186 for pset 5, and file I/O is just a short for file input I 29 00:01:17,186 --> 00:01:20,496 and output, so input being I have some file 30 00:01:20,496 --> 00:01:23,086 and it contains some bytes and some text and whatever else, 31 00:01:23,366 --> 00:01:26,046 and I wanna read that in, I want my C program to be able 32 00:01:26,046 --> 00:01:28,476 to tell me what is inside of that file. 33 00:01:28,896 --> 00:01:30,516 Output on the other hand is saying, well, 34 00:01:30,516 --> 00:01:32,956 I want to create a file for my C program 35 00:01:32,956 --> 00:01:35,466 and I wanna write this sequence of bytes in this file 36 00:01:35,466 --> 00:01:37,816 and that could create an image, that could create a text file, 37 00:01:37,816 --> 00:01:38,986 that could create a Word document, 38 00:01:39,406 --> 00:01:41,476 at the core of these files, are just sequences of bytes 39 00:01:41,716 --> 00:01:43,356 and our programs can either read them in 40 00:01:43,606 --> 00:01:45,336 or they can write them out. 41 00:01:46,276 --> 00:01:48,056 So, when we open a file, 42 00:01:48,086 --> 00:01:51,336 every file that we open is gonna have an associated file 43 00:01:51,416 --> 00:01:52,456 position indicator. 44 00:01:52,456 --> 00:01:55,456 And this basically just like the little cursor, when you open 45 00:01:55,456 --> 00:01:58,006 up Microsoft Word, that says where am I 46 00:01:58,006 --> 00:01:59,166 in the file right now? 47 00:01:59,756 --> 00:02:02,616 So if I say I want to read some number of bytes 48 00:02:02,616 --> 00:02:05,616 or read some number of letters from my file, I'm gonna start 49 00:02:05,616 --> 00:02:08,976 at where my cursor is, I'm gonna read something like 4 bytes 50 00:02:08,976 --> 00:02:11,316 and the cursor's gonna move over 4 bytes. 51 00:02:11,786 --> 00:02:13,256 So, if I read another 4 bytes, 52 00:02:13,376 --> 00:02:14,826 I'm not just gonna get the same thing back 53 00:02:15,036 --> 00:02:17,606 because I already read that, I'm gonna read the next 4 bytes. 54 00:02:18,836 --> 00:02:21,366 So, the first thing we wanna do before we can do anything 55 00:02:21,366 --> 00:02:22,956 with our files is open them up. 56 00:02:23,446 --> 00:02:26,176 So, one of the functions we can use is fopen, 57 00:02:26,176 --> 00:02:29,166 so a lot of these functions are gonna start with F, F for file, 58 00:02:29,536 --> 00:02:32,766 so you can fopen a file, the first argument is going to be 59 00:02:32,766 --> 00:02:35,616 where the file is and the second argument is going 60 00:02:35,616 --> 00:02:37,556 to be what you want to do with the file. 61 00:02:38,036 --> 00:02:40,646 So in whodunit, you have this bitmap, it's called clue.bitmap 62 00:02:40,646 --> 00:02:42,996 and you don't wanna modify that at all. 63 00:02:43,076 --> 00:02:45,526 You don't wanna modify clue.bitmap, you wanna just read 64 00:02:45,526 --> 00:02:47,726 in the bytes, and do something with them. 65 00:02:48,486 --> 00:02:52,026 So that R just says I'm only going to be reading this file. 66 00:02:52,266 --> 00:02:54,086 R for read actually makes sense which is nice. 67 00:02:55,106 --> 00:02:57,886 So if you wanted to open a file to write to, this file may 68 00:02:57,886 --> 00:03:00,376 or may not exist yet, you would say, okay, I want some path, 69 00:03:00,646 --> 00:03:03,926 in this case, just verdict.bmp, which may, may not exist. 70 00:03:03,926 --> 00:03:06,736 If it doesn't exist yet, then C is gonna create it for you 71 00:03:06,736 --> 00:03:09,376 and this W says that I'm going to write to this file. 72 00:03:09,726 --> 00:03:11,196 I'm not gonna be reading any bytes for it, 73 00:03:11,196 --> 00:03:12,966 I'm just going to be writing to it. 74 00:03:14,136 --> 00:03:16,046 So now, how do we read those bytes? 75 00:03:16,526 --> 00:03:19,296 So we have a function fread or fread, file read, 76 00:03:19,296 --> 00:03:21,466 and it's gonna take 4 arguments. 77 00:03:21,936 --> 00:03:24,196 So the first of these arguments is going to be a pointer, 78 00:03:24,356 --> 00:03:27,186 and this could be a pointer to a struct, or to see later pointed 79 00:03:27,186 --> 00:03:29,256 to an array and this pointer, 80 00:03:29,256 --> 00:03:31,616 after you call fread is what's going 81 00:03:31,616 --> 00:03:34,096 to contain the data from your file. 82 00:03:34,696 --> 00:03:36,126 So the reason is be it pointers 83 00:03:36,126 --> 00:03:37,976 so that the function can actually modify 84 00:03:38,046 --> 00:03:40,906 that variable rather than making a copy of it 85 00:03:40,906 --> 00:03:42,286 and then you're not having it back. 86 00:03:42,466 --> 00:03:46,606 So fread is going to return what was read, it's going to put it 87 00:03:46,606 --> 00:03:47,766 into that first argument. 88 00:03:48,616 --> 00:03:51,126 So that second too are just basically how much do you want 89 00:03:51,126 --> 00:03:54,536 to read so it's basically going to read size times number, 90 00:03:55,026 --> 00:03:57,296 so you gonna read a block of size size 91 00:03:57,296 --> 00:04:00,696 which is just some integer and it's going to read some number 92 00:04:00,746 --> 00:04:02,786 of them, so that's pretty simple 93 00:04:02,786 --> 00:04:05,476 and the last one is just the file pointer 94 00:04:05,476 --> 00:04:07,776 which is what you get back, when you open, 95 00:04:07,966 --> 00:04:09,356 when you fopen some file. 96 00:04:09,896 --> 00:04:12,976 So this is a pointer to a file and that is what you're going 97 00:04:12,976 --> 00:04:16,116 to pass as the last argument to a function like fread. 98 00:04:16,686 --> 00:04:20,136 And so just remember that because these two, the second 99 00:04:20,136 --> 00:04:22,006 and third arguments are basically just multiplied 100 00:04:22,006 --> 00:04:24,716 together, you could say something like okay, 101 00:04:24,896 --> 00:04:27,616 I wanna read some RGBTRIPLE which is just some struct, 102 00:04:28,026 --> 00:04:32,556 I wanna read two of those into my data point, into my data. 103 00:04:32,786 --> 00:04:34,786 So there's just some struct, I'm gonna read it into data, 104 00:04:34,786 --> 00:04:35,756 I'm gonna read two of those. 105 00:04:36,146 --> 00:04:38,056 Or I can say, well, I'm gonna read one of them 106 00:04:38,236 --> 00:04:39,806 but it's two times the size of one, 107 00:04:39,886 --> 00:04:41,996 so both of those things are the same thing 'cause they're just 108 00:04:41,996 --> 00:04:44,016 multiplying together the second and third argument. 109 00:04:44,686 --> 00:04:46,596 So that's reading. 110 00:04:46,826 --> 00:04:48,796 Now for what you write to a file, we're gonna have a very, 111 00:04:48,796 --> 00:04:49,706 very similar function. 112 00:04:50,416 --> 00:04:53,646 So fwrite is going to take again, just a pointer 113 00:04:53,646 --> 00:04:55,246 to some data that we want to write, 114 00:04:55,776 --> 00:04:58,676 and now this last argument is no longer the file 115 00:04:58,676 --> 00:05:01,906 that we're reading in, but the file that we're reading out. 116 00:05:02,466 --> 00:05:04,416 So again, it's still just a pointer to a file, 117 00:05:04,546 --> 00:05:06,906 so that thing we get back and we call fopen, 118 00:05:06,906 --> 00:05:08,496 and this is what's going 119 00:05:08,496 --> 00:05:10,636 to actually write whatever is contained 120 00:05:10,636 --> 00:05:12,296 within the struct to the file. 121 00:05:13,106 --> 00:05:14,156 So if we don't wanna write a byte 122 00:05:14,156 --> 00:05:16,706 but we wanna just write a single character instead, 123 00:05:16,706 --> 00:05:19,136 we can use anther function called fputc, 124 00:05:19,136 --> 00:05:21,656 and this as its data argument is just going 125 00:05:21,656 --> 00:05:23,466 to take a single character or a char. 126 00:05:23,626 --> 00:05:26,866 So you could just say fputc a in single quotes, 127 00:05:27,196 --> 00:05:29,616 and then the outpointer is still that file pointer 128 00:05:29,616 --> 00:05:31,386 that you got back when you called fopen. 129 00:05:31,526 --> 00:05:35,396 So there are many more functions to read and write strings 130 00:05:35,396 --> 00:05:37,986 from files or bytes from files, but these are the ones 131 00:05:37,986 --> 00:05:39,406 that you'll see on this pset. 132 00:05:39,516 --> 00:05:41,826 So any questions on how those are working? 133 00:05:42,316 --> 00:05:42,446 Yup? 134 00:05:42,726 --> 00:05:44,726 [ Inaudible Remark ] 135 00:05:45,006 --> 00:05:54,256 >> Okay sure, so, let's take a look at an example. 136 00:05:55,426 --> 00:05:57,716 Aha, so here we have some struct, 137 00:05:58,326 --> 00:06:00,266 and so I've just called this struct quad 138 00:06:00,266 --> 00:06:02,236 because it's gonna read in four letters. 139 00:06:02,556 --> 00:06:05,536 So notice that inside this struct I have essentially 4 140 00:06:05,536 --> 00:06:09,166 bytes, right, I have one for the first, this first char, second, 141 00:06:09,166 --> 00:06:10,876 and then I have a two byte array. 142 00:06:12,016 --> 00:06:14,476 So I can fill up this struct with 4 bytes, right, 143 00:06:14,476 --> 00:06:17,826 because each of these members is effectively one byte. 144 00:06:18,736 --> 00:06:22,016 So now, the fist thing I'm gonna do is open up my file. 145 00:06:22,336 --> 00:06:23,706 So I just have some file, 146 00:06:23,856 --> 00:06:25,936 it's called text.txt-- question first? 147 00:06:25,936 --> 00:06:27,506 >> Can you explain what typedef is? 148 00:06:27,916 --> 00:06:30,376 >> Oh sure, so can you explain what typedef is? 149 00:06:30,376 --> 00:06:32,706 So again, this is something that we'll see more 150 00:06:32,706 --> 00:06:34,706 in section this week, but this is just kind 151 00:06:34,706 --> 00:06:36,546 of an idiomatic way of creating a struct. 152 00:06:37,006 --> 00:06:39,596 This is how that your struct in pset 4 was declared. 153 00:06:39,856 --> 00:06:41,456 We saw a typedef struct board 154 00:06:41,456 --> 00:06:43,816 and then we call it G. This is just kind 155 00:06:43,816 --> 00:06:46,876 of an idiomatic syntactical way of declaring a struct, 156 00:06:46,876 --> 00:06:49,016 but basically what that does is it allows us 157 00:06:49,016 --> 00:06:51,476 to say later on quad letters. 158 00:06:51,476 --> 00:06:53,356 So I have a struct, its type is quad. 159 00:06:53,846 --> 00:06:55,046 If I didn't have this typedef, 160 00:06:55,046 --> 00:06:56,866 I'll have to say struct quad letters, 161 00:06:56,946 --> 00:06:58,176 which is more annoying to type. 162 00:06:58,696 --> 00:07:01,346 So, more about typedef in section, but this is just kind 163 00:07:01,346 --> 00:07:03,486 of the formula for creating a struct so I don't have 164 00:07:03,516 --> 00:07:06,346 to say struct quad every time I can just say quad. 165 00:07:07,716 --> 00:07:11,766 Other questions to the fopen? 166 00:07:11,766 --> 00:07:13,196 Okay, I really like pronouncing this, 167 00:07:13,316 --> 00:07:14,356 so sorry if that's annoying. 168 00:07:15,546 --> 00:07:19,226 So now, we know that this file is going to contain 12 bytes, 169 00:07:19,276 --> 00:07:20,746 just because I already wrote the file 170 00:07:21,066 --> 00:07:22,736 and that's how many letter it has. 171 00:07:23,066 --> 00:07:26,586 So it of course just says this is CS50 which is 12 characters. 172 00:07:26,766 --> 00:07:28,026 Each character is a single byte. 173 00:07:28,266 --> 00:07:28,986 This is 4. 174 00:07:28,986 --> 00:07:31,906 The space plus is another 4 and then CS50 makes 12. 175 00:07:32,376 --> 00:07:34,496 So we know how big this file is, and in the bitmaps 176 00:07:34,496 --> 00:07:35,886 that we're gonna be working with, 177 00:07:35,886 --> 00:07:38,516 we're also gonna know exactly how big they are before we 178 00:07:38,516 --> 00:07:39,036 do anything. 179 00:07:39,666 --> 00:07:40,606 So more on that later. 180 00:07:40,606 --> 00:07:44,536 But so now we're going to read 3 times, right, 181 00:07:44,536 --> 00:07:48,596 because our struct can hold 4 bytes, we have 4 one byte slots 182 00:07:48,596 --> 00:07:49,826 that we could read things into. 183 00:07:50,036 --> 00:07:51,346 So if we read 3 times, 184 00:07:51,636 --> 00:07:53,056 that means we're gonna read the whole file 185 00:07:53,056 --> 00:07:55,446 and I'm gonna get back 3 total structs. 186 00:07:56,466 --> 00:07:58,736 So the first thing I need to do is create a struct 187 00:07:58,736 --> 00:07:59,776 that I can fill with data. 188 00:08:00,296 --> 00:08:02,396 So this quad letter just says create a new struct, 189 00:08:02,776 --> 00:08:05,266 put it on the stack and it's gonna be an instance 190 00:08:05,546 --> 00:08:06,836 of this struct up here. 191 00:08:07,186 --> 00:08:09,946 So now I have some struct called letters, and inside of letters, 192 00:08:09,946 --> 00:08:13,026 I have letters.first, letters.second, and so on. 193 00:08:13,496 --> 00:08:18,466 So now when I say fread, I'm saying okay, I'm wanting to read 194 00:08:18,466 --> 00:08:20,556 into this variable or into the address 195 00:08:20,556 --> 00:08:22,856 of this variable the first 4 bytes. 196 00:08:23,346 --> 00:08:25,436 And how does I-- how did I specify 4 bytes? 197 00:08:25,766 --> 00:08:28,846 Well, I said, I want you to read one times the size 198 00:08:28,846 --> 00:08:32,986 of that single struct because that struct has 2 characters 199 00:08:32,986 --> 00:08:34,946 in a one 2-character array, that's 4 bytes, 200 00:08:35,296 --> 00:08:41,156 that means I'm reading in 4 characters into the struct. 201 00:08:41,306 --> 00:08:45,806 Question? Okay, so now that I've read my data from the file, 202 00:08:46,086 --> 00:08:49,846 these struct letters that's just a variable contains data 203 00:08:49,936 --> 00:08:50,366 from the file. 204 00:08:50,996 --> 00:08:53,236 So in this case it's going to contain the letters 205 00:08:53,516 --> 00:08:55,186 that I specified in my text file. 206 00:08:55,616 --> 00:08:58,576 So now when I just printf letters.first, 207 00:08:59,046 --> 00:09:02,686 I know that letters.first is a char because I said up here 208 00:09:02,686 --> 00:09:05,556 in the definition of my struct that it's going to be a char, 209 00:09:06,096 --> 00:09:09,746 and so I can just print out percent C for a character, 210 00:09:10,526 --> 00:09:11,866 so then I can print out the first, 211 00:09:11,866 --> 00:09:14,496 I can print out the second, and now I had an array 212 00:09:14,496 --> 00:09:16,796 from my third one so I can iterate through that array 213 00:09:16,796 --> 00:09:18,466 and print out each character. 214 00:09:18,916 --> 00:09:24,706 So if I run this on this file, just text.txt, and I run this, 215 00:09:24,706 --> 00:09:28,356 I can say make I/O, I can run I/O, 216 00:09:28,356 --> 00:09:31,146 I'm gonna get back just this is CS50, 217 00:09:31,776 --> 00:09:33,796 'cause I just read 4 characters at a time 218 00:09:34,026 --> 00:09:36,526 and after each 4 characters, I output a new line. 219 00:09:37,806 --> 00:09:40,276 So questions on how we're reading that text file 220 00:09:40,616 --> 00:09:42,006 into a struct and outputting them 221 00:09:42,006 --> 00:09:44,466 after we've filled up the struct? 222 00:09:44,976 --> 00:09:45,056 Yeah? 223 00:09:45,056 --> 00:09:46,916 [ Inaudible Remark ] 224 00:09:46,916 --> 00:09:51,706 >> How does it go to the next-- 225 00:09:51,706 --> 00:09:52,996 how does it know to go to the next line? 226 00:09:53,026 --> 00:09:54,326 My output? 227 00:09:54,326 --> 00:09:56,076 [ Inaudible Remark ] 228 00:09:56,076 --> 00:09:58,856 >> So my reader, so how does it know to go to the next line? 229 00:09:58,856 --> 00:10:02,266 So in this case, I only have one line of text, right, 230 00:10:02,266 --> 00:10:03,816 it just says this is CS50. 231 00:10:04,316 --> 00:10:07,736 >> So when I call fread, I'm not really concerned about lines, 232 00:10:08,246 --> 00:10:11,446 all I've told this function is I said I want you 233 00:10:11,446 --> 00:10:12,966 to go get 4 bytes. 234 00:10:13,856 --> 00:10:15,996 So fread says, okay, I'm gonna start at the beginning 235 00:10:15,996 --> 00:10:17,826 of the file, because you haven't done anything yet, 236 00:10:17,826 --> 00:10:24,276 and it's gonna say, I'm gonna read 1, 2, 3, 4, just these. 237 00:10:25,056 --> 00:10:28,756 So now the next time I call fread, you notice that my cursor 238 00:10:28,896 --> 00:10:31,126 where that file position indicator is now 239 00:10:31,366 --> 00:10:32,796 after the word this. 240 00:10:33,356 --> 00:10:36,326 So when I call fread again, it's gonna go 1, 2, 3, 241 00:10:36,326 --> 00:10:39,536 4 and I just read a different 4 characters. 242 00:10:40,136 --> 00:10:40,706 Does that make sense? 243 00:10:41,786 --> 00:10:42,456 Other questions? 244 00:10:43,226 --> 00:10:43,416 Yeah? 245 00:10:43,416 --> 00:10:43,636 [ Inaudible Remark ] 246 00:10:43,636 --> 00:10:48,256 >> So are those 4 characters getting put somewhere? 247 00:10:48,476 --> 00:10:50,946 So they're getting put into my struct 248 00:10:51,386 --> 00:10:54,556 because my struct contains spaces for those characters, 249 00:10:54,556 --> 00:10:57,046 in this case two variables and then an array. 250 00:10:57,856 --> 00:10:59,856 So it's just getting put into in order, 251 00:10:59,856 --> 00:11:01,426 the first thing is getting read, its' getting put 252 00:11:01,426 --> 00:11:03,816 into letters.first, and then letters.second, 253 00:11:03,816 --> 00:11:05,666 and then it's gonna fill up that array 254 00:11:05,906 --> 00:11:07,396 with the last two letters that it reads. 255 00:11:08,216 --> 00:11:10,296 So now I can access those letters. 256 00:11:10,596 --> 00:11:11,926 Even though I haven't, it doesn't look 257 00:11:11,926 --> 00:11:14,306 like I've actually modified this struct called letters, 258 00:11:14,566 --> 00:11:17,646 but I have because fread changed its contents. 259 00:11:17,786 --> 00:11:20,196 So now when I say letters.first, I'm actually getting data 260 00:11:20,196 --> 00:11:26,016 from the file, because it's now inside of the struct. 261 00:11:28,096 --> 00:11:32,156 Yes, in the front. 262 00:11:32,156 --> 00:11:32,236 [ Inaudible Remark ] 263 00:11:32,236 --> 00:11:35,036 >> So, okay-- so, it says read data into struct 264 00:11:35,036 --> 00:11:36,346 and then here it says FP. 265 00:11:36,586 --> 00:11:39,386 So remember the arguments to fread. 266 00:11:39,976 --> 00:11:42,736 So we had the data of the size of the number 267 00:11:42,736 --> 00:11:44,006 and then this input pointer. 268 00:11:44,606 --> 00:11:47,376 Remember this input pointer is whatever we got back 269 00:11:47,786 --> 00:11:50,166 when we said fopen, because this is going 270 00:11:50,166 --> 00:11:52,186 to return a pointer to a file. 271 00:11:53,026 --> 00:11:57,406 Now in my code, I didn't call it inptr, I just called it FP, 272 00:11:57,406 --> 00:11:59,966 I called fopen and it returned a portion to a file, 273 00:12:00,266 --> 00:12:03,586 so now when I tell fread to use FP for file pointer, 274 00:12:03,586 --> 00:12:05,876 I need to go to the file that I opened up there. 275 00:12:05,966 --> 00:12:08,166 Does that make sense? 276 00:12:09,236 --> 00:12:09,886 Other questions? 277 00:12:10,116 --> 00:12:10,306 Yeah. 278 00:12:10,306 --> 00:12:10,373 [ Inaudible Remark ] 279 00:12:10,373 --> 00:12:16,566 >> So how does it know to read 4 characters at a time? 280 00:12:16,696 --> 00:12:18,946 So remember these second two arguments 281 00:12:18,946 --> 00:12:21,036 to fread are how much you want to read. 282 00:12:21,576 --> 00:12:23,906 So size of-- when I take the size of a struct, 283 00:12:24,256 --> 00:12:25,666 what it's basically gonna do is add 284 00:12:25,856 --> 00:12:27,626 up everything that's inside of the struct. 285 00:12:27,996 --> 00:12:30,556 So inside of the struct, I have 4 characters. 286 00:12:30,856 --> 00:12:32,776 So it says, okay, each of these characters is 1 byte, 287 00:12:33,046 --> 00:12:35,306 now I have 4 when I say size of quad. 288 00:12:35,786 --> 00:12:38,976 So because I passed in that 4 and I passed in a 1 289 00:12:38,976 --> 00:12:41,196 for the third argument, 1 times 4 is just 4, 290 00:12:41,566 --> 00:12:48,486 fread says I just want 4 bytes in that file at a time. 291 00:12:48,486 --> 00:12:48,656 [ Inaudible Remark ] 292 00:12:48,656 --> 00:12:50,816 >> So how do we know that-- how do we know to do it 3 times? 293 00:12:50,816 --> 00:12:52,616 Well notice I'm calling it here in a loop. 294 00:12:52,866 --> 00:12:54,496 I said for I is less than length, 295 00:12:54,496 --> 00:12:56,346 and this is just something that I defined 296 00:12:56,346 --> 00:12:57,546 at the top of my file, S3. 297 00:12:57,546 --> 00:13:00,446 So it's gonna repeat this process 3 times, 298 00:13:00,446 --> 00:13:01,626 and every time it repeats, 299 00:13:01,946 --> 00:13:03,846 it's gonna print a new line at the end. 300 00:13:04,666 --> 00:13:07,366 That wasn't too clear on, but that's why it's going 3 times. 301 00:13:09,016 --> 00:13:13,786 Other questions on reading into structs? 302 00:13:13,886 --> 00:13:18,386 Okay, so we can also manipulate this cursor or where we are 303 00:13:18,386 --> 00:13:21,206 in the file without explicitly reading or writing. 304 00:13:21,636 --> 00:13:23,286 So when we read and write, we're gonna be moving 305 00:13:23,286 --> 00:13:25,436 over automatically, but if you wanna move it 306 00:13:25,436 --> 00:13:27,786 over to some position without necessarily reading 307 00:13:27,786 --> 00:13:30,706 or writing bytes, we have this handy function called fseek 308 00:13:30,706 --> 00:13:33,416 and the arguments are kind of annoyingly in a different order, 309 00:13:33,916 --> 00:13:35,786 but the first one is just the file. 310 00:13:36,246 --> 00:13:39,066 So if FP or inptr, whatever you wanna call it, 311 00:13:39,066 --> 00:13:41,976 and then we can say, well, I want you to just move 312 00:13:41,976 --> 00:13:44,906 over something like 8 bytes or 16 bytes, I don't want you 313 00:13:44,906 --> 00:13:46,976 to read the data, I just want you to move over, 314 00:13:46,976 --> 00:13:48,476 so the next time that I read the data, 315 00:13:48,866 --> 00:13:49,986 you're gonna read somewhere else. 316 00:13:50,086 --> 00:13:53,156 So this last argument just says that this offset, 317 00:13:53,526 --> 00:13:55,666 this amount to move the cursor, is that starting 318 00:13:55,666 --> 00:13:57,256 from the beginning of the file, is that starting 319 00:13:57,256 --> 00:14:00,586 from where you are right now, and so that's just gonna-- 320 00:14:00,586 --> 00:14:03,596 you can change how you're manipulating the cursor based 321 00:14:03,596 --> 00:14:04,636 on that third argument. 322 00:14:05,696 --> 00:14:07,376 So questions on how fseek works? 323 00:14:07,926 --> 00:14:13,056 So again, more info in lecture in section this week, 324 00:14:14,006 --> 00:14:16,296 but that is basic file I/O. 325 00:14:16,296 --> 00:14:16,666 Yup? 326 00:14:17,516 --> 00:14:23,446 [ Inaudible Remark ] 327 00:14:23,946 --> 00:14:26,376 >> So when you do fwrite, is that when you wanna write 328 00:14:26,376 --> 00:14:27,466 from a struct to a file? 329 00:14:27,466 --> 00:14:29,486 Exactly, that's exactly what you wanna do. 330 00:14:29,486 --> 00:14:33,126 This data is what's going to go into the file that you specified 331 00:14:33,126 --> 00:14:35,076 in outpointer, or before whatever is 332 00:14:35,076 --> 00:14:37,646 in the file is going into the struct. 333 00:14:40,866 --> 00:14:43,176 Other last questions on file I/O functions? 334 00:14:43,176 --> 00:14:48,016 Okay, so now in this case, we just used a text file, 335 00:14:48,306 --> 00:14:52,306 because it's easy to see exactly what we are reading, 336 00:14:52,306 --> 00:14:53,836 we are just reading 1 byte letters. 337 00:14:54,216 --> 00:14:56,506 On this pset you're gonna be working with images, 338 00:14:56,506 --> 00:14:58,886 where it sounds really scary because an image, you know, 339 00:14:58,886 --> 00:15:00,886 you can't just open up an image and get it and be able 340 00:15:00,886 --> 00:15:01,956 to figure out what's going on. 341 00:15:02,266 --> 00:15:04,266 But an image is just a sequence of bytes 342 00:15:04,266 --> 00:15:06,506 and a text file is just a sequence of bytes. 343 00:15:06,606 --> 00:15:08,736 So they're really not treated any differently 344 00:15:08,736 --> 00:15:09,696 as far as you're concerned. 345 00:15:09,696 --> 00:15:11,166 So it might be a little intimidating, 346 00:15:11,166 --> 00:15:12,926 but it's really not, they're just a sequence of bytes 347 00:15:12,926 --> 00:15:14,956 and that's all we're concerned about, is what are these bytes 348 00:15:14,956 --> 00:15:15,886 and what can we do with them. 349 00:15:16,926 --> 00:15:21,896 So inside of a 24 bitmap, each pixel under that map is going 350 00:15:21,896 --> 00:15:25,446 to represent it by 3 bytes and those 3 bytes are going 351 00:15:25,446 --> 00:15:27,936 to describe the amounts of blue in the pixel, 352 00:15:27,936 --> 00:15:31,206 the amount of green and the amount of red in that order. 353 00:15:31,596 --> 00:15:33,116 So let's take a look at some examples 354 00:15:33,116 --> 00:15:34,886 of how we can make bitmap colors. 355 00:15:35,056 --> 00:15:38,126 So, we're gonna divide each number into 3 parts, 356 00:15:38,236 --> 00:15:40,156 so the blue part, the green part, and the red part. 357 00:15:40,546 --> 00:15:42,936 So if we have something like 0000ff, 358 00:15:43,396 --> 00:15:45,986 that says we have no blue, because the blue is 0, 359 00:15:46,186 --> 00:15:48,716 we have 0 green, we have a lot of red 360 00:15:48,876 --> 00:15:51,336 because ff is the biggest number we can represent 361 00:15:51,336 --> 00:15:52,516 with 2 hexadecimal digits. 362 00:15:52,986 --> 00:15:56,246 So if I have this number, that's going to be a red pixel. 363 00:15:56,856 --> 00:16:00,166 And f on the other hand, we had no blue, so that's 00, 364 00:16:00,166 --> 00:16:02,236 but we had a lot of green and red, 365 00:16:02,236 --> 00:16:05,166 and those two are gonna combine to form yellow, 366 00:16:05,166 --> 00:16:07,916 because if you add a lot of red, and a lot of green, 367 00:16:07,916 --> 00:16:09,966 then you're gonna get a purely yellow pixel. 368 00:16:10,766 --> 00:16:14,376 So now these numbers don't just have to be either 00 or ff, 369 00:16:14,866 --> 00:16:17,946 but they can really be anything on a scale of 0 to 255. 370 00:16:18,586 --> 00:16:22,026 So if you had 3c which is, you know, some blue, 371 00:16:22,116 --> 00:16:25,766 14 just a little bit of green, and then dc which is a lot red, 372 00:16:25,766 --> 00:16:27,206 a lot more red compared to that 373 00:16:27,206 --> 00:16:29,426 and that's how you form a color like crimson. 374 00:16:30,736 --> 00:16:33,406 So now, how are we gonna represent that inside seek? 375 00:16:34,126 --> 00:16:38,146 So we've written for you inside of bmp.h this struct 376 00:16:38,456 --> 00:16:40,126 and it's called RGBTRIPLE. 377 00:16:40,126 --> 00:16:42,196 So if you wanted to create a new one, 378 00:16:42,286 --> 00:16:44,296 you could just say RGBTRIPLE triple, 379 00:16:44,736 --> 00:16:46,996 and now you have a variable called triple, 380 00:16:46,996 --> 00:16:50,216 and its type is this struct that we wrote for you. 381 00:16:51,036 --> 00:16:54,466 Now inside of the struct are 3 bytes, so each filled 382 00:16:54,466 --> 00:16:56,406 with just a single byte, 'cause now remember 383 00:16:56,406 --> 00:16:57,776 that we represented the amount 384 00:16:57,776 --> 00:16:59,536 of each color with a single byte. 385 00:17:00,436 --> 00:17:03,346 So now if you wanted to create that red pixel we saw, 386 00:17:03,346 --> 00:17:06,786 that 0000ff, we could say, well the amount 387 00:17:06,786 --> 00:17:11,266 of blue is gonna be 0x00, amount of green is 0, but the amount 388 00:17:11,266 --> 00:17:12,906 of red is going to be ff. 389 00:17:13,606 --> 00:17:16,826 So this rgbt is just red, green, blue triple 390 00:17:16,826 --> 00:17:18,586 and this is something that we wrote for you. 391 00:17:18,586 --> 00:17:21,086 If you wanna take a look at it, it's just in bmp.h. 392 00:17:21,446 --> 00:17:24,576 And so this is how we would literally construct the pixel 393 00:17:24,576 --> 00:17:26,336 inside of C if you wanted 394 00:17:26,336 --> 00:17:31,246 to create a red pixel for our bitmap. 395 00:17:31,306 --> 00:17:34,806 So, we're also concerned, about padding, and this is just kind 396 00:17:34,806 --> 00:17:37,536 of a nuance to the bitmap file format. 397 00:17:38,036 --> 00:17:41,166 So the bitmap file specification that says if you want a bitmap, 398 00:17:41,166 --> 00:17:42,366 it better look like this. 399 00:17:42,686 --> 00:17:46,156 It says that the size of each of your scan lines, 400 00:17:46,156 --> 00:17:49,546 or just like a single line of horizontal pixels in your image, 401 00:17:49,896 --> 00:17:53,256 the size of that better be a multiple of 4 bytes, 402 00:17:53,956 --> 00:17:55,906 or else just-- you can't just let it bitmap. 403 00:17:57,146 --> 00:18:00,666 Remember that each pixel is going to be 3 bytes. 404 00:18:01,936 --> 00:18:03,716 So if the number of pixels in the line-- 405 00:18:03,716 --> 00:18:07,086 in your line times 3 because there are 3 bytes per pixel, 406 00:18:07,316 --> 00:18:11,546 is not a multiple of 4, then we need to add some padding, 407 00:18:11,546 --> 00:18:15,346 and this padding is literally just some empty data that says, 408 00:18:15,346 --> 00:18:17,616 okay, this data is not really part of the image, 409 00:18:17,906 --> 00:18:20,996 but because bitmap tells us so, we need to make sure 410 00:18:20,996 --> 00:18:24,796 that every line has a number of bytes that is a multiple of 4, 411 00:18:25,606 --> 00:18:26,926 so in this case, what we do 412 00:18:26,926 --> 00:18:28,716 in copy.c [phonetic] is we literally just put 413 00:18:28,716 --> 00:18:32,346 in some extra zeroes, so we had something like 7 bytes 414 00:18:32,406 --> 00:18:34,586 which isn't right because we needed to have 8 415 00:18:34,586 --> 00:18:36,236 so we can just add in a couple of zeroes 416 00:18:36,236 --> 00:18:38,476 and now we created a line of 8 bytes. 417 00:18:39,486 --> 00:18:41,756 So we've given you this handy dandy formula 418 00:18:42,216 --> 00:18:44,626 to calculate the number of padding based 419 00:18:44,626 --> 00:18:46,756 on some width of width pixels. 420 00:18:47,256 --> 00:18:51,026 So if you have a width of 1 pixel, we know that the size 421 00:18:51,026 --> 00:18:55,666 of each-- the size of each byte is gonna be 1 byte 422 00:18:55,666 --> 00:18:58,526 and then the-- so the size of each pixel is gonna be 3 bytes. 423 00:18:59,186 --> 00:19:02,696 So if we have a 1 pixel image, that means we have 3 bytes. 424 00:19:03,806 --> 00:19:07,496 So that means we need 1 byte of padding, because we need to have 425 00:19:07,496 --> 00:19:08,686 to be able to pull up 4. 426 00:19:08,866 --> 00:19:10,786 If we have 3 bytes and we need 4 bytes, 427 00:19:10,786 --> 00:19:13,206 can we just add 1 extra byte of padding? 428 00:19:14,396 --> 00:19:17,086 So if instead we had an image that's 2 pixels wide, 429 00:19:17,596 --> 00:19:21,596 so now we have 2 times 3, that's 6, now we need to make that 8, 430 00:19:21,596 --> 00:19:24,396 because 8 is the nearest multiple of 4, we need 2 bytes 431 00:19:24,396 --> 00:19:26,586 of padding, and so on and so forth. 432 00:19:26,586 --> 00:19:28,736 And this formula, what we've given 433 00:19:28,736 --> 00:19:32,436 to you can just take some image of any width and it's kind 434 00:19:32,436 --> 00:19:35,286 of spit back the number of bytes of padding 435 00:19:35,656 --> 00:19:39,596 that you're gonna need to make each line a multiple of 4. 436 00:19:39,686 --> 00:19:39,966 Question? 437 00:19:40,516 --> 00:19:47,996 [ Inaudible Remark ] 438 00:19:48,496 --> 00:19:51,076 >> So why are we taking 4 bytes of space 439 00:19:51,076 --> 00:19:52,056 in the previous example? 440 00:19:52,056 --> 00:19:52,496 [ Inaudible Remark ] 441 00:19:52,496 --> 00:20:00,626 >> So why are we-- so in this case we're actually taking 3 442 00:20:00,626 --> 00:20:04,006 at a time, right, because each pixel is going to be 3 bytes 443 00:20:04,716 --> 00:20:07,436 and so inside of the struct we have fields 444 00:20:07,436 --> 00:20:08,976 that are going to fit 3 bytes. 445 00:20:09,636 --> 00:20:11,716 So, we only wanna read enough data that fits 446 00:20:11,716 --> 00:20:12,746 into the struct, okay? 447 00:20:12,746 --> 00:20:14,296 We don't wanna try to read too much data 448 00:20:14,296 --> 00:20:15,746 and then it's not gonna fit in our struct. 449 00:20:16,116 --> 00:20:18,766 So because our struct can handle 3 bytes, 450 00:20:18,826 --> 00:20:21,306 we wanna read in 3 bytes at a time. 451 00:20:21,836 --> 00:20:21,976 Yeah? 452 00:20:22,516 --> 00:20:27,516 [ Inaudible Remark ] 453 00:20:28,016 --> 00:20:30,306 >> So in our-- so in our previous example we had 454 00:20:30,306 --> 00:20:32,756 basically the same deal, so-- and then-- 455 00:20:32,756 --> 00:20:33,796 and when we're working with bitmaps, 456 00:20:34,406 --> 00:20:37,726 this RGBTRIPLE has space for 3 bytes but the one 457 00:20:37,726 --> 00:20:40,086 that I created has space for 4 bytes. 458 00:20:40,756 --> 00:20:42,456 We have 1, 2, 3, 4 characters 459 00:20:42,536 --> 00:20:44,096 because the last one is basically 2. 460 00:20:45,356 --> 00:20:46,726 So, we don't wanna read in 3 461 00:20:46,726 --> 00:20:48,376 because we're just gonna be wasting the character 462 00:20:48,376 --> 00:20:51,666 so we can fill up this entire 4 byte struct. 463 00:20:54,066 --> 00:20:55,016 Other questions? 464 00:20:55,556 --> 00:20:59,476 Okay, so those are our-- 465 00:20:59,476 --> 00:21:02,126 how we're gonna be representing each pixel. 466 00:21:02,556 --> 00:21:03,956 Don't forget about padding. 467 00:21:04,236 --> 00:21:06,136 If you're confused about the formula, you can just kind 468 00:21:06,136 --> 00:21:09,316 of run it through any width and it's gonna handle any case 469 00:21:09,316 --> 00:21:11,826 that you need to throw at it. 470 00:21:12,086 --> 00:21:15,276 So, now unfortunately we have more in our bitmap file. 471 00:21:15,276 --> 00:21:15,826 Question first? 472 00:21:16,076 --> 00:21:20,686 >> Why are you doing modulus twice on the previous formula? 473 00:21:20,756 --> 00:21:23,056 >> So, why are we doing modulus twice on this formula? 474 00:21:23,596 --> 00:21:28,356 So, when we say, if we just say width times size of byte mod 4, 475 00:21:28,786 --> 00:21:32,096 that's gonna give us the number of pixels away we are. 476 00:21:32,726 --> 00:21:37,436 So if we subtract that from 4 then we get them out of padding. 477 00:21:37,926 --> 00:21:39,666 But in the case that that's somehow negative, 478 00:21:39,666 --> 00:21:41,746 then we can just mod 4 it and make sure that we wrap 479 00:21:41,746 --> 00:21:42,986 around 2 positive numbers. 480 00:21:43,346 --> 00:21:46,816 So, this formula might be overly simplified a bit 481 00:21:46,856 --> 00:21:48,366 but this is just the one that we gave you. 482 00:21:48,406 --> 00:21:50,436 So, it's gonna make sure that it never turns something 483 00:21:50,436 --> 00:21:53,266 like a negative number or something like that. 484 00:21:56,506 --> 00:21:57,876 Other questions? 485 00:22:01,216 --> 00:22:05,046 Okay, so in addition to all of our pixels 486 00:22:05,046 --> 00:22:06,746 and the padding that's included in each line, 487 00:22:07,136 --> 00:22:10,266 we have this special block of information at the beginning 488 00:22:10,266 --> 00:22:13,206 of our bitmap and it looks just like this, we're dividing it 489 00:22:13,206 --> 00:22:16,506 into 2 parts, the first is the file header. 490 00:22:16,506 --> 00:22:19,876 Most importantly it's gonna say how big is my image, 491 00:22:20,396 --> 00:22:22,086 and then after that we just have some info 492 00:22:22,086 --> 00:22:25,516 about the bitmap itself like the compression or the width 493 00:22:25,516 --> 00:22:27,876 and height of the actual image. 494 00:22:28,756 --> 00:22:30,326 And so these are the ones that you're really, 495 00:22:30,326 --> 00:22:31,236 really concerned about. 496 00:22:31,536 --> 00:22:33,926 So, from that BITMAPFILEHEADER, you're concerned 497 00:22:33,926 --> 00:22:35,516 about the total size of the image. 498 00:22:35,866 --> 00:22:39,276 So this is given in bytes and this includes the header, 499 00:22:39,446 --> 00:22:42,186 it includes the pixels, it includes all the padding bytes. 500 00:22:42,186 --> 00:22:45,106 So, this is how many bytes is your image total. 501 00:22:45,496 --> 00:22:47,476 And this needs to be set correctly, all of this need 502 00:22:47,476 --> 00:22:50,596 to be set correctly in order for whatever program is reading 503 00:22:50,596 --> 00:22:52,886 and displaying your bitmap to display it correctly. 504 00:22:53,246 --> 00:22:55,186 Because if these are set wrong, then it's gonna try 505 00:22:55,186 --> 00:22:56,256 to read the bytes in the wrong-- 506 00:22:56,566 --> 00:22:58,586 read the wrong amount of bytes per line or something 507 00:22:58,586 --> 00:22:59,786 and your image isn't gonna look right. 508 00:23:00,556 --> 00:23:03,306 So, from the second part, this BITMAPINFOHEADER, 509 00:23:03,306 --> 00:23:05,556 which contains information about the image itself, 510 00:23:06,016 --> 00:23:08,896 you're concerned about the size which is still the total size 511 00:23:08,896 --> 00:23:10,796 of the image which includes pixels and padding 512 00:23:11,046 --> 00:23:13,596 and they're also concerned about the width and the height now 513 00:23:13,596 --> 00:23:15,386 which is the width of the image in pixels 514 00:23:15,386 --> 00:23:16,616 which it does not include padding, 515 00:23:16,616 --> 00:23:17,826 and then the height of the image. 516 00:23:18,616 --> 00:23:20,536 So, when you're modifying any images, 517 00:23:20,536 --> 00:23:23,296 if you're doing something like resizing it maybe, 518 00:23:23,296 --> 00:23:26,676 you need to make sure that before you do anything, 519 00:23:26,926 --> 00:23:28,646 you change these fields. 520 00:23:29,696 --> 00:23:33,926 So, these again are just structs that we created for you, 521 00:23:33,926 --> 00:23:37,646 they're inside the file bmp.h, which you can look up, 522 00:23:38,016 --> 00:23:39,486 if you're gonna open it and just check it out, 523 00:23:39,486 --> 00:23:42,736 but they're gonna look very much as you expect 524 00:23:42,856 --> 00:23:44,936 because these are just gonna be fields inside of the struct. 525 00:23:45,596 --> 00:23:48,316 So we can simply create one using BITMAPFILEHEADER bf 526 00:23:48,316 --> 00:23:50,816 and if we wanna fill that up with data 527 00:23:50,816 --> 00:23:53,476 from our file we can just as we expect we can say fread 528 00:23:53,476 --> 00:23:55,576 and we wanna put that data inside of the struct, 529 00:23:55,936 --> 00:23:57,496 no different than what we were doing before, 530 00:23:57,716 --> 00:23:59,856 then we can specify things like the size 531 00:23:59,856 --> 00:24:02,746 and the input pointer just as we know what to do. 532 00:24:03,876 --> 00:24:04,946 So questions on the header, yup? 533 00:24:04,946 --> 00:24:06,596 >> Just a general question, 534 00:24:06,896 --> 00:24:10,596 what distinguishes a white pixel from a padded pixel? 535 00:24:10,596 --> 00:24:13,296 >> So, what distinguishes a white pixel from a padded pixel? 536 00:24:14,116 --> 00:24:18,856 So, because of this file header, we're gonna know what padding is 537 00:24:18,856 --> 00:24:21,396 and what-- what is padding and what isn't padding, right? 538 00:24:21,396 --> 00:24:22,566 Because if we tell-- 539 00:24:22,786 --> 00:24:26,536 if we specify inside of my info header how wide the image should 540 00:24:26,536 --> 00:24:28,446 be in pixels, it's gonna know, okay, 541 00:24:28,446 --> 00:24:29,876 well this byte must be padding 542 00:24:30,146 --> 00:24:31,976 because I know how wide it should be 543 00:24:32,596 --> 00:24:34,846 and I now have some extra thing and okay well, 544 00:24:34,846 --> 00:24:36,556 it's not a multiple of 4 so this is padding 545 00:24:36,556 --> 00:24:38,566 and as I'm an image viewer, I'm not gonna display it. 546 00:24:38,566 --> 00:24:40,056 So, that's why it's critical 547 00:24:40,206 --> 00:24:42,906 that you make sure you update these headers or you might have 548 00:24:42,906 --> 00:24:46,016 like a valid file like when you do xxd and look at it 549 00:24:46,016 --> 00:24:46,956 but if you try to open it 550 00:24:46,956 --> 00:24:49,566 up in some image viewer it's not gonna work right. 551 00:24:51,146 --> 00:24:52,166 Other questions? 552 00:24:52,696 --> 00:25:00,686 Okay, so speaking of xxd, so this is a handy program 553 00:25:00,996 --> 00:25:05,136 that we can use to read in a bitmap and display the bytes 554 00:25:05,286 --> 00:25:06,866 in a format that we can read. 555 00:25:07,566 --> 00:25:10,246 So if we use this command, which is just given to you in a pset 556 00:25:11,086 --> 00:25:13,146 and something like smiley, 557 00:25:13,536 --> 00:25:16,196 then we can say we're going to our pset 5, BMP. 558 00:25:16,196 --> 00:25:21,616 So when you clone the file you have all these bitmaps 559 00:25:21,616 --> 00:25:22,546 and they're here for you. 560 00:25:22,546 --> 00:25:24,206 And if you wanna display one you can say, 561 00:25:24,206 --> 00:25:28,326 xxd and then you can just literally copy and paste, 562 00:25:28,326 --> 00:25:33,116 it's gonna be -c 24 -g 3 -s 54 and eventually you're going 563 00:25:33,116 --> 00:25:38,596 to get-- I typed it too long ago. 564 00:25:39,076 --> 00:25:39,546 That's okay. 565 00:25:39,546 --> 00:25:45,106 So actually you're gonna get xxd -c 24 -G-- 566 00:25:47,296 --> 00:25:51,906 oh, boy-- 3 -s 54 smiley.bmp. 567 00:25:51,906 --> 00:25:56,336 Oh, and I'm too-- you can kind of see it. 568 00:25:56,336 --> 00:25:57,826 Some my font size is a little too big. 569 00:25:57,946 --> 00:26:00,326 But you can basically see what each of these pixels look like. 570 00:26:00,536 --> 00:26:03,946 So every single one of these fff's that says I have all blue, 571 00:26:03,946 --> 00:26:06,276 all green, all red, not just the color white. 572 00:26:06,706 --> 00:26:09,856 But if you have a smaller font size, then you can see that all 573 00:26:09,856 --> 00:26:14,276 of these 000ff which is red are gonna be formed 574 00:26:14,276 --> 00:26:15,546 in a shape of a smiley face. 575 00:26:15,746 --> 00:26:18,236 So a better image inside of the pset. 576 00:26:18,486 --> 00:26:21,546 But to do that we're just gonna run this xxd command, 577 00:26:21,546 --> 00:26:24,266 and these options are just things like read 3 bytes 578 00:26:24,266 --> 00:26:26,596 at a time, this s 54 says, 579 00:26:26,596 --> 00:26:28,186 "I just want you to skip the header." 580 00:26:28,606 --> 00:26:30,206 Right, you'll notice that over here. 581 00:26:30,346 --> 00:26:33,616 This leftmost number is gonna be where you are in the file. 582 00:26:33,616 --> 00:26:37,146 So you notice that we're starting at 00036, 583 00:26:37,516 --> 00:26:40,396 so that's actually hexadecimal and that's gonna be equal 584 00:26:40,396 --> 00:26:44,706 to 3 times 16, just 48 plus 6 more which is 54. 585 00:26:44,986 --> 00:26:49,626 That makes sense because we said s 54 start at the 54th byte. 586 00:26:50,266 --> 00:26:52,586 So the reason for that being we just don't wanna display the 587 00:26:52,586 --> 00:26:54,606 bitmap header inside a hexadecimal 588 00:26:54,606 --> 00:26:56,636 because it's just gonna mess up what the image looks like. 589 00:26:57,206 --> 00:26:59,516 And you have the parts like the c 24 and a g 3 590 00:26:59,726 --> 00:27:02,716 to specify how many columns you want to be displayed at once. 591 00:27:04,336 --> 00:27:05,836 So questions on using that? 592 00:27:05,836 --> 00:27:08,746 It could be really handy when you're writing your programs if, 593 00:27:08,746 --> 00:27:11,436 you know, it's not displaying right inside 594 00:27:11,436 --> 00:27:12,696 of your image viewer and you did-- 595 00:27:12,746 --> 00:27:14,626 but it is displaying right inside of xxd, 596 00:27:14,626 --> 00:27:16,386 you can determine, well, maybe there's something wrong 597 00:27:16,386 --> 00:27:18,256 with my header or vice versa. 598 00:27:19,696 --> 00:27:23,036 So now we are-- that we are empowered with knowledge 599 00:27:23,036 --> 00:27:27,616 of bitmaps and knowledge of file I/O, we can walkthrough copy.c. 600 00:27:28,146 --> 00:27:29,686 So again, this was written for us. 601 00:27:29,926 --> 00:27:30,396 Question first? 602 00:27:30,396 --> 00:27:30,966 [ Inaudible Remark ] 603 00:27:30,966 --> 00:27:38,136 >> Yeah. So how do you know if it's displayed right? 604 00:27:38,136 --> 00:27:39,596 Unfortunately, this is a bad example 605 00:27:39,596 --> 00:27:41,146 because my font size is so big. 606 00:27:41,536 --> 00:27:44,676 We may try knocking it down a little bit. 607 00:27:44,876 --> 00:27:48,836 So if we make this standard 12 instead. 608 00:27:48,836 --> 00:27:53,796 Yeah, so now you can kind of see now, you can kind 609 00:27:53,796 --> 00:27:54,856 of see the smiley face? 610 00:27:55,186 --> 00:27:57,996 If you can't get this to open up in your image viewer at all, 611 00:27:58,036 --> 00:27:59,996 then this is actually not a bad way of trying to figure 612 00:27:59,996 --> 00:28:01,676 out if you resize image correctly. 613 00:28:02,386 --> 00:28:05,046 So you can kind of see it there, we highlighted the colors 614 00:28:05,046 --> 00:28:06,626 in a piece of phrase so it's more visible. 615 00:28:07,126 --> 00:28:08,506 But this is a good, oh no, 616 00:28:08,506 --> 00:28:09,876 the image viewer isn't working at all. 617 00:28:09,876 --> 00:28:11,246 But you're not totally in trouble 618 00:28:11,246 --> 00:28:13,486 because you can just do this instead. 619 00:28:15,376 --> 00:28:17,486 Unfortunately, last year we didn't have an image viewer, 620 00:28:17,486 --> 00:28:18,886 and so this is what everyone had to do. 621 00:28:18,886 --> 00:28:21,836 So you're in luck. 622 00:28:22,066 --> 00:28:25,926 So now, for copy.c. So this again was a file 623 00:28:25,926 --> 00:28:28,076 that was given-- written for you, 624 00:28:28,076 --> 00:28:30,586 and when you clone the pset 5 repository, 625 00:28:30,836 --> 00:28:31,886 you're gonna pull this down. 626 00:28:32,426 --> 00:28:34,286 So let's just walk through it. 627 00:28:34,286 --> 00:28:36,976 So first, as always you're just making sure we've supplied the 628 00:28:36,976 --> 00:28:38,116 right number of arguments. 629 00:28:38,486 --> 00:28:40,886 This file is gonna take some input file, 630 00:28:40,886 --> 00:28:42,636 just probably a bitmap, and it's going 631 00:28:42,636 --> 00:28:44,986 to create another file that's identical 632 00:28:45,086 --> 00:28:45,906 to the original bitmap. 633 00:28:46,546 --> 00:28:49,276 So in outfile and infile are gonna have identical, 634 00:28:49,276 --> 00:28:51,306 the identical sequence of bytes once this is done. 635 00:28:52,416 --> 00:28:55,386 So now, we're just getting the filenames from the command line. 636 00:28:55,706 --> 00:28:57,466 That's easy because the first one is the infile. 637 00:28:57,466 --> 00:29:00,796 RB2 is gonna be the outfile, we know what's going on there. 638 00:29:01,286 --> 00:29:03,266 And so now we're going to open them both up. 639 00:29:03,506 --> 00:29:07,306 So you notice that we open the first one with the mod of R 640 00:29:07,306 --> 00:29:08,996 because we're reading from the infile, 641 00:29:08,996 --> 00:29:11,196 and we open the second one with the mode of W 642 00:29:11,286 --> 00:29:12,346 because we're writing to that file. 643 00:29:13,246 --> 00:29:14,846 So after we do some more error checking, 644 00:29:15,306 --> 00:29:19,346 now we can start working with these two headers I mentioned. 645 00:29:20,076 --> 00:29:23,316 So we created a BITMAPFILEHEADER and then we read 646 00:29:23,316 --> 00:29:26,206 in that first amount of bytes that's equal 647 00:29:26,206 --> 00:29:27,296 to the size of that struct. 648 00:29:27,566 --> 00:29:30,896 We filled up that struct with the first bytes in the file. 649 00:29:31,416 --> 00:29:35,156 And so now we can access both the BITMAPFILEHEADER 650 00:29:35,156 --> 00:29:37,326 and the info header which we're just doing the same thing, 651 00:29:37,326 --> 00:29:39,446 just created a different struct and we're filling that struct 652 00:29:39,446 --> 00:29:40,366 up with the next bytes. 653 00:29:40,806 --> 00:29:43,076 And so now we can say something like bf.bfType. 654 00:29:43,076 --> 00:29:46,796 And this bfType is a field defined in a struct 655 00:29:46,796 --> 00:29:47,866 that someone else wrote. 656 00:29:48,506 --> 00:29:50,446 So we can just do some more error checking. 657 00:29:50,826 --> 00:29:54,126 But that's a good example of how to access the struct. 658 00:29:54,606 --> 00:29:57,686 And so now you'll notice we want to write out those same bytes 659 00:29:57,736 --> 00:30:00,506 in the same exact order this time to outpointer. 660 00:30:01,086 --> 00:30:02,746 >> So we called fread on inpointer. 661 00:30:02,746 --> 00:30:04,756 We're calling fwrite on outpointer. 662 00:30:05,016 --> 00:30:07,716 So now it's basically going to copy the headers 663 00:30:07,716 --> 00:30:09,766 from the infile into the outfile. 664 00:30:09,856 --> 00:30:11,876 So, that's the first 54 bytes. 665 00:30:12,856 --> 00:30:15,096 So now we need to calculate our padding, 666 00:30:15,096 --> 00:30:17,186 so this is just the same formula we mentioned, 667 00:30:17,186 --> 00:30:19,606 so that's just gonna give us back the number 668 00:30:19,606 --> 00:30:20,756 of bytes of padding we need. 669 00:30:21,396 --> 00:30:24,496 And so now we need to iterate over the entire file. 670 00:30:25,286 --> 00:30:28,786 So, this first 4 loop is going to be iterating over the height, 671 00:30:29,296 --> 00:30:32,336 so iterating over the rows and the second 4 loop is going 672 00:30:32,336 --> 00:30:35,366 to be iterating over the columns 'cause we're going height 673 00:30:35,366 --> 00:30:35,776 and width. 674 00:30:35,776 --> 00:30:38,386 So this looks really familiar, it's just the same 675 00:30:38,386 --> 00:30:39,716 as iterating over a Sudoku board. 676 00:30:39,716 --> 00:30:40,886 We're going rows and columns. 677 00:30:41,536 --> 00:30:43,576 So now we're creating a struct that's going 678 00:30:43,576 --> 00:30:46,906 to hold a single pixel because we're iterating over pixels 679 00:30:47,226 --> 00:30:49,266 and now that we're inside of this second 4 loop. 680 00:30:49,636 --> 00:30:54,416 So, we're reading in each pixel into the struct called triple. 681 00:30:55,076 --> 00:30:58,116 So now that the struct contains the data from the first file 682 00:30:58,116 --> 00:31:01,216 after this read then we can write it out into the other file 683 00:31:01,456 --> 00:31:02,836 so we're just copying pixel 684 00:31:02,836 --> 00:31:06,016 by pixel this first file into the second file. 685 00:31:07,256 --> 00:31:09,466 So now that we've read the entire line, 686 00:31:09,826 --> 00:31:12,306 we need to read all of the padding. 687 00:31:12,306 --> 00:31:15,056 So, you notice here we're using fputc instead of fwrite, 688 00:31:15,506 --> 00:31:18,066 that's just because we just wanna write one byte 689 00:31:18,066 --> 00:31:19,136 at a time padding. 690 00:31:19,496 --> 00:31:21,666 And these are just zeroes, they can be whatever you want 691 00:31:22,256 --> 00:31:24,346 and we're writing them out to that file. 692 00:31:24,636 --> 00:31:28,956 We're also using fseek to say, well, the next time 693 00:31:29,176 --> 00:31:32,786 that I call fread on my input file, I don't want you to try 694 00:31:32,786 --> 00:31:35,626 to read that padding, instead I wanna start 695 00:31:35,626 --> 00:31:38,446 at the current position of my cursor so the SEEK CUR 696 00:31:38,446 --> 00:31:41,946 for current and I want you to move over padding bytes. 697 00:31:42,296 --> 00:31:44,946 So, I want you to skip over that padding so the next time 698 00:31:44,946 --> 00:31:48,016 that you call fread, you're actually at the next line, 699 00:31:48,016 --> 00:31:49,726 the next scanline of your image 700 00:31:49,946 --> 00:31:54,166 and you don't start combining padding bytes with pixel bytes. 701 00:31:54,676 --> 00:31:57,976 So, once that's done, we can just close both of the files 702 00:31:57,976 --> 00:31:59,906 by calling fclose and we're done. 703 00:32:00,486 --> 00:32:04,036 So, this is initially really intimidating file, 704 00:32:04,036 --> 00:32:06,336 make a little more sense now or any questions on copy. 705 00:32:06,866 --> 00:32:06,966 Yup? 706 00:32:08,576 --> 00:32:12,826 >> Is there padding after each pixel? 707 00:32:12,926 --> 00:32:14,846 >> So, is there padding after each pixel? 708 00:32:14,986 --> 00:32:17,206 So, there's only padding at the end of the line, 709 00:32:17,996 --> 00:32:21,916 so that's why it's outside of this inner 4 loop but still 710 00:32:21,916 --> 00:32:23,706 within the outer 4 loop. 711 00:32:24,106 --> 00:32:24,196 Yeah? 712 00:32:25,136 --> 00:32:30,626 >> Why haven't you added that on the [inaudible]? 713 00:32:30,626 --> 00:32:34,096 >> So, okay, so this fseek says what are we doing 714 00:32:34,096 --> 00:32:35,266 with this input file? 715 00:32:35,476 --> 00:32:37,996 So, inside of the input file, we're skipping over the padding, 716 00:32:38,576 --> 00:32:40,956 so the next time I read, I'm at the next line. 717 00:32:41,446 --> 00:32:45,556 But inside of our output file, we know exactly how much padding 718 00:32:45,876 --> 00:32:48,036 that we need to add because we calculated it. 719 00:32:48,336 --> 00:32:50,656 And so we're writing out to the output file the number 720 00:32:50,656 --> 00:32:53,736 of padding while skipping over it inside of the input file. 721 00:32:54,316 --> 00:32:55,906 So, we could have just, we didn't have to do this, 722 00:32:55,906 --> 00:32:58,646 we could have just written the padding but this is just kind 723 00:32:58,646 --> 00:33:00,936 of to demonstrate what's actually going on here. 724 00:33:01,046 --> 00:33:04,046 You can skip it with fseek then you can explicitly write it 725 00:33:04,046 --> 00:33:05,476 with fputc in the zeroes. 726 00:33:05,956 --> 00:33:08,566 Other questions on copy? 727 00:33:08,566 --> 00:33:08,633 Yeah. 728 00:33:08,686 --> 00:33:10,376 >> It's not really about copy 729 00:33:10,376 --> 00:33:14,896 but if there was a 32 bit bitmap would we need padding? 730 00:33:15,956 --> 00:33:18,566 >> So, if it were a 32 bit bitmap would we need padding? 731 00:33:19,006 --> 00:33:22,166 I don't know off the top of my head like what the rules are 732 00:33:22,216 --> 00:33:25,306 if the 4 byte rule applies to 32 and 24 bit bitmaps 733 00:33:25,586 --> 00:33:28,576 but we're only concerned with 24 bit bitmaps for this pset. 734 00:33:28,576 --> 00:33:31,406 So, that the images depend on what the rule was for that. 735 00:33:34,546 --> 00:33:36,166 Other questions, yup? 736 00:33:38,036 --> 00:33:46,076 >> I did try and go over it and I don't know if you wanna go 737 00:33:46,676 --> 00:33:48,236 over this one [inaudible]. 738 00:33:48,486 --> 00:33:53,916 The difference between bi and bf and the weight and [inaudible]? 739 00:33:53,916 --> 00:33:56,606 >> Sure, so the difference between this BI and this BF? 740 00:33:56,886 --> 00:34:00,716 So all-- the only difference is what the bitmap specification 741 00:34:00,716 --> 00:34:01,866 tells us the difference is. 742 00:34:02,396 --> 00:34:04,606 So, this is just what it looks like, so this-- 743 00:34:04,606 --> 00:34:07,546 the info header and the file header just contain different 744 00:34:07,626 --> 00:34:10,376 information about the file and they're just separated 745 00:34:10,376 --> 00:34:12,896 into two structs because whoever designed bitmaps thought 746 00:34:12,896 --> 00:34:13,796 that would be a good idea. 747 00:34:14,376 --> 00:34:16,746 So, because these just contained different information, 748 00:34:16,986 --> 00:34:18,636 the structs contain different fields 749 00:34:18,856 --> 00:34:19,916 and their different sizes. 750 00:34:20,326 --> 00:34:22,546 And so that's why we have different structs for each 751 00:34:22,546 --> 00:34:25,856 of them and we know the file is going to occur before the info, 752 00:34:25,856 --> 00:34:28,106 so read the file first and then the info 753 00:34:28,276 --> 00:34:30,216 and write the file first and then write the info. 754 00:34:30,776 --> 00:34:32,566 So, the short answer why they're two things, 755 00:34:32,826 --> 00:34:35,776 just organizationally it makes more sense to group one-- 756 00:34:36,036 --> 00:34:38,456 some fields into one and others into the other. 757 00:34:38,456 --> 00:34:40,276 So that's why we just have two different structs, 758 00:34:40,756 --> 00:34:42,136 it's purely because bitmap said so. 759 00:34:43,426 --> 00:34:43,746 Yup? 760 00:34:44,516 --> 00:34:50,356 [ Inaudible Remark ] 761 00:34:50,856 --> 00:34:53,096 >> So, inside the loop I'm never-- I'm not-- 762 00:34:53,256 --> 00:34:54,396 it's a little different than Sudoku. 763 00:34:54,396 --> 00:34:56,536 I'm never referring to the row or the column number, 764 00:34:56,536 --> 00:34:59,566 and that's because every time I call fread, 765 00:34:59,786 --> 00:35:01,866 remember I'm moving over my cursor. 766 00:35:02,286 --> 00:35:04,636 So if I just say read, read, I'm not going 767 00:35:04,636 --> 00:35:07,956 to read the same two bytes be-- or however much I'm reading. 768 00:35:08,156 --> 00:35:10,476 Because after the first read, I'm going to move 769 00:35:10,476 --> 00:35:13,486 over to a new location so when I read from that location, 770 00:35:13,486 --> 00:35:15,676 I'm gonna read a different sequence of bytes. 771 00:35:16,726 --> 00:35:20,096 So we're just kind of reading-- we're reading and moving forward 772 00:35:20,096 --> 00:35:22,756 as we read, rather than saying go to this location. 773 00:35:22,756 --> 00:35:24,766 We're kind of literally moving through the file 774 00:35:25,446 --> 00:35:28,006 and we can't go back unless we call fseek. 775 00:35:29,566 --> 00:35:31,476 Other last questions on copy? 776 00:35:31,956 --> 00:35:37,006 Okay. So let's move on to whodunit. 777 00:35:37,776 --> 00:35:40,766 So the goal of whodunit is 778 00:35:40,766 --> 00:35:43,176 to take this picture that's really unreadable. 779 00:35:43,176 --> 00:35:45,256 It has some red pixels, some white pixels 780 00:35:45,256 --> 00:35:46,636 and then some bluish ones and you can't-- 781 00:35:46,636 --> 00:35:48,796 there's some message in there and you can't read it. 782 00:35:49,266 --> 00:35:51,436 And so we need to figure out how we can read it. 783 00:35:51,806 --> 00:35:55,186 So here's what we need to do, we nee d to open the file 784 00:35:55,426 --> 00:35:57,706 and we need to read each line pixel by pixel. 785 00:35:58,376 --> 00:36:00,086 And so as you read in those pixels, 786 00:36:00,086 --> 00:36:03,686 we need to somehow change them in some deterministic way 787 00:36:03,726 --> 00:36:05,836 so we can go from this totally unreadable state 788 00:36:06,006 --> 00:36:07,256 to something that we can read. 789 00:36:07,256 --> 00:36:09,586 So then after we changed the pixel, 790 00:36:09,726 --> 00:36:12,146 we want to write back to some new file. 791 00:36:13,156 --> 00:36:16,006 And so we want to start off with copy.c 792 00:36:16,156 --> 00:36:19,266 because that essentially handles three of these things for you. 793 00:36:19,656 --> 00:36:21,656 Right, copy.c handles opening it, reading it, 794 00:36:21,656 --> 00:36:23,176 and writing it pixel by pixel. 795 00:36:24,166 --> 00:36:27,686 So I would highly recommend you use copy.c as a starting point 796 00:36:27,976 --> 00:36:29,706 and just add in some extra code 797 00:36:29,846 --> 00:36:31,336 to change the color of the pixels. 798 00:36:32,416 --> 00:36:34,976 And so what we wanna be doing is kind of this effect 799 00:36:34,976 --> 00:36:37,966 that you've seen on like a serial box or some decoder ring 800 00:36:38,446 --> 00:36:42,216 but we wanna only let through the red parts of every pixel. 801 00:36:43,046 --> 00:36:44,786 So we're basically creating some filter 802 00:36:45,056 --> 00:36:47,536 and every pixel has some reds, some blue and some green. 803 00:36:47,536 --> 00:36:50,126 And we only wanna let through the red. 804 00:36:50,676 --> 00:36:53,486 So we can just tone down the green and tone down the blue, 805 00:36:53,736 --> 00:36:56,496 that means only red is gonna be left and we get this effect 806 00:36:57,026 --> 00:36:59,916 of putting the red glasses over the really confusing image 807 00:37:00,826 --> 00:37:04,636 and then the actual message is going to be revealed. 808 00:37:05,256 --> 00:37:08,126 So remember that with our struct, we can access the red, 809 00:37:08,126 --> 00:37:10,056 the blue, and the green individually 810 00:37:10,056 --> 00:37:11,516 because they're just fields of our struct 811 00:37:11,826 --> 00:37:14,506 and we can change those values and write the pixel back 812 00:37:14,506 --> 00:37:16,376 and we're going to get a new image. 813 00:37:16,936 --> 00:37:19,836 That's basically a result of putting on those 3D glasses. 814 00:37:20,386 --> 00:37:25,786 So questions on how we're gonna do that or how that works? 815 00:37:25,786 --> 00:37:30,786 So as the-- oh yup. 816 00:37:31,286 --> 00:37:37,316 [ Inaudible Remark ] 817 00:37:37,816 --> 00:37:39,656 >> Exactly, so when I say tone down, 818 00:37:39,656 --> 00:37:42,046 I literally just mean it's some value that's greater than 0 now 819 00:37:42,046 --> 00:37:43,166 and out and get rid of it. 820 00:37:43,166 --> 00:37:43,616 Make it 0. 821 00:37:43,616 --> 00:37:49,026 So as the piece I've mentioned, you might be surprised 822 00:37:49,196 --> 00:37:51,846 about how little code it takes to actually write this 823 00:37:52,156 --> 00:37:54,126 but it's actually pretty cool effect once you're done. 824 00:37:55,146 --> 00:37:57,066 So questions on who done it? 825 00:37:59,816 --> 00:38:02,056 Okay, so let's move on to resize. 826 00:38:02,986 --> 00:38:08,216 So the goal for this resize.c is to take some image and rather 827 00:38:08,216 --> 00:38:11,706 than just copy it or change the colors, we want to enlarge it. 828 00:38:12,236 --> 00:38:14,056 So, scale the image up by a factor of n, 829 00:38:14,316 --> 00:38:15,326 and you can be guaranteed 830 00:38:15,326 --> 00:38:17,936 that this is just an integer of from 0 to 100. 831 00:38:18,686 --> 00:38:21,296 It's not gonna be decimal but just, you know, do make sure 832 00:38:21,296 --> 00:38:22,886 that these are actually typed in in integer 833 00:38:23,156 --> 00:38:27,776 and not some negative number, and we want to resize it. 834 00:38:27,776 --> 00:38:30,666 So if you want to resize it by a factor of 2, 835 00:38:30,666 --> 00:38:31,746 we need to do 2 things. 836 00:38:32,196 --> 00:38:35,196 So given some pixel, in this case that pixel on the top left, 837 00:38:35,916 --> 00:38:38,586 we need to resize it horizontally and we need 838 00:38:38,586 --> 00:38:40,056 to resize it vertically. 839 00:38:40,756 --> 00:38:42,666 So in order to resize it horizontally, 840 00:38:42,866 --> 00:38:45,976 we take this one pixel and we need to make it two pixels 841 00:38:46,366 --> 00:38:47,856 that contain the same exact data. 842 00:38:48,766 --> 00:38:51,806 Now to resize it horizontally-- I mean vertically, we just take 843 00:38:51,806 --> 00:38:54,646 that one pixel and add another pixel below it, 844 00:38:54,646 --> 00:38:55,406 that's the same data. 845 00:38:55,926 --> 00:38:59,246 Or effectively take this one line and duplicate the line 846 00:38:59,816 --> 00:39:01,536 to make that one line two lines. 847 00:39:02,166 --> 00:39:05,036 So we're doing two things, we're duplicating pixels across 848 00:39:05,456 --> 00:39:07,426 and we're duplicating lines down. 849 00:39:08,096 --> 00:39:09,706 And there are a number of times 850 00:39:09,796 --> 00:39:12,036 that we duplicate lines is gonna be dependent 851 00:39:12,036 --> 00:39:15,236 on whatever this n is which is an argument to resize. 852 00:39:16,716 --> 00:39:18,776 So we know how to do things like open the file 853 00:39:18,776 --> 00:39:22,196 and read each scanline and so now, we need to make sure 854 00:39:22,196 --> 00:39:23,486 to update the header info 855 00:39:23,746 --> 00:39:26,006 because it's definitely different unless the user just 856 00:39:26,006 --> 00:39:26,806 typed in one. 857 00:39:26,806 --> 00:39:30,396 The image has a new size, it has a new height a new width. 858 00:39:30,636 --> 00:39:31,896 So we need to make sure we change that 859 00:39:31,896 --> 00:39:33,656 or we're not gonna be able to display the image correctly. 860 00:39:34,406 --> 00:39:36,866 So now, one side we're writing each row 861 00:39:36,866 --> 00:39:38,756 and to write each pixel n times 862 00:39:38,906 --> 00:39:43,266 and then write each line or row n times. 863 00:39:43,266 --> 00:39:45,026 So again, don't forget about this. 864 00:39:45,026 --> 00:39:46,306 We know how to change the values 865 00:39:46,336 --> 00:39:47,866 because we know their original values, 866 00:39:48,186 --> 00:39:49,296 we know what we're scaling by 867 00:39:49,416 --> 00:39:51,536 and so we can just calculate the new values 868 00:39:51,716 --> 00:39:52,756 very straightforwardly. 869 00:39:53,326 --> 00:39:56,136 So now, to write each pixel, 870 00:39:57,076 --> 00:39:59,906 you notice that copy.c is just writing it once. 871 00:39:59,976 --> 00:40:01,766 But we don't wanna write it once, 872 00:40:01,846 --> 00:40:04,816 we want to read a single pixel and write 873 00:40:04,876 --> 00:40:06,246 that pixel multiple times. 874 00:40:07,236 --> 00:40:08,516 >> So once we read the pixel, 875 00:40:08,516 --> 00:40:10,756 we know it's stored inside of some struct. 876 00:40:11,616 --> 00:40:14,516 Now writing that struct doesn't change what 877 00:40:14,516 --> 00:40:16,156 that struct contains, right? 878 00:40:16,156 --> 00:40:17,496 Unless we explicitly change it, 879 00:40:17,496 --> 00:40:19,546 that struct is still gonna contain that pixel. 880 00:40:20,176 --> 00:40:23,036 So we need to do is instead of just calling fwrite once, 881 00:40:23,036 --> 00:40:25,506 we probably wanna call fwrite in some loop 882 00:40:25,966 --> 00:40:27,396 where the value the number of times 883 00:40:27,396 --> 00:40:29,586 that loop is repeated needs to be the number 884 00:40:29,586 --> 00:40:31,496 of times we need to write that pixel. 885 00:40:32,506 --> 00:40:34,416 So we don't-- so for every one time we read, 886 00:40:34,416 --> 00:40:37,066 we need to write instead of once, n times. 887 00:40:38,116 --> 00:40:41,016 And so that's gonna take care of our horizontal resizing. 888 00:40:41,546 --> 00:40:44,606 But we also need to consider this padding thing. 889 00:40:45,346 --> 00:40:48,676 So because our old image and our new image have different sizes, 890 00:40:48,676 --> 00:40:51,546 we're probably going to have different amounts of padding. 891 00:40:52,246 --> 00:40:54,966 So we definitely need to recalculate padding based 892 00:40:54,966 --> 00:40:57,246 on the new dimensions of a resized image. 893 00:40:57,666 --> 00:40:59,296 That's a no big deal because we have a formula 894 00:40:59,296 --> 00:41:02,066 and that's really easy to plug into. 895 00:41:02,676 --> 00:41:04,796 But we're a little nuanced as we're now reading 896 00:41:04,796 --> 00:41:07,576 and writing data because when you're reading, 897 00:41:07,796 --> 00:41:11,046 you need to make sure that you skip over the original padding. 898 00:41:11,046 --> 00:41:14,566 So remembering copy.c, we explicitly used fseek 899 00:41:14,666 --> 00:41:15,716 and we skipped over the padding. 900 00:41:16,476 --> 00:41:18,906 So when using that fseek, you need to make sure you skip 901 00:41:18,906 --> 00:41:20,496 over the original images padding. 902 00:41:20,496 --> 00:41:23,926 But when you're writing, you need to write the amount 903 00:41:23,926 --> 00:41:26,556 of padding that you calculated for the new image. 904 00:41:27,386 --> 00:41:30,156 So in copy.c, we're just using the same padding value. 905 00:41:30,426 --> 00:41:31,856 Now that we're resizing, we need 906 00:41:31,856 --> 00:41:33,656 to make sure you use different padding values 907 00:41:33,786 --> 00:41:36,056 or else we're just not going to get a valid bitmap. 908 00:41:37,106 --> 00:41:39,146 So any questions on handling the padding 909 00:41:39,146 --> 00:41:44,666 between sizes or why we need to? 910 00:41:44,906 --> 00:41:47,366 To size your writing, think about, am I working 911 00:41:47,366 --> 00:41:49,676 on the original image or I'm working on the new image now 912 00:41:50,046 --> 00:41:51,866 and what's the padding for the current image 913 00:41:51,866 --> 00:41:53,336 that I'm working on. 914 00:41:54,816 --> 00:41:57,786 So now we have our image and it's resized horizontally. 915 00:41:57,786 --> 00:42:00,306 So that's fine, we know how we doubled all of our pixels, 916 00:42:00,306 --> 00:42:02,436 whatever, now we need to handle vertically. 917 00:42:03,006 --> 00:42:07,976 So we wrote this line once, and so we need to write it n times, 918 00:42:08,156 --> 00:42:10,176 so we need to write it n minus 1 more times. 919 00:42:11,396 --> 00:42:14,356 But the problem with the way copy is written is that as soon 920 00:42:14,356 --> 00:42:16,776 as copy write to pixel, it forgets about it. 921 00:42:17,386 --> 00:42:19,526 It's never good-- it's not saving these pixels anywhere. 922 00:42:19,526 --> 00:42:21,786 As soon as it writes it, it's gonna forget about it 923 00:42:21,786 --> 00:42:23,886 and just create a new struct and move on to the next pixel. 924 00:42:24,676 --> 00:42:26,226 So we obviously don't want that to happen 925 00:42:26,226 --> 00:42:28,086 because if we forget the pixel and we know-- 926 00:42:28,086 --> 00:42:29,716 never look at it again, there's no way 927 00:42:29,716 --> 00:42:30,936 to duplicate the entire line. 928 00:42:31,976 --> 00:42:33,256 There are a few things we can do here. 929 00:42:33,256 --> 00:42:36,556 We can do-- one thing we can do is remember the pixels inside 930 00:42:36,556 --> 00:42:36,846 of an array. 931 00:42:37,636 --> 00:42:39,706 So we could say, okay, I'm reading my lines, 932 00:42:40,086 --> 00:42:41,456 and I'm gonna have some array 933 00:42:41,456 --> 00:42:43,936 that represents a single line inside of my image. 934 00:42:44,606 --> 00:42:47,386 And so then once I've read in every line, the entire line, 935 00:42:47,496 --> 00:42:49,266 I can just write that line multiple times. 936 00:42:50,166 --> 00:42:52,936 Or if you don't wanna create a new array, we can use fseek. 937 00:42:53,256 --> 00:42:55,566 We can say okay, well, I've written this one line once, 938 00:42:56,056 --> 00:42:58,316 instead of going to the next line, I need to restart 939 00:42:58,586 --> 00:43:00,546 at the current line and write it again. 940 00:43:01,446 --> 00:43:03,816 So both approaches are totally, totally valid 941 00:43:04,366 --> 00:43:07,386 but the basic idea is we don't want to make-- 942 00:43:07,386 --> 00:43:09,566 we don't want to move on the next line immediately. 943 00:43:09,896 --> 00:43:12,586 We need to somehow come back to the current line that we're on 944 00:43:12,846 --> 00:43:16,416 and write that n times to the file. 945 00:43:16,646 --> 00:43:18,636 So this horizontally, this vertical case were kind 946 00:43:18,636 --> 00:43:21,576 of two separate cases and they're gonna combine 947 00:43:21,886 --> 00:43:24,606 to make sure that we get an image that's resized by n 948 00:43:24,606 --> 00:43:25,906 and all the padding is handled 949 00:43:25,906 --> 00:43:28,536 and we made sure we updated our headers and we're good to go. 950 00:43:29,416 --> 00:43:31,476 So if you wanted to take the former approach 951 00:43:31,816 --> 00:43:36,856 of saving every pixel in a line inside of an array, then we need 952 00:43:36,856 --> 00:43:41,726 to create an array that's not some static size, but well, 953 00:43:41,726 --> 00:43:44,426 I can't just say like array 5 because I could be entering 954 00:43:44,426 --> 00:43:46,076 in images that are various sizes, 955 00:43:46,076 --> 00:43:48,776 but we wanna create an array who's size is based 956 00:43:48,776 --> 00:43:49,276 on a variable. 957 00:43:49,276 --> 00:43:51,066 And so there are two ways to do that. 958 00:43:51,066 --> 00:43:54,046 The simpler way is just to say, okay, I can have some array, 959 00:43:54,046 --> 00:43:55,526 in this case we're using integers 960 00:43:55,526 --> 00:43:57,946 but we're not gonna be using integers on this pset, 961 00:43:57,946 --> 00:43:59,226 we're gonna make sure we have an array 962 00:43:59,226 --> 00:44:01,166 of those RGBTRIPLEs or those pixels. 963 00:44:02,126 --> 00:44:03,586 And inside of the link of the array, 964 00:44:03,586 --> 00:44:04,636 we could just use a variable. 965 00:44:05,046 --> 00:44:06,966 And whatever the value of that variable is, 966 00:44:06,966 --> 00:44:08,516 when this is executed, is going 967 00:44:08,516 --> 00:44:09,936 to determine the size of the array. 968 00:44:10,916 --> 00:44:13,636 But now that we know about the heap, we can also use malloc. 969 00:44:14,276 --> 00:44:17,366 Well we know that we want n ints, so just n times size 970 00:44:17,366 --> 00:44:20,116 of int where n could be however big I want the array to be. 971 00:44:20,116 --> 00:44:21,786 And if you take the lighter approach, 972 00:44:21,786 --> 00:44:23,516 make sure that you're free because freeing 973 00:44:23,516 --> 00:44:25,176 after malloc is really, really important. 974 00:44:25,666 --> 00:44:29,676 So questions on how we're resizing the image 975 00:44:29,676 --> 00:44:30,496 in either direction? 976 00:44:32,256 --> 00:44:32,636 Yup. 977 00:44:33,516 --> 00:44:38,176 [ Inaudible Remark ] 978 00:44:38,676 --> 00:44:40,246 >> So how do we know how much 979 00:44:40,246 --> 00:44:42,086 to initialize the length of this array to? 980 00:44:42,086 --> 00:44:43,346 So in this case, I just-- 981 00:44:43,346 --> 00:44:45,666 I have some variable and I just said 5 for the example. 982 00:44:46,106 --> 00:44:49,416 But we know ints from our bitmap header how wide 983 00:44:49,416 --> 00:44:51,466 and how tall our image is. 984 00:44:51,996 --> 00:44:53,776 So we can read the value of that struct 985 00:44:53,776 --> 00:44:55,776 which is gonna be determined by the file itself 986 00:44:55,776 --> 00:45:00,516 and then create an array based on that value. 987 00:45:00,646 --> 00:45:02,656 Other questions on anything resize? 988 00:45:03,196 --> 00:45:10,076 Okay. So now, let's move on to the fun one which is recover. 989 00:45:11,146 --> 00:45:14,446 So the goal of recover is we want to take some CF-- 990 00:45:14,536 --> 00:45:17,386 some corrupt CF card because David has no idea what he is 991 00:45:17,386 --> 00:45:21,526 doing with computers and want to recover 37 images from it. 992 00:45:22,146 --> 00:45:24,746 And so just a note if you happen to start this pset 993 00:45:25,096 --> 00:45:27,586 on Friday before like 2:30 or so, 994 00:45:27,586 --> 00:45:29,306 make sure you update your appliance [phonetic] again. 995 00:45:29,306 --> 00:45:32,286 There is just a small issue in the card we supplied you 996 00:45:32,286 --> 00:45:33,676 where you couldn't get the last image, 997 00:45:33,966 --> 00:45:35,896 so just make sure you update your appliance 998 00:45:35,896 --> 00:45:38,666 as soon you're done here to make sure you get the correct version 999 00:45:38,666 --> 00:45:39,516 of the CF card. 1000 00:45:40,856 --> 00:45:43,116 So this is what your CF card looks like, 1001 00:45:43,116 --> 00:45:46,176 and this middle image is indeed David's college yearbook photo. 1002 00:45:47,186 --> 00:45:50,006 So, on side-- inside of your card, your CF card, 1003 00:45:50,226 --> 00:45:51,976 your images are stored contiguously. 1004 00:45:52,356 --> 00:45:53,716 So, one after another, but we know-- 1005 00:45:54,726 --> 00:45:59,096 so before we go into that, just here it's hard to do again, 1006 00:45:59,096 --> 00:46:02,266 so we're gonna open up this, we're gonna determine 1007 00:46:02,526 --> 00:46:04,096 where the start of each images, 1008 00:46:04,516 --> 00:46:06,526 we wanna determine what we wanna call that image 1009 00:46:06,796 --> 00:46:08,326 and we wanna write out all the bytes 1010 00:46:08,326 --> 00:46:11,296 of that image to the same file. 1011 00:46:11,586 --> 00:46:16,426 So, this card.raw which again, when you do your get cloned, 1012 00:46:16,426 --> 00:46:18,036 you're not gonna pull down the raw file, 1013 00:46:18,356 --> 00:46:20,166 but when you do your pseudo [inaudible] update, 1014 00:46:20,166 --> 00:46:21,766 that's what's gonna download the raw file, 1015 00:46:22,116 --> 00:46:25,816 so make sure you update all the time. 1016 00:46:25,816 --> 00:46:28,696 And so we wanna open this file and it's located here 1017 00:46:28,696 --> 00:46:30,686 on your appliance, so we don't need to worry 1018 00:46:30,686 --> 00:46:32,586 about what's telling you where the file is 1019 00:46:32,586 --> 00:46:34,096 because it's always gonna be in the same place. 1020 00:46:34,506 --> 00:46:37,866 So just feel free to hard code this value into your recover. 1021 00:46:37,866 --> 00:46:39,396 It's not going to be a command-line argument. 1022 00:46:40,716 --> 00:46:44,366 So, that's how we open the file, just fopen with an R as usual. 1023 00:46:44,366 --> 00:46:48,186 And so now we need to determine the start of each JPEG. 1024 00:46:49,186 --> 00:46:52,216 So a JPEG, just like a bitmap, it's still just a sequence 1025 00:46:52,216 --> 00:46:54,026 of bytes because that's all files are. 1026 00:46:54,386 --> 00:46:56,416 Even though bitmaps and JPEGs are very different, 1027 00:46:56,666 --> 00:47:00,306 they're just sequences of bytes and it's no scarier than that. 1028 00:47:00,736 --> 00:47:04,606 So bit-- JPEGs can start with one of these two sequences. 1029 00:47:04,796 --> 00:47:09,046 They can start with either ffd8, ffe0, or the same thing is 1030 00:47:09,146 --> 00:47:10,956 with the e1 at the end. 1031 00:47:11,926 --> 00:47:14,826 So if you find this sequence of bytes, 1032 00:47:15,126 --> 00:47:18,216 you know JPEG starts right here. 1033 00:47:18,726 --> 00:47:22,486 And so, because this JPEG is restored contiguously, 1034 00:47:22,546 --> 00:47:24,086 we're really looking at something like this, 1035 00:47:24,316 --> 00:47:26,356 we're gonna find this sequence of bytes 1036 00:47:26,736 --> 00:47:30,726 and those 4 bytes are gonna be the first 4 bytes of my image. 1037 00:47:31,466 --> 00:47:33,546 So as I'm going through reading through the CF card, 1038 00:47:33,616 --> 00:47:35,056 I find those 4 bytes again. 1039 00:47:35,696 --> 00:47:37,836 That means that their image that I was reading, 1040 00:47:37,996 --> 00:47:41,006 it's gotta be done because I just found a new image. 1041 00:47:41,606 --> 00:47:43,846 And because this photo is restored contiguously, 1042 00:47:43,846 --> 00:47:46,116 we know that it has to be some new image 1043 00:47:46,416 --> 00:47:47,426 when we find the sequence. 1044 00:47:47,896 --> 00:47:51,006 So in that case, you wanna say okay, that first JPEG is done, 1045 00:47:51,006 --> 00:47:54,156 I wanna create a new JPEG and start writing all 1046 00:47:54,156 --> 00:47:56,746 of those bytes, including this first 4. 1047 00:47:57,246 --> 00:48:00,186 So these first 4 bytes are part of the JPEG itself, 1048 00:48:00,186 --> 00:48:02,036 so you don't wanna skip over and then start writing, 1049 00:48:02,036 --> 00:48:04,626 you wanna make sure you include those first 4 bytes. 1050 00:48:05,206 --> 00:48:10,056 So that's how we're going to determine the start of our JPEG. 1051 00:48:10,786 --> 00:48:14,926 So any questions to this point? 1052 00:48:15,086 --> 00:48:17,226 Okay. So we know how to open a file and we know how to read it 1053 00:48:17,226 --> 00:48:18,926 and we're just gonna make sure we're looking 1054 00:48:18,926 --> 00:48:20,536 for these 4 bytes in order. 1055 00:48:20,536 --> 00:48:25,666 So now we need to do a little work to determine the name 1056 00:48:25,666 --> 00:48:28,736 of our file, so they're all gonna end in .jpg 1057 00:48:28,736 --> 00:48:31,876 and the pset mentions that they have to be in the file, 1058 00:48:31,976 --> 00:48:34,336 the format number number number, 1059 00:48:34,696 --> 00:48:37,616 where this number is running from 0 up to 36. 1060 00:48:38,626 --> 00:48:41,326 And so we can use this new function called sprintf, 1061 00:48:42,096 --> 00:48:45,936 which is the exact same thing as printf except instead of writing 1062 00:48:45,936 --> 00:48:47,866 out to the terminal, you can write 1063 00:48:48,006 --> 00:48:49,766 to a string or a character array. 1064 00:48:50,436 --> 00:48:53,226 So this-- the first argument to sprintf here is going 1065 00:48:53,226 --> 00:48:54,636 to be the array you're writing to. 1066 00:48:54,876 --> 00:48:56,386 So up somewhere else in my program, 1067 00:48:56,386 --> 00:49:01,146 I declared some fixed size character array, and now, 1068 00:49:01,466 --> 00:49:04,396 the rest of the arguments are gonna operate just like printf. 1069 00:49:04,396 --> 00:49:06,836 So I can save the string that I wanna write in 1070 00:49:06,836 --> 00:49:09,356 and that string can contain things like percent D 1071 00:49:09,356 --> 00:49:12,436 and percent C and then every argument after that is going 1072 00:49:12,436 --> 00:49:13,776 to be what we're substituting in. 1073 00:49:14,256 --> 00:49:17,196 So if I said sprintf coolness and then percent D 1074 00:49:17,196 --> 00:49:19,856 and I'm making that a 10, instead of writing that out 1075 00:49:19,856 --> 00:49:23,156 to the terminal, I'm going fill up this character array 1076 00:49:23,416 --> 00:49:24,636 with the resulting string. 1077 00:49:25,626 --> 00:49:28,196 So one thing to note is because we're saying 000 1078 00:49:28,196 --> 00:49:30,196 and there are only 37 images, 1079 00:49:30,466 --> 00:49:33,006 you know that every filename is going to be the same size, 1080 00:49:33,076 --> 00:49:36,156 and that's pretty handy because these arrays has 1081 00:49:36,156 --> 00:49:39,046 to be the same size from [inaudible] and all the way 1082 00:49:39,046 --> 00:49:39,916 through its existence. 1083 00:49:41,056 --> 00:49:43,126 So, also note that the JPEGs are named 1084 00:49:43,126 --> 00:49:44,026 in the order you find them. 1085 00:49:44,536 --> 00:49:47,956 So 000 is gonna be the first one, the next one has to be 001, 1086 00:49:47,956 --> 00:49:50,446 so you could kinda see what we're gonna do here. 1087 00:49:50,506 --> 00:49:52,876 We need some counter and based on the counter, 1088 00:49:52,936 --> 00:49:54,636 we need to sprintf some filename 1089 00:49:54,636 --> 00:49:56,986 and that filename is always gonna be the same length, 1090 00:49:57,076 --> 00:49:57,986 which is really cool. 1091 00:49:58,316 --> 00:50:00,836 So now once we've formulate that, then we can pass 1092 00:50:00,886 --> 00:50:04,456 that argument to the file that we open up when we call fopen 1093 00:50:04,456 --> 00:50:06,406 and start writing bytes. 1094 00:50:07,176 --> 00:50:10,936 >> So, any questions on sprintf or how we can use 1095 00:50:10,936 --> 00:50:15,756 that to construct the filename? 1096 00:50:15,816 --> 00:50:17,506 Okay, so now that we have the filename, 1097 00:50:17,506 --> 00:50:19,816 we wanna actually start writing the bytes 1098 00:50:19,816 --> 00:50:21,076 of the image to the file. 1099 00:50:22,226 --> 00:50:25,466 So bitmaps, we were concerned with reading 3 bytes at a time, 1100 00:50:25,806 --> 00:50:27,766 because that's how many bytes were inside of the pixel. 1101 00:50:28,316 --> 00:50:31,666 With JPEGs, we're now concerned with much larger blocks, 1102 00:50:32,016 --> 00:50:34,586 in this case, there are 512 byte blocks. 1103 00:50:35,556 --> 00:50:37,516 So instead of reading 3 bytes at a time, 1104 00:50:37,956 --> 00:50:39,576 and instead saying 3 inside of fread, 1105 00:50:39,576 --> 00:50:44,036 we now wanna read 512 blocks at a time. 1106 00:50:44,266 --> 00:50:48,266 So before, we were reading into structs, right, and the number 1107 00:50:48,266 --> 00:50:50,656 of fields in the structs determine how much we can read 1108 00:50:50,656 --> 00:50:51,076 at a time. 1109 00:50:51,746 --> 00:50:53,616 But we can also [inaudible] that reading 1110 00:50:53,616 --> 00:50:56,436 into a struct we can read straight into in an array. 1111 00:50:57,346 --> 00:51:00,736 So here I've created an array of bytes, and you wanna use bytes 1112 00:51:00,736 --> 00:51:02,786 which is declared on that same header file. 1113 00:51:03,566 --> 00:51:05,596 A byte is just a data type, and that's what we wanna use 1114 00:51:05,596 --> 00:51:09,196 in our JPEGs because it represent about 512 block bytes. 1115 00:51:10,086 --> 00:51:12,496 So we're reading into that array 5 bytes, 1116 00:51:13,066 --> 00:51:15,266 because it's saying 5 times the size of 1 byte, 1117 00:51:15,316 --> 00:51:16,706 so that's 5 total bytes. 1118 00:51:16,926 --> 00:51:20,176 So after this call, array is now filled 1119 00:51:20,176 --> 00:51:21,926 up with the first 5 bytes, 1120 00:51:22,186 --> 00:51:24,456 of whatever file I opened with input pointer. 1121 00:51:25,436 --> 00:51:28,006 So, the same thing is using structs except now we don't have 1122 00:51:28,006 --> 00:51:31,696 to create a struct, and we can read in instead of 3 bytes 1123 00:51:31,696 --> 00:51:34,006 at a time really as much as we want, because the size 1124 00:51:34,006 --> 00:51:36,966 of the array that we create determines how much we could 1125 00:51:36,966 --> 00:51:38,086 read in at once. 1126 00:51:38,086 --> 00:51:41,536 So after we read this, if we want to get the first byte 1127 00:51:41,536 --> 00:51:44,136 that we just read, we would say array of 0, 1128 00:51:44,136 --> 00:51:46,966 and that's just going to be the first byte that fread read 1129 00:51:46,966 --> 00:51:49,086 and then you can go on until the size of the array. 1130 00:51:49,666 --> 00:51:52,306 So where structs you had to access some named field. 1131 00:51:52,656 --> 00:51:53,656 If we use arrays, 1132 00:51:53,656 --> 00:51:56,406 we can literally just say I want the third byte, 1133 00:51:57,026 --> 00:51:59,136 not some name field like first or second. 1134 00:52:00,326 --> 00:52:02,996 So, questions on how to use fread with arrays? 1135 00:52:03,496 --> 00:52:03,626 Yup? 1136 00:52:03,681 --> 00:52:05,681 [ Inaudible Remark ] 1137 00:52:05,736 --> 00:52:12,776 >> So fread and sprintf, so those are kind 1138 00:52:13,096 --> 00:52:15,076 of doing two different things. 1139 00:52:15,396 --> 00:52:19,546 So sprintf is creating some string from something 1140 00:52:19,546 --> 00:52:23,056 that you specify, so the string that we specified 1141 00:52:23,056 --> 00:52:23,966 as the second argument 1142 00:52:23,966 --> 00:52:27,276 to sprintf is gonna determine what the variable 1143 00:52:27,276 --> 00:52:28,626 array contains. 1144 00:52:29,736 --> 00:52:32,256 Where with fread, we're not supplying at a string 1145 00:52:32,836 --> 00:52:36,616 but we're operating with a file, so we're reading from the file 1146 00:52:36,896 --> 00:52:38,386 and putting it into an array. 1147 00:52:39,136 --> 00:52:41,026 So it's sprintf, we're not using files 1148 00:52:41,026 --> 00:52:42,606 but with fread we're reading files 1149 00:52:42,606 --> 00:52:45,546 and not something that we specified. 1150 00:52:46,146 --> 00:52:48,446 Yup. 1151 00:52:48,446 --> 00:52:49,636 [ Inaudible Remark ] 1152 00:52:49,636 --> 00:52:52,316 >> So if that 5, the 5 from the cursor? 1153 00:52:52,476 --> 00:52:55,536 Exactly. So, even though I'm not reading to structs anymore, 1154 00:52:55,536 --> 00:52:58,186 I'm still moving the cursor along as I fread, 1155 00:52:58,436 --> 00:53:00,736 so every time I call this, I'm reading 5 bytes 1156 00:53:00,736 --> 00:53:02,746 and the cursor is moving over 5. 1157 00:53:03,276 --> 00:53:04,736 So, exactly the same thing. 1158 00:53:04,736 --> 00:53:07,546 Yeah. Other questions? 1159 00:53:10,006 --> 00:53:16,596 Okay. So now we read in our 512 byte blocks, so now, 1160 00:53:16,596 --> 00:53:19,976 we need to write out those 512 blocks, and we know how to do 1161 00:53:19,976 --> 00:53:23,776 that because we can do the same to supply our array until fwrite 1162 00:53:23,846 --> 00:53:26,396 that we want 512 blocks written out to some file. 1163 00:53:26,986 --> 00:53:29,936 Now the file that we're writing out to needs to be the same 1164 00:53:29,936 --> 00:53:31,516 until we find some new image. 1165 00:53:32,126 --> 00:53:34,486 So we're basically gonna be finding an image. 1166 00:53:34,486 --> 00:53:36,436 We said okay, we just found a JPEG, 1167 00:53:36,436 --> 00:53:39,056 we're gonna create some new file, whether that be-- 1168 00:53:39,056 --> 00:53:40,706 let's just say 000.jpg. 1169 00:53:40,706 --> 00:53:45,766 And until we find another JPEG, we're writing out to 000.jpg, 1170 00:53:45,766 --> 00:53:48,536 just writing out 512 byte blocks. 1171 00:53:49,236 --> 00:53:52,096 And then eventually, while we're reading we're gonna say wait, 1172 00:53:52,096 --> 00:53:55,326 we just found that 4 byte string again, that 4-- 1173 00:53:55,396 --> 00:53:57,916 sequence of 4 bytes that says I'm a new JPEG. 1174 00:53:58,456 --> 00:54:01,416 So at this point, you wanna say okay, I know longer care 1175 00:54:01,616 --> 00:54:05,486 about 000.jpg, that's totally done, it's finished, 1176 00:54:05,686 --> 00:54:08,806 because I found a new JPEG and JPEGs are stored right next 1177 00:54:08,806 --> 00:54:09,586 to each other on the card. 1178 00:54:10,286 --> 00:54:12,076 So now I wanna open up a new file 1179 00:54:12,406 --> 00:54:15,096 which now is gonna be 001.jpg. 1180 00:54:15,096 --> 00:54:17,806 And now I wanna start writing to that file 1181 00:54:18,236 --> 00:54:19,566 until I find some other JPEG. 1182 00:54:19,566 --> 00:54:21,976 And we're just gonna continue this process 1183 00:54:22,166 --> 00:54:25,706 until we find the start of 37 different JPEGs. 1184 00:54:26,576 --> 00:54:29,306 But we need to worry about when we're done, 1185 00:54:29,306 --> 00:54:32,356 because we're not gonna end with the start of a new JPEG. 1186 00:54:32,386 --> 00:54:35,286 Our CF card is gonna end with the end of the last JPEG, 1187 00:54:35,286 --> 00:54:38,476 so we have this handy function, feof or feof, 1188 00:54:39,266 --> 00:54:40,806 that's going to return a Boolean. 1189 00:54:41,056 --> 00:54:43,296 And if it returns true, then that means 1190 00:54:43,296 --> 00:54:46,136 that we have reached the end of our file, we're done reading. 1191 00:54:47,056 --> 00:54:48,786 So if we put this inside of a loop 1192 00:54:48,786 --> 00:54:52,476 and we keep freading 512 bytes at a time, eventually, 1193 00:54:52,476 --> 00:54:55,816 this feof is going to return true and that means we've read 1194 00:54:55,816 --> 00:54:56,996 through the entire CF card. 1195 00:54:56,996 --> 00:55:00,156 And if at that point we have our program correct, 1196 00:55:00,546 --> 00:55:03,446 that means we found 37 JPEGs and we've written 1197 00:55:03,626 --> 00:55:05,956 to 37 different files. 1198 00:55:06,666 --> 00:55:09,596 So questions on recover? 1199 00:55:11,376 --> 00:55:11,936 Yeah. 1200 00:55:12,516 --> 00:55:18,436 [ Inaudible Remark ] 1201 00:55:18,936 --> 00:55:21,516 >> So, do we have to deal with RGBTRIPLEs and JPEGs? 1202 00:55:22,226 --> 00:55:23,656 So no, we don't. 1203 00:55:23,656 --> 00:55:25,646 RGBTRIPLEs are just a bitmap thing. 1204 00:55:26,116 --> 00:55:27,996 In JPEGs we're just saying we're just gonna look 1205 00:55:27,996 --> 00:55:29,946 at every block of 512 bytes. 1206 00:55:29,946 --> 00:55:32,396 We don't really know what those 512 bytes is? 1207 00:55:32,546 --> 00:55:34,806 But somehow, those bytes come together 1208 00:55:34,806 --> 00:55:36,186 to form our JPEG images. 1209 00:55:36,186 --> 00:55:39,576 So we never need to change any bytes themselves, we just need 1210 00:55:39,576 --> 00:55:42,146 to find where might-- did I find a new JPEG yet? 1211 00:55:42,146 --> 00:55:44,686 And if not, keep writing into the same file. 1212 00:55:45,346 --> 00:55:48,606 And if we do find a new one, create a new file. 1213 00:55:48,816 --> 00:55:50,086 Other questions on recover? 1214 00:55:50,206 --> 00:55:50,436 Yeah. 1215 00:55:50,436 --> 00:55:50,503 [ Inaudible Remark ] 1216 00:55:50,503 --> 00:55:51,876 >> Oh, sure. 1217 00:55:55,796 --> 00:55:59,106 So the feof, it just takes a single argument 1218 00:55:59,106 --> 00:56:00,306 and it takes the file pointer. 1219 00:56:00,766 --> 00:56:03,416 So this says, is this file pointer at the end? 1220 00:56:03,896 --> 00:56:06,056 So is there cursor associated with this file 1221 00:56:06,056 --> 00:56:07,006 at the end of the file. 1222 00:56:07,616 --> 00:56:10,056 And if not, then it's gonna return false. 1223 00:56:10,126 --> 00:56:12,696 And if it is at the end or past the end, it's gonna return true. 1224 00:56:13,806 --> 00:56:16,256 So this is a good condition for some loop that goes 1225 00:56:16,306 --> 00:56:20,896 through the entire CF card. 1226 00:56:21,076 --> 00:56:22,016 Any last questions? 1227 00:56:23,186 --> 00:56:23,606 Yeah. 1228 00:56:23,606 --> 00:56:23,856 [ Inaudible Remark ] 1229 00:56:23,856 --> 00:56:29,346 >> Oh, so why this have a size of 5? 1230 00:56:29,346 --> 00:56:29,646 >> Yeah. 1231 00:56:29,876 --> 00:56:33,516 >> No, no reason, just so to show you like do we need 1232 00:56:33,516 --> 00:56:36,516 to have some fixed size, and that fixed size just has 1233 00:56:36,556 --> 00:56:38,576 to match the amount of bytes that we're reading in. 1234 00:56:39,326 --> 00:56:41,806 So for you that your recover that-your recover file, 1235 00:56:42,076 --> 00:56:44,206 you want it to read in 512 bytes at a time. 1236 00:56:44,706 --> 00:56:47,666 Well, this is reading in 5 bytes at a time. 1237 00:56:47,876 --> 00:56:48,056 Yeah. 1238 00:56:48,806 --> 00:56:50,386 >> So as reading 5 bytes at a time 1239 00:56:50,716 --> 00:56:56,666 from that file pointer not the pointer 1240 00:56:57,236 --> 00:57:01,816 but that points they're in? 1241 00:57:02,866 --> 00:57:03,156 >> Yes. 1242 00:57:03,156 --> 00:57:03,223 [ Inaudible Remark ] 1243 00:57:03,223 --> 00:57:04,686 >> Yes. So what this line is doing-- 1244 00:57:04,846 --> 00:57:06,616 and it's reading from this input pointer. 1245 00:57:07,066 --> 00:57:08,266 And where are these data going? 1246 00:57:08,506 --> 00:57:09,916 Inside of array. 1247 00:57:10,576 --> 00:57:12,296 So before we put it inside of a struct, 1248 00:57:12,566 --> 00:57:14,186 now we're putting it inside of an array. 1249 00:57:14,646 --> 00:57:17,686 If we then wanted to write out to the JPEG, we would need 1250 00:57:17,686 --> 00:57:20,166 to call fwrite with different parameters 1251 00:57:20,166 --> 00:57:21,876 because we don't want input pointer anymore, 1252 00:57:21,876 --> 00:57:23,356 we now want our output pointer. 1253 00:57:23,816 --> 00:57:26,276 But we can still say array because that's the array 1254 00:57:26,276 --> 00:57:28,756 from the original file that we need to write out to the JPEG. 1255 00:57:29,216 --> 00:57:31,326 >> So we would then write another function using the array 1256 00:57:31,326 --> 00:57:33,676 we just got through reading out to the file? 1257 00:57:34,056 --> 00:57:35,526 >> Right. So then you'd have after this, 1258 00:57:35,526 --> 00:57:37,476 you'd have some other function that writes 1259 00:57:37,476 --> 00:57:40,366 out to the file, to the JPEG, exactly. 1260 00:57:40,746 --> 00:57:43,076 Other questions? 1261 00:57:43,606 --> 00:57:49,356 So before you go, this is an email that we actually received 1262 00:57:50,116 --> 00:57:53,266 at the end-- at the beginning of this year 1263 00:57:53,566 --> 00:57:55,656 and I thought this was the coolest thing ever. 1264 00:57:55,656 --> 00:57:59,196 So just read through that and just let it sink 1265 00:57:59,196 --> 00:58:01,746 in how much we are empowering you as a class. 1266 00:58:01,746 --> 00:58:03,016 [ Laughter ] 1267 00:58:03,016 --> 00:58:09,000 [ Pause ] 1268 00:58:09,296 --> 00:58:12,806 >> So, on that note good luck on pset 5.