imageMeta.js 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344
  1. 'use strict';
  2. function readPngSize(buf) {
  3. const sig = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);
  4. if (buf.length < 24 || !buf.subarray(0, 8).equals(sig)) return null;
  5. if (buf.toString('ascii', 12, 16) !== 'IHDR') return null;
  6. return { width: buf.readUInt32BE(16), height: buf.readUInt32BE(20) };
  7. }
  8. function readJpegSize(buf) {
  9. if (buf.length < 4 || buf[0] !== 0xff || buf[1] !== 0xd8) return null;
  10. let offset = 2;
  11. const SOF_MARKERS = new Set([
  12. 0xc0, 0xc1, 0xc2, 0xc3, 0xc5, 0xc6, 0xc7,
  13. 0xc9, 0xca, 0xcb, 0xcd, 0xce, 0xcf,
  14. ]);
  15. while (offset + 1 < buf.length) {
  16. if (buf[offset] !== 0xff) { offset++; continue; }
  17. const marker = buf[offset + 1];
  18. if (marker === 0xd8 || marker === 0x01 || (marker >= 0xd0 && marker <= 0xd7)) {
  19. offset += 2;
  20. continue;
  21. }
  22. if (marker === 0xd9 || offset + 3 >= buf.length) break;
  23. const segmentLength = buf.readUInt16BE(offset + 2);
  24. if (SOF_MARKERS.has(marker)) {
  25. const height = buf.readUInt16BE(offset + 5);
  26. const width = buf.readUInt16BE(offset + 7);
  27. return { width, height };
  28. }
  29. offset += 2 + segmentLength;
  30. }
  31. return null;
  32. }
  33. function getImageSize(buffer) {
  34. try {
  35. return readPngSize(buffer) || readJpegSize(buffer);
  36. } catch {
  37. return null;
  38. }
  39. }
  40. module.exports = { getImageSize };