Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@sean_kenny/coloured-bitmap-to-geojson-polygons-js

Package Overview
Dependencies
Maintainers
0
Versions
9
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@sean_kenny/coloured-bitmap-to-geojson-polygons-js - npm Package Compare versions

Comparing version 0.1.0 to 0.1.1

build/image-data-to-polygons/consolidate-polygon-cells-into-corner-index-polygon.d.ts

3

build/bits-per-pixel.d.ts

@@ -7,4 +7,5 @@ export declare enum BitsPerPixel {

SIXTEEN_BIT_RGB = "SIXTEEN_BIT_RGB",
TWENTY_FOUR_BIT_RGB = "TWENTY_FOUR_BIT_RGB"
TWENTY_FOUR_BIT_RGB = "TWENTY_FOUR_BIT_RGB",
THIRTY_TWO_BIT_ALPHA_PLUS_RGB = "THIRTY_TWO_BIT_ALPHA_PLUS_RGB"
}
export declare const hexValueToBitsPerPixel: Record<number, BitsPerPixel | undefined>;

@@ -9,2 +9,3 @@ export var BitsPerPixel;

BitsPerPixel["TWENTY_FOUR_BIT_RGB"] = "TWENTY_FOUR_BIT_RGB";
BitsPerPixel["THIRTY_TWO_BIT_ALPHA_PLUS_RGB"] = "THIRTY_TWO_BIT_ALPHA_PLUS_RGB";
})(BitsPerPixel || (BitsPerPixel = {}));

@@ -18,2 +19,3 @@ export const hexValueToBitsPerPixel = {

24: BitsPerPixel.TWENTY_FOUR_BIT_RGB,
32: BitsPerPixel.THIRTY_TWO_BIT_ALPHA_PLUS_RGB
};

@@ -37,2 +37,3 @@ import { BitsPerPixel } from "./bits-per-pixel.js";

header: BmpFileMetadataHeader;
headerSizeBytes: 14;
}

@@ -42,5 +43,7 @@ export declare const extractHeaderFromHexBmpData: (input: ExtractHeaderFromHexBmpDataInput) => ExtractHeaderFromHexBmpDataOutput;

hexBmpData: string;
headerSizeBytes: 14;
}
interface ExtractInfoHeaderFromHexBmpDataOutput {
infoHeader: BmpFileMetadataInfoHeader;
infoHeaderSizeBytes: number;
}

@@ -50,2 +53,4 @@ export declare const extractInfoHeaderFromHexBmpData: (input: ExtractInfoHeaderFromHexBmpDataInput) => ExtractInfoHeaderFromHexBmpDataOutput;

infoHeader: Pick<BmpFileMetadataInfoHeader, 'bitsPerPixel' | 'numberOfColoursUsed'>;
infoHeaderSizeBytes: number;
headerSizeBytes: 14;
hexBmpData: string;

@@ -55,5 +60,5 @@ }

colourMap: BmpFileColourMap;
bytesUsedForColourMap: number;
colourMapSizeBytes: number;
}
export declare const extractColourMapFromHexBmpData: (input: ExtractColourMapFromHexBmpDataInput) => ExtractColourMapFromHexBmpDataOutput;
export {};

@@ -10,19 +10,25 @@ import { BitsPerPixel, hexValueToBitsPerPixel } from "./bits-per-pixel.js";

