Графический формат 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.