Определение ширины и высоты файла JPEG
В «Эгее» есть какой-то плавающий баг, из-за которого иногда не заливаются файлы JPEG. Илья, автор «Эгеи», пытался с ним разобраться, но до конца понять проблему не смог.
Пока рабочая теория такая, что функция ПХП getimagesize (она возвращает тип изображения и его высоту с шириной) иногда выдаёт неправильные значения.
Опровергнуть или подтвердить эту теорию не так-то и просто — баг проявляется очень редко, но можно попытаться считывать размеры каким-то другим способом и посмотреть исчезнет проблема или нет.
Вот Илья и попросил написать меня такой код на чистом ПХП. Надеюсь это позволит продвинуться в изучении проблемы — код вошёл в одиннадцатую версию «Эгеи».
Выложу его у себя тоже, чтобы не потерялся, ну и может кому-то ещё пригодится:
function readJPEGWxH(string $filename): array
{
$file = new SplFileObject($filename);
if (!$file->flock(LOCK_SH)) {
throw new RuntimeException('Cannot lock the file');
}
if ($file->fread(2) !== "\xFF\xD8") {
throw new RuntimeException('Unknown format');
}
for (;;) {
$decoded = @unpack('H4segment/nlen', $file->fread(4));
if ($decoded === false) {
throw new RuntimeException('Unknown format');
}
['segment' => $segment, 'len' => $len] = $decoded;
// SOFn (Start Of Frame)?
if (preg_match('/^ffc[0-3]/', $segment)) {
$segdata = @unpack('Cbits/nheight/nwidth', $file->fread(5));
if ($segdata === false) {
throw new RuntimeException('Unknown format');
}
return [$segdata['width'], $segdata['height']];
}
// len = full lenght of segment except segment magic code
if ($file->fseek($len - 2, SEEK_CUR) !== 0) {
throw new RuntimeException('Cannot find start of frame');
}
}
}