[video output=day459 member=cmuratori stream_platform=twitch stream_username=handmade_hero project=code title="Partitioning the PNG Reader for Integration" vod_platform=youtube id=pPP4rn3DEAY annotator=Miblo]
[0:00][Recap and set the stage for the day working towards putting :art into [~hero Handmade Hero]][:speech]
[3:08][@puremouron][Is anyone else mesmerised by the bobbing orphan on the web page[ref
    site="Handmade Hero"
    url=https://handmadehero.org/game]]
[4:53][Unpack the new :art into a dedicated directory where the artist may dump art][:admin]
[7:13][Show off item_template.png and character_template.png][:drawing]
[9:20][Discover how to switch the default image viewer back to the one that used to be the default][:research]
[13:08][Switch the default image viewer back to Windows Photo viewer[ref
    site="Windows 10 Forums"
    page="Windows 10: Is Windows Photo Viewer gone?"
    url=https://www.tenforums.com/software-apps/8930-windows-photo-viewer-gone-2.html#post290818]][:admin]
[14:28][Show off our new :art][:drawing]
[17:26][Set up to read our new PNGs][:admin]
[19:02][:Run our PNG reader on character_hero.png and crash in ConsumeSize()][:compression :parsing]
[20:58][Note in ParsePNG() the need to handle BTYPE0 blocks that straddle IDAT chunk boundaries][:parsing]
[22:52][Step through ParsePNG() to see that BFINAL does not get set][:parsing :run]
[28:28][Let it :run to completion, writing out our image][:parsing]
[28:55][View character_hero.bmp to see that it looks correct but for the alpha channel][:drawing]
[31:10][Inspect the Width and Height values, to see that they are as expected][:parsing :run]
[32:25][Consult the DEFLATE,[ref
    site=IETF
    page="DEFLATE Compressed Data Format Specification version 1.3"
    url=https://www.ietf.org/rfc/rfc1951.txt] ZLIB[ref
        site=IETF
        page="ZLIB Compressed Data Format Specification version 3.3"
        url=http://www.ietf.org/rfc/rfc1950.txt] and PNG[ref
    site=W3C
    page="Portable Network Graphics (PNG) Specification (Second Edition)"
    url=https://w3.org/TR/2003/REC-PNG-20031110/] specifications for information on BFINAL and chunk processing][:research]
[41:52][Enable ParsePNG() to break out of its consumption loop once all the expected pixels have been consumed][:parsing]
[43:19][:Run it successfully to see that the output looks correct][:parsing]
[43:52][:Run it successfully on hand_skeleton.png][:parsing]
[44:17][Inspect the output image to see that it looks correct, and wonder if Photoshop's PNG encoder is busted][:drawing]
[46:55][Remove stale code from WriteImageTopDownRGBA() and note in ParsePNG() to figure out why we can't rely on BFINAL being set to 1 on the last chunk of Photoshop-exported PNG files][:parsing]
[49:47][Consult stb_image.h for insight into its consumption loop][:research]
[53:51][Set up to test our PNG image with stb_image.h][:compression :parsing]
[56:57][:Run stb_png_test successfully on character_hero.png][:compression :parsing]
[1:00:37][Step through stbi__parse_zlib() and into stbi__parse_uncompressed_block() to see that it processes 0-length blocks][:compression :parsing :run]
[1:05:29][Investigate the handling of 0-length blocks by FlushByte() in ParsePNG(), reverting the latter to break out of its consumption loop only if BFINAL is 1][:compression :parsing]
[1:07:24][Set up to test our PNG reader on character_hero.png][:admin]
[1:08:59][Break on the FlushByte() call in ParsePNG() and realise that it may be flushing more than a byte][:parsing :run]
[1:10:02][Change ParsePNG() to consume 16-bits for the LEN and NLEN, and FlushByte() to only flush the remainder of the byte][:parsing]
[1:11:41][:Run it to see that we correctly parse character_hero.png][:parsing]
[1:12:19][Enable ParsePNG() to parse blocks that straddle IDAT chunk boundaries, introducing RefillIfNecessary()][:parsing]
[1:16:07][:Run it to see that it still works][:parsing]
[1:16:35][Remove the ReversedBits table][:parsing]
[1:17:19][Determine to split up the PNG reader for integration into the game, while retaining the small test app][:speech]
[1:18:23][Create test_png.cpp to contain everything except the decoding code][:compression :parsing]
[1:22:07][Consider supporting buffered :"error handling" in the PNG decoder]
[1:24:01][Create handmade_stream.cpp to contain all the stream consumption code for our PNG reader][:parsing]
[1:32:03][Introduce Outf() to write errors into our stream, augmenting the stream struct with Errors and stream_chunk with File and LineNumber][:"error handling"]
[1:38:49][Make test_png.cpp initialise an Info and Error stream, pass them to ReadEntireFile() and WriteImageTopDownRGBA(), and write those stream to file using a new DumpStreamToCRT()][:"error handling" :"file io"]
[1:44:16][Introduce OnDemandMemoryStream()][:memory]
[1:45:02][Compile and :run and get no output, with a view to addressing that later]
[1:45:16][Q&A][:speech]
[1:46:29][@ivereadthesequel][Q: So what is the focus now? This logging / error system?][:"error handling"]
[1:48:18][@tonelessr][Q: I haven't been following the PNG streams closely, but how satisfied are you with the code for the reader?][:parsing]
[1:49:13][@lvias][Q: Could you explain the bug that was solved again?][:parsing]
[1:51:22][@flyinginthedark][Q: Is TODO comment still in the code?]
[1:51:57][@tonelessr][Q: Any plans to switch to LLVM anytime in the series?]
[1:52:41][@AsafGartner][Q: If Visual Studio can load PNG files, maybe it can display BMP files with alpha?]
[1:53:42][Enable WriteImageTopDownRGBA() to conditionally replace the alpha pixels with all black, and the program to output this as an extra BMP file][:parsing]
[1:58:38][:Run it and inspect our two output BMP files][:parsing]
[1:59:00][Introduce MulAlpha() to composite the alpha and non-alpha pixels][:parsing]
[2:03:06][:Run it to see our premultiplied output][:parsing]
[2:03:49][@tonelessr][Q: This is off-topic, but will there be any blog posts on Molly Rocket for any of the projects anytime? Kind of miss those]
[2:04:05][@cynokron][Q: I am confused why you shift the multiply down by 8 bits. Wouldn't you want to mask with 0xFF?]
[2:04:44][Basis in Fixed Point Multiply][:blackboard :mathematics]
[2:11:05][@sneakybob_wot][Q: Can you briefly explain how the binary reverse works you implemented last week?]
[2:11:10][Bit Reversal][:blackboard :memory]
[2:13:25][We're all done][:speech]
[/video]
