webp.js 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. 'use strict';
  2. // based on https://developers.google.com/speed/webp/docs/riff_container
  3. function isWebP (buffer) {
  4. var riffHeader = 'RIFF' === buffer.toString('ascii', 0, 4);
  5. var webpHeader = 'WEBP' === buffer.toString('ascii', 8, 12);
  6. var vp8Header = 'VP8' === buffer.toString('ascii', 12, 15);
  7. return (riffHeader && webpHeader && vp8Header);
  8. }
  9. function calculate (buffer) {
  10. var chunkHeader = buffer.toString('ascii', 12, 16);
  11. buffer = buffer.slice(20, 30);
  12. // Extended webp stream signature
  13. if (chunkHeader === 'VP8X') {
  14. var extendedHeader = buffer[0];
  15. var validStart = (extendedHeader & 0xc0) === 0;
  16. var validEnd = (extendedHeader & 0x01) === 0;
  17. if (validStart && validEnd) {
  18. return calculateExtended(buffer);
  19. } else {
  20. return false;
  21. }
  22. }
  23. // Lossless webp stream signature
  24. if (chunkHeader === 'VP8 ' && buffer[0] !== 0x2f) {
  25. return calculateLossy(buffer);
  26. }
  27. // Lossy webp stream signature
  28. var signature = buffer.toString('hex', 3, 6);
  29. if (chunkHeader === 'VP8L' && signature !== '9d012a') {
  30. return calculateLossless(buffer);
  31. }
  32. return false;
  33. }
  34. function calculateExtended (buffer) {
  35. return {
  36. 'width': 1 + buffer.readUIntLE(4, 3),
  37. 'height': 1 + buffer.readUIntLE(7, 3)
  38. }
  39. }
  40. function calculateLossless (buffer) {
  41. return {
  42. 'width': 1 + (((buffer[2] & 0x3F) << 8) | buffer[1]),
  43. 'height': 1 + (((buffer[4] & 0xF) << 10) | (buffer[3] << 2) |
  44. ((buffer[2] & 0xC0) >> 6))
  45. };
  46. }
  47. function calculateLossy (buffer) {
  48. // `& 0x3fff` returns the last 14 bits
  49. // TO-DO: include webp scaling in the calculations
  50. return {
  51. 'width': buffer.readInt16LE(6) & 0x3fff,
  52. 'height': buffer.readInt16LE(8) & 0x3fff
  53. };
  54. }
  55. module.exports = {
  56. 'detect': isWebP,
  57. 'calculate': calculate
  58. };