18:53Continue to step through ParsePNG() to completion, and inspect the DecompressedPixels

🏃

18:53Continue to step through ParsePNG() to completion, and inspect the DecompressedPixels

🏃

18:53Continue to step through ParsePNG() to completion, and inspect the DecompressedPixels

🏃

24:57Deduce that the DecompressedPixels contain row transform filter indicators that we have not yet learnt

🏃

24:57Deduce that the DecompressedPixels contain row transform filter indicators that we have not yet learnt

🏃

24:57Deduce that the DecompressedPixels contain row transform filter indicators that we have not yet learnt

🏃

26:56Rename DecompressedPixels to FinalPixels, initialising it before the parsing loop in ParsePNG()

26:56Rename DecompressedPixels to FinalPixels, initialising it before the parsing loop in ParsePNG()

26:56Rename DecompressedPixels to FinalPixels, initialising it before the parsing loop in ParsePNG()

27:59Crash 4coder and step into it to see what's going on

🗹

27:59Crash 4coder and step into it to see what's going on

🗹

27:59Crash 4coder and step into it to see what's going on

🗹

30:10Continue setting up ParsePNG() to apply the filters to the FinalPixels

30:10Continue setting up ParsePNG() to apply the filters to the FinalPixels

30:10Continue setting up ParsePNG() to apply the filters to the FinalPixels

33:274.3 Reference image to PNG image transformation1

📖

33:274.3 Reference image to PNG image transformation1

📖

33:274.3 Reference image to PNG image transformation1

📖

40:279 Filtering (PNG)2

📖

40:279 Filtering (PNG)2

📖

40:279 Filtering (PNG)2

📖

49:05Finish setting up ParsePNG() to apply the filters to our parsed pixels, noting that it seems tailor-made for SIMD3

49:05Finish setting up ParsePNG() to apply the filters to our parsed pixels, noting that it seems tailor-made for SIMD3

49:05Finish setting up ParsePNG() to apply the filters to our parsed pixels, noting that it seems tailor-made for SIMD3

1:08:10Introduce our PNGFilter*() functions4

1:08:10Introduce our PNGFilter*() functions4

1:08:10Introduce our PNGFilter*() functions4

1:22:16Introduce PNGFilterReconstruct() to perform the filtering part of ParsePNG()

1:22:16Introduce PNGFilterReconstruct() to perform the filtering part of ParsePNG()

1:22:16Introduce PNGFilterReconstruct() to perform the filtering part of ParsePNG()

1:26:03Step through PNGFilterReconstruct() to see what we end up with

🏃

1:26:03Step through PNGFilterReconstruct() to see what we end up with

🏃

1:26:03Step through PNGFilterReconstruct() to see what we end up with

🏃

1:29:32Add assertions in the untested Average and Paeth filter cases in PNGFilterReconstruct()

1:29:32Add assertions in the untested Average and Paeth filter cases in PNGFilterReconstruct()

1:29:32Add assertions in the untested Average and Paeth filter cases in PNGFilterReconstruct()

1:30:55Run the program on the compressed gimp_8x8.png to see that it looks right

🏃

1:30:55Run the program on the compressed gimp_8x8.png to see that it looks right

🏃

1:30:55Run the program on the compressed gimp_8x8.png to see that it looks right

🏃

1:39:16Draw a more complicated image

🎨

1:39:16Draw a more complicated image

🎨

1:39:16Draw a more complicated image

🎨

1:41:00Run it on our more complicated, uncompressed image and hit the Paeth filter

🏃

1:41:00Run it on our more complicated, uncompressed image and hit the Paeth filter

🏃

1:41:00Run it on our more complicated, uncompressed image and hit the Paeth filter

🏃

1:42:40Remove that assertion from the Paeth filter case in PNGFilterReconstruct()

1:42:40Remove that assertion from the Paeth filter case in PNGFilterReconstruct()

1:42:40Remove that assertion from the Paeth filter case in PNGFilterReconstruct()

1:42:53Step through PNGFilterReconstruct() into PNGFilter4() (Paeth) to see that it looks reasonable

🏃

1:42:53Step through PNGFilterReconstruct() into PNGFilter4() (Paeth) to see that it looks reasonable

🏃

1:42:53Step through PNGFilterReconstruct() into PNGFilter4() (Paeth) to see that it looks reasonable

🏃

1:46:21Run it on our compressed complex image, to see that it look good too

🏃

1:46:21Run it on our compressed complex image, to see that it look good too

🏃

1:46:21Run it on our compressed complex image, to see that it look good too

🏃

1:46:57Run it on our fully complex gimp_test.png and crash in ParsePNG()

🏃

1:46:57Run it on our fully complex gimp_test.png and crash in ParsePNG()

🏃

1:46:57Run it on our fully complex gimp_test.png and crash in ParsePNG()

🏃

1:48:41Step through ConsumeSize() to realise that the crash occurs even in the first IDAT chunk, so the bug must be in the Huffman decode

1:48:41Step through ConsumeSize() to realise that the crash occurs even in the first IDAT chunk, so the bug must be in the Huffman decode

1:48:41Step through ConsumeSize() to realise that the crash occurs even in the first IDAT chunk, so the bug must be in the Huffman decode

1:53:53Perform coverage checking on every EncodedLen case in ParsePNG() to find that the 16-long (0x10) case is never used in the successfully parsed file

🏃

1:53:53Perform coverage checking on every EncodedLen case in ParsePNG() to find that the 16-long (0x10) case is never used in the successfully parsed file

🏃

1:53:53Perform coverage checking on every EncodedLen case in ParsePNG() to find that the 16-long (0x10) case is never used in the successfully parsed file

🏃

1:58:563.2.7 Compression with dynamic Huffman codes BTYE=105

