Skip to content
Sean Isom edited this page Jun 22, 2020 · 7 revisions

Using flightsimlib

flightsimlib is designed with simple modern C++ constructs and is very easy to use.

Decompressing BGL Data

It is straightforward to use the included DLL library functions from the binary release.

For a refresher on BGL structure and compressed sections, see the FSDeveloper wiki topic.

5 Exported functions are provided for the different compression types in BGlDecompressor.h:

  • DecompressLz1
  • DecompressLz2
  • DecompressDelta
  • DecompressBitPack
  • DecompressPtc

Let's take a look at the signature for one of these algorithms, bitpack:

static FLIGHTSIMLIB_EXPORTED int CDECL DecompressBitPack(
	uint8_t* p_uncompressed, 
	int uncompressed_size, 
	const uint8_t* p_compressed, 
	int compressed_size, 
	int rows, 
	int cols);

All functions are located in the static class CBglDecompressor in the flightsimlib::io namespace (as this is part of a much larger codebase). The API is fully stateless and needs no initialization: just call the functions with your data.

Note: for PTC all additional parameters are present in the TRQ1 record header except the bpp (bytes per pixel) value, which could be calculated as follows:

int TerrainRasterQuad::BPPForType(TerrainRasterQuadType type)
{
	switch (type)
	{
	case TerrainRasterQuadType::POPULATION_DENSITY:
	case TerrainRasterQuadType::TERRAIN_INDEX:
	case TerrainRasterQuadType::TERRAIN_LAND_CLASS:
	case TerrainRasterQuadType::TERRAIN_REGION:
	case TerrainRasterQuadType::TERRAIN_SEASON_XXX:
	case TerrainRasterQuadType::TERRAIN_WATER_CLASS:
		return 1;
	case TerrainRasterQuadType::TERRAIN_ELEVATION:
	case TerrainRasterQuadType::UNKNOWN_ELEVATION:
	case TerrainRasterQuadType::TERRAIN_PHOTO:
		return 2;
	case TerrainRasterQuadType::TERRAIN_PHOTO_32: // MS Flight Only
		return 4;
	}

	return 0;
}

You are responsible for managing your own memory however you choose with this stateless design: no malloc is performed by the library. The API uses raw C pointers to ease linking with other languages, however, if writing a client in C++ you are strongly encouraged to wrap these with RAII smart pointer types. The input data and size is given by the input file. You will need to allocate your output byte array for a size of num_rows * num_cols * bpp (bytes per pixel as calculated above). Either memset or use a uniform initializer of all 0s.

Each function returns the number of bytes written (or 0 for failure). Ensure the decompressed data is valid by asserting the return value equals the output array size.

Note from the BGL Docs that compound compression is often applied, which requires you to first decompress the data with one method, then decompress that output again with another. In this case the first 4 bytes of the input compressed stream are an int specifying the intermediate compressed size.

Linking

Precompiled DLLs are provide for Windows. Linking is as easy as adding the included convenience link library as input to your linker in VS2019. Alternatively you could dynamically link by adding the following code:

typedef int (*LP_DECOMPRESSBITPACK)(char *p_uncompressed, int uncompressed_size,
	const char *p_compressed, int compressed_size, int rows, int cols);
HINSTANCE hDLL = NULL;
LP_DECOMPRESSBITPACK DecompressBitPack = nullptr;
hDLL = LoadLibrary(L"fligthsimlib.dll");
DecompressBitPack = (LP_DECOMPRESSBITPACK)GetProcAddress((HMODULE)hDLL,
	"?DecompressBitPack@CBglDecompressor@io@flightsimlib@@SAHPEAEHPEBEHHH@Z");

The code can also be consumed for other C++ compilers or platforms as there is no dependency on the Windows SDK (without PTC support, as explained below).

Samples

See the examples/decompression example for a working sample of basic usage.

Building flightsimlib

Although not strictly necessary, you can easily build flightsimlib from source under Visual Studio 2019. Simply use the enclosed .sln to build or execute headless as a MSBuild task. The library builds in both x86 and x64 configs (and you most likely should just use the x64 build).

In order to run the samples, you will need to xcopy the headers from include into examples\include, and similarly the produced dll and link .lib to examples\lib\x64 (or x86), as the binaries are not checked in.

The PTC component is distributed in binary form, as both MDd and MD (please just say no to MT!) static .libs for both x86 and x64. These are linked in with the included C++ code to form the final DLL. These are currently a work in progress and Windows-only. These are being actively developed and eventually will be open-sourced in cross-platform C as well.

Other than PTC, flightsimlib otherwise has no dependencies on Windows and could be built without this component using the included macros for any platform under gcc or clang in a manner similar to the following:

g++ -c -fPIC BglDecompressor.cpp
g++ -shared -o flightsimlib.so -fPIC BglDecompressor.o

A note on PTC

The resample tool from FSX (and its successors) heavily uses PTC (Progressive Transform Codec) compressed data. This is a proprietary image codec developer by Microsoft in the late 1990s that saw use in applications such as FSX, the Xbox 360 SDK, the Microsoft Office MDI file format, the Windows Journal app, and other applications on Windows. Like other proprietary coders of the era, PTC never saw widespread adoption. It was subsequently iterated into the Windows HD Photo codec, integrated with WIC, and then slightly modified and published as an ISO standard as JPEG-XR. The JXR Device Porting Kit was since released under open-source and, while fairly different from the initial PTC format, still shares some implementation details. JXR is still not widespread, but has seen more adoption in areas such as Bing Maps and the OpenXML Paper Specification, and with some experimental browser support.

A high-level overview of this algorithm can be found from Microsoft here.

PTC is a progressive image compressor somewhat similar to the JPEG 2000 standard. In supplementing JPEG's DCTs, instead of using a Wavelet transform, a novel integer transform (HLBT) is proposed for a standard 3 step codec. The basic components include:

  • A simple wrapper file format
  • Support for various bitplane types and color depths
  • Conversion to the YCoCg color space
  • Hierarchical Lapped Biorthogonal Transforms (HLBT)
  • Coefficient block reordering
  • Adaptive bit-plane encoding via RLGR

Image (C) Microsoft, 2000

Image (C) Microsoft, 2000, reproduced under fair use

PTC has no freely-available implementation, although it is included (but not documented) in the Windows Imaging Component stack. Through careful study of all of Malvar's work, analysis of resample and the ptcencode/ptcdecode tools from Microsoft, and subsequent work from analyzing the successor jxrlib codebase, I have built a semi-functional PTC library.

The included ptclib static library files are based on my re-implementation of the PTC algorithm. It is perhaps 60% complete in decoding and 10% complete for encoding. Thus far it is proven to be fully functional for decompression of resample BGL images. Unused features such as different bit-plane settings and mip-mapping are not implemented. Notably, FSX only stores PTC data in two types, a single channel 16-bit grey-scale format or a 16-bit (555+1) color (+water mask). Thus, only elevation or terrain imagery data is stored using PTC, with other raster formats stored using the simpler lossless compression types.

Curiously, the Adaptive Delta Compressor from the algorithm's frontend is actually used for compressing vector data in FSX (.cvx BGL files). I will add code for this in the future.

Roadmap

The roadmap is currently in the main readme.md.

I intend to port more of my features into flightsimlib, and also intend to make it truly cross-platform via CMake.

A note on next steps

This is a living document, and I will add more as I expand the library functionality.

If you need help or have anything to contribute, feel free to open an issue or pull request.