You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
601 lines
20 KiB
601 lines
20 KiB
var Bitmap = module.exports = exports = function(buffer){
|
|
this.buffer = buffer;
|
|
this.initialized = false;
|
|
|
|
this.fileHeader = null;
|
|
this.infoHeader = null;
|
|
this.coreHeader = null;
|
|
this.colorPalette = null;
|
|
this.dataPos = -1;
|
|
};
|
|
Bitmap.prototype.CORE_TYPE_WINDOWS_V3 = 40;
|
|
Bitmap.prototype.CORE_TYPE_WINDOWS_V4 = 108;
|
|
Bitmap.prototype.CORE_TYPE_WINDOWS_V5 = 124;
|
|
Bitmap.prototype.CORE_TYPE_OS2_V1 = 12;
|
|
Bitmap.prototype.CORE_TYPE_OS2_V2 = 64;
|
|
Bitmap.prototype.BITMAPCOREHEADER = Bitmap.prototype.CORE_TYPE_OS2_V1;
|
|
Bitmap.prototype.BITMAPINFOHEADER = Bitmap.prototype.CORE_TYPE_WINDOWS_V3;
|
|
Bitmap.prototype.BITMAPINFOHEADER2 = Bitmap.prototype.CORE_TYPE_OS2_V2;
|
|
Bitmap.prototype.BITMAPV4HEADER = Bitmap.prototype.CORE_TYPE_WINDOWS_V4;
|
|
Bitmap.prototype.BITMAPV5HEADER = Bitmap.prototype.CORE_TYPE_WINDOWS_V5;
|
|
Bitmap.prototype.COMPRESSION_BI_RGB = 0;
|
|
Bitmap.prototype.COMPRESSION_BI_RLE8 = 1;
|
|
Bitmap.prototype.COMPRESSION_BI_RLE4 = 2;
|
|
Bitmap.prototype.COMPRESSION_BI_BITFIELDS = 3;
|
|
Bitmap.prototype.COMPRESSION_BI_JPEG = 4;
|
|
Bitmap.prototype.COMPRESSION_BI_PNG = 5;
|
|
Bitmap.prototype.BITCOUNT_2 = 1;
|
|
Bitmap.prototype.BITCOUNT_16 = 4;
|
|
Bitmap.prototype.BITCOUNT_256 = 8;
|
|
Bitmap.prototype.BITCOUNT_16bit = 16;
|
|
Bitmap.prototype.BITCOUNT_24bit = 24;
|
|
Bitmap.prototype.BITCOUNT_32bit = 32;
|
|
Bitmap.prototype.init = function(){
|
|
this.readFileHeader();
|
|
this.readInfoHeader();
|
|
this.readCoreHeader();
|
|
this.readColorPalette();
|
|
|
|
this.initDataPos();
|
|
this.initialized = true;
|
|
};
|
|
Bitmap.prototype.checkInit = function (){
|
|
if(!this.initialized){
|
|
throw new Error('not initialized');
|
|
}
|
|
/* nop */
|
|
};
|
|
Bitmap.prototype.isBitmap = function(){
|
|
this.checkInit();
|
|
|
|
if('BM' == this.fileHeader.bfType){
|
|
return true;
|
|
}
|
|
return false;
|
|
};
|
|
Bitmap.prototype.getData = function (){
|
|
this.checkInit();
|
|
|
|
if(this.COMPRESSION_BI_RGB !== this.coreHeader.__copmression__){
|
|
throw new Error('not supported compression: ' + this.coreHeader.__copmression__);
|
|
}
|
|
|
|
var bitCount = this.coreHeader.__bitCount__;
|
|
var width = this.getWidth();
|
|
var height = this.getHeight();
|
|
|
|
var line = (width * bitCount) / 8;
|
|
if(0 != (line % 4)){
|
|
line = ((line / 4) + 1) * 4;
|
|
}
|
|
|
|
var rgbaData = [];
|
|
var dataPos = this.dataPos;
|
|
for(var i = 0; i < height; ++i) {
|
|
var pos = dataPos + (line * (height - (i + 1)));
|
|
var buf = this.buffer.slice(pos, pos + line);
|
|
var color = this.mapColor(buf, bitCount);
|
|
rgbaData.push(color);
|
|
}
|
|
return rgbaData;
|
|
};
|
|
Bitmap.prototype.getWidth = function (){
|
|
this.checkInit();
|
|
|
|
return this.coreHeader.__width__;
|
|
};
|
|
Bitmap.prototype.getHeight = function (){
|
|
this.checkInit();
|
|
|
|
return this.coreHeader.__height__;
|
|
};
|
|
Bitmap.prototype.read = function(buf, offset, limit){
|
|
var read = [];
|
|
for(var i = offset, len = offset + limit; i < len; ++i){
|
|
read.push(buf.readInt8(i));
|
|
}
|
|
return new Buffer(read);
|
|
};
|
|
Bitmap.prototype.readFileHeader = function(){
|
|
var bfType = this.read(this.buffer, 0, 2);
|
|
var bfSize = this.read(this.buffer, 2, 4);
|
|
var bfReserved1 = this.read(this.buffer, 6, 2);
|
|
var bfReserved2 = this.read(this.buffer, 8, 2);
|
|
var bfOffBits = this.read(this.buffer, 10, 4);
|
|
|
|
this.fileHeader = {
|
|
bfType: bfType.toString('ascii'),
|
|
_bfType: bfType,
|
|
bfSize: bfSize.readUInt16LE(0),
|
|
_bfSize: bfSize,
|
|
bfReserved1: 0,
|
|
bfReserved2: 0,
|
|
bfOffBits: bfOffBits.readUInt16LE(0),
|
|
_bfOffBits: bfOffBits
|
|
};
|
|
};
|
|
Bitmap.prototype.readInfoHeader = function (){
|
|
this.infoHeader = this.read(this.buffer, 14, 4);
|
|
};
|
|
Bitmap.prototype.readCoreHeader = function (){
|
|
var coreType = this.infoHeader.readUInt16LE(0);
|
|
switch(coreType){
|
|
case this.BITMAPCOREHEADER:
|
|
return this.readCoreHeaderOS2_V1();
|
|
case this.BITMAPINFOHEADER2:
|
|
return this.readCoreHeaderOS2_V2();
|
|
case this.BITMAPV4HEADER:
|
|
return this.readCoreHeaderWINDOWS_V4();
|
|
case this.BITMAPV5HEADER:
|
|
return this.readCoreHeaderWINDOWS_V5();
|
|
case this.BITMAPINFOHEADER:
|
|
return this.readCoreHeaderWINDOWS_V3();
|
|
default:
|
|
throw new Error('unknown coreType: ' + coreType);
|
|
}
|
|
};
|
|
Bitmap.prototype.readCoreHeaderWINDOWS_V3 = function (){
|
|
var biWidth = this.read(this.buffer, 0x12, 4);
|
|
var biHeight = this.read(this.buffer, 0x16, 4);
|
|
var biPlanes = this.read(this.buffer, 0x1a, 2);
|
|
var biBitCount = this.read(this.buffer, 0x1c, 2);
|
|
var biCopmression = this.read(this.buffer, 0x1e, 4);
|
|
var biSizeImage = this.read(this.buffer, 0x22, 4);
|
|
var biXPixPerMeter = this.read(this.buffer, 0x26, 4);
|
|
var biYPixPerMeter = this.read(this.buffer, 0x2a, 4);
|
|
var biClrUsed = this.read(this.buffer, 0x2e, 4);
|
|
var biCirImportant = this.read(this.buffer, 0x32, 4);
|
|
|
|
this.coreHeader = {
|
|
__copmression__: biCopmression.readUInt16LE(0),
|
|
__bitCount__: biBitCount.readUInt8(0),
|
|
__width__: biWidth.readUInt16LE(0),
|
|
__height__: biHeight.readUInt16LE(0),
|
|
biWidth: biWidth.readUInt16LE(0),
|
|
_biWidth: biWidth,
|
|
biHeight: biHeight.readUInt16LE(0),
|
|
_biHeight: biHeight,
|
|
biPlanes: biPlanes.readUInt8(0),
|
|
_biPlanes: biPlanes,
|
|
biBitCount: biBitCount.readUInt8(0),
|
|
_biBitCount: biBitCount,
|
|
biCopmression: biCopmression.readUInt16LE(0),
|
|
_biCopmression: biCopmression,
|
|
biSizeImage: biSizeImage.readUInt16LE(0),
|
|
_biSizeImage: biSizeImage,
|
|
biXPixPerMeter: biXPixPerMeter.readUInt16LE(0),
|
|
_biXPixPerMeter: biXPixPerMeter,
|
|
biYPixPerMeter: biYPixPerMeter.readUInt16LE(0),
|
|
_biYPixPerMeter: biYPixPerMeter,
|
|
biClrUsed: biClrUsed.readUInt16LE(0),
|
|
_biClrUsed: biClrUsed,
|
|
biCirImportant: biCirImportant.readUInt16LE(0),
|
|
_biCirImportant: biCirImportant
|
|
};
|
|
};
|
|
Bitmap.prototype.readCoreHeaderWINDOWS_V4 = function (){
|
|
throw new Error('not yet impl');
|
|
|
|
var bV4Width = this.read(this.buffer, 0x12, 4);
|
|
var bV4Height = this.read(this.buffer, 0x16, 4);
|
|
var bV4Planes = this.read(this.buffer, 0x1a, 2);
|
|
var bV4BitCount = this.read(this.buffer, 0x1c, 2);
|
|
var bV4Compression = this.read(this.buffer, 0x1e, 4);
|
|
var bV4SizeImage = this.read(this.buffer, 0x22, 4);
|
|
var bV4XPelsPerMeter = this.read(this.buffer, 0x26, 4);
|
|
var bV4YPelsPerMeter = this.read(this.buffer, 0x2a, 4);
|
|
var bV4ClrUsed = this.read(this.buffer, 0x2e, 4);
|
|
var bV4ClrImportant = this.read(this.buffer, 0x32, 4);
|
|
var bV4RedMask = this.read(this.buffer, 0x36, 4);
|
|
var bV4GreenMask = this.read(this.buffer, 0x3a, 4);
|
|
var bV4BlueMask = this.read(this.buffer, 0x3e, 4);
|
|
var bV4AlphaMask = this.read(this.buffer, 0x42, 4);
|
|
var bV4CSType = this.read(this.buffer, 0x46, 4);
|
|
var bV4Endpoints = this.read(this.buffer, 0x6a, 36);
|
|
var bV4GammaRed = this.read(this.buffer, 0x6e, 4);
|
|
var bV4GammaGreen = this.read(this.buffer, 0x72, 4);
|
|
var bV4GammaBlue = this.read(this.buffer, 0x76, 4);
|
|
|
|
this.coreHeader = {
|
|
__compression__: bV4Compression.readUInt16LE(0),
|
|
__bitCount__: bV4BitCount.readUInt8(0),
|
|
__width__: bV4Width.readUInt16LE(0),
|
|
__height__: bV4Height.readUInt16LE(0),
|
|
bV4Width: bV4Width.readUInt16LE(0),
|
|
_bV4Width: bV4Width,
|
|
bV4Height: bV4Height.readUInt16LE(0),
|
|
_bV4Height: bV4Height,
|
|
bV4Planes: bV4Planes.readUInt8(0),
|
|
_bV4Planes: bV4Planes,
|
|
bV4BitCount: bV4BitCount.readUInt8(0),
|
|
_bV4BitCount: bV4BitCount,
|
|
bV4Compression: bV4Compression.readUInt16LE(0),
|
|
_bV4Compression: bV4Compression,
|
|
bV4SizeImage: bV4SizeImage.readUInt16LE(0),
|
|
_bV4SizeImage: bV4SizeImage,
|
|
bV4XPelsPerMeter: bV4XPelsPerMeter.readUInt16LE(0),
|
|
_bV4XPelsPerMeter: bV4XPelsPerMeter,
|
|
bV4YPelsPerMeter: bV4YPelsPerMeter.readUInt16LE(0),
|
|
_bV4YPelsPerMeter: bV4YPelsPerMeter,
|
|
bV4ClrUsed: bV4ClrUsed.readUInt16LE(0),
|
|
_bV4ClrUsed: bV4ClrUsed,
|
|
bV4ClrImportant: bV4ClrImportant.readUInt16LE(0),
|
|
_bV4ClrImportant: bV4ClrImportant,
|
|
bV4RedMask: bV4RedMask.readUInt16LE(0),
|
|
_bV4RedMask: bV4RedMask,
|
|
bV4GreenMask: bV4GreenMask.readUInt16LE(0),
|
|
_bV4GreenMask: bV4GreenMask,
|
|
bV4BlueMask: bV4BlueMask.readUInt16LE(0),
|
|
_bV4BlueMask: bV4BlueMask,
|
|
bV4AlphaMask: bV4AlphaMask.readUInt16LE(0),
|
|
_bV4AlphaMask: bV4AlphaMask,
|
|
bV4CSType: bV4CSType.readUInt16LE(0),
|
|
_bV4CSType: bV4CSType,
|
|
bV4Endpoints: null,
|
|
_bV4Endpoints: bV4Endpoints,
|
|
bV4GammaRed: bV4GammaRed.readUInt16LE(0),
|
|
_bV4GammaRed: bV4GammaRed,
|
|
bV4GammaGreen: bV4GammaGreen.readUInt16LE(0),
|
|
_bV4GammaGreen: bV4GammaGreen,
|
|
bV4GammaBlue: bV4GammaBlue.readUInt16LE(0),
|
|
_bV4GammaBlue: bV4GammaBlue
|
|
};
|
|
};
|
|
Bitmap.prototype.readCoreHeaderWINDOWS_V5 = function (){
|
|
throw new Error('not yet impl');
|
|
|
|
var bV5Width = this.read(this.buffer, 0x12, 4);
|
|
var bV5Height = this.read(this.buffer, 0x16, 4);
|
|
var bV5Planes = this.read(this.buffer, 0x1a, 2);
|
|
var bV5BitCount = this.read(this.buffer, 0x1c, 2);
|
|
var bV5Compression = this.read(this.buffer, 0x1e, 4);
|
|
var bV5SizeImage = this.read(this.buffer, 0x22, 4);
|
|
var bV5XPelsPerMeter = this.read(this.buffer, 0x26, 4);
|
|
var bV5YPelsPerMeter = this.read(this.buffer, 0x2a, 4);
|
|
var bV5ClrUsed = this.read(this.buffer, 0x2e, 4);
|
|
var bV5ClrImportant = this.read(this.buffer, 0x32, 4);
|
|
var bV5RedMask = this.read(this.buffer, 0x36, 4);
|
|
var bV5GreenMask = this.read(this.buffer, 0x3a, 4);
|
|
var bV5BlueMask = this.read(this.buffer, 0x3e, 4);
|
|
var bV5AlphaMask = this.read(this.buffer, 0x42, 4);
|
|
var bV5CSType = this.read(this.buffer, 0x46, 4);
|
|
var bV5Endpoints = this.read(this.buffer, 0x6a, 36);
|
|
var bV5GammaRed = this.read(this.buffer, 0x6e, 4);
|
|
var bV5GammaGreen = this.read(this.buffer, 0x72, 4);
|
|
var bV5GammaBlue = this.read(this.buffer, 0x76, 4);
|
|
var bV5Intent = this.read(this.buffer, 0x7a, 4);
|
|
var bV5ProfileData = this.read(this.buffer, 0x7e, 4);
|
|
var bV5ProfileSize = this.read(this.buffer, 0x82, 4);
|
|
var bV5Reserved = this.read(this.buffer, 0x86, 4);
|
|
|
|
this.coreHeader = {
|
|
__compression__: bV5Compression.readUInt16LE(0),
|
|
__bitCount__: bV5BitCount.readUInt8(0),
|
|
__width__: bV5Width.readUInt16LE(0),
|
|
__height__: bV5Height.readUInt16LE(0),
|
|
bV5Width: bV5Width.readUInt16LE(0),
|
|
_bV5Width: bV5Width,
|
|
bV5Height: bV5Height.readUInt16LE(0),
|
|
_bV5Height: bV5Height,
|
|
bV5Planes: bV5Planes.readUInt8(0),
|
|
_bV5Planes: bV5Planes,
|
|
bV5BitCount: bV5BitCount.readUInt8(0),
|
|
_bV5BitCount: bV5BitCount,
|
|
bV5Compression: bV5Compression.readUInt16LE(0),
|
|
_bV5Compression: bV5Compression,
|
|
bV5SizeImage: bV5SizeImage.readUInt16LE(0),
|
|
_bV5SizeImage: bV5SizeImage,
|
|
bV5XPelsPerMeter: bV5XPelsPerMeter.readUInt16LE(0),
|
|
_bV5XPelsPerMeter: bV5XPelsPerMeter,
|
|
bV5YPelsPerMeter: bV5YPelsPerMeter.readUInt16LE(0),
|
|
_bV5YPelsPerMeter: bV5YPelsPerMeter,
|
|
bV5ClrUsed: bV5ClrUsed.readUInt16LE(0),
|
|
_bV5ClrUsed: bV5ClrUsed,
|
|
bV5ClrImportant: bV5ClrImportant.readUInt16LE(0),
|
|
_bV5ClrImportant: bV5ClrImportant,
|
|
bV5RedMask: bV5RedMask.readUInt16LE(0),
|
|
_bV5RedMask: bV5RedMask,
|
|
bV5GreenMask: bV5GreenMask.readUInt16LE(0),
|
|
_bV5GreenMask: bV5GreenMask,
|
|
bV5BlueMask: bV5BlueMask.readUInt16LE(0),
|
|
_bV5BlueMask: bV5BlueMask,
|
|
bV5AlphaMask: bV5AlphaMask.readUInt16LE(0),
|
|
_bV5AlphaMask: bV5AlphaMask,
|
|
bV5CSType: bV5CSType.readUInt16LE(0),
|
|
_bV5CSType: bV5CSType,
|
|
bV5Endpoints: null,
|
|
_bV5Endpoints: bV5Endpoints,
|
|
bV5GammaRed: bV5GammaRed.readUInt16LE(0),
|
|
_bV5GammaRed: bV5GammaRed,
|
|
bV5GammaGreen: bV5GammaGreen.readUInt16LE(0),
|
|
_bV5GammaGreen: bV5GammaGreen,
|
|
bV5GammaBlue: bV5GammaBlue.readUInt16LE(0),
|
|
_bV5GammaBlue: bV5GammaBlue,
|
|
bV5Intent: bV5Intent.readUInt16LE(0),
|
|
_bV5Intent: bV5Intent,
|
|
bV5ProfileData: bV5ProfileData.readUInt16LE(0),
|
|
_bV5ProfileData: bV5ProfileData,
|
|
bV5ProfileSize: bV5ProfileSize.readUInt16LE(0),
|
|
_bV5ProfileSize: bV5ProfileSize,
|
|
bV5Reserved: 0,
|
|
_bV5Reserved: bV5Reserved
|
|
};
|
|
};
|
|
Bitmap.prototype.readCoreHeaderOS2_V1 = function (){
|
|
throw new Error('not yet impl');
|
|
|
|
var bcWidth = this.read(this.buffer, 0x12, 2);
|
|
var bcHeight = this.read(this.buffer, 0x14, 2);
|
|
var bcPlanes = this.read(this.buffer, 0x16, 2);
|
|
var bcBitCount = this.read(this.buffer, 0x18, 2);
|
|
|
|
this.coreHeader = {
|
|
__compression__: 0,
|
|
__bitCount__: bcBitCount.readUInt8(0),
|
|
__width__: bcWidth.readUInt8(0),
|
|
__height__: bcHeight.readUInt8(0),
|
|
bcWidth: bcWidth.readUInt8(0),
|
|
_bcWidth: bcWidth,
|
|
bcHeight: bcHeight.readUInt8(0),
|
|
_bcHeight: bcHeight,
|
|
bcPlanes: bcPlanes.readUInt8(0),
|
|
_bcPlanes: bcPlanes,
|
|
bcBitCount: bcBitCount.readUInt8(0),
|
|
_bcBitCount: bcBitCount
|
|
};
|
|
};
|
|
Bitmap.prototype.readCoreHeaderOS2_V2 = function (){
|
|
throw new Error('not yet impl');
|
|
|
|
var cx = this.read(this.buffer, 0x12, 4);
|
|
var cy = this.read(this.buffer, 0x16, 4);
|
|
var cPlanes = this.read(this.buffer, 0x1a, 2);
|
|
var cBitCount = this.read(this.buffer, 0x1c, 2);
|
|
var ulCompression = this.read(this.buffer, 0x1e, 4);
|
|
var cbImage = this.read(this.buffer, 0x22, 4);
|
|
var cxResolution = this.read(this.buffer, 0x26, 4);
|
|
var cyResolution = this.read(this.buffer, 0x2a, 4);
|
|
var cclrUsed = this.read(this.buffer, 0x2e, 4);
|
|
var cclrImportant = this.read(this.buffer, 0x32, 4);
|
|
var usUnits = this.read(this.buffer, 0x36, 2);
|
|
var usReserved = this.read(this.buffer, 0x38, 2);
|
|
var usRecording = this.read(this.buffer, 0x3a, 2);
|
|
var usRendering = this.read(this.buffer, 0x3c, 2);
|
|
var cSize1 = this.read(this.buffer, 0x3e, 4);
|
|
var cSize2 = this.read(this.buffer, 0x42, 4);
|
|
var ulColorEncoding = this.read(this.buffer, 0x46, 4);
|
|
var ulIdentifier = this.read(this.buffer, 0x4a, 4);
|
|
|
|
this.coreHeader = {
|
|
__compression__: ulCompression.readUInt16LE(0),
|
|
__bitCount__: cBitCount.readUInt8(0),
|
|
__width__: cx.readUInt16LE(0),
|
|
__height__: cy.readUInt16LE(0),
|
|
cx: cx.readUInt16LE(0),
|
|
_cx: cx,
|
|
cy: cy.readUInt16LE(0),
|
|
_cy: cy,
|
|
cPlanes: cPlanes.readUInt8(0),
|
|
_cPlanes: cPlanes,
|
|
cBitCount: cBitCount.readUInt8(0),
|
|
_cBitCount: cBitCount,
|
|
ulCompression: ulCompression.readUInt16LE(0),
|
|
_ulCompression: ulCompression,
|
|
cbImage: cbImage.readUInt16LE(0),
|
|
_cbImage: cbImage,
|
|
cxResolution: cxResolution.readUInt16LE(0),
|
|
_cxResolution: cxResolution,
|
|
cyResolution: cyResolution.readUInt16LE(0),
|
|
_cyResolution: cyResolution,
|
|
cclrUsed: cclrUsed.readUInt16LE(0),
|
|
_cclrUsed: cclrUsed,
|
|
cclrImportant: cclrImportant.readUInt16LE(0),
|
|
_cclrImportant: cclrImportant,
|
|
usUnits: usUnits.readUInt8(0),
|
|
_usUnits: usUnits,
|
|
usReserved: usReserved.readUInt8(0),
|
|
_usReserved: usReserved,
|
|
usRecording: usRecording.readUInt8(0),
|
|
_usRecording: usRecording,
|
|
usRendering: usRendering.readUInt8(0),
|
|
_usRendering: usRendering,
|
|
cSize1: cSize1.readUInt16LE(0),
|
|
_cSize1: cSize1,
|
|
cSize2: cSize2.readUInt16LE(0),
|
|
_cSize1: cSize1,
|
|
ulColorEncoding: ulColorEncoding.readUInt16LE(0),
|
|
_ulColorEncoding: ulColorEncoding,
|
|
ulIdentifier: ulIdentifier.readUInt16LE(0),
|
|
_ulIdentifier: ulIdentifier
|
|
};
|
|
};
|
|
Bitmap.prototype.readColorPalette = function (){
|
|
var bitCount = this.coreHeader.__bitCount__;
|
|
if(this.BITCOUNT_16bit == bitCount){
|
|
return /* nop */;
|
|
}
|
|
if(this.BITCOUNT_24bit == bitCount){
|
|
return /* nop */;
|
|
}
|
|
if(this.BITCOUNT_32bit == bitCount){
|
|
return /* nop */;
|
|
}
|
|
|
|
var coreType = this.infoHeader.readUInt16LE(0);
|
|
switch(coreType){
|
|
case this.BITMAPCOREHEADER:
|
|
return this.readColorPalette_RGBTRIPLE(bitCount, 0x1a);
|
|
case this.BITMAPINFOHEADER2:
|
|
return this.readColorPalette_RGBTRIPLE(bitCount, 0x4e);
|
|
case this.BITMAPV4HEADER:
|
|
return this.readColorPalette_RGBQUAD(bitCount, 0x7a);
|
|
case this.BITMAPV5HEADER:
|
|
return this.readColorPalette_RGBQUAD(bitCount, 0x8a);
|
|
case this.BITMAPINFOHEADER:
|
|
return this.readColorPalette_RGBQUAD(bitCount, 0x36);
|
|
default:
|
|
throw new Error('unknown colorPalette: ' + coreType + ',' + bitCount);
|
|
}
|
|
};
|
|
Bitmap.prototype.readColorPalette_RGBTRIPLE = function (bitCount, startPos){
|
|
throw new Error('not yet impl');
|
|
};
|
|
Bitmap.prototype.readColorPalette_RGBQUAD = function (bitCount, startPos){
|
|
if(this.BITCOUNT_2 == bitCount){
|
|
return this.readRGBQUAD(1 << this.BITCOUNT_2, startPos);
|
|
}
|
|
if(this.BITCOUNT_16 == bitCount){
|
|
return this.readRGBQUAD(1 << this.BITCOUNT_16, startPos);
|
|
}
|
|
if(this.BITCOUNT_256 == bitCount){
|
|
return this.readRGBQUAD(1 << this.BITCOUNT_256, startPos);
|
|
}
|
|
throw new Error('unknown bitCount: ' + bitCount);
|
|
};
|
|
Bitmap.prototype.readRGBQUAD = function(count, startPos){
|
|
var palette = [];
|
|
for(var i = startPos, len = startPos + (4 * count); i < len; i += 4){
|
|
palette.push({
|
|
rgbBlue: this.read(this.buffer, i, 1).readUInt8(0),
|
|
rgbGreen: this.read(this.buffer, i + 1, 1).readUInt8(0),
|
|
rgbRed: this.read(this.buffer, i + 2, 1).readUInt8(0),
|
|
rgbReserved: this.read(this.buffer, i + 3, 1).readUInt8(0)
|
|
});
|
|
}
|
|
this.colorPalette = palette;
|
|
};
|
|
Bitmap.prototype.initDataPos = function(){
|
|
var bitCount = this.coreHeader.__bitCount__;
|
|
var hasPalette = true;
|
|
if(this.BITCOUNT_16bit == bitCount){
|
|
hasPalette = true;
|
|
}
|
|
if(this.BITCOUNT_24bit == bitCount){
|
|
hasPalette = true;
|
|
}
|
|
if(this.BITCOUNT_32bit == bitCount){
|
|
hasPalette = true;
|
|
}
|
|
|
|
var coreType = this.infoHeader.readUInt16LE(0);
|
|
switch(coreType){
|
|
case this.BITMAPCOREHEADER:
|
|
this.dataPos = 0x1a;
|
|
if(hasPalette){
|
|
this.dataPos = this.dataPos + (3 * (1 << bitCount));
|
|
}
|
|
break;
|
|
case this.BITMAPINFOHEADER2:
|
|
this.dataPos = 0x4e;
|
|
if(hasPalette){
|
|
this.dataPos = this.dataPos + (3 * (1 << bitCount));
|
|
}
|
|
break;
|
|
case this.BITMAPV4HEADER:
|
|
this.dataPos = 0x7a;
|
|
if(hasPalette){
|
|
this.dataPos = this.dataPos + (4 * (1 << bitCount));
|
|
}
|
|
break;
|
|
case this.BITMAPV5HEADER:
|
|
this.dataPos = 0x8a;
|
|
if(hasPalette){
|
|
this.dataPos = this.dataPos + (4 * (1 << bitCount));
|
|
}
|
|
case this.BITMAPINFOHEADER:
|
|
this.dataPos = 0x36;
|
|
if(hasPalette){
|
|
this.dataPos = this.dataPos + (4 * (1 << bitCount));
|
|
}
|
|
break;
|
|
default:
|
|
throw new Error('unknown colorPalette: ' + coreType + ',' + bitCount);
|
|
}
|
|
};
|
|
Bitmap.prototype.mapRGBA = function(r, g, b, a){
|
|
var hex = [];
|
|
|
|
var padHex = function(value){
|
|
var h = value.toString(16);
|
|
if(value < 0x0f){
|
|
return '0' + h;
|
|
}
|
|
return h;
|
|
};
|
|
|
|
hex.push(padHex(r));
|
|
hex.push(padHex(g));
|
|
hex.push(padHex(b));
|
|
|
|
return '#' + hex.join('');
|
|
};
|
|
Bitmap.prototype.mapColor = function(bmpBuf, bitCount){
|
|
var b, g, r, a;
|
|
var length = bmpBuf.length;
|
|
var colorData = [];
|
|
|
|
if(this.BITCOUNT_2 == bitCount){
|
|
for(var i = 0; i < length; ++i){
|
|
var paletteValue = bmpBuf[i];
|
|
var bin = paletteValue.toString(2);
|
|
bin = new Array(8 - bin.length).join('0') + bin;
|
|
|
|
for(var j = 0; j < bin.length; ++j){
|
|
var paletteIndex = parseInt(bin.substring(j, j + 1), 10);
|
|
var palette = this.colorPalette[paletteIndex];
|
|
colorData.push(this.mapRGBA(palette.rgbRed, palette.rgbGreen, palette.rgbBlue, -1));
|
|
}
|
|
}
|
|
return colorData;
|
|
}
|
|
if(this.BITCOUNT_16 == bitCount){
|
|
for(var i = 0; i < length; i += 2){
|
|
var paletteHigh = bmpBuf.readUInt8(i);
|
|
var paletteLow = bmpBuf.readUInt8(i + 1);
|
|
var indexes = [paletteHigh, paletteLow];
|
|
indexes.forEach(function(paletteIndex){
|
|
var palette = this.colorPalette[paletteIndex];
|
|
colorData.push(this.mapRGBA(palette.rgbRed, palette.rgbGreen, palette.rgbBlue, -1));
|
|
});
|
|
}
|
|
|
|
return colorData;
|
|
}
|
|
if(this.BITCOUNT_256 == bitCount){
|
|
for(var i = 0; i < length; ++i){
|
|
var paletteIndex = bmpBuf.readUInt16LE(i);
|
|
var palette = this.colorPalette[paletteIndex];
|
|
colorData.push(this.mapRGBA(palette.rgbRed, palette.rgbGreen, palette.rgbBlue, -1));
|
|
}
|
|
return colorData;
|
|
}
|
|
if(this.BITCOUNT_16bit == bitCount){
|
|
for(var i = 0; i < length; i += 3){
|
|
b = bmpBuf[i];
|
|
g = bmpBuf[i + 1];
|
|
r = bmpBuf[i + 2];
|
|
colorData.push(this.mapRGBA(r, g, b, -1));
|
|
}
|
|
return colorData;
|
|
}
|
|
if(this.BITCOUNT_24bit == bitCount){
|
|
for(var i = 0; i < length; i += 3){
|
|
b = bmpBuf[i];
|
|
g = bmpBuf[i + 1];
|
|
r = bmpBuf[i + 2];
|
|
colorData.push(this.mapRGBA(r, g, b, -1));
|
|
}
|
|
return colorData;
|
|
}
|
|
if(this.BITCOUNT_32bit == bitCount){
|
|
for(var i = 0; i < length; i += 4){
|
|
b = bmpBuf[i];
|
|
g = bmpBuf[i + 1];
|
|
r = bmpBuf[i + 2];
|
|
a = bmpBuf[i + 3];
|
|
colorData.push(this.mapRGBA(r, g, b, a));
|
|
}
|
|
return colorData;
|
|
}
|
|
throw new Error('unknown bitCount: ' + bitCount);
|
|
};
|
|
|