[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]