Обзор архитектуры кодеков
В этом разделе
Определения:
- Декодер - объект, выполняющий декодирование изображений определенного формата.
- Энкодер - объект, выполняющий кодирование изображений определенного формата.
- Кодек - объект, управляющий энкодером и декодером для определенного формата изображений.
SDK содержит открытую архитектуру кодеков изображений, которая используется для получения информации, кодирования и декодирования изображений различных форматов (TIFF, PDF, BMP и т.д.).
Все классы, используемые для кодирования и декодирования изображений, расположены в пространстве имен Vintasoft.Imaging.Codecs.
На следующей диаграмме показаны логические связи между базовыми классами архитектуры кодеков:
Базовые классы, показанные на диаграмме выше, разделены на четыре уровня абстракции:
- Уровень "кодеки" состоит из AvailableCodecs, AvailableDecoders, AvailableEncoders,Codec и производных классов. Классы AvailableCodecs, AvailableDecoders и AvailableEncoders предоставляют информацию о доступных декодерах и энкодерах, а также предоставляют возможность добавлять и удалять кодеки. Codec и производные классы содержат методы, позволяющие создавать энкодер или декодер для определенных форматов изображений.
- Уровень "кодер/декодер" состоит из классов EncoderBase и DecoderBase и производных классов, которые обеспечивают единый доступ к функциям, предназначенным для получения информации и кодирования/декодирования изображений.
-
Уровень "файла изображения" состоит из
ImageFileBase<T>
а также производных классов и связанных классов. Классы, производные от классов
ImageFileBase<T>
и ImagePage, обеспечивают полный доступ ко всем функциям декодирования/кодирования изображений и к метаданным определенного формата.
ImageFileSource используется классами
ImageFileBase<T>
иерархии для чтения/записи двоичных данных из экземпляра объекта System.IO.Stream.
- Уровень "закодированные данные" представляет класс System.IO.Stream, который содержит данные изображения, закодированные в определенном формате (TIFF, PDF, BMP и т. д.).
1. Классы "Codec" и "AvailableCodecs"
Статический класс
AvailableCodecs содержит информацию о доступных кодеках, а также предоставляет возможность удалять и добавлять новые кодеки:
Класс
Codec является базовым классом для всех кодеков. Класс
Codec определяет, как создать декодер и энкодер для изображений определенного формата.
Класс
Codec включает следующие информативные свойства:
Новый кодек, производный от класса
Codec, всегда должен реализовывать как минимум следующие методы:
- Codec.CreateDecoder - создает экземпляр класса, производного от класса DecoderBase с использованием конструктора без параметров или с использованием конструктора, который получает поток, содержащий закодированные данные изображения.
- Codec.CreateEncoder - создает экземпляр класса, производного от класса EncoderBase, с использованием конструктора без параметров.
Важно:
Статический метод
Codec.CreateStandardCodec позволяет создать по имени "стандартный" кодек для следующих форматов файлов изображений: Bmp, Docx, Emf, Gif, Icon, Jbig2, Jpeg, Jpeg2000, Pbm, Pdf, Png, Raw, Tga, Tiff, Webp, Wmf, Xlsx.
Вот C#/VB.NET код, который демонстрирует, как получить информацию о доступных кодеках и их характеристиках:
/// <summary>
/// Shows detailed information about available codecs.
/// </summary>
public static void ShowAvailableCodecsInfo()
{
foreach (Vintasoft.Imaging.Codecs.Codec codec in Vintasoft.Imaging.Codecs.AvailableCodecs.Codecs)
{
string codecInfo = "";
if (codec.CanCreateDecoder && codec.CanCreateEncoder)
codecInfo = "decoder, encoder";
else if (codec.CanCreateDecoder)
codecInfo = "decoder";
else if (codec.CanCreateEncoder)
codecInfo = "encoder";
System.Console.WriteLine(string.Format("{0} codec ({1}):", codec.Name, codecInfo));
System.Console.Write(" File extensions:");
for (int i = 0; i < codec.FileExtensions.Length; i++)
{
System.Console.Write(string.Format(" *{0}", codec.FileExtensions[i].ToLowerInvariant()));
}
System.Console.WriteLine();
}
}
/* This code example produces the following output:
Raw codec (decoder):
File extensions: *.nef *.nrw *.cr2 *.crw *.dng
Tiff codec (decoder, encoder):
File extensions: *.tif *.tiff
Gif codec (decoder, encoder):
File extensions: *.gif
Png codec (decoder, encoder):
File extensions: *.png
Jpeg codec (decoder, encoder):
File extensions: *.jpg *.jpeg
Bmp codec (decoder, encoder):
File extensions: *.bmp
Pdf codec (decoder, encoder):
File extensions: *.pdf
Jbig2 codec (decoder, encoder):
File extensions: *.jb2 *.jbig2
Jpeg2000 codec (decoder, encoder):
File extensions: *.jp2 *.jpc *.j2k *.j2c
Dicom codec (decoder):
File extensions: *.dcm *.dic *.acr
Docx codec (decoder):
File extensions: *.docx
Wmf codec (decoder):
File extensions: *.wmf
Emf codec (decoder):
File extensions: *.emf
Icon codec (decoder):
File extensions: *.ico *.cur
Jpeg-LS codec (decoder):
File extensions: *.jls
Pcx codec (decoder, encoder):
File extensions: *.pcx
*/
''' <summary>
''' Shows detailed information about available codecs.
''' </summary>
Public Shared Sub ShowAvailableCodecsInfo()
For Each codec As Vintasoft.Imaging.Codecs.Codec In Vintasoft.Imaging.Codecs.AvailableCodecs.Codecs
Dim codecInfo As String = ""
If codec.CanCreateDecoder AndAlso codec.CanCreateEncoder Then
codecInfo = "decoder, encoder"
ElseIf codec.CanCreateDecoder Then
codecInfo = "decoder"
ElseIf codec.CanCreateEncoder Then
codecInfo = "encoder"
End If
System.Console.WriteLine(String.Format("{0} codec ({1}):", codec.Name, codecInfo))
System.Console.Write(" File extensions:")
For i As Integer = 0 To codec.FileExtensions.Length - 1
System.Console.Write(String.Format(" *{0}", codec.FileExtensions(i).ToLowerInvariant()))
Next
System.Console.WriteLine()
Next
End Sub
' This code example produces the following output:
'
' Raw codec (decoder):
' File extensions: *.nef *.nrw *.cr2 *.crw *.dng
' Tiff codec (decoder, encoder):
' File extensions: *.tif *.tiff
' Gif codec (decoder, encoder):
' File extensions: *.gif
' Png codec (decoder, encoder):
' File extensions: *.png
' Jpeg codec (decoder, encoder):
' File extensions: *.jpg *.jpeg
' Bmp codec (decoder, encoder):
' File extensions: *.bmp
' Pdf codec (decoder, encoder):
' File extensions: *.pdf
' Jbig2 codec (decoder, encoder):
' File extensions: *.jb2 *.jbig2
' Jpeg2000 codec (decoder, encoder):
' File extensions: *.jp2 *.jpc *.j2k *.j2c
' Dicom codec (decoder):
' File extensions: *.dcm *.dic *.acr
' Docx codec (decoder):
' File extensions: *.docx
' Wmf codec (decoder):
' File extensions: *.wmf
' Emf codec (decoder):
' File extensions: *.emf
' Icon codec (decoder):
' File extensions: *.ico *.cur
' Jpeg-LS codec (decoder):
' File extensions: *.jls
' Pcx codec (decoder, encoder):
' File extensions: *.pcx
'
'
2. Классы "DecoderBase" и "AvailableDecoders"
Статический класс
AvailableDecoders содержит информацию о доступных декодерах и позволяет:
Объект
VintasoftImage использует метод
AvailableDecoders.CreateDecoder для выбора декодера, который позволяет декодировать данные изображения из потока или файла, содержащего данные изображения.
Класс
DecoderBase является базовым классом для всех декодеров. Класс
DecoderBase определяет единый набор методов, предназначенных для получения метаданных и декодирования изображений:
Вот C#/VB.NET код, который демонстрирует, как получить декодер для указанного потока и получить информацию обо всех изображениях, закодированных в этом потоке:
/// <summary>
/// Shows detailed information about pages of image stored in specified stream.
/// </summary>
public static void ShowInformationAboutPages(System.IO.Stream stream)
{
Vintasoft.Imaging.Codecs.Decoders.DecoderBase decoder;
try
{
// create appropriate decoder
decoder = Vintasoft.Imaging.Codecs.Decoders.AvailableDecoders.CreateDecoder(stream);
}
catch (Vintasoft.Imaging.Codecs.Decoders.DecoderException ex)
{
System.Console.WriteLine(ex.Message);
return;
}
if (decoder == null)
{
System.Console.WriteLine("Appropriate decoder was not found.");
return;
}
// get the number of pages
System.Console.WriteLine(string.Format("Stream contains {0} page(s).", decoder.PageCount));
for (int i = 0; i < decoder.PageCount; i++)
{
// get the information about the page
Vintasoft.Imaging.Codecs.Decoders.ImageInfo pageImageInfo = decoder.GetImageInfo(i);
System.Console.WriteLine();
// get general image parameters
System.Console.WriteLine(string.Format("Page {0}:", i + 1));
System.Console.WriteLine(string.Format(" Image dimensions: {0}x{1} pixels", pageImageInfo.Width, pageImageInfo.Height));
System.Console.WriteLine(string.Format(" Image resolution: {0}x{1} dpi",
System.Math.Round(pageImageInfo.Resolution.Horizontal), System.Math.Round(pageImageInfo.Resolution.Vertical)));
System.Console.WriteLine(string.Format(" Image bit depth: {0}", pageImageInfo.BitsPerPixel));
System.Console.WriteLine(string.Format(" Image pixel format: {0}", pageImageInfo.PixelFormat));
// get information about palette
int paletteColorCount = pageImageInfo.Palette.ColorCount;
if (paletteColorCount > 0)
System.Console.WriteLine(string.Format(" Image has a palette with {0} colors", paletteColorCount));
else
System.Console.WriteLine(string.Format(" Image has no palette"));
System.Console.WriteLine();
}
}
''' <summary>
''' Shows detailed information about pages of image stored in specified stream.
''' </summary>
Public Shared Sub ShowInformationAboutPages(stream As System.IO.Stream)
Dim decoder As Vintasoft.Imaging.Codecs.Decoders.DecoderBase
Try
' create appropriate decoder
decoder = Vintasoft.Imaging.Codecs.Decoders.AvailableDecoders.CreateDecoder(stream)
Catch ex As Vintasoft.Imaging.Codecs.Decoders.DecoderException
System.Console.WriteLine(ex.Message)
Return
End Try
If decoder Is Nothing Then
System.Console.WriteLine("Appropriate decoder was not found.")
Return
End If
' get the number of pages
System.Console.WriteLine(String.Format("Stream contains {0} page(s).", decoder.PageCount))
For i As Integer = 0 To decoder.PageCount - 1
' get the information about the page
Dim pageImageInfo As Vintasoft.Imaging.Codecs.Decoders.ImageInfo = decoder.GetImageInfo(i)
System.Console.WriteLine()
' get general image parameters
System.Console.WriteLine(String.Format("Page {0}:", i + 1))
System.Console.WriteLine(String.Format(" Image dimensions: {0}x{1} pixels", pageImageInfo.Width, pageImageInfo.Height))
System.Console.WriteLine(String.Format(" Image resolution: {0}x{1} dpi", System.Math.Round(pageImageInfo.Resolution.Horizontal), System.Math.Round(pageImageInfo.Resolution.Vertical)))
System.Console.WriteLine(String.Format(" Image bit depth: {0}", pageImageInfo.BitsPerPixel))
System.Console.WriteLine(String.Format(" Image pixel format: {0}", pageImageInfo.PixelFormat))
' get information about palette
Dim paletteColorCount As Integer = pageImageInfo.Palette.ColorCount
If paletteColorCount > 0 Then
System.Console.WriteLine(String.Format(" Image has a palette with {0} colors", paletteColorCount))
Else
System.Console.WriteLine(String.Format(" Image has no palette"))
End If
System.Console.WriteLine()
Next
End Sub
3. Классы "EncoderBase", "MultipageEncoderBase" и "AvailableEncoders"
Статический класс
AvailableEncoders содержит информацию о доступных энкодерах и позволяет:
Объекты
VintasoftImage и
ImageCollection используют метод
AvailableEncoders.CreateEncoder для выбора энкодера по имени кодируемого файла.
Класс
EncoderBase является базовым классом для всех энкодеров. Класс
EncoderBase определяет единый набор методов, предназначенных для кодирования изображений в формат одностраничных изображений (PNG, BMP, JPEG, JPEG2000):
Класс
MultipageEncoderBase является производным от
EncoderBase и определяет унифицированный набор методов, предназначенных для кодирования коллекции изображений в формат многостраничных изображений (TIFF, PDF, GIF, JBIG2):
Вот C#/VB.NET код, который демонстрирует, как выбрать энкодирер для определенного файла и выполнить сохранение коллекции изображений в файл:
/// <summary>
/// Gets an encoder by the filename extension,
/// changes settings of the encoder and
/// saves an image collection to a file using encoder.
/// </summary>
public static void ChangeEncoderSettingsAndSave(Vintasoft.Imaging.ImageCollection images, string filename)
{
// get an encoder by the filename extension
Vintasoft.Imaging.Codecs.Encoders.EncoderBase encoder =
Vintasoft.Imaging.Codecs.Encoders.AvailableEncoders.CreateEncoder(filename);
// if encoder was not found
if (encoder == null)
{
throw new System.Exception("Encoder is not found for specified file extension.");
}
// if encoder is TIFF
if (encoder is Vintasoft.Imaging.Codecs.Encoders.TiffEncoder)
{
// specify that encoded image must be divided into tiles with size 512x512
(encoder as Vintasoft.Imaging.Codecs.Encoders.TiffEncoder).Settings.UseTiles = true;
(encoder as Vintasoft.Imaging.Codecs.Encoders.TiffEncoder).Settings.TileSize = new System.Drawing.Size(512, 512);
}
// create file
using (System.IO.Stream stream = new System.IO.FileStream(filename,
System.IO.FileMode.Create, System.IO.FileAccess.ReadWrite))
{
// if encoder is multipage
if (encoder is Vintasoft.Imaging.Codecs.Encoders.MultipageEncoderBase)
{
// save all images
(encoder as Vintasoft.Imaging.Codecs.Encoders.MultipageEncoderBase).SaveImages(images, stream);
}
else
{
// check if there is exactly 1 image
if (images.Count != 1)
throw new System.Exception("Single-page encoder cannot be used for saving multiple images.");
encoder.SaveImage(images[0], stream);
}
}
}
''' <summary>
''' Gets an encoder by the filename extension,
''' changes settings of the encoder and
''' saves an image collection to a file using encoder.
''' </summary>
Public Shared Sub ChangeEncoderSettingsAndSave(images As Vintasoft.Imaging.ImageCollection, filename As String)
' get an encoder by the filename extension
Dim encoder As Vintasoft.Imaging.Codecs.Encoders.EncoderBase = Vintasoft.Imaging.Codecs.Encoders.AvailableEncoders.CreateEncoder(filename)
' if encoder was not found
If encoder Is Nothing Then
Throw New System.Exception("Encoder is not found for specified file extension.")
End If
' if encoder is TIFF
If TypeOf encoder Is Vintasoft.Imaging.Codecs.Encoders.TiffEncoder Then
' specify that encoded image must be divided into tiles with size 512x512
TryCast(encoder, Vintasoft.Imaging.Codecs.Encoders.TiffEncoder).Settings.UseTiles = True
TryCast(encoder, Vintasoft.Imaging.Codecs.Encoders.TiffEncoder).Settings.TileSize = New System.Drawing.Size(512, 512)
End If
' create file
Using stream As System.IO.Stream = New System.IO.FileStream(filename, System.IO.FileMode.Create, System.IO.FileAccess.ReadWrite)
' if encoder is multipage
If TypeOf encoder Is Vintasoft.Imaging.Codecs.Encoders.MultipageEncoderBase Then
' save all images
TryCast(encoder, Vintasoft.Imaging.Codecs.Encoders.MultipageEncoderBase).SaveImages(images, stream)
Else
' check if there is exactly 1 image
If images.Count <> 1 Then
Throw New System.Exception("Single-page encoder cannot be used for saving multiple images.")
End If
encoder.SaveImage(images(0), stream)
End If
End Using
End Sub
4. Иерархия файлов изображений
Иерархия ImageFile предоставляет набор классов для анализа, декодирования и кодирования файлов изображений.
Следующая диаграмма иллюстрирует логические связи между базовыми классами архитектуры ImageFile:
4.1. Файл изображения
ImageFileBase<T>
класс является базовым классом для:
-
абстрактного
SinglePageImageFile<T>
класса, который используется для создания одностраничных файлов изображений (BmpFile, PngFile, JpegFile, Jpeg2000File, RawImageFile)
-
абстрактного
ImageFile<TPage, TPageCollection>
класса, который используется для создания многостраничных файлов изображений (TiffFile, GifFile, Jbig2File, IconFile)
Классы, производные от
ImageFileBase<T>
, предоставляют доступ к набору страниц файла (или странице в случае одностраничного формата) и общей информации о файле. Они также реализуют функции парсинга, сохранения изменений, сохранения в новый источник и упаковки файла.
4.2. Страница изображения
Абстрактный класс
ImagePage определяет методы, которые позволяют получать информацию о закодированном изображении (высота, ширина, палитра, разрешение и т.д.) и кодировать изображение.
Классы
TiffPage,
PngPage,
BmpPage,
DibPage,
GifPage,
IconPage,
JpegPage,
Jpeg2000Page,
Jbig2Page,
RawImagePageBase, которые являются производными от класса
ImagePage, также предоставляют дополнительную информацию об изображении: цветовое пространство, сжатие, миниатюру и другие подробности, специфичные для формата.
4.3. Блок файла изображения
Каждый файл изображения состоит из блоков файла. Абстрактный класс
ImageFileBlock описывает блок данных в файле.
Все блоки файла имеют следующие общие атрибуты:
- длина блока
- смещение блока в файле
- источник
Блок может быть виртуальным (
ImageFileBlock.IsVirtual, т.е. созданным в памяти без ссылки на реальный источник (
ImageFileSource). Виртуальные блоки появляются при создании нового файла или добавлении новых блоков в существующий файл. Блоки становятся реальными после сохранения файла в источник.
Переопределенный абстрактный метод
ImageFileBlock.Parse позволяет реализовать алгоритм парсинга для конкретного блока. Переопределенный абстрактный метод
ImageFileBlock.Write позволяет реализовать запись закодированных данных в источник.
4.4. Источник файла изображения
Класс
ImageFileSource позволяет читать/записывать данные из/в источник. Класс реализует широкий набор функций чтения/записи данных для разных форматов данных: Int16, Uint16, Int32, UInt32, Int64, UInt64, Char, Bool, Single, Double, Byte, Byte[]. Класс
ImageFileSource реализует операции чтения/записи в формате с прямым порядком байтов. Класс
BigEndianImageSource реализует операции чтения/записи в формате с обратным порядком байтов.