Играйте с потоковой передачей изображений

Ресурсы изображений
Играйте с потоковой передачей изображений

сделатьраспознавание изображенийПрограммное обеспечение, применяемое для потоковой передачи изображений, предварительного просмотра, технологий Blob, Base64 и преобразования типов. Эти технологии незаменимы при разработке изображений. На этот раз давайте поиграем с «потоковой передачей изображений»!

1. Общие сценарии

Давайте сначала посмотрим на сценарий использования образа:

  • Загрузить через ввод;
  • загрузка файлов методом перетаскивания;
  • Предварительный просмотр изображения;
  • хранение данных изображения;
  • Нужен сторонний интерфейс;

Конечно, фактическое приложение намного сложнее, чем это, но если мы освоим основную идею, то это не что иное, как получение и преобразование «потока изображения», давайте углубимся!

Во-вторых, поговорим о потоке изображений

Упомянутый выше «поток изображений» на самом деле представляет собой двоичный поток для представления изображений, который мы часто называем «двоичными изображениями».

Хранилище компьютера физически полностью двоичное, поэтому разница между текстовыми файлами и двоичными файлами не физическая, а логическая.


Некоторые люди могут спросить, зачем использовать двоичный код для представления изображений? Давайте посмотрим на преимущества бинарника:

  1. Двоичные файлы более компактны и ничем не отличаются от обычного хранилища при хранении символьных данных. Но при хранении чисел, особенно вещественных, двоичный код экономит место;
  2. Данные, участвующие в вычислении в памяти, хранятся в бинарном формате, поэтому быстрее использовать бинарник для сохранения в файл. При сохранении в виде текстового файла требуется процесс преобразования. Когда объем данных велик, между ними будет значительная разница в скорости;
  3. При использовании некоторых относительно точных данных использование двоичного хранилища не приведет к потере значимых битов;

Видя это, я считаю, что у каждого есть определенное понимание потоковой передачи изображений. Теперь, когда упомянуто хранилище, добавьте описание того, как изображения хранятся в бэкэнде:

  • Один: изображение может быть сохранено в указанной папке сервера как независимый файл, а затем путь может быть сохранен в поле базы данных;
  • Второе: преобразовать изображение в бинарный поток и сохранить его непосредственно в базе данных.Imageв поле типа;

3. Что такое FileReader?

FileReaderобъект разрешенWebПриложение асинхронно считывает содержимое файла (или буфера необработанных данных), хранящегося на компьютере пользователя, используяFileилиBlobОбъект указывает файл или данные для чтения.

вFileОбъекты могут быть от пользователя в<input>Возвращается после выбора файла на элементеFileListОбъекты, которые также могут быть созданы с помощью операций перетаскивания.DataTransferобъекта, а также может исходить отHTMLCanvasElementвыполнить наmozGetAsFile()Метод возвращает результат.

Официальная много сказала, на самом деле достаточно знать только, что "используется для чтения файлов".


Описание параметра выглядит следующим образом:

  • FileReader.error(только чтение): аDOMException, указывая на то, что при чтении файла произошла ошибка;
  • FileReader.readyState(только для чтения): указываетFileReaderНомер состояния. Значения следующие:
    • EMPTY0 Данные еще не загружены.
    • LOADING1 данные загружаются.
    • DONE2 Выполнены все запросы на чтение.
  • FileReader.result(только для чтения): содержимое файла. Это свойство действует только после завершения операции чтения, формат данных зависит от того, какой метод использовался для инициации операции чтения.

Также есть несколько обработчиков событий:

  • FileReader.onabort:иметь дело сabortмероприятие. Это событие запускается, когда операция чтения прерывается.
  • FileReader.onerror:иметь дело сerrorмероприятие. Это событие запускается при возникновении ошибки в операции чтения.
  • FileReader.onload:иметь дело сloadмероприятие. Это событие срабатывает после завершения операции чтения.
  • FileReader.onloadstart:иметь дело сloadstartмероприятие. Это событие срабатывает при запуске операции чтения.
  • FileReader.onloadend:иметь дело сloadendмероприятие. Это событие срабатывает, когда операция чтения завершается (успешно или неудачно).
  • FileReader.onprogress:иметь дело сprogressмероприятие. Событие читаетсяBlobсрабатывает когда.

