Comparing version 0.0.3 to 0.1.0
@@ -0,0 +0,0 @@ /** |
@@ -12,6 +12,7 @@ /** | ||
this.is_with_alpha = !!is_with_alpha; | ||
this.bottom_up = true; | ||
this.flag = this.buffer.toString("utf-8", 0, this.pos += 2); | ||
if (this.flag != "BM") throw new Error("Invalid BMP File"); | ||
this.parseHeader(); | ||
this.parseBGR(); | ||
this.parseRGBA(); | ||
} | ||
@@ -30,3 +31,3 @@ | ||
this.pos += 4; | ||
this.height = this.buffer.readUInt32LE(this.pos); | ||
this.height = this.buffer.readInt32LE(this.pos); | ||
this.pos += 4; | ||
@@ -52,3 +53,3 @@ this.planes = this.buffer.readUInt16LE(this.pos); | ||
this.bitPP = 15 | ||
}; | ||
} | ||
if (this.bitPP < 15) { | ||
@@ -70,17 +71,14 @@ var len = this.colors === 0 ? 1 << this.bitPP : this.colors; | ||
} | ||
if(this.height < 0) { | ||
this.height *= -1; | ||
this.bottom_up = false; | ||
} | ||
} | ||
BmpDecoder.prototype.parseBGR = function() { | ||
this.pos = this.offset; | ||
try { | ||
BmpDecoder.prototype.parseRGBA = function() { | ||
var bitn = "bit" + this.bitPP; | ||
var len = this.width * this.height * 4; | ||
this.data = new Buffer(len); | ||
this[bitn](); | ||
} catch (e) { | ||
console.log("bit decode error:" + e); | ||
} | ||
}; | ||
@@ -91,13 +89,17 @@ | ||
var mode = xlen%4; | ||
var y = this.height >= 0 ? this.height - 1 : -this.height | ||
for (var y = this.height - 1; y >= 0; y--) { | ||
var line = this.bottom_up ? y : this.height - 1 - y | ||
for (var x = 0; x < xlen; x++) { | ||
var b = this.buffer.readUInt8(this.pos++); | ||
var location = y * this.width * 4 + x*8*4; | ||
var location = line * this.width * 4 + x*8*4; | ||
for (var i = 0; i < 8; i++) { | ||
if(x*8+i<this.width){ | ||
var rgb = this.palette[((b>>(7-i))&0x1)]; | ||
this.data[location+i*4] = rgb.blue; | ||
this.data[location+i*4 + 1] = rgb.green; | ||
this.data[location+i*4 + 2] = rgb.red; | ||
this.data[location+i*4 + 3] = 0xFF; | ||
this.data[location+i*4] = 0; | ||
this.data[location+i*4 + 1] = rgb.blue; | ||
this.data[location+i*4 + 2] = rgb.green; | ||
this.data[location+i*4 + 3] = rgb.red; | ||
}else{ | ||
@@ -116,31 +118,119 @@ break; | ||
BmpDecoder.prototype.bit4 = function() { | ||
var xlen = Math.ceil(this.width/2); | ||
var mode = xlen%4; | ||
for (var y = this.height - 1; y >= 0; y--) { | ||
for (var x = 0; x < xlen; x++) { | ||
var b = this.buffer.readUInt8(this.pos++); | ||
var location = y * this.width * 4 + x*2*4; | ||
//RLE-4 | ||
if(this.compress == 2){ | ||
this.data.fill(0xff); | ||
var before = b>>4; | ||
var after = b&0x0F; | ||
var location = 0; | ||
var lines = this.bottom_up?this.height-1:0; | ||
var low_nibble = false;//for all count of pixel | ||
var rgb = this.palette[before]; | ||
this.data[location] = rgb.blue; | ||
this.data[location + 1] = rgb.green; | ||
this.data[location + 2] = rgb.red; | ||
this.data[location + 3] = 0xFF; | ||
while(location<this.data.length){ | ||
var a = this.buffer.readUInt8(this.pos++); | ||
var b = this.buffer.readUInt8(this.pos++); | ||
//absolute mode | ||
if(a == 0){ | ||
if(b == 0){//line end | ||
if(this.bottom_up){ | ||
lines--; | ||
}else{ | ||
lines++; | ||
} | ||
location = lines*this.width*4; | ||
low_nibble = false; | ||
continue; | ||
}else if(b == 1){//image end | ||
break; | ||
}else if(b ==2){ | ||
//offset x,y | ||
var x = this.buffer.readUInt8(this.pos++); | ||
var y = this.buffer.readUInt8(this.pos++); | ||
if(this.bottom_up){ | ||
lines-=y; | ||
}else{ | ||
lines+=y; | ||
} | ||
if(x*2+1>=this.width)break; | ||
location +=(y*this.width*4+x*4); | ||
}else{ | ||
var c = this.buffer.readUInt8(this.pos++); | ||
for(var i=0;i<b;i++){ | ||
if (low_nibble) { | ||
setPixelData.call(this, (c & 0x0f)); | ||
} else { | ||
setPixelData.call(this, (c & 0xf0)>>4); | ||
} | ||
rgb = this.palette[after]; | ||
this.data[location+4] = rgb.blue; | ||
this.data[location+4 + 1] = rgb.green; | ||
this.data[location+4 + 2] = rgb.red; | ||
this.data[location+4 + 3] = 0xFF; | ||
} | ||
if ((i & 1) && (i+1 < b)){ | ||
c = this.buffer.readUInt8(this.pos++); | ||
} | ||
if (mode != 0){ | ||
this.pos+=(4 - mode); | ||
low_nibble = !low_nibble; | ||
} | ||
if ((((b+1) >> 1) & 1 ) == 1){ | ||
this.pos++ | ||
} | ||
} | ||
}else{//encoded mode | ||
for (var i = 0; i < a; i++) { | ||
if (low_nibble) { | ||
setPixelData.call(this, (b & 0x0f)); | ||
} else { | ||
setPixelData.call(this, (b & 0xf0)>>4); | ||
} | ||
low_nibble = !low_nibble; | ||
} | ||
} | ||
} | ||
function setPixelData(rgbIndex){ | ||
var rgb = this.palette[rgbIndex]; | ||
this.data[location] = 0; | ||
this.data[location + 1] = rgb.blue; | ||
this.data[location + 2] = rgb.green; | ||
this.data[location + 3] = rgb.red; | ||
location+=4; | ||
} | ||
}else{ | ||
var xlen = Math.ceil(this.width/2); | ||
var mode = xlen%4; | ||
for (var y = this.height - 1; y >= 0; y--) { | ||
var line = this.bottom_up ? y : this.height - 1 - y | ||
for (var x = 0; x < xlen; x++) { | ||
var b = this.buffer.readUInt8(this.pos++); | ||
var location = line * this.width * 4 + x*2*4; | ||
var before = b>>4; | ||
var after = b&0x0F; | ||
var rgb = this.palette[before]; | ||
this.data[location] = 0; | ||
this.data[location + 1] = rgb.blue; | ||
this.data[location + 2] = rgb.green; | ||
this.data[location + 3] = rgb.red; | ||
if(x*2+1>=this.width)break; | ||
rgb = this.palette[after]; | ||
this.data[location+4] = 0; | ||
this.data[location+4 + 1] = rgb.blue; | ||
this.data[location+4 + 2] = rgb.green; | ||
this.data[location+4 + 3] = rgb.red; | ||
} | ||
if (mode != 0){ | ||
this.pos+=(4 - mode); | ||
} | ||
} | ||
} | ||
} | ||
@@ -150,24 +240,92 @@ }; | ||
BmpDecoder.prototype.bit8 = function() { | ||
var mode = this.width%4; | ||
for (var y = this.height - 1; y >= 0; y--) { | ||
for (var x = 0; x < this.width; x++) { | ||
var b = this.buffer.readUInt8(this.pos++); | ||
var location = y * this.width * 4 + x*4; | ||
if(b < this.palette.length) { | ||
var rgb = this.palette[b]; | ||
this.data[location] = rgb.blue; | ||
this.data[location + 1] = rgb.green; | ||
this.data[location + 2] = rgb.red; | ||
this.data[location + 3] = 0xFF; | ||
} else { | ||
this.data[location] = 0xFF; | ||
this.data[location + 1] = 0xFF; | ||
this.data[location + 2] = 0xFF; | ||
this.data[location + 3] = 0xFF; | ||
} | ||
//RLE-8 | ||
if(this.compress == 1){ | ||
this.data.fill(0xff); | ||
var location = 0; | ||
var lines = this.bottom_up?this.height-1:0; | ||
while(location<this.data.length){ | ||
var a = this.buffer.readUInt8(this.pos++); | ||
var b = this.buffer.readUInt8(this.pos++); | ||
//absolute mode | ||
if(a == 0){ | ||
if(b == 0){//line end | ||
if(this.bottom_up){ | ||
lines--; | ||
}else{ | ||
lines++; | ||
} | ||
location = lines*this.width*4; | ||
continue; | ||
}else if(b == 1){//image end | ||
break; | ||
}else if(b ==2){ | ||
//offset x,y | ||
var x = this.buffer.readUInt8(this.pos++); | ||
var y = this.buffer.readUInt8(this.pos++); | ||
if(this.bottom_up){ | ||
lines-=y; | ||
}else{ | ||
lines+=y; | ||
} | ||
location +=(y*this.width*4+x*4); | ||
}else{ | ||
for(var i=0;i<b;i++){ | ||
var c = this.buffer.readUInt8(this.pos++); | ||
setPixelData.call(this, c); | ||
} | ||
if(b&1 == 1){ | ||
this.pos++; | ||
} | ||
} | ||
}else{//encoded mode | ||
for (var i = 0; i < a; i++) { | ||
setPixelData.call(this, b); | ||
} | ||
} | ||
} | ||
function setPixelData(rgbIndex){ | ||
var rgb = this.palette[rgbIndex]; | ||
this.data[location] = 0; | ||
this.data[location + 1] = rgb.blue; | ||
this.data[location + 2] = rgb.green; | ||
this.data[location + 3] = rgb.red; | ||
location+=4; | ||
} | ||
}else { | ||
var mode = this.width % 4; | ||
for (var y = this.height - 1; y >= 0; y--) { | ||
var line = this.bottom_up ? y : this.height - 1 - y | ||
for (var x = 0; x < this.width; x++) { | ||
var b = this.buffer.readUInt8(this.pos++); | ||
var location = line * this.width * 4 + x * 4; | ||
if (b < this.palette.length) { | ||
var rgb = this.palette[b]; | ||
this.data[location] = 0; | ||
this.data[location + 1] = rgb.blue; | ||
this.data[location + 2] = rgb.green; | ||
this.data[location + 3] = rgb.red; | ||
} else { | ||
this.data[location] = 0; | ||
this.data[location + 1] = 0xFF; | ||
this.data[location + 2] = 0xFF; | ||
this.data[location + 3] = 0xFF; | ||
} | ||
} | ||
if (mode != 0) { | ||
this.pos += (4 - mode); | ||
} | ||
} | ||
} | ||
if (mode != 0){ | ||
this.pos+=(4 - mode); | ||
} | ||
} | ||
}; | ||
@@ -179,2 +337,3 @@ | ||
for (var y = this.height - 1; y >= 0; y--) { | ||
var line = this.bottom_up ? y : this.height - 1 - y | ||
for (var x = 0; x < this.width; x++) { | ||
@@ -189,7 +348,8 @@ | ||
var location = y * this.width * 4 + x * 4; | ||
this.data[location] = red; | ||
this.data[location + 1] = green; | ||
this.data[location + 2] = blue; | ||
this.data[location + 3] = alpha; | ||
var location = line * this.width * 4 + x * 4; | ||
this.data[location] = alpha; | ||
this.data[location + 1] = blue; | ||
this.data[location + 2] = green; | ||
this.data[location + 3] = red; | ||
} | ||
@@ -202,6 +362,31 @@ //skip extra bytes | ||
BmpDecoder.prototype.bit16 = function() { | ||
var dif_w =this.width % 3; | ||
var _11111 = parseInt("11111", 2),_1_5 = _11111; | ||
var _111111 = parseInt("111111", 2),_1_6 = _111111; | ||
var dif_w =(this.width % 2)*2; | ||
//default xrgb555 | ||
this.maskRed = 0x7C00; | ||
this.maskGreen = 0x3E0; | ||
this.maskBlue =0x1F; | ||
this.mask0 = 0; | ||
if(this.compress == 3){ | ||
this.maskRed = this.buffer.readUInt32LE(this.pos); | ||
this.pos+=4; | ||
this.maskGreen = this.buffer.readUInt32LE(this.pos); | ||
this.pos+=4; | ||
this.maskBlue = this.buffer.readUInt32LE(this.pos); | ||
this.pos+=4; | ||
this.mask0 = this.buffer.readUInt32LE(this.pos); | ||
this.pos+=4; | ||
} | ||
var ns=[0,0,0]; | ||
for (var i=0;i<16;i++){ | ||
if ((this.maskRed>>i)&0x01) ns[0]++; | ||
if ((this.maskGreen>>i)&0x01) ns[1]++; | ||
if ((this.maskBlue>>i)&0x01) ns[2]++; | ||
} | ||
ns[1]+=ns[0]; ns[2]+=ns[1]; ns[0]=8-ns[0]; ns[1]-=8; ns[2]-=8; | ||
for (var y = this.height - 1; y >= 0; y--) { | ||
var line = this.bottom_up ? y : this.height - 1 - y; | ||
for (var x = 0; x < this.width; x++) { | ||
@@ -211,12 +396,13 @@ | ||
this.pos+=2; | ||
var alpha = 0xFF; | ||
var blue = (B & _1_5) / _1_5 * 255 | 0; | ||
var green = (B >> 5 & _1_6 ) / _1_6 * 255 | 0; | ||
var red = (B >> 11) / _1_5 * 255 | 0; | ||
var location = y * this.width * 4 + x * 4; | ||
this.data[location] = red; | ||
this.data[location + 1] = green; | ||
this.data[location + 2] = blue; | ||
this.data[location + 3] = alpha; | ||
var blue = (B&this.maskBlue)<<ns[0]; | ||
var green = (B&this.maskGreen)>>ns[1]; | ||
var red = (B&this.maskRed)>>ns[2]; | ||
var location = line * this.width * 4 + x * 4; | ||
this.data[location] = 0; | ||
this.data[location + 1] = blue; | ||
this.data[location + 2] = green; | ||
this.data[location + 3] = red; | ||
} | ||
@@ -229,13 +415,14 @@ //skip extra bytes | ||
BmpDecoder.prototype.bit24 = function() { | ||
//when height > 0 | ||
for (var y = this.height - 1; y >= 0; y--) { | ||
var line = this.bottom_up ? y : this.height - 1 - y | ||
for (var x = 0; x < this.width; x++) { | ||
//Little Endian rgb | ||
var blue = this.buffer.readUInt8(this.pos++); | ||
var green = this.buffer.readUInt8(this.pos++); | ||
var red = this.buffer.readUInt8(this.pos++); | ||
var location = y * this.width * 4 + x * 4; | ||
this.data[location] = red; | ||
this.data[location + 1] = green; | ||
this.data[location + 2] = blue; | ||
this.data[location + 3] = 0xFF; | ||
var location = line * this.width * 4 + x * 4; | ||
this.data[location] = 0; | ||
this.data[location + 1] = blue; | ||
this.data[location + 2] = green; | ||
this.data[location + 3] = red; | ||
} | ||
@@ -253,19 +440,50 @@ //skip extra bytes | ||
BmpDecoder.prototype.bit32 = function() { | ||
//when height > 0 | ||
for (var y = this.height - 1; y >= 0; y--) { | ||
for (var x = 0; x < this.width; x++) { | ||
var blue = this.buffer.readUInt8(this.pos++); | ||
var green = this.buffer.readUInt8(this.pos++); | ||
var red = this.buffer.readUInt8(this.pos++); | ||
var alpha = this.buffer.readUInt8(this.pos++); | ||
var location = y * this.width * 4 + x * 4; | ||
this.data[location] = red; | ||
this.data[location + 1] = green; | ||
this.data[location + 2] = blue; | ||
this.data[location + 3] = alpha; | ||
} | ||
//skip extra bytes | ||
this.pos += (this.width % 4); | ||
//BI_BITFIELDS | ||
if(this.compress == 3){ | ||
this.maskRed = this.buffer.readUInt32LE(this.pos); | ||
this.pos+=4; | ||
this.maskGreen = this.buffer.readUInt32LE(this.pos); | ||
this.pos+=4; | ||
this.maskBlue = this.buffer.readUInt32LE(this.pos); | ||
this.pos+=4; | ||
this.mask0 = this.buffer.readUInt32LE(this.pos); | ||
this.pos+=4; | ||
for (var y = this.height - 1; y >= 0; y--) { | ||
var line = this.bottom_up ? y : this.height - 1 - y; | ||
for (var x = 0; x < this.width; x++) { | ||
//Little Endian rgba | ||
var alpha = this.buffer.readUInt8(this.pos++); | ||
var blue = this.buffer.readUInt8(this.pos++); | ||
var green = this.buffer.readUInt8(this.pos++); | ||
var red = this.buffer.readUInt8(this.pos++); | ||
var location = line * this.width * 4 + x * 4; | ||
this.data[location] = alpha; | ||
this.data[location + 1] = blue; | ||
this.data[location + 2] = green; | ||
this.data[location + 3] = red; | ||
} | ||
} | ||
}else{ | ||
for (var y = this.height - 1; y >= 0; y--) { | ||
var line = this.bottom_up ? y : this.height - 1 - y; | ||
for (var x = 0; x < this.width; x++) { | ||
//Little Endian argb | ||
var blue = this.buffer.readUInt8(this.pos++); | ||
var green = this.buffer.readUInt8(this.pos++); | ||
var red = this.buffer.readUInt8(this.pos++); | ||
var alpha = this.buffer.readUInt8(this.pos++); | ||
var location = line * this.width * 4 + x * 4; | ||
this.data[location] = alpha; | ||
this.data[location + 1] = blue; | ||
this.data[location + 2] = green; | ||
this.data[location + 3] = red; | ||
} | ||
} | ||
} | ||
}; | ||
@@ -279,7 +497,3 @@ | ||
var decoder = new BmpDecoder(bmpData); | ||
return { | ||
data: decoder.getData(), | ||
width: decoder.width, | ||
height: decoder.height | ||
}; | ||
return decoder; | ||
}; |
@@ -42,3 +42,3 @@ /** | ||
tempBuffer.writeUInt32LE(this.width,this.pos);this.pos+=4; | ||
tempBuffer.writeUInt32LE(this.height,this.pos);this.pos+=4; | ||
tempBuffer.writeInt32LE(-this.height,this.pos);this.pos+=4; | ||
tempBuffer.writeUInt16LE(this.planes,this.pos);this.pos+=2; | ||
@@ -56,9 +56,9 @@ tempBuffer.writeUInt16LE(this.bitPP,this.pos);this.pos+=2; | ||
for (var y = this.height - 1; y >= 0; y--){ | ||
for (var y = 0; y <this.height; y++){ | ||
for (var x = 0; x < this.width; x++){ | ||
var p = this.pos+y*rowBytes+x*3; | ||
tempBuffer[p+2]= this.buffer[i++];//r | ||
i++;//a | ||
tempBuffer[p]= this.buffer[i++];//b | ||
tempBuffer[p+1] = this.buffer[i++];//g | ||
tempBuffer[p] = this.buffer[i++];//b | ||
i++; | ||
tempBuffer[p+2] = this.buffer[i++];//r | ||
} | ||
@@ -65,0 +65,0 @@ if(this.extraBytes>0){ |
{ | ||
"name": "bmp-js", | ||
"version": "0.0.3", | ||
"version": "0.1.0", | ||
"description": "A pure javascript BMP encoder and decoder", | ||
@@ -15,3 +15,5 @@ "main": "index.js", | ||
"8bit", | ||
"16bit", | ||
"24bit", | ||
"32bit", | ||
"encoder", | ||
@@ -18,0 +20,0 @@ "decoder", |
@@ -6,3 +6,3 @@ bmp-js | ||
Supports 1bit 4bit 8bit 24bit decoding and encoding with 24bit. | ||
Supports all bits decoding(1,4,8,16,24,32) and encoding with 24bit. | ||
@@ -19,8 +19,18 @@ ##Install | ||
var bmp = require("bmp-js"); | ||
var bmpBuffer = fs.readFileSync('aa.bmp'); | ||
var bmpBuffer = fs.readFileSync('bit24.bmp'); | ||
var bmpData = bmp.decode(bmpBuffer); | ||
//bmpData={data:Buffer,width:Number,height:Height} | ||
``` | ||
`bmpData` has all properties includes: | ||
1. fileSize,reserved,offset | ||
2. headerSize,width,height,planes,bitPP,compress,rawSize,hr,vr,colors,importantColors | ||
3. palette | ||
4. data-------byte array order by ABGR ABGR ABGR,4 bytes per pixel | ||
###Encode RGB | ||
@@ -30,3 +40,3 @@ ```js | ||
//bmpData={data:Buffer,width:Number,height:Height} | ||
var rawData = bmp.encode(bmpData);//default no compression | ||
var rawData = bmp.encode(bmpData);//default no compression,write rawData to .bmp file | ||
@@ -33,0 +43,0 @@ ``` |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
645720
35
518
44
1