📖

1:58:563.2.7 Compression with dynamic Huffman codes BTYE=105

📖

1:58:563.2.7 Compression with dynamic Huffman codes BTYE=105

📖

2:01:44Step through the BTYPE=10 case in ParsePNG() to see that the LitLenDistTable seems to be built correctly

🏃

2:01:44Step through the BTYPE=10 case in ParsePNG() to see that the LitLenDistTable seems to be built correctly

🏃

2:01:44Step through the BTYPE=10 case in ParsePNG() to see that the LitLenDistTable seems to be built correctly

🏃

2:02:40Consider our current situation and ways to proceed

🗩

2:02:40Consider our current situation and ways to proceed

🗩

2:02:40Consider our current situation and ways to proceed

🗩

2:03:18Q&A

🗩

2:03:18Q&A

🗩

2:03:18Q&A

🗩

2:03:38ratchetfreak Q: The LEN, NLEN is so the decompressor can resync with a compressor if a block got corrupted (and the compressor emitted an empty block) by looking for the bytes 0000FFFF, mostly handy for byte streams

🗪

2:03:38ratchetfreak Q: The LEN, NLEN is so the decompressor can resync with a compressor if a block got corrupted (and the compressor emitted an empty block) by looking for the bytes 0000FFFF, mostly handy for byte streams

🗪

2:03:38ratchetfreak Q: The LEN, NLEN is so the decompressor can resync with a compressor if a block got corrupted (and the compressor emitted an empty block) by looking for the bytes 0000FFFF, mostly handy for byte streams

🗪

2:04:09rooctag Q: C is up and left6

🗪

2:04:09rooctag Q: C is up and left6

🗪

2:04:09rooctag Q: C is up and left6

🗪

2:05:26Fix PNGFilterReconstruct() to correctly filter Paeth

2:05:26Fix PNGFilterReconstruct() to correctly filter Paeth

2:05:26Fix PNGFilterReconstruct() to correctly filter Paeth

2:06:24geekengale Q: Did I see for(;;) in your code? What's that for / how does it work?

🗪

2:06:24geekengale Q: Did I see for(;;) in your code? What's that for / how does it work?

🗪

2:06:24geekengale Q: Did I see for(;;) in your code? What's that for / how does it work?

🗪

2:07:56john_diresta Q: In the memory window when you were writing the "decoded" pixel (non-compressed 8x8) you were writing to some memory that you have not allocated, accordingly to the ASCII representation, there were some strings about a path in windows

🗪

2:07:56john_diresta Q: In the memory window when you were writing the "decoded" pixel (non-compressed 8x8) you were writing to some memory that you have not allocated, accordingly to the ASCII representation, there were some strings about a path in windows

🗪

2:07:56john_diresta Q: In the memory window when you were writing the "decoded" pixel (non-compressed 8x8) you were writing to some memory that you have not allocated, accordingly to the ASCII representation, there were some strings about a path in windows

🗪

2:09:16Brian Q: In Day 055 when you create the hash table, you added your TODO on getting a better hash. Other than for educational purposes investigating better hashes, what kinds of problems would you start to see if the hash was not good enough? Like would it pop-up when you are profiling or something? Would you get any errors?

🗪

2:09:16Brian Q: In Day 055 when you create the hash table, you added your TODO on getting a better hash. Other than for educational purposes investigating better hashes, what kinds of problems would you start to see if the hash was not good enough? Like would it pop-up when you are profiling or something? Would you get any errors?

🗪

2:09:16Brian Q: In Day 055 when you create the hash table, you added your TODO on getting a better hash. Other than for educational purposes investigating better hashes, what kinds of problems would you start to see if the hash was not good enough? Like would it pop-up when you are profiling or something? Would you get any errors?

🗪

2:11:09sharlock93 Q: There is a VS plugin that lets you see images in memory. It's called Image Watch. Was pretty useful when I did the PNG decoding

🗪

2:11:09sharlock93 Q: There is a VS plugin that lets you see images in memory. It's called Image Watch. Was pretty useful when I did the PNG decoding

🗪

2:11:09sharlock93 Q: There is a VS plugin that lets you see images in memory. It's called Image Watch. Was pretty useful when I did the PNG decoding

🗪

2:11:38john_diresta Q: Oh okay, it's that it looked strange. Usually it's filled with 0xDD of 0xCD if I remember correctly, or maybe it's just for stack memory?

🗪

2:11:38john_diresta Q: Oh okay, it's that it looked strange. Usually it's filled with 0xDD of 0xCD if I remember correctly, or maybe it's just for stack memory?

🗪

2:11:38john_diresta Q: Oh okay, it's that it looked strange. Usually it's filled with 0xDD of 0xCD if I remember correctly, or maybe it's just for stack memory?

🗪

2:13:22uplinkcoder Q: Try a big empty image which compresses very well

🗪

2:13:22uplinkcoder Q: Try a big empty image which compresses very well

🗪

2:13:22uplinkcoder Q: Try a big empty image which compresses very well

🗪

2:14:49quickshift_ Q: So on Linux, would you have to use calloc() instead of VirtualAlloc() or is there an alternative?7

🗪

2:14:49quickshift_ Q: So on Linux, would you have to use calloc() instead of VirtualAlloc() or is there an alternative?7

🗪

2:14:49quickshift_ Q: So on Linux, would you have to use calloc() instead of VirtualAlloc() or is there an alternative?7

🗪

2:15:32sgtrumbi Q: Will you integrate the decoder directly into the game or into the simple_preprocessor?

🗪

2:15:32sgtrumbi Q: Will you integrate the decoder directly into the game or into the simple_preprocessor?

🗪

2:15:32sgtrumbi Q: Will you integrate the decoder directly into the game or into the simple_preprocessor?