[video output=day353 member=cmuratori stream_platform=twitch stream_username=handmade_hero project=code title="Simple RLE Compression" vod_platform=youtube id=kikLEdc3C1c annotator=Miblo] [0:18][Set the stage for the day] [1:10][Blackboard: RLE vs LZ] [1:53][Blackboard: On exploiting the properties of the data we want to compress] [5:56][Blackboard: Run-length Encoding] [8:24][Blackboard: Distinguishing between "literals" and "runs"] [9:59][Blackboard: Various formats developed by Electronic Arts: IFF, ILBM, PCX] [11:53][Blackboard: LZ (Lempel-Ziv) as a more heavy-duty form of compression] [16:03][Blackboard: Encoding an additional offset in LZ] [20:07][Blackboard: How LZ gives you RLE almost for free] [25:50][Blackboard: Replicating blocks] [32:28][Blackboard: Why LZ schemes use relative positioning, and choosing how many bits to allocate for the look-back distance] [39:06][Blackboard: LZ encoding] [44:50][Blackboard: Keeping a hash table and information of overlapping runs for the back catalogue] [46:48][Blackboard: Entropy encoding and backends, e.g. Huffman, Arithmetic, rANS / tANS] [49:52][Blackboard: Charting the frequency of values] [53:10][Blackboard: Huffman] [1:01:21][Blackboard: On the inefficiency, size-wise, of Huffman compared to Arithmetic] [1:02:32]["Please take it with a grain of salt, or even a cube of salt"][quote 539] [1:03:27][Blackboard: rANS / tANS[ref site="The ryg blog" page="rANS notes" url="https://fgiesen.wordpress.com/2014/02/02/rans-notes/"]] [1:06:43][Determine to compress our art assets] [1:08:16][Save test_scene_layer_00.bmp as a png and compress it with 7zip for comparison] [1:11:09][simple_compressor.cpp: Setup the code to make an actual command-line compressor] [1:14:56][Run the compressor and view the documentation] [1:15:16][simple_compressor.cpp: Parse the Args] [1:17:46][simple_compressor.cpp: Introduce file_contents struct for ReadEntireFileIntoMemory() to return] [1:20:39][simple_compressor.cpp: Set up the call sites for Compress() and Decompress()] [1:28:53][simple_compressor.cpp: Introduce Compress(), Decompress() and Copy()] [1:32:38][Run the compressor on test1.hha] [1:35:00][simple_compressor.cpp: Introduce RLECompress() and RLEDecompress()] [1:43:01][simple_compressor.cpp: Implement RLEDecompress()] [1:45:32][simple_compressor.cpp: Enable RLECompress() to encode a run] [1:51:33][Run the compressor in the debugger] [1:53:18][simple_compressor.cpp: Make RLECompress() and RLEDecompress() more symmetric] [1:54:59][Step in to RLECompress() and inspect the values] [1:58:20][simple_compressor.cpp: Make RLECompress() correctly loop to the MAX_RUN_COUNT and compute the OutSize] [1:59:41][Run the compressor on test1.hha to find that it has output exactly the same size] [2:01:08][simple_compressor.cpp: Make Compress() use the MaxOutSize value, run the compressor on test1.hha and find that the output is much smaller] [2:02:15][Run the decompressor on test1.scp to find that it doesn't work at all] [2:02:56][simple_compressor.cpp: Correctly store the InFile.FileSize] [2:05:02][Step in to the compressor and inspect what it does] [2:07:04][Step in to the decompressor to find that it works fine, and diff the files it produced] [2:08:39][Run the compressor on intro_art.hha to see how it fares with that] [2:10:34][Q&A][:speech] [2:11:21][Compress test1.hha and intro_art.hha with 7zip for comparison] [2:12:38][@Miblo][Awesome stuff! I hadn't been making the distinction between "literals" and "runs" in my thing. My test stuff has been just 0s and 1s, mind, so I was just storing the first Token and then the Counter values] [2:14:14][@magik603][Tomorrow you will show us what again?] [2:15:36][@ttbjm][Are hardware image decompressors still a thing?] [2:22:54][Conclude][:speech] [/video]