Определение размера изображения JPEG (JFIF)

Это функция ECMAScript 6, называемая литералами шаблонов строк.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals

Литералы шаблонов могут использоваться многострочные линии и могут использовать «интерполяцию» для вставки содержимого переменных :

var a = 123, str = `---
   a is: ${a}
---`;
console.log(str);

Будет выводиться:

---
   a is: 123
---

Что более важно, они могут содержать не только имя переменной, но и любое выражение Javascript:

var a = 3, b = 3.1415;

console.log(`PI is nearly ${Math.max(a, b)}`);

Поддерживается с Firefox 34 и Chrome 41.

30
задан Andrew T. 11 March 2019 в 10:32
поделиться

4 ответа

Сжатые данные не будут включать байты SOI или EOI, поэтому вы в безопасности. Но комментарий, данные приложения или другие заголовки могут. К счастью, вы можете определить и пропустить эти разделы, если указана длина.

В спецификации JPEG указано, что вам нужно:
http://www.w3.org/Graphics/JPEG/itu-t81.pdf

См. Таблицу B.1 на стр. 32. Символы со знаком * не имеют поля длины после него (RST, SOI, EOI, TEM). Другие делают.

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

Как пройти:

  1. Начать чтение SOI ( FFD8 ). Это начало. Он должен быть первым в потоке.

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

    • Маркер SOI ( FFD8 ): поврежденное изображение. Вы уже должны были найти EOI!

    • TEM ( FF01 ): автономный маркер, продолжайте.

    • RST ( FFD0 - FFD7 ): автономный маркер, продолжайте. Вы можете проверить, что маркеры перезапуска отсчитываются от FFD0 до FFD7 и повторяются, но это не обязательно для измерения длины.

    • Маркер EOI ( FFD9 ]): Готово!

    • Любой маркер, не являющийся RST, SOI, EOI, TEM ( FF01 - FFFE , за вычетом исключений, указанных выше): После маркера, прочтите следующие 2 байта, это 16-битная прямая последовательность байтов этого заголовка кадра (не включая 2-байтовый маркер, но включая поле длины). Пропустите указанное количество (обычно длина минус 2, поскольку у вас уже есть эти байты).

    • Если вы получили конец файла до EOI, значит, у вас поврежденное изображение.

    • После того, как вы получили EOI, вы прошли через JPEG и должны иметь длину. Вы можете начать заново, прочитав другой SOI, если вы ожидаете, что в вашем потоке будет более одного JPEG.

38
ответ дан 28 November 2019 в 00:08
поделиться

В Python вы можете просто прочитать весь файл в строковом объекте и найти первое вхождение FF E0 и последнее вхождение FF D9. Предположительно, это начало и конец, которые вы ищете?

f = open("filename.jpg", "r")
s = f.read()
start = s.find("\xff\xe0")
end = s.rfind("\xff\xd9")
imagesize = end - start
0
ответ дан 28 November 2019 в 00:08
поделиться

Поскольку у вас нет опубликованных языков, я не уверен, что это сработает, но:

Можете ли вы Stream.Seek (0, StreamOffset.End); , а затем определить позицию потока?

Пожалуйста, уточните, какой фреймворк вы используете.

На самом деле дело в том, что , если в заголовке файла не указан ожидаемый размер, вы должны искать (или читать) до конца изображения.

EDIT

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

OGG должен хорошо подходить для этого.

JPEG на самом деле уже поддерживает потоковую передачу, но вы должны гарантировать, что каждый файл имеет допустимый терминатор, прежде чем отправлять его по потоку, иначе вы рискуете привести к сбою приложения из-за неожиданного ввода.

2
ответ дан 28 November 2019 в 00:08
поделиться

Может быть, что-то вроде этого

int GetJpgSize(unsigned char *pData, DWORD FileSizeLow, unsigned short *pWidth, unsigned short *pHeight)
{
  unsigned int i = 0;


  if ((pData[i] == 0xFF) && (pData[i + 1] == 0xD8) && (pData[i + 2] == 0xFF) && (pData[i + 3] == 0xE0)) {
    i += 4;

    // Check for valid JPEG header (null terminated JFIF)
    if ((pData[i + 2] == 'J') && (pData[i + 3] == 'F') && (pData[i + 4] == 'I') && (pData[i + 5] == 'F')
        && (pData[i + 6] == 0x00)) {

      //Retrieve the block length of the first block since the first block will not contain the size of file
      unsigned short block_length = pData[i] * 256 + pData[i + 1];

      while (i < FileSizeLow) {
        //Increase the file index to get to the next block
        i += block_length; 

        if (i >= FileSizeLow) {
          //Check to protect against segmentation faults
          return -1;
        }

        if (pData[i] != 0xFF) {
          return -2;
        } 

        if (pData[i + 1] == 0xC0) {
          //0xFFC0 is the "Start of frame" marker which contains the file size
          //The structure of the 0xFFC0 block is quite simple [0xFFC0][ushort length][uchar precision][ushort x][ushort y]
          *pHeight = pData[i + 5] * 256 + pData[i + 6];
          *pWidth = pData[i + 7] * 256 + pData[i + 8];

          return 0;
        }
        else {
          i += 2; //Skip the block marker

          //Go to the next block
          block_length = pData[i] * 256 + pData[i + 1];
        }
      }

      //If this point is reached then no size was found
      return -3;
    }
    else {
      return -4;
    } //Not a valid JFIF string
  }
  else {
    return -5;
  } //Not a valid SOI header

  return -6;
}  // GetJpgSize
3
ответ дан 28 November 2019 в 00:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: