Skip to content
Siorki edited this page Mar 25, 2017 · 3 revisions

Thermal view

Purpose

This tool is integrated in RegPack GUI when run in a browser. It represents the local compression rate on each character of the original code as a color map.

It was requested as a mimic to the features of pngThermal and gzThermal.

Behavior

The rendering is done next to the "Original source" window once the packing is performed.

Thermal view on an example

The background color of each character illustrates how many bytes are needed to represent it once packed. Dark blue is for the best compression, green and yellow mean mild compression, red is for expansion, as shows this scale :

Color code by compression rate

There is an obvious parallel between pattern and thermal view. Parts of a pattern that end up in multiple compression level get better compression rates, thus need less bytes to represent them in the output, and are shifted towards the color blue in the thermal view.

Comparison of thermal and pattern views on the same piece of code

The unpacking routine from both the crusher and the packer adds an overhead that is distributed amongst all characters : hence any original code that is not packed end up being slightly expanded.

Inner clockwork

Transforms and code mapping

All modules contribute to the elaboration of the thermal view by recording the operations performed on their input. This is stored as a mapping between source and destination ranges, stored in the array PackerData.thermalMapping. Each item of the array is itself an array with the following structure :

[  {
      inLength : // (integer) byte length of the input
	  outLength: // (integer) byte length of the output
	  complete : // (boolean) true if the mapping is complete, false if it should be added to the input cost
   },
   { 
	  chapter  : // 0 for main code, 1+ for unpacking routine, see below
          rangeIn  : [ offset, // byte offset to beginning of input block
                       length  // byte length of input block
		       // possibly other offset/length couples 
                     ],
	  rangeOut : [ offset, // byte offset to beginning of output block
                       length  // byte length of output block
		       // possibly other offset/length couples 
                     ],
   } // as many instances of that object as blocks mapped
]

Cost computation

The final operation turns the set of transforms into a heatmap, matching each original character with its compressed cost, in bytes.

The cost map is initialized from the final output (packed string with unpacking routine), with each character being assigned its actual length - 8 bits. Then, the algorithm processes the transforms one at a time, starting from the final output and iterating backwards to the original input. The cost for a block of characters in the transform input (rangeIn attribute) equates the cost of its output (rangeOut attribute) :

  • if the input and output block are the same length, individual values are copied for each byte
  • otherwise, the output cost (sum of values over the block) is averaged over all characters in the input block
  • if the transform has the complete flag unset, the cost is added to the previous values. This represents a chapter being appended to the code, with its length split on the input (or a substring thereof).

One step of transform

Once the loop is completed, the map is represented by a color code as described above. This computation is performed only on the branch yielding the best compression result.

Implementation

The class PackerData initializes the member variable thermalMapping as an empty array []. When multiple branches are created by a module, the cloned PackerData holds a copy of the original thermalMapping.

Each module is in charge of adding its transform to the thermalMapping. When the only operations are replacement of all copies of a string with another, possibly with an added prefix or suffix, the helper method StringHelper.matchAndReplaceAll() encapsulates both the operation on the string and the recording of the transform.

The cost computation is performed by the class ThermalViewer after the packing is complete.