Simple tool built on Kaitai Struct for reading BMP images
BMP Tool is a Node.js CLI tool written in JavaScript. It is intended to be able to parse various BMP files, created on any device, in any program. I try to support all color depths, header types and compression methods for which I can find documentation or sample files.
When a BMP file is loaded, one can save it in another image format (e.g. PNG), with another compression method, bit depth or header type to make it more portable etc.
To get a local copy up and running follow these simple steps.
- Node.js (JavaScript runtime environment) + npm (package manager): https://nodejs.org/en/download/
- Clone the repo
git clone https://github.com/generalmimon/bmptool.git
Note: If you don't want to use
git
, you can download the project in a ZIP archive.
-
Install NPM packages
npm install
-
Build the BMP parsing code from the spec
resources/bmp.ksy
(see Kaitai Struct project for more info)npm run build
Load BMP file /path/to/image.bmp
:
node index.js /path/to/image.bmp
This will load the file into the memory, dump some info about the image to the screen and save resulting bitmap to PNG file (by default to samples/out/
directory).
You can also specify more BMPs and even wildcards:
node index.js /path/to/image.bmp /path/to/images/*.bmp
Many programs and libraries that claim they can work with BMP files support only limited subset of the specification. This limits the usage of the format to the very core supported by most of the programs and disallows the use of any advanced features. For example, who knows that BMP can save alpha channel? Any feature invented by file format authors is useless if programmers don't want to implement it.
With Kaitai Struct, it's easy to define a human-readable format specification that is unambiguous and ready to be compiled into parser code, so the programmers have less troubles with the internal representation of the binary format and can focus on what to do with the data obtained from the file.
The BMP format specification in Kaitai Struct language is the core of this tool, it is used to be compiled into JavaScript parsing library to get structured data. The operating JavaScript code is just a small wrapper around the generated code from the resources/bmp.ksy
specification, it's simple to compile it into another language and implement some similar wrapping code. See Kaitai Struct project for more info.
To fetch the master
branch of the kaitai_struct_formats repo into the folder formats/
, run:
git pull --recurse-submodule
git submodule update --remote formats
Whenever the formats/image/bmp.ksy
spec is updated, it's necessary to recompile the parser code in src/Bmp.js
:
npm run build
The directory samples/ is designated for test samples. There are 4 subdirectories inside:
- in/ - input BMP samples
- out/ - output PNG files (generated by BMP Tool based on input BMP files from in/)
- exp/ - PNG samples that represent the correct (expected) interpretation of the corresponding BMP input files in the in/ directory
- diff/ - output directory for generated diffs between the samples from out/ and exp/ (they show how much differ the real output files from BMP Tool from the expected ones)
BMP Tool uses the excellent BMP Suite for testing.
There are two ways how you can get the samples from BMP Suite.
- Building samples from source (using
make
andgcc
, recommended) - Downloading samples in a ZIP archive
If the bmpsuite/
folder in the project root already contains the BMP samples (i.e. the subdirs b/
, g/
and q/
are full of .bmp
files), skip to section Testing on samples from BMP Suite.
Prerequisites:
- GNU Make (
make
)cc
-compatible C compiler (gcc
is recommended)First check if you don't have them already installed (run
make --version
+gcc --version
and see if it works fine).If you don't have both tools installed, you can install them by following these steps:
- for Linux - this command installs both GNU
make
andgcc
compiler- for Windows:
Install MinGW Installation Manager (the installer is called
mingw-get-setup.exe
) and launch it.In Basic Setup, mark
mingw32-base-bin
(includesgcc
) andmsys-base-bin
(includesmake
) for installation (right-click > Mark for Installation) and select Installation > Apply Changes in the top menu bar.Press
⊞ Win
+R
simultaneously to open the Run dialog.Type
SystemPropertiesAdvanced.exe
and click OK.Click Environment Variables... at the bottom of the dialog.
In User variables, search for a variable called
Path
(the letter case isn't important, it can be called e.g.PATH
orpATh
as well), select it and click the Edit... button.Note: If there is no
Path
variable, follow these steps instead.
- Click the New... button.
- Fill in Variable name:
Path
, Variable value:C:\MinGW\bin;C:\MinGW\msys\1.0\bin
- Click OK.
- Skip to step x. (10.)
Click New and type
C:\MinGW\bin
Click New again and type
C:\MinGW\msys\1.0\bin
Click OK.
Click OK again to confirm the Environment Variables dialog.
The commands
make
andgcc
should now be available in every new command line session. Runmake --version
andgcc --version
there to verify the installation.
The samples from BMP Suite can be compiled using the following commands (make sure the current working directory is the project root):
git clone --branch 2.7 --depth 1 https://github.com/jsummers/bmpsuite.git
cd bmpsuite/ || exit 1
export CC=gcc # (1.)
make clean && make check
cd ../ || exit 1
- You can choose any
cc
-compatible C compiler installed on your system, e.g.cc
,gcc
,clang
, etc.
Go to https://entropymine.com/jason/bmpsuite/releases/ and download the bmpsuite-2.7.zip
file. Then copy all files and directories from the archive directly to bmpsuite/
folder in the project root directory.
When you have the bmpsuite/
folder initialized and filled with .bmp samples (see Getting the BMP Suite samples for testing), it's necessary to prepare them for BMP Tool usage (i.e. moving them to samples/in/bmpsuite and samples/exp/bmpsuite folders):
./bin/prepare-bmpsuite
Then run BMP Tool with the sample input bitmaps and set the output directory to samples/out. The program takes just the file basename while generating output files, so it's necessary to process each folder (g/, q/ and b/) independently:
node index.js samples/in/bmpsuite/g/*.bmp -d samples/out/bmpsuite/g/
node index.js samples/in/bmpsuite/q/*.bmp -d samples/out/bmpsuite/q/
node index.js samples/in/bmpsuite/b/*.bmp -d samples/out/bmpsuite/b/
If you want to log the parse exceptions along with the .bmp filenames, add -l log/failed.log
to the end.
Diffs between the real output files (from out/) and "ideal" ones (from exp/) are generated as follows:
./bin/test
- Kaitai Struct - BMP format spec
resources/bmp.ksy
is compiled to JS parsing code - pngjs - for saving parsed bitmap to PNG image
- BMP Suite - sample files for testing
- pixelmatch - for generating diffs between test samples and images that are expected to match the interpretation of the samples