Доступны следующие методы:

  • FileReader.abort(): Прервать операцию чтения. По возвращении,readyStateсобственностьDONE.
  • FileReader.readAsArrayBuffer(): начать чтение указанногоBlobсодержание в . Когда-то сделали,resultсвойство будет содержатьArrayBufferпредставлять данные файла;
  • FileReader.readAsBinaryString(): начать чтение указанногоBlobсодержание в . Когда-то сделали,resultСвойства будут содержать необработанные двоичные данные читаемого файла.
  • FileReader.readAsDataURL(): начать чтение указанногоBlobсодержание в . Когда-то сделали,resultсвойства будут содержатьdata: URLСтрока формата для представления содержимого читаемого файла.
  • FileReader.readAsText(): начать чтение указанногоBlobсодержание в . Когда-то сделали,resultАтрибут будет содержать строку, представляющую содержимое читаемого файла.

Приведенный выше документ очень понятен, но я думаю, вы не читали его по порядку, не беда, у нас еще есть примеры🙈

Конкретные сценарии применения могут быть следующими:

onDrop(files) {
  files.forEach(file => {
    const reader = new FileReader();
    reader.onload = () => {
      console.log('Jartto files logs: ', file);
      const fileAsBinaryString = reader.result;
      // Todo...
    };
    reader.onabort = () => console.log('file reading was aborted');
    reader.onerror = () => console.log('file reading has failed');
    reader.readAsBinaryString(file);
  });
}

Использование очень простое, единственное, на что вам нужно обратить внимание, это то, что он должен быть вonloadСделай это позже!

В-четвертых, формат base64

Иногда мы видим такой код на веб-страницах:

data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAb4AAABYCAYAAACK55LCAAAgAElEQVR4Xuy9aXNc2ZEleN4e+wIgsO8ACXAnk8mUUqoqldQ9Yz3W/an/wsxvnA/TM2NWizKVmczkTgIg9h0IxL6+fez4DbCo7JQqpZLZfGBARjEJBOK95/de9+PHj3toO//7f40x/BpaYGiBoQWGFhha4BOxgDYMfJ/ISg8fc2iBoQWGFhhaQCwwDHzDjTC0wNACQwsMLfBJWWAY
...

Этоbase64Данные в формате представляют собой данные изображения.Технический термин называется:Data URI scheme.

Data URI schemeОн определен в RFC2397 и предназначен для встраивания небольших данных непосредственно в веб-страницу, чтобы их не нужно было загружать из внешнего файла.

В настоящее время,Data URI schemeПоддерживаемые типы:

data:,文本数据
data:text/plain,文本数据
data:text/html,HTML 代码
data:text/html;base64,base64 编码的 HTML 代码
data:text/css,CSS代码
data:text/css;base64,base64 编码的 CSS 代码
data:text/javascript,Javascript 代码
data:text/javascript;base64,base64 编码的 Javascript代码
data:image/gif;base64,base64 编码的 gif 图片数据
data:image/png;base64,base64 编码的 png 图片数据
data:image/jpeg;base64,base64 编码的 jpeg 图片数据
data:image/x-icon;base64,base64 编码的 icon 图片数据

Base64кодировка называетсяBase64, потому что он использует 64 символа для кодирования произвольных данных.Base64Кодирование — это, по сути, схема преобразования двоичных данных в текстовые данные. Для недвоичных данных сначала преобразуйте их в двоичную форму, затем вычислите их десятичное значение для каждых 6 последовательных битов (2 в 6-й степени = 64) и найдите соответствующий символ в таблице индексов выше в соответствии с этим значением, и, наконец, получить текстовую строку.

Для более глубокого понимания, пожалуйста, обратитесь к:Принцип кодирования Base64 и применение

5. Формат BLOB-объекта

Большой двоичный объект (двоичный большой объект), большой двоичный объект, представляет собой контейнер, в котором могут храниться двоичные файлы.

Blobэто большой файл, обычноBlobизображение или звуковой файл, с которым из-за его размера необходимо обращаться особым образом (например, загружать, скачивать или хранить в базе данных).

Вот тот, который я переделалBlobОбъект:

Blob {
  name: "图片示例:jartto.png",
  preview: "blob:file:///f3823a2a-2908-44cb-81e2-c19d98abc5d1",
  size: 47396,
  type: "image/png",
}

Обратите внимание, что здесьpreviewАтрибуты можно вынуть для предварительного просмотра изображения.

Шесть, base64 в Blob

когда мы получимbase64Представленный код изображения кажется вам недостаточно элегантным или по различным другим причинам вам может потребоваться преобразовать его вBlobФормат, код выглядит следующим образом:

