Duplicating base64 data

2019-07-26 02:57发布

This is a follow up from the following link on stackoverflow Iterating through : Reader.OnLoad

which Máté Safranka kindly helped me with earlier.

I'm almost finished with it, does anyone know why in the function function onAllImagesLoaded(imageList) the line console.log ("imageList: " + imageList); is duplicating the image data all the time, that's what it's doing at the moment and I can't figure it out. If I select more than 1 file, the image data is the same for each one! Arggghh

Thank you

function encodeImageFileAsURL() {

  var filesSelected = document.getElementById("inputFileToLoad").files;
  var arrayCounter = 0;
  var imageList = [];

  for (arrayCounter = 0; arrayCounter < filesSelected.length; arrayCounter++) {

    var fileToLoad = filesSelected[arrayCounter];
    var fileReader = new FileReader();

    fileReader.onload = (function(fileLoadedEvent) {
      return function(e) {
        var srcData = e.target.result; // base64 data

        getOrientation(fileToLoad, function(orientation) {
        
          if (orientation == 1) {
            imageList.push(srcData);
            if (imageList.length == filesSelected.length) {
          			//console.log ("imageList length: " + imageList.length);
            		//console.log ("filesSelected length: " + filesSelected.length);
                onAllImagesLoaded(imageList);
          	}
          }
          else {
            resetOrientation(URL.createObjectURL(fileToLoad), orientation, function(resetBase64Image) {
              imageList.push(resetBase64Image);
              if (imageList.length == filesSelected.length) {
          			//console.log ("imageList length: " + imageList.length);
            		//console.log ("filesSelected length: " + filesSelected.length);
                onAllImagesLoaded(imageList);
          		}
            });
          }
          
        });
			}
      
    })(fileToLoad);

    fileReader.readAsDataURL(fileToLoad);
  }
}



function onAllImagesLoaded(imageList) {
	console.log ("imageList: " + imageList);
}


function resetOrientation(srcBase64, srcOrientation, callback) {
  var img = new Image();

  img.onload = function() {
    var width = img.width,
      height = img.height,
      canvas = document.createElement('canvas'),
      ctx = canvas.getContext("2d");

    // set proper canvas dimensions before transform & export
    if (4 < srcOrientation && srcOrientation < 9) {
      canvas.width = height;
      canvas.height = width;
    } else {
      canvas.width = width;
      canvas.height = height;
    }

    // transform context before drawing image
    switch (srcOrientation) {
      case 2:
        ctx.transform(-1, 0, 0, 1, width, 0);
        break;
      case 3:
        ctx.transform(-1, 0, 0, -1, width, height);
        break;
      case 4:
        ctx.transform(1, 0, 0, -1, 0, height);
        break;
      case 5:
        ctx.transform(0, 1, 1, 0, 0, 0);
        break;
      case 6:
        ctx.transform(0, 1, -1, 0, height, 0);
        break;
      case 7:
        ctx.transform(0, -1, -1, 0, height, width);
        break;
      case 8:
        ctx.transform(0, -1, 1, 0, 0, width);
        break;
      default:
        break;
    }

    // draw image
    ctx.drawImage(img, 0, 0);

    // export base64
    callback(canvas.toDataURL());
  };

  img.src = srcBase64;
}



function getOrientation(file, callback) {
  var reader = new FileReader();
  reader.onload = function(e) {

    var view = new DataView(e.target.result);
    if (view.getUint16(0, false) != 0xFFD8) {
      return callback(-2);
    }
    var length = view.byteLength,
      offset = 2;
    while (offset < length) {
      if (view.getUint16(offset + 2, false) <= 8) return callback(-1);
      var marker = view.getUint16(offset, false);
      offset += 2;
      if (marker == 0xFFE1) {
        if (view.getUint32(offset += 2, false) != 0x45786966) {
          return callback(-1);
        }

        var little = view.getUint16(offset += 6, false) == 0x4949;
        offset += view.getUint32(offset + 4, little);
        var tags = view.getUint16(offset, little);
        offset += 2;
        for (var i = 0; i < tags; i++) {
          if (view.getUint16(offset + (i * 12), little) == 0x0112) {
            return callback(view.getUint16(offset + (i * 12) + 8, little));
          }
        }
      } else if ((marker & 0xFF00) != 0xFF00) {
        break;
      } else {
        offset += view.getUint16(offset, false);
      }
    }
    return callback(-1);
  };
  reader.readAsArrayBuffer(file);
}
<!-- Learn about this code on MDN: https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readAsDataURL -->

<input id="inputFileToLoad" type="file" accept="image/*" multiple="true" style="opacity: 100" onchange="encodeImageFileAsURL();" />

2条回答
smile是对你的礼貌
2楼-- · 2019-07-26 03:12

getOrientation() returned -2 for all of my images. Looking at the code, that happens when first two bytes of the image aren't 0xFFD8. Google tells me this particular byte sequence is called the "JPEG frame tag". I.e. getOrientation() is only compatible with JPEG images, whereas the ones I tried were all PNG. You'll need to find some way to handle that.

查看更多
Deceive 欺骗
3楼-- · 2019-07-26 03:23

I had a similar problem with getOrientation(). Because it's asynchronous it doesn't process the pics in order.

So you need to amend getOrientation() to return file as well as the exif value, like this...

...return callback(file, -2);
...return callback(file, -1);
...return callback(file, view.getUint16(offset + (i * 12) + 8, little));
etc

That way when it returns you can match the exif value with the file that went in.

Otherwise there's no way for your script to know & it will just use the data from the last file that went in for all files.

查看更多
登录 后发表回答