Графический формат JPEG. Класс TJPEGImage

В 1988 году был принят первый международный стандарт сжатия неподвижных изображений. Он был назван по имени группы, которая над ним работала — JPEG (Joint Photographic Expert Group). Дело в том, что стандартные архиваторы (ZIP, ARJ) и традиционные алгоритмы сжатия в форматах GIF, TIFF и PCX не могут достаточно сильно сжать полутоновую или цветную картинку (типа фотографии) — максимум в 2—3 раза. Примененный в JPEG алгоритм позволяет достичь сжатия в десятки раз — правда, при этом изображение подвергается необратимому искажению, и из него пропадает часть деталей. Бессмысленно (и вредно!) подвергать хранению в формате JPEG чертежи, рисунки, а также любые изображения с малым числом градаций — он предназначен именно для изображений фотографического качества.

Поддержка формата JPEG реализована в Delphi посредством класса TJPEGImage, который является потомком класса TGraphic.

Примечание

Название TJPEGImage не совсем удачное. К Timage этот класс не имеет ни малейшего отношения. Скорее, это "двоюродный брат" класса TBitmap.

К такому объекту предъявляются двоякие требования. С одной стороны, он должен поддерживать сжатие данных для записи на диск. С другой — распакованные данные в формате DIB, чтобы по требованию системы отрисовать их. Поэтому объект класса TJPEGimage может хранить оба вида данных, а также производить их взаимные преобразования, т. е. сжатие и распаковку. Для этого в нем предусмотрены методы:

procedure Compress; 

procedure DIBNeeded;

procedure JPEGNeeded;

Рекомендуется вызывать метод DIBNeeded заранее, перед отрисовкой картинки — это ускорит процесс ее вывода на экран.

Кроме того, полезно использовать метод Assign, который позволяет поместить в класс TJPEGimage объект TBitmap и наоборот:

MyJPEGImage.Assign(MyBitmap);

 MyBitmap.Assign(MyJPEGImage);

При этом происходит преобразование форматов.

Свойства TJPEGimage можно условно разделить на две группы: используемые при сжатии и при распаковке.

Важнейшим из свойств, нужных при сжатии, является compressionQuality:

type TJPEGQualityRange = 1..100;

property CompressionQuaiity: TJPEGQualityRange;

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

Примечание 

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

По умолчанию значение этого свойства равно 75, что обеспечивает разумный компромисс между размером и качеством.

Кроме CompressionQuality, на качество отображения может повлиять и свойство

type TJPEGPerformance = (jpBestQuality, jpBestSpeed); 

property Performance: TJPEGPerformance;

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

Как и у класса TBitmap, у TJPEGimage есть свойство

type TJPEGPixelFormat = (jf24Bit, jfSBit); 

property PixelFormat: TJPEGPixelForm;

Для рассматриваемого объекта возможных значений всего два— jf8bit и jf24bit. По умолчанию используется 24-битный формат. Если информация о цвете не нужна, то можно установить свойство Grayscale в значение True — в этом случае изображение будет записано (или распаковано) в полутоновом виде (256 оттенков серого).

Свойства ProgressiveEncoding и ProgressiveDisplay определяют способ показа изображения при распаковке. Первое из них отвечает за порядок записи в файл сжатых компонентов. Если ProgressiveEncoding установлено в значение True, начинает играть роль свойство ProgressiveDisplay. От его значения зависит, будет ли показываться изображение по мере распаковки (при значении True), либо будет сначала полностью распаковано, а потом показано (при значении False).

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

type TJPEGScale = (jsFullSize, jsHalf, jsQuarter, jsEighth);

 property Scale: TJPEGScale;

Искушенные в графике специалисты зададут вопрос: зачем оно? Ведь можно прочитать изображение, а затем уменьшить его масштаб стандартными способами? Представление информации в файлах JPEG таково, что можно достаточно просто извлечь изображение сразу в нужном масштабе. Таким образом достигается двойной выигрыш — на времени распаковки и на времени отображения.

Примечание 

Печать растровых изображений может вызвать проблемы при согласовании его размеров с размерами листа принтера и его разрешением. Большую часть из них можно снять, изучив пример, поставляемый с Delphi — jpegProj. Он находится не в папке \Demos, как обычно, а в папке Help\Examples\Jpeg.

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