base64ToBlob(b64data, contentType, sliceSize) {
  sliceSize || (sliceSize = 512);
  return new Promise((resolve, reject) => {
    // 使用 atob() 方法将数据解码
    let byteCharacters = atob(b64data);
    let byteArrays = [];
      for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
        let slice = byteCharacters.slice(offset, offset + sliceSize);
        let byteNumbers = [];
        for (let i = 0; i < slice.length; i++) {
            byteNumbers.push(slice.charCodeAt(i));
        }
        // 8 位无符号整数值的类型化数组。内容将初始化为 0。
        // 如果无法分配请求数目的字节,则将引发异常。
        byteArrays.push(new Uint8Array(byteNumbers));
      }
      resolve(new Blob(byteArrays, {
        type: contentType
      }))
  })
}

Метод вызова:

// dataUri 是你的 base64 图片流
let blob = await this.base64ToBlob(dataUri.split(',')[1], 'image/png');

После обработки мы получилиBlobобъект, но, возможно, это:

Blob {
  size: 47396,
  type: "image/png",
}

Вот и все, план я хочу озвучить не зря? Не волнуйтесь, добавим:

Object.assign(blob,{
  // jartto: 这里一定要处理一下
  preview: URL.createObjectURL(blob),
  name: `图片示例:${index}.png`
});

вы можете использоватьwindow.btoa()метод кодирования данных, которые могут иметь проблемы во время передачи, и после принятия данных использоватьatob()метод декодирования данных.

оatobа такжеUint8ArrayЯ не буду вдаваться в подробности здесь, вы можете взглянуть на документацию:

Семь, Blob в base64

Это еще один сценарий. Он может появиться, когда вы используете сторонний плагин, такой как плагин загрузки изображений, и он автоматически вернется к вам.Blobобъекта, но, к сожалению, вы обнаружили, что использовали сторонний сервисный интерфейс, который получает толькоbase64Данные в формате немного похожи на плач.

Не бойтесь, у нас также есть решение, а именно:

blobToBase64(blob) {
  return new Promise((resolve, reject) => {
    const fileReader = new FileReader();
    fileReader.onload = (e) => {
      resolve(e.target.result);
    };
    fileReader.readAsDataURL(blob);
    fileReader.onerror = () => {
      reject(new Error('文件流异常'));
    };
  });
}

Метод вызова:

const allBase64 = await this.blobToBase64(blobObj);

Добавлю, что упомянутая выше сцена — это то, с чем я действительно столкнулся, а жизнь полна сюрпризов.

Восемь, URL-адрес base64

Что ж, самое интересное, я повысил требования, дайте только URL-адрес (локальный или онлайн-адрес) изображения, можете ли вы закодировать изображение в поток? Ответ да, здесь мы должны спроситьcanvasсейчас:

Идея очень проста, нарисовать холст в соответствии с данными объекта изображения, а затем использовать его для эквивалентного представления потока изображения.


getDataUri(url) {
  return new Promise((resolve, reject) => {
    /* eslint-disable */
    let image = new Image();
    image.onload = function() {
      let canvas = document.createElement('canvas');
      canvas.width = this.naturalWidth;
      canvas.height = this.naturalHeight;
      canvas.getContext('2d').drawImage(this, 0, 0);
      // Data URI
      resolve(canvas.toDataURL('image/png'));
    };
    image.src = url;
    // console.log(image.src);
    image.onerror = () => {
      reject(new Error('图片流异常'));
    };
  });
}

Вы можете назвать это так:

let dataUri = await this.getDataUri(`image/test/jartto.png`);

9. Часто задаваемые вопросы и дополнительные инструкции

1.Failed to execute 'readAsDataURL' on 'FileReader': parameter 1 is not of type 'Blob'.
Если возникает вышеуказанная проблема, проверьте, имеет ли ваш объект Blob правильный формат и отсутствуют ли необходимые элементы.

2. Необходимо удалить многие сторонние приложенияbase64информация заголовка:

base64.replace(/^data:image\/(jpeg|png|gif);base64,/,'')

3.FileReaderПосле прочтения файла не забудьте поставитьonloadПомните, внутри функции.

4. В использованииcanvas.getContext('2d').drawImage(this, 0, 0);В процессе обязательно обращайте внимание наthisуказать, в противном случае может возникнуть исключение.

5.base64ПеременаBlob,Пожалуйста, помните:

Object.assign(blob,{
  // jartto: 这里一定要处理一下
  preview: URL.createObjectURL(blob),
  name: `图片示例:${index}.png`
});

10. Резюме

Чувствуете ли вы легкое головокружение, когда изображение перемещается? Поверьте, если вы внимательно прочитаете статью, то ваша обработка графических данных в дальнейшем будет проходить гораздо более плавно.

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

Итак, усердно учитесь, позвольте себе вырасти в высокое дерево, полное жизненной силы, и затенять небо.

11. Справочные ресурсы

Blob
MDN FileReader
бинарное изображение
Convert Image to Data URI
Отображение изображения HTML base64 img