Skip to content

Instantly share code, notes, and snippets.

@nowelium
Created March 27, 2012 22:42
Show Gist options
  • Select an option

  • Save nowelium/2221106 to your computer and use it in GitHub Desktop.

Select an option

Save nowelium/2221106 to your computer and use it in GitHub Desktop.

Revisions

  1. nowelium revised this gist Mar 29, 2012. 1 changed file with 3 additions and 1 deletion.
    4 changes: 3 additions & 1 deletion badapple.js
    Original file line number Diff line number Diff line change
    @@ -6,13 +6,14 @@ var Bitmap = require('./bitmap');

    //
    // ニコニコ動画の【東方】Bad Apple!! PV【影絵】 <http://www.nicovideo.jp/watch/sm8628149>
    // を 25fps な bitmap に分割したので、
    // を 30fps な bitmap に分割したので、
    // それを読み込みつつ、コンソールに表示してみる。
    //
    // async <https://github.com/caolan/async>
    // を使ってるので、 npm install async する
    //
    // youtubeにモッサリ動画を上げてみた。<http://youtu.be/IALA76KSc4I>
    // 音付きにしてニコニコ動画に上げてみた。<http://www.nicovideo.jp/watch/sm17397285>
    //
    var imageSequenceDir = 'badapple_30fps_160_120';
    fs.readdir(__dirname + '/' + imageSequenceDir, function(err, files){
    @@ -29,6 +30,7 @@ fs.readdir(__dirname + '/' + imageSequenceDir, function(err, files){
    return false;
    });

    // コンソールに出すときに半角スペースと#の文字列に変換
    Bitmap.prototype.mapRGBA = function(r, g, b){
    if(255 == r && 255 == g && 255 == b){
    return ' ';
  2. nowelium revised this gist Mar 29, 2012. 1 changed file with 7 additions and 17 deletions.
    24 changes: 7 additions & 17 deletions badapple.js
    Original file line number Diff line number Diff line change
    @@ -14,13 +14,14 @@ var Bitmap = require('./bitmap');
    //
    // youtubeにモッサリ動画を上げてみた。<http://youtu.be/IALA76KSc4I>
    //
    fs.readdir(__dirname + '/badapple_25fps', function(err, files){
    var imageSequenceDir = 'badapple_30fps_160_120';
    fs.readdir(__dirname + '/' + imageSequenceDir, function(err, files){
    if(err){
    throw err;
    }

    var pathes = files.map(function(file){
    return __dirname + '/badapple_25fps/' + file;
    return __dirname + '/' + imageSequenceDir + '/' + file;
    }).filter(function(path){
    if(/\.bmp$/.test(path)){
    return true;
    @@ -30,9 +31,9 @@ fs.readdir(__dirname + '/badapple_25fps', function(err, files){

    Bitmap.prototype.mapRGBA = function(r, g, b){
    if(255 == r && 255 == g && 255 == b){
    return ' ';
    return ' ';
    }
    return '#';
    return '##';
    };

    var render = async.queue(function(view, next){
    @@ -61,22 +62,11 @@ fs.readdir(__dirname + '/badapple_25fps', function(err, files){
    serial.push(function(next){
    var values = bitmap.getData();

    /*
    console.log('\033[2J'); // clear screen
    console.log('\033[0;0H'); // location(0, 0)
    var view = values.map(function(line){
    return line.join('');
    });
    console.log(view.join('\n'));
    return setTimeout(next, 0);
    */

    var view = values.map(function(line){
    return line.join('');
    });
    render.push(view.join('\n'), function(){
    return next(null);
    return render.push(view.join('\n'), function(){
    return setTimeout(next, 22);
    });
    });
    });
  3. nowelium revised this gist Mar 27, 2012. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions badapple.js
    Original file line number Diff line number Diff line change
    @@ -12,6 +12,8 @@ var Bitmap = require('./bitmap');
    // async <https://github.com/caolan/async>
    // を使ってるので、 npm install async する
    //
    // youtubeにモッサリ動画を上げてみた。<http://youtu.be/IALA76KSc4I>
    //
    fs.readdir(__dirname + '/badapple_25fps', function(err, files){
    if(err){
    throw err;
  4. nowelium created this gist Mar 27, 2012.
    92 changes: 92 additions & 0 deletions badapple.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,92 @@
    var fs = require('fs');
    var util = require('util');
    var async = require('async');

    var Bitmap = require('./bitmap');

    //
    // ニコニコ動画の【東方】Bad Apple!! PV【影絵】 <http://www.nicovideo.jp/watch/sm8628149>
    // を 25fps な bitmap に分割したので、
    // それを読み込みつつ、コンソールに表示してみる。
    //
    // async <https://github.com/caolan/async>
    // を使ってるので、 npm install async する
    //
    fs.readdir(__dirname + '/badapple_25fps', function(err, files){
    if(err){
    throw err;
    }

    var pathes = files.map(function(file){
    return __dirname + '/badapple_25fps/' + file;
    }).filter(function(path){
    if(/\.bmp$/.test(path)){
    return true;
    }
    return false;
    });

    Bitmap.prototype.mapRGBA = function(r, g, b){
    if(255 == r && 255 == g && 255 == b){
    return ' ';
    }
    return '#';
    };

    var render = async.queue(function(view, next){
    util.print('\033[2J');
    util.print(view);
    util.print('\033[0;0H');
    return next(null);
    }, 1);

    var queue = async.queue(function(path, next){
    return fs.readFile(path, next);
    }, 8);

    var serial = [];
    queue.push(pathes, function(err, buffer){
    if(err){
    throw err;
    }

    var bitmap = new Bitmap(buffer);
    bitmap.init();
    if(!bitmap.isBitmap()){
    throw new Error('not bitmap');
    }

    serial.push(function(next){
    var values = bitmap.getData();

    /*
    console.log('\033[2J'); // clear screen
    console.log('\033[0;0H'); // location(0, 0)
    var view = values.map(function(line){
    return line.join('');
    });
    console.log(view.join('\n'));
    return setTimeout(next, 0);
    */

    var view = values.map(function(line){
    return line.join('');
    });
    render.push(view.join('\n'), function(){
    return next(null);
    });
    });
    });
    queue.drain = function(){
    async.series(serial, function(err, results){
    if(err){
    console.error(err);
    return process.exit(1);
    }

    console.log('\033[2J'); // clear screen
    return process.exit(0);
    });
    };
    });
    603 changes: 603 additions & 0 deletions bitmap.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,603 @@
    // origin:: https://github.com/nowelium/node-bitmap

    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);
    };