Получение разрешения JPEG без декодирования изображения
Я пытаюсь получить разрешение изображения JPEG без декодирования файла. Я получил несколько образцов из Интернета, но ни один не работает должным образом. Кажется, это так, потому что многие файлы JPEG не являются стандартными, хотя любое графическое приложение (Irfan, PSP, Firefox и т. Д.) Может открыть их.
Заголовок JPEG должен был быть:
typedef struct _JFIFHeader
{
BYTE SOI[2]; /* 00h Start of Image Marker */
BYTE APP0[2]; /* 02h Application Use Marker */
BYTE Length[2]; /* 04h Length of APP0 Field */
BYTE Identifier[5]; /* 06h "JFIF" (zero terminated) Id String */
BYTE Version[2]; /* 07h JFIF Format Revision */
BYTE Units; /* 09h Units used for Resolution */
BYTE Xdensity[2]; /* 0Ah Horizontal Resolution */
BYTE Ydensity[2]; /* 0Ch Vertical Resolution */
BYTE XThumbnail; /* 0Eh Horizontal Pixel Count */
BYTE YThumbnail; /* 0Fh Vertical Pixel Count */
} JFIFHEAD;
Однако, когда я посмотрел один из этих нестандартных файлов, поля Xdensity и Ydensity были неправильными. Но опять же, все графические приложения могут читать этот нестандартный файл.
Кто-нибудь знает кусок кода Delphi, который может читать все файлы JPEG?
Delphi 7, Win 7 32 бит
4 ответа
Вот код, который может помочь вам получить нужные данные:
function GetJpegSize(jpeg: TMemoryStream; out width, height, BitDepth: integer): boolean;
var n: integer;
b: byte;
w: Word;
begin
result := false;
n := jpeg.Size-8;
jpeg.Position := 0;
if n<=0 then
exit;
jpeg.Read(w,2);
if w<>$D8FF then
exit; // invalid format
jpeg.Read(b,1);
while (jpeg.Position<n) and (b=$FF) do begin
jpeg.Read(b,1);
case b of
$C0..$C3: begin
jpeg.Seek(3,soFromCurrent);
jpeg.Read(w,2);
height := swap(w);
jpeg.Read(w,2);
width := swap(w);
jpeg.Read(b,1);
BitDepth := b*8;
Result := true; // JPEG format OK
exit;
end;
$FF:
jpeg.Read(b,1);
$D0..$D9, $01: begin
jpeg.Seek(1,soFromCurrent);
jpeg.Read(b,1);
end;
else begin
jpeg.Read(w,2);
jpeg.Seek(swap(w)-2, soFromCurrent);
jpeg.Read(b,1);
end;
end;
end;
end;
Я не знаю обо всех файлах JPEG, но вам нужно будет обработать два распространенных формата файлов для JPEG. Поскольку JPEG - это метод сжатия, а не формат файла, мир в целом разработал несколько способов хранения данных изображения JPEG в файлах. Скорее всего, вы столкнетесь с JFIF и EXIF. Приведенный выше код охватывает JFIF, но не обрабатывает EXIF. Эти два в значительной степени несовместимы, но оба являются JPEG, поэтому вам нужно будет обнаружить и обработать, если вы используете информацию заголовка, поскольку они откладываются.
Для разрешения, в качестве примера. Поле EXIF - это x-Resolution и y-Resolution против подхода плотности X/Y.
Я мог бы:
Чтение некоторых двух форматов (JFIF и EXIF). Я считаю, что Википедия - отличное место для начала по этой ссылке (для некоторых прошлых проектов, которые я делал), но, скорее всего, у SO тоже есть отличная информация по этой теме.
JFIF: http://en.wikipedia.org/wiki/JPEG_File_Interchange_Format
Напишите код для определения формата, используя начальные заголовки
Обрабатывать каждый формат независимо
Оберните все это так, чтобы вы могли просто добавить к нему JPEG и получить плотность. Это также даст вам отличное место, чтобы бросить другой вспомогательный код для работы с "забавным" миром обработки JPEG.
Элементы Units, Xdensity и Ydensity заголовка файла JPEG задают единицы измерения, используемые для описания физической плотности точек при печати файла.
- Если Units - 1, Xdensity и Ydensity - это точки на дюйм.
- Если Units - 2, Xdensity и Ydensity - это точки на см.
Дело в том, что разрешение точек (масштабированное разрешение печати), хранящееся в файле изображения, просто не имеет значения на экране. Таким образом, программы Windows всегда будут показывать вам 96 логических точек на дюйм на экране для любого файла. Обратите внимание, что некоторые приложения предпочитают использовать 72 логических ppi для отображения изображений на экране, например приложения Adobe.
Графические приложения, такие как ACDSee, Adobe Photoshop, CorelDRAW, просто игнорируют элементы Units, Xdensity и Ydensity при отображении файлов JPG на экране, но графические приложения учитывают значение этих элементов при печати файлов JPG, если они существуют. В случае, если файл JPG не имеет элементов Units, Xdensity и Ydensity, графические приложения используют свои пользовательские значения по умолчанию (обычно 150 dpi) для печати файла JPG.
Итак, на вопрос о коде Delphi, который может читать все файлы заголовков JPEG, ответ прост - просто прочитайте информацию заголовка файла JPG; в случае, если дополнительные элементы не существуют в файле, просто проигнорируйте дополнительные элементы или сообщите конечным пользователям, что они в данный момент не указаны в файле.
Дальнейшее чтение путаницы в DPI и PPI
Ссылки на спецификацию формата файла JPEG
Существует пакет TP/TPW/Delphi (1-4, но, вероятно, он будет работать до версий Unicode без больших модов), pasjp(e)g, который может читать большинство старых типов JPG (но не, например, JPEG2000)
FPC также включает этот пакет.
Оригинальный сайт от J. Nommsi исчез, но пакет все еще доступен, например, от