dataOffsetBytes: hexStringToNumericValue(input.hexBmpData.slice(20, 28)),
}
},
headerSizeBytes: 14
});
export const extractInfoHeaderFromHexBmpData = (input) => ({
infoHeader: {
infoHeaderSizeBytes: hexStringToNumericValue(input.hexBmpData.slice(28, 36)),
bmpWidthPx: hexStringToNumericValue(input.hexBmpData.slice(36, 44)),
bmpHeightPx: hexStringToNumericValue(input.hexBmpData.slice(44, 52)),
numberOfPlanes: hexStringToNumericValue(input.hexBmpData.slice(52, 56)),
bitsPerPixel: hexValueToBitsPerPixel[hexStringToNumericValue(input.hexBmpData.slice(56, 60))] ?? 'UNKNOWN',
compressionType: hexValueToCompressionType[hexStringToNumericValue(input.hexBmpData.slice(60, 68))] ?? 'UNKNOWN',
imageCompressedSizeBytes: hexStringToNumericValue(input.hexBmpData.slice(68, 76)),
horizontalPixelsPerMetre: hexStringToNumericValue(input.hexBmpData.slice(76, 84)),
verticalPixelsPerMetre: hexStringToNumericValue(input.hexBmpData.slice(84, 92)),
numberOfColoursUsed: hexStringToNumericValue(input.hexBmpData.slice(92, 100)),
numberOfImportantColours: hexStringToNumericValue(input.hexBmpData.slice(100, 108)),
}
});
export const extractInfoHeaderFromHexBmpData = (input) => {
const startIndex = input.headerSizeBytes * 2;
const infoHeaderSizeBytes = hexStringToNumericValue(input.hexBmpData.slice(startIndex, startIndex + 8));
return {
infoHeader: {
infoHeaderSizeBytes,
bmpWidthPx: hexStringToNumericValue(input.hexBmpData.slice(startIndex + 8, startIndex + 16)),
bmpHeightPx: hexStringToNumericValue(input.hexBmpData.slice(startIndex + 16, startIndex + 24)),
numberOfPlanes: hexStringToNumericValue(input.hexBmpData.slice(startIndex + 24, startIndex + 28)),
bitsPerPixel: hexValueToBitsPerPixel[hexStringToNumericValue(input.hexBmpData.slice(startIndex + 28, startIndex + 32))] ?? 'UNKNOWN',
compressionType: hexValueToCompressionType[hexStringToNumericValue(input.hexBmpData.slice(startIndex + 32, startIndex + 40))] ?? 'UNKNOWN',
imageCompressedSizeBytes: hexStringToNumericValue(input.hexBmpData.slice(startIndex + 40, startIndex + 48)),
horizontalPixelsPerMetre: hexStringToNumericValue(input.hexBmpData.slice(startIndex + 48, startIndex + 56)),
verticalPixelsPerMetre: hexStringToNumericValue(input.hexBmpData.slice(startIndex + 56, startIndex + 64)),
numberOfColoursUsed: hexStringToNumericValue(input.hexBmpData.slice(startIndex + 64, startIndex + 72)),
numberOfImportantColours: hexStringToNumericValue(input.hexBmpData.slice(startIndex + 72, startIndex + 80)),
},
infoHeaderSizeBytes
};
};
export const extractColourMapFromHexBmpData = (input) => {

@@ -38,8 +44,8 @@ const { bitsPerPixel, numberOfColoursUsed } = input.infoHeader;

colourMap: {},
bytesUsedForColourMap: 0
colourMapSizeBytes: 0
};
}
const bytesUsedForColourMap = 4 * numberOfColoursUsed;
const startIndexInHexBmpData = 108;
const endIndexInHexBmpData = startIndexInHexBmpData + bytesUsedForColourMap;
const colourMapSizeBytes = 4 * numberOfColoursUsed;
const startIndexInHexBmpData = (input.infoHeaderSizeBytes + input.headerSizeBytes) * 2;
const endIndexInHexBmpData = startIndexInHexBmpData + colourMapSizeBytes;
let currentIndex = 0;

@@ -66,4 +72,4 @@ let currentIndexInHexBmpData = startIndexInHexBmpData;

colourMap,
bytesUsedForColourMap
colourMapSizeBytes
};
};

@@ -5,4 +5,2 @@ import { BmpFileMetadata } from "./bmp-file-metadata.js";

inputFilePath: string;
bitmapWidthPx?: number | undefined;
bitmapHeightPx?: number | undefined;
colourToPropertiesMap: Record<string, TData>;

@@ -9,0 +7,0 @@ }

