Как я могу сохранить ImageData как PNG в Electron - PullRequest
0 голосов
/ 05 мая 2019

В браузере я строил массив данных изображения и, как вы можете видеть здесь, преобразовал его в несколько различных форм, чтобы загрузить его в браузере, который работал:

let clamped = Uint8ClampedArray.from(frameBuffer);
let imageData = new ImageData(clamped, width, height);
this.resultContext.putImageData(imageData, 0, 0);
this.uri = this.resultCanvas.toDataURL("image/png");
this.blob = dataURItoBlob(this.uri);

Но сейчас я пытаюсь сохранить этот BLOB-объект с помощью модуля Node.js fs, и это не работает:

fs.writeFile(this.path + "/" + angle + ".png", this.blob, err => {
  if (err) {
    alert("An error ocurred creating the file " + err.message);
  }
  console.log("The file has been successfully saved");
});

Редактировать: dataURItoBlob:

function dataURItoBlob(dataURI) {
  // convert base64/URLEncoded data component to raw binary data held in a string
  var byteString;
  if (dataURI.split(",")[0].indexOf("base64") >= 0)
    byteString = atob(dataURI.split(",")[1]);
  else byteString = unescape(dataURI.split(",")[1]);
  // separate out the mime component
  var mimeString = dataURI
    .split(",")[0]
    .split(":")[1]
    .split(";")[0];
  // write the bytes of the string to a typed array
  var ia = new Uint8Array(byteString.length);
  for (var i = 0; i < byteString.length; i++) {
    ia[i] = byteString.charCodeAt(i);
  }
  return new Blob([ia], { type: mimeString });
}

Ошибка не выдается, но полученный файл неверен. Как я могу это исправить?

1 Ответ

1 голос
/ 05 мая 2019

Похоже, это работает

canvas.toBlob(saveBlob);

function saveBlob(blob) {
  const reader = new FileReader();
  reader.onloadend = () => {
    fs.writeFile('filename.png', new Uint8Array(reader.result), err => {
      if (err) {
        alert("An error ocurred creating the file " + err.message);
      } else {
        console.log("The file has been successfully saved");
      }
    });
  }
  reader.readAsArrayBuffer(blob);
}

примечание в 2019 году, я мог бы перейти к обещаниям и асинхронным вещам. Там немного настройки, но затем использование легче для некоторого определения проще

const fs = require('fs');  // would prefer import
const util = require('util');

const writeFile = util.promisify(fs.writeFile);

function readBlobAsUint8Array(blob) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onloadend = () => {
      return new Uint8Array(reader.result);
    };
    reader.onerror = reject;
    reader.readAsArrayBuffer(blob);
  });
}

function getCanvasAsBlob(canvas) {
  return new Promise((resolve) => {
     canvas.toBlob(resolve);
  });
}

async function saveCanvasAsPNG(filename, canvas) {
  const blob = await getCanvasAsBlob(canvas);
  const data = await readBlobAsUint8Array(blob);
  await writeFile(filename, data);
}

, которая может быть вызвана из другой асинхронной функции, например

async function someFunc() {
  try {
    await saveCanvasAsPNG('foo.png', canvas);
    console.log('success');
  } catch (e) {
    alert(e);
  }
}

или из не асинхронной функции как

saveCanvasAsPng('foo.png', canvas)
  .then(() => {
     console.log('success');
  })
  .catch(alert);

обратите внимание, это также работает

const dataUrl = canvas.toDataURL();
const uu = dataUrl.substring('data:image/png;base64,'.length);
fs.writeFileSync(filename, uu, 'base64');
...