filepond-plugin-image-exif-orientation.esm.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. /*!
  2. * FilePondPluginImageExifOrientation 1.0.11
  3. * Licensed under MIT, https://opensource.org/licenses/MIT/
  4. * Please visit https://pqina.nl/filepond/ for details.
  5. */
  6. /* eslint-disable */
  7. // test if file is of type image
  8. const isJPEG = file => /^image\/jpeg/.test(file.type);
  9. const Marker = {
  10. JPEG: 0xffd8,
  11. APP1: 0xffe1,
  12. EXIF: 0x45786966,
  13. TIFF: 0x4949,
  14. Orientation: 0x0112,
  15. Unknown: 0xff00
  16. };
  17. const getUint16 = (view, offset, little = false) =>
  18. view.getUint16(offset, little);
  19. const getUint32 = (view, offset, little = false) =>
  20. view.getUint32(offset, little);
  21. const getImageOrientation = file =>
  22. new Promise((resolve, reject) => {
  23. const reader = new FileReader();
  24. reader.onload = function(e) {
  25. const view = new DataView(e.target.result);
  26. // Every JPEG file starts from binary value '0xFFD8'
  27. if (getUint16(view, 0) !== Marker.JPEG) {
  28. // This aint no JPEG
  29. resolve(-1);
  30. return;
  31. }
  32. const length = view.byteLength;
  33. let offset = 2;
  34. while (offset < length) {
  35. const marker = getUint16(view, offset);
  36. offset += 2;
  37. // There's our APP1 Marker
  38. if (marker === Marker.APP1) {
  39. if (getUint32(view, (offset += 2)) !== Marker.EXIF) {
  40. // no EXIF info defined
  41. break;
  42. }
  43. // Get TIFF Header
  44. const little = getUint16(view, (offset += 6)) === Marker.TIFF;
  45. offset += getUint32(view, offset + 4, little);
  46. const tags = getUint16(view, offset, little);
  47. offset += 2;
  48. for (let i = 0; i < tags; i++) {
  49. // found the orientation tag
  50. if (
  51. getUint16(view, offset + i * 12, little) === Marker.Orientation
  52. ) {
  53. resolve(getUint16(view, offset + i * 12 + 8, little));
  54. return;
  55. }
  56. }
  57. } else if ((marker & Marker.Unknown) !== Marker.Unknown) {
  58. // Invalid
  59. break;
  60. } else {
  61. offset += getUint16(view, offset);
  62. }
  63. }
  64. // Nothing found
  65. resolve(-1);
  66. };
  67. // we don't need to read the entire file to get the orientation
  68. reader.readAsArrayBuffer(file.slice(0, 64 * 1024));
  69. });
  70. const IS_BROWSER = (() =>
  71. typeof window !== 'undefined' && typeof window.document !== 'undefined')();
  72. const isBrowser = () => IS_BROWSER;
  73. // 2x1 pixel image 90CW rotated with orientation header
  74. const testSrc =
  75. 'data:image/jpg;base64,/9j/4AAQSkZJRgABAQEASABIAAD/4QA6RXhpZgAATU0AKgAAAAgAAwESAAMAAAABAAYAAAEoAAMAAAABAAIAAAITAAMAAAABAAEAAAAAAAD/2wBDAP//////////////////////////////////////////////////////////////////////////////////////wAALCAABAAIBASIA/8QAJgABAAAAAAAAAAAAAAAAAAAAAxABAAAAAAAAAAAAAAAAAAAAAP/aAAgBAQAAPwBH/9k=';
  76. // should correct orientation if is presented in landscape, in which case the browser doesn't autocorrect
  77. let shouldCorrect = undefined;
  78. const testImage = isBrowser() ? new Image() : {};
  79. testImage.onload = () =>
  80. (shouldCorrect = testImage.naturalWidth > testImage.naturalHeight);
  81. testImage.src = testSrc;
  82. const shouldCorrectImageExifOrientation = () => shouldCorrect;
  83. /**
  84. * Read Image Orientation Plugin
  85. */
  86. const plugin = ({ addFilter, utils }) => {
  87. const { Type, isFile } = utils;
  88. // subscribe to file load and append required info
  89. addFilter(
  90. 'DID_LOAD_ITEM',
  91. (item, { query }) =>
  92. new Promise((resolve, reject) => {
  93. // get file reference
  94. const file = item.file;
  95. // if this is not a jpeg image we are not interested
  96. if (
  97. !isFile(file) ||
  98. !isJPEG(file) ||
  99. !query('GET_ALLOW_IMAGE_EXIF_ORIENTATION') ||
  100. !shouldCorrectImageExifOrientation()
  101. ) {
  102. // continue with the unaltered dataset
  103. return resolve(item);
  104. }
  105. // get orientation from exif data
  106. getImageOrientation(file).then(orientation => {
  107. item.setMetadata('exif', { orientation });
  108. resolve(item);
  109. });
  110. })
  111. );
  112. // Expose plugin options
  113. return {
  114. options: {
  115. // Enable or disable image orientation reading
  116. allowImageExifOrientation: [true, Type.BOOLEAN]
  117. }
  118. };
  119. };
  120. // fire pluginloaded event if running in browser, this allows registering the plugin when using async script tags
  121. const isBrowser$1 =
  122. typeof window !== 'undefined' && typeof window.document !== 'undefined';
  123. if (isBrowser$1) {
  124. document.dispatchEvent(
  125. new CustomEvent('FilePond:pluginloaded', { detail: plugin })
  126. );
  127. }
  128. export default plugin;