packer.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. 'use strict';
  2. var constants = require('./constants');
  3. var CrcStream = require('./crc');
  4. var bitPacker = require('./bitpacker');
  5. var filter = require('./filter-pack');
  6. var zlib = require('zlib');
  7. var Packer = module.exports = function(options) {
  8. this._options = options;
  9. options.deflateChunkSize = options.deflateChunkSize || 32 * 1024;
  10. options.deflateLevel = options.deflateLevel != null ? options.deflateLevel : 9;
  11. options.deflateStrategy = options.deflateStrategy != null ? options.deflateStrategy : 3;
  12. options.inputHasAlpha = options.inputHasAlpha != null ? options.inputHasAlpha : true;
  13. options.deflateFactory = options.deflateFactory || zlib.createDeflate;
  14. options.bitDepth = options.bitDepth || 8;
  15. // This is outputColorType
  16. options.colorType = (typeof options.colorType === 'number') ? options.colorType : constants.COLORTYPE_COLOR_ALPHA;
  17. options.inputColorType = (typeof options.inputColorType === 'number') ? options.inputColorType : constants.COLORTYPE_COLOR_ALPHA;
  18. if ([
  19. constants.COLORTYPE_GRAYSCALE,
  20. constants.COLORTYPE_COLOR,
  21. constants.COLORTYPE_COLOR_ALPHA,
  22. constants.COLORTYPE_ALPHA
  23. ].indexOf(options.colorType) === -1) {
  24. throw new Error('option color type:' + options.colorType + ' is not supported at present');
  25. }
  26. if ([
  27. constants.COLORTYPE_GRAYSCALE,
  28. constants.COLORTYPE_COLOR,
  29. constants.COLORTYPE_COLOR_ALPHA,
  30. constants.COLORTYPE_ALPHA
  31. ].indexOf(options.inputColorType) === -1) {
  32. throw new Error('option input color type:' + options.inputColorType + ' is not supported at present');
  33. }
  34. if (options.bitDepth !== 8 && options.bitDepth !== 16) {
  35. throw new Error('option bit depth:' + options.bitDepth + ' is not supported at present');
  36. }
  37. };
  38. Packer.prototype.getDeflateOptions = function() {
  39. return {
  40. chunkSize: this._options.deflateChunkSize,
  41. level: this._options.deflateLevel,
  42. strategy: this._options.deflateStrategy
  43. };
  44. };
  45. Packer.prototype.createDeflate = function() {
  46. return this._options.deflateFactory(this.getDeflateOptions());
  47. };
  48. Packer.prototype.filterData = function(data, width, height) {
  49. // convert to correct format for filtering (e.g. right bpp and bit depth)
  50. var packedData = bitPacker(data, width, height, this._options);
  51. // filter pixel data
  52. var bpp = constants.COLORTYPE_TO_BPP_MAP[this._options.colorType];
  53. var filteredData = filter(packedData, width, height, this._options, bpp);
  54. return filteredData;
  55. };
  56. Packer.prototype._packChunk = function(type, data) {
  57. var len = (data ? data.length : 0);
  58. var buf = new Buffer(len + 12);
  59. buf.writeUInt32BE(len, 0);
  60. buf.writeUInt32BE(type, 4);
  61. if (data) {
  62. data.copy(buf, 8);
  63. }
  64. buf.writeInt32BE(CrcStream.crc32(buf.slice(4, buf.length - 4)), buf.length - 4);
  65. return buf;
  66. };
  67. Packer.prototype.packGAMA = function(gamma) {
  68. var buf = new Buffer(4);
  69. buf.writeUInt32BE(Math.floor(gamma * constants.GAMMA_DIVISION), 0);
  70. return this._packChunk(constants.TYPE_gAMA, buf);
  71. };
  72. Packer.prototype.packIHDR = function(width, height) {
  73. var buf = new Buffer(13);
  74. buf.writeUInt32BE(width, 0);
  75. buf.writeUInt32BE(height, 4);
  76. buf[8] = this._options.bitDepth; // Bit depth
  77. buf[9] = this._options.colorType; // colorType
  78. buf[10] = 0; // compression
  79. buf[11] = 0; // filter
  80. buf[12] = 0; // interlace
  81. return this._packChunk(constants.TYPE_IHDR, buf);
  82. };
  83. Packer.prototype.packIDAT = function(data) {
  84. return this._packChunk(constants.TYPE_IDAT, data);
  85. };
  86. Packer.prototype.packIEND = function() {
  87. return this._packChunk(constants.TYPE_IEND, null);
  88. };