import { readFile } from "fs/promises";
import { extractColourMapFromHexBmpData, extractHeaderFromHexBmpData, extractInfoHeaderFromHexBmpData } from "./bmp-file-metadata.js";
import { extractImageDataFromHexBmpData } from "./image-data.js";
import { determineBitmapWidthAndHeight } from "./bitmap-width-and-height.js";
import { consolidateImageDataIntoPolygons } from "./image-data-to-polygons.js";
import { extractImageDataFromHexBmpData } from "./image-data/image-data.js";
import { consolidateImageDataIntoPolygons } from "./image-data-to-polygons/image-data-to-polygons.js";
export const exportColouredBitmapToGeoJSONPolygons = async (input) => {
const bmpData = await readFile(input.inputFilePath);
const hexBmpData = bmpData.toString('hex');
const { header } = extractHeaderFromHexBmpData({ hexBmpData });
const { infoHeader } = extractInfoHeaderFromHexBmpData({ hexBmpData });
const { colourMap, bytesUsedForColourMap } = extractColourMapFromHexBmpData({ hexBmpData, infoHeader });
const { bitmapWidthPx, bitmapHeightPx } = determineBitmapWidthAndHeight({
const { header, headerSizeBytes } = extractHeaderFromHexBmpData({ hexBmpData });
const { infoHeader, infoHeaderSizeBytes } = extractInfoHeaderFromHexBmpData({ hexBmpData, headerSizeBytes });
const { colourMap, colourMapSizeBytes } = extractColourMapFromHexBmpData({
hexBmpData,
infoHeader,
bitmapWidthPxOverride: input.bitmapWidthPx,
bitmapHeightPxOverride: input.bitmapHeightPx,
headerSizeBytes,
infoHeaderSizeBytes
});

@@ -20,8 +19,13 @@ const { imageData, allColoursPresent } = extractImageDataFromHexBmpData({

colourMap,
bitmapWidthPx,
bitmapHeightPx,
bytesUsedForColourMap
bitmapWidthPx: infoHeader.bmpWidthPx,
bitmapHeightPx: infoHeader.bmpHeightPx,
bitsPerPixel: infoHeader.bitsPerPixel,
headerSizeBytes,
infoHeaderSizeBytes,
colourMapSizeBytes
});
const { polygons } = consolidateImageDataIntoPolygons({
imageData,
bitmapWidthPx: infoHeader.bmpWidthPx,
bitmapHeightPx: infoHeader.bmpHeightPx,
allColoursPresent,

@@ -28,0 +32,0 @@ colourToPropertiesMap: input.colourToPropertiesMap

@@ -9,4 +9,4 @@ export const hexStringtoAsciiString = (hexString) => {

?.reverse()
?.join() ?? '';
?.join('') ?? '';
return parseInt(bigEndianHexString, 16);
};
{
"name": "@sean_kenny/coloured-bitmap-to-geojson-polygons-js",
"version": "0.1.0",
"version": "0.1.1",
"description": "A library for convering colour segmented bitmaps to a GeoJSON file of polygons.",

@@ -5,0 +5,0 @@ "scripts": {

# coloured-bitmap-to-geojson-js
coloured-bitmap-to-geojson-js
This is a TypeScript library which contains a function which converts `.bmp` bitmap files into a GeoJSON file.
[![Version](https://img.shields.io/npm/v/@sean_kenny/coloured-bitmap-to-geojson-polygons-js.svg)](https://www.npmjs.com/package/@sean_kenny/coloured-bitmap-to-geojson-polygons-js)
[![Downloads/week](https://img.shields.io/npm/dw/@sean_kenny/coloured-bitmap-to-geojson-polygons-js.svg)](https://www.npmjs.com/package/@sean_kenny/coloured-bitmap-to-geojson-polygons-js)
## Installation and Usage
```
$ npm install --save-dev @sean_kenny/coloured-bitmap-to-geojson-polygons-js
# or
$ yarn add -D @sean_kenny/coloured-bitmap-to-geojson-polygons-js
```
An output can then be generated by calling the `exportColouredBitmapToGeoJSONPolygons` function, which is the only function in the library. `colourToPropertiesMap` is an argument which can be used to attach properties (besides `colourHexCode`) to regions in your bitmap of a particular colour. Keys in `colourToPropertiesMap` must be lowercase (Ex. `ff0000` rather than `FF0000`).
```
const { outputGeoJSON, bmpFileMetadata } = exportColouredBitmapToGeoJSONPolygons({
inputFilePath: '/path/to/your/file/your_file.bmp'
colourToPropertiesMap: {
"#ff0000": {
zone: "The red zone"
},
"#00ff00": {
zone: "The green zone"
},
}
})
```
`bmpFileMetadata` will contain some data in the following format:
```
{
"header": {
"signature": "BM",
"fileSizeBytes": 120054,
"reservedField": "00000000",
"dataOffsetBytes": 54
},
"infoHeader": {
"bitsPerPixel": "TWENTY_FOUR_BIT_RGB",
"bmpHeightPx": 200,
"bmpWidthPx": 200,
"compressionType": "BI_RGB",
"horizontalPixelsPerMetre": 0,
"imageCompressedSizeBytes": 0,
"infoHeaderSizeBytes": 40,
"numberOfColoursUsed": 0,
"numberOfImportantColours": 0,
"numberOfPlanes": 1,
"verticalPixelsPerMetre": 0
},
"colourMap": {}
}
```
And `outputGeoJSON` will contain some data in the following format:
```
{
"type": "GeometryCollection",
"geometries": [
{
"type": "Polygon",
"coordinates": [
[
[-180, 90],
[-180, -90],
...
]
],
"properties": {
"colourHexCode": "#ff0000",
"data": { "zone": "The red zone" }
}
},
{
"type": "Polygon",
"coordinates": [
[
[-176.4, 90],
[-176.4, 89.1],
...
]
],
"properties": {
"colourHexCode": "#00ff00",
"data": { "zone": "The green zone" }
}
},
{
"type": "Polygon",
"coordinates": [
[
[1.8000000000000114, 1.7999999999999972],
[1.8000000000000114, 0],
...
]
],
"properties": {
"colourHexCode": "#0000ff",
"data": null
}
}
]
}
```
## Some sample inputs and outputs
Original BMP file | Output GeoJSON file
:-------------------------:|:-------------------------:
![](https://github.com/SeanKennyNF/coloured-bitmap-to-geojson-polygons-js/blob/main/readme-images/bmp-24.png) | ![](https://github.com/SeanKennyNF/coloured-bitmap-to-geojson-polygons-js/blob/main/readme-images/bmp-24-output.png)
![](https://github.com/SeanKennyNF/coloured-bitmap-to-geojson-polygons-js/blob/main/readme-images/provinces-subset-2.png) | ![](https://github.com/SeanKennyNF/coloured-bitmap-to-geojson-polygons-js/blob/main/readme-images/provinces-subset-2-output.png)
## Acknowledgements
There's some interesting reading about the exact structure of a bitmap file [here](https://en.wikipedia.org/wiki/BMP_file_format) which is what a lot of this library is based on.
All files whose name follows the pattern `provinces-XXXXXXX.bmp` which are used for testing are pulled directly from the `ab937cf899b75f74662a17574bd0d46072793beb` version of [Anbennar](https://bitbucket.org/JayBean/anbennar-eu4-fork-public-build) which was published to Bitbucket on August 23rd 2024. All credit for those bitmaps goes to their creator. ``bmp-24.bmp` was generously made public by the [University of South Carolina]('https://people.math.sc.edu/Burkardt/data/bmp/bmp.html').
You're welcome to use this library for anything you'd like. Please keep in mind this hasn't been thoroughly tested with a large variety of bitmap files so this may or may not work for your use case. Please reach out if you have a bitmap file which is not processed properly by this library and I'd be happy to work on something to make it work for you.
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc